From 1d786a13b03b3055612dbf84a594b9fd2fb68aba Mon Sep 17 00:00:00 2001 From: Jens Nolte <git@queezle.net> Date: Sun, 21 Aug 2022 14:45:10 +0200 Subject: [PATCH] Simplify buffer release event handling --- src/Quasar/Wayland/Server/Shm.hs | 4 ++-- src/Quasar/Wayland/Server/Surface.hs | 25 ++++++++----------------- src/Quasar/Wayland/Shm.hs | 6 +++--- src/Quasar/Wayland/Surface.hs | 16 ++++++++++++---- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/Quasar/Wayland/Server/Shm.hs b/src/Quasar/Wayland/Server/Shm.hs index 65234b9..0a077e5 100644 --- a/src/Quasar/Wayland/Server/Shm.hs +++ b/src/Quasar/Wayland/Server/Shm.hs @@ -38,5 +38,5 @@ initializeWlShmPool wlShmPool fd size = do initializeWlShmBuffer :: ShmPool -> NewObject 'Server Interface_wl_buffer -> Int32 -> Int32 -> Int32 -> Int32 -> Word32 -> STM () initializeWlShmBuffer pool wlBuffer offset width height stride format = do - let initializeBufferFn = newShmBuffer pool offset width height stride format - initializeWlBuffer @ShmBufferBackend wlBuffer initializeBufferFn + buffer <- newShmBuffer pool offset width height stride format + initializeWlBuffer @ShmBufferBackend wlBuffer buffer diff --git a/src/Quasar/Wayland/Server/Surface.hs b/src/Quasar/Wayland/Server/Surface.hs index 8144428..9d9093c 100644 --- a/src/Quasar/Wayland/Server/Surface.hs +++ b/src/Quasar/Wayland/Server/Surface.hs @@ -24,7 +24,7 @@ data ServerSurface b = ServerSurface { data ServerBuffer b = ServerBuffer { buffer :: Buffer b, - attachedCount :: TVar Int + wlBuffer :: Object 'Server Interface_wl_buffer } newServerSurface :: forall b. STM (ServerSurface b) @@ -57,15 +57,16 @@ commitServerSurface surface = do _ -> DamageAll combinedDamage = bufferDamage <> convertedSurfaceDamage + -- Attach callback for wl_buffer.release + forM_ serverBuffer \sb -> + addBufferReleaseCallback sb.buffer sb.wlBuffer.release + commitSurface surface.surface SurfaceCommit { buffer = (.buffer) <$> serverBuffer, offset, bufferDamage = combinedDamage } - case serverBuffer of - Just sb -> modifyTVar sb.attachedCount (+ 1) - Nothing -> pure () attachToSurface :: forall b. BufferBackend b => ServerSurface b -> Maybe (Object 'Server Interface_wl_buffer) -> Int32 -> Int32 -> STM () attachToSurface surface wlBuffer x y = do @@ -103,27 +104,17 @@ initializeServerSurface wlSurface = do setInterfaceData wlSurface surface traceM "wl_surface not implemented" -initializeWlBuffer :: forall b. BufferBackend b => NewObject 'Server Interface_wl_buffer -> (STM () -> STM (Buffer b)) -> STM () -initializeWlBuffer wlBuffer initializeBufferFn = do - attachedCount <- newTVar 0 - buffer <- initializeBufferFn (releaseServerBuffer attachedCount) - +initializeWlBuffer :: forall b. BufferBackend b => NewObject 'Server Interface_wl_buffer -> Buffer b -> STM () +initializeWlBuffer wlBuffer buffer = do let serverBuffer = ServerBuffer { buffer, - attachedCount + wlBuffer } setInterfaceData wlBuffer serverBuffer setRequestHandler wlBuffer RequestHandler_wl_buffer { -- TODO propagate buffer destruction destroy = destroyBuffer buffer } - where - releaseServerBuffer :: TVar Int -> STM () - releaseServerBuffer attachedCountVar = do - attachedCount <- swapTVar attachedCountVar 0 - -- TODO handle other exceptions (e.g. disconnects) - unlessM (isDestroyed wlBuffer) $ - sequence_ $ replicate attachedCount $ wlBuffer.release getServerBuffer :: forall b. BufferBackend b => Object 'Server Interface_wl_buffer -> STM (ServerBuffer b) diff --git a/src/Quasar/Wayland/Shm.hs b/src/Quasar/Wayland/Shm.hs index 7114f22..954a0c4 100644 --- a/src/Quasar/Wayland/Shm.hs +++ b/src/Quasar/Wayland/Shm.hs @@ -83,12 +83,12 @@ tryFinalizeShmPool pool = do -- | Create a new buffer for an externally managed pool -newShmBuffer :: ShmPool -> Int32 -> Int32 -> Int32 -> Int32 -> Word32 -> STM () -> STM (Buffer ShmBufferBackend) -newShmBuffer pool offset width height stride format releaseBuffer = do +newShmBuffer :: ShmPool -> Int32 -> Int32 -> Int32 -> Int32 -> Word32 -> STM (Buffer ShmBufferBackend) +newShmBuffer pool offset width height stride format = do -- TODO check arguments modifyTVar pool.bufferCount succ let shmBuffer = ShmBuffer pool offset width height stride format - newBuffer @ShmBufferBackend shmBuffer releaseBuffer + newBuffer @ShmBufferBackend shmBuffer data DownstreamShmPool = DownstreamShmPool diff --git a/src/Quasar/Wayland/Surface.hs b/src/Quasar/Wayland/Surface.hs index d779193..0902461 100644 --- a/src/Quasar/Wayland/Surface.hs +++ b/src/Quasar/Wayland/Surface.hs @@ -5,6 +5,7 @@ module Quasar.Wayland.Surface ( newBuffer, lockBuffer, destroyBuffer, + addBufferReleaseCallback, -- * Surface Damage(..), @@ -31,14 +32,15 @@ class Typeable b => BufferBackend b where data Buffer b = Buffer { content :: BufferContent b, -- | Buffer has been released by all current users and can be reused by the owner. - releaseBuffer :: STM (), + releaseBuffer :: TVar (STM ()), -- | Refcount that tracks how many times the buffer is locked by consumers. lockCount :: TVar Int, destroyed :: TVar Bool } -newBuffer :: forall b. BufferContent b -> STM () -> STM (Buffer b) -newBuffer content releaseBuffer = do +newBuffer :: forall b. BufferContent b -> STM (Buffer b) +newBuffer content = do + releaseBuffer <- newTVar (pure ()) lockCount <- newTVar 0 destroyed <- newTVar False pure Buffer { @@ -48,6 +50,12 @@ newBuffer content releaseBuffer = do destroyed } + +addBufferReleaseCallback :: Buffer b -> STM () -> STM () +addBufferReleaseCallback buffer releaseFn = + modifyTVar buffer.releaseBuffer (>> releaseFn) + + -- | Prevents the buffer from being released. Returns an unlock action. lockBuffer :: forall b. BufferBackend b => Buffer b -> STM (STM ()) lockBuffer buffer = do @@ -58,7 +66,7 @@ lockBuffer buffer = do unlockBuffer = do lockCount <- stateTVar buffer.lockCount (dup . pred) when (lockCount == 0) do - buffer.releaseBuffer + join $ swapTVar buffer.releaseBuffer (pure ()) tryFinalizeBuffer @b buffer -- | Request destruction of the buffer. Since the buffer might still be in use downstream, the backing storage must not be changed until all downstreams release the buffer (signalled by `releaseBufferStorage`). -- GitLab