Beispiel #1
0
Datei: hash.c Projekt: aosm/X11
/**
 * Insert 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 = key & (TABLE_SIZE-1);
   entry = table->Table[pos];
   while (entry) {
      if (entry->Key == key) {
         /* replace entry's data */
	 entry->Data = data;
         _glthread_UNLOCK_MUTEX(table->Mutex);
	 return;
      }
      entry = entry->Next;
   }

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

   _glthread_UNLOCK_MUTEX(table->Mutex);
}
Beispiel #2
0
Datei: hash.c Projekt: aosm/X11
/**
 * Remove an entry from the hash table.
 * \param table - the hash table
 * \param key - key of entry to remove
 */
void _mesa_HashRemove(struct _mesa_HashTable *table, GLuint key)
{
   GLuint pos;
   struct HashEntry *entry, *prev;

   assert(table);
   assert(key);

   _glthread_LOCK_MUTEX(table->Mutex);

   pos = key & (TABLE_SIZE-1);
   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);
}
Beispiel #3
0
/**
 * Make context 'ctx' share the display lists, textures and programs
 * that are associated with 'ctxToShare'.
 * Any display lists, textures or programs associated with 'ctx' will
 * be deleted if nobody else is sharing them.
 */
GLboolean
_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
{
   if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
      struct gl_shared_state *oldSharedState = ctx->Shared;
      GLint RefCount;

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

      update_default_objects(ctx);

      _glthread_LOCK_MUTEX(oldSharedState->Mutex);
      RefCount = --oldSharedState->RefCount;
      _glthread_UNLOCK_MUTEX(oldSharedState->Mutex);

      if (RefCount == 0) {
         _mesa_free_shared_state(ctx, oldSharedState);
      }

      return GL_TRUE;
   }
   else {
      return GL_FALSE;
   }
}
Beispiel #4
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) {
         oldRb->Delete(oldRb);
      }

      *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;
   }
}
Beispiel #5
0
Datei: hash.c Projekt: aosm/X11
/**
 * Find a block of 'numKeys' adjacent unused hash keys.
 * \param table - the hash table
 * \param numKeys - number of keys needed
 * \return Starting key of free block or 0 if failure
 */
GLuint _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys)
{
   GLuint maxKey = ~((GLuint) 0);
   _glthread_LOCK_MUTEX(table->Mutex);
   if (maxKey - numKeys > table->MaxKey) {
      /* the quick solution */
      _glthread_UNLOCK_MUTEX(table->Mutex);
      return table->MaxKey + 1;
   }
   else {
      /* the slow solution */
      GLuint freeCount = 0;
      GLuint freeStart = 1;
      GLuint key;
      for (key=1; key!=maxKey; key++) {
	 if (_mesa_HashLookup(table, key)) {
	    /* darn, this key is already in use */
	    freeCount = 0;
	    freeStart = key+1;
	 }
	 else {
	    /* this key not in use, check if we've found enough */
	    freeCount++;
	    if (freeCount == numKeys) {
               _glthread_UNLOCK_MUTEX(table->Mutex);
	       return freeStart;
	    }
	 }
      }
      /* cannot allocate a block of numKeys consecutive keys */
      _glthread_UNLOCK_MUTEX(table->Mutex);
      return 0;
   }
}
/**
 * Set *ptr to point to fb, with refcounting and locking.
 * This is normally only called from the _mesa_reference_framebuffer() macro
 * when there's a real pointer change.
 */
void
_mesa_reference_framebuffer_(struct gl_framebuffer **ptr,
                             struct gl_framebuffer *fb)
{
   if (*ptr) {
      /* unreference old renderbuffer */
      GLboolean deleteFlag = GL_FALSE;
      struct gl_framebuffer *oldFb = *ptr;

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

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

   if (fb) {
      _glthread_LOCK_MUTEX(fb->Mutex);
      fb->RefCount++;
      _glthread_UNLOCK_MUTEX(fb->Mutex);
      *ptr = fb;
   }
}
Beispiel #7
0
/**
 * Set ptr to bufObj w/ reference counting.
 * This is normally only called from the _mesa_reference_buffer_object() macro
 * when there's a real pointer change.
 */
void
_mesa_reference_buffer_object_(struct gl_context *ctx,
                               struct gl_buffer_object **ptr,
                               struct gl_buffer_object *bufObj)
{
   if (*ptr) {
      /* Unreference the old buffer */
      GLboolean deleteFlag = GL_FALSE;
      struct gl_buffer_object *oldObj = *ptr;

      _glthread_LOCK_MUTEX(oldObj->Mutex);
      ASSERT(oldObj->RefCount > 0);
      oldObj->RefCount--;
#if 0
      printf("BufferObj %p %d DECR to %d\n",
             (void *) oldObj, oldObj->Name, oldObj->RefCount);
#endif
      deleteFlag = (oldObj->RefCount == 0);
      _glthread_UNLOCK_MUTEX(oldObj->Mutex);

      if (deleteFlag) {

         /* some sanity checking: don't delete a buffer still in use */
#if 0
         /* unfortunately, these tests are invalid during context tear-down */
	 ASSERT(ctx->Array.ArrayBufferObj != bufObj);
	 ASSERT(ctx->Array.ArrayObj->ElementArrayBufferObj != bufObj);
	 ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj);
#endif

	 ASSERT(ctx->Driver.DeleteBuffer);
         ctx->Driver.DeleteBuffer(ctx, oldObj);
      }

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

