diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 65f50893..e5aaab62 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -457,12 +457,12 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); - GLint glf, glt; - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); - if (glf == 0 || glt == 0) { - glf = drmFormatToGL(frame->pMonitor->drmFormat); - glt = glFormatToType(glf); + const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format); + if (!PFORMAT) { + g_pHyprRenderer->endRender(); + wlr_texture_destroy(sourceTex); + wlr_buffer_end_data_ptr_access(frame->buffer); + return false; } g_pHyprRenderer->endRender(); @@ -473,16 +473,15 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* glPixelStorei(GL_PACK_ALIGNMENT, 1); - const auto FMT = g_pHyprOpenGL->getPreferredReadFormat(frame->pMonitor); - const wlr_pixel_format_info* drmFmtWlr = drm_get_pixel_format_info(FMT); + const wlr_pixel_format_info* drmFmtWlr = drm_get_pixel_format_info(format); uint32_t packStride = pixel_format_info_min_stride(drmFmtWlr, frame->box.w); if (packStride == stride) { - glReadPixels(frame->box.x, frame->box.y, frame->box.w, frame->box.h, glf, glt, data); + glReadPixels(frame->box.x, frame->box.y, frame->box.w, frame->box.h, PFORMAT->glFormat, PFORMAT->glType, data); } else { for (size_t i = 0; i < frame->box.h; ++i) { uint32_t y = frame->box.x + i; - glReadPixels(frame->box.x, y, frame->box.w, 1, glf, glt, ((unsigned char*)data) + i * stride); + glReadPixels(frame->box.x, y, frame->box.w, 1, PFORMAT->glFormat, PFORMAT->glType, ((unsigned char*)data) + i * stride); } } diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 6a001c02..dabad2ab 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -387,19 +387,18 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times if (frame->overlayCursor) g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); - GLint glf, glt; - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); - if (glf == 0 || glt == 0) { - glf = drmFormatToGL(frame->pMonitor->drmFormat); - glt = glFormatToType(glf); + const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format); + if (!PFORMAT) { + g_pHyprRenderer->endRender(); + wlr_buffer_end_data_ptr_access(frame->buffer); + return false; } g_pHyprOpenGL->m_RenderData.mainFB->bind(); glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(0, 0, frame->box.width, frame->box.height, glf, glt, data); + glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->glFormat, PFORMAT->glType, data); g_pHyprRenderer->endRender(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 061cc2b5..2c9151e5 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2067,14 +2067,6 @@ void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) { m_bEndFrame = !enabled; } -struct SGLPixelFormat { - uint32_t drmFormat = DRM_FORMAT_INVALID; - GLint glInternalFormat = 0; - GLint glFormat = 0; - GLint glType = 0; - bool withAlpha = false; -}; - inline const SGLPixelFormat GLES2_FORMATS[] = { { .drmFormat = DRM_FORMAT_ARGB8888, @@ -2179,9 +2171,6 @@ inline const SGLPixelFormat GLES2_FORMATS[] = { }; uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { - if (g_pHyprRenderer->isNvidia()) - return DRM_FORMAT_XBGR8888; - GLint glf = -1, glt = -1, as = -1; glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); @@ -2202,3 +2191,12 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { return DRM_FORMAT_XBGR8888; } + +const SGLPixelFormat* CHyprOpenGLImpl::getPixelFormatFromDRM(uint32_t drmFormat) { + for (auto& fmt : GLES2_FORMATS) { + if (fmt.drmFormat == drmFormat) + return &fmt; + } + + return nullptr; +} \ No newline at end of file diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index c3726575..efccaad4 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -41,6 +41,14 @@ struct SRenderModifData { float scale = 1.f; }; +struct SGLPixelFormat { + uint32_t drmFormat = DRM_FORMAT_INVALID; + GLint glInternalFormat = 0; + GLint glFormat = 0; + GLint glType = 0; + bool withAlpha = false; +}; + struct SMonitorRenderData { CFramebuffer offloadFB; CFramebuffer mirrorFB; // these are used for some effects, @@ -108,66 +116,67 @@ class CHyprOpenGLImpl { public: CHyprOpenGLImpl(); - void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */); - void end(); + void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */); + void end(); - void renderRect(CBox*, const CColor&, int round = 0); - void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f); - void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); - void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); - void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); - void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); - void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); - void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); + void renderRect(CBox*, const CColor&, int round = 0); + void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f); + void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); + void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); + void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); + void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); + void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); + void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); + void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); - void setMonitorTransformEnabled(bool enabled); + void setMonitorTransformEnabled(bool enabled); - void saveMatrix(); - void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); - void restoreMatrix(); + void saveMatrix(); + void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); + void restoreMatrix(); - void blend(bool enabled); + void blend(bool enabled); - void makeWindowSnapshot(CWindow*); - void makeRawWindowSnapshot(CWindow*, CFramebuffer*); - void makeLayerSnapshot(SLayerSurface*); - void renderSnapshot(CWindow**); - void renderSnapshot(SLayerSurface**); + void makeWindowSnapshot(CWindow*); + void makeRawWindowSnapshot(CWindow*, CFramebuffer*); + void makeLayerSnapshot(SLayerSurface*); + void renderSnapshot(CWindow**); + void renderSnapshot(SLayerSurface**); - void clear(const CColor&); - void clearWithTex(); - void scissor(const CBox*, bool transform = true); - void scissor(const pixman_box32*, bool transform = true); - void scissor(const int x, const int y, const int w, const int h, bool transform = true); + void clear(const CColor&); + void clearWithTex(); + void scissor(const CBox*, bool transform = true); + void scissor(const pixman_box32*, bool transform = true); + void scissor(const int x, const int y, const int w, const int h, bool transform = true); - void destroyMonitorResources(CMonitor*); + void destroyMonitorResources(CMonitor*); - void markBlurDirtyForMonitor(CMonitor*); + void markBlurDirtyForMonitor(CMonitor*); - void preWindowPass(); - bool preBlurQueued(); - void preRender(CMonitor*); + void preWindowPass(); + bool preBlurQueued(); + void preRender(CMonitor*); - void saveBufferForMirror(); - void renderMirrored(); + void saveBufferForMirror(); + void renderMirrored(); - void applyScreenShader(const std::string& path); + void applyScreenShader(const std::string& path); - void bindOffMain(); - void renderOffToMain(CFramebuffer* off); - void bindBackOnMain(); + void bindOffMain(); + void renderOffToMain(CFramebuffer* off); + void bindBackOnMain(); - uint32_t getPreferredReadFormat(CMonitor* pMonitor); + uint32_t getPreferredReadFormat(CMonitor* pMonitor); + const SGLPixelFormat* getPixelFormatFromDRM(uint32_t drmFormat); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window - SLayerSurface* m_pCurrentLayer = nullptr; // hack to get the current rendered layer + CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window + SLayerSurface* m_pCurrentLayer = nullptr; // hack to get the current rendered layer std::unordered_map m_mWindowFramebuffers; std::unordered_map m_mLayerFramebuffers;