| /**************************************************************************** |
| * Copyright (C) 2016 Intel Corporation. All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| * IN THE SOFTWARE. |
| ***************************************************************************/ |
| |
| #include "swr_context.h" |
| #include "swr_fence.h" |
| |
| #include "util/u_inlines.h" |
| #include "util/u_memory.h" |
| |
| /* |
| * Called by swr_fence_cb to complete the work queue |
| */ |
| void |
| swr_fence_do_work(struct swr_fence *fence) |
| { |
| struct swr_fence_work *work, *tmp; |
| |
| if (fence->work.head.next) { |
| work = fence->work.head.next; |
| /* Immediately clear the head so any new work gets added to a new work |
| * queue */ |
| p_atomic_set(&fence->work.head.next, 0); |
| p_atomic_set(&fence->work.tail, &fence->work.head); |
| p_atomic_set(&fence->work.count, 0); |
| |
| do { |
| tmp = work->next; |
| work->callback(work); |
| FREE(work); |
| work = tmp; |
| } while(work); |
| } |
| } |
| |
| |
| /* |
| * Called by one of the specialized work routines below |
| */ |
| static inline void |
| swr_add_fence_work(struct pipe_fence_handle *fh, |
| struct swr_fence_work *work) |
| { |
| /* If no fence, just do the work now */ |
| if (!fh) { |
| work->callback(work); |
| FREE(work); |
| return; |
| } |
| |
| struct swr_fence *fence = swr_fence(fh); |
| p_atomic_set(&fence->work.tail->next, work); |
| p_atomic_set(&fence->work.tail, work); |
| p_atomic_inc(&fence->work.count); |
| } |
| |
| |
| /* |
| * Generic free/free_aligned, and delete vs/fs |
| */ |
| template<bool aligned_free> |
| static void |
| swr_free_cb(struct swr_fence_work *work) |
| { |
| if (aligned_free) |
| AlignedFree(work->free.data); |
| else |
| FREE(work->free.data); |
| } |
| |
| static void |
| swr_delete_vs_cb(struct swr_fence_work *work) |
| { |
| delete work->free.swr_vs; |
| } |
| |
| static void |
| swr_delete_fs_cb(struct swr_fence_work *work) |
| { |
| delete work->free.swr_fs; |
| } |
| |
| static void |
| swr_delete_gs_cb(struct swr_fence_work *work) |
| { |
| delete work->free.swr_gs; |
| } |
| |
| bool |
| swr_fence_work_free(struct pipe_fence_handle *fence, void *data, |
| bool aligned_free) |
| { |
| struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); |
| if (!work) |
| return false; |
| if (aligned_free) |
| work->callback = swr_free_cb<true>; |
| else |
| work->callback = swr_free_cb<false>; |
| work->free.data = data; |
| |
| swr_add_fence_work(fence, work); |
| |
| return true; |
| } |
| |
| bool |
| swr_fence_work_delete_vs(struct pipe_fence_handle *fence, |
| struct swr_vertex_shader *swr_vs) |
| { |
| struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); |
| if (!work) |
| return false; |
| work->callback = swr_delete_vs_cb; |
| work->free.swr_vs = swr_vs; |
| |
| swr_add_fence_work(fence, work); |
| |
| return true; |
| } |
| |
| bool |
| swr_fence_work_delete_fs(struct pipe_fence_handle *fence, |
| struct swr_fragment_shader *swr_fs) |
| { |
| struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); |
| if (!work) |
| return false; |
| work->callback = swr_delete_fs_cb; |
| work->free.swr_fs = swr_fs; |
| |
| swr_add_fence_work(fence, work); |
| |
| return true; |
| } |
| |
| bool |
| swr_fence_work_delete_gs(struct pipe_fence_handle *fence, |
| struct swr_geometry_shader *swr_gs) |
| { |
| struct swr_fence_work *work = CALLOC_STRUCT(swr_fence_work); |
| if (!work) |
| return false; |
| work->callback = swr_delete_gs_cb; |
| work->free.swr_gs = swr_gs; |
| |
| swr_add_fence_work(fence, work); |
| |
| return true; |
| } |