New device driver hooks for texture object and texture image creation to

allow drivers to implement C++-like inheritance via containment.
Lots of assorted clean-ups related to texture objects.
This commit is contained in:
Brian Paul
2003-04-01 16:41:50 +00:00
parent 926c34f894
commit a3f137094c
9 changed files with 491 additions and 395 deletions

View File

@@ -1,4 +1,4 @@
/* $Id: osmesa.c,v 1.101 2003/03/04 19:16:47 brianp Exp $ */ /* $Id: osmesa.c,v 1.102 2003/04/01 16:41:57 brianp Exp $ */
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
@@ -47,6 +47,7 @@
#include "matrix.h" #include "matrix.h"
#include "mtypes.h" #include "mtypes.h"
#include "texformat.h" #include "texformat.h"
#include "texobj.h"
#include "texstore.h" #include "texstore.h"
#include "array_cache/acache.h" #include "array_cache/acache.h"
#include "swrast/swrast.h" #include "swrast/swrast.h"
@@ -648,7 +649,7 @@ hook_in_driver_functions( GLcontext *ctx )
ctx->Driver.Accum = _swrast_Accum; ctx->Driver.Accum = _swrast_Accum;
ctx->Driver.Bitmap = _swrast_Bitmap; ctx->Driver.Bitmap = _swrast_Bitmap;
ctx->Driver.Clear = clear; /* = _swrast_Clear */ ctx->Driver.Clear = clear; /* uses _swrast_Clear */
ctx->Driver.CopyPixels = _swrast_CopyPixels; ctx->Driver.CopyPixels = _swrast_CopyPixels;
ctx->Driver.DrawPixels = _swrast_DrawPixels; ctx->Driver.DrawPixels = _swrast_DrawPixels;
ctx->Driver.ReadPixels = _swrast_ReadPixels; ctx->Driver.ReadPixels = _swrast_ReadPixels;
@@ -670,6 +671,9 @@ hook_in_driver_functions( GLcontext *ctx )
ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d; ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d; ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
ctx->Driver.NewTextureObject = _mesa_new_texture_object;
ctx->Driver.DeleteTexture = _mesa_delete_texture_object;
ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;

View File

@@ -1,4 +1,4 @@
/* $Id: xm_dd.c,v 1.45 2003/03/27 17:51:33 brianp Exp $ */ /* $Id: xm_dd.c,v 1.46 2003/04/01 16:41:58 brianp Exp $ */
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
@@ -965,6 +965,9 @@ void xmesa_init_pointers( GLcontext *ctx )
ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
ctx->Driver.NewTextureObject = _mesa_new_texture_object;
ctx->Driver.DeleteTexture = _mesa_delete_texture_object;
ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d; ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d; ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d; ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;

View File

