Exemplo n.º 1
0
/**
 * Free a context's vertex/fragment program state
 */
void
_mesa_free_program_data(GLcontext *ctx)
{
#if FEATURE_NV_vertex_program
   if (ctx->VertexProgram.Current) {
      ctx->VertexProgram.Current->Base.RefCount--;
      if (ctx->VertexProgram.Current->Base.RefCount <= 0) {
         _mesa_HashRemove(ctx->Shared->Programs,
                          ctx->VertexProgram.Current->Base.Id);
         _mesa_delete_program(ctx, &(ctx->VertexProgram.Current->Base));
      }
   }
#endif
#if FEATURE_NV_fragment_program
   if (ctx->FragmentProgram.Current) {
      ctx->FragmentProgram.Current->Base.RefCount--;
      if (ctx->FragmentProgram.Current->Base.RefCount <= 0) {
         _mesa_HashRemove(ctx->Shared->Programs,
                          ctx->FragmentProgram.Current->Base.Id);
         _mesa_delete_program(ctx, &(ctx->FragmentProgram.Current->Base));
      }
   }
#endif
   _mesa_free((void *) ctx->Program.ErrorString);
}
Exemplo n.º 2
0
void GLAPIENTRY
_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

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

   /* No query objects can be active at this time! */
   if (ctx->Query.CurrentOcclusionObject ||
       ctx->Query.CurrentTimerObject) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB");
      return;
   }

   for (i = 0; i < n; i++) {
      if (ids[i] > 0) {
         struct gl_query_object *q = lookup_query_object(ctx, ids[i]);
         if (q) {
            ASSERT(!q->Active); /* should be caught earlier */
            _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]);
            ctx->Driver.DeleteQuery(ctx, q);
         }
      }
   }
}
Exemplo n.º 3
0
void GLAPIENTRY
_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);

   ASSERT_OUTSIDE_BEGIN_END(ctx);
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);

   for (i = 0; i < n; i++) {
      if (renderbuffers[i] > 0) {
	 struct gl_renderbuffer *rb;
	 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
	 if (rb) {
            /* check if deleting currently bound renderbuffer object */
            if (rb == ctx->CurrentRenderbuffer) {
               /* bind default */
               ASSERT(rb->RefCount >= 2);
               _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
            }

	    /* Remove from hash table immediately, to free the ID.
             * But the object will not be freed until it's no longer
             * referenced anywhere else.
             */
	    _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);

            if (rb != &DummyRenderbuffer) {
               /* no longer referenced by hash table */
               _mesa_reference_renderbuffer(&rb, NULL);
	    }
	 }
      }
   }
}
Exemplo n.º 4
0
/**
 * Delete the given transform feedback objects.
 * Part of GL_ARB_transform_feedback2.
 */
void GLAPIENTRY
_mesa_DeleteTransformFeedbacks(GLsizei n, const GLuint *names)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);

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

   if (!names)
      return;

   for (i = 0; i < n; i++) {
      if (names[i] > 0) {
         struct gl_transform_feedback_object *obj
            = _mesa_lookup_transform_feedback_object(ctx, names[i]);
         if (obj) {
            if (obj->Active) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glDeleteTransformFeedbacks(object %u is active)",
                           names[i]);
               return;
            }
            _mesa_HashRemove(ctx->TransformFeedback.Objects, names[i]);
            /* unref, but object may not be deleted until later */
            reference_transform_feedback_object(&obj, NULL);
         }
      }
   }
}
Exemplo n.º 5
0
/**
 * Set ptr to point to sh.
 * If ptr is pointing to another shader, decrement its refcount (and delete
 * if refcount hits zero).
 * Then set ptr to point to sh, incrementing its refcount.
 */