   if (bufObj) {
      /* reference new buffer */
      _glthread_LOCK_MUTEX(bufObj->Mutex);
      if (bufObj->RefCount == 0) {
         /* this buffer's being deleted (look just above) */
         /* Not sure this can every really happen.  Warn if it does. */
         _mesa_problem(NULL, "referencing deleted buffer object");
         *ptr = NULL;
      }
      else {
         bufObj->RefCount++;
#if 0
         printf("BufferObj %p %d INCR to %d\n",
                (void *) bufObj, bufObj->Name, bufObj->RefCount);
#endif
         *ptr = bufObj;
      }
      _glthread_UNLOCK_MUTEX(bufObj->Mutex);
   }
}
Beispiel #8
0
/**
 * Set ptr to arrayObj w/ reference counting.
 */
void
_mesa_reference_array_object(struct gl_context *ctx,
                             struct gl_array_object **ptr,
                             struct gl_array_object *arrayObj)
{
   if (*ptr == arrayObj)
      return;

   if (*ptr) {
      /* Unreference the old array object */
      GLboolean deleteFlag = GL_FALSE;
      struct gl_array_object *oldObj = *ptr;

      _glthread_LOCK_MUTEX(oldObj->Mutex);
      ASSERT(oldObj->RefCount > 0);
      oldObj->RefCount--;
#if 0
      printf("ArrayObj %p %d DECR to %d\n",
             (void *) oldObj, oldObj->Name, oldObj->RefCount);
#endif
      deleteFlag = (oldObj->RefCount == 0);
      _glthread_UNLOCK_MUTEX(oldObj->Mutex);

      if (deleteFlag) {
	 ASSERT(ctx->Driver.DeleteArrayObject);
         ctx->Driver.DeleteArrayObject(ctx, oldObj);
      }

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

   if (arrayObj) {
      /* reference new array object */
      _glthread_LOCK_MUTEX(arrayObj->Mutex);
      if (arrayObj->RefCount == 0) {
         /* this array's being deleted (look just above) */
         /* Not sure this can every really happen.  Warn if it does. */
         _mesa_problem(NULL, "referencing deleted array object");
         *ptr = NULL;
      }
      else {
         arrayObj->RefCount++;
#if 0
         printf("ArrayObj %p %d INCR to %d\n",
                (void *) arrayObj, arrayObj->Name, arrayObj->RefCount);
#endif
         *ptr = arrayObj;
      }
      _glthread_UNLOCK_MUTEX(arrayObj->Mutex);
   }
}
Beispiel #9
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);
   }
}
Beispiel #10
0
/**
 * Reference (or unreference) a texture object.
 * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
 * If 'tex' is non-null, increment its refcount.
 * This is normally only called from the _mesa_reference_texobj() macro
 * when there's a real pointer change.
 */
void
_mesa_reference_texobj_(struct gl_texture_object **ptr,
                        struct gl_texture_object *tex)
{
   assert(ptr);

   if (*ptr) {
      /* Unreference the old texture */
      GLboolean deleteFlag = GL_FALSE;
      struct gl_texture_object *oldTex = *ptr;

      ASSERT(valid_texture_object(oldTex));
      (void) valid_texture_object; /* silence warning in release builds */

      _glthread_LOCK_MUTEX(oldTex->Mutex);
      ASSERT(oldTex->RefCount > 0);
      oldTex->RefCount--;

      deleteFlag = (oldTex->RefCount == 0);
      _glthread_UNLOCK_MUTEX(oldTex->Mutex);

      if (deleteFlag) {
         GET_CURRENT_CONTEXT(ctx);
         if (ctx)
            ctx->Driver.DeleteTexture(ctx, oldTex);
         else
            _mesa_problem(NULL, "Unable to delete texture, no context");
      }

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

   if (tex) {
      /* reference new texture */
      ASSERT(valid_texture_object(tex));
      _glthread_LOCK_MUTEX(tex->Mutex);
      if (tex->RefCount == 0) {
         /* this texture's being deleted (look just above) */
         /* Not sure this can every really happen.  Warn if it does. */
         _mesa_problem(NULL, "referencing deleted texture object");
         *ptr = NULL;
      }
      else {
         tex->RefCount++;
         *ptr = tex;
      }
      _glthread_UNLOCK_MUTEX(tex->Mutex);
   }
}
Beispiel #11
0
Datei: hash.c Projekt: 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;
}
Beispiel #12
0
void GLAPIENTRY
_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
{
   GET_CURRENT_CONTEXT(ctx);
   GLuint first;
   GLint i;

   ASSERT_OUTSIDE_BEGIN_END(ctx);

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

   if (!renderbuffers)
      return;

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

   for (i = 0; i < n; i++) {
      GLuint name = first + i;
      renderbuffers[i] = name;
      /* insert dummy placeholder into hash table */
      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
      _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
   }
}
Beispiel #13
0
/*
 * Allocate and initialize a new MemRange struct.
 * Try to allocate it from the pool of free MemRange nodes rather than malloc.
 */
