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