void
_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
                       struct gl_shader *sh)
{
   assert(ptr);
   if (*ptr == sh) {
      /* no-op */
      return;
   }
   if (*ptr) {
      /* Unreference the old shader */
      GLboolean deleteFlag = GL_FALSE;
      struct gl_shader *old = *ptr;

      assert(old->RefCount > 0);
      old->RefCount--;
      deleteFlag = (old->RefCount == 0);

      if (deleteFlag) {
	 if (old->Name != 0)
	    _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
         _mesa_delete_shader(ctx, old);
      }

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

   if (sh) {
      /* reference new */
      sh->RefCount++;
      *ptr = sh;
   }
}
Exemplo n.º 6
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);
   }
}
Exemplo n.º 7
0
/**
 * Remove the given pipeline object from the pipeline object pool.
 * Do not deallocate the pipeline object though.
 */
static void
remove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
{
   if (obj->Name > 0) {
      _mesa_HashRemove(ctx->Pipeline.Objects, obj->Name);
   }
}
Exemplo n.º 8
0
/**
 * Delete a list of programs.
 * \note Not compiled into display lists.
 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
 */
void GLAPIENTRY 
_mesa_DeleteProgramsARB(GLsizei n, const GLuint *ids)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);

   FLUSH_VERTICES(ctx, 0);

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

   for (i = 0; i < n; i++) {
      if (ids[i] != 0) {
         struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
         if (prog == &_mesa_DummyProgram) {
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
         }
         else if (prog) {
            /* Unbind program if necessary */
            switch (prog->Target) {
            case GL_VERTEX_PROGRAM_ARB:
               if (ctx->VertexProgram.Current &&
                   ctx->VertexProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgramARB(prog->Target, 0);
               }
               break;
            case GL_FRAGMENT_PROGRAM_ARB:
               if (ctx->FragmentProgram.Current &&
                   ctx->FragmentProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgramARB(prog->Target, 0);
               }
               break;
            default:
               _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
               return;
            }
            /* The ID is immediately available for re-use now */
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
            _mesa_reference_program(ctx, &prog, NULL);
         }
      }
   }
}
Exemplo n.º 9
0
/**
 * Delete a list of programs.
 * \note Not compiled into display lists.
 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
 */
void GLAPIENTRY 
_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

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

   for (i = 0; i < n; i++) {
      if (ids[i] != 0) {
         struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
         if (prog == &_mesa_DummyProgram) {
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
         }
         else if (prog) {
            /* Unbind program if necessary */
            if (prog->Target == GL_VERTEX_PROGRAM_ARB || /* == GL_VERTEX_PROGRAM_NV */
                prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
               if (ctx->VertexProgram.Current &&
                   ctx->VertexProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgram(prog->Target, 0);
               }
            }
            else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
                     prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
               if (ctx->FragmentProgram.Current &&
                   ctx->FragmentProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgram(prog->Target, 0);
               }
            }
            else {
               _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
               return;
            }
            /* The ID is immediately available for re-use now */
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
            _mesa_reference_program(ctx, &prog, NULL);
         }
      }
   }
}
Exemplo n.º 10
0
/**
 * Remove the given buffer object from the buffer object pool.
 * Do not deallocate the buffer object though.
 */
void
_mesa_remove_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj )
{
   if (bufObj->Name > 0) {
      /* remove from hash table */
      _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name);
   }
}
Exemplo n.º 11
0
/**
 * Remove the given array object from the array object pool.
 * Do not deallocate the array object though.
 */
static void
remove_array_object( struct gl_context *ctx, struct gl_array_object *obj )
{
   if (obj->Name > 0) {
      /* remove from hash table */
      _mesa_HashRemove(ctx->Array.Objects, obj->Name);
   }
}
Exemplo n.º 12
0
/**
 * Remove the given array object from the array object pool.
 * Do not deallocate the array object though.
 */
void
_mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj )
{
   if (obj->Name > 0) {
      /* remove from hash table */
      _mesa_HashRemove(ctx->Shared->ArrayObjects, obj->Name);
   }
}
Exemplo n.º 13
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);
}
Exemplo n.º 14
0
Arquivo: texobj.c Projeto: RAOF/mesa
/**
 * 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);
         }
      }
   }
}
Exemplo n.º 15
0
Arquivo: vpstate.c Projeto: aosm/X11
/**
 * Delete a program and remove it from the hash table, ignoring the
 * reference count.
 * \note Called from the GL API dispatcher.
 */