@@ -1,4 +1,4 @@
/* $Id: context.c,v 1.194 2003/03/01 01:50:20 brianp Exp $ */ /* $Id: context.c,v 1.195 2003/04/01 16:41:50 brianp Exp $ */
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
@@ -637,15 +637,14 @@ free_matrix_stack( struct matrix_stack *stack )
/* /*
* Allocate and initialize a shared context state structure. * Allocate and initialize a shared context state structure.
*/ */
static struct gl_shared_state * static GLboolean
alloc_shared_state( void ) alloc_shared_state( GLcontext *ctx )
{ {
struct gl_shared_state *ss; struct gl_shared_state *ss = CALLOC_STRUCT(gl_shared_state);
GLboolean outOfMemory;
ss = CALLOC_STRUCT(gl_shared_state);
if (!ss) if (!ss)
return NULL; return GL_FALSE;
ctx->Shared = ss;
_glthread_INIT_MUTEX(ss->Mutex); _glthread_INIT_MUTEX(ss->Mutex);
@@ -655,64 +654,66 @@ alloc_shared_state( void )
ss->Programs = _mesa_NewHashTable(); ss->Programs = _mesa_NewHashTable();
#endif #endif
/* Default Texture objects */ ss->Default1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
outOfMemory = GL_FALSE; if (!ss->Default1D)
goto cleanup;
ss->Default1D = _mesa_alloc_texture_object(ss, 0, GL_TEXTURE_1D); ss->Default2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D);
if (!ss->Default1D) { if (!ss->Default2D)
outOfMemory = GL_TRUE; goto cleanup;
}
ss->Default2D = _mesa_alloc_texture_object(ss, 0, GL_TEXTURE_2D); ss->Default3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D);
if (!ss->Default2D) { if (!ss->Default3D)
outOfMemory = GL_TRUE; goto cleanup;
}
ss->Default3D = _mesa_alloc_texture_object(ss, 0, GL_TEXTURE_3D); ss->DefaultCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB);
if (!ss->Default3D) { if (!ss->DefaultCubeMap)
outOfMemory = GL_TRUE; goto cleanup;
}
ss->DefaultCubeMap = _mesa_alloc_texture_object(ss, 0, ss->DefaultRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV);
GL_TEXTURE_CUBE_MAP_ARB); if (!ss->DefaultRect)
if (!ss->DefaultCubeMap) { goto cleanup;
outOfMemory = GL_TRUE;
}
ss->DefaultRect = _mesa_alloc_texture_object(ss, 0, #if 0
GL_TEXTURE_RECTANGLE_NV); _mesa_save_texture_object(ctx, ss->Default1D);
if (!ss->DefaultRect) { _mesa_save_texture_object(ctx, ss->Default2D);
outOfMemory = GL_TRUE; _mesa_save_texture_object(ctx, ss->Default3D);
} _mesa_save_texture_object(ctx, ss->DefaultCubeMap);
_mesa_save_texture_object(ctx, ss->DefaultRect);
if (!ss->DisplayList || !ss->TexObjects
#if FEATURE_NV_vertex_program
|| !ss->Programs
#endif #endif
|| outOfMemory) {
/* Effectively bind the default textures to all texture units */
ss->Default1D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
ss->Default2D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
ss->Default3D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
ss->DefaultCubeMap->RefCount += MAX_TEXTURE_IMAGE_UNITS;
ss->DefaultRect->RefCount += MAX_TEXTURE_IMAGE_UNITS;
return GL_TRUE;
cleanup:
/* Ran out of memory at some point. Free everything and return NULL */ /* Ran out of memory at some point. Free everything and return NULL */
if (ss->DisplayList) if (ss->DisplayList)
_mesa_DeleteHashTable(ss->DisplayList); _mesa_DeleteHashTable(ss->DisplayList);
if (ss->TexObjects) if (ss->TexObjects)
_mesa_DeleteHashTable(ss->TexObjects); _mesa_DeleteHashTable(ss->TexObjects);
#if FEATURE_NV_vertex_program
if (ss->Programs) if (ss->Programs)
_mesa_DeleteHashTable(ss->Programs); _mesa_DeleteHashTable(ss->Programs);
#endif
if (ss->Default1D) if (ss->Default1D)
_mesa_free_texture_object(ss, ss->Default1D); (*ctx->Driver.DeleteTexture)(ctx, ss->Default1D);
if (ss->Default2D) if (ss->Default2D)
_mesa_free_texture_object(ss, ss->Default2D); (*ctx->Driver.DeleteTexture)(ctx, ss->Default2D);
if (ss->Default3D) if (ss->Default3D)
_mesa_free_texture_object(ss, ss->Default3D); (*ctx->Driver.DeleteTexture)(ctx, ss->Default3D);
if (ss->DefaultCubeMap) if (ss->DefaultCubeMap)
_mesa_free_texture_object(ss, ss->DefaultCubeMap); (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultCubeMap);
if (ss->DefaultRect) if (ss->DefaultRect)
_mesa_free_texture_object(ss, ss->DefaultRect); (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultRect);
FREE(ss); if (ss)
return NULL; _mesa_free(ss);
} return GL_FALSE;
else {
return ss;
}
} }
@@ -735,11 +736,19 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
_mesa_DeleteHashTable(ss->DisplayList); _mesa_DeleteHashTable(ss->DisplayList);
/* Free texture objects */ /* Free texture objects */
while (ss->TexObjectList) { ASSERT(ctx->Driver.DeleteTexture);
if (ctx->Driver.DeleteTexture) while (1) {
(*ctx->Driver.DeleteTexture)( ctx, ss->TexObjectList ); GLuint texName = _mesa_HashFirstEntry(ss->TexObjects);
/* this function removes from linked list too! */ if (texName) {
_mesa_free_texture_object(ss, ss->TexObjectList); struct gl_texture_object *texObj = (struct gl_texture_object *)
_mesa_HashLookup(ss->TexObjects, texName);
ASSERT(texObj);
(*ctx->Driver.DeleteTexture)(ctx, texObj);
_mesa_HashRemove(ss->TexObjects, texName);
}
else {
break;
}
} }
_mesa_DeleteHashTable(ss->TexObjects); _mesa_DeleteHashTable(ss->TexObjects);
@@ -1529,99 +1538,48 @@ init_attrib_groups( GLcontext *ctx )
/* /**
* Allocate the proxy textures. If we run out of memory part way through * Allocate the proxy textures for the given context.
* the allocations clean up and return GL_FALSE. * \param ctx the context to allocate proxies for.
* Return: GL_TRUE=success, GL_FALSE=failure * \return GL_TRUE if success, GL_FALSE if failure.
*/ */
static GLboolean static GLboolean
alloc_proxy_textures( GLcontext *ctx ) alloc_proxy_textures( GLcontext *ctx )
{ {
GLboolean out_of_memory; ctx->Texture.Proxy1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
GLint i; if (!ctx->Texture.Proxy1D)
goto cleanup;
ctx->Texture.Proxy1D = _mesa_alloc_texture_object(NULL, 0, GL_TEXTURE_1D); ctx->Texture.Proxy2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D);
if (!ctx->Texture.Proxy1D) { if (!ctx->Texture.Proxy2D)
return GL_FALSE; goto cleanup;
}
ctx->Texture.Proxy2D = _mesa_alloc_texture_object(NULL, 0, GL_TEXTURE_2D); ctx->Texture.Proxy3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D);
if (!ctx->Texture.Proxy2D) { if (!ctx->Texture.Proxy3D)
_mesa_free_texture_object(NULL, ctx->Texture.Proxy1D); goto cleanup;
return GL_FALSE;
}
ctx->Texture.Proxy3D = _mesa_alloc_texture_object(NULL, 0, GL_TEXTURE_3D); ctx->Texture.ProxyCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB);
if (!ctx->Texture.Proxy3D) { if (!ctx->Texture.ProxyCubeMap)
_mesa_free_texture_object(NULL, ctx->Texture.Proxy1D); goto cleanup;
_mesa_free_texture_object(NULL, ctx->Texture.Proxy2D);
return GL_FALSE;
}
ctx->Texture.ProxyCubeMap = _mesa_alloc_texture_object(NULL, 0, ctx->Texture.ProxyRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV);
GL_TEXTURE_CUBE_MAP_ARB); if (!ctx->Texture.ProxyRect)
if (!ctx->Texture.ProxyCubeMap) { goto cleanup;
_mesa_free_texture_object(NULL, ctx->Texture.Proxy1D);
_mesa_free_texture_object(NULL, ctx->Texture.Proxy2D);
_mesa_free_texture_object(NULL, ctx->Texture.Proxy3D);
return GL_FALSE;
}
ctx->Texture.ProxyRect = _mesa_alloc_texture_object(NULL, 0,
GL_TEXTURE_RECTANGLE_NV);
if (!ctx->Texture.ProxyRect) {
_mesa_free_texture_object(NULL, ctx->Texture.Proxy1D);
_mesa_free_texture_object(NULL, ctx->Texture.Proxy2D);
_mesa_free_texture_object(NULL, ctx->Texture.Proxy3D);
_mesa_free_texture_object(NULL, ctx->Texture.ProxyCubeMap);
return GL_FALSE;
}
out_of_memory = GL_FALSE;
for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
ctx->Texture.Proxy1D->Image[i] = _mesa_alloc_texture_image();
ctx->Texture.Proxy2D->Image[i] = _mesa_alloc_texture_image();
ctx->Texture.Proxy3D->Image[i] = _mesa_alloc_texture_image();
ctx->Texture.ProxyCubeMap->Image[i] = _mesa_alloc_texture_image();
if (!ctx->Texture.Proxy1D->Image[i]
|| !ctx->Texture.Proxy2D->Image[i]
|| !ctx->Texture.Proxy3D->Image[i]
|| !ctx->Texture.ProxyCubeMap->Image[i]) {
out_of_memory = GL_TRUE;
}
}
ctx->Texture.ProxyRect->Image[0] = _mesa_alloc_texture_image();
if (!ctx->Texture.ProxyRect->Image[0])
out_of_memory = GL_TRUE;
if (out_of_memory) {
for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
if (ctx->Texture.Proxy1D->Image[i]) {
_mesa_free_texture_image(ctx->Texture.Proxy1D->Image[i]);
}
if (ctx->Texture.Proxy2D->Image[i]) {
_mesa_free_texture_image(ctx->Texture.Proxy2D->Image[i]);
}
if (ctx->Texture.Proxy3D->Image[i]) {
_mesa_free_texture_image(ctx->Texture.Proxy3D->Image[i]);
}
if (ctx->Texture.ProxyCubeMap->Image[i]) {
_mesa_free_texture_image(ctx->Texture.ProxyCubeMap->Image[i]);
}
}
if (ctx->Texture.ProxyRect->Image[0]) {
_mesa_free_texture_image(ctx->Texture.ProxyRect->Image[0]);
}
_mesa_free_texture_object(NULL, ctx->Texture.Proxy1D);
_mesa_free_texture_object(NULL, ctx->Texture.Proxy2D);
_mesa_free_texture_object(NULL, ctx->Texture.Proxy3D);
_mesa_free_texture_object(NULL, ctx->Texture.ProxyCubeMap);
_mesa_free_texture_object(NULL, ctx->Texture.ProxyRect);
return GL_FALSE;
}
else {
return GL_TRUE; return GL_TRUE;
}
cleanup:
if (ctx->Texture.Proxy1D)
(ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D);
if (ctx->Texture.Proxy2D)
(ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D);
if (ctx->Texture.Proxy3D)
(ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D);
if (ctx->Texture.ProxyCubeMap)
(ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap);
if (ctx->Texture.ProxyRect)
(ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect);
return GL_FALSE;
} }
@@ -1695,14 +1653,23 @@ _mesa_initialize_context( GLcontext *ctx,
ctx->DrawBuffer = NULL; ctx->DrawBuffer = NULL;
ctx->ReadBuffer = NULL; ctx->ReadBuffer = NULL;
/* Set these pointers to defaults now in case they're not set since
* we need them while creating the default textures.
*/
if (!ctx->Driver.NewTextureObject)
ctx->Driver.NewTextureObject = _mesa_new_texture_object;
if (!ctx->Driver.DeleteTexture)
ctx->Driver.DeleteTexture = _mesa_delete_texture_object;
if (!ctx->Driver.NewTextureImage)
ctx->Driver.NewTextureImage = _mesa_new_texture_image;
if (share_list) { if (share_list) {
/* share state with another context */ /* share state with another context */
ctx->Shared = share_list->Shared; ctx->Shared = share_list->Shared;
} }
else { else {
/* allocate new, unshared state */ /* allocate new, unshared state */
ctx->Shared = alloc_shared_state(); if (!alloc_shared_state( ctx )) {
if (!ctx->Shared) {
return GL_FALSE; return GL_FALSE;
} }
} }
@@ -1710,13 +1677,6 @@ _mesa_initialize_context( GLcontext *ctx,
ctx->Shared->RefCount++; ctx->Shared->RefCount++;
_glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
/* Effectively bind the default textures to all texture units */
ctx->Shared->Default1D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
ctx->Shared->Default2D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
ctx->Shared->Default3D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_IMAGE_UNITS;
ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_IMAGE_UNITS;
init_attrib_groups( ctx ); init_attrib_groups( ctx );
if (visual->doubleBufferMode) { if (visual->doubleBufferMode) {
@@ -1837,6 +1797,7 @@ _mesa_initialize_context( GLcontext *ctx,
_glapi_add_entrypoint("glGetFenceivNV", 651); _glapi_add_entrypoint("glGetFenceivNV", 651);
_glapi_add_entrypoint("glFinishFenceNV", 652); _glapi_add_entrypoint("glFinishFenceNV", 652);
_glapi_add_entrypoint("glSetFenceNV", 653); _glapi_add_entrypoint("glSetFenceNV", 653);
/* XXX add NV_fragment_program and ARB_vertex_program functions */
/* Find the larger of Mesa's dispatch table and libGL's dispatch table. /* Find the larger of Mesa's dispatch table and libGL's dispatch table.
* In practice, this'll be the same for stand-alone Mesa. But for DRI * In practice, this'll be the same for stand-alone Mesa. But for DRI
@@ -1997,11 +1958,11 @@ _mesa_free_context_data( GLcontext *ctx )
FREE( ctx->_ShineTabList ); FREE( ctx->_ShineTabList );
/* Free proxy texture objects */ /* Free proxy texture objects */
_mesa_free_texture_object( NULL, ctx->Texture.Proxy1D ); (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D );
_mesa_free_texture_object( NULL, ctx->Texture.Proxy2D ); (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D );
_mesa_free_texture_object( NULL, ctx->Texture.Proxy3D ); (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D );
_mesa_free_texture_object( NULL, ctx->Texture.ProxyCubeMap ); (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap );
_mesa_free_texture_object( NULL, ctx->Texture.ProxyRect ); (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect );
for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
_mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable ); _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );

View File

@@ -1,4 +1,4 @@
/* $Id: dd.h,v 1.74 2002/10/11 17:41:04 brianp Exp $ */ /* $Id: dd.h,v 1.75 2003/04/01 16:41:52 brianp Exp $ */
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
@@ -51,7 +51,6 @@ struct gl_pixelstore_attrib;
* Device Driver function table. * Device Driver function table.
*/ */
struct dd_function_table { struct dd_function_table {
const GLubyte * (*GetString)( GLcontext *ctx, GLenum name ); const GLubyte * (*GetString)( GLcontext *ctx, GLenum name );
/* Return a string as needed by glGetString(). /* Return a string as needed by glGetString().
* Only the GL_RENDERER token must be implemented. Otherwise, * Only the GL_RENDERER token must be implemented. Otherwise,
@@ -354,8 +353,12 @@ struct dd_function_table {
/* Called by glBindTexture(). /* Called by glBindTexture().
*/ */
void (*CreateTexture)( GLcontext *ctx, struct gl_texture_object *tObj ); struct gl_texture_object * (*NewTextureObject)( GLcontext *ctx, GLuint name,
/* Called when a texture object is created. GLenum target );
/* Called to allocate a new texture object.
* NOTE: this function pointer should be initialized by drivers _BEFORE_
* calling _mesa_initialize_context() since context initialization involves
* allocating some texture objects!
*/ */
void (*DeleteTexture)( GLcontext *ctx, struct gl_texture_object *tObj ); void (*DeleteTexture)( GLcontext *ctx, struct gl_texture_object *tObj );
@@ -363,6 +366,10 @@ struct dd_function_table {
* should free anything attached to the DriverData pointers. * should free anything attached to the DriverData pointers.
*/ */
struct gl_texture_image * (*NewTextureImage)( GLcontext *ctx );
/* Called to allocate a new texture image object.
*/
GLboolean (*IsTextureResident)( GLcontext *ctx, GLboolean (*IsTextureResident)( GLcontext *ctx,
struct gl_texture_object *t ); struct gl_texture_object *t );
/* Called by glAreTextureResident(). /* Called by glAreTextureResident().

View File

@@ -1,4 +1,4 @@
/* $Id: teximage.c,v 1.126 2003/03/01 01:50:22 brianp Exp $ */ /* $Id: teximage.c,v 1.127 2003/04/01 16:41:53 brianp Exp $ */
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
@@ -415,19 +415,26 @@ _mesa_set_tex_image(struct gl_texture_object *tObj,
/* /**
* Return new gl_texture_image struct with all fields initialized to zero. * Return new gl_texture_image struct with all fields initialized to zero.
* Called via ctx->Driver.NewTextureImage() unless overriden by a device
* driver.
*/ */
struct gl_texture_image * struct gl_texture_image *
_mesa_alloc_texture_image( void ) _mesa_new_texture_image( GLcontext *ctx )
{ {
(void) ctx;
return CALLOC_STRUCT(gl_texture_image); return CALLOC_STRUCT(gl_texture_image);
} }
/**
* Delete/free the given texture image and associated image data if it's not
* marked as client data.
*/
void void
_mesa_free_texture_image( struct gl_texture_image *teximage ) _mesa_delete_texture_image( struct gl_texture_image *teximage )
{ {
if (teximage->Data && !teximage->IsClientData) { if (teximage->Data && !teximage->IsClientData) {
MESA_PBUFFER_FREE( teximage->Data ); MESA_PBUFFER_FREE( teximage->Data );
@@ -577,6 +584,118 @@ _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
} }
/**
* Like _mesa_select_tex_image() but if the image doesn't exist, allocate
* it and install it. Only return NULL if passed a bad parameter or run
* out of memory.
*/
struct gl_texture_image *
_mesa_get_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
GLenum target, GLint level)
{
struct gl_texture_image *texImage;
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (!texImage) {
struct gl_texture_object *texObj;
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
return NULL;
}
texObj = _mesa_select_tex_object(ctx, texUnit, target);
ASSERT(texObj);
_mesa_set_tex_image(texObj, target, level, texImage);
}
return texImage;
}
/**
* Return pointer to the specified proxy texture image.
* Note that proxy textures are per-context, not per-texture unit.
* \return pointer to texture image or NULL if invalid target, invalid
* level, or out of memory.
*/
struct gl_texture_image *
_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
{
struct gl_texture_image *texImage;
if (level < 0 )
return NULL;
switch (target) {
case GL_PROXY_TEXTURE_1D:
if (level >= ctx->Const.MaxTextureLevels)
return NULL;
texImage = ctx->Texture.Proxy1D->Image[level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.Proxy1D->Image[level] = texImage;
}
return texImage;
case GL_PROXY_TEXTURE_2D:
if (level >= ctx->Const.MaxTextureLevels)
return NULL;
texImage = ctx->Texture.Proxy2D->Image[level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.Proxy2D->Image[level] = texImage;
}
return texImage;
case GL_PROXY_TEXTURE_3D:
if (level >= ctx->Const.Max3DTextureLevels)
return NULL;
texImage = ctx->Texture.Proxy3D->Image[level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.Proxy3D->Image[level] = texImage;
}
return texImage;
case GL_PROXY_TEXTURE_CUBE_MAP:
if (level >= ctx->Const.MaxCubeTextureLevels)
return NULL;
texImage = ctx->Texture.ProxyCubeMap->Image[level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.ProxyCubeMap->Image[level] = texImage;
}
return texImage;
case GL_PROXY_TEXTURE_RECTANGLE_NV:
if (level > 0)
return NULL;
texImage = ctx->Texture.ProxyRect->Image[level];
if (!texImage) {
texImage = ctx->Driver.NewTextureImage(ctx);
if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
return NULL;
}
ctx->Texture.ProxyRect->Image[level] = texImage;
}
return texImage;
default:
return NULL;
}
}
/* /*
* Return the maximum number of allows mipmap levels for the given * Return the maximum number of allows mipmap levels for the given
* texture target. * texture target.
@@ -1167,10 +1286,8 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
if (destTex->IsCompressed) { if (destTex->IsCompressed) {
const struct gl_texture_unit *texUnit; const struct gl_texture_unit *texUnit;
const struct gl_texture_object *texObj;
const struct gl_texture_image *texImage; const struct gl_texture_image *texImage;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) { if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
@@ -1637,16 +1754,12 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
texImage = _mesa_alloc_texture_image();
texObj->Image[level] = texImage;
if (!texImage) { if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
return; return;
} }
}
else if (texImage->Data && !texImage->IsClientData) { else if (texImage->Data && !texImage->IsClientData) {
/* free the old texture data */ /* free the old texture data */
MESA_PBUFFER_FREE(texImage->Data); MESA_PBUFFER_FREE(texImage->Data);
@@ -1690,9 +1803,10 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
} }
if (error) { if (error) {
/* if error, clear all proxy texture image parameters */ /* if error, clear all proxy texture image parameters */
if (level >= 0 && level < ctx->Const.MaxTextureLevels) { struct gl_texture_image *texImage;
clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]); texImage = _mesa_get_proxy_tex_image(ctx, target, level);
} if (texImage)
clear_teximage_fields(texImage);
} }
else { else {
/* no error, set the tex image parameters */ /* no error, set the tex image parameters */
@@ -1746,16 +1860,11 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
texImage = _mesa_alloc_texture_image();
_mesa_set_tex_image(texObj, target, level, texImage);
if (!texImage) { if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return; return;
} }
}
else if (texImage->Data && !texImage->IsClientData) { else if (texImage->Data && !texImage->IsClientData) {
/* free the old texture data */ /* free the old texture data */
MESA_PBUFFER_FREE(texImage->Data); MESA_PBUFFER_FREE(texImage->Data);
@@ -1803,12 +1912,11 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
} }
if (error) { if (error) {
/* if error, clear all proxy texture image parameters */ /* if error, clear all proxy texture image parameters */
const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ? struct gl_texture_image *texImage;
ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels; texImage = _mesa_get_proxy_tex_image(ctx, target, level);
if (level >= 0 && level < maxLevels) { if (texImage)
clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]); clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
} }
}
else { else {
/* no error, set the tex image parameters */ /* no error, set the tex image parameters */
struct gl_texture_unit *texUnit; struct gl_texture_unit *texUnit;
@@ -1852,16 +1960,11 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
texImage = _mesa_alloc_texture_image();
texObj->Image[level] = texImage;
if (!texImage) { if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
return; return;
} }
}
else if (texImage->Data && !texImage->IsClientData) { else if (texImage->Data && !texImage->IsClientData) {
MESA_PBUFFER_FREE(texImage->Data); MESA_PBUFFER_FREE(texImage->Data);
} }
@@ -1904,9 +2007,10 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
} }
if (error) { if (error) {
/* if error, clear all proxy texture image parameters */ /* if error, clear all proxy texture image parameters */
if (level >= 0 && level < ctx->Const.Max3DTextureLevels) { struct gl_texture_image *texImage;
clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]); texImage = _mesa_get_proxy_tex_image(ctx, target, level);
} if (texImage)
clear_teximage_fields(texImage);
} }
else { else {
/* no error, set the tex image parameters */ /* no error, set the tex image parameters */
@@ -2102,15 +2206,11 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
texImage = _mesa_alloc_texture_image();
_mesa_set_tex_image(texObj, target, level, texImage);
if (!texImage) { if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
return; return;
} }
}
else if (texImage->Data && !texImage->IsClientData) { else if (texImage->Data && !texImage->IsClientData) {
/* free the old texture data */ /* free the old texture data */
MESA_PBUFFER_FREE(texImage->Data); MESA_PBUFFER_FREE(texImage->Data);
@@ -2166,15 +2266,11 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
texImage = _mesa_alloc_texture_image();
_mesa_set_tex_image(texObj, target, level, texImage);
if (!texImage) { if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
return; return;
} }
}
else if (texImage->Data && !texImage->IsClientData) { else if (texImage->Data && !texImage->IsClientData) {
/* free the old texture data */ /* free the old texture data */
MESA_PBUFFER_FREE(texImage->Data); MESA_PBUFFER_FREE(texImage->Data);
@@ -2228,6 +2324,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
/* If we have a border, xoffset=-1 is legal. Bias by border width */ /* If we have a border, xoffset=-1 is legal. Bias by border width */
xoffset += texImage->Border; xoffset += texImage->Border;
@@ -2264,6 +2361,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
/* If we have a border, xoffset=-1 is legal. Bias by border width */ /* If we have a border, xoffset=-1 is legal. Bias by border width */
xoffset += texImage->Border; xoffset += texImage->Border;
@@ -2302,6 +2400,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
ASSERT(texImage);
/* If we have a border, xoffset=-1 is legal. Bias by border width */ /* If we have a border, xoffset=-1 is legal. Bias by border width */
xoffset += texImage->Border; xoffset += texImage->Border;
@@ -2509,16 +2608,11 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
texImage = _mesa_alloc_texture_image();
texObj->Image[level] = texImage;
if (!texImage) { if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
return; return;
} }
}
else if (texImage->Data && !texImage->IsClientData) { else if (texImage->Data && !texImage->IsClientData) {
MESA_PBUFFER_FREE(texImage->Data); MESA_PBUFFER_FREE(texImage->Data);
} }
@@ -2549,9 +2643,10 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
} }
if (error) { if (error) {
/* if error, clear all proxy texture image parameters */ /* if error, clear all proxy texture image parameters */
if (level >= 0 && level < ctx->Const.MaxTextureLevels) { struct gl_texture_image *texImage;
clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]); texImage = _mesa_get_proxy_tex_image(ctx, target, level);
} if (texImage)
clear_teximage_fields(texImage);
} }
else { else {
/* store the teximage parameters */ /* store the teximage parameters */
@@ -2595,16 +2690,11 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
texImage = _mesa_alloc_texture_image();
texObj->Image[level] = texImage;
if (!texImage) { if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
return; return;
} }
}
else if (texImage->Data && !texImage->IsClientData) { else if (texImage->Data && !texImage->IsClientData) {
MESA_PBUFFER_FREE(texImage->Data); MESA_PBUFFER_FREE(texImage->Data);
} }
@@ -2637,11 +2727,10 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
} }
if (error) { if (error) {
/* if error, clear all proxy texture image parameters */ /* if error, clear all proxy texture image parameters */
const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ? struct gl_texture_image *texImage;
ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels; texImage = _mesa_get_proxy_tex_image(ctx, target, level);
if (level >= 0 && level < maxLevels) { if (texImage)
clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]); clear_teximage_fields(texImage);
}
} }
else { else {
/* store the teximage parameters */ /* store the teximage parameters */
@@ -2682,16 +2771,11 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target); texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level); texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
texImage = _mesa_alloc_texture_image();
texObj->Image[level] = texImage;
if (!texImage) { if (!texImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
return; return;
} }
}
else if (texImage->Data && !texImage->IsClientData) { else if (texImage->Data && !texImage->IsClientData) {
MESA_PBUFFER_FREE(texImage->Data); MESA_PBUFFER_FREE(texImage->Data);
} }
@@ -2723,9 +2807,10 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
} }
if (error) { if (error) {
/* if error, clear all proxy texture image parameters */ /* if error, clear all proxy texture image parameters */
if (level >= 0 && level < ctx->Const.Max3DTextureLevels) { struct gl_texture_image *texImage;
clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]); texImage = _mesa_get_proxy_tex_image(ctx, target, level);
} if (texImage)
clear_teximage_fields(texImage);
} }
else { else {
/* store the teximage parameters */ /* store the teximage parameters */

View File

@@ -1,4 +1,4 @@
/* $Id: teximage.h,v 1.22 2002/10/18 18:03:07 brianp Exp $ */ /* $Id: teximage.h,v 1.23 2003/04/01 16:41:54 brianp Exp $ */
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
@@ -40,11 +40,11 @@ _mesa_base_tex_format( GLcontext *ctx, GLint format );
extern struct gl_texture_image * extern struct gl_texture_image *
_mesa_alloc_texture_image( void ); _mesa_new_texture_image( GLcontext *ctx );
extern void extern void
_mesa_free_texture_image( struct gl_texture_image *teximage ); _mesa_delete_texture_image( struct gl_texture_image *teximage );
extern void extern void
@@ -70,6 +70,15 @@ _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
GLenum target, GLint level); GLenum target, GLint level);
extern struct gl_texture_image *
_mesa_get_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
GLenum target, GLint level);
extern struct gl_texture_image *
_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level);
extern GLint extern GLint
_mesa_max_texture_levels(GLcontext *ctx, GLenum target); _mesa_max_texture_levels(GLcontext *ctx, GLenum target);

