Exemplo n.º 1
0
/**
 * Lookup a GLSL shader object.
 */
struct gl_shader *
_mesa_lookup_shader(struct gl_context *ctx, GLuint name)
{
   if (name) {
      struct gl_shader *sh = (struct gl_shader *)
         _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
      /* Note that both gl_shader and gl_shader_program objects are kept
       * in the same hash table.  Check the object's type to be sure it's
       * what we're expecting.
       */
      if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
         return NULL;
      }
      return sh;
   }
   return NULL;
}
Exemplo n.º 2
0
Arquivo: vpstate.c Projeto: aosm/X11
/**
 * Determine if id names a program.
 * \note Not compiled into display lists.
 * \note Called from the GL API dispatcher.
 * \param id is the program identifier
 * \return GL_TRUE if id is a program, else GL_FALSE.
 */
GLboolean _mesa_IsProgramNV(GLuint id)
{
   struct vp_program *vprog;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);

   if (id == 0)
      return GL_FALSE;

   vprog = (struct vp_program *)
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);

   if (vprog && vprog->Target)
      return GL_TRUE;
   else
      return GL_FALSE;
}
Exemplo n.º 3
0
/**
 * Determine if a set of programs is resident in hardware.
 * \note Not compiled into display lists.
 * \note Called from the GL API dispatcher.
 */
GLboolean GLAPIENTRY _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
                                      GLboolean *residences)
{
   GLint i, j;
   GLboolean allResident = GL_TRUE;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);

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

   for (i = 0; i < n; i++) {
      const struct program *prog;
      if (ids[i] == 0) {
         _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
         return GL_FALSE;
      }
      prog = (const struct program *)
         _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
      if (!prog) {
         _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
         return GL_FALSE;
      }
      if (prog->Resident) {
	 if (!allResident)
	    residences[i] = GL_TRUE;
      }
      else {
         if (allResident) {
	    allResident = GL_FALSE;
	    for (j = 0; j < i; j++)
	       residences[j] = GL_TRUE;
	 }
	 residences[i] = GL_FALSE;
      }
   }

   return allResident;
}
Exemplo n.º 4
0
/**
 * As above, but record an error if shader is not found.
 */
struct gl_shader *
_mesa_lookup_shader_err(struct gl_context *ctx, GLuint name, const char *caller)
{
   if (!name) {
      _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
      return NULL;
   }
   else {
      struct gl_shader *sh = (struct gl_shader *)
         _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
      if (!sh) {
         _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
         return NULL;
      }
      if (sh->Type == GL_SHADER_PROGRAM_MESA) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
         return NULL;
      }
      return sh;
   }
}
Exemplo n.º 5
0
void GLAPIENTRY
_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
                                GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
   struct program *prog;
   struct fragment_program *fragProg;
   GLfloat *v;

   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   FLUSH_VERTICES(ctx, _NEW_PROGRAM);

   prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
   if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
      return;
   }

   if (len <= 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)");
      return;
   }

   fragProg = (struct fragment_program *) prog;
   v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len,
                                    (char *) name);
   if (v) {
      v[0] = x;
      v[1] = y;
      v[2] = z;
      v[3] = w;
      return;
   }

   _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)");
}
Exemplo n.º 6
0
void GLAPIENTRY
_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
                                   GLfloat *params)
{
   struct program *prog;
   struct fragment_program *fragProg;
   const GLfloat *v;

   GET_CURRENT_CONTEXT(ctx);

   if (!ctx->_CurrentProgram)
      ASSERT_OUTSIDE_BEGIN_END(ctx);

   prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
   if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
      return;
   }

   if (len <= 0) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
      return;
   }

   fragProg = (struct fragment_program *) prog;
   v = _mesa_lookup_parameter_value(fragProg->Base.Parameters,
                                    len, (char *) name);
   if (v) {
      params[0] = v[0];
      params[1] = v[1];
      params[2] = v[2];
      params[3] = v[3];
      return;
   }

   _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
}
Exemplo n.º 7
0
Arquivo: vpstate.c Projeto: aosm/X11
/**
 * Execute a vertex state program.
 * \note Called from the GL API dispatcher.
 */
