summaryrefslogtreecommitdiff
path: root/src/protocols/core/Compositor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/protocols/core/Compositor.cpp')
-rw-r--r--src/protocols/core/Compositor.cpp109
1 files changed, 80 insertions, 29 deletions
diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp
index cb1aa69a..57f0ff3f 100644
--- a/src/protocols/core/Compositor.cpp
+++ b/src/protocols/core/Compositor.cpp
@@ -71,23 +71,32 @@ 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.updated.buffer = true;
+ pending.updated.offset = true;
+
pending.offset = {x, y};
- pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_BUFFER | SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_OFFSET;
- if (!buffer) {
- pending.buffer.reset();
+ if (pending.buffer)
+ pending.buffer.drop();
+
+ auto buf = buffer ? CWLBufferResource::fromResource(buffer) : nullptr;
+
+ if (buf && buf->buffer) {
+ pending.buffer = CHLBufferReference(buf->buffer.lock());
+ pending.texture = buf->buffer->texture;
+ pending.size = buf->buffer->size;
+ pending.bufferSize = buf->buffer->size;
+ } else {
+ pending.buffer = {};
pending.texture.reset();
+ pending.size = Vector2D{};
pending.bufferSize = Vector2D{};
- } else {
- auto res = CWLBufferResource::fromResource(buffer);
- pending.buffer = res && res->buffer ? makeShared<CHLBufferReference>(res->buffer.lock(), self.lock()) : nullptr;
- pending.size = res && res->buffer ? res->buffer->size : Vector2D{};
- pending.texture = res && res->buffer ? res->buffer->texture : nullptr;
- pending.bufferSize = res && res->buffer ? res->buffer->size : Vector2D{};
}
- if (pending.bufferSize != current.bufferSize)
- pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
+ if (pending.bufferSize != current.bufferSize) {
+ pending.updated.damage = true;
+ pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
+ }
});
resource->setCommit([this](CWlSurface* r) {
@@ -109,34 +118,78 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
events.precommit.emit();
if (pending.rejected) {
+ pending.rejected = false;
dropPendingBuffer();
return;
}
- if (!syncobj)
- commitPendingState(pending);
+ if ((!pending.updated.buffer) || // no new buffer attached
+ (!pending.buffer && !pending.texture) || // null buffer attached
+ (!pending.updated.acquire && pending.buffer->isSynchronous()) // synchronous buffers (ex. shm) can be read immediately
+ ) {
+ commitState(pending);
+ pending.reset();
+ return;
+ }
+
+ // save state while we wait for buffer to become ready
+ const auto& state = pendingStates.emplace(makeUnique<SSurfaceState>(pending));
+ pending.reset();
+
+ auto whenReadable = [this, surf = self, state = WP<SSurfaceState>(pendingStates.back())] {
+ if (!surf || state.expired())
+ return;
+
+ while (!pendingStates.empty() && pendingStates.front() != state) {
+ commitState(*pendingStates.front());
+ pendingStates.pop();
+ }
+
+ commitState(*pendingStates.front());
+ pendingStates.pop();
+ };
+
+ if (state->updated.acquire) {
+ // wait on acquire point for this surface, from explicit sync protocol
+ state->acquire.addWaiter(whenReadable);
+ } else if (state->buffer->dmabuf().success) {
+ // https://www.kernel.org/doc/html/latest/driver-api/dma-buf.html#implicit-fence-poll-support
+ // TODO: wait for the dma-buf fd's to become readable
+ whenReadable();
+ } else {
+ // huh??? only buffers with acquire or dmabuf should get through here...
+ Debug::log(ERR, "BUG THIS: wl_surface.commit: non-acquire non-dmabuf buffers needs wait...");
+ whenReadable();
+ }
});
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.updated.damage = true;
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.updated.damage = true;
pending.bufferDamage.add(CBox{x, y, w, h});
});
resource->setSetBufferScale([this](CWlSurface* r, int32_t scale) {
if (scale == pending.scale)
return;
- pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_SCALE | SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
+
+ pending.updated.scale = true;
+ pending.updated.damage = true;
+
pending.scale = scale;
pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
});
+
resource->setSetBufferTransform([this](CWlSurface* r, uint32_t tr) {
if (tr == pending.transform)
return;
- pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_TRANSFORM | SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
+
+ pending.updated.transform = true;
+ pending.updated.damage = true;
+
pending.transform = (wl_output_transform)tr;
pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
});
@@ -147,7 +200,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
return;
}
- pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_INPUT;
+ pending.updated.input = true;
auto RG = CWLRegionResource::fromResource(region);
pending.input = RG->region;
@@ -159,7 +212,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
return;
}
- pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_OPAQUE;
+ pending.updated.opaque = true;
auto RG = CWLRegionResource::fromResource(region);
pending.opaque = RG->region;
@@ -168,8 +221,8 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
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.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_OFFSET;
- pending.offset = {x, y};
+ pending.updated.offset = true;
+ pending.offset = {x, y};
});
}
@@ -188,11 +241,11 @@ void CWLSurfaceResource::destroy() {
}
void CWLSurfaceResource::dropPendingBuffer() {
- pending.buffer.reset();
+ pending.buffer = {};
}
void CWLSurfaceResource::dropCurrentBuffer() {
- current.buffer.reset();
+ current.buffer = {};
}
SP<CWLSurfaceResource> CWLSurfaceResource::fromResource(wl_resource* res) {
@@ -279,7 +332,6 @@ void CWLSurfaceResource::resetRole() {
}
void CWLSurfaceResource::bfHelper(std::vector<SP<CWLSurfaceResource>> const& nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data) {
-
std::vector<SP<CWLSurfaceResource>> nodes2;
nodes2.reserve(nodes.size() * 2);
@@ -424,13 +476,12 @@ CBox CWLSurfaceResource::extends() {
return full.getExtents();
}
-void CWLSurfaceResource::commitPendingState(SSurfaceState& state) {
+void CWLSurfaceResource::commitState(SSurfaceState& state) {
auto lastTexture = current.texture;
current.updateFrom(state);
- state.updated = 0;
if (current.buffer) {
- if (current.buffer->buffer->isSynchronous())
+ if (current.buffer->isSynchronous())
current.updateSynchronousTexture(lastTexture);
// if the surface is a cursor, update the shm buffer
@@ -465,7 +516,7 @@ void CWLSurfaceResource::commitPendingState(SSurfaceState& state) {
// release the buffer if it's synchronous (SHM) as update() has done everything thats needed
// so we can let the app know we're done.
// if it doesn't have a role, we can't release it yet, in case it gets turned into a cursor.
- if (current.buffer && current.buffer->buffer && current.buffer->buffer->isSynchronous() && role->role() != SURFACE_ROLE_UNASSIGNED)
+ if (current.buffer && current.buffer->isSynchronous() && role->role() != SURFACE_ROLE_UNASSIGNED)
dropCurrentBuffer();
}
@@ -473,7 +524,7 @@ void CWLSurfaceResource::updateCursorShm(CRegion damage) {
if (damage.empty())
return;
- auto buf = current.buffer ? current.buffer->buffer : SP<IHLBuffer>{};
+ auto buf = current.buffer ? current.buffer : SP<IHLBuffer>{};
if UNLIKELY (!buf)
return;