Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4358 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 
59
#include "glheader.h"
60
#include "imports.h"
61
#include "context.h"
62
#include "macros.h"
63
#include "get.h"
64
#include "dispatch.h"
65
#include "mtypes.h"
66
#include "set.h"
67
#include "hash_table.h"
68
 
69
#include "syncobj.h"
70
 
71
static struct gl_sync_object *
72
_mesa_new_sync_object(struct gl_context *ctx, GLenum type)
73
{
74
   struct gl_sync_object *s = MALLOC_STRUCT(gl_sync_object);
75
   (void) ctx;
76
   (void) type;
77
 
78
   return s;
79
}
80
 
81
 
82
static void
83
_mesa_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
84
{
85
   (void) ctx;
86
   free(syncObj);
87
}
88
 
89
 
90
static void
91
_mesa_fence_sync(struct gl_context *ctx, struct gl_sync_object *syncObj,
92
		 GLenum condition, GLbitfield flags)
93
{
94
   (void) ctx;
95
   (void) condition;
96
   (void) flags;
97
 
98
   syncObj->StatusFlag = 1;
99
}
100
 
101
 
102
static void
103
_mesa_check_sync(struct gl_context *ctx, struct gl_sync_object *syncObj)
104
{
105
   (void) ctx;
106
   (void) syncObj;
107
 
108
   /* No-op for software rendering.  Hardware drivers will need to determine
109
    * whether the state of the sync object has changed.
110
    */
111
}
112
 
113
 
114
static void
115
_mesa_wait_sync(struct gl_context *ctx, struct gl_sync_object *syncObj,
116
		GLbitfield flags, GLuint64 timeout)
117
{
118
   (void) ctx;
119
   (void) syncObj;
120
   (void) flags;
121
   (void) timeout;
122
 
123
   /* No-op for software rendering.  Hardware drivers will need to wait until
124
    * the state of the sync object changes or the timeout expires.
125
    */
126
}
127
 
128
 
129
void
130
_mesa_init_sync_object_functions(struct dd_function_table *driver)
131
{
132
   driver->NewSyncObject = _mesa_new_sync_object;
133
   driver->FenceSync = _mesa_fence_sync;
134
   driver->DeleteSyncObject = _mesa_delete_sync_object;
135
   driver->CheckSync = _mesa_check_sync;
136
 
137
   /* Use the same no-op wait function for both.
138
    */
139
   driver->ClientWaitSync = _mesa_wait_sync;
140
   driver->ServerWaitSync = _mesa_wait_sync;
141
}
142
 
143
/**
144
 * Allocate/init the context state related to sync objects.
145
 */
146
void
147
_mesa_init_sync(struct gl_context *ctx)
148
{
149
   (void) ctx;
150
}
151
 
152
 
153
/**
154
 * Free the context state related to sync objects.
155
 */
156
void
157
_mesa_free_sync_data(struct gl_context *ctx)
158
{
159
   (void) ctx;
160
}
161
 
162
 
163
static int
164
_mesa_validate_sync(struct gl_context *ctx, struct gl_sync_object *syncObj)
165
{
166
   return (syncObj != NULL)
167
      && _mesa_set_search(ctx->Shared->SyncObjects,
168
                          _mesa_hash_pointer(syncObj),
169
                          syncObj) != NULL
170
      && (syncObj->Type == GL_SYNC_FENCE)
171
      && !syncObj->DeletePending;
172
}
173
 
174
 
175
void
176
_mesa_ref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
177
{
178
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
179
   syncObj->RefCount++;
180
   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
181
}
182
 
183
 
184
void
185
_mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
186
{
187
   struct set_entry *entry;
188
 
189
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
190
   syncObj->RefCount--;
191
   if (syncObj->RefCount == 0) {
192
      entry = _mesa_set_search(ctx->Shared->SyncObjects,
193
                               _mesa_hash_pointer(syncObj),
194
                               syncObj);
195
      assert (entry != NULL);
196
      _mesa_set_remove(ctx->Shared->SyncObjects, entry);
197
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
198
 
199
      ctx->Driver.DeleteSyncObject(ctx, syncObj);
200
   } else {
201
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
202
   }
203
}
204
 
205
 
206
GLboolean GLAPIENTRY
207
_mesa_IsSync(GLsync sync)
208
{
209
   GET_CURRENT_CONTEXT(ctx);
210
   struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
211
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
212
 
213
   return _mesa_validate_sync(ctx, syncObj) ? GL_TRUE : GL_FALSE;
214
}
215
 
216
 
217
void GLAPIENTRY
218
_mesa_DeleteSync(GLsync sync)
219
{
220
   GET_CURRENT_CONTEXT(ctx);
221
   struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
222
 
223
   /* From the GL_ARB_sync spec:
224
    *
225
    *    DeleteSync will silently ignore a  value of zero. An
226
    *    INVALID_VALUE error is generated if  is neither zero nor the
227
    *    name of a sync object.
228
    */
229
   if (sync == 0) {
230
      return;
231
   }
232
 
233
   if (!_mesa_validate_sync(ctx, syncObj)) {
234
      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSync (not a valid sync object)");
235
      return;
236
   }
237
 
238
   /* If there are no client-waits or server-waits pending on this sync, delete
239
    * the underlying object.
240
    */
241
   syncObj->DeletePending = GL_TRUE;
242
   _mesa_unref_sync_object(ctx, syncObj);
243
}
244
 
245
 
246
GLsync GLAPIENTRY
247
_mesa_FenceSync(GLenum condition, GLbitfield flags)
248
{
249
   GET_CURRENT_CONTEXT(ctx);
250
   struct gl_sync_object *syncObj;
251
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
252
 
253
   if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) {
254
      _mesa_error(ctx, GL_INVALID_ENUM, "glFenceSync(condition=0x%x)",
255
		  condition);
256
      return 0;
257
   }
