Пример #1
0
/**
 * Determine if ID is the name of a buffer object.
 * 
 * \param id  ID of the potential buffer object.
 * \return  \c GL_TRUE if \c id is the name of a buffer object, 
 *          \c GL_FALSE otherwise.
 */
GLboolean GLAPIENTRY
_mesa_IsBufferARB(GLuint id)
{
   struct gl_buffer_object *bufObj;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);

   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
   bufObj = _mesa_lookup_bufferobj(ctx, id);
   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);

   return bufObj ? GL_TRUE : GL_FALSE;
}
/**
 * Returns an error code specified by GL_ARB_robustness, or GL_NO_ERROR.
 * \return current context status
 */
GLenum GLAPIENTRY
_mesa_GetGraphicsResetStatusARB( void )
{
   GET_CURRENT_CONTEXT(ctx);
   GLenum status = GL_NO_ERROR;

   /* The ARB_robustness specification says:
    *
    *     "If the reset notification behavior is NO_RESET_NOTIFICATION_ARB,
    *     then the implementation will never deliver notification of reset
    *     events, and GetGraphicsResetStatusARB will always return NO_ERROR."
    */
   if (ctx->Const.ResetStrategy == GL_NO_RESET_NOTIFICATION_ARB) {
      if (MESA_VERBOSE & VERBOSE_API)
         _mesa_debug(ctx,
                     "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
                     "because reset notifictation was not requested at context "
                     "creation.\n");

      return GL_NO_ERROR;
   }

   if (ctx->Driver.GetGraphicsResetStatus) {
      /* Query the reset status of this context from the driver core.
       */
      status = ctx->Driver.GetGraphicsResetStatus(ctx);

      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);

      /* If this context has not been affected by a GPU reset, check to see if
       * some other context in the share group has been affected by a reset.
       * If another context saw a reset but this context did not, assume that
       * this context was not guilty.
       */
      if (status != GL_NO_ERROR) {
         ctx->Shared->ShareGroupReset = true;
      } else if (ctx->Shared->ShareGroupReset && !ctx->ShareGroupReset) {
         status = GL_INNOCENT_CONTEXT_RESET_ARB;
      }

      ctx->ShareGroupReset = ctx->Shared->ShareGroupReset;
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
   }

   if (!ctx->Driver.GetGraphicsResetStatus && (MESA_VERBOSE & VERBOSE_API))
      _mesa_debug(ctx,
                  "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
                  "because the driver doesn't track reset status.\n");

   return status;
}
Пример #3
0
void
_mesa_unref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj)
{
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
   syncObj->RefCount--;
   if (syncObj->RefCount == 0) {
      remove_from_list(& syncObj->link);
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);

      ctx->Driver.DeleteSyncObject(ctx, syncObj);
   } else {
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
   }
}
Пример #4
0
Файл: hash.c Проект: aosm/X11
/**
 * Get the key of the "first" entry in the hash table.
 * This is used in the course of deleting all display lists when
 * a context is destroyed.
 * \param table - the hash table
 * \return key for the "first" entry in the hash table.
 */
GLuint _mesa_HashFirstEntry(struct _mesa_HashTable *table)
{
   GLuint pos;
   assert(table);
   _glthread_LOCK_MUTEX(table->Mutex);
   for (pos=0; pos < TABLE_SIZE; pos++) {
      if (table->Table[pos]) {
         _glthread_UNLOCK_MUTEX(table->Mutex);
         return table->Table[pos]->Key;
      }
   }
   _glthread_UNLOCK_MUTEX(table->Mutex);
   return 0;
}
Пример #5
0
static void
finish_or_flush( GLcontext *ctx )
{
#ifdef XFree86Server
      /* NOT_NEEDED */
#else
   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
   if (xmesa) {
      _glthread_LOCK_MUTEX(_xmesa_lock);
      XSync( xmesa->display, False );
      _glthread_UNLOCK_MUTEX(_xmesa_lock);
   }
#endif
}
Пример #6
0
void
_mesa_exec_free(void *addr)
{
    _glthread_LOCK_MUTEX(exec_mutex);

    if (exec_heap) {
        struct mem_block *block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem);

        if (block)
            mmFreeMem(block);
    }

    _glthread_UNLOCK_MUTEX(exec_mutex);
}
Пример #7
0
/**
 * Add the given texture object to the texture object pool.
 */