void _mesa_delete_program(GLcontext *ctx, GLuint id)
{
   struct vp_program *vprog = (struct vp_program *)
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);

   if (vprog) {
      if (vprog->String)
         FREE(vprog->String);
      if (vprog->Instructions)
         FREE(vprog->Instructions);
      _mesa_HashRemove(ctx->Shared->VertexPrograms, id);
      FREE(vprog);
   }
}
Exemplo n.º 16
0
/**
 * Delete a list of programs.
 * \note Not compiled into display lists.
 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
 */
void GLAPIENTRY 
_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

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

   for (i = 0; i < n; i++) {
      if (ids[i] != 0) {
         struct program *prog = (struct program *)
            _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
         if (prog) {
            if (prog->Target == GL_VERTEX_PROGRAM_NV ||
                prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
               if (ctx->VertexProgram.Current &&
                   ctx->VertexProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgram(prog->Target, 0);
               }
            }
            else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
                     prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
               if (ctx->FragmentProgram.Current &&
                   ctx->FragmentProgram.Current->Base.Id == ids[i]) {
                  /* unbind this currently bound program */
                  _mesa_BindProgram(prog->Target, 0);
               }
            }
            else {
               _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
               return;
            }
            prog->RefCount--;
            if (prog->RefCount <= 0) {
               _mesa_delete_program(ctx, prog);
            }
            /* always remove from hash table */
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
         }
      }
   }
}
Exemplo n.º 17
0
/**
 * Free the context state related to query objects.
 */
void
_mesa_free_query_data(GLcontext *ctx)
{
    while (1) {
        GLuint id = _mesa_HashFirstEntry(ctx->Query.QueryObjects);
        if (id) {
            struct gl_query_object *q = lookup_query_object(ctx, id);
            ASSERT(q);
            delete_query_object(q);
            _mesa_HashRemove(ctx->Query.QueryObjects, id);
        }
        else {
            break;
        }
    }
    _mesa_DeleteHashTable(ctx->Query.QueryObjects);
}
Exemplo n.º 18
0
/**
 * Set ptr to point to shProg.
 * If ptr is pointing to another object, decrement its refcount (and delete
 * if refcount hits zero).
 * Then set ptr to point to shProg, incrementing its refcount.
 */
