freedreno_fence.c revision 01e04c3f
1/* 2 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Rob Clark <robclark@freedesktop.org> 25 */ 26 27#include <libsync.h> 28 29#include "util/u_inlines.h" 30 31#include "freedreno_fence.h" 32#include "freedreno_context.h" 33#include "freedreno_util.h" 34 35struct pipe_fence_handle { 36 struct pipe_reference reference; 37 /* fence holds a weak reference to the batch until the batch is flushed, 38 * at which point fd_fence_populate() is called and timestamp and possibly 39 * fence_fd become valid and the week reference is dropped. 40 */ 41 struct fd_batch *batch; 42 struct fd_pipe *pipe; 43 struct fd_screen *screen; 44 int fence_fd; 45 uint32_t timestamp; 46}; 47 48static void fence_flush(struct pipe_fence_handle *fence) 49{ 50 if (fence->batch) 51 fd_batch_flush(fence->batch, true, true); 52 debug_assert(!fence->batch); 53} 54 55void fd_fence_populate(struct pipe_fence_handle *fence, 56 uint32_t timestamp, int fence_fd) 57{ 58 if (!fence->batch) 59 return; 60 fence->timestamp = timestamp; 61 fence->fence_fd = fence_fd; 62 fence->batch = NULL; 63} 64 65static void fd_fence_destroy(struct pipe_fence_handle *fence) 66{ 67 if (fence->fence_fd != -1) 68 close(fence->fence_fd); 69 fd_pipe_del(fence->pipe); 70 FREE(fence); 71} 72 73void fd_fence_ref(struct pipe_screen *pscreen, 74 struct pipe_fence_handle **ptr, 75 struct pipe_fence_handle *pfence) 76{ 77 if (pipe_reference(&(*ptr)->reference, &pfence->reference)) 78 fd_fence_destroy(*ptr); 79 80 *ptr = pfence; 81} 82 83boolean fd_fence_finish(struct pipe_screen *pscreen, 84 struct pipe_context *ctx, 85 struct pipe_fence_handle *fence, 86 uint64_t timeout) 87{ 88 fence_flush(fence); 89 90 if (fence->fence_fd != -1) { 91 int ret = sync_wait(fence->fence_fd, timeout / 1000000); 92 return ret == 0; 93 } 94 95 if (fd_pipe_wait_timeout(fence->pipe, fence->timestamp, timeout)) 96 return false; 97 98 return true; 99} 100 101static struct pipe_fence_handle * fence_create(struct fd_context *ctx, 102 struct fd_batch *batch, uint32_t timestamp, int fence_fd) 103{ 104 struct pipe_fence_handle *fence; 105 106 fence = CALLOC_STRUCT(pipe_fence_handle); 107 if (!fence) 108 return NULL; 109 110 pipe_reference_init(&fence->reference, 1); 111 112 fence->batch = batch; 113 fence->pipe = fd_pipe_ref(ctx->pipe); 114 fence->screen = ctx->screen; 115 fence->timestamp = timestamp; 116 fence->fence_fd = fence_fd; 117 118 return fence; 119} 120 121void fd_create_fence_fd(struct pipe_context *pctx, 122 struct pipe_fence_handle **pfence, int fd, 123 enum pipe_fd_type type) 124{ 125 assert(type == PIPE_FD_TYPE_NATIVE_SYNC); 126 *pfence = fence_create(fd_context(pctx), NULL, 0, dup(fd)); 127} 128 129void fd_fence_server_sync(struct pipe_context *pctx, 130 struct pipe_fence_handle *fence) 131{ 132 struct fd_context *ctx = fd_context(pctx); 133 struct fd_batch *batch = fd_context_batch(ctx); 134 135 fence_flush(fence); 136 137 /* if not an external fence, then nothing more to do without preemption: */ 138 if (fence->fence_fd == -1) 139 return; 140 141 if (sync_accumulate("freedreno", &batch->in_fence_fd, fence->fence_fd)) { 142 /* error */ 143 } 144} 145 146int fd_fence_get_fd(struct pipe_screen *pscreen, 147 struct pipe_fence_handle *fence) 148{ 149 fence_flush(fence); 150 return dup(fence->fence_fd); 151} 152 153struct pipe_fence_handle * fd_fence_create(struct fd_batch *batch) 154{ 155 return fence_create(batch->ctx, batch, 0, -1); 156} 157