summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
authorIkalco <73481042+ikalco@users.noreply.github.com>2026-02-22 06:30:11 -0600
committerGitHub <noreply@github.com>2026-02-22 12:30:11 +0000
commitb4ee4674f9a74e3d602c7fb17bc09f79d221583c (patch)
tree294bbb207c44e778dd78afda65cbd79181f04124 /src/render
parent93dbf884261efcb387e920b1cd0e4ed5b288bc3a (diff)
protocols: implement image-capture-source-v1 and image-copy-capture-v1 (#11709)
Implements the new screencopy protocols
Diffstat (limited to 'src/render')
-rw-r--r--src/render/OpenGL.cpp50
-rw-r--r--src/render/OpenGL.hpp5
-rw-r--r--src/render/Renderer.hpp11
-rw-r--r--src/render/pass/Pass.cpp2
-rw-r--r--src/render/pass/SurfacePassElement.cpp2
5 files changed, 45 insertions, 25 deletions
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index 3e0c4f26..351df0c3 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -685,6 +685,7 @@ void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP
if (!m_shadersInitialized)
initShaders();
+ m_renderData.transformDamage = true;
m_renderData.damage.set(damage);
m_renderData.finalDamage.set(damage);
@@ -752,6 +753,7 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
if (m_renderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_renderData.pMonitor->m_mirrors.empty())
m_renderData.pCurrentMonData->monitorMirrorFB.release();
+ m_renderData.transformDamage = true;
m_renderData.damage.set(damage_);
m_renderData.finalDamage.set(finalDamage.value_or(damage_));
@@ -1059,7 +1061,7 @@ void CHyprOpenGLImpl::clear(const CHyprColor& color) {
if (!m_renderData.damage.empty()) {
m_renderData.damage.forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glClear(GL_COLOR_BUFFER_BIT);
});
}
@@ -1194,13 +1196,13 @@ void CHyprOpenGLImpl::renderRectWithDamageInternal(const CBox& box, const CHyprC
if (!damageClip.empty()) {
damageClip.forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
}
} else {
data.damage->forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
}
@@ -1588,13 +1590,13 @@ void CHyprOpenGLImpl::renderTextureInternal(SP<CTexture> tex, const CBox& box, c
if (!damageClip.empty()) {
damageClip.forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
}
} else {
data.damage->forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
}
@@ -1640,7 +1642,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP<CTexture> tex, const CBox& box)
glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO));
m_renderData.damage.forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
@@ -1681,7 +1683,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFra
glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO));
m_renderData.damage.forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
@@ -2275,7 +2277,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
if (!borderRegion.empty()) {
borderRegion.forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
}
@@ -2364,7 +2366,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
if (!borderRegion.empty()) {
borderRegion.forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
}
@@ -2427,13 +2429,13 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun
if (!damageClip.empty()) {
damageClip.forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
}
} else {
m_renderData.damage.forEachRect([this](const auto& RECT) {
- scissor(&RECT);
+ scissor(&RECT, m_renderData.transformDamage);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
});
}
@@ -3063,18 +3065,30 @@ void CHyprOpenGLImpl::setCapStatus(int cap, bool status) {
}
}
-uint32_t CHyprOpenGLImpl::getPreferredReadFormat(PHLMONITOR pMonitor) {
+DRMFormat CHyprOpenGLImpl::getPreferredReadFormat(PHLMONITOR pMonitor) {
static const auto PFORCE8BIT = CConfigValue<Hyprlang::INT>("misc:screencopy_force_8b");
- if (!*PFORCE8BIT)
- return pMonitor->m_output->state->state().drmFormat;
+ auto monFmt = pMonitor->m_output->state->state().drmFormat;
- auto fmt = pMonitor->m_output->state->state().drmFormat;
+ if (*PFORCE8BIT)
+ if (monFmt == DRM_FORMAT_BGRA1010102 || monFmt == DRM_FORMAT_ARGB2101010 || monFmt == DRM_FORMAT_XRGB2101010 || monFmt == DRM_FORMAT_BGRX1010102 ||
+ monFmt == DRM_FORMAT_XBGR2101010)
+ monFmt = DRM_FORMAT_XRGB8888;
- if (fmt == DRM_FORMAT_BGRA1010102 || fmt == DRM_FORMAT_ARGB2101010 || fmt == DRM_FORMAT_XRGB2101010 || fmt == DRM_FORMAT_BGRX1010102 || fmt == DRM_FORMAT_XBGR2101010)
- return DRM_FORMAT_XRGB8888;
+ return monFmt;
+}
+
+std::vector<uint64_t> CHyprOpenGLImpl::getDRMFormatModifiers(DRMFormat drmFormat) {
+ SDRMFormat format;
+
+ for (const auto& fmt : m_drmFormats) {
+ if (fmt.drmFormat == drmFormat) {
+ format = fmt;
+ break;
+ }
+ }
- return fmt;
+ return format.modifiers;
}
bool CHyprOpenGLImpl::explicitSyncSupported() {
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index 3df8322b..bc1f5f4d 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -172,6 +172,8 @@ struct SCurrentRenderData {
bool useNearestNeighbor = false;
bool blockScreenShader = false;
bool simplePass = false;
+ bool transformDamage = true;
+ bool noSimplify = false;
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
@@ -305,8 +307,9 @@ class CHyprOpenGLImpl {
void setDamage(const CRegion& damage, std::optional<CRegion> finalDamage = {});
- uint32_t getPreferredReadFormat(PHLMONITOR pMonitor);
+ DRMFormat getPreferredReadFormat(PHLMONITOR pMonitor);
std::vector<SDRMFormat> getDRMFormats();
+ std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format);
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
bool initShaders();
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index f2377b3b..24e0fb66 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -16,6 +16,12 @@ class CWorkspace;
class CInputPopup;
class IHLBuffer;
class CEventLoopTimer;
+class CToplevelExportProtocolManager;
+class CInputManager;
+struct SSessionLockSurface;
+namespace Screenshare {
+ class CScreenshareFrame;
+};
enum eDamageTrackingModes : int8_t {
DAMAGE_TRACKING_INVALID = -1,
@@ -37,10 +43,6 @@ enum eRenderMode : uint8_t {
RENDER_MODE_TO_BUFFER_READ_ONLY = 3,
};
-class CToplevelExportProtocolManager;
-class CInputManager;
-struct SSessionLockSurface;
-
struct SRenderWorkspaceUntilData {
PHLLS ls;
PHLWINDOW w;
@@ -166,6 +168,7 @@ class CHyprRenderer {
friend class CHyprOpenGLImpl;
friend class CToplevelExportFrame;
+ friend class Screenshare::CScreenshareFrame;
friend class CInputManager;
friend class CPointerManager;
friend class CMonitor;
diff --git a/src/render/pass/Pass.cpp b/src/render/pass/Pass.cpp
index b62a4734..3c82c84c 100644
--- a/src/render/pass/Pass.cpp
+++ b/src/render/pass/Pass.cpp
@@ -171,7 +171,7 @@ CRegion CRenderPass::render(const CRegion& damage_) {
} else
g_pHyprOpenGL->m_renderData.finalDamage = m_damage;
- if (std::ranges::any_of(m_passElements, [](const auto& el) { return el->element->disableSimplification(); })) {
+ if (g_pHyprOpenGL->m_renderData.noSimplify || std::ranges::any_of(m_passElements, [](const auto& el) { return el->element->disableSimplification(); })) {
for (auto& el : m_passElements) {
el->elementDamage = m_damage;
}
diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp
index df410014..c5feb8f7 100644
--- a/src/render/pass/SurfacePassElement.cpp
+++ b/src/render/pass/SurfacePassElement.cpp
@@ -104,7 +104,7 @@ void CSurfacePassElement::draw(const CRegion& damage) {
}
const bool WINDOWOPAQUE = m_data.pWindow && m_data.pWindow->wlSurface()->resource() == m_data.surface ? m_data.pWindow->opaque() : false;
- const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE;
+ const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding <= 0 && WINDOWOPAQUE;
if (CANDISABLEBLEND)
g_pHyprOpenGL->blend(false);