void
_mesa_reference_shader_program(struct gl_context *ctx,
                               struct gl_shader_program **ptr,
                               struct gl_shader_program *shProg)
{
   assert(ptr);
   if (*ptr == shProg) {
      /* no-op */
      return;
   }
   if (*ptr) {
      /* Unreference the old shader program */
      GLboolean deleteFlag = GL_FALSE;
      struct gl_shader_program *old = *ptr;

      ASSERT(old->RefCount > 0);
      old->RefCount--;
#if 0
      printf("ShaderProgram %p ID=%u  RefCount-- to %d\n",
             (void *) old, old->Name, old->RefCount);
#endif
      deleteFlag = (old->RefCount == 0);

      if (deleteFlag) {
	 if (old->Name != 0)
	    _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
         ctx->Driver.DeleteShaderProgram(ctx, old);
      }

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

   if (shProg) {
      shProg->RefCount++;
#if 0
      printf("ShaderProgram %p ID=%u  RefCount++ to %d\n",
             (void *) shProg, shProg->Name, shProg->RefCount);
#endif
      *ptr = shProg;
   }
}
Exemplo n.º 19
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 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);
         }
      }
   }
}
Exemplo n.º 20
0
void GLAPIENTRY
_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);

   ASSERT_OUTSIDE_BEGIN_END(ctx);
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
   /* The above doesn't fully flush the drivers in the way that a
    * glFlush does, but that is required here:
    */
   if (ctx->Driver.Flush)
      ctx->Driver.Flush(ctx);

   for (i = 0; i < n; i++) {
      if (framebuffers[i] > 0) {
	 struct gl_framebuffer *fb;
	 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
	 if (fb) {
            ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);

            /* check if deleting currently bound framebuffer object */
            if (fb == ctx->DrawBuffer) {
               /* bind default */
               ASSERT(fb->RefCount >= 2);
               _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
            }

	    /* remove from hash table immediately, to free the ID */
	    _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);

            if (fb != &DummyFramebuffer) {
               /* But the object will not be freed until it's no longer
                * bound in any context.
                */
               _mesa_unreference_framebuffer(&fb);
	    }
	 }
      }
   }
}
Exemplo n.º 21
0
void GLAPIENTRY
_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
{
   GET_CURRENT_CONTEXT(ctx);
   GLsizei i;

   FLUSH_VERTICES(ctx, 0);

   if (count < 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSamplers(count)");
      return;
   }

   mtx_lock(&ctx->Shared->Mutex);

   for (i = 0; i < count; i++) {
      if (samplers[i]) {
         GLuint j;
         struct gl_sampler_object *sampObj =
            _mesa_lookup_samplerobj(ctx, samplers[i]);
   
         if (sampObj) {
            /* If the sampler is currently bound, unbind it. */
            for (j = 0; j < ctx->Const.MaxCombinedTextureImageUnits; j++) {
               if (ctx->Texture.Unit[j].Sampler == sampObj) {
                  FLUSH_VERTICES(ctx, _NEW_TEXTURE);
                  _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[j].Sampler, NULL);
               }
            }

            /* The ID is immediately freed for re-use */
            _mesa_HashRemove(ctx->Shared->SamplerObjects, samplers[i]);
            /* But the object exists until its reference count goes to zero */
            _mesa_reference_sampler_object(ctx, &sampObj, NULL);
         }
      }
   }

   mtx_unlock(&ctx->Shared->Mutex);
}
Exemplo n.º 22
0
/**
 * Set ptr to point to sh.
 * If ptr is pointing to another shader, decrement its refcount (and delete
 * if refcount hits zero).
 * Then set ptr to point to sh, incrementing its refcount.
 */
void
_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
                       struct gl_shader *sh)
{
   assert(ptr);
   if (*ptr == sh) {
      /* no-op */
      return;
   }
   if (*ptr) {
      /* Unreference the old shader */
      GLboolean deleteFlag = GL_FALSE;
      struct gl_shader *old = *ptr;

      ASSERT(old->RefCount > 0);
      old->RefCount--;
      /*printf("SHADER DECR %p (%d) to %d\n",
        (void*) old, old->Name, old->RefCount);*/
      deleteFlag = (old->RefCount == 0);

      if (deleteFlag) {
	 if (old->Name != 0)
	    _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
         ctx->Driver.DeleteShader(ctx, old);
      }

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

   if (sh) {
      /* reference new */
      sh->RefCount++;
      /*printf("SHADER INCR %p (%d) to %d\n",
        (void*) sh, sh->Name, sh->RefCount);*/
      *ptr = sh;
   }
}
Exemplo n.º 23
0
/* XXX this could be static */
void
_mesa_reference_shader_program(GLcontext *ctx,
                               struct gl_shader_program **ptr,
                               struct gl_shader_program *shProg)
{
   assert(ptr);
   if (*ptr == shProg) {
      /* no-op */
      return;
   }
   if (*ptr) {
      /* Unreference the old shader program */
      GLboolean deleteFlag = GL_FALSE;
      struct gl_shader_program *old = *ptr;

      ASSERT(old->RefCount > 0);
      old->RefCount--;
      /*printf("SHPROG DECR %p (%d) to %d\n",
        (void*) old, old->Name, old->RefCount);*/
      deleteFlag = (old->RefCount == 0);

      if (deleteFlag) {
         _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
         _mesa_free_shader_program(ctx, old);
      }

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

   if (shProg) {
      shProg->RefCount++;
      /*printf("SHPROG INCR %p (%d) to %d\n",
        (void*) shProg, shProg->Name, shProg->RefCount);*/
      *ptr = shProg;
   }
}
Exemplo n.º 24
0
/**
 * Test walking over all the entries in a hash table.
 */
static void
test_hash_walking(void)
{
   struct _mesa_HashTable *t = _mesa_NewHashTable();
   const GLuint limit = 50000;
   GLuint i;

   /* create some entries */
   for (i = 0; i < limit; i++) {
      GLuint dummy;
      GLuint k = (rand() % (limit * 10)) + 1;
      while (_mesa_HashLookup(t, k)) {
         /* id already in use, try another */
         k = (rand() % (limit * 10)) + 1;
      }
      _mesa_HashInsert(t, k, &dummy);
   }

   /* walk over all entries */
   {
      GLuint k = _mesa_HashFirstEntry(t);
      GLuint count = 0;
      while (k) {
         GLuint knext = _mesa_HashNextEntry(t, k);
         assert(knext != k);
         _mesa_HashRemove(t, k);
         count++;
         k = knext;
      }
      assert(count == limit);
      k = _mesa_HashFirstEntry(t);
      assert(k==0);
   }

   _mesa_DeleteHashTable(t);
}
Exemplo n.º 25
0
/**
 * Bind a program (make it current)
 * \note Called from the GL API dispatcher by both glBindProgramNV
 * and glBindProgramARB.
 */
void GLAPIENTRY
_mesa_BindProgram(GLenum target, GLuint id)
{
   struct program *prog;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   /* texture state is dependent on current fragment and vertex programs */
   FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_TEXTURE);

