diff options
Diffstat (limited to 'src/gallium/drivers/freedreno/freedreno_fence.c')
-rw-r--r-- | src/gallium/drivers/freedreno/freedreno_fence.c | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/src/gallium/drivers/freedreno/freedreno_fence.c b/src/gallium/drivers/freedreno/freedreno_fence.c index e3d200aa3a1..928972003c6 100644 --- a/src/gallium/drivers/freedreno/freedreno_fence.c +++ b/src/gallium/drivers/freedreno/freedreno_fence.c @@ -36,12 +36,34 @@ struct pipe_fence_handle { struct pipe_reference reference; + /* fence holds a weak reference to the batch until the batch is flushed, + * at which point fd_fence_populate() is called and timestamp and possibly + * fence_fd become valid and the week reference is dropped. + */ + struct fd_batch *batch; struct fd_context *ctx; struct fd_screen *screen; int fence_fd; uint32_t timestamp; }; +static void fence_flush(struct pipe_fence_handle *fence) +{ + if (fence->batch) + fd_batch_flush(fence->batch, true, true); + debug_assert(!fence->batch); +} + +void fd_fence_populate(struct pipe_fence_handle *fence, + uint32_t timestamp, int fence_fd) +{ + if (!fence->batch) + return; + fence->timestamp = timestamp; + fence->fence_fd = fence_fd; + fence->batch = NULL; +} + static void fd_fence_destroy(struct pipe_fence_handle *fence) { if (fence->fence_fd != -1) @@ -64,6 +86,8 @@ boolean fd_fence_finish(struct pipe_screen *pscreen, struct pipe_fence_handle *fence, uint64_t timeout) { + fence_flush(fence); + if (fence->fence_fd != -1) { int ret = sync_wait(fence->fence_fd, timeout / 1000000); return ret == 0; @@ -75,10 +99,30 @@ boolean fd_fence_finish(struct pipe_screen *pscreen, return true; } +static struct pipe_fence_handle * fence_create(struct fd_context *ctx, + struct fd_batch *batch, uint32_t timestamp, int fence_fd) +{ + struct pipe_fence_handle *fence; + + fence = CALLOC_STRUCT(pipe_fence_handle); + if (!fence) + return NULL; + + pipe_reference_init(&fence->reference, 1); + + fence->batch = batch; + fence->ctx = ctx; + fence->screen = ctx->screen; + fence->timestamp = timestamp; + fence->fence_fd = fence_fd; + + return fence; +} + void fd_create_fence_fd(struct pipe_context *pctx, struct pipe_fence_handle **pfence, int fd) { - *pfence = fd_fence_create(fd_context(pctx), 0, dup(fd)); + *pfence = fence_create(fd_context(pctx), NULL, 0, dup(fd)); } void fd_fence_server_sync(struct pipe_context *pctx, @@ -87,6 +131,8 @@ void fd_fence_server_sync(struct pipe_context *pctx, struct fd_context *ctx = fd_context(pctx); struct fd_batch *batch = ctx->batch; + fence_flush(fence); + if (sync_accumulate("freedreno", &batch->in_fence_fd, fence->fence_fd)) { /* error */ } @@ -95,24 +141,11 @@ void fd_fence_server_sync(struct pipe_context *pctx, int fd_fence_get_fd(struct pipe_screen *pscreen, struct pipe_fence_handle *fence) { + fence_flush(fence); return dup(fence->fence_fd); } -struct pipe_fence_handle * fd_fence_create(struct fd_context *ctx, - uint32_t timestamp, int fence_fd) +struct pipe_fence_handle * fd_fence_create(struct fd_batch *batch) { - struct pipe_fence_handle *fence; - - fence = CALLOC_STRUCT(pipe_fence_handle); - if (!fence) - return NULL; - - pipe_reference_init(&fence->reference, 1); - - fence->ctx = ctx; - fence->screen = ctx->screen; - fence->timestamp = timestamp; - fence->fence_fd = fence_fd; - - return fence; + return fence_create(batch->ctx, batch, 0, -1); } |