void
_mesa_save_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
{
   /* insert into linked list */
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
   texObj->Next = ctx->Shared->TexObjectList;
   ctx->Shared->TexObjectList = texObj;
   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);

   if (texObj->Name > 0) {
      /* insert into hash table */
      _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
   }
}
Пример #8
0
/**
 * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
 * dereference that buffer first.  The new renderbuffer's refcount will
 * be incremented.  The old renderbuffer's refcount will be decremented.
 * This is normally only called from the _mesa_reference_renderbuffer() macro
 * when there's a real pointer change.
 */
void
_mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr,
                              struct gl_renderbuffer *rb)
{
   if (*ptr) {
      /* Unreference the old renderbuffer */
      GLboolean deleteFlag = GL_FALSE;
      struct gl_renderbuffer *oldRb = *ptr;

      _glthread_LOCK_MUTEX(oldRb->Mutex);
      ASSERT(oldRb->RefCount > 0);
      oldRb->RefCount--;
      /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
      deleteFlag = (oldRb->RefCount == 0);
      _glthread_UNLOCK_MUTEX(oldRb->Mutex);

      if (deleteFlag) {
         GET_CURRENT_CONTEXT(ctx);
         if (ctx)
            oldRb->Delete(ctx, oldRb);
         else
            _mesa_problem(NULL, "Unable to delete renderbuffer, no context");
      }

      *ptr = NULL;
   }
   assert(!*ptr);

   if (rb) {
      /* reference new renderbuffer */
      _glthread_LOCK_MUTEX(rb->Mutex);
      rb->RefCount++;
      /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
      _glthread_UNLOCK_MUTEX(rb->Mutex);
      *ptr = rb;
   }
}
Пример #9
0
/**
 * Delete named textures.
 *
 * \param n number of textures to be deleted.
 * \param textures array of texture IDs to be deleted.
 *
 * \sa glDeleteTextures().
 *
 * If we're about to delete a texture that's currently bound to any
 * texture unit, unbind the texture first.  Decrement the reference
 * count on the texture object and delete it if it's zero.
 * Recall that texture objects can be shared among several rendering
 * contexts.
 */
void GLAPIENTRY
_mesa_DeleteTextures( GLsizei n, const GLuint *textures)
{
   GET_CURRENT_CONTEXT(ctx);
   GLint i;
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */

   if (!textures)
      return;

   for (i = 0; i < n; i++) {
      if (textures[i] > 0) {
         struct gl_texture_object *delObj
            = _mesa_lookup_texture(ctx, textures[i]);

         if (delObj) {
            _mesa_lock_texture(ctx, delObj);

            /* Check if texture is bound to any framebuffer objects.
             * If so, unbind.
             * See section 4.4.2.3 of GL_EXT_framebuffer_object.
             */
            unbind_texobj_from_fbo(ctx, delObj);

            /* Check if this texture is currently bound to any texture units.
             * If so, unbind it.
             */
            unbind_texobj_from_texunits(ctx, delObj);

            _mesa_unlock_texture(ctx, delObj);

            ctx->NewState |= _NEW_TEXTURE;

            /* The texture _name_ is now free for re-use.
             * Remove it from the hash table now.
             */
            _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
            _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
            _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);

            /* Unreference the texobj.  If refcount hits zero, the texture
             * will be deleted.
             */
            _mesa_reference_texobj(&delObj, NULL);
         }
      }
   }
}
Пример #10
0
/**
 * Determine if ID is the name of an array object.
 * 
 * \param id  ID of the potential array object.
 * \return  \c GL_TRUE if \c id is the name of a array object, 
 *          \c GL_FALSE otherwise.
 */