View File

@@ -1,4 +1,4 @@
/* $Id: texobj.c,v 1.66 2003/03/10 00:26:24 brianp Exp $ */ /* $Id: texobj.c,v 1.67 2003/04/01 16:41:55 brianp Exp $ */
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
@@ -37,23 +37,37 @@
#include "mtypes.h" #include "mtypes.h"
/* /**
* Allocate a new texture object and add it to the linked list of texture * Allocate and initialize a new texture object
* objects. If name>0 then also insert the new texture object into the hash * Called via ctx->Driver.NewTextureObject, unless overridden by a device
* table. * driver.
* Input: shared - the shared GL state structure to contain the texture object * \param ctx the rendering context
* name - integer name for the texture object * \param name the integer name for the texture object
* target - either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,
* GL_TEXTURE_CUBE_MAP_ARB or GL_TEXTURE_RECTANGLE_NV * GL_TEXTURE_CUBE_MAP_ARB or GL_TEXTURE_RECTANGLE_NV
* zero is ok for the sake of GenTextures() * zero is ok for the sake of GenTextures()
* Return: pointer to new texture object * \return pointer to new texture object
*/ */
struct gl_texture_object * struct gl_texture_object *
_mesa_alloc_texture_object( struct gl_shared_state *shared, _mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target )
GLuint name, GLenum target )
{ {
struct gl_texture_object *obj; struct gl_texture_object *obj;
obj = CALLOC_STRUCT(gl_texture_object);
_mesa_initialize_texture_object(obj, name, target);
return obj;
}
/**
* Initialize a texture object to default values.
* \param obj the texture object
* \param name the texture name
* \param target the texture target
*/
void
_mesa_initialize_texture_object( struct gl_texture_object *obj,
GLuint name, GLenum target )
{
ASSERT(target == 0 || ASSERT(target == 0 ||
target == GL_TEXTURE_1D || target == GL_TEXTURE_1D ||
target == GL_TEXTURE_2D || target == GL_TEXTURE_2D ||
@@ -61,9 +75,6 @@ _mesa_alloc_texture_object( struct gl_shared_state *shared,
target == GL_TEXTURE_CUBE_MAP_ARB || target == GL_TEXTURE_CUBE_MAP_ARB ||
target == GL_TEXTURE_RECTANGLE_NV); target == GL_TEXTURE_RECTANGLE_NV);
obj = CALLOC_STRUCT(gl_texture_object);
if (obj) {
/* init the non-zero fields */ /* init the non-zero fields */
_glthread_INIT_MUTEX(obj->Mutex); _glthread_INIT_MUTEX(obj->Mutex);
obj->RefCount = 1; obj->RefCount = 1;
@@ -95,80 +106,93 @@ _mesa_alloc_texture_object( struct gl_shared_state *shared,
obj->DepthMode = GL_LUMINANCE; /* ARB_depth_texture */ obj->DepthMode = GL_LUMINANCE; /* ARB_depth_texture */
obj->ShadowAmbient = 0.0F; /* ARB/SGIX_shadow_ambient */ obj->ShadowAmbient = 0.0F; /* ARB/SGIX_shadow_ambient */
_mesa_init_colortable(&obj->Palette); _mesa_init_colortable(&obj->Palette);
/* insert into linked list */
if (shared) {
_glthread_LOCK_MUTEX(shared->Mutex);
obj->Next = shared->TexObjectList;
shared->TexObjectList = obj;
_glthread_UNLOCK_MUTEX(shared->Mutex);
}
if (name > 0) {
/* insert into hash table */
_mesa_HashInsert(shared->TexObjects, name, obj);
}
}
return obj;
} }
/* /*
* Deallocate a texture object struct and remove it from the given * Deallocate a texture object. It should have already been removed from
* shared GL state. * the texture object pool.
* Input: shared - the shared GL state to which the object belongs * \param texObj the texture object to deallocate
* t - the texture object to delete
*/ */
void _mesa_free_texture_object( struct gl_shared_state *shared, void
struct gl_texture_object *t ) _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
{
GLuint i;
(void) ctx;
assert(texObj);
_mesa_free_colortable_data(&texObj->Palette);
/* free the texture images */
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
if (texObj->Image[i]) {
_mesa_delete_texture_image( texObj->Image[i] );
}
}
/* destroy the mutex -- it may have allocated memory (eg on bsd) */
_glthread_DESTROY_MUTEX(texObj->Mutex);
/* free this object */
_mesa_free(texObj);
}
/**
* Add the given texture object to the texture object pool.
*/
void
_mesa_save_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
{
/* insert into linked list */
_glthread_LOCK_MUTEX(ctx->Shared->Mutex);
texObj->Next = ctx->Shared->TexObjectList;
ctx->Shared->TexObjectList = texObj;
_glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
if (texObj->Name > 0) {
/* insert into hash table */
_mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
}
}
/**
* 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; struct gl_texture_object *tprev, *tcurr;
assert(t); _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
/* unlink t from the linked list */ /* unlink from the linked list */
if (shared) {
_glthread_LOCK_MUTEX(shared->Mutex);
tprev = NULL; tprev = NULL;
tcurr = shared->TexObjectList; tcurr = ctx->Shared->TexObjectList;
while (tcurr) { while (tcurr) {
if (tcurr==t) { if (tcurr == texObj) {
if (tprev) { if (tprev) {
tprev->Next = t->Next; tprev->Next = texObj->Next;
} }
else { else {
shared->TexObjectList = t->Next; ctx->Shared->TexObjectList = texObj->Next;
} }
break; break;
} }
tprev = tcurr; tprev = tcurr;
tcurr = tcurr->Next; tcurr = tcurr->Next;
} }
_glthread_UNLOCK_MUTEX(shared->Mutex);
}
if (t->Name) { _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
if (texObj->Name > 0) {
/* remove from hash table */ /* remove from hash table */
_mesa_HashRemove(shared->TexObjects, t->Name); _mesa_HashRemove(ctx->Shared->TexObjects, texObj->Name);
} }
_mesa_free_colortable_data(&t->Palette);
/* free the texture images */
{
GLuint i;
for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
if (t->Image[i]) {
_mesa_free_texture_image( t->Image[i] );
}
}
}
/* destroy the mutex -- it may have allocated memory (eg on bsd) */
_glthread_DESTROY_MUTEX(t->Mutex);
/* free this object */
FREE( t );
} }
@@ -531,10 +555,16 @@ _mesa_GenTextures( GLsizei n, GLuint *texName )
} }
/* Allocate new, empty texture objects */ /* Allocate new, empty texture objects */
for (i=0;i<n;i++) { for (i = 0; i < n; i++) {
struct gl_texture_object *texObj;
GLuint name = first + i; GLuint name = first + i;
GLenum target = 0; GLenum target = 0;
(void) _mesa_alloc_texture_object( ctx->Shared, name, target); texObj = (*ctx->Driver.NewTextureObject)( ctx, name, target);
if (!texObj) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
return;
}
_mesa_save_texture_object(ctx, texObj);
} }
_glthread_UNLOCK_MUTEX(GenTexturesLock); _glthread_UNLOCK_MUTEX(GenTexturesLock);
@@ -610,9 +640,9 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *texName)
if (delObj->RefCount == 0) { if (delObj->RefCount == 0) {
ASSERT(delObj->Name != 0); ASSERT(delObj->Name != 0);
if (ctx->Driver.DeleteTexture) _mesa_remove_texture_object(ctx, delObj);
(*ctx->Driver.DeleteTexture)( ctx, delObj ); ASSERT(ctx->Driver.DeleteTexture);
_mesa_free_texture_object(ctx->Shared, delObj); (*ctx->Driver.DeleteTexture)(ctx, delObj);
} }
} }
} }
@@ -717,12 +747,12 @@ _mesa_BindTexture( GLenum target, GLuint texName )
} }
else { else {
/* if this is a new texture id, allocate a texture object now */ /* if this is a new texture id, allocate a texture object now */
newTexObj = _mesa_alloc_texture_object( ctx->Shared, texName, newTexObj = (*ctx->Driver.NewTextureObject)(ctx, texName, target);
target);
if (!newTexObj) { if (!newTexObj) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
return; return;
} }
_mesa_save_texture_object(ctx, newTexObj);
} }
newTexObj->Target = target; newTexObj->Target = target;
} }
@@ -762,11 +792,10 @@ _mesa_BindTexture( GLenum target, GLuint texName )
assert(oldTexObj->RefCount >= 0); assert(oldTexObj->RefCount >= 0);
if (oldTexObj->RefCount == 0) { if (oldTexObj->RefCount == 0) {
assert(oldTexObj->Name != 0); assert(oldTexObj->Name != 0);
if (ctx->Driver.DeleteTexture) { _mesa_remove_texture_object(ctx, oldTexObj);
ASSERT(ctx->Driver.DeleteTexture);
(*ctx->Driver.DeleteTexture)( ctx, oldTexObj ); (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
} }
_mesa_free_texture_object(ctx->Shared, oldTexObj);
}
} }

