Skip to content

Commit

Permalink
protocols: add hyprland_surface_v1.set_visible_region implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
outfoxxed committed Jan 19, 2025
1 parent 4da9b7c commit 37c8796
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 8 deletions.
3 changes: 2 additions & 1 deletion src/desktop/WLSurface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ class CWLSurface {
float m_fAlphaModifier = 1.F;

// used by the hyprland-surface protocol
float m_fOverallOpacity = 1.F;
float m_fOverallOpacity = 1.F;
CRegion m_visibleRegion;

struct {
CSignal destroy;
Expand Down
2 changes: 1 addition & 1 deletion src/managers/ProtocolManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ CProtocolManager::CProtocolManager() {
PROTO::singlePixel = std::make_unique<CSinglePixelProtocol>(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel");
PROTO::securityContext = std::make_unique<CSecurityContextProtocol>(&wp_security_context_manager_v1_interface, 1, "SecurityContext");
PROTO::ctm = std::make_unique<CHyprlandCTMControlProtocol>(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl");
PROTO::hyprlandSurface = std::make_unique<CHyprlandSurfaceProtocol>(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface");
PROTO::hyprlandSurface = std::make_unique<CHyprlandSurfaceProtocol>(&hyprland_surface_manager_v1_interface, 2, "HyprlandSurface");

if (*PENABLEXXCM) {
PROTO::colorManagement = std::make_unique<CColorManagementProtocol>(&xx_color_manager_v4_interface, 1, "ColorManagement");
Expand Down
23 changes: 22 additions & 1 deletion src/protocols/HyprlandSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "../render/Renderer.hpp"
#include "core/Compositor.hpp"
#include "hyprland-surface-v1.hpp"
#include <hyprutils/math/Region.hpp>
#include <wayland-server.h>

CHyprlandSurface::CHyprlandSurface(SP<CHyprlandSurfaceV1> resource, SP<CWLSurfaceResource> surface) : m_pSurface(surface) {
setResource(std::move(resource));
Expand Down Expand Up @@ -36,11 +38,25 @@ void CHyprlandSurface::setResource(SP<CHyprlandSurfaceV1> resource) {
m_fOpacity = fOpacity;
});

m_pResource->setSetVisibleRegion([this](CHyprlandSurfaceV1* resource, wl_resource* region) {
if (!region) {
if (!this->m_visibleRegion.empty())
m_bVisibleRegionChanged = true;

this->m_visibleRegion.clear();
return;
}

m_bVisibleRegionChanged = true;
this->m_visibleRegion = CWLRegionResource::fromResource(region)->region;
});

listeners.surfaceCommitted = m_pSurface->events.commit.registerListener([this](std::any data) {
auto surface = CWLSurface::fromResource(m_pSurface.lock());

if (surface && surface->m_fOverallOpacity != m_fOpacity) {
if (surface && (surface->m_fOverallOpacity != m_fOpacity || m_bVisibleRegionChanged)) {
surface->m_fOverallOpacity = m_fOpacity;
surface->m_visibleRegion = m_visibleRegion;
auto box = surface->getSurfaceBoxGlobal();

if (box.has_value())
Expand All @@ -61,6 +77,11 @@ void CHyprlandSurface::destroy() {
m_pResource.reset();
m_fOpacity = 1.F;

if (!this->m_visibleRegion.empty())
m_bVisibleRegionChanged = true;

m_visibleRegion.clear();

if (!m_pSurface)
PROTO::hyprlandSurface->destroySurface(this);
}
Expand Down
5 changes: 4 additions & 1 deletion src/protocols/HyprlandSurface.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <hyprutils/math/Region.hpp>
#include <memory>
#include <vector>
#include <unordered_map>
Expand All @@ -20,7 +21,9 @@ class CHyprlandSurface {
private:
SP<CHyprlandSurfaceV1> m_pResource;
WP<CWLSurfaceResource> m_pSurface;
float m_fOpacity = 1.0;
float m_fOpacity = 1.0;
bool m_bVisibleRegionChanged = false;
CRegion m_visibleRegion;

void destroy();

Expand Down
17 changes: 14 additions & 3 deletions src/render/OpenGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1556,9 +1556,15 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
glEnableVertexAttribArray(shader->posAttrib);
glEnableVertexAttribArray(shader->texAttrib);

if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
damageClip.intersect(damage);
if (!m_RenderData.clipBox.empty() || !m_RenderData.clipRegion.empty()) {
CRegion damageClip = m_RenderData.clipBox;

if (!m_RenderData.clipRegion.empty()) {
if (m_RenderData.clipBox.empty())
damageClip = m_RenderData.clipRegion;
else
damageClip.intersect(m_RenderData.clipRegion);
}

if (!damageClip.empty()) {
for (auto const& RECT : damageClip.getRects()) {
Expand Down Expand Up @@ -2079,6 +2085,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
CRegion texDamage{m_RenderData.damage};
texDamage.intersect(pBox->x, pBox->y, pBox->width, pBox->height);

// While renderTextureInternalWithDamage will clip the blur as well,
// clipping texDamage here allows blur generation to be optimized.
if (!m_RenderData.clipRegion.empty())
texDamage.intersect(m_RenderData.clipRegion);

if (texDamage.empty())
return;

Expand Down
1 change: 1 addition & 0 deletions src/render/OpenGL.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ struct SCurrentRenderData {
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);

CBox clipBox = {}; // scaled coordinates
CRegion clipRegion;

uint32_t discardMode = DISCARD_OPAQUE;
float discardOpacity = 0.f;
Expand Down
4 changes: 4 additions & 0 deletions src/render/pass/SurfacePassElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ void CSurfacePassElement::draw(const CRegion& damage) {
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
g_pHyprOpenGL->m_RenderData.clipBox = {};
g_pHyprOpenGL->m_RenderData.clipRegion = {};
g_pHyprOpenGL->m_RenderData.discardMode = 0;
g_pHyprOpenGL->m_RenderData.discardOpacity = 0;
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
Expand Down Expand Up @@ -75,6 +76,9 @@ void CSurfacePassElement::draw(const CRegion& damage) {
return;
}

if (PSURFACE)
g_pHyprOpenGL->m_RenderData.clipRegion = PSURFACE->m_visibleRegion.copy().translate(windowBox.pos());

const bool MISALIGNEDFSV1 = std::floor(data.pMonitor->scale) != data.pMonitor->scale /* Fractional */ && data.surface->current.scale == 1 /* fs protocol */ &&
windowBox.size() != data.surface->current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, data.surface->current.bufferSize.x, 3) &&
DELTALESSTHAN(windowBox.height, data.surface->current.bufferSize.y, 3) /* off by one-or-two */ &&
Expand Down
2 changes: 1 addition & 1 deletion subprojects/hyprland-protocols

0 comments on commit 37c8796

Please sign in to comment.