summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2025-03-26 15:11:19 +0000
committerVaxry <vaxry@vaxry.net>2025-03-26 17:22:21 +0000
commit0cd04bd666665bfdeafc0f55a93e532cd8978827 (patch)
treeb5bd31ee41aff585ab45506278d4d17fee09d3a1 /src
parent1c2b9a9ce3a58c76632834774a4716af1de45fe6 (diff)
surfacestate: track and apply updated state
fixes #9729
Diffstat (limited to 'src')
-rw-r--r--src/protocols/DRMSyncobj.cpp11
-rw-r--r--src/protocols/core/Compositor.cpp42
-rw-r--r--src/protocols/types/SurfaceState.cpp34
-rw-r--r--src/protocols/types/SurfaceState.hpp18
4 files changed, 85 insertions, 20 deletions
diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp
index 5238d1fb..0a4ca439 100644
--- a/src/protocols/DRMSyncobj.cpp
+++ b/src/protocols/DRMSyncobj.cpp
@@ -75,20 +75,22 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(UP<CWpLinuxDrmSyncobjSurf
});
listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) {
- if (!surface->pending.buffer && surface->pending.newBuffer && !surface->pending.texture) {
+ const bool PENDING_HAS_NEW_BUFFER = surface->pending.updated & SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_BUFFER;
+
+ if (!surface->pending.buffer && PENDING_HAS_NEW_BUFFER && !surface->pending.texture) {
removeAllWaiters();
surface->commitPendingState(surface->pending);
return; // null buffer attached.
}
- if (!surface->pending.buffer && !surface->pending.newBuffer && surface->current.buffer) {
+ if (!surface->pending.buffer && !PENDING_HAS_NEW_BUFFER && surface->current.buffer) {
surface->current.bufferDamage.clear();
surface->current.damage.clear();
surface->commitPendingState(surface->current);
return; // no new buffer, but we still have current around and a commit happend, commit current again.
}
- if (!surface->pending.buffer && !surface->pending.newBuffer && !surface->current.buffer) {
+ if (!surface->pending.buffer && !PENDING_HAS_NEW_BUFFER && !surface->current.buffer) {
surface->commitPendingState(surface->pending); // no pending buffer, no current buffer. probably first commit
return;
}
@@ -109,7 +111,8 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(UP<CWpLinuxDrmSyncobjSurf
const auto& state = pendingStates.emplace_back(makeShared<SSurfaceState>(surface->pending));
surface->pending.damage.clear();
surface->pending.bufferDamage.clear();
- surface->pending.newBuffer = false;
+ surface->pending.updated &= ~SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_BUFFER;
+ surface->pending.updated &= ~SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
surface->pending.buffer.reset();
state->buffer->buffer->syncReleaser = state->buffer->release->createSyncRelease();
diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp
index 2dd374a8..974207a4 100644
--- a/src/protocols/core/Compositor.cpp
+++ b/src/protocols/core/Compositor.cpp
@@ -71,8 +71,8 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
resource->setOnDestroy([this](CWlSurface* r) { destroy(); });
resource->setAttach([this](CWlSurface* r, wl_resource* buffer, int32_t x, int32_t y) {
- pending.offset = {x, y};
- pending.newBuffer = true;
+ pending.offset = {x, y};
+ pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_BUFFER | SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_OFFSET;
if (!buffer) {
pending.buffer.reset();
@@ -119,11 +119,23 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
commitPendingState(pending);
});
- resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.damage.add(CBox{x, y, w, h}); });
- resource->setDamageBuffer([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.bufferDamage.add(CBox{x, y, w, h}); });
+ resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) {
+ pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
+ pending.damage.add(CBox{x, y, w, h});
+ });
+ resource->setDamageBuffer([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) {
+ pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
+ pending.bufferDamage.add(CBox{x, y, w, h});
+ });
- resource->setSetBufferScale([this](CWlSurface* r, int32_t scale) { pending.scale = scale; });
- resource->setSetBufferTransform([this](CWlSurface* r, uint32_t tr) { pending.transform = (wl_output_transform)tr; });
+ resource->setSetBufferScale([this](CWlSurface* r, int32_t scale) {
+ pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_SCALE;
+ pending.scale = scale;
+ });
+ resource->setSetBufferTransform([this](CWlSurface* r, uint32_t tr) {
+ pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_TRANSFORM;
+ pending.transform = (wl_output_transform)tr;
+ });
resource->setSetInputRegion([this](CWlSurface* r, wl_resource* region) {
if (!region) {
@@ -131,6 +143,8 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
return;
}
+ pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_INPUT;
+
auto RG = CWLRegionResource::fromResource(region);
pending.input = RG->region;
});
@@ -141,13 +155,18 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
return;
}
+ pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_OPAQUE;
+
auto RG = CWLRegionResource::fromResource(region);
pending.opaque = RG->region;
});
resource->setFrame([this](CWlSurface* r, uint32_t id) { callbacks.emplace_back(makeShared<CWLCallbackResource>(makeShared<CWlCallback>(pClient, 1, id))); });
- resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) { pending.offset = {x, y}; });
+ resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) {
+ pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_OFFSET;
+ pending.offset = {x, y};
+ });
}
CWLSurfaceResource::~CWLSurfaceResource() {
@@ -403,13 +422,8 @@ CBox CWLSurfaceResource::extends() {
void CWLSurfaceResource::commitPendingState(SSurfaceState& state) {
auto lastTexture = current.texture;
- if (state.newBuffer) {
- state.newBuffer = false;
- current = state;
- state.damage.clear();
- state.bufferDamage.clear();
- state.buffer.reset();
- }
+ current.updateFrom(state);
+ state.updated = 0;
if (current.buffer) {
if (current.buffer->buffer->isSynchronous())
diff --git a/src/protocols/types/SurfaceState.cpp b/src/protocols/types/SurfaceState.cpp
index 6f9636ff..bb58b9ae 100644
--- a/src/protocols/types/SurfaceState.cpp
+++ b/src/protocols/types/SurfaceState.cpp
@@ -56,3 +56,37 @@ void SSurfaceState::reset() {
offset = {};
size = {};
}
+
+void SSurfaceState::updateFrom(SSurfaceState& ref) {
+ updated = ref.updated;
+
+ if (ref.updated & SURFACE_UPDATED_BUFFER) {
+ *this = ref;
+ ref.damage.clear();
+ ref.bufferDamage.clear();
+ ref.buffer.reset();
+ } else {
+ if (ref.updated & SURFACE_UPDATED_DAMAGE) {
+ damage = ref.damage;
+ bufferDamage = ref.bufferDamage;
+ }
+
+ if (ref.updated & SURFACE_UPDATED_INPUT)
+ input = ref.input;
+
+ if (ref.updated & SURFACE_UPDATED_OPAQUE)
+ opaque = ref.opaque;
+
+ if (ref.updated & SURFACE_UPDATED_OFFSET)
+ offset = ref.offset;
+
+ if (ref.updated & SURFACE_UPDATED_SCALE)
+ scale = ref.scale;
+
+ if (ref.updated & SURFACE_UPDATED_VIEWPORT)
+ viewport = ref.viewport;
+
+ if (ref.updated & SURFACE_UPDATED_TRANSFORM)
+ transform = ref.transform;
+ }
+}
diff --git a/src/protocols/types/SurfaceState.hpp b/src/protocols/types/SurfaceState.hpp
index b5093759..4c995bb0 100644
--- a/src/protocols/types/SurfaceState.hpp
+++ b/src/protocols/types/SurfaceState.hpp
@@ -7,6 +7,17 @@ class CHLBufferReference;
class CTexture;
struct SSurfaceState {
+ enum eUpdatedProperties : uint8_t {
+ SURFACE_UPDATED_OPAQUE = 1 << 0,
+ SURFACE_UPDATED_INPUT = 1 << 1,
+ SURFACE_UPDATED_DAMAGE = 1 << 2,
+ SURFACE_UPDATED_SCALE = 1 << 3,
+ SURFACE_UPDATED_BUFFER = 1 << 4,
+ SURFACE_UPDATED_OFFSET = 1 << 5,
+ SURFACE_UPDATED_VIEWPORT = 1 << 6,
+ SURFACE_UPDATED_TRANSFORM = 1 << 7,
+ };
+
CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
int scale = 1;
@@ -20,12 +31,15 @@ struct SSurfaceState {
Vector2D destination;
CBox source;
} viewport;
- bool rejected = false;
- bool newBuffer = false;
+ bool rejected = false;
+ uint8_t updated = 0; // eUpdatedProperties. Stores what the last update changed
Vector2D sourceSize();
// Translates damage into bufferDamage, clearing damage and returning the updated bufferDamage
CRegion accumulateBufferDamage();
void updateSynchronousTexture(SP<CTexture> lastTexture);
void reset();
+ // updates this state from a reference state. Mutates the reference state. If a new buffer is committed,
+ // reference state gets its damage and buffer cleared.
+ void updateFrom(SSurfaceState& ref);
};