258
 
259
   if (flags != 0) {
260
      _mesa_error(ctx, GL_INVALID_VALUE, "glFenceSync(flags=0x%x)",
261
		  condition);
262
      return 0;
263
   }
264
 
265
   syncObj = ctx->Driver.NewSyncObject(ctx, GL_SYNC_FENCE);
266
   if (syncObj != NULL) {
267
      syncObj->Type = GL_SYNC_FENCE;
268
      /* The name is not currently used, and it is never visible to
269
       * applications.  If sync support is extended to provide support for
270
       * NV_fence, this field will be used.  We'll also need to add an object
271
       * ID hashtable.
272
       */
273
      syncObj->Name = 1;
274
      syncObj->RefCount = 1;
275
      syncObj->DeletePending = GL_FALSE;
276
      syncObj->SyncCondition = condition;
277
      syncObj->Flags = flags;
278
      syncObj->StatusFlag = 0;
279
 
280
      ctx->Driver.FenceSync(ctx, syncObj, condition, flags);
281
 
282
      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
283
      _mesa_set_add(ctx->Shared->SyncObjects,
284
                    _mesa_hash_pointer(syncObj),
285
                    syncObj);
286
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
287
 
288
      return (GLsync) syncObj;
289
   }
290
 
291
   return NULL;
292
}
293
 
294
 
295
GLenum GLAPIENTRY
296
_mesa_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
297
{
298
   GET_CURRENT_CONTEXT(ctx);
299
   struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
300
   GLenum ret;
301
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_WAIT_FAILED);
302
 
303
   if (!_mesa_validate_sync(ctx, syncObj)) {
304
      _mesa_error(ctx, GL_INVALID_VALUE, "glClientWaitSync (not a valid sync object)");
305
      return GL_WAIT_FAILED;
306
   }
307
 
308
   if ((flags & ~GL_SYNC_FLUSH_COMMANDS_BIT) != 0) {
309
      _mesa_error(ctx, GL_INVALID_VALUE, "glClientWaitSync(flags=0x%x)", flags);
310
      return GL_WAIT_FAILED;
311
   }
312
 
313
   _mesa_ref_sync_object(ctx, syncObj);
314
 
315
   /* From the GL_ARB_sync spec:
316
    *
317
    *    ClientWaitSync returns one of four status values. A return value of
318
    *    ALREADY_SIGNALED indicates that  was signaled at the time
319
    *    ClientWaitSync was called. ALREADY_SIGNALED will always be returned
320
    *    if  was signaled, even if the value of  is zero.
321
    */
322
   ctx->Driver.CheckSync(ctx, syncObj);
323
   if (syncObj->StatusFlag) {
324
      ret = GL_ALREADY_SIGNALED;
325
   } else {
326
      if (timeout == 0) {
327
         ret = GL_TIMEOUT_EXPIRED;
328
      } else {
329
         ctx->Driver.ClientWaitSync(ctx, syncObj, flags, timeout);
330
 
331
         ret = syncObj->StatusFlag ? GL_CONDITION_SATISFIED : GL_TIMEOUT_EXPIRED;
332
      }
333
   }
334
 
335
   _mesa_unref_sync_object(ctx, syncObj);
336
   return ret;
337
}
338
 
339
 
340
void GLAPIENTRY
341
_mesa_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
342
{
343
   GET_CURRENT_CONTEXT(ctx);
344
   struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
345
 
346
   if (!_mesa_validate_sync(ctx, syncObj)) {
347
      _mesa_error(ctx, GL_INVALID_VALUE, "glWaitSync (not a valid sync object)");
348
      return;
349
   }
350
 
351
   if (flags != 0) {
352
      _mesa_error(ctx, GL_INVALID_VALUE, "glWaitSync(flags=0x%x)", flags);
353
      return;
354
   }
355
 
356
   if (timeout != GL_TIMEOUT_IGNORED) {
357
      _mesa_error(ctx, GL_INVALID_VALUE, "glWaitSync(timeout=0x%" PRIx64 ")",
358
                  (uint64_t) timeout);
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
 
375
   if (!_mesa_validate_sync(ctx, syncObj)) {
376
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetSynciv (not a valid sync object)");
377
      return;
378
   }
379
 
380
   switch (pname) {
381
   case GL_OBJECT_TYPE:
382
      v[0] = syncObj->Type;
383
      size = 1;
384
      break;
385
 
386
   case GL_SYNC_CONDITION:
387
      v[0] = syncObj->SyncCondition;
388
      size = 1;
389
      break;
390
 
391
   case GL_SYNC_STATUS:
392
      /* Update the state of the sync by dipping into the driver.  Note that
393
       * this call won't block.  It just updates state in the common object
394
       * data from the current driver state.
395
       */
396
      ctx->Driver.CheckSync(ctx, syncObj);
397
 
398
      v[0] = (syncObj->StatusFlag) ? GL_SIGNALED : GL_UNSIGNALED;
399
      size = 1;
400
      break;
401
 
402
   case GL_SYNC_FLAGS:
403
      v[0] = syncObj->Flags;
404
      size = 1;
405
      break;
406
 
407
   default:
408
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetSynciv(pname=0x%x)\n", pname);
409
      return;
410
   }
411
 
412
   if (size > 0 && bufSize > 0) {
413
      const GLsizei copy_count = MIN2(size, bufSize);
414
 
415
      memcpy(values, v, sizeof(GLint) * copy_count);
416
   }
417
 
418
   if (length != NULL) {
419
      *length = size;
420
   }
421
}