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