13192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz/**********************************************************
2e2a1d21cb665b7e7bc2c9684cf533003cdc817b3Brian Paul * Copyright 2009-2015 VMware, Inc.  All rights reserved.
33192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz *
43192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * Permission is hereby granted, free of charge, to any person
53192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * obtaining a copy of this software and associated documentation
63192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * files (the "Software"), to deal in the Software without
73192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * restriction, including without limitation the rights to use, copy,
83192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * modify, merge, publish, distribute, sublicense, and/or sell copies
93192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * of the Software, and to permit persons to whom the Software is
103192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * furnished to do so, subject to the following conditions:
113192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz *
123192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * The above copyright notice and this permission notice shall be
133192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * included in all copies or substantial portions of the Software.
143192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz *
153192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
163192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
173192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
183192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
193192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
203192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
213192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
223192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * SOFTWARE.
233192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz *
243192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz **********************************************************/
253192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "util/u_memory.h"
26e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom#include "util/u_atomic.h"
277a30668ad665f3315106e1a959c6186dea79a24aJason Ekstrand#include "util/list.h"
28fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul#include "os/os_thread.h"
29e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
303192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "pipebuffer/pb_buffer_fenced.h"
313192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
323192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "vmw_screen.h"
333192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "vmw_fence.h"
343192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
353192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzstruct vmw_fence_ops
363192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
37fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   /*
38fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul    * Immutable members.
39fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul    */
403192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct pb_fence_ops base;
413192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct vmw_winsys_screen *vws;
42fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
43fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   pipe_mutex mutex;
44fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
45fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   /*
46fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul    * Protected by mutex;
47fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul    */
48fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   struct list_head not_signaled;
49fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   uint32_t last_signaled;
50fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   uint32_t last_emitted;
513192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz};
523192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
53e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstromstruct vmw_fence
54e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom{
55fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   struct list_head ops_list;
56e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   int32_t refcount;
57e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   uint32_t handle;
58e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   uint32_t mask;
59e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   int32_t signalled;
60fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   uint32_t seqno;
61e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom};
623192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
63e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
64fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * vmw_fence_seq_is_signaled - Check whether a fence seqno is
65fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * signaled.
66fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul *
67fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * @ops: Pointer to a struct pb_fence_ops.
68fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul *
69fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul */
70a2a1a5805fd617e7f3cc8be44dd79b50da07ebb9Ilia Mirkinstatic inline boolean
71fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paulvmw_fence_seq_is_signaled(uint32_t seq, uint32_t last, uint32_t cur)
72fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul{
73fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   return (cur - last <= cur - seq);
74fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul}
75fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
76fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
77fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul/**
78fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * vmw_fence_ops - Return the vmw_fence_ops structure backing a
79fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * struct pb_fence_ops pointer.
80fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul *
81fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * @ops: Pointer to a struct pb_fence_ops.
82fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul *
83fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul */
84a2a1a5805fd617e7f3cc8be44dd79b50da07ebb9Ilia Mirkinstatic inline struct vmw_fence_ops *
85fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paulvmw_fence_ops(struct pb_fence_ops *ops)
86fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul{
87fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   assert(ops);
88fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   return (struct vmw_fence_ops *)ops;
89fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul}
90fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
91fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
92fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul/**
93fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * vmw_fences_release - Release all fences from the not_signaled
94fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * list.
95fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul *
96fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * @ops: Pointer to a struct vmw_fence_ops.
97fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul *
98fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul */
99fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paulstatic void
100fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paulvmw_fences_release(struct vmw_fence_ops *ops)
101fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul{
102fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   struct vmw_fence *fence, *n;
103fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
104fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   pipe_mutex_lock(ops->mutex);
105fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   LIST_FOR_EACH_ENTRY_SAFE(fence, n, &ops->not_signaled, ops_list)
106fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      LIST_DELINIT(&fence->ops_list);
107fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   pipe_mutex_unlock(ops->mutex);
108fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul}
109fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
110fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul/**
111fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * vmw_fences_signal - Traverse the not_signaled list and try to
112fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * signal unsignaled fences.
113fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul *
114fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * @ops: Pointer to a struct pb_fence_ops.
115fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * @signaled: Seqno that has signaled.
116fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * @emitted: Last seqno emitted by the kernel.
117fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * @has_emitted: Whether we provide the emitted value.
118fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul *
119fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul */
120fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paulvoid
121fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paulvmw_fences_signal(struct pb_fence_ops *fence_ops,
122fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul                  uint32_t signaled,
123fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul                  uint32_t emitted,
124fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul                  boolean has_emitted)
125fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul{
126fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   struct vmw_fence_ops *ops = NULL;
127fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   struct vmw_fence *fence, *n;
128fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
129fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   if (fence_ops == NULL)
130fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      return;
131fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
132fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   ops = vmw_fence_ops(fence_ops);
133fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   pipe_mutex_lock(ops->mutex);
134fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
135fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   if (!has_emitted) {
136fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      emitted = ops->last_emitted;
137fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      if (emitted - signaled > (1 << 30))
138fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul	emitted = signaled;
139fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   }
140fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
141fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   if (signaled == ops->last_signaled && emitted == ops->last_emitted)
142fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      goto out_unlock;
143fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
144fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   LIST_FOR_EACH_ENTRY_SAFE(fence, n, &ops->not_signaled, ops_list) {
145fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      if (!vmw_fence_seq_is_signaled(fence->seqno, signaled, emitted))
146fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul         break;
147fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
148fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      p_atomic_set(&fence->signalled, 1);
149fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      LIST_DELINIT(&fence->ops_list);
150fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   }
151fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   ops->last_signaled = signaled;
152fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   ops->last_emitted = emitted;
153fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
154fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paulout_unlock:
155fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   pipe_mutex_unlock(ops->mutex);
156fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul}
157fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
158fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
159fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul/**
160e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence - return the vmw_fence object identified by a
161e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * struct pipe_fence_handle *
162e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
163e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @fence: The opaque pipe fence handle.
164e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
165a2a1a5805fd617e7f3cc8be44dd79b50da07ebb9Ilia Mirkinstatic inline struct vmw_fence *
166e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstromvmw_fence(struct pipe_fence_handle *fence)
167e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom{
168e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   return (struct vmw_fence *) fence;
169e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom}
170e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
171fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
172e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
173e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence_create - Create a user-space fence object.
174e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
175fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul * @fence_ops: The fence_ops manager to register with.
176e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @handle: Handle identifying the kernel fence object.
177e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @mask: Mask of flags that this fence object may signal.
178e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
179e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * Returns NULL on failure.
180e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
181e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstromstruct pipe_fence_handle *
182fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paulvmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle,
183fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul                 uint32_t seqno, uint32_t mask)
184e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom{
185e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   struct vmw_fence *fence = CALLOC_STRUCT(vmw_fence);
186fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   struct vmw_fence_ops *ops = vmw_fence_ops(fence_ops);
187e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
188e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   if (!fence)
189e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      return NULL;
190e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
191e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   p_atomic_set(&fence->refcount, 1);
192e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   fence->handle = handle;
193e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   fence->mask = mask;
194fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   fence->seqno = seqno;
195e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   p_atomic_set(&fence->signalled, 0);
196fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   pipe_mutex_lock(ops->mutex);
197fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
198fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   if (vmw_fence_seq_is_signaled(seqno, ops->last_signaled, seqno)) {
199fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      p_atomic_set(&fence->signalled, 1);
200fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      LIST_INITHEAD(&fence->ops_list);
201fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   } else {
202fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      p_atomic_set(&fence->signalled, 0);
203fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      LIST_ADDTAIL(&fence->ops_list, &ops->not_signaled);
204fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   }
205e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
206fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   pipe_mutex_unlock(ops->mutex);
207e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
208fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   return (struct pipe_fence_handle *) fence;
2093192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
2103192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2113192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
212e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
213e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence_reference - Reference / unreference a vmw fence object.
214e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
215e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @vws: Pointer to the winsys screen.
216e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @ptr: Pointer to reference transfer destination.
217e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @fence: Pointer to object to reference. May be NULL.
218e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
219e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstromvoid
220e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstromvmw_fence_reference(struct vmw_winsys_screen *vws,
221e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom		    struct pipe_fence_handle **ptr,
222e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom		    struct pipe_fence_handle *fence)
223e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom{
224e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   if (*ptr) {
225e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      struct vmw_fence *vfence = vmw_fence(*ptr);
226e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
227e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      if (p_atomic_dec_zero(&vfence->refcount)) {
228fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul         struct vmw_fence_ops *ops = vmw_fence_ops(vws->fence_ops);
229fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
230e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom	 vmw_ioctl_fence_unref(vws, vfence->handle);
231fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
232fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul         pipe_mutex_lock(ops->mutex);
233fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul         LIST_DELINIT(&vfence->ops_list);
234fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul         pipe_mutex_unlock(ops->mutex);
235fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul
236e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom	 FREE(vfence);
237e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      }
238e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   }
239e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
240e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   if (fence) {
241e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      struct vmw_fence *vfence = vmw_fence(fence);
242e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
243e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      p_atomic_inc(&vfence->refcount);
244e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   }
245e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
246e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   *ptr = fence;
247e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom}
248e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
249e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
250e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
251e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence_signalled - Check whether a fence object is signalled.
252e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
253e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @vws: Pointer to the winsys screen.
254e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @fence: Handle to the fence object.
255e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @flag: Fence flags to check. If the fence object can't signal
256e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * a flag, it is assumed to be already signaled.
257e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
258e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * Returns 0 if the fence object was signaled, nonzero otherwise.
259e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
260e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstromint
261e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstromvmw_fence_signalled(struct vmw_winsys_screen *vws,
262e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom		   struct pipe_fence_handle *fence,
263e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom		   unsigned flag)
264e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom{
265e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   struct vmw_fence *vfence;
266e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   int32_t vflags = SVGA_FENCE_FLAG_EXEC;
267e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   int ret;
268e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   uint32_t old;
269e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
270e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   if (!fence)
271e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      return 0;
272e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
273e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   vfence = vmw_fence(fence);
274e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   old = p_atomic_read(&vfence->signalled);
275e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
276e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   vflags &= ~vfence->mask;
277e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
278e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   if ((old & vflags) == vflags)
279e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      return 0;
280e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
281fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   /*
282fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul    * Currently we update signaled fences on each execbuf call.
283fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul    * That should really be sufficient, and we can avoid
284fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul    * a lot of kernel calls this way.
285fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul    */
286fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul#if 1
287e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   ret = vmw_ioctl_fence_signalled(vws, vfence->handle, vflags);
288e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
289fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   if (ret == 0)
290fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul      p_atomic_set(&vfence->signalled, 1);
291e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   return ret;
292fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul#else
293fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   (void) ret;
294fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   return -1;
295fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul#endif
296e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom}
297e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
298e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
299e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence_finish - Wait for a fence object to signal.
300e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
301e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @vws: Pointer to the winsys screen.
302e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @fence: Handle to the fence object.
303e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @flag: Fence flags to wait for. If the fence object can't signal
304e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * a flag, it is assumed to be already signaled.
305e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
306e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * Returns 0 if the wait succeeded. Nonzero otherwise.
307e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
308e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstromint
309e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstromvmw_fence_finish(struct vmw_winsys_screen *vws,
310e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom		 struct pipe_fence_handle *fence,
311e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom		 unsigned flag)
312e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom{
313e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   struct vmw_fence *vfence;
314e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   int32_t vflags = SVGA_FENCE_FLAG_EXEC;
315e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   int ret;
316e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   uint32_t old;
317e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
318e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   if (!fence)
319e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      return 0;
320e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
321e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   vfence = vmw_fence(fence);
322e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   old = p_atomic_read(&vfence->signalled);
323e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   vflags &= ~vfence->mask;
324e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
325e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   if ((old & vflags) == vflags)
326e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      return 0;
327e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
328e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   ret = vmw_ioctl_fence_finish(vws, vfence->handle, vflags);
329e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
330e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   if (ret == 0) {
331e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      int32_t prev = old;
332e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
333e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      do {
334e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom	 old = prev;
335e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom	 prev = p_atomic_cmpxchg(&vfence->signalled, old, old | vflags);
336e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom      } while (prev != old);
337e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   }
338e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
339e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   return ret;
340e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom}
341e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
342e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
343e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
344e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence_ops_fence_reference - wrapper for the pb_fence_ops api.
345e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
346e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * wrapper around vmw_fence_reference.
347e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
3483192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzstatic void
3493192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzvmw_fence_ops_fence_reference(struct pb_fence_ops *ops,
3503192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                              struct pipe_fence_handle **ptr,
3513192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                              struct pipe_fence_handle *fence)
3523192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
353e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
3543192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
355e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   vmw_fence_reference(vws, ptr, fence);
356e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom}
3573192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
358e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
359e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence_ops_fence_signalled - wrapper for the pb_fence_ops api.
360e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
361e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * wrapper around vmw_fence_signalled.
362e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
3633192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzstatic int
3643192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzvmw_fence_ops_fence_signalled(struct pb_fence_ops *ops,
3653192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                              struct pipe_fence_handle *fence,
3663192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                              unsigned flag)
3673192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
3683192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
369e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
370e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   return vmw_fence_signalled(vws, fence, flag);
3713192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
3723192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
3733192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
374e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
375e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence_ops_fence_finish - wrapper for the pb_fence_ops api.
376e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
377e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * wrapper around vmw_fence_finish.
378e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
3793192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzstatic int
3803192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzvmw_fence_ops_fence_finish(struct pb_fence_ops *ops,
3813192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                           struct pipe_fence_handle *fence,
3823192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                           unsigned flag)
3833192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
3843192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
385e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom
386e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom   return vmw_fence_finish(vws, fence, flag);
3873192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
3883192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
3893192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
390e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
391e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence_ops_destroy - Destroy a pb_fence_ops function table.
392e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
393e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @ops: The function table to destroy.
394e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
395e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * Part of the pb_fence_ops api.
396e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
3973192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzstatic void
3983192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzvmw_fence_ops_destroy(struct pb_fence_ops *ops)
3993192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
400fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   vmw_fences_release(vmw_fence_ops(ops));
4013192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   FREE(ops);
4023192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
4033192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
4043192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
405e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom/**
406e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * vmw_fence_ops_create - Create a pb_fence_ops function table.
407e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
408e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * @vws: Pointer to a struct vmw_winsys_screen.
409e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
410e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * Returns a pointer to a pb_fence_ops function table to interface
411e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * with pipe_buffer. This function is typically called on driver setup.
412e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom *
413e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom * Returns NULL on failure.
414e7843273fae516fa9922f12053bb6c063b39921cThomas Hellstrom */
4153192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzstruct pb_fence_ops *
4163192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzvmw_fence_ops_create(struct vmw_winsys_screen *vws)
4173192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
4183192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct vmw_fence_ops *ops;
4193192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
4203192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   ops = CALLOC_STRUCT(vmw_fence_ops);
4213192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   if(!ops)
4223192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      return NULL;
4233192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
424fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   pipe_mutex_init(ops->mutex);
425fe6a854477c2ed30c37c200668a4dc86512120f7Brian Paul   LIST_INITHEAD(&ops->not_signaled);
4263192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   ops->base.destroy = &vmw_fence_ops_destroy;
4273192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   ops->base.fence_reference = &vmw_fence_ops_fence_reference;
4283192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   ops->base.fence_signalled = &vmw_fence_ops_fence_signalled;
4293192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   ops->base.fence_finish = &vmw_fence_ops_fence_finish;
4303192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
4313192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   ops->vws = vws;
4323192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
4333192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   return &ops->base;
4343192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
435