GLboolean GLAPIENTRY
_mesa_IsVertexArrayAPPLE( GLuint id )
{
   struct gl_array_object * obj;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);

   if (id == 0)
      return GL_FALSE;

   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
   obj = lookup_arrayobj(ctx, id);
   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);

   return (obj != NULL) ? GL_TRUE : GL_FALSE;
}
Пример #11
0
GLsync GLAPIENTRY
_mesa_FenceSync(GLenum condition, GLbitfield flags)
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_sync_object *syncObj;
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);

   if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glFenceSync(condition=0x%x)",
		  condition);
      return 0;
   }

   if (flags != 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glFenceSync(flags=0x%x)",
		  condition);
      return 0;
   }

   syncObj = ctx->Driver.NewSyncObject(ctx, GL_SYNC_FENCE);
   if (syncObj != NULL) {
      syncObj->Type = GL_SYNC_FENCE;
      /* The name is not currently used, and it is never visible to
       * applications.  If sync support is extended to provide support for
       * NV_fence, this field will be used.  We'll also need to add an object
       * ID hashtable.
       */
      syncObj->Name = 1;
      syncObj->RefCount = 1;
      syncObj->DeletePending = GL_FALSE;
      syncObj->SyncCondition = condition;
      syncObj->Flags = flags;
      syncObj->StatusFlag = 0;

      ctx->Driver.FenceSync(ctx, syncObj, condition, flags);

      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
      _mesa_set_add(ctx->Shared->SyncObjects,
                    _mesa_hash_pointer(syncObj),
                    syncObj);
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);

      return (GLsync) syncObj;
   }

   return NULL;
}
Пример #12
0
Файл: xm_api.c Проект: RAOF/mesa
/**
 * Return the size of the window (or pixmap) that corresponds to the
 * given XMesaBuffer.
 * \param width  returns width in pixels
 * \param height  returns height in pixels
 */
void
xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b,
                      GLuint *width, GLuint *height)
{
   Status stat;

   _glthread_LOCK_MUTEX(_xmesa_lock);
   XSync(b->xm_visual->display, 0); /* added for Chromium */
   stat = get_drawable_size(dpy, b->frontxrb->pixmap, width, height);
   _glthread_UNLOCK_MUTEX(_xmesa_lock);

   if (!stat) {
      /* probably querying a window that's recently been destroyed */
      _mesa_warning(NULL, "XGetGeometry failed!\n");
      *width = *height = 1;
   }
}
Пример #13
0
/**
 * Calls all the various one-time-init functions in Mesa.
 *
 * While holding a global mutex lock, calls several initialization functions,
 * and sets the glapi callbacks if the \c MESA_DEBUG environment variable is
 * defined.
 *
 * \sa _math_init().
 */
static void
one_time_init( GLcontext *ctx )
{
   static GLboolean alreadyCalled = GL_FALSE;
   (void) ctx;
   _glthread_LOCK_MUTEX(OneTimeLock);
   if (!alreadyCalled) {
      GLuint i;

      /* do some implementation tests */
      assert( sizeof(GLbyte) == 1 );
      assert( sizeof(GLubyte) == 1 );
      assert( sizeof(GLshort) == 2 );
      assert( sizeof(GLushort) == 2 );
      assert( sizeof(GLint) == 4 );
      assert( sizeof(GLuint) == 4 );

      _mesa_get_cpu_features();

      _mesa_init_remap_table();

      _mesa_init_sqrt_table();

      for (i = 0; i < 256; i++) {
         _mesa_ubyte_to_float_color_tab[i] = (float) i / 255.0F;
      }

      if (_mesa_getenv("MESA_DEBUG")) {
         _glapi_noop_enable_warnings(GL_TRUE);
         _glapi_set_warning_func( (_glapi_warning_func) _mesa_warning );
      }
      else {
         _glapi_noop_enable_warnings(GL_FALSE);
      }

#if defined(DEBUG) && defined(__DATE__) && defined(__TIME__)
      _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n",
                  MESA_VERSION_STRING, __DATE__, __TIME__);
#endif

      alreadyCalled = GL_TRUE;
   }
   _glthread_UNLOCK_MUTEX(OneTimeLock);

   dummy_enum_func();
}
Пример #14
0
Файл: texobj.c Проект: RAOF/mesa
/**
 * Generate texture names.
 *
 * \param n number of texture names to be generated.
 * \param textures an array in which will hold the generated texture names.
 *
 * \sa glGenTextures().
 *
 * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
 * IDs which are stored in \p textures.  Corresponding empty texture
 * objects are also generated.
 */ 
void GLAPIENTRY
_mesa_GenTextures( GLsizei n, GLuint *textures )
{
   GET_CURRENT_CONTEXT(ctx);
   GLuint first;
   GLint i;

   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
      _mesa_debug(ctx, "glGenTextures %d\n", n);

   if (n < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
      return;
   }

   if (!textures)
      return;

   /*
    * This must be atomic (generation and allocation of texture IDs)
    */
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);

   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);

   /* Allocate new, empty texture objects */
   for (i = 0; i < n; i++) {
      struct gl_texture_object *texObj;
      GLuint name = first + i;
      GLenum target = 0;
      texObj = ctx->Driver.NewTextureObject(ctx, name, target);
      if (!texObj) {
         _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
         return;
      }

      /* insert into hash table */
      _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);

      textures[i] = name;
   }

   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
