Skip to content

Commit

Permalink
core/surface/buffer: Buffer lock/release fixes (#7110)
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski authored Jul 31, 2024
1 parent 5489682 commit 37e1411
Show file tree
Hide file tree
Showing 27 changed files with 304 additions and 129 deletions.
2 changes: 1 addition & 1 deletion src/desktop/LayerSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ void CLayerSurface::onCommit() {

if (!mapped) {
// we're re-mapping if this is the case
if (layerSurface->surface && !layerSurface->surface->current.buffer) {
if (layerSurface->surface && !layerSurface->surface->current.texture) {
fadingOut = false;
geometry = {};
g_pHyprRenderer->arrangeLayersForMonitor(monitorID);
Expand Down
23 changes: 11 additions & 12 deletions src/desktop/WLSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ bool CWLSurface::small() const {
if (!validMapped(m_pWindowOwner) || !exists())
return false;

if (!m_pResource->current.buffer)
if (!m_pResource->current.texture)
return false;

const auto O = m_pWindowOwner.lock();

return O->m_vReportedSize.x > m_pResource->current.buffer->size.x + 1 || O->m_vReportedSize.y > m_pResource->current.buffer->size.y + 1;
return O->m_vReportedSize.x > m_pResource->current.bufferSize.x + 1 || O->m_vReportedSize.y > m_pResource->current.bufferSize.y + 1;
}

Vector2D CWLSurface::correctSmallVec() const {
Expand All @@ -76,45 +76,44 @@ Vector2D CWLSurface::correctSmallVec() const {
}

Vector2D CWLSurface::correctSmallVecBuf() const {
if (!exists() || !small() || m_bFillIgnoreSmall || !m_pResource->current.buffer)
if (!exists() || !small() || m_bFillIgnoreSmall || !m_pResource->current.texture)
return {};

const auto SIZE = getViewporterCorrectedSize();
const auto BS = m_pResource->current.buffer->size;
const auto BS = m_pResource->current.bufferSize;

return Vector2D{(BS.x - SIZE.x) / 2, (BS.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY});
}

Vector2D CWLSurface::getViewporterCorrectedSize() const {
if (!exists() || !m_pResource->current.buffer)
if (!exists() || !m_pResource->current.texture)
return {};

return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.buffer->size;
return m_pResource->current.viewport.hasDestination ? m_pResource->current.viewport.destination : m_pResource->current.bufferSize;
}

CRegion CWLSurface::computeDamage() const {
if (!m_pResource->current.buffer)
if (!m_pResource->current.texture)
return {};

CRegion damage = m_pResource->accumulateCurrentBufferDamage();
damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.buffer->size.x, m_pResource->current.buffer->size.y);
damage.transform(wlTransformToHyprutils(m_pResource->current.transform), m_pResource->current.bufferSize.x, m_pResource->current.bufferSize.y);

const auto BUFSIZE = m_pResource->current.buffer->size;
const auto BUFSIZE = m_pResource->current.bufferSize;
const auto CORRECTVEC = correctSmallVecBuf();

if (m_pResource->current.viewport.hasSource)
damage.intersect(m_pResource->current.viewport.source);

const auto SCALEDSRCSIZE =
m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.size() * m_pResource->current.scale : m_pResource->current.buffer->size;
const auto SCALEDSRCSIZE = m_pResource->current.viewport.hasSource ? m_pResource->current.viewport.source.size() * m_pResource->current.scale : m_pResource->current.bufferSize;

damage.scale({BUFSIZE.x / SCALEDSRCSIZE.x, BUFSIZE.y / SCALEDSRCSIZE.y});
damage.translate(CORRECTVEC);

// go from buffer coords in the damage to hl logical

const auto BOX = getSurfaceBoxGlobal();
const Vector2D SCALE = BOX.has_value() ? BOX->size() / m_pResource->current.buffer->size :
const Vector2D SCALE = BOX.has_value() ? BOX->size() / m_pResource->current.bufferSize :
Vector2D{1.0 / m_pResource->current.scale, 1.0 / m_pResource->current.scale /* Wrong... but we can't really do better */};

damage.scale(SCALE);
Expand Down
10 changes: 5 additions & 5 deletions src/desktop/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1097,18 +1097,18 @@ bool CWindow::opaque() {
if (PWORKSPACE->m_fAlpha.value() != 1.f)
return false;

if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.buffer)
return m_pXWaylandSurface->surface->current.buffer->opaque;
if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.texture)
return m_pXWaylandSurface->surface->current.texture->m_bOpaque;

if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.buffer)
if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.texture)
return false;

// TODO: this is wrong
const auto EXTENTS = m_pXDGSurface->surface->current.opaque.getExtents();
if (EXTENTS.w >= m_pXDGSurface->surface->current.buffer->size.x && EXTENTS.h >= m_pXDGSurface->surface->current.buffer->size.y)
if (EXTENTS.w >= m_pXDGSurface->surface->current.bufferSize.x && EXTENTS.h >= m_pXDGSurface->surface->current.bufferSize.y)
return true;

return m_pWLSurface->resource()->current.buffer->opaque;
return m_pWLSurface->resource()->current.texture->m_bOpaque;
}

float CWindow::rounding() {
Expand Down
2 changes: 1 addition & 1 deletion src/events/Windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ void Events::listener_commitWindow(void* owner, void* data) {

// tearing: if solitary, redraw it. This still might be a single surface window
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.buffer) {
if (PMONITOR && PMONITOR->solitaryClient.lock() == PWINDOW && PWINDOW->canBeTorn() && PMONITOR->tearingState.canTear && PWINDOW->m_pWLSurface->resource()->current.texture) {
CRegion damageBox{PWINDOW->m_pWLSurface->resource()->accumulateCurrentBufferDamage()};

if (!damageBox.empty()) {
Expand Down
7 changes: 3 additions & 4 deletions src/helpers/Monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -801,17 +801,16 @@ bool CMonitor::attemptDirectScanout() {

const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE);

if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.buffer->size != vecPixelSize || PSURFACE->current.transform != transform)
if (!PSURFACE || !PSURFACE->current.buffer || PSURFACE->current.bufferSize != vecPixelSize || PSURFACE->current.transform != transform)
return false;

// we can't scanout shm buffers.
if (!PSURFACE->current.buffer->dmabuf().success)
if (!PSURFACE->current.buffer || !PSURFACE->current.texture || !PSURFACE->current.texture->m_pEglImage /* dmabuf */)
return false;

// FIXME: make sure the buffer actually follows the available scanout dmabuf formats
// and comes from the appropriate device. This may implode on multi-gpu!!

output->state->setBuffer(PSURFACE->current.buffer);
output->state->setBuffer(PSURFACE->current.buffer->buffer.lock());
output->state->setPresentationMode(tearingState.activelyTearing ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE :
Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC);

Expand Down
50 changes: 37 additions & 13 deletions src/managers/PointerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "../protocols/PointerGestures.hpp"
#include "../protocols/FractionalScale.hpp"
#include "../protocols/core/Compositor.hpp"
#include "../protocols/core/Seat.hpp"
#include "eventLoop/EventLoopManager.hpp"
#include "SeatManager.hpp"
#include <cstring>
Expand Down Expand Up @@ -156,15 +157,15 @@ void CPointerManager::setCursorSurface(SP<CWLSurface> surf, const Vector2D& hots
currentCursorImage.destroySurface = surf->events.destroy.registerListener([this](std::any data) { resetCursorImage(); });
currentCursorImage.commitSurface = surf->resource()->events.commit.registerListener([this](std::any data) {
damageIfSoftware();
currentCursorImage.size = currentCursorImage.surface->resource()->current.buffer ? currentCursorImage.surface->resource()->current.buffer->size : Vector2D{};
currentCursorImage.size = currentCursorImage.surface->resource()->current.texture ? currentCursorImage.surface->resource()->current.bufferSize : Vector2D{};
currentCursorImage.scale = currentCursorImage.surface ? currentCursorImage.surface->resource()->current.scale : 1.F;
recheckEnteredOutputs();
updateCursorBackend();
damageIfSoftware();
});

if (surf->resource()->current.buffer) {
currentCursorImage.size = surf->resource()->current.buffer->size;
if (surf->resource()->current.texture) {
currentCursorImage.size = surf->resource()->current.bufferSize;
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
surf->resource()->frame(&now);
Expand Down Expand Up @@ -430,16 +431,39 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
// clear buffer
memset(bufPtr, 0, std::get<2>(bufData));

auto texBuffer = currentCursorImage.pBuffer ? currentCursorImage.pBuffer : currentCursorImage.surface->resource()->current.buffer;
if (currentCursorImage.pBuffer) {
auto texAttrs = currentCursorImage.pBuffer->shm();

if (texBuffer) {
auto textAttrs = texBuffer->shm();
auto texData = texBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE);
auto texPtr = std::get<0>(texData);
Debug::log(TRACE, "cursor texture {}x{} {} {} {}", textAttrs.size.x, textAttrs.size.y, (void*)texPtr, textAttrs.format, textAttrs.stride);
if (!texAttrs.success) {
Debug::log(TRACE, "Cannot use dumb copy on dmabuf cursor buffers");
return nullptr;
}

auto texData = currentCursorImage.pBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE);
auto texPtr = std::get<0>(texData);
Debug::log(TRACE, "cursor texture {}x{} {} {} {}", texAttrs.size.x, texAttrs.size.y, (void*)texPtr, texAttrs.format, texAttrs.stride);
// copy cursor texture
for (int i = 0; i < texBuffer->shm().size.y; i++)
memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * textAttrs.stride, textAttrs.stride);
for (int i = 0; i < texAttrs.size.y; i++)
memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * texAttrs.stride, texAttrs.stride);
} else if (currentCursorImage.surface && currentCursorImage.surface->resource()->role->role() == SURFACE_ROLE_CURSOR) {
const auto SURFACE = currentCursorImage.surface->resource();
auto& shmBuffer = CCursorSurfaceRole::cursorPixelData(SURFACE);
Debug::log(TRACE, "cursor texture pixel data length: {}B", shmBuffer.size());

if (shmBuffer.data()) {
// copy cursor texture
// assume format is 32bpp
size_t STRIDE = 4 * SURFACE->current.bufferSize.x;
for (int i = 0; i < SURFACE->current.bufferSize.y; i++)
memcpy(bufPtr + i * buf->dmabuf().strides[0], shmBuffer.data() + i * STRIDE, STRIDE);
} else {
// if there is no data, hide the cursor
memset(bufPtr, '\0', buf->size.x * buf->size.y * 4 /* assume 32bpp */);
}

} else {
Debug::log(TRACE, "Unsupported cursor buffer/surface, falling back to sw (can't dumb copy)");
return nullptr;
}

buf->endDataPtr();
Expand Down Expand Up @@ -740,7 +764,7 @@ void CPointerManager::onMonitorLayoutChange() {
}

SP<CTexture> CPointerManager::getCurrentCursorTexture() {
if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !currentCursorImage.surface->resource()->current.buffer))
if (!currentCursorImage.pBuffer && (!currentCursorImage.surface || !currentCursorImage.surface->resource()->current.texture))
return nullptr;

if (currentCursorImage.pBuffer) {
Expand All @@ -749,7 +773,7 @@ SP<CTexture> CPointerManager::getCurrentCursorTexture() {
return currentCursorImage.bufferTex;
}

return currentCursorImage.surface->resource()->current.buffer->texture;
return currentCursorImage.surface->resource()->current.texture;
}

void CPointerManager::attachPointer(SP<IPointer> pointer) {
Expand Down
2 changes: 1 addition & 1 deletion src/protocols/DRMSyncobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurf
return;
}

if ((acquireTimeline || releaseTimeline) && !surface->pending.buffer) {
if ((acquireTimeline || releaseTimeline) && !surface->pending.texture) {
resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer");
surface->pending.rejected = true;
return;
Expand Down
4 changes: 2 additions & 2 deletions src/protocols/InputMethodV2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,14 @@ CInputMethodPopupV2::CInputMethodPopupV2(SP<CZwpInputPopupSurfaceV2> resource_,
});

listeners.commitSurface = surface->events.commit.registerListener([this](std::any d) {
if (pSurface->current.buffer && !mapped) {
if (pSurface->current.texture && !mapped) {
mapped = true;
pSurface->map();
events.map.emit();
return;
}

if (!pSurface->current.buffer && mapped) {
if (!pSurface->current.texture && mapped) {
mapped = false;
pSurface->unmap();
events.unmap.emit();
Expand Down
2 changes: 1 addition & 1 deletion src/protocols/LayerShell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ CLayerShellResource::CLayerShellResource(SP<CZwlrLayerSurfaceV1> resource_, SP<C
current = pending;
pending.committed = 0;

bool attachedBuffer = surface->current.buffer;
bool attachedBuffer = surface->current.texture;

if (attachedBuffer && !configured) {
surface->error(-1, "layerSurface was not configured, but a buffer was attached");
Expand Down
2 changes: 1 addition & 1 deletion src/protocols/SessionLock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ CSessionLockSurface::CSessionLockSurface(SP<CExtSessionLockSurfaceV1> resource_,
resource->setAckConfigure([this](CExtSessionLockSurfaceV1* r, uint32_t serial) { ackdConfigure = true; });

listeners.surfaceCommit = pSurface->events.commit.registerListener([this](std::any d) {
if (!pSurface->current.buffer) {
if (!pSurface->current.texture) {
LOGM(ERR, "SessionLock attached a null buffer");
resource->error(EXT_SESSION_LOCK_SURFACE_V1_ERROR_NULL_BUFFER, "Null buffer attached");
return;
Expand Down
4 changes: 2 additions & 2 deletions src/protocols/Viewporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ CViewportResource::CViewportResource(SP<CWpViewport> resource_, SP<CWLSurfaceRes
});

listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) {
if (!surface || !surface->pending.buffer)
if (!surface || !surface->pending.texture)
return;

if (surface->pending.viewport.hasSource) {
auto& src = surface->pending.viewport.source;

if (src.w + src.x > surface->pending.buffer->size.x || src.h + src.y > surface->pending.buffer->size.y) {
if (src.w + src.x > surface->pending.bufferSize.x || src.h + src.y > surface->pending.bufferSize.y) {
resource->error(WP_VIEWPORT_ERROR_BAD_VALUE, "Box doesn't fit");
surface->pending.rejected = true;
return;
Expand Down
6 changes: 3 additions & 3 deletions src/protocols/XDGShell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,12 +347,12 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP<CXdgSurface> resource_, SP<CXDGWMBas
if (toplevel)
toplevel->current = toplevel->pending;

if (initialCommit && surface->pending.buffer) {
if (initialCommit && surface->pending.texture) {
resource->error(-1, "Buffer attached before initial commit");
return;
}

if (surface->current.buffer && !mapped) {
if (surface->current.texture && !mapped) {
// this forces apps to not draw CSD.
if (toplevel)
toplevel->setMaximized(true);
Expand All @@ -363,7 +363,7 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP<CXdgSurface> resource_, SP<CXDGWMBas
return;
}

if (!surface->current.buffer && mapped) {
if (!surface->current.texture && mapped) {
mapped = false;
events.unmap.emit();
surface->unmap();
Expand Down
Loading

0 comments on commit 37e1411

Please sign in to comment.