void _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
{
   struct vp_program *vprog;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (target != GL_VERTEX_STATE_PROGRAM_NV) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV");
      return;
   }

   vprog = (struct vp_program *)
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);

   if (!vprog || vprog->Target != GL_VERTEX_STATE_PROGRAM_NV) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
      return;
   }
   
   _mesa_init_vp_registers(ctx);
   _mesa_init_tracked_matrices(ctx);
   COPY_4V(ctx->VertexProgram.Machine.Registers[VP_INPUT_REG_START], params);
   _mesa_exec_program(ctx, vprog);
}
Exemplo n.º 8
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.º 9
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.º 10
0
/**
 * Return the gl_texture_object for a given ID.
 */
struct gl_texture_object *
_mesa_lookup_texture(struct gl_context *ctx, GLuint id)
{
   return (struct gl_texture_object *)
      _mesa_HashLookup(ctx->Shared->TexObjects, id);
}
Exemplo n.º 11
0
static struct gl_query_object *
lookup_query_object(GLcontext *ctx, GLuint id)
{
   return (struct gl_query_object *)
      _mesa_HashLookup(ctx->Query.QueryObjects, id);
}
Exemplo n.º 12
0
/**
 * Delete named textures.
 *
 * \param n number of textures to be deleted.
 * \param texName array of textures names to be deleted.
 *
 * \sa glDeleteTextures().
 *
 * For each texture checks if its bound to any of the texture units, unbinding
 * it and decrementing the reference count if so. If the texture reference
 * count is zero, delete its object.
 */
