From c3f0a511a725c7b3d3d7d93b1955aaaa2bb32f0d Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 3 Nov 1999 17:27:05 +0000 Subject: new texture image processing --- src/mesa/main/dlist.c | 379 ++++---- src/mesa/main/image.c | 1188 +++++++++++++++++++++++- src/mesa/main/image.h | 29 +- src/mesa/main/teximage.c | 2236 +++++++++++++++++----------------------------- src/mesa/main/teximage.h | 99 +- 5 files changed, 2286 insertions(+), 1645 deletions(-) (limited to 'src') diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index e970637390..5729851df3 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -1,4 +1,4 @@ -/* $Id: dlist.c,v 1.12 1999/10/31 08:34:47 brianp Exp $ */ +/* $Id: dlist.c,v 1.13 1999/11/03 17:27:05 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -389,26 +389,28 @@ void gl_destroy_list( GLcontext *ctx, GLuint list ) n += InstSize[n[0].opcode]; break; case OPCODE_TEX_IMAGE1D: - gl_free_image( (struct gl_image *) n[8].data ); + FREE( n[8]. data ); n += InstSize[n[0].opcode]; break; case OPCODE_TEX_IMAGE2D: - gl_free_image( (struct gl_image *) n[9].data ); + FREE( n[9].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_IMAGE3D: + FREE( n[10].data ); n += InstSize[n[0].opcode]; break; case OPCODE_TEX_SUB_IMAGE1D: - { - struct gl_image *image; - image = (struct gl_image *) n[7].data; - gl_free_image( image ); - } + FREE( n[7].data ); + n += InstSize[n[0].opcode]; break; case OPCODE_TEX_SUB_IMAGE2D: - { - struct gl_image *image; - image = (struct gl_image *) n[9].data; - gl_free_image( image ); - } + FREE( n[9].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_SUB_IMAGE3D: + FREE( n[11].data ); + n += InstSize[n[0].opcode]; break; case OPCODE_CONTINUE: n = (Node *) n[1].next; @@ -1097,11 +1099,12 @@ static void save_CopyTexSubImage2D( GLcontext *ctx, } -static void save_CopyTexSubImage3DEXT( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, - GLsizei width, GLint height ) +static void save_CopyTexSubImage3D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, + GLint x, GLint y, + GLsizei width, GLint height ) { Node *n; FLUSH_VB(ctx, "dlist"); @@ -1118,8 +1121,8 @@ static void save_CopyTexSubImage3DEXT( GLcontext *ctx, n[9].i = height; } if (ctx->ExecuteFlag) { - (*ctx->Exec.CopyTexSubImage3DEXT)( ctx, target, level, xoffset, yoffset, zoffset, - x, y, width, height ); + (*ctx->Exec.CopyTexSubImage3D)(ctx, target, level, xoffset, yoffset, + zoffset, x, y, width, height ); } } @@ -2111,105 +2114,128 @@ static void save_TexParameterfv( GLcontext *ctx, GLenum target, static void save_TexImage1D( GLcontext *ctx, GLenum target, - GLint level, GLint components, - GLsizei width, GLint border, - GLenum format, GLenum type, - struct gl_image *teximage ) + GLint level, GLint components, + GLsizei width, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ) { - Node *n; FLUSH_VB(ctx, "dlist"); - n = alloc_instruction( ctx, OPCODE_TEX_IMAGE1D, 8 ); - if (n) { - n[1].e = target; - n[2].i = level; - n[3].i = components; - n[4].i = (GLint) width; - n[5].i = border; - n[6].e = format; - n[7].e = type; - n[8].data = teximage; - if (teximage) { - /* this prevents gl_TexImage1D() from freeing the image */ - teximage->RefCount = 1; - } - } - if (ctx->ExecuteFlag) { + if (target == GL_PROXY_TEXTURE_1D) { (*ctx->Exec.TexImage1D)( ctx, target, level, components, width, - border, format, type, teximage ); + border, format, type, pixels ); + } + else { + Node *n; + GLvoid *image = _mesa_unpack_image(width, 1, 1, format, type, + pixels, &ctx->Unpack); + n = alloc_instruction( ctx, OPCODE_TEX_IMAGE1D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = components; + n[4].i = (GLint) width; + n[5].i = border; + n[6].e = format; + n[7].e = type; + n[8].data = image; + } + else { + FREE(image); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexImage1D)( ctx, target, level, components, width, + border, format, type, pixels ); + } } } static void save_TexImage2D( GLcontext *ctx, GLenum target, - GLint level, GLint components, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, - struct gl_image *teximage ) + GLint level, GLint components, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ) { - Node *n; FLUSH_VB(ctx, "dlist"); - n = alloc_instruction( ctx, OPCODE_TEX_IMAGE2D, 9 ); - if (n) { - n[1].e = target; - n[2].i = level; - n[3].i = components; - n[4].i = (GLint) width; - n[5].i = (GLint) height; - n[6].i = border; - n[7].e = format; - n[8].e = type; - n[9].data = teximage; - if (teximage) { - /* this prevents gl_TexImage2D() from freeing the image */ - teximage->RefCount = 1; - } - } - if (ctx->ExecuteFlag) { + if (target == GL_PROXY_TEXTURE_2D) { (*ctx->Exec.TexImage2D)( ctx, target, level, components, width, - height, border, format, type, teximage ); + height, border, format, type, pixels ); + } + else { + Node *n; + GLvoid *image = _mesa_unpack_image(width, height, 1, format, type, + pixels, &ctx->Unpack); + n = alloc_instruction( ctx, OPCODE_TEX_IMAGE2D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = components; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = border; + n[7].e = format; + n[8].e = type; + n[9].data = image; + } + else { + FREE(image); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexImage2D)( ctx, target, level, components, width, + height, border, format, type, pixels ); + } } } -static void save_TexImage3DEXT( GLcontext *ctx, GLenum target, - GLint level, GLint components, - GLsizei width, GLsizei height, GLsizei depth, - GLint border, - GLenum format, GLenum type, - struct gl_image *teximage ) +static void save_TexImage3D( GLcontext *ctx, GLenum target, + GLint level, GLint components, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ) { - Node *n; FLUSH_VB(ctx, "dlist"); - n = alloc_instruction( ctx, OPCODE_TEX_IMAGE3D, 10 ); - if (n) { - n[1].e = target; - n[2].i = level; - n[3].i = components; - n[4].i = (GLint) width; - n[5].i = (GLint) height; - n[6].i = (GLint) depth; - n[7].i = border; - n[8].e = format; - n[9].e = type; - n[10].data = teximage; - if (teximage) { - /* this prevents gl_TexImage3D() from freeing the image */ - teximage->RefCount = 1; - } + if (target == GL_PROXY_TEXTURE_3D) { + (*ctx->Exec.TexImage3D)( ctx, target, level, components, width, + height, depth, border, format, type, pixels ); } - if (ctx->ExecuteFlag) { - (*ctx->Exec.TexImage3DEXT)( ctx, target, level, components, width, - height, depth, border, format, type, teximage ); + else { + GLvoid *image = _mesa_unpack_image(width, height, depth, format, type, + pixels, &ctx->Unpack); + Node *n; + n = alloc_instruction( ctx, OPCODE_TEX_IMAGE3D, 10 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = components; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = (GLint) depth; + n[7].i = border; + n[8].e = format; + n[9].e = type; + n[10].data = image; + } + else { + FREE(image); + } + if (ctx->ExecuteFlag) { + (*ctx->Exec.TexImage3D)( ctx, target, level, components, width, + height, depth, border, format, type, pixels ); + } } } static void save_TexSubImage1D( GLcontext *ctx, - GLenum target, GLint level, GLint xoffset, - GLsizei width, GLenum format, GLenum type, - struct gl_image *image ) + GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, GLenum type, + const GLvoid *pixels ) { Node *n; + GLvoid *image = _mesa_unpack_image(width, 1, 1, format, type, + pixels, &ctx->Unpack); FLUSH_VB(ctx, "dlist"); n = alloc_instruction( ctx, OPCODE_TEX_SUB_IMAGE1D, 7 ); if (n) { @@ -2220,24 +2246,27 @@ static void save_TexSubImage1D( GLcontext *ctx, n[5].e = format; n[6].e = type; n[7].data = image; - if (image) - image->RefCount = 1; + } + else { + FREE(image); } if (ctx->ExecuteFlag) { (*ctx->Exec.TexSubImage1D)( ctx, target, level, xoffset, width, - format, type, image ); + format, type, pixels ); } } static void save_TexSubImage2D( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - struct gl_image *image ) + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ) { Node *n; + GLvoid *image = _mesa_unpack_image(width, height, 1, format, type, + pixels, &ctx->Unpack); FLUSH_VB(ctx, "dlist"); n = alloc_instruction( ctx, OPCODE_TEX_SUB_IMAGE2D, 9 ); if (n) { @@ -2250,24 +2279,27 @@ static void save_TexSubImage2D( GLcontext *ctx, n[7].e = format; n[8].e = type; n[9].data = image; - if (image) - image->RefCount = 1; + } + else { + FREE(image); } if (ctx->ExecuteFlag) { (*ctx->Exec.TexSubImage2D)( ctx, target, level, xoffset, yoffset, - width, height, format, type, image ); + width, height, format, type, pixels ); } } -static void save_TexSubImage3DEXT( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset,GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - struct gl_image *image ) +static void save_TexSubImage3D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset,GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid *pixels ) { Node *n; + GLvoid *image = _mesa_unpack_image(width, height, depth, format, type, + pixels, &ctx->Unpack); FLUSH_VB(ctx, "dlist"); n = alloc_instruction( ctx, OPCODE_TEX_SUB_IMAGE3D, 11 ); if (n) { @@ -2282,12 +2314,13 @@ static void save_TexSubImage3DEXT( GLcontext *ctx, n[9].e = format; n[10].e = type; n[11].data = image; - if (image) - image->RefCount = 1; + } + else { + FREE(image); } if (ctx->ExecuteFlag) { - (*ctx->Exec.TexSubImage3DEXT)( ctx, target, level, xoffset, yoffset, zoffset, - width, height, depth, format, type, image ); + (*ctx->Exec.TexSubImage3D)(ctx, target, level, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels ); } } @@ -2460,6 +2493,16 @@ void gl_save_error( GLcontext *ctx, GLenum error, const char *s ) */ static void execute_list( GLcontext *ctx, GLuint list ) { + static struct gl_pixelstore_attrib defaultPacking = { + 1, /* Alignment */ + 0, /* RowLength */ + 0, /* SkipPixels */ + 0, /* SkipRows */ + 0, /* ImageHeight */ + 0, /* SkipImages */ + GL_FALSE, /* SwapBytes */ + GL_FALSE /* LsbFirst */ + }; Node *n; GLboolean done; OpCode opcode; @@ -2527,16 +2570,6 @@ static void execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_BITMAP: { - static struct gl_pixelstore_attrib defaultPacking = { - 1, /* Alignment */ - 0, /* RowLength */ - 0, /* SkipPixels */ - 0, /* SkipRows */ - 0, /* ImageHeight */ - 0, /* SkipImages */ - GL_FALSE, /* SwapBytes */ - GL_FALSE /* LsbFirst */ - }; const struct gl_image *image = (struct gl_image *) n[7].data; const GLubyte *bitmap = image ? image->Data : NULL; gl_Bitmap( ctx, (GLsizei) n[1].i, (GLsizei) n[2].i, @@ -2630,8 +2663,8 @@ static void execute_list( GLcontext *ctx, GLuint list ) n[5].i, n[6].i, n[7].i, n[8].i ); break; case OPCODE_COPY_TEX_SUB_IMAGE3D: - gl_CopyTexSubImage3DEXT( ctx, n[1].e, n[2].i, n[3].i, n[4].i, - n[5].i, n[6].i, n[7].i, n[8].i , n[9].i); + gl_CopyTexSubImage3D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, + n[5].i, n[6].i, n[7].i, n[8].i, n[9].i); break; case OPCODE_CULL_FACE: gl_CullFace( ctx, n[1].e ); @@ -2889,30 +2922,43 @@ static void execute_list( GLcontext *ctx, GLuint list ) } break; case OPCODE_TEX_IMAGE1D: - gl_TexImage1D( ctx, - n[1].e, /* target */ - n[2].i, /* level */ - n[3].i, /* components */ - n[4].i, /* width */ - n[5].e, /* border */ - n[6].e, /* format */ - n[7].e, /* type */ - (struct gl_image *) n[8].data ); + { + struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = defaultPacking; + gl_TexImage1D( ctx, + n[1].e, /* target */ + n[2].i, /* level */ + n[3].i, /* components */ + n[4].i, /* width */ + n[5].e, /* border */ + n[6].e, /* format */ + n[7].e, /* type */ + n[8].data ); + ctx->Unpack = save; /* restore */ + } break; case OPCODE_TEX_IMAGE2D: - gl_TexImage2D( ctx, - n[1].e, /* target */ - n[2].i, /* level */ - n[3].i, /* components */ - n[4].i, /* width */ - n[5].i, /* height */ - n[6].e, /* border */ - n[7].e, /* format */ - n[8].e, /* type */ - (struct gl_image *) n[9].data ); + { + struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = defaultPacking; + gl_TexImage2D( ctx, + n[1].e, /* target */ + n[2].i, /* level */ + n[3].i, /* components */ + n[4].i, /* width */ + n[5].i, /* height */ + n[6].e, /* border */ + n[7].e, /* format */ + n[8].e, /* type */ + n[9].data ); + ctx->Unpack = save; /* restore */ + } break; case OPCODE_TEX_IMAGE3D: - gl_TexImage3DEXT( ctx, + { + struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = defaultPacking; + gl_TexImage3D( ctx, n[1].e, /* target */ n[2].i, /* level */ n[3].i, /* components */ @@ -2922,21 +2968,38 @@ static void execute_list( GLcontext *ctx, GLuint list ) n[7].e, /* border */ n[8].e, /* format */ n[9].e, /* type */ - (struct gl_image *) n[10].data ); + n[10].data ); + ctx->Unpack = save; /* restore */ + } break; case OPCODE_TEX_SUB_IMAGE1D: - gl_TexSubImage1D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, - n[6].e, (struct gl_image *) n[7].data ); + { + struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = defaultPacking; + gl_TexSubImage1D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, + n[6].e, n[7].data ); + ctx->Unpack = save; /* restore */ + } break; case OPCODE_TEX_SUB_IMAGE2D: - gl_TexSubImage2D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, - n[6].i, n[7].e, n[8].e, - (struct gl_image *) n[9].data ); + { + struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = defaultPacking; + (*ctx->Exec.TexSubImage2D)( ctx, n[1].e, n[2].i, n[3].i, + n[4].i, n[5].e, + n[6].i, n[7].e, n[8].e, n[9].data ); + ctx->Unpack = save; /* restore */ + } break; case OPCODE_TEX_SUB_IMAGE3D: - gl_TexSubImage3DEXT( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].i, + { + struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = defaultPacking; + gl_TexSubImage3D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].i, n[6].i, n[7].i, n[8].i, n[9].e, n[10].e, - (struct gl_image *) n[11].data ); + n[11].data ); + ctx->Unpack = save; /* restore */ + } break; case OPCODE_TRANSLATE: gl_Translatef( ctx, n[1].f, n[2].f, n[3].f ); @@ -3255,7 +3318,7 @@ void gl_init_dlist_pointers( struct gl_api_table *table ) table->CopyTexImage2D = save_CopyTexImage2D; table->CopyTexSubImage1D = save_CopyTexSubImage1D; table->CopyTexSubImage2D = save_CopyTexSubImage2D; - table->CopyTexSubImage3DEXT = save_CopyTexSubImage3DEXT; + table->CopyTexSubImage3D = save_CopyTexSubImage3D; table->CullFace = save_CullFace; table->DeleteLists = gl_DeleteLists; /* NOT SAVED */ table->DeleteTextures = gl_DeleteTextures; /* NOT SAVED */ @@ -3373,10 +3436,10 @@ void gl_init_dlist_pointers( struct gl_api_table *table ) table->TexGenfv = save_TexGenfv; table->TexImage1D = save_TexImage1D; table->TexImage2D = save_TexImage2D; - table->TexImage3DEXT = save_TexImage3DEXT; + table->TexImage3D = save_TexImage3D; table->TexSubImage1D = save_TexSubImage1D; table->TexSubImage2D = save_TexSubImage2D; - table->TexSubImage3DEXT = save_TexSubImage3DEXT; + table->TexSubImage3D = save_TexSubImage3D; table->TexParameterfv = save_TexParameterfv; table->Translatef = save_Translatef; table->Viewport = save_Viewport; diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c index 7959668cdc..41ce693eb0 100644 --- a/src/mesa/main/image.c +++ b/src/mesa/main/image.c @@ -1,4 +1,4 @@ -/* $Id: image.c,v 1.10 1999/10/26 09:21:04 brianp Exp $ */ +/* $Id: image.c,v 1.11 1999/11/03 17:27:05 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -210,6 +210,7 @@ GLint gl_components_in_format( GLenum format ) case GL_BLUE: case GL_ALPHA: case GL_LUMINANCE: + case GL_INTENSITY: return 1; case GL_LUMINANCE_ALPHA: return 2; @@ -2470,3 +2471,1188 @@ void gl_pack_rgba_span( const GLcontext *ctx, } } } + + + +/* + * New (3.3) functions + */ + +#define SWAP2BYTE(VALUE) \ + { \ + GLubyte *bytes = (GLubyte *) &(VALUE); \ + GLubyte tmp = bytes[0]; \ + bytes[0] = bytes[1]; \ + bytes[1] = tmp; \ + } + +#define SWAP4BYTE(VALUE) \ + { \ + GLubyte *bytes = (GLubyte *) &(VALUE); \ + GLubyte tmp = bytes[0]; \ + bytes[0] = bytes[3]; \ + bytes[3] = tmp; \ + tmp = bytes[1]; \ + bytes[1] = bytes[2]; \ + bytes[2] = tmp; \ + } + + +static void +extract_uint_indexes(GLuint n, GLuint indexes[], + GLenum srcFormat, GLenum srcType, const GLvoid *src, + const struct gl_pixelstore_attrib *unpack ) +{ + assert(srcFormat == GL_COLOR_INDEX); + + ASSERT(srcType == GL_BITMAP || + srcType == GL_UNSIGNED_BYTE || + srcType == GL_BYTE || + srcType == GL_UNSIGNED_SHORT || + srcType == GL_SHORT || + srcType == GL_UNSIGNED_INT || + srcType == GL_INT || + srcType == GL_FLOAT); + + switch (srcType) { + case GL_BITMAP: + { + GLubyte *ubsrc = (GLubyte *) src; + if (unpack->LsbFirst) { + GLubyte mask = 1 << (unpack->SkipPixels & 0x7); + GLuint i; + for (i = 0; i < n; i++) { + indexes[i] = (*ubsrc & mask) ? 1 : 0; + if (mask == 128) { + mask = 1; + ubsrc++; + } + else { + mask = mask << 1; + } + } + } + else { + GLubyte mask = 128 >> (unpack->SkipPixels & 0x7); + GLuint i; + for (i = 0; i < n; i++) { + indexes[i] = (*ubsrc & mask) ? 1 : 0; + if (mask == 1) { + mask = 128; + ubsrc++; + } + else { + mask = mask >> 1; + } + } + } + } + break; + case GL_UNSIGNED_BYTE: + { + GLuint i; + const GLubyte *s = (const GLubyte *) src; + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + break; + case GL_BYTE: + { + GLuint i; + const GLbyte *s = (const GLbyte *) src; + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + break; + case GL_UNSIGNED_SHORT: + { + GLuint i; + const GLushort *s = (const GLushort *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLushort value = s[i]; + SWAP2BYTE(value); + indexes[i] = value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + } + break; + case GL_SHORT: + { + GLuint i; + const GLshort *s = (const GLshort *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLshort value = s[i]; + SWAP2BYTE(value); + indexes[i] = value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint i; + const GLuint *s = (const GLuint *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLuint value = s[i]; + SWAP4BYTE(value); + indexes[i] = value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + } + break; + case GL_INT: + { + GLuint i; + const GLint *s = (const GLint *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLint value = s[i]; + SWAP4BYTE(value); + indexes[i] = value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + } + break; + case GL_FLOAT: + { + GLuint i; + const GLfloat *s = (const GLfloat *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLfloat value = s[i]; + SWAP4BYTE(value); + indexes[i] = value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + } + break; + default: + gl_problem(NULL, "bad srcType in extract_uint_indexes"); + return; + } +} + + + +/* + * This function extracts floating point RGBA values from arbitrary + * image data. srcFormat and srcType are the format and type parameters + * passed to glDrawPixels, glTexImage[123]D, glTexSubImage[123]D, etc. + * + * Refering to section 3.6.4 of the OpenGL 1.2 spec, this function + * implements the "Conversion to floating point", "Conversion to RGB", + * and "Final Expansion to RGBA" operations. + * + * Args: n - number of pixels + * rgba - output colors + * srcFormat - format of incoming data + * srcType - datatype of incoming data + * src - source data pointer + * swapBytes - perform byteswapping of incoming data? + */ +static void +extract_float_rgba(GLuint n, GLfloat rgba[][4], + GLenum srcFormat, GLenum srcType, const GLvoid *src, + GLboolean swapBytes) +{ + GLint redIndex, greenIndex, blueIndex, alphaIndex; + GLint stride; + GLint rComp, bComp, gComp, aComp; + + if (0) + { + int i; + for (i = 0; i= -1 && redIndex <= 4); + assert(greenIndex >= -1 && greenIndex <= 4); + assert(blueIndex >= -1 && blueIndex <= 4); + assert(alphaIndex >= -1 && alphaIndex <= 4); + +#define PROCESS(INDEX, CHANNEL, DEFAULT, TYPE, CONVERSION) \ + if ((INDEX) < 0) { \ + GLuint i; \ + for (i = 0; i < n; i++) { \ + rgba[i][CHANNEL] = DEFAULT; \ + } \ + } \ + else if (swapBytes) { \ + const TYPE *s = (const TYPE *) src; \ + GLuint i; \ + for (i = 0; i < n; i++) { \ + TYPE value = s[INDEX]; \ + if (sizeof(TYPE) == 2) { \ + SWAP2BYTE(value); \ + } \ + else if (sizeof(TYPE) == 4) { \ + SWAP4BYTE(value); \ + } \ + rgba[i][CHANNEL] = (GLfloat) CONVERSION(value); \ + s += stride; \ + } \ + } \ + else { \ + const TYPE *s = (const TYPE *) src; \ + GLuint i; \ + for (i = 0; i < n; i++) { \ + rgba[i][CHANNEL] = (GLfloat) CONVERSION(s[INDEX]); \ + s += stride; \ + } \ + } + + switch (srcType) { + case GL_UNSIGNED_BYTE: + PROCESS(redIndex, RCOMP, 0.0F, GLubyte, UBYTE_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLubyte, UBYTE_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLubyte, UBYTE_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLubyte, UBYTE_TO_FLOAT); + break; + case GL_BYTE: + PROCESS(redIndex, RCOMP, 0.0F, GLbyte, BYTE_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLbyte, BYTE_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLbyte, BYTE_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLbyte, BYTE_TO_FLOAT); + break; + case GL_UNSIGNED_SHORT: + PROCESS(redIndex, RCOMP, 0.0F, GLushort, USHORT_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLushort, USHORT_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLushort, USHORT_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLushort, USHORT_TO_FLOAT); + break; + case GL_SHORT: + PROCESS(redIndex, RCOMP, 0.0F, GLshort, SHORT_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLshort, SHORT_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLshort, SHORT_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLshort, SHORT_TO_FLOAT); + break; + case GL_UNSIGNED_INT: + PROCESS(redIndex, RCOMP, 0.0F, GLuint, UINT_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLuint, UINT_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLuint, UINT_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLuint, UINT_TO_FLOAT); + break; + case GL_INT: + PROCESS(redIndex, RCOMP, 0.0F, GLint, INT_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLint, INT_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLint, INT_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLint, INT_TO_FLOAT); + break; + case GL_FLOAT: + PROCESS(redIndex, RCOMP, 0.0F, GLfloat, (GLfloat)); + PROCESS(greenIndex, GCOMP, 0.0F, GLfloat, (GLfloat)); + PROCESS(blueIndex, BCOMP, 0.0F, GLfloat, (GLfloat)); + PROCESS(alphaIndex, ACOMP, 1.0F, GLfloat, (GLfloat)); + break; + case GL_UNSIGNED_BYTE_3_3_2: + { + const GLubyte *ubsrc = (const GLubyte *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLubyte p = ubsrc[i]; + rgba[i][RCOMP] = ((p >> 5) ) * (1.0F / 7.0F); + rgba[i][GCOMP] = ((p >> 2) & 0x7) * (1.0F / 7.0F); + rgba[i][BCOMP] = ((p ) & 0x3) * (1.0F / 3.0F); + rgba[i][ACOMP] = 1.0F; + } + } + break; + case GL_UNSIGNED_BYTE_2_3_3_REV: + { + const GLubyte *ubsrc = (const GLubyte *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLubyte p = ubsrc[i]; + rgba[i][RCOMP] = ((p ) & 0x7) * (1.0F / 7.0F); + rgba[i][GCOMP] = ((p >> 3) & 0x7) * (1.0F / 7.0F); + rgba[i][BCOMP] = ((p >> 6) ) * (1.0F / 3.0F); + rgba[i][ACOMP] = 1.0F; + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][RCOMP] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][GCOMP] = ((p >> 5) & 0x3f) * (1.0F / 63.0F); + rgba[i][BCOMP] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][ACOMP] = 1.0F; + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][RCOMP] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][GCOMP] = ((p >> 5) & 0x3f) * (1.0F / 63.0F); + rgba[i][BCOMP] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][ACOMP] = 1.0F; + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5_REV: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][RCOMP] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][GCOMP] = ((p >> 5) & 0x3f) * (1.0F / 63.0F); + rgba[i][BCOMP] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][ACOMP] = 1.0F; + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][RCOMP] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][GCOMP] = ((p >> 5) & 0x3f) * (1.0F / 63.0F); + rgba[i][BCOMP] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][ACOMP] = 1.0F; + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p >> 12) ) * (1.0F / 15.0F); + rgba[i][gComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F); + rgba[i][bComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F); + rgba[i][aComp] = ((p ) & 0xf) * (1.0F / 15.0F); + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p >> 12) ) * (1.0F / 15.0F); + rgba[i][gComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F); + rgba[i][bComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F); + rgba[i][aComp] = ((p ) & 0xf) * (1.0F / 15.0F); + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p ) & 0xf) * (1.0F / 15.0F); + rgba[i][gComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F); + rgba[i][bComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F); + rgba[i][aComp] = ((p >> 12) ) * (1.0F / 15.0F); + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p ) & 0xf) * (1.0F / 15.0F); + rgba[i][gComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F); + rgba[i][bComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F); + rgba[i][aComp] = ((p >> 12) ) * (1.0F / 15.0F); + } + } + break; + case GL_UNSIGNED_SHORT_5_5_5_1: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 6) & 0x1f) * (1.0F / 31.0F); + rgba[i][bComp] = ((p >> 1) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = ((p ) & 0x1) * (1.0F / 1.0F); + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 6) & 0x1f) * (1.0F / 31.0F); + rgba[i][bComp] = ((p >> 1) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = ((p ) & 0x1) * (1.0F / 1.0F); + } + } + break; + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 5) & 0x1f) * (1.0F / 31.0F); + rgba[i][bComp] = ((p >> 10) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = ((p >> 15) ) * (1.0F / 1.0F); + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 5) & 0x1f) * (1.0F / 31.0F); + rgba[i][bComp] = ((p >> 10) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = ((p >> 15) ) * (1.0F / 1.0F); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff); + rgba[i][gComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff); + rgba[i][bComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff); + rgba[i][aComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); + rgba[i][gComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff); + rgba[i][bComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff); + rgba[i][aComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8_REV: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); + rgba[i][gComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff); + rgba[i][bComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff); + rgba[i][aComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff); + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff); + rgba[i][gComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff); + rgba[i][bComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff); + rgba[i][aComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); + } + } + break; + case GL_UNSIGNED_INT_10_10_10_2: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + SWAP4BYTE(p); + rgba[i][rComp] = ((p ) & 0x3 ) * (1.0F / 3.0F); + rgba[i][gComp] = ((p >> 2) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][bComp] = ((p >> 12) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][aComp] = ((p >> 22) ) * (1.0F / 1023.0F); + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = ((p ) & 0x3 ) * (1.0F / 3.0F); + rgba[i][gComp] = ((p >> 2) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][bComp] = ((p >> 12) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][aComp] = ((p >> 22) ) * (1.0F / 1023.0F); + } + } + break; + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + SWAP4BYTE(p); + rgba[i][rComp] = ((p ) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][gComp] = ((p >> 10) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][bComp] = ((p >> 20) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][aComp] = ((p >> 30) ) * (1.0F / 3.0F); + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = ((p ) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][gComp] = ((p >> 10) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][bComp] = ((p >> 20) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][aComp] = ((p >> 30) ) * (1.0F / 3.0F); + } + } + break; + default: + gl_problem(NULL, "bad srcType in extract float data"); + break; + } +} + + + +/* + * Unpack a row of color image data from a client buffer according to + * the pixel unpacking parameters. Apply any enabled pixel transfer + * ops (PixelMap, scale/bias) if the applyTransferOps flag is enabled. + * Return GLubyte values in the specified dest image format. + * This is (or will be) used by glDrawPixels and glTexImage?D(). + * Input: ctx - the context + * n - number of pixels in the span + * dstFormat - format of destination color array + * dest - the destination color array + * srcFormat - source image format + * srcType - source image datatype + * source - source image pointer + * unpacking - pixel unpacking parameters + * applyTransferOps - apply scale/bias/lookup-table ops? + * + * XXX perhaps expand this to process whole images someday. + */ +void +_mesa_unpack_ubyte_color_span( const GLcontext *ctx, + GLuint n, GLenum dstFormat, GLubyte dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *unpacking, + GLboolean applyTransferOps ) +{ + ASSERT(dstFormat == GL_ALPHA || + dstFormat == GL_LUMINANCE || + dstFormat == GL_LUMINANCE_ALPHA || + dstFormat == GL_INTENSITY || + dstFormat == GL_RGB || + dstFormat == GL_RGBA || + dstFormat == GL_COLOR_INDEX); + + ASSERT(srcFormat == GL_RED || + srcFormat == GL_GREEN || + srcFormat == GL_BLUE || + srcFormat == GL_ALPHA || + srcFormat == GL_LUMINANCE || + srcFormat == GL_LUMINANCE_ALPHA || + srcFormat == GL_INTENSITY || + srcFormat == GL_RGB || + srcFormat == GL_BGR || + srcFormat == GL_RGBA || + srcFormat == GL_BGRA || + srcFormat == GL_ABGR_EXT || + srcFormat == GL_COLOR_INDEX); + + ASSERT(srcType == GL_BITMAP || + srcType == GL_UNSIGNED_BYTE || + srcType == GL_BYTE || + srcType == GL_UNSIGNED_SHORT || + srcType == GL_SHORT || + srcType == GL_UNSIGNED_INT || + srcType == GL_INT || + srcType == GL_FLOAT || + srcType == GL_UNSIGNED_BYTE_3_3_2 || + srcType == GL_UNSIGNED_BYTE_2_3_3_REV || + srcType == GL_UNSIGNED_SHORT_5_6_5 || + srcType == GL_UNSIGNED_SHORT_5_6_5_REV || + srcType == GL_UNSIGNED_SHORT_4_4_4_4 || + srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV || + srcType == GL_UNSIGNED_SHORT_5_5_5_1 || + srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV || + srcType == GL_UNSIGNED_INT_8_8_8_8 || + srcType == GL_UNSIGNED_INT_8_8_8_8_REV || + srcType == GL_UNSIGNED_INT_10_10_10_2 || + srcType == GL_UNSIGNED_INT_2_10_10_10_REV); + + /* this is intended for RGBA mode */ + ASSERT(ctx->Visual->RGBAflag); + + applyTransferOps &= (ctx->Pixel.ScaleOrBiasRGBA || + ctx->Pixel.MapColorFlag || + ctx->Pixel.MapColorFlag); + + /* Try simple cases first */ + if (!applyTransferOps && srcType == GL_UNSIGNED_BYTE) { + if (dstFormat == GL_RGBA) { + if (srcFormat == GL_RGBA) { + MEMCPY( dest, source, n * 4 * sizeof(GLubyte) ); + return; + } + else if (srcFormat == GL_RGB) { + GLuint i; + const GLubyte *src = (const GLubyte *) source; + GLubyte *dst = dest; + for (i = 0; i < n; i++) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 255; + src += 3; + dst += 4; + } + return; + } + } + else if (dstFormat == GL_RGB) { + if (srcFormat == GL_RGB) { + MEMCPY( dest, source, n * 3 * sizeof(GLubyte) ); + return; + } + else if (srcFormat == GL_RGBA) { + GLuint i; + const GLubyte *src = (const GLubyte *) source; + GLubyte *dst = dest; + for (i = 0; i < n; i++) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + src += 4; + dst += 3; + } + return; + } + } + else if (dstFormat == GL_ALPHA && srcFormat == GL_ALPHA) { + MEMCPY( dest, source, n * sizeof(GLubyte) ); + return; + } + } + + + { + /* general solution */ + GLfloat rgba[MAX_WIDTH][4]; + GLint dstComponents; + GLint dstRedIndex, dstGreenIndex, dstBlueIndex, dstAlphaIndex; + GLint dstLuminanceIndex, dstIntensityIndex; + + dstComponents = gl_components_in_format( dstFormat ); + /* source & dest image formats should have been error checked by now */ + assert(dstComponents > 0); + + /* + * Extract image data and convert to RGBA floats + */ + assert(n <= MAX_WIDTH); + if (srcFormat == GL_COLOR_INDEX) { + GLuint indexes[MAX_WIDTH]; + extract_uint_indexes(n, indexes, srcFormat, srcType, source, + unpacking); + + /* shift and offset indexes */ + gl_shift_and_offset_ci(ctx, n, indexes); + + if (dstFormat == GL_COLOR_INDEX) { + if (applyTransferOps) { + if (ctx->Pixel.MapColorFlag) { + /* Apply lookup table */ + gl_map_ci(ctx, n, indexes); + } + + if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset) { + + } + } + + /* convert to GLubyte and return */ + { + GLuint i; + for (i = 0; i < n; i++) { + dest[i] = (GLubyte) (indexes[i] & 0xff); + } + } + } + else { + /* Convert indexes to RGBA */ + gl_map_ci_to_rgba_float(ctx, n, indexes, rgba); + } + } + else { + extract_float_rgba(n, rgba, srcFormat, srcType, source, + unpacking->SwapBytes); + + if (applyTransferOps) { + /* scale and bias colors */ + gl_scale_and_bias_rgba_float(ctx, n, rgba); + + /* color table lookup */ + if (ctx->Pixel.MapColorFlag) { + gl_map_rgba_float(ctx, n, rgba); + } + } + } + + + /* + * XXX this is where more color table lookups, convolution and + * histogram would take place, if implemented. + */ + + + /* clamp to [0,1] */ + { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); + rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); + rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); + rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); + } + } + + /* Now determine which color channels we need to produce. + * And determine the dest index (offset) within each color tuple. + */ + switch (dstFormat) { + case GL_ALPHA: + dstAlphaIndex = 0; + dstRedIndex = dstGreenIndex = dstBlueIndex = -1; + dstLuminanceIndex = dstIntensityIndex = -1; + break; + case GL_LUMINANCE: + dstLuminanceIndex = 0; + dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1; + dstIntensityIndex = -1; + break; + case GL_LUMINANCE_ALPHA: + dstLuminanceIndex = 0; + dstAlphaIndex = 1; + dstRedIndex = dstGreenIndex = dstBlueIndex = -1; + dstIntensityIndex = -1; + break; + case GL_INTENSITY: + dstIntensityIndex = 0; + dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1; + dstLuminanceIndex = -1; + break; + case GL_RGB: + dstRedIndex = 0; + dstGreenIndex = 1; + dstBlueIndex = 2; + dstAlphaIndex = dstLuminanceIndex = dstIntensityIndex = -1; + break; + case GL_RGBA: + dstRedIndex = 0; + dstGreenIndex = 1; + dstBlueIndex = 2; + dstAlphaIndex = 3; + dstLuminanceIndex = dstIntensityIndex = -1; + break; + case GL_COLOR_INDEX: + assert(0); + break; + default: + gl_problem(ctx, "bad dstFormat in _mesa_unpack_ubyte_span()"); + } + + + /* Now return the GLubyte data in the requested dstFormat */ + if (dstRedIndex >= 0) { + GLubyte *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[dstRedIndex] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); + dst += dstComponents; + } + } + + if (dstGreenIndex >= 0) { + GLubyte *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[dstGreenIndex] = FLOAT_TO_UBYTE(rgba[i][GCOMP]); + dst += dstComponents; + } + } + + if (dstBlueIndex >= 0) { + GLubyte *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[dstBlueIndex] = FLOAT_TO_UBYTE(rgba[i][BCOMP]); + dst += dstComponents; + } + } + + if (dstAlphaIndex >= 0) { + GLubyte *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[dstAlphaIndex] = FLOAT_TO_UBYTE(rgba[i][ACOMP]); + dst += dstComponents; + } + } + + if (dstIntensityIndex >= 0) { + GLubyte *dst = dest; + GLuint i; + assert(dstIntensityIndex == 0); + assert(dstComponents == 1); + for (i = 0; i < n; i++) { + /* Intensity comes from red channel */ + dst[i] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); + } + } + + if (dstLuminanceIndex >= 0) { + GLubyte *dst = dest; + GLuint i; + assert(dstLuminanceIndex == 0); + for (i = 0; i < n; i++) { + /* Luminance comes from red channel */ + dst[0] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); + dst += dstComponents; + } + } + } +} + + + +/* + * Unpack a row of color index data from a client buffer according to + * the pixel unpacking parameters. Apply pixel transfer ops if enabled + * and applyTransferOps is true. + * This is (or will be) used by glDrawPixels, glTexImage[123]D, etc. + * + * Args: ctx - the context + * n - number of pixels + * dstType - destination datatype + * dest - destination array + * srcType - source pixel type + * source - source data pointer + * unpacking - pixel unpacking parameters + * applyTransferOps - apply offset/bias/lookup ops? + */ +void +_mesa_unpack_index_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *unpacking, + GLboolean applyTransferOps ) +{ + ASSERT(srcType == GL_BITMAP || + srcType == GL_UNSIGNED_BYTE || + srcType == GL_BYTE || + srcType == GL_UNSIGNED_SHORT || + srcType == GL_SHORT || + srcType == GL_UNSIGNED_INT || + srcType == GL_INT || + srcType == GL_FLOAT); + + ASSERT(dstType == GL_UNSIGNED_BYTE || + dstType == GL_UNSIGNED_SHORT || + dstType == GL_UNSIGNED_INT); + + applyTransferOps &= (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset || ctx->Pixel.MapColorFlag); + + /* + * Try simple cases first + */ + if (!applyTransferOps && srcType == GL_UNSIGNED_BYTE + && dstType == GL_UNSIGNED_BYTE) { + MEMCPY(dest, source, n * sizeof(GLubyte)); + } + else if (!applyTransferOps && srcType == GL_UNSIGNED_INT + && dstType == GL_UNSIGNED_INT && !unpacking->SwapBytes) { + MEMCPY(dest, source, n * sizeof(GLuint)); + } + else { + /* + * general solution + */ + GLuint indexes[MAX_WIDTH]; + assert(n <= MAX_WIDTH); + + extract_uint_indexes(n, indexes, GL_COLOR_INDEX, srcType, source, + unpacking); + + if (applyTransferOps) { + if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset) { + /* shift and offset indexes */ + gl_shift_and_offset_ci(ctx, n, indexes); + } + + if (ctx->Pixel.MapColorFlag) { + /* Apply lookup table */ + gl_map_ci(ctx, n, indexes); + } + } + + /* convert to dest type */ + switch (dstType) { + case GL_UNSIGNED_BYTE: + { + GLubyte *dst = (GLubyte *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLubyte) (indexes[i] & 0xff); + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLuint *dst = (GLuint *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLushort) (indexes[i] & 0xffff); + } + } + break; + case GL_UNSIGNED_INT: + MEMCPY(dest, indexes, n * sizeof(GLuint)); + break; + default: + gl_problem(ctx, "bad dstType in _mesa_unpack_index_span"); + } + } +} + + +/* + * Unpack image data. Apply byteswapping, byte flipping (bitmap). + * Return all image data in a contiguous block. + */ +void * +_mesa_unpack_image( GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack ) +{ + GLint bytesPerRow, compsPerRow; + GLboolean flipBytes, swap2, swap4; + + if (!pixels) + return NULL; /* not necessarily an error */ + + if (width <= 0 || height <= 0 || depth <= 0) + return NULL; /* generate error later */ + + if (format == GL_BITMAP) { + bytesPerRow = (width + 7) >> 3; + flipBytes = !unpack->LsbFirst; + swap2 = swap4 = GL_FALSE; + compsPerRow = 0; + } + else { + const GLint bytesPerPixel = gl_bytes_per_pixel(format, type); + const GLint components = gl_components_in_format(format); + GLint bytesPerComp; + if (bytesPerPixel <= 0 || components <= 0) + return NULL; /* bad format or type. generate error later */ + bytesPerRow = bytesPerPixel * width; + bytesPerComp = bytesPerPixel / components; + flipBytes = GL_FALSE; + swap2 = (bytesPerComp == 2) && unpack->SwapBytes; + swap4 = (bytesPerComp == 4) && unpack->SwapBytes; + compsPerRow = components * width; + assert(compsPerRow >= width); + } + + { + GLubyte *destBuffer = MALLOC(bytesPerRow * height * depth); + GLubyte *dst; + GLint img, row; + if (!destBuffer) + return NULL; /* generate GL_OUT_OF_MEMORY later */ + + dst = destBuffer; + for (img = 0; img < depth; img++) { + for (row = 0; row < height; row++) { + const GLvoid *src = gl_pixel_addr_in_image(unpack, pixels, + width, height, format, type, img, row, 0); + MEMCPY(dst, src, bytesPerRow); + /* byte flipping/swapping */ + if (flipBytes) { + gl_flip_bytes((GLubyte *) dst, bytesPerRow); + } + else if (swap2) { + gl_swap2((GLushort*) dst, compsPerRow); + } + else if (swap4) { + gl_swap4((GLuint*) dst, compsPerRow); + } + dst += bytesPerRow; + } + } + return destBuffer; + } +} diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h index 3fd2ca8b33..80e5ea7c3f 100644 --- a/src/mesa/main/image.h +++ b/src/mesa/main/image.h @@ -1,4 +1,4 @@ -/* $Id: image.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ +/* $Id: image.h,v 1.2 1999/11/03 17:27:05 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -106,4 +106,31 @@ extern GLboolean gl_image_error_test( GLcontext *ctx, const char *msg ); +/* + * New (3.3) functions + */ + + +extern void +_mesa_unpack_ubyte_color_span( const GLcontext *ctx, + GLuint n, GLenum dstFormat, GLubyte dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *unpacking, + GLboolean applyTransferOps ); + + +extern void +_mesa_unpack_index_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *unpacking, + GLboolean applyTransferOps ); + +extern void * +_mesa_unpack_image( GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack ); + + #endif diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 0f6bde4bb0..2a732b178e 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -1,4 +1,4 @@ -/* $Id: teximage.c,v 1.8 1999/10/22 10:43:35 brianp Exp $ */ +/* $Id: teximage.c,v 1.9 1999/11/03 17:27:05 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -25,8 +25,6 @@ */ -/* $XFree86: xc/lib/GL/mesa/src/teximage.c,v 1.3 1999/04/04 00:20:32 dawes Exp $ */ - #ifdef PC_HEADER #include "all.h" #else @@ -55,12 +53,26 @@ /* * NOTES: * - * The internal texture storage convension is an array of N GLubytes - * where N = width * height * components. There is no padding. + * Mesa's native texture datatype is GLubyte. Native formats are + * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, + * and GL_COLOR_INDEX. + * Device drivers are free to implement any internal format they want. */ +static struct gl_pixelstore_attrib defaultPacking = { + 1, /* Alignment */ + 0, /* RowLength */ + 0, /* SkipPixels */ + 0, /* SkipRows */ + 0, /* ImageHeight */ + 0, /* SkipImages */ + GL_FALSE, /* SwapBytes */ + GL_FALSE /* LsbFirst */ +}; + + /* * Compute log base 2 of n. @@ -93,8 +105,8 @@ static int logbase2( int n ) /* * Given an internal texture format enum or 1, 2, 3, 4 return the * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, - * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return -1 if - * invalid enum. + * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. + * Return -1 if invalid enum. */ static GLint decode_internal_format( GLint format ) { @@ -370,32 +382,34 @@ static void set_teximage_component_sizes( struct gl_texture_image *texImage ) #endif + /* - * Given a gl_image, apply the pixel transfer scale, bias, and mapping - * to produce a gl_texture_image. Convert image data to GLubytes. - * Input: image - the incoming gl_image - * internalFormat - desired format of resultant texture - * border - texture border width (0 or 1) - * Return: pointer to a gl_texture_image or NULL if an error occurs. + * This is called by glTexImage[123]D in order to build a gl_texture_image + * object given the client's parameters and image data. + * + * NOTES: Width, height and depth should include the border. + * All texture image parameters should have already been error checked. */ static struct gl_texture_image * -image_to_texture( GLcontext *ctx, const struct gl_image *image, - GLint internalFormat, GLint border ) +make_texture_image( GLcontext *ctx, GLint internalFormat, + GLint width, GLint height, GLint depth, GLint border, + GLenum srcFormat, GLenum srcType, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpacking) { - GLint components; + GLint components, numPixels; struct gl_texture_image *texImage; - GLint numPixels, pixel; - GLboolean scaleOrBias; - assert(image); - assert(image->Width>0); - assert(image->Height>0); - assert(image->Depth>0); + assert(width > 0); + assert(height > 0); + assert(depth > 0); + assert(border == 0 || border == 1); + assert(pixels); + assert(unpacking); - /* internalFormat = decode_internal_format(internalFormat);*/ - components = components_in_intformat(internalFormat); - numPixels = image->Width * image->Height * image->Depth; + /* + * Allocate and initialize the texture_image struct + */ texImage = gl_alloc_texture_image(); if (!texImage) return NULL; @@ -404,458 +418,132 @@ image_to_texture( GLcontext *ctx, const struct gl_image *image, set_teximage_component_sizes( texImage ); texImage->IntFormat = (GLenum) internalFormat; texImage->Border = border; - texImage->Width = image->Width; - texImage->Height = image->Height; - texImage->Depth = image->Depth; - texImage->WidthLog2 = logbase2(image->Width - 2*border); - if (image->Height==1) /* 1-D texture */ + texImage->Width = width; + texImage->Height = height; + texImage->Depth = depth; + texImage->WidthLog2 = logbase2(width - 2 * border); + if (height == 1) /* 1-D texture */ texImage->HeightLog2 = 0; else - texImage->HeightLog2 = logbase2(image->Height - 2*border); - if (image->Depth==1) /* 2-D texture */ + texImage->HeightLog2 = logbase2(height - 2 * border); + if (depth == 1) /* 2-D texture */ texImage->DepthLog2 = 0; else - texImage->DepthLog2 = logbase2(image->Depth - 2*border); + texImage->DepthLog2 = logbase2(depth - 2 * border); texImage->Width2 = 1 << texImage->WidthLog2; texImage->Height2 = 1 << texImage->HeightLog2; texImage->Depth2 = 1 << texImage->DepthLog2; - texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 ); - texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE ); + texImage->MaxLog2 = MAX2(texImage->WidthLog2, texImage->HeightLog2); + + components = components_in_intformat(internalFormat); + numPixels = texImage->Width * texImage->Height * texImage->Depth; + + texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE); if (!texImage->Data) { /* out of memory */ - gl_free_texture_image( texImage ); + gl_free_texture_image(texImage); return NULL; } - /* Determine if scaling and/or biasing is needed */ - if (ctx->Pixel.RedScale!=1.0F || ctx->Pixel.RedBias!=0.0F || - ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F || - ctx->Pixel.BlueScale!=1.0F || ctx->Pixel.BlueBias!=0.0F || - ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) { - scaleOrBias = GL_TRUE; - } - else { - scaleOrBias = GL_FALSE; - } - - switch (image->Type) { - case GL_BITMAP: - { - GLint shift = ctx->Pixel.IndexShift; - GLint offset = ctx->Pixel.IndexOffset; - /* MapIto[RGBA]Size must be powers of two */ - GLint rMask = ctx->Pixel.MapItoRsize-1; - GLint gMask = ctx->Pixel.MapItoGsize-1; - GLint bMask = ctx->Pixel.MapItoBsize-1; - GLint aMask = ctx->Pixel.MapItoAsize-1; - GLint i, j; - GLubyte *srcPtr = (GLubyte *) image->Data; - - assert( image->Format==GL_COLOR_INDEX ); - - for (j=0; jHeight; j++) { - GLubyte bitMask = 128; - for (i=0; iWidth; i++) { - GLint index; - GLubyte red, green, blue, alpha; - - /* Fetch image color index */ - index = (*srcPtr & bitMask) ? 1 : 0; - bitMask = bitMask >> 1; - if (bitMask==0) { - bitMask = 128; - srcPtr++; - } - /* apply index shift and offset */ - if (shift>=0) { - index = (index << shift) + offset; - } - else { - index = (index >> -shift) + offset; - } - /* convert index to RGBA */ - red = (GLint) (ctx->Pixel.MapItoR[index & rMask] * 255.0F); - green = (GLint) (ctx->Pixel.MapItoG[index & gMask] * 255.0F); - blue = (GLint) (ctx->Pixel.MapItoB[index & bMask] * 255.0F); - alpha = (GLint) (ctx->Pixel.MapItoA[index & aMask] * 255.0F); - - /* store texel (components are GLubytes in [0,255]) */ - pixel = j * image->Width + i; - switch (texImage->Format) { - case GL_ALPHA: - texImage->Data[pixel] = alpha; - break; - case GL_LUMINANCE: - texImage->Data[pixel] = red; - break; - case GL_LUMINANCE_ALPHA: - texImage->Data[pixel*2+0] = red; - texImage->Data[pixel*2+1] = alpha; - break; - case GL_INTENSITY: - texImage->Data[pixel] = red; - break; - case GL_RGB: - texImage->Data[pixel*3+0] = red; - texImage->Data[pixel*3+1] = green; - texImage->Data[pixel*3+2] = blue; - break; - case GL_RGBA: - texImage->Data[pixel*4+0] = red; - texImage->Data[pixel*4+1] = green; - texImage->Data[pixel*4+2] = blue; - texImage->Data[pixel*4+3] = alpha; - break; - default: - gl_problem(ctx,"Bad format in image_to_texture"); - return NULL; - } - } - if (bitMask!=128) { - srcPtr++; - } - } - } - break; - case GL_UNSIGNED_BYTE: - if (image->Format == texImage->Format && !scaleOrBias && !ctx->Pixel.MapColorFlag) { - switch (image->Format) { - case GL_COLOR_INDEX: - if (decode_internal_format(internalFormat)!=GL_COLOR_INDEX) { - /* convert color index to RGBA */ - for (pixel=0; pixelData)[pixel]; - index = (GLint) (255.0F * ctx->Pixel.MapItoR[index]); - texImage->Data[pixel] = index; - } - numPixels = 0; - break; - } - case GL_ALPHA: - case GL_LUMINANCE: - case GL_INTENSITY: - MEMCPY(texImage->Data, image->Data, numPixels * 1); - numPixels = 0; - break; - case GL_LUMINANCE_ALPHA: - MEMCPY(texImage->Data, image->Data, numPixels * 2); - numPixels = 0; - break; - case GL_RGB: - MEMCPY(texImage->Data, image->Data, numPixels * 3); - numPixels = 0; - break; - case GL_RGBA: - MEMCPY(texImage->Data, image->Data, numPixels * 4); - numPixels = 0; - break; - default: - break; - } + /* + * OK, the texture image struct has been initialized and the texture + * image memory has been allocated. + * Now fill in the texture image from the source data. + * This includes applying the pixel transfer operations. + */ + + /* try common 2D texture cases first */ + if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag + && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift + && srcType == GL_UNSIGNED_BYTE && depth == 1) { + + if (srcFormat == internalFormat) { + /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA, + * GL_LUMINANCE_ALPHA, etc. texture formats. + */ + const GLubyte *src = gl_pixel_addr_in_image(unpacking, + pixels, width, height, srcFormat, srcType, 0, 0, 0); + const GLubyte *src1 = gl_pixel_addr_in_image(unpacking, + pixels, width, height, srcFormat, srcType, 0, 1, 0); + const GLint srcStride = src1 - src; + GLubyte *dst = texImage->Data; + GLint dstBytesPerRow = width * components * sizeof(GLubyte); + if (srcStride == dstBytesPerRow) { + MEMCPY(dst, src, height * dstBytesPerRow); } - for (pixel=0; pixelFormat) { - case GL_COLOR_INDEX: - if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) { - /* a paletted texture */ - GLint index = ((GLubyte*)image->Data)[pixel]; - red = index; - green = blue = alpha = 0; /* silence compiler warnings */ - } - else { - /* convert color index to RGBA */ - GLint index = ((GLubyte*)image->Data)[pixel]; - red = (GLint) (255.0F * ctx->Pixel.MapItoR[index]); - green = (GLint) (255.0F * ctx->Pixel.MapItoG[index]); - blue = (GLint) (255.0F * ctx->Pixel.MapItoB[index]); - alpha = (GLint) (255.0F * ctx->Pixel.MapItoA[index]); - } - break; - case GL_RGB: - /* Fetch image RGBA values */ - red = ((GLubyte*) image->Data)[pixel*3+0]; - green = ((GLubyte*) image->Data)[pixel*3+1]; - blue = ((GLubyte*) image->Data)[pixel*3+2]; - alpha = 255; - break; - case GL_RGBA: - red = ((GLubyte*) image->Data)[pixel*4+0]; - green = ((GLubyte*) image->Data)[pixel*4+1]; - blue = ((GLubyte*) image->Data)[pixel*4+2]; - alpha = ((GLubyte*) image->Data)[pixel*4+3]; - break; - case GL_RED: - red = ((GLubyte*) image->Data)[pixel]; - green = 0; - blue = 0; - alpha = 255; - break; - case GL_GREEN: - red = 0; - green = ((GLubyte*) image->Data)[pixel]; - blue = 0; - alpha = 255; - break; - case GL_BLUE: - red = 0; - green = 0; - blue = ((GLubyte*) image->Data)[pixel]; - alpha = 255; - break; - case GL_ALPHA: - red = 0; - green = 0; - blue = 0; - alpha = ((GLubyte*) image->Data)[pixel]; - break; - case GL_LUMINANCE: - red = ((GLubyte*) image->Data)[pixel]; - green = red; - blue = red; - alpha = 255; - break; - case GL_LUMINANCE_ALPHA: - red = ((GLubyte*) image->Data)[pixel*2+0]; - green = red; - blue = red; - alpha = ((GLubyte*) image->Data)[pixel*2+1]; - break; - default: - red = green = blue = alpha = 0; - gl_problem(ctx,"Bad format (2) in image_to_texture"); - return NULL; - } - - if (scaleOrBias || ctx->Pixel.MapColorFlag) { - /* Apply RGBA scale and bias */ - GLfloat r = UBYTE_COLOR_TO_FLOAT_COLOR(red); - GLfloat g = UBYTE_COLOR_TO_FLOAT_COLOR(green); - GLfloat b = UBYTE_COLOR_TO_FLOAT_COLOR(blue); - GLfloat a = UBYTE_COLOR_TO_FLOAT_COLOR(alpha); - if (scaleOrBias) { - /* r,g,b,a now in [0,1] */ - r = r * ctx->Pixel.RedScale + ctx->Pixel.RedBias; - g = g * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; - b = b * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; - a = a * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; - r = CLAMP( r, 0.0F, 1.0F ); - g = CLAMP( g, 0.0F, 1.0F ); - b = CLAMP( b, 0.0F, 1.0F ); - a = CLAMP( a, 0.0F, 1.0F ); - } - /* Apply pixel maps */ - if (ctx->Pixel.MapColorFlag) { - GLint ir = (GLint) (r*ctx->Pixel.MapRtoRsize); - GLint ig = (GLint) (g*ctx->Pixel.MapGtoGsize); - GLint ib = (GLint) (b*ctx->Pixel.MapBtoBsize); - GLint ia = (GLint) (a*ctx->Pixel.MapAtoAsize); - r = ctx->Pixel.MapRtoR[ir]; - g = ctx->Pixel.MapGtoG[ig]; - b = ctx->Pixel.MapBtoB[ib]; - a = ctx->Pixel.MapAtoA[ia]; - } - red = (GLint) (r * 255.0F); - green = (GLint) (g * 255.0F); - blue = (GLint) (b * 255.0F); - alpha = (GLint) (a * 255.0F); + else { + GLint i; + for (i = 0; i < height; i++) { + MEMCPY(dst, src, dstBytesPerRow); + src += srcStride; + dst += dstBytesPerRow; } - - /* store texel (components are GLubytes in [0,255]) */ - switch (texImage->Format) { - case GL_COLOR_INDEX: - texImage->Data[pixel] = red; /* really an index */ - break; - case GL_ALPHA: - texImage->Data[pixel] = alpha; - break; - case GL_LUMINANCE: - texImage->Data[pixel] = red; - break; - case GL_LUMINANCE_ALPHA: - texImage->Data[pixel*2+0] = red; - texImage->Data[pixel*2+1] = alpha; - break; - case GL_INTENSITY: - texImage->Data[pixel] = red; - break; - case GL_RGB: - texImage->Data[pixel*3+0] = red; - texImage->Data[pixel*3+1] = green; - texImage->Data[pixel*3+2] = blue; - break; - case GL_RGBA: - texImage->Data[pixel*4+0] = red; - texImage->Data[pixel*4+1] = green; - texImage->Data[pixel*4+2] = blue; - texImage->Data[pixel*4+3] = alpha; - break; - default: - gl_problem(ctx,"Bad format (3) in image_to_texture"); - return NULL; + } + return texImage; /* all done */ + } + else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) { + /* commonly used by Quake */ + const GLubyte *src = gl_pixel_addr_in_image(unpacking, + pixels, width, height, srcFormat, srcType, 0, 0, 0); + const GLubyte *src1 = gl_pixel_addr_in_image(unpacking, + pixels, width, height, srcFormat, srcType, 0, 1, 0); + const GLint srcStride = src1 - src; + GLubyte *dst = texImage->Data; + GLint i, j; + for (i = 0; i < height; i++) { + const GLubyte *s = src; + for (j = 0; j < width; j++) { + *dst++ = *s++; /*red*/ + *dst++ = *s++; /*green*/ + *dst++ = *s++; /*blue*/ + s++; /*alpha*/ } + src += srcStride; } - break; + return texImage; /* all done */ + } + } - case GL_FLOAT: - for (pixel=0; pixelFormat) { - case GL_COLOR_INDEX: - if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) { - /* a paletted texture */ - GLint index = (GLint) ((GLfloat*) image->Data)[pixel]; - red = index; - green = blue = alpha = 0; /* silence compiler warning */ - } - else { - GLint shift = ctx->Pixel.IndexShift; - GLint offset = ctx->Pixel.IndexOffset; - /* MapIto[RGBA]Size must be powers of two */ - GLint rMask = ctx->Pixel.MapItoRsize-1; - GLint gMask = ctx->Pixel.MapItoGsize-1; - GLint bMask = ctx->Pixel.MapItoBsize-1; - GLint aMask = ctx->Pixel.MapItoAsize-1; - /* Fetch image color index */ - GLint index = (GLint) ((GLfloat*) image->Data)[pixel]; - /* apply index shift and offset */ - if (shift>=0) { - index = (index << shift) + offset; - } - else { - index = (index >> -shift) + offset; - } - /* convert index to RGBA */ - red = ctx->Pixel.MapItoR[index & rMask]; - green = ctx->Pixel.MapItoG[index & gMask]; - blue = ctx->Pixel.MapItoB[index & bMask]; - alpha = ctx->Pixel.MapItoA[index & aMask]; - } - break; - case GL_RGB: - /* Fetch image RGBA values */ - red = ((GLfloat*) image->Data)[pixel*3+0]; - green = ((GLfloat*) image->Data)[pixel*3+1]; - blue = ((GLfloat*) image->Data)[pixel*3+2]; - alpha = 1.0; - break; - case GL_RGBA: - red = ((GLfloat*) image->Data)[pixel*4+0]; - green = ((GLfloat*) image->Data)[pixel*4+1]; - blue = ((GLfloat*) image->Data)[pixel*4+2]; - alpha = ((GLfloat*) image->Data)[pixel*4+3]; - break; - case GL_RED: - red = ((GLfloat*) image->Data)[pixel]; - green = 0.0; - blue = 0.0; - alpha = 1.0; - break; - case GL_GREEN: - red = 0.0; - green = ((GLfloat*) image->Data)[pixel]; - blue = 0.0; - alpha = 1.0; - break; - case GL_BLUE: - red = 0.0; - green = 0.0; - blue = ((GLfloat*) image->Data)[pixel]; - alpha = 1.0; - break; - case GL_ALPHA: - red = 0.0; - green = 0.0; - blue = 0.0; - alpha = ((GLfloat*) image->Data)[pixel]; - break; - case GL_LUMINANCE: - red = ((GLfloat*) image->Data)[pixel]; - green = red; - blue = red; - alpha = 1.0; - break; - case GL_LUMINANCE_ALPHA: - red = ((GLfloat*) image->Data)[pixel*2+0]; - green = red; - blue = red; - alpha = ((GLfloat*) image->Data)[pixel*2+1]; - break; - default: - gl_problem(ctx,"Bad format (4) in image_to_texture"); - return NULL; - } - - if (image->Format!=GL_COLOR_INDEX) { - /* Apply RGBA scale and bias */ - if (scaleOrBias) { - red = red * ctx->Pixel.RedScale + ctx->Pixel.RedBias; - green = green * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; - blue = blue * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; - alpha = alpha * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; - red = CLAMP( red, 0.0F, 1.0F ); - green = CLAMP( green, 0.0F, 1.0F ); - blue = CLAMP( blue, 0.0F, 1.0F ); - alpha = CLAMP( alpha, 0.0F, 1.0F ); - } - /* Apply pixel maps */ - if (ctx->Pixel.MapColorFlag) { - GLint ir = (GLint) (red *ctx->Pixel.MapRtoRsize); - GLint ig = (GLint) (green*ctx->Pixel.MapGtoGsize); - GLint ib = (GLint) (blue *ctx->Pixel.MapBtoBsize); - GLint ia = (GLint) (alpha*ctx->Pixel.MapAtoAsize); - red = ctx->Pixel.MapRtoR[ir]; - green = ctx->Pixel.MapGtoG[ig]; - blue = ctx->Pixel.MapBtoB[ib]; - alpha = ctx->Pixel.MapAtoA[ia]; - } - } - /* store texel (components are GLubytes in [0,255]) */ - switch (texImage->Format) { - case GL_COLOR_INDEX: - /* a paletted texture */ - texImage->Data[pixel] = (GLint) (red * 255.0F); - break; - case GL_ALPHA: - texImage->Data[pixel] = (GLint) (alpha * 255.0F); - break; - case GL_LUMINANCE: - texImage->Data[pixel] = (GLint) (red * 255.0F); - break; - case GL_LUMINANCE_ALPHA: - texImage->Data[pixel*2+0] = (GLint) (red * 255.0F); - texImage->Data[pixel*2+1] = (GLint) (alpha * 255.0F); - break; - case GL_INTENSITY: - texImage->Data[pixel] = (GLint) (red * 255.0F); - break; - case GL_RGB: - texImage->Data[pixel*3+0] = (GLint) (red * 255.0F); - texImage->Data[pixel*3+1] = (GLint) (green * 255.0F); - texImage->Data[pixel*3+2] = (GLint) (blue * 255.0F); - break; - case GL_RGBA: - texImage->Data[pixel*4+0] = (GLint) (red * 255.0F); - texImage->Data[pixel*4+1] = (GLint) (green * 255.0F); - texImage->Data[pixel*4+2] = (GLint) (blue * 255.0F); - texImage->Data[pixel*4+3] = (GLint) (alpha * 255.0F); - break; - default: - gl_problem(ctx,"Bad format (5) in image_to_texture"); - return NULL; - } + /* + * General case solutions + */ + if (texImage->Format == GL_COLOR_INDEX) { + /* color index texture */ + const GLint destBytesPerRow = width * components * sizeof(GLubyte); + const GLenum dstType = GL_UNSIGNED_BYTE; + GLubyte *dest = texImage->Data; + GLint img, row; + for (img = 0; img < depth; img++) { + for (row = 0; row < height; row++) { + const GLvoid *source = gl_pixel_addr_in_image(unpacking, + pixels, width, height, srcFormat, srcType, img, row, 0); + _mesa_unpack_index_span(ctx, width, dstType, dest, + srcType, source, unpacking, GL_TRUE); + dest += destBytesPerRow; } - break; - - default: - gl_problem(ctx, "Bad image type in image_to_texture"); - return NULL; + } + } + else { + /* regular, color texture */ + const GLint destBytesPerRow = width * components * sizeof(GLubyte); + const GLenum dstFormat = texImage->Format; + GLubyte *dest = texImage->Data; + GLint img, row; + for (img = 0; img < depth; img++) { + for (row = 0; row < height; row++) { + const GLvoid *source = gl_pixel_addr_in_image(unpacking, + pixels, width, height, srcFormat, srcType, img, row, 0); + _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest, + srcFormat, srcType, source, unpacking, GL_TRUE); + dest += destBytesPerRow; + } + } } - return texImage; + return texImage; /* All done! */ } @@ -945,17 +633,18 @@ make_null_texture( GLcontext *ctx, GLenum internalFormat, /* - * Test glTexImage() parameters for errors. + * Test glTexImage[123]D() parameters for errors. * Input: * dimensions - must be 1 or 2 or 3 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors */ -static GLboolean texture_error_check( GLcontext *ctx, GLenum target, - GLint level, GLint internalFormat, - GLenum format, GLenum type, - GLint dimensions, - GLint width, GLint height, - GLint depth, GLint border ) +static GLboolean +texture_error_check( GLcontext *ctx, GLenum target, + GLint level, GLint internalFormat, + GLenum format, GLenum type, + GLint dimensions, + GLint width, GLint height, + GLint depth, GLint border ) { GLboolean isProxy; GLint iformat; @@ -989,12 +678,9 @@ static GLboolean texture_error_check( GLcontext *ctx, GLenum target, /* Border */ if (border!=0 && border!=1) { if (!isProxy) { - if (dimensions == 1) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(border)" ); - else if (dimensions == 2) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(border)" ); - else if (dimensions == 3) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(border)" ); + char message[100]; + sprintf(message, "glTexImage%dD(border)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); } return GL_TRUE; } @@ -1003,12 +689,9 @@ static GLboolean texture_error_check( GLcontext *ctx, GLenum target, if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize || logbase2( width - 2 * border ) < 0) { if (!isProxy) { - if (dimensions == 1) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(width)" ); - else if (dimensions == 2) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(width)" ); - else if (dimensions == 3) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(width)" ); + char message[100]; + sprintf(message, "glTexImage%dD(width)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); } return GL_TRUE; } @@ -1018,12 +701,11 @@ static GLboolean texture_error_check( GLcontext *ctx, GLenum target, if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize || logbase2( height - 2 * border ) < 0) { if (!isProxy) { - if (dimensions == 2) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(height)" ); - else if (dimensions == 3) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(height)" ); - return GL_TRUE; + char message[100]; + sprintf(message, "glTexImage%dD(height)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); } + return GL_TRUE; } } @@ -1040,23 +722,21 @@ static GLboolean texture_error_check( GLcontext *ctx, GLenum target, /* Level */ if (level<0 || level>=ctx->Const.MaxTextureLevels) { - if (dimensions == 1) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(level)" ); - else if (dimensions == 2) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(level)" ); - else if (dimensions == 3) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(level)" ); + if (!isProxy) { + char message[100]; + sprintf(message, "glTexImage%dD(level)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + } return GL_TRUE; } iformat = decode_internal_format( internalFormat ); if (iformat < 0) { - if (dimensions == 1) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(internalFormat)" ); - else if (dimensions == 2) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(internalFormat)" ); - else if (dimensions == 3) - gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(internalFormat)" ); + if (!isProxy) { + char message[100]; + sprintf(message, "glTexImage%dD(internalFormat)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + } return GL_TRUE; } @@ -1064,12 +744,11 @@ static GLboolean texture_error_check( GLcontext *ctx, GLenum target, /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. */ - if (dimensions == 1) - gl_error( ctx, GL_INVALID_OPERATION, "glTexImage1D(format or type)"); - else if (dimensions == 2) - gl_error( ctx, GL_INVALID_OPERATION, "glTexImage2D(format or type)"); - else if (dimensions == 3) - gl_error( ctx, GL_INVALID_OPERATION, "glTexImage3D(format or type)"); + if (!isProxy) { + char message[100]; + sprintf(message, "glTexImage%dD(format or type)", dimensions); + gl_error(ctx, GL_INVALID_OPERATION, message); + } return GL_TRUE; } @@ -1080,120 +759,389 @@ static GLboolean texture_error_check( GLcontext *ctx, GLenum target, /* - * Called from the API. Note that width includes the border. + * Test glTexSubImage[123]D() parameters for errors. + * Input: + * dimensions - must be 1 or 2 or 3 + * Return: GL_TRUE = an error was detected, GL_FALSE = no errors */ -void gl_TexImage1D( GLcontext *ctx, - GLenum target, GLint level, GLint internalformat, - GLsizei width, GLint border, GLenum format, - GLenum type, struct gl_image *image ) +static GLboolean +subtexture_error_check( GLcontext *ctx, GLint dimensions, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type ) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D"); - - if (target==GL_TEXTURE_1D) { - struct gl_texture_image *teximage; - if (texture_error_check( ctx, target, level, internalformat, - format, type, 1, width, 1, 1, border )) { - /* error in texture image was detected */ - return; - } + struct gl_texture_image *destTex; - /* free current texture image, if any */ - if (texUnit->CurrentD[1]->Image[level]) { - gl_free_texture_image( texUnit->CurrentD[1]->Image[level] ); + if (dimensions == 1) { + if (target != GL_TEXTURE_1D) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); + return GL_TRUE; } - - /* make new texture from source image */ - if (image) { - teximage = image_to_texture(ctx, image, internalformat, border); + } + else if (dimensions == 2) { + if (target != GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); + return GL_TRUE; } - else { - teximage = make_null_texture(ctx, (GLenum) internalformat, - width, 1, 1, border); + } + else if (dimensions == 3) { + if (target != GL_TEXTURE_3D) { + gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); + return GL_TRUE; } + } + else { + gl_problem( ctx, "bad dims in texture_error_check" ); + return GL_TRUE; + } - /* install new texture image */ + if (level < 0 || level >= ctx->Const.MaxTextureLevels) { + gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)"); + return GL_TRUE; + } - texUnit->CurrentD[1]->Image[level] = teximage; - gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); - ctx->NewState |= NEW_TEXTURING; + if (width < 0) { + char message[100]; + sprintf(message, "glTexSubImage%dD(width)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + if (height < 0 && dimensions > 1) { + char message[100]; + sprintf(message, "glTexSubImage%dD(height)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + if (depth < 0 && dimensions > 2) { + char message[100]; + sprintf(message, "glTexSubImage%dD(depth)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } - /* free the source image */ - if (image && image->RefCount==0) { - /* if RefCount>0 then image must be in a display list */ - gl_free_image(image); - } + destTex = texUnit->CurrentD[2]->Image[level]; + if (!destTex) { + gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D"); + return GL_TRUE; + } - /* tell driver about change */ - if (ctx->Driver.TexImage) { - (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, - texUnit->CurrentD[1], - level, internalformat, teximage ); - } + if (xoffset < -((GLint)destTex->Border)) { + gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)"); + return GL_TRUE; } - else if (target==GL_PROXY_TEXTURE_1D) { - /* Proxy texture: check for errors and update proxy state */ - if (texture_error_check( ctx, target, level, internalformat, - format, type, 1, width, 1, 1, border )) { - if (level>=0 && levelConst.MaxTextureLevels) { - MEMSET( ctx->Texture.Proxy1D->Image[level], 0, - sizeof(struct gl_texture_image) ); - } - } - else { - ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format; - set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] ); - ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalformat; - ctx->Texture.Proxy1D->Image[level]->Border = border; - ctx->Texture.Proxy1D->Image[level]->Width = width; - ctx->Texture.Proxy1D->Image[level]->Height = 1; - ctx->Texture.Proxy1D->Image[level]->Depth = 1; + if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { + gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)"); + return GL_TRUE; + } + if (dimensions > 1) { + if (yoffset < -((GLint)destTex->Border)) { + gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)"); + return GL_TRUE; } - if (image && image->RefCount==0) { - /* if RefCount>0 then image must be in a display list */ - gl_free_image(image); + if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { + gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)"); + return GL_TRUE; } } - else { - gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); - return; + if (dimensions > 2) { + if (zoffset < -((GLint)destTex->Border)) { + gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); + return GL_TRUE; + } + if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) { + gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); + return GL_TRUE; + } } -} + if (!gl_is_legal_format_and_type(format, type)) { + char message[100]; + sprintf(message, "glTexSubImage%dD(format or type)", dimensions); + gl_error(ctx, GL_INVALID_ENUM, message); + return GL_TRUE; + } + return GL_FALSE; +} /* - * Called by the API or display list executor. - * Note that width and height include the border. + * Test glCopyTexImage[12]D() parameters for errors. + * Input: dimensions - must be 1 or 2 or 3 + * Return: GL_TRUE = an error was detected, GL_FALSE = no errors */ -void gl_TexImage2D( GLcontext *ctx, - GLenum target, GLint level, GLint internalformat, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, - struct gl_image *image ) +static GLboolean +copytexture_error_check( GLcontext *ctx, GLint dimensions, + GLenum target, GLint level, GLint internalFormat, + GLint width, GLint height, GLint border ) { - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D"); - - if (target==GL_TEXTURE_2D) { - struct gl_texture_image *teximage; - if (texture_error_check( ctx, target, level, internalformat, - format, type, 2, width, height, 1, border )) { - /* error in texture image was detected */ - return; - } + GLint iformat; - /* free current texture image, if any */ - if (texUnit->CurrentD[2]->Image[level]) { - gl_free_texture_image( texUnit->CurrentD[2]->Image[level] ); - } + if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" ); + return GL_TRUE; + } - /* make new texture from source image */ - if (image) { - teximage = image_to_texture(ctx, image, internalformat, border); - } - else { + if (dimensions == 1 && target != GL_TEXTURE_1D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); + return GL_TRUE; + } + else if (dimensions == 2 && target != GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); + return GL_TRUE; + } + + /* Border */ + if (border!=0 && border!=1) { + char message[100]; + sprintf(message, "glCopyTexImage%dD(border)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + + /* Width */ + if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize + || logbase2( width - 2 * border ) < 0) { + char message[100]; + sprintf(message, "glCopyTexImage%dD(width)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + + /* Height */ + if (dimensions >= 2) { + if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize + || logbase2( height - 2 * border ) < 0) { + char message[100]; + sprintf(message, "glCopyTexImage%dD(height)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + } + + /* Level */ + if (level<0 || level>=ctx->Const.MaxTextureLevels) { + char message[100]; + sprintf(message, "glCopyTexImage%dD(level)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + + iformat = decode_internal_format( internalFormat ); + if (iformat < 0) { + char message[100]; + sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + + /* if we get here, the parameters are OK */ + return GL_FALSE; +} + + +static GLboolean +copytexsubimage_error_check( GLcontext *ctx, GLint dimensions, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *teximage; + + if (dimensions == 1 && target != GL_TEXTURE_1D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); + return GL_TRUE; + } + else if (dimensions == 2 && target != GL_TEXTURE_2D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); + return GL_TRUE; + } + else if (dimensions == 3 && target != GL_TEXTURE_3D) { + gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); + return GL_TRUE; + } + + if (level < 0 || level >= ctx->Const.MaxTextureLevels) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(level)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + + if (width < 0) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(width)", dimensions ); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + if (dimensions > 1 && height < 0) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(height)", dimensions ); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + + teximage = texUnit->CurrentD[dimensions]->Image[level]; + if (!teximage) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions); + gl_error(ctx, GL_INVALID_OPERATION, message); + return GL_TRUE; + } + + if (xoffset < -((GLint)teximage->Border)) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + if (dimensions > 1) { + if (yoffset < -((GLint)teximage->Border)) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + /* NOTE: we're adding the border here, not subtracting! */ + if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + } + + if (dimensions > 2) { + if (zoffset < -((GLint)teximage->Border)) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + if (zoffset > (GLint) (teximage->Depth+teximage->Border)) { + char message[100]; + sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions); + gl_error(ctx, GL_INVALID_VALUE, message); + return GL_TRUE; + } + } + + /* if we get here, the parameters are OK */ + return GL_FALSE; +} + + + + +/* + * Called from the API. Note that width includes the border. + */ +void gl_TexImage1D( GLcontext *ctx, GLenum target, GLint level, + GLint internalformat, + GLsizei width, GLint border, GLenum format, + GLenum type, const GLvoid *pixels ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D"); + + if (target==GL_TEXTURE_1D) { + struct gl_texture_image *teximage; + if (texture_error_check( ctx, target, level, internalformat, + format, type, 1, width, 1, 1, border )) { + /* error in texture image was detected */ + return; + } + + /* free current texture image, if any */ + if (texUnit->CurrentD[1]->Image[level]) { + gl_free_texture_image( texUnit->CurrentD[1]->Image[level] ); + } + + /* make new texture from source image */ + if (pixels) { + teximage = make_texture_image(ctx, internalformat, width, 1, 1, + border, format, type, pixels, &ctx->Unpack); + } + else { + teximage = make_null_texture(ctx, (GLenum) internalformat, + width, 1, 1, border); + } + + /* install new texture image */ + texUnit->CurrentD[1]->Image[level] = teximage; + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); + ctx->NewState |= NEW_TEXTURING; + + /* tell driver about change */ + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, + texUnit->CurrentD[1], + level, internalformat, teximage ); + } + } + else if (target==GL_PROXY_TEXTURE_1D) { + /* Proxy texture: check for errors and update proxy state */ + if (texture_error_check( ctx, target, level, internalformat, + format, type, 1, width, 1, 1, border )) { + if (level>=0 && levelConst.MaxTextureLevels) { + MEMSET( ctx->Texture.Proxy1D->Image[level], 0, + sizeof(struct gl_texture_image) ); + } + } + else { + ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format; + set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] ); + ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalformat; + ctx->Texture.Proxy1D->Image[level]->Border = border; + ctx->Texture.Proxy1D->Image[level]->Width = width; + ctx->Texture.Proxy1D->Image[level]->Height = 1; + ctx->Texture.Proxy1D->Image[level]->Depth = 1; + } + } + else { + gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); + return; + } +} + + +void gl_TexImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D"); + + if (target==GL_TEXTURE_2D) { + struct gl_texture_image *teximage; + if (texture_error_check( ctx, target, level, internalformat, + format, type, 2, width, height, 1, border )) { + /* error in texture image was detected */ + return; + } + + /* free current texture image, if any */ + if (texUnit->CurrentD[2]->Image[level]) { + gl_free_texture_image( texUnit->CurrentD[2]->Image[level] ); + } + + /* make new texture from source image */ + if (pixels) { + teximage = make_texture_image(ctx, internalformat, width, height, 1, + border, format, type, pixels, &ctx->Unpack); + } + else { teximage = make_null_texture(ctx, (GLenum) internalformat, width, height, 1, border); } @@ -1203,12 +1151,6 @@ void gl_TexImage2D( GLcontext *ctx, gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] ); ctx->NewState |= NEW_TEXTURING; - /* free the source image */ - if (image && image->RefCount==0) { - /* if RefCount>0 then image must be in a display list */ - gl_free_image(image); - } - /* tell driver about change */ if (ctx->Driver.TexImage) { (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, @@ -1234,10 +1176,6 @@ void gl_TexImage2D( GLcontext *ctx, ctx->Texture.Proxy2D->Image[level]->Height = height; ctx->Texture.Proxy2D->Image[level]->Depth = 1; } - if (image && image->RefCount==0) { - /* if RefCount>0 then image must be in a display list */ - gl_free_image(image); - } } else { gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); @@ -1251,16 +1189,16 @@ void gl_TexImage2D( GLcontext *ctx, * Called by the API or display list executor. * Note that width and height include the border. */ -void gl_TexImage3DEXT( GLcontext *ctx, - GLenum target, GLint level, GLint internalformat, - GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, - struct gl_image *image ) +void gl_TexImage3D( GLcontext *ctx, GLenum target, GLint level, + GLint internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels ) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3DEXT"); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D"); - if (target==GL_TEXTURE_3D_EXT) { + if (target==GL_TEXTURE_3D) { struct gl_texture_image *teximage; if (texture_error_check( ctx, target, level, internalformat, format, type, 3, width, height, depth, @@ -1275,8 +1213,9 @@ void gl_TexImage3DEXT( GLcontext *ctx, } /* make new texture from source image */ - if (image) { - teximage = image_to_texture(ctx, image, internalformat, border); + if (pixels) { + teximage = make_texture_image(ctx, internalformat, width, height, + depth, border, format, type, pixels, &ctx->Unpack); } else { teximage = make_null_texture(ctx, (GLenum) internalformat, @@ -1288,12 +1227,6 @@ void gl_TexImage3DEXT( GLcontext *ctx, gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] ); ctx->NewState |= NEW_TEXTURING; - /* free the source image */ - if (image && image->RefCount==0) { - /* if RefCount>0 then image must be in a display list */ - gl_free_image(image); - } - /* tell driver about change */ if (ctx->Driver.TexImage) { (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, @@ -1320,13 +1253,9 @@ void gl_TexImage3DEXT( GLcontext *ctx, ctx->Texture.Proxy3D->Image[level]->Height = height; ctx->Texture.Proxy3D->Image[level]->Depth = depth; } - if (image && image->RefCount==0) { - /* if RefCount>0 then image must be in a display list */ - gl_free_image(image); - } } else { - gl_error( ctx, GL_INVALID_ENUM, "glTexImage3DEXT(target)" ); + gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); return; } } @@ -1461,560 +1390,257 @@ void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level, GLenum format, -/* - * Unpack the image data given to glTexSubImage[12]D. - * This function is just a wrapper for gl_unpack_image() but it does - * some extra error checking. - */ -struct gl_image * -gl_unpack_texsubimage( GLcontext *ctx, GLint width, GLint height, - GLenum format, GLenum type, const GLvoid *pixels ) +void gl_TexSubImage1D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels ) { - if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { - return NULL; - } + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *destTex; - if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){ - return NULL; + if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, + width, 1, 1, format, type)) { + /* error was detected */ + return; } - if (gl_sizeof_type(type)<=0) { - return NULL; - } + destTex = texUnit->CurrentD[1]->Image[level]; + assert(destTex); - return gl_unpack_image3D( ctx, width, height, 1, format, type, pixels, &ctx->Unpack ); -} + if (width == 0 || !pixels) + return; /* no-op, not an error */ -/* - * Unpack the image data given to glTexSubImage3D. - * This function is just a wrapper for gl_unpack_image() but it does - * some extra error checking. - */ -struct gl_image * -gl_unpack_texsubimage3D( GLcontext *ctx, GLint width, GLint height, - GLint depth, GLenum format, GLenum type, - const GLvoid *pixels ) -{ - if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { - return NULL; + /* + * Replace the texture subimage + */ + { + const GLint texComponents = components_in_intformat(destTex->Format); + const GLenum texFormat = destTex->Format; + const GLint xoffsetb = xoffset + destTex->Border; + GLubyte *dst = destTex->Data + xoffsetb * texComponents; + if (texFormat == GL_COLOR_INDEX) { + /* color index texture */ + const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels, + width, 1, format, type, 0, 0, 0); + _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, + type, src, &ctx->Unpack, GL_TRUE); + } + else { + /* color texture */ + const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels, + width, 1, format, type, 0, 0, 0); + _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, + format, type, src, &ctx->Unpack, GL_TRUE); + } } - if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){ - return NULL; - } + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); - if (gl_sizeof_type(type)<=0) { - return NULL; + /* + * Inform device driver of texture image change. + */ + if (ctx->Driver.TexSubImage) { + (*ctx->Driver.TexSubImage)(ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], + level, xoffset, 0, width, 1, + texUnit->CurrentD[1]->Image[level]->IntFormat, + destTex ); + } + else { + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], + level, + texUnit->CurrentD[1]->Image[level]->IntFormat, + destTex ); + } } - - return gl_unpack_image3D( ctx, width, height, depth, format, type, pixels, - &ctx->Unpack ); } - -void gl_TexSubImage1D( GLcontext *ctx, - GLenum target, GLint level, GLint xoffset, - GLsizei width, GLenum format, GLenum type, - struct gl_image *image ) +void gl_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_image *destTex; - if (target!=GL_TEXTURE_1D) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); - return; - } - if (level<0 || level>=ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(level)" ); + if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, + width, height, 1, format, type)) { + /* error was detected */ return; } - destTex = texUnit->CurrentD[1]->Image[level]; - if (!destTex) { - gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage1D" ); - return; - } + destTex = texUnit->CurrentD[2]->Image[level]; + assert(destTex); - if (xoffset < -((GLint)destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset)" ); - return; - } - if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset+width)" ); - return; - } + if (width == 0 || height == 0 || !pixels) + return; /* no-op, not an error */ - if (image) { - /* unpacking must have been error-free */ - const GLint texcomponents = components_in_intformat(destTex->Format); - const GLint xoffsetb = xoffset + destTex->Border; - if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) { - /* Simple case, just byte copy image data into texture image */ - /* row by row. */ - GLubyte *dst = destTex->Data + texcomponents * xoffsetb; - GLubyte *src = (GLubyte *) image->Data; - MEMCPY( dst, src, width * texcomponents ); + /* + * Replace the texture subimage + */ + { + const GLint texComponents = components_in_intformat(destTex->Format); + const GLenum texFormat = destTex->Format; + const GLint xoffsetb = xoffset + destTex->Border; + const GLint yoffsetb = yoffset + destTex->Border; + GLubyte *dst = destTex->Data + + (yoffsetb * destTex->Width + xoffsetb) * texComponents; + if (texFormat == GL_COLOR_INDEX) { + /* color index texture */ + const GLint stride = destTex->Width * sizeof(GLubyte); + GLint row; + for (row = 0; row < height; row++) { + const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels, + width, height, format, type, 0, row, 0); + _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, + type, src, &ctx->Unpack, GL_TRUE); + dst += stride; + } } else { - /* General case, convert image pixels into texels, scale, bias, etc */ - struct gl_texture_image *subTexImg = image_to_texture(ctx, image, - destTex->IntFormat, destTex->Border); - GLubyte *dst = destTex->Data + texcomponents * xoffsetb; - GLubyte *src = subTexImg->Data; - MEMCPY( dst, src, width * texcomponents ); - gl_free_texture_image(subTexImg); + /* color texture */ + const GLint stride = destTex->Width * texComponents * sizeof(GLubyte); + GLint row; + for (row = 0; row < height; row++) { + const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels, + width, height, format, type, 0, row, 0); + _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, + format, type, src, &ctx->Unpack, GL_TRUE); + dst += stride; + } } + } - /* if the image's reference count is zero, delete it now */ - if (image->RefCount==0) { - gl_free_image(image); + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] ); + + /* + * Inform device driver of texture image change. + */ + if (ctx->Driver.TexSubImage) { + (*ctx->Driver.TexSubImage)(ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], + level, xoffset, yoffset, width, height, + texUnit->CurrentD[2]->Image[level]->IntFormat, + destTex ); + } + else { + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], + level, + texUnit->CurrentD[2]->Image[level]->IntFormat, + destTex ); } + } +} - gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); - - /* tell driver about change */ - if (ctx->Driver.TexSubImage) { - (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D, - texUnit->CurrentD[1], level, - xoffset,0,width,1, - texUnit->CurrentD[1]->Image[level]->IntFormat, - destTex ); - } - else { - if (ctx->Driver.TexImage) { - (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level, - texUnit->CurrentD[1]->Image[level]->IntFormat, - destTex ); - } - } - } - else { - /* if no image, an error must have occured, do more testing now */ - GLint components, size; - - if (width<0) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(width)" ); - return; - } - if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" ); - return; - } - components = components_in_intformat( format ); - if (components<0 || format==GL_STENCIL_INDEX - || format==GL_DEPTH_COMPONENT){ - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" ); - return; - } - size = gl_sizeof_type( type ); - if (size<=0) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(type)" ); - return; - } - /* if we get here, probably ran out of memory during unpacking */ - gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D" ); - } -} - -void gl_TexSubImage2D( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, +void gl_TexSubImage3D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - struct gl_image *image ) + const GLvoid *pixels ) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_image *destTex; - if (target!=GL_TEXTURE_2D) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); - return; - } - if (level<0 || level>=ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)" ); - return; - } - - destTex = texUnit->CurrentD[2]->Image[level]; - if (!destTex) { - gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage2D" ); - return; - } - - if (xoffset < -((GLint)destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset)" ); - return; - } - if (yoffset < -((GLint)destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset)" ); - return; - } - if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset+width)" ); - return; - } - if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset+height)" ); - return; - } - - if (image) { - /* unpacking must have been error-free */ - const GLint texcomponents = components_in_intformat(destTex->Format); - const GLint xoffsetb = xoffset + destTex->Border; - const GLint yoffsetb = yoffset + destTex->Border; - - if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) { - /* Simple case, just byte copy image data into texture image */ - /* row by row. */ - GLubyte *dst = destTex->Data - + (yoffsetb * destTex->Width + xoffsetb) * texcomponents; - const GLubyte *src = (const GLubyte *) image->Data; - GLint j; - for (j=0;jWidth * texcomponents * sizeof(GLubyte); - src += width * texcomponents * sizeof(GLubyte); - } - } - else if (image->Type==GL_UNSIGNED_BYTE - && texcomponents==3 && image->Components == 4 ) { - /* 32 bit (padded) to 24 bit case, used heavily by quake */ - GLubyte *dst = destTex->Data - + (yoffsetb * destTex->Width + xoffsetb) * texcomponents; - const GLubyte *src = (const GLubyte *) image->Data; - GLint j; - for (j=0;jWidth - width) * texcomponents * sizeof(GLubyte); - } - } - else { - /* General case, convert image pixels into texels, scale, bias, etc */ - struct gl_texture_image *subTexImg = image_to_texture(ctx, image, - destTex->IntFormat, destTex->Border); - GLubyte *dst = destTex->Data - + (yoffsetb * destTex->Width + xoffsetb) * texcomponents; - const GLubyte *src = subTexImg->Data; - GLint j; - for (j=0;jWidth * texcomponents * sizeof(GLubyte); - src += width * texcomponents * sizeof(GLubyte); - } - gl_free_texture_image(subTexImg); - } - - /* if the image's reference count is zero, delete it now */ - if (image->RefCount==0) { - gl_free_image(image); - } - - gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] ); - - /* tell driver about change */ - if (ctx->Driver.TexSubImage) { - (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, - xoffset, yoffset, width, height, - texUnit->CurrentD[2]->Image[level]->IntFormat, - destTex ); - } - else { - if (ctx->Driver.TexImage) { - (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, - texUnit->CurrentD[2]->Image[level]->IntFormat, - destTex ); - } - } - } - else { - /* if no image, an error must have occured, do more testing now */ - GLint components, size; - - if (width<0) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(width)" ); - return; - } - if (height<0) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(height)" ); - return; - } - if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" ); - return; - } - components = gl_components_in_format( format ); - if (components<0 || format==GL_STENCIL_INDEX - || format==GL_DEPTH_COMPONENT){ - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(format)" ); - return; - } - size = gl_sizeof_packed_type( type ); - if (size<=0) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(type)" ); - return; - } - /* if we get here, probably ran out of memory during unpacking */ - gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D" ); - } -} - - - -void gl_TexSubImage3DEXT( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - struct gl_image *image ) -{ - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_image *destTex; - - if (target!=GL_TEXTURE_3D_EXT) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(target)" ); - return; - } - if (level<0 || level>=ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(level)" ); + if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, + width, height, depth, format, type)) { + /* error was detected */ return; } destTex = texUnit->CurrentD[3]->Image[level]; - if (!destTex) { - gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage3DEXT" ); - return; - } + assert(destTex); - if (xoffset < -((GLint)destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset)" ); - return; - } - if (yoffset < -((GLint)destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset)" ); - return; - } - if (zoffset < -((GLint)destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset)" ); - return; - } - if (xoffset + width > (GLint) (destTex->Width+destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset+width)" ); - return; - } - if (yoffset + height > (GLint) (destTex->Height+destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset+height)" ); - return; - } - if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset+depth)" ); - return; - } + if (width == 0 || height == 0 || height == 0 || !pixels) + return; /* no-op, not an error */ - if (image) { - /* unpacking must have been error-free */ - GLint texcomponents = components_in_intformat(destTex->Format); - GLint dstRectArea = destTex->Width * destTex->Height; - GLint srcRectArea = width * height; + /* + * Replace the texture subimage + */ + { + const GLint texComponents = components_in_intformat(destTex->Format); + const GLenum texFormat = destTex->Format; const GLint xoffsetb = xoffset + destTex->Border; const GLint yoffsetb = yoffset + destTex->Border; const GLint zoffsetb = zoffset + destTex->Border; - - if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) { - /* Simple case, just byte copy image data into texture image */ - /* row by row. */ - GLubyte *dst = destTex->Data - + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb) - * texcomponents; - GLubyte *src = (GLubyte *) image->Data; - GLint j, k; - for(k=0;kWidth * texcomponents; - src += width * texcomponents; - } - dst += dstRectArea * texcomponents * sizeof(GLubyte); - src += srcRectArea * texcomponents * sizeof(GLubyte); + GLint dstRectArea = destTex->Width * destTex->Height; + GLubyte *dst = destTex->Data + + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb) + * texComponents; + + if (texFormat == GL_COLOR_INDEX) { + /* color index texture */ + const GLint stride = destTex->Width * sizeof(GLubyte); + GLint img, row; + for (img = 0; img < depth; img++) { + for (row = 0; row < height; row++) { + const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels, + width, height, format, type, img, row, 0); + _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, + type, src, &ctx->Unpack, GL_TRUE); + dst += stride; + } } } else { - /* General case, convert image pixels into texels, scale, bias, etc */ - struct gl_texture_image *subTexImg = image_to_texture(ctx, image, - destTex->IntFormat, destTex->Border); - GLubyte *dst = destTex->Data - + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb) - * texcomponents; - GLubyte *src = subTexImg->Data; - GLint j, k; - for(k=0;kWidth * texcomponents; - src += width * texcomponents; - } - dst += dstRectArea * texcomponents * sizeof(GLubyte); - src += srcRectArea * texcomponents * sizeof(GLubyte); + /* color texture */ + const GLint stride = destTex->Width * texComponents * sizeof(GLubyte); + GLint img, row; + for (img = 0; img < depth; img++) { + for (row = 0; row < height; row++) { + const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels, + width, height, format, type, img, row, 0); + _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, + format, type, src, &ctx->Unpack, GL_TRUE); + dst += stride; + } } - gl_free_texture_image(subTexImg); - } - /* if the image's reference count is zero, delete it now */ - if (image->RefCount==0) { - gl_free_image(image); - } - - gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] ); - - /* tell driver about change */ - if (ctx->Driver.TexImage) { - (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3], - level, texUnit->CurrentD[3]->Image[level]->IntFormat, - destTex ); } } - else { - /* if no image, an error must have occured, do more testing now */ - GLint components, size; - if (width<0) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(width)" ); - return; - } - if (height<0) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(height)" ); - return; - } - if (depth<0) { - gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(depth)" ); - return; - } - if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" ); - return; - } - components = gl_components_in_format( format ); - if (components<0 || format==GL_STENCIL_INDEX - || format==GL_DEPTH_COMPONENT){ - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" ); - return; - } - size = gl_sizeof_packed_type( type ); - if (size<=0) { - gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(type)" ); - return; - } - /* if we get here, probably ran out of memory during unpacking */ - gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage3DEXT" ); - } + gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); + + /* + * Inform device driver of texture image change. + */ + /* XXX todo */ } /* * Read an RGBA image from the frame buffer. + * This is used by glCopyTexSubImage[12]D(). * Input: ctx - the context * x, y - lower left corner * width, height - size of region to read - * format - one of GL_RED, GL_RGB, GL_LUMINANCE, etc. - * Return: gl_image pointer or NULL if out of memory + * Return: pointer to block of GL_RGBA, GLubyte data. */ -static struct gl_image *read_color_image( GLcontext *ctx, GLint x, GLint y, - GLsizei width, GLsizei height, - GLenum format ) +static GLubyte * +read_color_image( GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height ) { - struct gl_image *image; - GLubyte *imgptr; - GLint components; - GLint i, j; + GLint stride, i; + GLubyte *image, *dst; - components = components_in_intformat( format ); - - /* - * Allocate image struct and image data buffer - */ - image = MALLOC_STRUCT( gl_image ); - if (image) { - image->Width = width; - image->Height = height; - image->Depth = 1; - image->Components = components; - image->Format = format; - image->Type = GL_UNSIGNED_BYTE; - image->RefCount = 0; - image->Data = (GLubyte *) MALLOC( width * height * components ); - if (!image->Data) { - FREE(image); - return NULL; - } - } - else { + image = MALLOC(width * height * 4 * sizeof(GLubyte)); + if (!image) return NULL; - } - - imgptr = (GLubyte *) image->Data; /* Select buffer to read from */ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer ); - for (j=0;jDriver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer ); @@ -2024,113 +1650,76 @@ static struct gl_image *read_color_image( GLcontext *ctx, GLint x, GLint y, - -void gl_CopyTexImage1D( GLcontext *ctx, - GLenum target, GLint level, - GLenum internalformat, +void gl_CopyTexImage1D( GLcontext *ctx, GLenum target, GLint level, + GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border ) { - GLint format; - struct gl_image *teximage; - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D"); - if (target!=GL_TEXTURE_1D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); - return; - } - if (level<0 || level>=ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(level)" ); - return; - } - if (border!=0 && border!=1) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(border)" ); - return; - } - if (width < 2*border || width > 2 + ctx->Const.MaxTextureSize || width<0) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(width)" ); - return; - } - format = decode_internal_format( internalformat ); - if (format<0 || (internalformat>=1 && internalformat<=4)) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(format)" ); - return; - } - teximage = read_color_image( ctx, x, y, width, 1, (GLenum) format ); - if (!teximage) { - gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" ); - return; + if (!copytexture_error_check(ctx, 1, target, level, internalFormat, + width, 1, border)) { + GLubyte *image = read_color_image( ctx, x, y, width, 1 ); + if (!image) { + gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" ); + return; + } + (*ctx->Exec.TexImage1D)( ctx, target, level, internalFormat, width, + border, GL_RGBA, GL_UNSIGNED_BYTE, image ); + FREE(image); } - - gl_TexImage1D( ctx, target, level, internalformat, width, - border, GL_RGBA, GL_UNSIGNED_BYTE, teximage ); - - /* teximage was freed in gl_TexImage1D */ } -void gl_CopyTexImage2D( GLcontext *ctx, - GLenum target, GLint level, GLenum internalformat, +void gl_CopyTexImage2D( GLcontext *ctx, GLenum target, GLint level, + GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) { - GLint format; - struct gl_image *teximage; - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D"); - if (target!=GL_TEXTURE_2D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); - return; - } - if (level<0 || level>=ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(level)" ); - return; - } - if (border!=0 && border!=1) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(border)" ); - return; - } - if (width<2*border || width>2+ctx->Const.MaxTextureSize || width<0) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width)" ); - return; - } - if (height<2*border || height>2+ctx->Const.MaxTextureSize || height<0) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(height)" ); - return; - } - format = decode_internal_format( internalformat ); - if (format<0 || (internalformat>=1 && internalformat<=4)) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(format)" ); - return; - } - teximage = read_color_image( ctx, x, y, width, height, (GLenum) format ); - if (!teximage) { - gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" ); - return; + if (!copytexture_error_check(ctx, 2, target, level, internalFormat, + width, height, border)) { + GLubyte *image = read_color_image( ctx, x, y, width, height ); + if (!image) { + gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" ); + return; + } + { + struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = defaultPacking; + (ctx->Exec.TexImage2D)( ctx, target, level, internalFormat, width, + height, border, GL_RGBA, GL_UNSIGNED_BYTE, image ); + ctx->Unpack = save; /* restore */ + } + FREE(image); } - - gl_TexImage2D( ctx, target, level, internalformat, width, height, - border, GL_RGBA, GL_UNSIGNED_BYTE, teximage ); - - /* teximage was freed in gl_TexImage2D */ } - /* * Do the work of glCopyTexSubImage[123]D. - * TODO: apply pixel bias scale and mapping. */ -static void copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest, - GLint width, GLint height, - GLint srcx, GLint srcy, - GLint dstx, GLint dsty, GLint dstz ) +static void +copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest, + GLint width, GLint height, + GLint srcx, GLint srcy, + GLint dstx, GLint dsty, GLint dstz ) { - GLint i, j; + static struct gl_pixelstore_attrib packing = { + 1, /* Alignment */ + 0, /* RowLength */ + 0, /* SkipPixels */ + 0, /* SkipRows */ + 0, /* ImageHeight */ + 0, /* SkipImages */ + GL_FALSE, /* SwapBytes */ + GL_FALSE /* LsbFirst */ + }; + + GLint i; GLint format, components, rectarea; GLint texwidth, texheight, zoffset; @@ -2148,54 +1737,15 @@ static void copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest, /* Select buffer to read from */ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer ); - for (j=0;jData + ( zoffset + (dsty+j) * texwidth + dstx) * components; - - switch (format) { - case GL_ALPHA: - for (i=0;iData + ( zoffset + (dsty+i) * texwidth + dstx) * components; + _mesa_unpack_ubyte_color_span(ctx, width, format, dst, + GL_RGBA, GL_UNSIGNED_BYTE, rgba, + &packing, GL_TRUE); + } /* Restore drawing buffer */ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer ); @@ -2204,213 +1754,83 @@ static void copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest, -void gl_CopyTexSubImage1D( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint x, GLint y, GLsizei width ) +void gl_CopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width ) { - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_image *teximage; - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D"); - if (target!=GL_TEXTURE_1D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); - return; - } - if (level<0 || level>=ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(level)" ); - return; - } - if (width<0) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(width)" ); - return; - } - - teximage = texUnit->CurrentD[1]->Image[level]; - if (teximage) { - if (xoffset < -((GLint)teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(xoffset)" ); - return; - } - /* NOTE: we're adding the border here, not subtracting! */ - if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, - "glCopyTexSubImage1D(xoffset+width)" ); - return; - } + if (!copytexsubimage_error_check(ctx, 1, target, level, + xoffset, 0, 0, x, y, width, 1)) { + struct gl_texture_unit *texUnit; + struct gl_texture_image *teximage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + teximage = texUnit->CurrentD[1]->Image[level]; + assert(teximage); if (teximage->Data) { - copy_tex_sub_image( ctx, teximage, width, 1, x, y, xoffset, 0, 0 ); - - /* tell driver about change */ - if (ctx->Driver.TexSubImage) { - (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D, - texUnit->CurrentD[1], level, - xoffset,0,width,1, - teximage->IntFormat, - teximage ); - } - else { - if (ctx->Driver.TexImage) { - (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level, - teximage->IntFormat, - teximage ); - } + copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0); + /* tell driver about the change */ + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, + texUnit->CurrentD[1], + level, teximage->IntFormat, teximage ); } } } - else { - gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage1D" ); - } } -void gl_CopyTexSubImage2D( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint x, GLint y, GLsizei width, GLsizei height ) +void gl_CopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height ) { - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_image *teximage; - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D"); - if (target!=GL_TEXTURE_2D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); - return; - } - if (level<0 || level>=ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(level)" ); - return; - } - if (width<0) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(width)" ); - return; - } - if (height<0) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(height)" ); - return; - } - - teximage = texUnit->CurrentD[2]->Image[level]; - - if (teximage) { - if (xoffset < -((GLint)teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(xoffset)" ); - return; - } - if (yoffset < -((GLint)teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(yoffset)" ); - return; - } - /* NOTE: we're adding the border here, not subtracting! */ - if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, - "glCopyTexSubImage2D(xoffset+width)" ); - return; - } - if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, - "glCopyTexSubImage2D(yoffset+height)" ); - return; - } + if (!copytexsubimage_error_check(ctx, 2, target, level, + xoffset, yoffset, 0, x, y, width, height)) { + struct gl_texture_unit *texUnit; + struct gl_texture_image *teximage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + teximage = texUnit->CurrentD[2]->Image[level]; + assert(teximage); if (teximage->Data) { - copy_tex_sub_image( ctx, teximage, width, height, - x, y, xoffset, yoffset, 0 ); - /* tell driver about change */ - if (ctx->Driver.TexSubImage) { - (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, - xoffset, yoffset, width, height, - teximage->IntFormat, - teximage ); - } - else { - if (ctx->Driver.TexImage) { - (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, - teximage->IntFormat, - teximage ); - } + copy_tex_sub_image(ctx, teximage, width, height, + x, y, xoffset, yoffset, 0); + /* tell driver about the change */ + if (ctx->Driver.TexImage) { + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, + texUnit->CurrentD[2], + level, teximage->IntFormat, teximage ); } } } - else { - gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D" ); - } } -void gl_CopyTexSubImage3DEXT( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height ) +void gl_CopyTexSubImage3D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height ) { - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_image *teximage; - - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3DEXT"); - if (target!=GL_TEXTURE_3D) { - gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3DEXT(target)" ); - return; - } - if (level<0 || level>=ctx->Const.MaxTextureLevels) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(level)" ); - return; - } - if (width<0) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(width)" ); - return; - } - if (height<0) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(height)" ); - return; - } - - teximage = texUnit->CurrentD[3]->Image[level]; - if (teximage) { - if (xoffset < -((GLint)teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(xoffset)" ); - return; - } - if (yoffset < -((GLint)teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(yoffset)" ); - return; - } - if (zoffset < -((GLint)teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(zoffset)" ); - return; - } - /* NOTE: we're adding the border here, not subtracting! */ - if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, - "glCopyTexSubImage3DEXT(xoffset+width)" ); - return; - } - if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, - "glCopyTexSubImage3DEXT(yoffset+height)" ); - return; - } - if (zoffset > (GLint) (teximage->Depth+teximage->Border)) { - gl_error( ctx, GL_INVALID_VALUE, - "glCopyTexSubImage3DEXT(zoffset+depth)" ); - return; - } + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D"); + if (!copytexsubimage_error_check(ctx, 3, target, level, + xoffset, yoffset, zoffset, x, y, width, height)) { + struct gl_texture_unit *texUnit; + struct gl_texture_image *teximage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + teximage = texUnit->CurrentD[3]->Image[level]; + assert(teximage); if (teximage->Data) { - copy_tex_sub_image( ctx, teximage, width, height, - x, y, xoffset, yoffset, zoffset); - - /* tell driver about change */ + copy_tex_sub_image(ctx, teximage, width, height, + x, y, xoffset, yoffset, zoffset); + /* tell driver about the change */ if (ctx->Driver.TexImage) { - (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3], - level, teximage->IntFormat, - teximage ); + (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D, + texUnit->CurrentD[3], + level, teximage->IntFormat, teximage ); } } } - else { - gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage3DEXT" ); - } } diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h index eb72f961e5..032f44ce7f 100644 --- a/src/mesa/main/teximage.h +++ b/src/mesa/main/teximage.h @@ -1,4 +1,4 @@ -/* $Id: teximage.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ +/* $Id: teximage.h,v 1.2 1999/11/03 17:27:05 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -25,9 +25,6 @@ */ - - - #ifndef TEXIMAGE_H #define TEXIMAGE_H @@ -44,57 +41,6 @@ extern struct gl_texture_image *gl_alloc_texture_image( void ); extern void gl_free_texture_image( struct gl_texture_image *teximage ); -extern struct gl_image * -gl_unpack_texsubimage( GLcontext *ctx, GLint width, GLint height, - GLenum format, GLenum type, const GLvoid *pixels ); - - -extern struct gl_image * -gl_unpack_texsubimage3D( GLcontext *ctx, GLint width, GLint height,GLint depth, - GLenum format, GLenum type, const GLvoid *pixels ); - - -extern struct gl_texture_image * -gl_unpack_texture( GLcontext *ctx, - GLint dimensions, - GLenum target, - GLint level, - GLint internalformat, - GLsizei width, GLsizei height, - GLint border, - GLenum format, GLenum type, - const GLvoid *pixels ); - -extern struct gl_texture_image * -gl_unpack_texture3D( GLcontext *ctx, - GLint dimensions, - GLenum target, - GLint level, - GLint internalformat, - GLsizei width, GLsizei height, GLsizei depth, - GLint border, - GLenum format, GLenum type, - const GLvoid *pixels ); - - -extern void gl_tex_image_1D( GLcontext *ctx, - GLenum target, GLint level, GLint internalformat, - GLsizei width, GLint border, GLenum format, - GLenum type, const GLvoid *pixels ); - - -extern void gl_tex_image_2D( GLcontext *ctx, - GLenum target, GLint level, GLint internalformat, - GLsizei width, GLint height, GLint border, - GLenum format, GLenum type, - const GLvoid *pixels ); - -extern void gl_tex_image_3D( GLcontext *ctx, - GLenum target, GLint level, GLint internalformat, - GLsizei width, GLint height, GLint depth, - GLint border, - GLenum format, GLenum type, - const GLvoid *pixels ); /*** API entry points ***/ @@ -103,22 +49,21 @@ extern void gl_tex_image_3D( GLcontext *ctx, extern void gl_TexImage1D( GLcontext *ctx, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, - GLenum type, struct gl_image *teximage ); + GLenum type, const GLvoid *pixels ); extern void gl_TexImage2D( GLcontext *ctx, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, - struct gl_image *teximage ); + const GLvoid *pixels ); -extern void gl_TexImage3DEXT( GLcontext *ctx, - GLenum target, GLint level, GLint internalformat, - GLsizei width, GLsizei height, GLsizei depth, - GLint border, - GLenum format, GLenum type, - struct gl_image *teximage ); +extern void gl_TexImage3D( GLcontext *ctx, + GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels ); extern void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level, @@ -129,7 +74,7 @@ extern void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level, extern void gl_TexSubImage1D( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, - struct gl_image *image ); + const GLvoid *pixels ); extern void gl_TexSubImage2D( GLcontext *ctx, @@ -137,15 +82,15 @@ extern void gl_TexSubImage2D( GLcontext *ctx, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, - struct gl_image *image ); + const GLvoid *pixels ); -extern void gl_TexSubImage3DEXT( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - struct gl_image *image ); +extern void gl_TexSubImage3D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid *pixels ); extern void gl_CopyTexImage1D( GLcontext *ctx, @@ -175,12 +120,12 @@ extern void gl_CopyTexSubImage2D( GLcontext *ctx, GLsizei width, GLsizei height ); -extern void gl_CopyTexSubImage3DEXT( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint zoffset, - GLint x, GLint y, - GLsizei width, GLsizei height ); +extern void gl_CopyTexSubImage3D( GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, + GLint x, GLint y, + GLsizei width, GLsizei height ); #endif -- cgit v1.2.3