1/**************************************************************************** 2 * Copyright (C) 2015 Intel Corporation. All Rights Reserved. 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 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 ***************************************************************************/ 23 24#include "pipe/p_screen.h" 25#include "util/u_memory.h" 26#include "util/os_time.h" 27 28#include "swr_context.h" 29#include "swr_screen.h" 30#include "swr_fence.h" 31 32#ifdef __APPLE__ 33#include <sched.h> 34#endif 35 36#if defined(PIPE_CC_MSVC) // portable thread yield 37 #define sched_yield SwitchToThread 38#endif 39 40/* 41 * Fence callback, called by back-end thread on completion of all rendering up 42 * to SwrSync call. 43 */ 44static void 45swr_fence_cb(uint64_t userData, uint64_t userData2, uint64_t userData3) 46{ 47 struct swr_fence *fence = (struct swr_fence *)userData; 48 49 /* Complete all work attached to the fence */ 50 swr_fence_do_work(fence); 51 52 /* Correct value is in SwrSync data, and not the fence write field. */ 53 /* Contexts may not finish in order, but fence value always increases */ 54 if (fence->read < userData2) 55 fence->read = userData2; 56} 57 58/* 59 * Submit an existing fence. 60 */ 61void 62swr_fence_submit(struct swr_context *ctx, struct pipe_fence_handle *fh) 63{ 64 struct swr_fence *fence = swr_fence(fh); 65 66 fence->write++; 67 fence->pending = TRUE; 68 ctx->api.pfnSwrSync(ctx->swrContext, swr_fence_cb, (uint64_t)fence, fence->write, 0); 69} 70 71/* 72 * Create a new fence object. 73 */ 74struct pipe_fence_handle * 75swr_fence_create() 76{ 77 static int fence_id = 0; 78 struct swr_fence *fence = CALLOC_STRUCT(swr_fence); 79 if (!fence) 80 return NULL; 81 82 pipe_reference_init(&fence->reference, 1); 83 fence->id = fence_id++; 84 fence->work.tail = &fence->work.head; 85 86 return (struct pipe_fence_handle *)fence; 87} 88 89/** Destroy a fence. Called when refcount hits zero. */ 90static void 91swr_fence_destroy(struct swr_fence *fence) 92{ 93 /* Complete any work left if fence was not submitted */ 94 swr_fence_do_work(fence); 95 FREE(fence); 96} 97 98/** 99 * Set ptr = fence, with reference counting 100 */ 101void 102swr_fence_reference(struct pipe_screen *screen, 103 struct pipe_fence_handle **ptr, 104 struct pipe_fence_handle *f) 105{ 106 struct swr_fence *fence = swr_fence(f); 107 struct swr_fence *old; 108 109 if (likely(ptr)) { 110 old = swr_fence(*ptr); 111 *ptr = f; 112 } else { 113 old = NULL; 114 } 115 116 if (pipe_reference(&old->reference, &fence->reference)) { 117 swr_fence_finish(screen, NULL, (struct pipe_fence_handle *) old, 0); 118 swr_fence_destroy(old); 119 } 120} 121 122 123/* 124 * Wait for the fence to finish. 125 */ 126bool 127swr_fence_finish(struct pipe_screen *screen, 128 struct pipe_context *ctx, 129 struct pipe_fence_handle *fence_handle, 130 uint64_t timeout) 131{ 132 while (!swr_is_fence_done(fence_handle)) 133 sched_yield(); 134 135 swr_fence(fence_handle)->pending = FALSE; 136 137 return TRUE; 138} 139 140 141uint64_t 142swr_get_timestamp(struct pipe_screen *screen) 143{ 144 return os_time_get_nano(); 145} 146 147 148void 149swr_fence_init(struct pipe_screen *p_screen) 150{ 151 p_screen->fence_reference = swr_fence_reference; 152 p_screen->fence_finish = swr_fence_finish; 153 p_screen->get_timestamp = swr_get_timestamp; 154 155 /* Create persistant StoreTiles "flush" fence, used to signal completion 156 * of flushing tile state back to resource texture, via StoreTiles. */ 157 struct swr_screen *screen = swr_screen(p_screen); 158 screen->flush_fence = swr_fence_create(); 159} 160