static tdfxMemRange *
NewRangeNode(tdfxContextPtr fxMesa, FxU32 start, FxU32 end)
{
    struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
    struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
    tdfxMemRange *result;

    _glthread_LOCK_MUTEX(mesaShared->Mutex);
    if (shared && shared->tmPool) {
        result = shared->tmPool;
        shared->tmPool = shared->tmPool->next;
    }
    else {
        result = MALLOC(sizeof(tdfxMemRange));

    }
    _glthread_UNLOCK_MUTEX(mesaShared->Mutex);

    if (!result) {
        /*fprintf(stderr, "fxDriver: out of memory!\n");*/
        return NULL;
    }

    result->startAddr = start;
    result->endAddr = end;
    result->next = NULL;

    return result;
}
Beispiel #14
0
void
_mesa_ref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj)
{
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
   syncObj->RefCount++;
   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
Beispiel #15
0
/**
 * Remove the given texture object from the texture object pool.
 * Do not deallocate the texture object though.
 */
void
_mesa_remove_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
{
   struct gl_texture_object *tprev, *tcurr;

   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);

   /* unlink from the linked list */
   tprev = NULL;
   tcurr = ctx->Shared->TexObjectList;
   while (tcurr) {
      if (tcurr == texObj) {
         if (tprev) {
            tprev->Next = texObj->Next;
         }
         else {
            ctx->Shared->TexObjectList = texObj->Next;
         }
         break;
      }
      tprev = tcurr;
      tcurr = tcurr->Next;
   }

   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);

   if (texObj->Name > 0) {
      /* remove from hash table */
      _mesa_HashRemove(ctx->Shared->TexObjects, texObj->Name);
   }
}
Beispiel #16
0
void *
_mesa_exec_malloc(GLuint size)
{
    struct mem_block *block = NULL;
    void *addr = NULL;

    _glthread_LOCK_MUTEX(exec_mutex);

    if (!init_heap())
        goto bail;

    if (exec_heap) {
        size = (size + 31) & ~31;
        block = mmAllocMem( exec_heap, size, 32, 0 );
    }

    if (block)
        addr = exec_mem + block->ofs;
    else
        printf("_mesa_exec_malloc failed\n");

bail:
    _glthread_UNLOCK_MUTEX(exec_mutex);

    return addr;
}
Beispiel #17
0
            /* Combine */
            prev->endAddr = range->endAddr;
            prev->next = range->next;
            DELETE_RANGE_NODE(shared, range);
        }
        else {
            prev->next = range;
        }
    }
    else {
        shared->tmFree[tmu] = range;
    }
}


#if 0 /* NOT USED */
static void
RemoveRange(tdfxContextPtr fxMesa, FxU32 tmu, tdfxMemRange *range)
{
    struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
    _glthread_LOCK_MUTEX(mesaShared->Mutex);
    RemoveRange_NoLock(fxMesa, tmu, range);
    _glthread_UNLOCK_MUTEX(mesaShared->Mutex);
}
Beispiel #18
0
/**
 * 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().
 *
 * While holding the GenTexturesLock lock, 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;
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   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(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) {
         _glthread_UNLOCK_MUTEX(GenTexturesLock);
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
         return;
      }

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

      textures[i] = name;
   }

   _glthread_UNLOCK_MUTEX(GenTexturesLock);
}
Beispiel #19
0
/**
 * Delete a set of buffer objects.
 * 
 * \param n      Number of buffer objects to delete.
 * \param ids    Array of \c n buffer object IDs.
 */