   if ((target == GL_VERTEX_PROGRAM_NV
        && ctx->Extensions.NV_vertex_program) ||
       (target == GL_VERTEX_PROGRAM_ARB
        && ctx->Extensions.ARB_vertex_program)) {
      if (ctx->VertexProgram.Current &&
          ctx->VertexProgram.Current->Base.Id == id)
         return;
      /* decrement refcount on previously bound vertex program */
      if (ctx->VertexProgram.Current) {
         ctx->VertexProgram.Current->Base.RefCount--;
         /* and delete if refcount goes below one */
         if (ctx->VertexProgram.Current->Base.RefCount <= 0) {
            _mesa_delete_program(ctx, &(ctx->VertexProgram.Current->Base));
            _mesa_HashRemove(ctx->Shared->Programs, id);
         }
      }
   }
   else if ((target == GL_FRAGMENT_PROGRAM_NV
             && ctx->Extensions.NV_fragment_program) ||
            (target == GL_FRAGMENT_PROGRAM_ARB
             && ctx->Extensions.ARB_fragment_program)) {
      if (ctx->FragmentProgram.Current &&
          ctx->FragmentProgram.Current->Base.Id == id)
         return;
      /* decrement refcount on previously bound fragment program */
      if (ctx->FragmentProgram.Current) {
         ctx->FragmentProgram.Current->Base.RefCount--;
         /* and delete if refcount goes below one */
         if (ctx->FragmentProgram.Current->Base.RefCount <= 0) {
            _mesa_delete_program(ctx, &(ctx->FragmentProgram.Current->Base));
            _mesa_HashRemove(ctx->Shared->Programs, id);
         }
      }
   }
   else {
      _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
      return;
   }

