screencopy: use buffer format for glReadPixels

fixes #4029
This commit is contained in:
Vaxry 2023-12-04 03:52:54 +00:00
parent 5d100bdcbb
commit 68783d904d
4 changed files with 76 additions and 71 deletions

View file

@ -457,12 +457,12 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb);
GLint glf, glt; const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format);
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); if (!PFORMAT) {
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); g_pHyprRenderer->endRender();
if (glf == 0 || glt == 0) { wlr_texture_destroy(sourceTex);
glf = drmFormatToGL(frame->pMonitor->drmFormat); wlr_buffer_end_data_ptr_access(frame->buffer);
glt = glFormatToType(glf); return false;
} }
g_pHyprRenderer->endRender(); g_pHyprRenderer->endRender();
@ -473,16 +473,15 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
const auto FMT = g_pHyprOpenGL->getPreferredReadFormat(frame->pMonitor); const wlr_pixel_format_info* drmFmtWlr = drm_get_pixel_format_info(format);
const wlr_pixel_format_info* drmFmtWlr = drm_get_pixel_format_info(FMT);
uint32_t packStride = pixel_format_info_min_stride(drmFmtWlr, frame->box.w); uint32_t packStride = pixel_format_info_min_stride(drmFmtWlr, frame->box.w);
if (packStride == stride) { 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 { } else {
for (size_t i = 0; i < frame->box.h; ++i) { for (size_t i = 0; i < frame->box.h; ++i) {
uint32_t y = frame->box.x + 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);
} }
} }

View file

@ -387,19 +387,18 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
if (frame->overlayCursor) if (frame->overlayCursor)
g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec());
GLint glf, glt; const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format);
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); if (!PFORMAT) {
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); g_pHyprRenderer->endRender();
if (glf == 0 || glt == 0) { wlr_buffer_end_data_ptr_access(frame->buffer);
glf = drmFormatToGL(frame->pMonitor->drmFormat); return false;
glt = glFormatToType(glf);
} }
g_pHyprOpenGL->m_RenderData.mainFB->bind(); g_pHyprOpenGL->m_RenderData.mainFB->bind();
glPixelStorei(GL_PACK_ALIGNMENT, 1); 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(); g_pHyprRenderer->endRender();

View file

@ -2067,14 +2067,6 @@ void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) {
m_bEndFrame = !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[] = { inline const SGLPixelFormat GLES2_FORMATS[] = {
{ {
.drmFormat = DRM_FORMAT_ARGB8888, .drmFormat = DRM_FORMAT_ARGB8888,
@ -2179,9 +2171,6 @@ inline const SGLPixelFormat GLES2_FORMATS[] = {
}; };
uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) {
if (g_pHyprRenderer->isNvidia())
return DRM_FORMAT_XBGR8888;
GLint glf = -1, glt = -1, as = -1; GLint glf = -1, glt = -1, as = -1;
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf);
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt);
@ -2202,3 +2191,12 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) {
return DRM_FORMAT_XBGR8888; return DRM_FORMAT_XBGR8888;
} }
const SGLPixelFormat* CHyprOpenGLImpl::getPixelFormatFromDRM(uint32_t drmFormat) {
for (auto& fmt : GLES2_FORMATS) {
if (fmt.drmFormat == drmFormat)
return &fmt;
}
return nullptr;
}

View file

@ -41,6 +41,14 @@ struct SRenderModifData {
float scale = 1.f; 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 { struct SMonitorRenderData {
CFramebuffer offloadFB; CFramebuffer offloadFB;
CFramebuffer mirrorFB; // these are used for some effects, CFramebuffer mirrorFB; // these are used for some effects,
@ -108,66 +116,67 @@ class CHyprOpenGLImpl {
public: public:
CHyprOpenGLImpl(); CHyprOpenGLImpl();
void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */); void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */);
void end(); void end();
void renderRect(CBox*, const CColor&, int round = 0); void renderRect(CBox*, const CColor&, int round = 0);
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f); void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f);
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); 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(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 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 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 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 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 renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte);
void setMonitorTransformEnabled(bool enabled); void setMonitorTransformEnabled(bool enabled);
void saveMatrix(); void saveMatrix();
void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); void setMatrixScaleTranslate(const Vector2D& translate, const float& scale);
void restoreMatrix(); void restoreMatrix();
void blend(bool enabled); void blend(bool enabled);
void makeWindowSnapshot(CWindow*); void makeWindowSnapshot(CWindow*);
void makeRawWindowSnapshot(CWindow*, CFramebuffer*); void makeRawWindowSnapshot(CWindow*, CFramebuffer*);
void makeLayerSnapshot(SLayerSurface*); void makeLayerSnapshot(SLayerSurface*);
void renderSnapshot(CWindow**); void renderSnapshot(CWindow**);
void renderSnapshot(SLayerSurface**); void renderSnapshot(SLayerSurface**);
void clear(const CColor&); void clear(const CColor&);
void clearWithTex(); void clearWithTex();
void scissor(const CBox*, bool transform = true); void scissor(const CBox*, bool transform = true);
void scissor(const pixman_box32*, 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 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(); void preWindowPass();
bool preBlurQueued(); bool preBlurQueued();
void preRender(CMonitor*); void preRender(CMonitor*);
void saveBufferForMirror(); void saveBufferForMirror();
void renderMirrored(); void renderMirrored();
void applyScreenShader(const std::string& path); void applyScreenShader(const std::string& path);
void bindOffMain(); void bindOffMain();
void renderOffToMain(CFramebuffer* off); void renderOffToMain(CFramebuffer* off);
void bindBackOnMain(); 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 CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window
SLayerSurface* m_pCurrentLayer = nullptr; // hack to get the current rendered layer SLayerSurface* m_pCurrentLayer = nullptr; // hack to get the current rendered layer
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers; std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
std::unordered_map<SLayerSurface*, CFramebuffer> m_mLayerFramebuffers; std::unordered_map<SLayerSurface*, CFramebuffer> m_mLayerFramebuffers;