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.cpp80
1 files changed, 40 insertions, 40 deletions
diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp
index 8ad2a373..06a4587f 100644
--- a/src/protocols/core/Compositor.cpp
+++ b/src/protocols/core/Compositor.cpp
@@ -91,10 +91,12 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
if (buf && buf->m_buffer) {
m_pending.buffer = CHLBufferReference(buf->m_buffer.lock());
+ m_pending.texture = buf->m_buffer->m_texture;
m_pending.size = buf->m_buffer->size;
m_pending.bufferSize = buf->m_buffer->size;
} else {
- m_pending.buffer = {};
+ m_pending.buffer = {};
+ m_pending.texture.reset();
m_pending.size = Vector2D{};
m_pending.bufferSize = Vector2D{};
}
@@ -134,23 +136,33 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
commitState(m_pending);
// remove any pending states.
- while (!m_pendingStates.empty()) {
- m_pendingStates.pop();
- }
-
- m_pendingWaiting = false;
+ m_stateQueue.clear();
m_pending.reset();
return;
}
- // save state while we wait for buffer to become ready to read
- const auto& state = m_pendingStates.emplace(makeUnique<SSurfaceState>(m_pending));
+ // save state while we wait for buffer to become ready
+ auto state = m_stateQueue.enqueue(makeUnique<SSurfaceState>(m_pending));
m_pending.reset();
- if (!m_pendingWaiting) {
- m_pendingWaiting = true;
- scheduleState(state);
+ // fifo and fences first
+ m_events.stateCommit.emit(state);
+
+ if (state->buffer && state->buffer->type() == Aquamarine::BUFFER_TYPE_DMABUF && state->buffer->dmabuf().success && !state->updated.bits.acquire) {
+ state->buffer->m_syncFd = dc<CDMABuffer*>(state->buffer.m_buffer.get())->exportSyncFile();
+ if (state->buffer->m_syncFd.isValid())
+ m_stateQueue.lock(state, LOCK_REASON_FENCE);
}
+
+ // now for timer.
+ m_events.stateCommit2.emit(state);
+
+ if (state->rejected) {
+ m_stateQueue.dropState(state);
+ return;
+ }
+
+ scheduleState(state);
});
m_resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) {
@@ -479,43 +491,25 @@ CBox CWLSurfaceResource::extends() {
}
void CWLSurfaceResource::scheduleState(WP<SSurfaceState> state) {
- auto whenReadable = [this, surf = m_self, state] {
- if (!surf || state.expired() || m_pendingStates.empty())
+ auto whenReadable = [this, surf = m_self](auto state, auto reason) {
+ if (!surf || !state)
return;
- while (!m_pendingStates.empty() && m_pendingStates.front() != state) {
- commitState(*m_pendingStates.front());
- m_pendingStates.pop();
- }
-
- commitState(*m_pendingStates.front());
- m_pendingStates.pop();
-
- // If more states are queued, schedule next state
- if (!m_pendingStates.empty()) {
- scheduleState(m_pendingStates.front());
- } else {
- m_pendingWaiting = false;
- }
+ m_stateQueue.unlock(state, reason);
};
if (state->updated.bits.acquire) {
// wait on acquire point for this surface, from explicit sync protocol
- state->acquire.addWaiter(std::move(whenReadable));
+ state->acquire.addWaiter([state, whenReadable]() { whenReadable(state, LOCK_REASON_FENCE); });
} else if (state->buffer && state->buffer->isSynchronous()) {
// synchronous (shm) buffers can be read immediately
- whenReadable();
- } else if (state->buffer && state->buffer->type() == Aquamarine::BUFFER_TYPE_DMABUF && state->buffer->dmabuf().success) {
+ m_stateQueue.unlock(state);
+ } else if (state->buffer && state->buffer->m_syncFd.isValid()) {
// async buffer and is dmabuf, then we can wait on implicit fences
- auto syncFd = dc<CDMABuffer*>(state->buffer.m_buffer.get())->exportSyncFile();
-
- if (syncFd.isValid())
- g_pEventLoopManager->doOnReadable(std::move(syncFd), std::move(whenReadable));
- else
- whenReadable();
+ g_pEventLoopManager->doOnReadable(std::move(state->buffer->m_syncFd), [state, whenReadable]() { whenReadable(state, LOCK_REASON_FENCE); });
} else {
// state commit without a buffer.
- whenReadable();
+ m_stateQueue.unlock(state);
}
}
@@ -526,8 +520,6 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) {
if (m_current.buffer) {
if (m_current.buffer->isSynchronous())
m_current.updateSynchronousTexture(lastTexture);
- else if (!m_current.buffer->isSynchronous() && state.updated.bits.buffer) // only get a new texture when a new buffer arrived
- m_current.texture = m_current.buffer->createTexture();
// if the surface is a cursor, update the shm buffer
// TODO: don't update the entire texture
@@ -558,6 +550,13 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) {
nullptr);
}
+ if (m_current.updated.bits.damage) {
+ // damage is always relative to the current commit
+ m_current.updated.bits.damage = false;
+ m_current.damage.clear();
+ m_current.bufferDamage.clear();
+ }
+
// release the buffer if it's synchronous (SHM) as updateSynchronousTexture() has copied the buffer data to a GPU tex
// if it doesn't have a role, we can't release it yet, in case it gets turned into a cursor.
if (m_current.buffer && m_current.buffer->isSynchronous() && m_role->role() != SURFACE_ROLE_UNASSIGNED)
@@ -667,7 +666,8 @@ CWLCompositorResource::CWLCompositorResource(SP<CWlCompositor> resource_) : m_re
return;
}
- RESOURCE->m_self = RESOURCE;
+ RESOURCE->m_self = RESOURCE;
+ RESOURCE->m_stateQueue = CSurfaceStateQueue(RESOURCE);
LOGM(LOG, "New wl_surface with id {} at {:x}", id, (uintptr_t)RESOURCE.get());