Пример #15
0
/**
 * Set *ptr to point to fb, with refcounting and locking.
 */
void
_mesa_reference_framebuffer(struct gl_framebuffer **ptr,
                            struct gl_framebuffer *fb)
{
   assert(ptr);
   if (*ptr == fb) {
      /* no change */
      return;
   }
   if (*ptr) {
      _mesa_unreference_framebuffer(ptr);
   }
   assert(!*ptr);
   assert(fb);
   _glthread_LOCK_MUTEX(fb->Mutex);
   fb->RefCount++;
   _glthread_UNLOCK_MUTEX(fb->Mutex);
   *ptr = fb;
}
Пример #16
0
/**
 * Fallback for ctx->Driver.FramebufferRenderbuffer()
 * Attach a renderbuffer object to a framebuffer object.
 */
void
_mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
                               GLenum attachment, struct gl_renderbuffer *rb)
{
   struct gl_renderbuffer_attachment *att;

   _glthread_LOCK_MUTEX(fb->Mutex);

   att = _mesa_get_attachment(ctx, fb, attachment);
   ASSERT(att);
   if (rb) {
      _mesa_set_renderbuffer_attachment(ctx, att, rb);
   }
   else {
      _mesa_remove_attachment(ctx, att);
   }

   _glthread_UNLOCK_MUTEX(fb->Mutex);
}
Пример #17
0
/**
 * Insert a key/pointer pair into the hash table.  
 * If an entry with this key already exists we'll replace the existing entry.
 * 
 * \param table the hash table.
 * \param key the key (not zero).
 * \param data pointer to user data.
 */
void
_mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data)
{
   /* search for existing entry with this key */
   GLuint pos;
   struct HashEntry *entry;

   assert(table);
   assert(key);

   _glthread_LOCK_MUTEX(table->Mutex);

   if (key > table->MaxKey)
      table->MaxKey = key;

   pos = HASH_FUNC(key);

   /* check if replacing an existing entry with same key */
   for (entry = table->Table[pos]; entry; entry = entry->Next) {
      if (entry->Key == key) {
         /* replace entry's data */
#if 0 /* not sure this check is always valid */
         if (entry->Data) {
            _mesa_problem(NULL, "Memory leak detected in _mesa_HashInsert");
         }
#endif
	 entry->Data = data;
         _glthread_UNLOCK_MUTEX(table->Mutex);
	 return;
      }
   }

   /* alloc and insert new table entry */
   entry = MALLOC_STRUCT(HashEntry);
   if (entry) {
      entry->Key = key;
      entry->Data = data;
      entry->Next = table->Table[pos];
      table->Table[pos] = entry;
   }

   _glthread_UNLOCK_MUTEX(table->Mutex);
}
Пример #18
0
/**
 * Undo/remove a reference to a framebuffer object.
 * Decrement the framebuffer object's reference count and delete it when
 * the refcount hits zero.
 * Note: we pass the address of a pointer and set it to NULL.
 */
void
_mesa_unreference_framebuffer(struct gl_framebuffer **fb)
{
   assert(fb);
   if (*fb) {
      GLboolean deleteFlag = GL_FALSE;

      _glthread_LOCK_MUTEX((*fb)->Mutex);
      ASSERT((*fb)->RefCount > 0);
      (*fb)->RefCount--;
      deleteFlag = ((*fb)->RefCount == 0);
      _glthread_UNLOCK_MUTEX((*fb)->Mutex);
      
      if (deleteFlag)
         (*fb)->Delete(*fb);

      *fb = NULL;
   }
}
Пример #19
0
void
_mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
{
   struct set_entry *entry;

   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
   syncObj->RefCount--;
   if (syncObj->RefCount == 0) {
      entry = _mesa_set_search(ctx->Shared->SyncObjects,
                               _mesa_hash_pointer(syncObj),
                               syncObj);
      assert (entry != NULL);
      _mesa_set_remove(ctx->Shared->SyncObjects, entry);
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);

      ctx->Driver.DeleteSyncObject(ctx, syncObj);
   } else {
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
   }
}
Пример #20
0
/**
 * Generate a set of unique buffer object IDs and store them in \c buffer.
 * 
 * \param n       Number of IDs to generate.
 * \param buffer  Array of \c n locations to store the IDs.
 */