View File

@@ -1,4 +1,4 @@
/* $Id: texobj.h,v 1.8 2002/06/17 23:36:31 brianp Exp $ */ /* $Id: texobj.h,v 1.9 2003/04/01 16:41:55 brianp Exp $ */
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
@@ -38,23 +38,28 @@
*/ */
extern struct gl_texture_object * extern struct gl_texture_object *
_mesa_alloc_texture_object( struct gl_shared_state *shared, GLuint name, _mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target );
GLenum target );
extern void extern void
_mesa_free_texture_object( struct gl_shared_state *shared, _mesa_initialize_texture_object( struct gl_texture_object *obj,
struct gl_texture_object *t ); GLuint name, GLenum target );
extern void
_mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *obj );
extern void
_mesa_save_texture_object( GLcontext *ctx, struct gl_texture_object *obj );
extern void
_mesa_remove_texture_object( GLcontext *ctx, struct gl_texture_object *obj );
extern void extern void
_mesa_copy_texture_object( struct gl_texture_object *dest, _mesa_copy_texture_object( struct gl_texture_object *dest,
const struct gl_texture_object *src ); const struct gl_texture_object *src );
extern void extern void
_mesa_test_texobj_completeness( const GLcontext *ctx, _mesa_test_texobj_completeness( const GLcontext *ctx,
struct gl_texture_object *t ); struct gl_texture_object *obj );
/* /*

View File

@@ -1,4 +1,4 @@
/* $Id: texstore.c,v 1.54 2003/03/04 19:16:23 brianp Exp $ */ /* $Id: texstore.c,v 1.55 2003/04/01 16:41:55 brianp Exp $ */
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
@@ -482,6 +482,7 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
baseInternalFormat == GL_ALPHA || baseInternalFormat == GL_ALPHA ||
baseInternalFormat == GL_RGB || baseInternalFormat == GL_RGB ||
baseInternalFormat == GL_RGBA || baseInternalFormat == GL_RGBA ||
baseInternalFormat == GL_COLOR_INDEX ||
baseInternalFormat == GL_DEPTH_COMPONENT); baseInternalFormat == GL_DEPTH_COMPONENT);
if (transferOps & IMAGE_CONVOLUTION_BIT) { if (transferOps & IMAGE_CONVOLUTION_BIT) {
@@ -1274,16 +1275,12 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat, GLenum format, GLenum type, GLint internalFormat, GLenum format, GLenum type,
GLint width, GLint height, GLint depth, GLint border) GLint width, GLint height, GLint depth, GLint border)
{ {
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage; struct gl_texture_image *texImage;
(void) format; (void) format;
(void) type; (void) type;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; texImage = _mesa_get_proxy_tex_image(ctx, target, level);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
/* We always pass. /* We always pass.
* The core Mesa code will have already tested the image size, etc. * The core Mesa code will have already tested the image size, etc.
@@ -2011,15 +2008,11 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
} }
/* get dest gl_texture_image */ /* get dest gl_texture_image */
dstImage = _mesa_select_tex_image(ctx, texUnit, target, level+1); dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1);
if (!dstImage) {
dstImage = _mesa_alloc_texture_image();
if (!dstImage) { if (!dstImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
return; return;
} }
_mesa_set_tex_image(texObj, target, level + 1, dstImage);
}
/* Free old image data */ /* Free old image data */
if (dstImage->Data) if (dstImage->Data)