1 /************************************************************************** 2 * 3 * Copyright 2011 Marek Olk <maraeo (at) gmail.com> 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Authors: 30 * Marek Olk <maraeo (at) gmail.com> 31 */ 32 33 #include "main/glheader.h" 34 #include "main/macros.h" 35 #include "pipe/p_context.h" 36 #include "pipe/p_screen.h" 37 #include "st_context.h" 38 #include "st_cb_syncobj.h" 39 40 struct st_sync_object { 41 struct gl_sync_object b; 42 43 struct pipe_fence_handle *fence; 44 mtx_t mutex; /**< protects "fence" */ 45 }; 46 47 48 static struct gl_sync_object *st_new_sync_object(struct gl_context *ctx) 49 { 50 struct st_sync_object *so = CALLOC_STRUCT(st_sync_object); 51 52 mtx_init(&so->mutex, mtx_plain); 53 return &so->b; 54 } 55 56 static void st_delete_sync_object(struct gl_context *ctx, 57 struct gl_sync_object *obj) 58 { 59 struct pipe_screen *screen = st_context(ctx)->pipe->screen; 60 struct st_sync_object *so = (struct st_sync_object*)obj; 61 62 screen->fence_reference(screen, &so->fence, NULL); 63 mtx_destroy(&so->mutex); 64 free(so->b.Label); 65 free(so); 66 } 67 68 static void st_fence_sync(struct gl_context *ctx, struct gl_sync_object *obj, 69 GLenum condition, GLbitfield flags) 70 { 71 struct pipe_context *pipe = st_context(ctx)->pipe; 72 struct st_sync_object *so = (struct st_sync_object*)obj; 73 74 assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0); 75 assert(so->fence == NULL); 76 77 pipe->flush(pipe, &so->fence, PIPE_FLUSH_DEFERRED); 78 } 79 80 static void st_client_wait_sync(struct gl_context *ctx, 81 struct gl_sync_object *obj, 82 GLbitfield flags, GLuint64 timeout) 83 { 84 struct pipe_context *pipe = st_context(ctx)->pipe; 85 struct pipe_screen *screen = pipe->screen; 86 struct st_sync_object *so = (struct st_sync_object*)obj; 87 struct pipe_fence_handle *fence = NULL; 88 89 /* If the fence doesn't exist, assume it's signalled. */ 90 mtx_lock(&so->mutex); 91 if (!so->fence) { 92 mtx_unlock(&so->mutex); 93 so->b.StatusFlag = GL_TRUE; 94 return; 95 } 96 97 /* We need a local copy of the fence pointer, so that we can call 98 * fence_finish unlocked. 99 */ 100 screen->fence_reference(screen, &fence, so->fence); 101 mtx_unlock(&so->mutex); 102 103 /* Section 4.1.2 of OpenGL 4.5 (Compatibility Profile) says: 104 * [...] if ClientWaitSync is called and all of the following are true: 105 * - the SYNC_FLUSH_COMMANDS_BIT bit is set in flags, 106 * - sync is unsignaled when ClientWaitSync is called, 107 * - and the calls to ClientWaitSync and FenceSync were issued from 108 * the same context, 109 * then the GL will behave as if the equivalent of Flush were inserted 110 * immediately after the creation of sync. 111 * 112 * Assume GL_SYNC_FLUSH_COMMANDS_BIT is always set, because applications 113 * forget to set it. 114 */ 115 if (screen->fence_finish(screen, pipe, fence, timeout)) { 116 mtx_lock(&so->mutex); 117 screen->fence_reference(screen, &so->fence, NULL); 118 mtx_unlock(&so->mutex); 119 so->b.StatusFlag = GL_TRUE; 120 } 121 screen->fence_reference(screen, &fence, NULL); 122 } 123 124 static void st_check_sync(struct gl_context *ctx, struct gl_sync_object *obj) 125 { 126 st_client_wait_sync(ctx, obj, 0, 0); 127 } 128 129 static void st_server_wait_sync(struct gl_context *ctx, 130 struct gl_sync_object *obj, 131 GLbitfield flags, GLuint64 timeout) 132 { 133 struct pipe_context *pipe = st_context(ctx)->pipe; 134 struct pipe_screen *screen = pipe->screen; 135 struct st_sync_object *so = (struct st_sync_object*)obj; 136 struct pipe_fence_handle *fence = NULL; 137 138 /* Nothing needs to be done here if the driver does not support async 139 * flushes. */ 140 if (!pipe->fence_server_sync) 141 return; 142 143 /* If the fence doesn't exist, assume it's signalled. */ 144 mtx_lock(&so->mutex); 145 if (!so->fence) { 146 mtx_unlock(&so->mutex); 147 so->b.StatusFlag = GL_TRUE; 148 return; 149 } 150 151 /* We need a local copy of the fence pointer. */ 152 screen->fence_reference(screen, &fence, so->fence); 153 mtx_unlock(&so->mutex); 154 155 pipe->fence_server_sync(pipe, fence); 156 screen->fence_reference(screen, &fence, NULL); 157 } 158 159 void st_init_syncobj_functions(struct dd_function_table *functions) 160 { 161 functions->NewSyncObject = st_new_sync_object; 162 functions->FenceSync = st_fence_sync; 163 functions->DeleteSyncObject = st_delete_sync_object; 164 functions->CheckSync = st_check_sync; 165 functions->ClientWaitSync = st_client_wait_sync; 166 functions->ServerWaitSync = st_server_wait_sync; 167 } 168