Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Copyright © 2009 Intel Corporation
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
21
 * DEALINGS IN THE SOFTWARE.
22
 */
23
 
24
/**
25
 * \file syncobj.c
26
 * Sync object management.
27
 *
28
 * Unlike textures and other objects that are shared between contexts, sync
29
 * objects are not bound to the context.  As a result, the reference counting
30
 * and delete behavior of sync objects is slightly different.  References to
31
 * sync objects are added:
32
 *
33
 *    - By \c glFencSynce.  This sets the initial reference count to 1.
34
 *    - At the start of \c glClientWaitSync.  The reference is held for the
35
 *      duration of the wait call.
36
 *
37
 * References are removed:
38
 *
39
 *    - By \c glDeleteSync.
40
 *    - At the end of \c glClientWaitSync.
41
 *
42
 * Additionally, drivers may call \c _mesa_ref_sync_object and
43
 * \c _mesa_unref_sync_object as needed to implement \c ServerWaitSync.
44
 *
45
 * As with shader objects, sync object names become invalid as soon as
46
 * \c glDeleteSync is called.  For this reason \c glDeleteSync sets the
47
 * \c DeletePending flag.  All functions validate object handles by testing
48
 * this flag.
49
 *
50
 * \note
51
 * Only \c GL_ARB_sync objects are shared between contexts.  If support is ever
52
 * added for either \c GL_NV_fence or \c GL_APPLE_fence different semantics
53
 * will need to be implemented.
54
 *
55
 * \author Ian Romanick 
56
 */
57
 
58
#include "glheader.h"
59
#include "imports.h"
60
#include "context.h"
61
#include "macros.h"
62
#include "get.h"
63
#include "dispatch.h"
64
 
65
#if FEATURE_ARB_sync
66
#include "syncobj.h"
67
 
68
static struct gl_sync_object *
69
_mesa_new_sync_object(struct gl_context *ctx, GLenum type)
70
{
71
   struct gl_sync_object *s = MALLOC_STRUCT(gl_sync_object);
72
   (void) ctx;
73
   (void) type;
74
 
75
   return s;
76
}
77
 
78
 
79
static void
80
_mesa_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
81
{
82
   (void) ctx;
83
   free(syncObj);
84
}
85
 
86
 
87
static void
88
_mesa_fence_sync(struct gl_context *ctx, struct gl_sync_object *syncObj,
89
		 GLenum condition, GLbitfield flags)
90
{
91
   (void) ctx;
92
   (void) condition;
93
   (void) flags;
94
 
95
   syncObj->StatusFlag = 1;
96
}
97
 
98
 
99
static void
100
_mesa_check_sync(struct gl_context *ctx, struct gl_sync_object *syncObj)
101
{
102
   (void) ctx;
103
   (void) syncObj;
104
 
105
   /* No-op for software rendering.  Hardware drivers will need to determine
106
    * whether the state of the sync object has changed.
107
    */
108
}
109
 
110
 
111
static void
112
_mesa_wait_sync(struct gl_context *ctx, struct gl_sync_object *syncObj,
113
		GLbitfield flags, GLuint64 timeout)
114
{
115
   (void) ctx;
116
   (void) syncObj;
117
   (void) flags;
118
   (void) timeout;
119
 
120
   /* No-op for software rendering.  Hardware drivers will need to wait until
121
    * the state of the sync object changes or the timeout expires.
122
    */
123
}
124
 
125
 
126
void
127
_mesa_init_sync_object_functions(struct dd_function_table *driver)
128
{
129
   driver->NewSyncObject = _mesa_new_sync_object;
130
   driver->FenceSync = _mesa_fence_sync;
131
   driver->DeleteSyncObject = _mesa_delete_sync_object;
132
   driver->CheckSync = _mesa_check_sync;
133
 
134
   /* Use the same no-op wait function for both.
135
    */
136
   driver->ClientWaitSync = _mesa_wait_sync;
137
   driver->ServerWaitSync = _mesa_wait_sync;
138
}
139
 
140
 
141
void
142
_mesa_init_sync_dispatch(struct _glapi_table *disp)
143
{
144
   SET_IsSync(disp, _mesa_IsSync);
145
   SET_DeleteSync(disp, _mesa_DeleteSync);
146
   SET_FenceSync(disp, _mesa_FenceSync);
147
   SET_ClientWaitSync(disp, _mesa_ClientWaitSync);
148
   SET_WaitSync(disp, _mesa_WaitSync);
149
   SET_GetInteger64v(disp, _mesa_GetInteger64v);
150
   SET_GetSynciv(disp, _mesa_GetSynciv);
151
}
152
 