   /* NOTE: binding to a non-existant program is not an error.
    * That's supposed to be caught in glBegin.
    */
   if (id == 0) {
      /* default program */
      prog = NULL;
      if (target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_PROGRAM_ARB)
         prog = ctx->Shared->DefaultVertexProgram;
      else
         prog = ctx->Shared->DefaultFragmentProgram;
   }
   else {
      prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
      if (prog) {
         if (prog->Target == 0) {
            /* prog was allocated with glGenProgramsNV */
            prog->Target = target;
         }
         else if (prog->Target != target) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glBindProgramNV/ARB(target mismatch)");
            return;
         }
      }
      else {
         /* allocate a new program now */
         prog = _mesa_alloc_program(ctx, target, id);
         if (!prog) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
            return;
         }
         prog->Id = id;
         prog->Target = target;
         prog->Resident = GL_TRUE;
         prog->RefCount = 1;
         _mesa_HashInsert(ctx->Shared->Programs, id, prog);
      }
   }

   /* bind now */
   if (target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_PROGRAM_ARB) {
      ctx->VertexProgram.Current = (struct vertex_program *) prog;
   }
   else if (target == GL_FRAGMENT_PROGRAM_NV || target == GL_FRAGMENT_PROGRAM_ARB) {
      ctx->FragmentProgram.Current = (struct fragment_program *) prog;
   }

   if (prog)
      prog->RefCount++;
}
Exemplo n.º 26
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 = (struct gl_texture_object *)
            _mesa_HashLookup(ctx->Shared->TexObjects, textures[i]);
         if (delObj) {
            /* First check if this texture is currently bound.
             * If so, unbind it and decrement the reference count.
             * XXX all RefCount accesses should be protected by a mutex.
             */
            GLuint u;
            for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
               struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
               if (delObj == unit->Current1D) {
                  unit->Current1D = ctx->Shared->Default1D;
                  ctx->Shared->Default1D->RefCount++;
                  delObj->RefCount--;
                  if (delObj == unit->_Current)
                     unit->_Current = unit->Current1D;
               }
               else if (delObj == unit->Current2D) {
                  unit->Current2D = ctx->Shared->Default2D;
                  ctx->Shared->Default2D->RefCount++;
                  delObj->RefCount--;
                  if (delObj == unit->_Current)
                     unit->_Current = unit->Current2D;
               }
               else if (delObj == unit->Current3D) {
                  unit->Current3D = ctx->Shared->Default3D;
                  ctx->Shared->Default3D->RefCount++;
                  delObj->RefCount--;
                  if (delObj == unit->_Current)
                     unit->_Current = unit->Current3D;
               }
               else if (delObj == unit->CurrentCubeMap) {
                  unit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
                  ctx->Shared->DefaultCubeMap->RefCount++;
                  delObj->RefCount--;
                  if (delObj == unit->_Current)
                     unit->_Current = unit->CurrentCubeMap;
               }
               else if (delObj == unit->CurrentRect) {
                  unit->CurrentRect = ctx->Shared->DefaultRect;
                  ctx->Shared->DefaultRect->RefCount++;
                  delObj->RefCount--;
                  if (delObj == unit->_Current)
                     unit->_Current = unit->CurrentRect;
               }
            }
            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);

            /* The actual texture object will not be freed until it's no
             * longer bound in any context.
             * XXX all RefCount accesses should be protected by a mutex.
             */
            delObj->RefCount--;
            if (delObj->RefCount == 0) {
               ASSERT(delObj->Name != 0); /* Never delete default tex objs */
               ASSERT(ctx->Driver.DeleteTexture);
               (*ctx->Driver.DeleteTexture)(ctx, delObj);
            }
         }
      }
   }
}
Exemplo n.º 27
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);

   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) {
         struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
         GLuint j;

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

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

         /* unbind any vertex pointers bound to this buffer */
         unbind(ctx, &arrayObj->Vertex.BufferObj, bufObj);
         unbind(ctx, &arrayObj->Weight.BufferObj, bufObj);
         unbind(ctx, &arrayObj->Normal.BufferObj, bufObj);
         unbind(ctx, &arrayObj->Color.BufferObj, bufObj);
         unbind(ctx, &arrayObj->SecondaryColor.BufferObj, bufObj);
         unbind(ctx, &arrayObj->FogCoord.BufferObj, bufObj);
         unbind(ctx, &arrayObj->Index.BufferObj, bufObj);
         unbind(ctx, &arrayObj->EdgeFlag.BufferObj, bufObj);
         for (j = 0; j < Elements(arrayObj->TexCoord); j++) {
            unbind(ctx, &arrayObj->TexCoord[j].BufferObj, bufObj);
         }
         for (j = 0; j < Elements(arrayObj->VertexAttrib); j++) {
            unbind(ctx, &arrayObj->VertexAttrib[j].BufferObj, bufObj);
         }

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

         /* unbind any pixel pack/unpack pointers bound to this buffer */
         if (ctx->Pack.BufferObj == bufObj) {
            _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 );
         }
         if (ctx->Unpack.BufferObj == bufObj) {
            _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 );
         }

         /* The ID is immediately freed for re-use */
         _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name);
         _mesa_reference_buffer_object(ctx, &bufObj, NULL);
      }
   }

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