void GLAPIENTRY
_mesa_DeleteTextures( GLsizei n, const GLuint *texName)
{
   GET_CURRENT_CONTEXT(ctx);
   GLint i;
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */

   if (!texName)
      return;

   for (i=0;i<n;i++) {
      if (texName[i] > 0) {
         struct gl_texture_object *delObj = (struct gl_texture_object *)
            _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]);
         if (delObj) {
            /* First check if this texture is currently bound.
             * If so, unbind it and decrement the reference count.
             */
            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;

            /* Decrement reference count and delete if zero */
            delObj->RefCount--;
            ASSERT(delObj->RefCount >= 0);

            if (delObj->RefCount == 0) {
               ASSERT(delObj->Name != 0);
               _mesa_remove_texture_object(ctx, delObj);
               ASSERT(ctx->Driver.DeleteTexture);
               (*ctx->Driver.DeleteTexture)(ctx, delObj);
            }
         }
      }
   }
}
Exemplo n.º 13
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);
   GLuint unit = ctx->Texture.CurrentUnit;
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *oldTexObj;
   struct gl_texture_object *newTexObj = NULL;
   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);

   /*
    * Get pointer to currently bound texture object (oldTexObj)
    */
   switch (target) {
      case GL_TEXTURE_1D:
         oldTexObj = texUnit->Current1D;
         break;
      case GL_TEXTURE_2D:
         oldTexObj = texUnit->Current2D;
         break;
      case GL_TEXTURE_3D:
         oldTexObj = texUnit->Current3D;
         break;
      case GL_TEXTURE_CUBE_MAP_ARB:
         if (!ctx->Extensions.ARB_texture_cube_map) {
            _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
            return;
         }
         oldTexObj = texUnit->CurrentCubeMap;
         break;
      case GL_TEXTURE_RECTANGLE_NV:
         if (!ctx->Extensions.NV_texture_rectangle) {
            _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
            return;
         }
         oldTexObj = texUnit->CurrentRect;
         break;
      default:
         _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
         return;
   }

   if (oldTexObj->Name == texName)
      /* XXX this might be wrong.  If the texobj is in use by another
       * context and a texobj parameter was changed, this might be our
       * only chance to update this context's hardware state.
       */
      return;   /* rebinding the same texture- no change */

   /*
    * Get pointer to new texture object (newTexObj)
    */
   if (texName == 0) {
      /* newTexObj = a default texture object */
      switch (target) {
         case GL_TEXTURE_1D:
            newTexObj = ctx->Shared->Default1D;
            break;
         case GL_TEXTURE_2D:
            newTexObj = ctx->Shared->Default2D;
            break;
         case GL_TEXTURE_3D:
            newTexObj = ctx->Shared->Default3D;
            break;
         case GL_TEXTURE_CUBE_MAP_ARB:
            newTexObj = ctx->Shared->DefaultCubeMap;
            break;
         case GL_TEXTURE_RECTANGLE_NV:
            newTexObj = ctx->Shared->DefaultRect;
            break;
         default:
            ; /* Bad targets are caught above */
      }
   }
   else {
      /* non-default texture object */
      const struct _mesa_HashTable *hash = ctx->Shared->TexObjects;
      newTexObj = (struct gl_texture_object *) _mesa_HashLookup(hash, texName);
      if (newTexObj) {
         /* error checking */
         if (newTexObj->Target != 0 && newTexObj->Target != target) {
            /* the named texture object's dimensions don't match the target */
            _mesa_error( ctx, GL_INVALID_OPERATION,
                         "glBindTexture(wrong dimensionality)" );
            return;
         }
         if (newTexObj->Target == 0 && target == GL_TEXTURE_RECTANGLE_NV) {
            /* have to init wrap and filter state here - kind of klunky */
            newTexObj->WrapS = GL_CLAMP_TO_EDGE;
            newTexObj->WrapT = GL_CLAMP_TO_EDGE;
            newTexObj->WrapR = GL_CLAMP_TO_EDGE;
            newTexObj->MinFilter = GL_LINEAR;
            if (ctx->Driver.TexParameter) {
               static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE};
               static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR};
               (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_WRAP_S, fparam_wrap );
               (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_WRAP_T, fparam_wrap );
               (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_WRAP_R, fparam_wrap );
               (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_MIN_FILTER, fparam_filter );
            }
         }
      }
      else {
         /* 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;
   }

   /* XXX all RefCount accesses should be protected by a mutex. */
   newTexObj->RefCount++;

   /* do the actual binding, but first flush outstanding vertices:
    */
   FLUSH_VERTICES(ctx, _NEW_TEXTURE);

   switch (target) {
      case GL_TEXTURE_1D:
         texUnit->Current1D = newTexObj;
         break;
      case GL_TEXTURE_2D:
         texUnit->Current2D = newTexObj;
         break;
      case GL_TEXTURE_3D:
         texUnit->Current3D = newTexObj;
         break;
      case GL_TEXTURE_CUBE_MAP_ARB:
         texUnit->CurrentCubeMap = newTexObj;
         break;
      case GL_TEXTURE_RECTANGLE_NV:
         texUnit->CurrentRect = newTexObj;
         break;
      default:
         _mesa_problem(ctx, "bad target in BindTexture");
         return;
   }

   /* Pass BindTexture call to device driver */
   if (ctx->Driver.BindTexture)
      (*ctx->Driver.BindTexture)( ctx, target, newTexObj );

   /* Decrement the reference count on the old texture and check if it's
    * time to delete it.
    */
   /* XXX all RefCount accesses should be protected by a mutex. */
   oldTexObj->RefCount--;
   ASSERT(oldTexObj->RefCount >= 0);
   if (oldTexObj->RefCount == 0) {
      ASSERT(oldTexObj->Name != 0);
      ASSERT(ctx->Driver.DeleteTexture);
      (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
   }
}
Exemplo n.º 14
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.º 15
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++) {
      if (ids[i] != 0) {
         struct gl_buffer_object *bufObj = (struct gl_buffer_object *)
            _mesa_HashLookup(ctx->Shared->BufferObjects, ids[i]);
         if (bufObj) {
            /* unbind any vertex pointers bound to this buffer */
            GLuint j;

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

            if (ctx->Array.Vertex.BufferObj == bufObj) {
               bufObj->RefCount--;
               ctx->Array.Vertex.BufferObj = ctx->Array.NullBufferObj;
               ctx->Array.NullBufferObj->RefCount++;
            }
            if (ctx->Array.Normal.BufferObj == bufObj) {
               bufObj->RefCount--;
               ctx->Array.Normal.BufferObj = ctx->Array.NullBufferObj;
               ctx->Array.NullBufferObj->RefCount++;
            }
            if (ctx->Array.Color.BufferObj == bufObj) {
               bufObj->RefCount--;
               ctx->Array.Color.BufferObj = ctx->Array.NullBufferObj;
               ctx->Array.NullBufferObj->RefCount++;
            }
            if (ctx->Array.SecondaryColor.BufferObj == bufObj) {
               bufObj->RefCount--;
               ctx->Array.SecondaryColor.BufferObj = ctx->Array.NullBufferObj;
               ctx->Array.NullBufferObj->RefCount++;
            }
            if (ctx->Array.FogCoord.BufferObj == bufObj) {
               bufObj->RefCount--;
               ctx->Array.FogCoord.BufferObj = ctx->Array.NullBufferObj;
               ctx->Array.NullBufferObj->RefCount++;
            }
            if (ctx->Array.Index.BufferObj == bufObj) {
               bufObj->RefCount--;
               ctx->Array.Index.BufferObj = ctx->Array.NullBufferObj;
               ctx->Array.NullBufferObj->RefCount++;
            }
            if (ctx->Array.EdgeFlag.BufferObj == bufObj) {
               bufObj->RefCount--;
               ctx->Array.EdgeFlag.BufferObj = ctx->Array.NullBufferObj;
               ctx->Array.NullBufferObj->RefCount++;
            }
            for (j = 0; j < MAX_TEXTURE_UNITS; j++) {
               if (ctx->Array.TexCoord[j].BufferObj == bufObj) {
                  bufObj->RefCount--;
                  ctx->Array.TexCoord[j].BufferObj = ctx->Array.NullBufferObj;
                  ctx->Array.NullBufferObj->RefCount++;
               }
            }
            for (j = 0; j < VERT_ATTRIB_MAX; j++) {
               if (ctx->Array.VertexAttrib[j].BufferObj == bufObj) {
                  bufObj->RefCount--;
                  ctx->Array.VertexAttrib[j].BufferObj = ctx->Array.NullBufferObj;
                  ctx->Array.NullBufferObj->RefCount++;
               }
            }

            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 );
            }

            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_remove_buffer_object(ctx, bufObj);
            bufObj->RefCount--;
            if (bufObj->RefCount <= 0) {
               ASSERT(ctx->Array.ArrayBufferObj != bufObj);
               ASSERT(ctx->Array.ElementArrayBufferObj != bufObj);
               ASSERT(ctx->Array.Vertex.BufferObj != bufObj);
               ASSERT(ctx->Driver.DeleteBuffer);
               ctx->Driver.DeleteBuffer(ctx, bufObj);
            }
         }
      }
   }

   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