153
 
154
/**
155
 * Allocate/init the context state related to sync objects.
156
 */
157
void
158
_mesa_init_sync(struct gl_context *ctx)
159
{
160
   (void) ctx;
161
}
162
 
163
 
164
/**
165
 * Free the context state related to sync objects.
166
 */
167
void
168
_mesa_free_sync_data(struct gl_context *ctx)
169
{
170
   (void) ctx;
171
}
172
 
173
 
174
static int
175
_mesa_validate_sync(struct gl_sync_object *syncObj)
176
{
177
   return (syncObj != NULL)
178
      && (syncObj->Type == GL_SYNC_FENCE)
179
      && !syncObj->DeletePending;
180
}
181
 
182
 
183
void
184
_mesa_ref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
185
{
186
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
187
   syncObj->RefCount++;
188
   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
189
}
190
 
191
 
192
void
193
_mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
194
{
195
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
196
   syncObj->RefCount--;
197
   if (syncObj->RefCount == 0) {
198
      remove_from_list(& syncObj->link);
199
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
200
 
201
      ctx->Driver.DeleteSyncObject(ctx, syncObj);
202
   } else {
203
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
204
   }
205
}
206
 
207
 
208
GLboolean GLAPIENTRY
209
_mesa_IsSync(GLsync sync)
210
{
211
   GET_CURRENT_CONTEXT(ctx);
212
   struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
213
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
214
 
215
   return _mesa_validate_sync(syncObj) ? GL_TRUE : GL_FALSE;
216
}
217
 
218
 
219
void GLAPIENTRY
220
_mesa_DeleteSync(GLsync sync)
221
{
222
   GET_CURRENT_CONTEXT(ctx);
223
   struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
224
   ASSERT_OUTSIDE_BEGIN_END(ctx);
225
 
226
   /* From the GL_ARB_sync spec:
227
    *
228
    *    DeleteSync will silently ignore a  value of zero. An
229
    *    INVALID_VALUE error is generated if  is neither zero nor the
230
    *    name of a sync object.
231
    */
232
   if (sync == 0) {
233
      return;
234
   }
235
 
236
   if (!_mesa_validate_sync(syncObj)) {
237
      _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteSync");
238
      return;
239
   }
240
 
241
   /* If there are no client-waits or server-waits pending on this sync, delete
242
    * the underlying object.
243
    */
244
   syncObj->DeletePending = GL_TRUE;
245
   _mesa_unref_sync_object(ctx, syncObj);
246
}
247
 
248
 
249
GLsync GLAPIENTRY
250
_mesa_FenceSync(GLenum condition, GLbitfield flags)
251
{
252
   GET_CURRENT_CONTEXT(ctx);
253
   struct gl_sync_object *syncObj;
254
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
255
 
256
   if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) {
257
      _mesa_error(ctx, GL_INVALID_ENUM, "glFenceSync(condition=0x%x)",
258
		  condition);
259
      return 0;
260
   }
261
 
262
   if (flags != 0) {
263
      _mesa_error(ctx, GL_INVALID_VALUE, "glFenceSync(flags=0x%x)",
264
		  condition);
265
      return 0;
266
   }
267
 
268
   syncObj = ctx->Driver.NewSyncObject(ctx, GL_SYNC_FENCE);
269
   if (syncObj != NULL) {
270
      syncObj->Type = GL_SYNC_FENCE;
271
      /* The name is not currently used, and it is never visible to
272
       * applications.  If sync support is extended to provide support for
273
       * NV_fence, this field will be used.  We'll also need to add an object
274
       * ID hashtable.
275
       */
276
      syncObj->Name = 1;
277
      syncObj->RefCount = 1;
278
      syncObj->DeletePending = GL_FALSE;
279
      syncObj->SyncCondition = condition;
280
      syncObj->Flags = flags;
281
      syncObj->StatusFlag = 0;
282
 
283
      ctx->Driver.FenceSync(ctx, syncObj, condition, flags);
284
 
285
      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
286
      insert_at_tail(& ctx->Shared->SyncObjects, & syncObj->link);
287
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
288
 
289
      return (GLsync) syncObj;
290
   }
291
 
292
   return NULL;
293
}
294
 
295
 
