1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**********************************************************
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2009-2011 VMware, Inc.  All rights reserved.
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * obtaining a copy of this software and associated documentation
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * files (the "Software"), to deal in the Software without
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * restriction, including without limitation the rights to use, copy,
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * modify, merge, publish, distribute, sublicense, and/or sell copies
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the Software, and to permit persons to whom the Software is
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * furnished to do so, subject to the following conditions:
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice shall be
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * included in all copies or substantial portions of the Software.
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * SOFTWARE.
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org **********************************************************/
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * TODO:
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Fencing is currently a bit inefficient, since we need to call the
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * kernel do determine a fence object signaled status if the fence is not
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * signaled. This can be greatly improved upon by using the fact that the
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * execbuf ioctl returns the last signaled fence seqno, as does the
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * fence signaled ioctl. We should set up a ring of fence objects and
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * walk through them checking for signaled status each time we receive a
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * new passed fence seqno.
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_memory.h"
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_atomic.h"
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipebuffer/pb_buffer_fenced.h"
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "vmw_screen.h"
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "vmw_fence.h"
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct vmw_fence_ops
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct pb_fence_ops base;
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vmw_winsys_screen *vws;
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct vmw_fence
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int32_t refcount;
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   uint32_t handle;
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   uint32_t mask;
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int32_t signalled;
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence - return the vmw_fence object identified by a
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * struct pipe_fence_handle *
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @fence: The opaque pipe fence handle.
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE struct vmw_fence *
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence(struct pipe_fence_handle *fence)
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return (struct vmw_fence *) fence;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_create - Create a user-space fence object.
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @handle: Handle identifying the kernel fence object.
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @mask: Mask of flags that this fence object may signal.
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Returns NULL on failure.
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct pipe_fence_handle *
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_create(uint32_t handle, uint32_t mask)
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vmw_fence *fence = CALLOC_STRUCT(vmw_fence);
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!fence)
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p_atomic_set(&fence->refcount, 1);
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   fence->handle = handle;
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   fence->mask = mask;
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p_atomic_set(&fence->signalled, 0);
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return (struct pipe_fence_handle *) fence;
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_ops - Return the vmw_fence_ops structure backing a
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * struct pb_fence_ops pointer.
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @ops: Pointer to a struct pb_fence_ops.
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE struct vmw_fence_ops *
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_ops(struct pb_fence_ops *ops)
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(ops);
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return (struct vmw_fence_ops *)ops;
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_reference - Reference / unreference a vmw fence object.
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @vws: Pointer to the winsys screen.
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @ptr: Pointer to reference transfer destination.
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @fence: Pointer to object to reference. May be NULL.
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_reference(struct vmw_winsys_screen *vws,
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    struct pipe_fence_handle **ptr,
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    struct pipe_fence_handle *fence)
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (*ptr) {
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct vmw_fence *vfence = vmw_fence(*ptr);
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (p_atomic_dec_zero(&vfence->refcount)) {
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 vmw_ioctl_fence_unref(vws, vfence->handle);
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 FREE(vfence);
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (fence) {
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct vmw_fence *vfence = vmw_fence(fence);
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p_atomic_inc(&vfence->refcount);
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   *ptr = fence;
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_signalled - Check whether a fence object is signalled.
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @vws: Pointer to the winsys screen.
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @fence: Handle to the fence object.
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @flag: Fence flags to check. If the fence object can't signal
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * a flag, it is assumed to be already signaled.
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Returns 0 if the fence object was signaled, nonzero otherwise.
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_signalled(struct vmw_winsys_screen *vws,
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   struct pipe_fence_handle *fence,
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   unsigned flag)
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vmw_fence *vfence;
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int32_t vflags = SVGA_FENCE_FLAG_EXEC;
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int ret;
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   uint32_t old;
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!fence)
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vfence = vmw_fence(fence);
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   old = p_atomic_read(&vfence->signalled);
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vflags &= ~vfence->mask;
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if ((old & vflags) == vflags)
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ret = vmw_ioctl_fence_signalled(vws, vfence->handle, vflags);
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ret == 0) {
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      int32_t prev = old;
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      do {
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 old = prev;
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 prev = p_atomic_cmpxchg(&vfence->signalled, old, old | vflags);
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } while (prev != old);
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return ret;
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_finish - Wait for a fence object to signal.
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @vws: Pointer to the winsys screen.
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @fence: Handle to the fence object.
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @flag: Fence flags to wait for. If the fence object can't signal
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * a flag, it is assumed to be already signaled.
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Returns 0 if the wait succeeded. Nonzero otherwise.
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_finish(struct vmw_winsys_screen *vws,
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 struct pipe_fence_handle *fence,
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 unsigned flag)
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vmw_fence *vfence;
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int32_t vflags = SVGA_FENCE_FLAG_EXEC;
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int ret;
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   uint32_t old;
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!fence)
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vfence = vmw_fence(fence);
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   old = p_atomic_read(&vfence->signalled);
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vflags &= ~vfence->mask;
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if ((old & vflags) == vflags)
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return 0;
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ret = vmw_ioctl_fence_finish(vws, vfence->handle, vflags);
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ret == 0) {
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      int32_t prev = old;
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      do {
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 old = prev;
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 prev = p_atomic_cmpxchg(&vfence->signalled, old, old | vflags);
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } while (prev != old);
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return ret;
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_ops_fence_reference - wrapper for the pb_fence_ops api.
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * wrapper around vmw_fence_reference.
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_ops_fence_reference(struct pb_fence_ops *ops,
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              struct pipe_fence_handle **ptr,
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              struct pipe_fence_handle *fence)
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vmw_fence_reference(vws, ptr, fence);
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_ops_fence_signalled - wrapper for the pb_fence_ops api.
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * wrapper around vmw_fence_signalled.
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_ops_fence_signalled(struct pb_fence_ops *ops,
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              struct pipe_fence_handle *fence,
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              unsigned flag)
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return vmw_fence_signalled(vws, fence, flag);
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_ops_fence_finish - wrapper for the pb_fence_ops api.
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * wrapper around vmw_fence_finish.
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_ops_fence_finish(struct pb_fence_ops *ops,
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           struct pipe_fence_handle *fence,
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           unsigned flag)
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return vmw_fence_finish(vws, fence, flag);
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_ops_destroy - Destroy a pb_fence_ops function table.
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @ops: The function table to destroy.
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Part of the pb_fence_ops api.
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_ops_destroy(struct pb_fence_ops *ops)
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE(ops);
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * vmw_fence_ops_create - Create a pb_fence_ops function table.
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @vws: Pointer to a struct vmw_winsys_screen.
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Returns a pointer to a pb_fence_ops function table to interface
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * with pipe_buffer. This function is typically called on driver setup.
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Returns NULL on failure.
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct pb_fence_ops *
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvmw_fence_ops_create(struct vmw_winsys_screen *vws)
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vmw_fence_ops *ops;
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ops = CALLOC_STRUCT(vmw_fence_ops);
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(!ops)
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ops->base.destroy = &vmw_fence_ops_destroy;
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ops->base.fence_reference = &vmw_fence_ops_fence_reference;
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ops->base.fence_signalled = &vmw_fence_ops_fence_signalled;
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ops->base.fence_finish = &vmw_fence_ops_fence_finish;
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ops->vws = vws;
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return &ops->base;
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
324