1 /**************************************************************************** 2 * Copyright (C) 2016 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 "swr_context.h" 25 #include "swr_fence.h" 26 27 #include "util/u_inlines.h" 28 #include "util/u_memory.h" 29 30 /* 31 * Called by swr_fence_cb to complete the work queue 32 */ 33 void 34 swr_fence_do_work(struct swr_fence *fence) 35 { 36 struct swr_fence_work *work, *tmp; 37 38 if (fence->work.head.next) { 39 work = fence->work.head.next; 40 /* Immediately clear the head so any new work gets added to a new work 41 * queue */ 42 p_atomic_set(&fence->work.head.next, 0); 43 p_atomic_set(&fence->work.tail, &fence->work.head); 44 p_atomic_set(&fence->work.count, 0); 45 46 do { 47 tmp = work->next; 48 work->callback(work); 49 FREE(work); 50 work = tmp; 51 } while(work); 52 } 53 } 54 55 56 /* 57 * Called by one of the specialized work routines below 58 */ 59 static inline void 60 swr_add_fence_work(struct pipe_fence_handle *fh, 61 struct swr_fence_work *work) 62 { 63 /* If no fence, just do the work now */ 64 if (!fh) { 65 work->callback(work); 66 FREE(work); 67 return; 68 } 69 70 struct swr_fence *fence = swr_fence(fh); 71 p_atomic_set(&fence->work.tail->next, work); 72 p_atomic_set(&fence->work.tail, work); 73 p_atomic_inc(&fence->work.count); 74 } 75 76 77 /* 78 * Generic free/free_aligned, and delete vs/fs 79 */ 80 template<bool aligned_free> 81 static void 82 swr_free_cb(struct swr_fence_work *work) 83 { 84 if (aligned_free) 85 AlignedFree(work->free.data); 86 else 87 FREE(work->free.data); 88 } 89 90 static void 91 swr_delete_vs_cb(struct swr_fence_work *work) 92 { 93 delete work->free.swr_vs; 94 } 95 96 static void 97 swr_delete_fs_cb(struct swr_fence_work *work) 98 { 99 delete work->free.swr_fs; 100 } 101 102 bool 103 swr_fence_work_free(struct pipe_fence_handle *fence, void *data, 104 bool aligned_free) 105 { 106 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 107 if (!work) 108 return false; 109 if (aligned_free) 110 work->callback = swr_free_cb<true>; 111 else 112 work->callback = swr_free_cb<false>; 113 work->free.data = data; 114 115 swr_add_fence_work(fence, work); 116 117 return true; 118 } 119 120 bool 121 swr_fence_work_delete_vs(struct pipe_fence_handle *fence, 122 struct swr_vertex_shader *swr_vs) 123 { 124 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 125 if (!work) 126 return false; 127 work->callback = swr_delete_vs_cb; 128 work->free.swr_vs = swr_vs; 129 130 swr_add_fence_work(fence, work); 131 132 return true; 133 } 134 135 bool 136 swr_fence_work_delete_fs(struct pipe_fence_handle *fence, 137 struct swr_fragment_shader *swr_fs) 138 { 139 struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); 140 if (!work) 141 return false; 142 work->callback = swr_delete_fs_cb; 143 work->free.swr_fs = swr_fs; 144 145 swr_add_fence_work(fence, work); 146 147 return true; 148 } 149