void GLAPIENTRY
_mesa_GenBuffersARB(GLsizei n, GLuint *buffer)
{
   GET_CURRENT_CONTEXT(ctx);
   GLuint first;
   GLint i;
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (n < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
      return;
   }

   if (!buffer) {
      return;
   }

   /*
    * This must be atomic (generation and allocation of buffer object IDs)
    */
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);

   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);

   /* Allocate new, empty buffer objects and return identifiers */
   for (i = 0; i < n; i++) {
      struct gl_buffer_object *bufObj;
      GLuint name = first + i;
      GLenum target = 0;
      bufObj = ctx->Driver.NewBufferObject( ctx, name, target );
      if (!bufObj) {
         _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB");
         return;
      }
      _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, bufObj);
      buffer[i] = first + i;
   }

   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
Пример #21
0
/**
 * Generate a set of unique array object IDs and store them in \c arrays.
 * 
 * \param n       Number of IDs to generate.
 * \param arrays  Array of \c n locations to store the IDs.
 */
void GLAPIENTRY
_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
{
   GET_CURRENT_CONTEXT(ctx);
   GLuint first;
   GLint i;
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (n < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArraysAPPLE");
      return;
   }

   if (!arrays) {
      return;
   }

   /*
    * This must be atomic (generation and allocation of array object IDs)
    */
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);

   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ArrayObjects, n);

   /* Allocate new, empty array objects and return identifiers */
   for (i = 0; i < n; i++) {
      struct gl_array_object *obj;
      GLuint name = first + i;

      obj = (*ctx->Driver.NewArrayObject)( ctx, name );
      if (!obj) {
         _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE");
         return;
      }
      _mesa_save_array_object(ctx, obj);
      arrays[i] = first + i;
   }

   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
Пример #22
0
/**
 * Walk over all entries in a hash table, calling callback function for each.
 * Note: we use a separate mutex in this function to avoid a recursive
 * locking deadlock (in case the callback calls _mesa_HashRemove()) and to
 * prevent multiple threads/contexts from getting tangled up.
 * A lock-less version of this function could be used when the table will
 * not be modified.
 * \param table  the hash table to walk
 * \param callback  the callback function
 * \param userData  arbitrary pointer to pass along to the callback
 *                  (this is typically a struct gl_context pointer)
 */
void
_mesa_HashWalk(const struct _mesa_HashTable *table,
               void (*callback)(GLuint key, void *data, void *userData),
               void *userData)
{
   /* cast-away const */
   struct _mesa_HashTable *table2 = (struct _mesa_HashTable *) table;
   GLuint pos;
   ASSERT(table);
   ASSERT(callback);
   _glthread_LOCK_MUTEX(table2->WalkMutex);
   for (pos = 0; pos < TABLE_SIZE; pos++) {
      struct HashEntry *entry, *next;
      for (entry = table->Table[pos]; entry; entry = next) {
         /* save 'next' pointer now in case the callback deletes the entry */
         next = entry->Next;
         callback(entry->Key, entry->Data, userData);
      }
   }
   _glthread_UNLOCK_MUTEX(table2->WalkMutex);
}
Пример #23
0
/**
 * Remove an entry from the hash table.
 * 
 * \param table the hash table.
 * \param key key of entry to remove.
 *
 * While holding the hash table's lock, searches the entry with the matching
 * key and unlinks it.
 */
void
_mesa_HashRemove(struct _mesa_HashTable *table, GLuint key)
{
   GLuint pos;
   struct HashEntry *entry, *prev;

   assert(table);
   assert(key);

   /* have to check this outside of mutex lock */
   if (table->InDeleteAll) {
      _mesa_problem(NULL, "_mesa_HashRemove illegally called from "
                    "_mesa_HashDeleteAll callback function");
      return;
   }

   _glthread_LOCK_MUTEX(table->Mutex);

   pos = HASH_FUNC(key);
   prev = NULL;
   entry = table->Table[pos];
   while (entry) {
      if (entry->Key == key) {
         /* found it! */
         if (prev) {
            prev->Next = entry->Next;
         }
         else {
            table->Table[pos] = entry->Next;
         }
         free(entry);
         _glthread_UNLOCK_MUTEX(table->Mutex);
	 return;
      }
      prev = entry;
      entry = entry->Next;
   }

   _glthread_UNLOCK_MUTEX(table->Mutex);
}
Пример #24
0
/**
 * Delete all entries in a hash table, but don't delete the table itself.
 * Invoke the given callback function for each table entry.
 *
 * \param table  the hash table to delete
 * \param callback  the callback function
 * \param userData  arbitrary pointer to pass along to the callback
 *                  (this is typically a struct gl_context pointer)
 */