Exemplo n.º 16
0
void GLAPIENTRY
_mesa_BindBufferARB(GLenum target, GLuint buffer)
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_buffer_object *oldBufObj;
   struct gl_buffer_object *newBufObj = NULL;
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   oldBufObj = buffer_object_get_target( ctx, target, "BindBufferARB" );
   if (oldBufObj && oldBufObj->Name == buffer)
      return;   /* rebinding the same buffer object- no change */

   /*
    * Get pointer to new buffer object (newBufObj)
    */
   if (buffer == 0) {
      /* The spec says there's not a buffer object named 0, but we use
       * one internally because it simplifies things.
       */
      newBufObj = ctx->Array.NullBufferObj;
   }
   else {
      /* non-default buffer object */
      const struct _mesa_HashTable *hash = ctx->Shared->BufferObjects;
      newBufObj = (struct gl_buffer_object *) _mesa_HashLookup(hash, buffer);
      if (!newBufObj) {
         /* if this is a new buffer object id, allocate a buffer object now */
	 newBufObj = (*ctx->Driver.NewBufferObject)(ctx, buffer, target);
         if (!newBufObj) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB");
            return;
         }
         _mesa_save_buffer_object(ctx, newBufObj);
      }
      newBufObj->RefCount++;
   }
   
   switch (target) {
      case GL_ARRAY_BUFFER_ARB:
         ctx->Array.ArrayBufferObj = newBufObj;
         break;
      case GL_ELEMENT_ARRAY_BUFFER_ARB:
         ctx->Array.ElementArrayBufferObj = newBufObj;
         break;
      case GL_PIXEL_PACK_BUFFER_EXT:
         ctx->Pack.BufferObj = newBufObj;
         break;
      case GL_PIXEL_UNPACK_BUFFER_EXT:
         ctx->Unpack.BufferObj = newBufObj;
         break;
      default:
         _mesa_problem(ctx, "Bad target in _mesa_BindBufferARB");
         return;
   }

   /* Pass BindBuffer call to device driver */
   if (ctx->Driver.BindBuffer && newBufObj)
      (*ctx->Driver.BindBuffer)( ctx, target, newBufObj );

   if (oldBufObj) {
      oldBufObj->RefCount--;
      assert(oldBufObj->RefCount >= 0);
      if (oldBufObj->RefCount == 0) {
	 assert(oldBufObj->Name != 0);
	 ASSERT(ctx->Driver.DeleteBuffer);
	 ctx->Driver.DeleteBuffer( ctx, oldBufObj );
      }
   }
}
Exemplo n.º 17
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);
   GLuint unit = ctx->Texture.CurrentUnit;
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *oldTexObj;
   struct gl_texture_object *newTexObj = 0;
   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);

   switch (target) {
      case GL_TEXTURE_1D:
         oldTexObj = texUnit->Current1D;
         break;
      case GL_TEXTURE_2D:
         oldTexObj = texUnit->Current2D;
         break;
      case GL_TEXTURE_3D:
         oldTexObj = texUnit->Current3D;
         break;
      case GL_TEXTURE_CUBE_MAP_ARB:
         if (!ctx->Extensions.ARB_texture_cube_map) {
            _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
            return;
         }
         oldTexObj = texUnit->CurrentCubeMap;
         break;
      case GL_TEXTURE_RECTANGLE_NV:
         if (!ctx->Extensions.NV_texture_rectangle) {
            _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
            return;
         }
         oldTexObj = texUnit->CurrentRect;
         break;
      default:
         _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
         return;
   }

   if (oldTexObj->Name == texName)
      return;   /* rebinding the same texture- no change */

   /*
    * Get pointer to new texture object (newTexObj)
    */
   if (texName == 0) {
      /* newTexObj = a default texture object */
      switch (target) {
         case GL_TEXTURE_1D:
            newTexObj = ctx->Shared->Default1D;
            break;
         case GL_TEXTURE_2D:
            newTexObj = ctx->Shared->Default2D;
            break;
         case GL_TEXTURE_3D:
            newTexObj = ctx->Shared->Default3D;
            break;
         case GL_TEXTURE_CUBE_MAP_ARB:
            newTexObj = ctx->Shared->DefaultCubeMap;
            break;
         case GL_TEXTURE_RECTANGLE_NV:
            newTexObj = ctx->Shared->DefaultRect;
            break;
         default:
            ; /* Bad targets are caught above */
      }
   }
   else {
      /* non-default texture object */
      const struct _mesa_HashTable *hash = ctx->Shared->TexObjects;
      newTexObj = (struct gl_texture_object *) _mesa_HashLookup(hash, texName);
      if (newTexObj) {
         /* error checking */
         if (newTexObj->Target != 0 && newTexObj->Target != target) {
            /* the named texture object's dimensions don't match the target */
            _mesa_error( ctx, GL_INVALID_OPERATION,
                         "glBindTexture(wrong dimensionality)" );
            return;
         }
         if (newTexObj->Target == 0 && target == GL_TEXTURE_RECTANGLE_NV) {
            /* have to init wrap and filter state here - kind of klunky */
            newTexObj->WrapS = GL_CLAMP_TO_EDGE;
            newTexObj->WrapT = GL_CLAMP_TO_EDGE;
            newTexObj->WrapR = GL_CLAMP_TO_EDGE;
            newTexObj->MinFilter = GL_LINEAR;
         }
      }
      else {
         /* 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;
         }
         _mesa_save_texture_object(ctx, newTexObj);
      }
      newTexObj->Target = target;
   }

   newTexObj->RefCount++;

   /* do the actual binding, but first flush outstanding vertices:
    */
   FLUSH_VERTICES(ctx, _NEW_TEXTURE);

   switch (target) {
      case GL_TEXTURE_1D:
         texUnit->Current1D = newTexObj;
         break;
      case GL_TEXTURE_2D:
         texUnit->Current2D = newTexObj;
         break;
      case GL_TEXTURE_3D:
         texUnit->Current3D = newTexObj;
         break;
      case GL_TEXTURE_CUBE_MAP_ARB:
         texUnit->CurrentCubeMap = newTexObj;
         break;
      case GL_TEXTURE_RECTANGLE_NV:
         texUnit->CurrentRect = newTexObj;
         break;
      default:
         _mesa_problem(ctx, "bad target in BindTexture");
         return;
   }

   /* Pass BindTexture call to device driver */
   if (ctx->Driver.BindTexture)
      (*ctx->Driver.BindTexture)( ctx, target, newTexObj );

   oldTexObj->RefCount--;
   assert(oldTexObj->RefCount >= 0);
   if (oldTexObj->RefCount == 0) {
      assert(oldTexObj->Name != 0);
      _mesa_remove_texture_object(ctx, oldTexObj);
      ASSERT(ctx->Driver.DeleteTexture);
      (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
   }
}