void GLAPIENTRY
_mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
{
   GET_CURRENT_CONTEXT(ctx);
   GLsizei i;
   ASSERT_OUTSIDE_BEGIN_END(ctx);
   FLUSH_VERTICES(ctx, 0);

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

   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);

   for (i = 0; i < n; i++) {
      struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]);
      if (bufObj) {
         GLuint j;

         ASSERT(bufObj->Name == ids[i] || bufObj == &DummyBufferObject);

         if (_mesa_bufferobj_mapped(bufObj)) {
            /* if mapped, unmap it now */
            ctx->Driver.UnmapBuffer(ctx, bufObj);
            bufObj->AccessFlags = default_access_mode(ctx);
            bufObj->Pointer = NULL;
         }

         /* unbind any vertex pointers bound to this buffer */
         for (j = 0; j < Elements(ctx->Array.VertexAttrib); j++) {
            unbind(ctx, &ctx->Array.VertexAttrib[j].BufferObj, bufObj);
         }

         if (ctx->Array.ElementArrayBufferObj == bufObj) {
            _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
         }

         /* The ID is immediately freed for re-use */
         _mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]);
         /* Make sure we do not run into the classic ABA problem on bind.
          * We don't want to allow re-binding a buffer object that's been
          * "deleted" by glDeleteBuffers().
          *
          * The explicit rebinding to the default object in the current context
          * prevents the above in the current context, but another context
          * sharing the same objects might suffer from this problem.
          * The alternative would be to do the hash lookup in any case on bind
          * which would introduce more runtime overhead than this.
          */
         bufObj->DeletePending = GL_TRUE;
         _mesa_reference_buffer_object(ctx, &bufObj, NULL);
      }
   }

   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
/**
 * Delete a set of array objects.
 * 
 * \param n      Number of array objects to delete.
 * \param ids    Array of \c n array object IDs.
 */
void GLAPIENTRY
_mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids)
{
   GET_CURRENT_CONTEXT(ctx);
   GLsizei i;
   ASSERT_OUTSIDE_BEGIN_END(ctx);

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

   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);

   for (i = 0; i < n; i++) {
      struct gl_array_object *obj = lookup_arrayobj(ctx, ids[i]);

      if ( obj != NULL ) {
	 ASSERT( obj->Name == ids[i] );


	 /* If the array object is currently bound, the spec says "the binding
	  * for that object reverts to zero and the default vertex array
	  * becomes current."
	  */
	 if ( obj == ctx->Array.ArrayObj ) {
	    CALL_BindVertexArrayAPPLE( ctx->Exec, (0) );
	 }

#if FEATURE_ARB_vertex_buffer_object
	 /* Unbind any buffer objects that might be bound to arrays in
	  * this array object.
	  */
	 unbind_buffer_object( ctx, obj->Vertex.BufferObj );
	 unbind_buffer_object( ctx, obj->Normal.BufferObj );
	 unbind_buffer_object( ctx, obj->Color.BufferObj );
	 unbind_buffer_object( ctx, obj->SecondaryColor.BufferObj );
	 unbind_buffer_object( ctx, obj->FogCoord.BufferObj );
	 unbind_buffer_object( ctx, obj->Index.BufferObj );
	 for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
	    unbind_buffer_object( ctx, obj->TexCoord[i].BufferObj );
	 }
	 unbind_buffer_object( ctx, obj->EdgeFlag.BufferObj );
	 for (i = 0; i < VERT_ATTRIB_MAX; i++) {
	    unbind_buffer_object( ctx, obj->VertexAttrib[i].BufferObj );
	 }
#endif

	 /* The ID is immediately freed for re-use */
	 _mesa_remove_array_object(ctx, obj);
	 ctx->Driver.DeleteArrayObject(ctx, obj);
      }
   }

   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
Beispiel #21
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);
}
Beispiel #22
0
static void
finish_or_flush( struct gl_context *ctx )
{
   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
   if (xmesa) {
      _glthread_LOCK_MUTEX(_xmesa_lock);
      XSync( xmesa->display, False );
      _glthread_UNLOCK_MUTEX(_xmesa_lock);
   }
}
Beispiel #23
0
/**
 * Lookup an entry in the hash table.
 * 
 * \param table the hash table.
 * \param key the key.
 * 
 * \return pointer to user's data or NULL if key not in table
 */
void *
_mesa_HashLookup(struct _mesa_HashTable *table, GLuint key)
{
   void *res;
   assert(table);
   _glthread_LOCK_MUTEX(table->Mutex);
   res = _mesa_HashLookup_unlocked(table, key);
   _glthread_UNLOCK_MUTEX(table->Mutex);
   return res;
}
Beispiel #24
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);
   }
}
/**
 * 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);
}
Beispiel #26
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);
}
Beispiel #27
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);
}
Beispiel #28
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;

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

   FLUSH_VERTICES(ctx, 0); /* 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);
         }
      }
   }
}
Beispiel #29
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;
}