void
_mesa_HashDeleteAll(struct _mesa_HashTable *table,
                    void (*callback)(GLuint key, void *data, void *userData),
                    void *userData)
{
   GLuint pos;
   ASSERT(table);
   ASSERT(callback);
   _glthread_LOCK_MUTEX(table->Mutex);
   table->InDeleteAll = GL_TRUE;
   for (pos = 0; pos < TABLE_SIZE; pos++) {
      struct HashEntry *entry, *next;
      for (entry = table->Table[pos]; entry; entry = next) {
         callback(entry->Key, entry->Data, userData);
         next = entry->Next;
         free(entry);
      }
      table->Table[pos] = NULL;
   }
   table->InDeleteAll = GL_FALSE;
   _glthread_UNLOCK_MUTEX(table->Mutex);
}
Пример #25
0
/**
 * Generate texture names.
 *
 * \param n number of texture names to be generated.
 * \param texName an array in which will hold the generated texture names.
 *
 * \sa glGenTextures().
 *
 * While holding the GenTexturesLock lock, calls _mesa_HashFindFreeKeyBlock()
 * to find a block of free texture IDs which are stored in \p texName.
 * Corresponding empty texture objects are also generated.
 */ 
void GLAPIENTRY
_mesa_GenTextures( GLsizei n, GLuint *texName )
{
   GET_CURRENT_CONTEXT(ctx);
   GLuint first;
   GLint i;
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (n < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
      return;
   }

   if (!texName)
      return;

   /*
    * This must be atomic (generation and allocation of texture IDs)
    */
   _glthread_LOCK_MUTEX(GenTexturesLock);

   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);

   /* Allocate new, empty texture objects */
   for (i = 0; i < n; i++) {
      struct gl_texture_object *texObj;
      GLuint name = first + i;
      GLenum target = 0;
      texObj = (*ctx->Driver.NewTextureObject)( ctx, name, target);
      if (!texObj) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
         return;
      }
      _mesa_save_texture_object(ctx, texObj);
      texName[i] = name;
   }

   _glthread_UNLOCK_MUTEX(GenTexturesLock);
}
Пример #26
0
static void
clear_color( GLcontext *ctx, const GLfloat color[4] )
{
   if (ctx->DrawBuffer->Name == 0) {
      const XMesaContext xmesa = XMESA_CONTEXT(ctx);
      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);

      CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
      CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
      CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
      CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
      xmesa->clearpixel = xmesa_color_to_pixel( ctx,
                                                xmesa->clearcolor[0],
                                                xmesa->clearcolor[1],
                                                xmesa->clearcolor[2],
                                                xmesa->clearcolor[3],
                                                xmesa->xm_visual->undithered_pf );
      _glthread_LOCK_MUTEX(_xmesa_lock);
      XMesaSetForeground( xmesa->display, xmbuf->cleargc,
                          xmesa->clearpixel );
      _glthread_UNLOCK_MUTEX(_xmesa_lock);
   }
}
Пример #27
0
/**
 * Generate a set of unique buffer object IDs and store them in \c buffer.
 * 
 * \param n       Number of IDs to generate.
 * \param buffer  Array of \c n locations to store the IDs.
 */
void GLAPIENTRY
_mesa_GenBuffersARB(GLsizei n, GLuint *buffer)
{
   GET_CURRENT_CONTEXT(ctx);
   GLuint first;
   GLint i;
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "glGenBuffers(%d)\n", n);

   if (n < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
      return;
   }

   if (!buffer) {
      return;
   }

   /*
    * This must be atomic (generation and allocation of buffer object IDs)
    */
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);

   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);

   /* Insert the ID and pointer to dummy buffer object into hash table */
   for (i = 0; i < n; i++) {
      _mesa_HashInsert(ctx->Shared->BufferObjects, first + i,
                       &DummyBufferObject);
      buffer[i] = first + i;
   }

   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
Пример #28
0
/**
 * Bind a named texture to a texturing target.
 * 
 * \param target texture target.
 * \param texName texture name.
 * 
 * \sa glBindTexture().
 *
 * Determines the old texture object bound and returns immediately if rebinding
 * the same texture.  Get the current texture which is either a default texture
 * if name is null, a named texture from the hash, or a new texture if the
 * given texture name is new. Increments its reference count, binds it, and
 * calls dd_function_table::BindTexture. Decrements the old texture reference
 * count and deletes it if it reaches zero.
 */
