diff options
Diffstat (limited to 'src/protocols/core/Compositor.cpp')
| -rw-r--r-- | src/protocols/core/Compositor.cpp | 80 |
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()); |
