summaryrefslogtreecommitdiff
path: root/src/mesa/main/teximage.c
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2003-04-01 16:41:50 +0000
committerBrian Paul <brian.paul@tungstengraphics.com>2003-04-01 16:41:50 +0000
commita3f137094cd965d27e1b088499dd609b81a91906 (patch)
tree76d361c0998c5fbe55ce7d665ac8f1d2ca6e2e0f /src/mesa/main/teximage.c
parent926c34f89453c9b0455910bbdbe20b52d909d962 (diff)
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.
Diffstat (limited to 'src/mesa/main/teximage.c')
-rw-r--r--src/mesa/main/teximage.c261
1 files changed, 173 insertions, 88 deletions
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 3397a865cd..cef81cb670 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -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
@@ -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.
+ * Called via ctx->Driver.NewTextureImage() unless overriden by a device
+ * driver.
*/
struct gl_texture_image *
-_mesa_alloc_texture_image( void )
+_mesa_new_texture_image( GLcontext *ctx )
{
+ (void) ctx;
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
-_mesa_free_texture_image( struct gl_texture_image *teximage )
+_mesa_delete_texture_image( struct gl_texture_image *teximage )
{
if (teximage->Data && !teximage->IsClientData) {
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
* texture target.
@@ -1167,10 +1286,8 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
if (destTex->IsCompressed) {
const struct gl_texture_unit *texUnit;
- const struct gl_texture_object *texObj;
const struct gl_texture_image *texImage;
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
@@ -1637,15 +1754,11 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
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_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
- texImage = _mesa_alloc_texture_image();
- texObj->Image[level] = texImage;
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
- return;
- }
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+ return;
}
else if (texImage->Data && !texImage->IsClientData) {
/* free the old texture data */
@@ -1690,9 +1803,10 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
}
if (error) {
/* if error, clear all proxy texture image parameters */
- if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
- clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
- }
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage)
+ clear_teximage_fields(texImage);
}
else {
/* no error, set the tex image parameters */
@@ -1746,15 +1860,10 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
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_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
- texImage = _mesa_alloc_texture_image();
- _mesa_set_tex_image(texObj, target, level, texImage);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
- return;
- }
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
}
else if (texImage->Data && !texImage->IsClientData) {
/* free the old texture data */
@@ -1803,11 +1912,10 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
}
if (error) {
/* if error, clear all proxy texture image parameters */
- const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
- ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
- if (level >= 0 && level < maxLevels) {
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage)
clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
- }
}
else {
/* no error, set the tex image parameters */
@@ -1852,15 +1960,10 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
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_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
- texImage = _mesa_alloc_texture_image();
- texObj->Image[level] = texImage;
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
- return;
- }
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
+ return;
}
else if (texImage->Data && !texImage->IsClientData) {
MESA_PBUFFER_FREE(texImage->Data);
@@ -1904,9 +2007,10 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
}
if (error) {
/* if error, clear all proxy texture image parameters */
- if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
- clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
- }
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage)
+ clear_teximage_fields(texImage);
}
else {
/* no error, set the tex image parameters */
@@ -2102,14 +2206,10 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
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_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
- texImage = _mesa_alloc_texture_image();
- _mesa_set_tex_image(texObj, target, level, texImage);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
- return;
- }
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
+ return;
}
else if (texImage->Data && !texImage->IsClientData) {
/* free the old texture data */
@@ -2166,14 +2266,10 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
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_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
- texImage = _mesa_alloc_texture_image();
- _mesa_set_tex_image(texObj, target, level, texImage);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
- return;
- }
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
+ return;
}
else if (texImage->Data && !texImage->IsClientData) {
/* free the old texture data */
@@ -2228,6 +2324,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+ ASSERT(texImage);
/* If we have a border, xoffset=-1 is legal. Bias by border width */
xoffset += texImage->Border;
@@ -2264,6 +2361,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+ ASSERT(texImage);
/* If we have a border, xoffset=-1 is legal. Bias by border width */
xoffset += texImage->Border;
@@ -2302,6 +2400,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
texObj = _mesa_select_tex_object(ctx, texUnit, target);
texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+ ASSERT(texImage);
/* If we have a border, xoffset=-1 is legal. Bias by border width */
xoffset += texImage->Border;
@@ -2509,15 +2608,10 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
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_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
- texImage = _mesa_alloc_texture_image();
- texObj->Image[level] = texImage;
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
- return;
- }
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
+ return;
}
else if (texImage->Data && !texImage->IsClientData) {
MESA_PBUFFER_FREE(texImage->Data);
@@ -2549,9 +2643,10 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
}
if (error) {
/* if error, clear all proxy texture image parameters */
- if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
- clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
- }
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage)
+ clear_teximage_fields(texImage);
}
else {
/* store the teximage parameters */
@@ -2595,15 +2690,10 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
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_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
- texImage = _mesa_alloc_texture_image();
- texObj->Image[level] = texImage;
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
- return;
- }
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+ return;
}
else if (texImage->Data && !texImage->IsClientData) {
MESA_PBUFFER_FREE(texImage->Data);
@@ -2637,11 +2727,10 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
}
if (error) {
/* if error, clear all proxy texture image parameters */
- const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
- ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
- if (level >= 0 && level < maxLevels) {
- clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
- }
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage)
+ clear_teximage_fields(texImage);
}
else {
/* store the teximage parameters */
@@ -2682,15 +2771,10 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
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_get_tex_image(ctx, texUnit, target, level);
if (!texImage) {
- texImage = _mesa_alloc_texture_image();
- texObj->Image[level] = texImage;
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
- return;
- }
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
+ return;
}
else if (texImage->Data && !texImage->IsClientData) {
MESA_PBUFFER_FREE(texImage->Data);
@@ -2723,9 +2807,10 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
}
if (error) {
/* if error, clear all proxy texture image parameters */
- if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
- clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
- }
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage)
+ clear_teximage_fields(texImage);
}
else {
/* store the teximage parameters */