void GLAPIENTRY
_mesa_BindTexture( GLenum target, GLuint texName )
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
   struct gl_texture_object *newTexObj = NULL;
   GLint targetIndex;
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
      _mesa_debug(ctx, "glBindTexture %s %d\n",
                  _mesa_lookup_enum_by_nr(target), (GLint) texName);

   targetIndex = target_enum_to_index(ctx, target);
   if (targetIndex < 0) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
      return;
   }
   assert(targetIndex < NUM_TEXTURE_TARGETS);

   /*
    * Get pointer to new texture object (newTexObj)
    */
   if (texName == 0) {
      /* Use a default texture object */
      newTexObj = ctx->Shared->DefaultTex[targetIndex];
   }
   else {
      /* non-default texture object */
      newTexObj = _mesa_lookup_texture(ctx, texName);
      if (newTexObj) {
         /* error checking */
         if (newTexObj->Target != 0 && newTexObj->Target != target) {
            /* the named texture object's target doesn't match the given target */
            _mesa_error( ctx, GL_INVALID_OPERATION,
                         "glBindTexture(target mismatch)" );
            return;
         }
         if (newTexObj->Target == 0) {
            finish_texture_init(ctx, target, newTexObj);
         }
      }
      else {
         if (ctx->API == API_OPENGL_CORE) {
            _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTexture");
            return;
         }

         /* if this is a new texture id, allocate a texture object now */
         newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target);
         if (!newTexObj) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
            return;
         }

         /* and insert it into hash table */
         _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
         _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
         _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
      }
      newTexObj->Target = target;
   }

   assert(valid_texture_object(newTexObj));

   /* Check if this texture is only used by this context and is already bound.
    * If so, just return.
    */
   {
      GLboolean early_out;
      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
      early_out = ((ctx->Shared->RefCount == 1)
                   && (newTexObj == texUnit->CurrentTex[targetIndex]));
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
      if (early_out) {
         return;
      }
   }

   /* flush before changing binding */
   FLUSH_VERTICES(ctx, _NEW_TEXTURE);

   /* Do the actual binding.  The refcount on the previously bound
    * texture object will be decremented.  It'll be deleted if the
    * count hits zero.
    */
   _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
   ASSERT(texUnit->CurrentTex[targetIndex]);

   /* Pass BindTexture call to device driver */
   if (ctx->Driver.BindTexture)
      ctx->Driver.BindTexture(ctx, target, newTexObj);
}
Пример #29
0
/**
 * Free the data associated with the given context.
 * 
 * But doesn't free the GLcontext struct itself.
 *
 * \sa _mesa_initialize_context() and init_attrib_groups().
 */
void
_mesa_free_context_data( GLcontext *ctx )
{
   GLint RefCount;

   if (!_mesa_get_current_context()){
      /* No current context, but we may need one in order to delete
       * texture objs, etc.  So temporarily bind the context now.
       */
      _mesa_make_current(ctx, NULL, NULL);
   }

   /* unreference WinSysDraw/Read buffers */
   _mesa_reference_framebuffer(&ctx->WinSysDrawBuffer, NULL);
   _mesa_reference_framebuffer(&ctx->WinSysReadBuffer, NULL);
   _mesa_reference_framebuffer(&ctx->DrawBuffer, NULL);
   _mesa_reference_framebuffer(&ctx->ReadBuffer, NULL);

   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL);

   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);

   _mesa_free_attrib_data(ctx);
   _mesa_free_lighting_data( ctx );
   _mesa_free_eval_data( ctx );
   _mesa_free_texture_data( ctx );
   _mesa_free_matrix_data( ctx );
   _mesa_free_viewport_data( ctx );
   _mesa_free_colortables_data( ctx );
   _mesa_free_program_data(ctx);
   _mesa_free_shader_state(ctx);
   _mesa_free_queryobj_data(ctx);
#if FEATURE_ARB_sync
   _mesa_free_sync_data(ctx);
#endif
   _mesa_free_varray_data(ctx);

   _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);

#if FEATURE_ARB_pixel_buffer_object
   _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
   _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
#endif

#if FEATURE_ARB_vertex_buffer_object
   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
   _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL);