296
GLenum GLAPIENTRY
297
_mesa_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
298
{
299
   GET_CURRENT_CONTEXT(ctx);
300
   struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
301
   GLenum ret;
302
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_WAIT_FAILED);
303
 
304
   if (!_mesa_validate_sync(syncObj)) {
305
      _mesa_error(ctx, GL_INVALID_OPERATION, "glClientWaitSync");
306
      return GL_WAIT_FAILED;
307
   }
308
 
309
   if ((flags & ~GL_SYNC_FLUSH_COMMANDS_BIT) != 0) {
310
      _mesa_error(ctx, GL_INVALID_ENUM, "glClientWaitSync(flags=0x%x)", flags);
311
      return GL_WAIT_FAILED;
312
   }
313
 
314
   _mesa_ref_sync_object(ctx, syncObj);
315
 
316
   /* From the GL_ARB_sync spec:
317
    *
318
    *    ClientWaitSync returns one of four status values. A return value of
319
    *    ALREADY_SIGNALED indicates that  was signaled at the time
320
    *    ClientWaitSync was called. ALREADY_SIGNALED will always be returned
321
    *    if  was signaled, even if the value of  is zero.
322
    */
323
   ctx->Driver.CheckSync(ctx, syncObj);
324
   if (syncObj->StatusFlag) {
325
      ret = GL_ALREADY_SIGNALED;
326
   } else {
327
      ctx->Driver.ClientWaitSync(ctx, syncObj, flags, timeout);
328
 
329
      ret = syncObj->StatusFlag ? GL_CONDITION_SATISFIED : GL_TIMEOUT_EXPIRED;
330
   }
331
 
332
   _mesa_unref_sync_object(ctx, syncObj);
333
   return ret;
334
}
335
 
336
 
337
void GLAPIENTRY
338
_mesa_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
339
{
340
   GET_CURRENT_CONTEXT(ctx);
341
   struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
342
   ASSERT_OUTSIDE_BEGIN_END(ctx);
343
 
344
   if (!_mesa_validate_sync(syncObj)) {
345
      _mesa_error(ctx, GL_INVALID_OPERATION, "glWaitSync");
346
      return;
347
   }
348
 
349
   if (flags != 0) {
350
      _mesa_error(ctx, GL_INVALID_ENUM, "glWaitSync(flags=0x%x)", flags);
351
      return;
352
   }
353
 
354
   /* From the GL_ARB_sync spec:
355
    *
356
    *     If the value of  is zero, then WaitSync does nothing.
357
    */
358
   if (timeout == 0) {
359
      return;
360
   }
361
 
362
   ctx->Driver.ServerWaitSync(ctx, syncObj, flags, timeout);
363
}
364
 
365
 
366
void GLAPIENTRY
367
_mesa_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length,
368
		GLint *values)
369
{
370
   GET_CURRENT_CONTEXT(ctx);
371
   struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
372
   GLsizei size = 0;
373
   GLint v[1];
374
   ASSERT_OUTSIDE_BEGIN_END(ctx);
375
 
376
   if (!_mesa_validate_sync(syncObj)) {
377
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetSynciv");
378
      return;
379
   }
380
 
381
   switch (pname) {
382
   case GL_OBJECT_TYPE:
383
      v[0] = syncObj->Type;
384
      size = 1;
385
      break;
386
 
387
   case GL_SYNC_CONDITION:
388
      v[0] = syncObj->SyncCondition;
389
      size = 1;
390
      break;
391
 
392
   case GL_SYNC_STATUS:
393
      /* Update the state of the sync by dipping into the driver.  Note that
394
       * this call won't block.  It just updates state in the common object
395
       * data from the current driver state.
396
       */
397
      ctx->Driver.CheckSync(ctx, syncObj);
398
 
399
      v[0] = (syncObj->StatusFlag) ? GL_SIGNALED : GL_UNSIGNALED;
400
      size = 1;
401
      break;
402
 
403
   case GL_SYNC_FLAGS:
404
      v[0] = syncObj->Flags;
405
      size = 1;
406
      break;
407
 
408
   default:
409
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetSynciv(pname=0x%x)\n", pname);
410
      return;
411
   }
412
 
413
   if (size > 0) {
414
      const GLsizei copy_count = MIN2(size, bufSize);
415
 
416
      memcpy(values, v, sizeof(GLint) * copy_count);
417
   }
418
 
419
   if (length != NULL) {
420
      *length = size;
421
   }
422
}
423
 
424
#endif /* FEATURE_ARB_sync */