#endif

   /* free dispatch tables */
   _mesa_free(ctx->Exec);
   _mesa_free(ctx->Save);

   /* Shared context state (display lists, textures, etc) */
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
   RefCount = --ctx->Shared->RefCount;
   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
   assert(RefCount >= 0);
   if (RefCount == 0) {
      /* free shared state */
      _mesa_free_shared_state( ctx, ctx->Shared );
   }

   /* needs to be after freeing shared state */
   _mesa_free_display_list_data(ctx);

   if (ctx->Extensions.String)
      _mesa_free((void *) ctx->Extensions.String);

   /* unbind the context if it's currently bound */
   if (ctx == _mesa_get_current_context()) {
      _mesa_make_current(NULL, NULL, NULL);
   }
}
Пример #30
0
/**
 * Initialize a GLcontext struct (rendering context).
 *
 * This includes allocating all the other structs and arrays which hang off of
 * the context by pointers.
 * Note that the driver needs to pass in its dd_function_table here since
 * we need to at least call driverFunctions->NewTextureObject to create the
 * default texture objects.
 * 
 * Called by _mesa_create_context().
 *
 * Performs the imports and exports callback tables initialization, and
 * miscellaneous one-time initializations. If no shared context is supplied one
 * is allocated, and increase its reference count.  Setups the GL API dispatch
 * tables.  Initialize the TNL module. Sets the maximum Z buffer depth.
 * Finally queries the \c MESA_DEBUG and \c MESA_VERBOSE environment variables
 * for debug flags.
 *
 * \param ctx the context to initialize
 * \param visual describes the visual attributes for this context
 * \param share_list points to context to share textures, display lists,
 *        etc with, or NULL
 * \param driverFunctions table of device driver functions for this context
 *        to use
 * \param driverContext pointer to driver-specific context data
 */
GLboolean
_mesa_initialize_context(GLcontext *ctx,
                         const GLvisual *visual,
                         GLcontext *share_list,
                         const struct dd_function_table *driverFunctions,
                         void *driverContext)
{
   struct gl_shared_state *shared;

   /*ASSERT(driverContext);*/
   assert(driverFunctions->NewTextureObject);
   assert(driverFunctions->FreeTexImageData);

   /* misc one-time initializations */
   one_time_init(ctx);

   ctx->Visual = *visual;
   ctx->DrawBuffer = NULL;
   ctx->ReadBuffer = NULL;
   ctx->WinSysDrawBuffer = NULL;
   ctx->WinSysReadBuffer = NULL;

   /* Plug in driver functions and context pointer here.
    * This is important because when we call alloc_shared_state() below
    * we'll call ctx->Driver.NewTextureObject() to create the default
    * textures.
    */
   ctx->Driver = *driverFunctions;
   ctx->DriverCtx = driverContext;

   if (share_list) {
      /* share state with another context */
      shared = share_list->Shared;
   }
   else {
      /* allocate new, unshared state */
      shared = _mesa_alloc_shared_state(ctx);
      if (!shared)
         return GL_FALSE;
   }

   _glthread_LOCK_MUTEX(shared->Mutex);
   ctx->Shared = shared;
   shared->RefCount++;
   _glthread_UNLOCK_MUTEX(shared->Mutex);

   if (!init_attrib_groups( ctx )) {
      _mesa_free_shared_state(ctx, ctx->Shared);
      return GL_FALSE;
   }

   /* setup the API dispatch tables */
   ctx->Exec = alloc_dispatch_table();
   ctx->Save = alloc_dispatch_table();
   if (!ctx->Exec || !ctx->Save) {
      _mesa_free_shared_state(ctx, ctx->Shared);
      if (ctx->Exec)
         _mesa_free(ctx->Exec);
      return GL_FALSE;
   }
#if FEATURE_dispatch
   _mesa_init_exec_table(ctx->Exec);
#endif
   ctx->CurrentDispatch = ctx->Exec;

#if FEATURE_dlist
   _mesa_init_save_table(ctx->Save);
   _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
#endif

   /* Neutral tnl module stuff */
   _mesa_init_exec_vtxfmt( ctx ); 
   ctx->TnlModule.Current = NULL;
   ctx->TnlModule.SwapCount = 0;

   ctx->FragmentProgram._MaintainTexEnvProgram
      = (_mesa_getenv("MESA_TEX_PROG") != NULL);

   ctx->VertexProgram._MaintainTnlProgram
      = (_mesa_getenv("MESA_TNL_PROG") != NULL);
   if (ctx->VertexProgram._MaintainTnlProgram) {
      /* this is required... */
      ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
   }

#ifdef FEATURE_extra_context_init
   _mesa_initialize_context_extra(ctx);
#endif

   ctx->FirstTimeCurrent = GL_TRUE;

   return GL_TRUE;
}