| @@ -1,4 +1,4 @@ | |||
| /* $Id: teximage.c,v 1.44 2000/09/01 22:01:12 brianp Exp $ */ | |||
| /* $Id: teximage.c,v 1.45 2000/09/02 17:52:21 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| @@ -670,184 +670,157 @@ adjust_texture_size_for_convolution(const GLcontext *ctx, GLuint dimensions, | |||
| /* Need this to prevent an out-of-bounds memory access when using | |||
| * X86 optimized code. | |||
| */ | |||
| #ifdef USE_X86_ASM | |||
| # define EXTRA_BYTE 1 | |||
| #else | |||
| # define EXTRA_BYTE 0 | |||
| #endif | |||
| /* | |||
| * Called by glTexImage[123]D. Fill in a texture image with data given | |||
| * by the client. All pixel transfer and unpack modes are handled here. | |||
| * Input: dimensions (1, 2, or 3) | |||
| * texImage - destination texture image (we'll malloc the memory) | |||
| * width, height, depth - size of source image | |||
| * srcFormat, srcType - source image format and type | |||
| * pixels - source image data | |||
| * srcPacking - source image packing parameters | |||
| * | |||
| * NOTE: All texture image parameters should have already been error checked. | |||
| * | |||
| * NOTE: the texImage dimensions and source image dimensions must be correct | |||
| * with respect to convolution with border mode = reduce. | |||
| * This function is used to move user image data into a texture image. | |||
| * We handle full texture images and subtexture images. We also take | |||
| * care of all image transfer operations here, including convolution. | |||
| * Input: | |||
| * dstXoffset, dstYoffset, dstZoffset - offsets in pixels | |||
| * dstRowStride, dstImageStride - strides in bytes | |||
| */ | |||
| static void | |||
| make_texture_image( GLcontext *ctx, GLuint dimensions, | |||
| struct gl_texture_image *texImage, | |||
| GLint width, GLint height, GLint depth, | |||
| GLenum srcFormat, GLenum srcType, const GLvoid *pixels, | |||
| fill_texture_image( GLcontext *ctx, GLuint dimensions, | |||
| GLenum texFormat, GLubyte *texAddr, | |||
| GLint srcWidth, GLint srcHeight, GLint srcDepth, | |||
| GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, | |||
| GLint dstRowStride, GLint dstImageStride, | |||
| GLenum srcFormat, GLenum srcType, const GLvoid *srcAddr, | |||
| const struct gl_pixelstore_attrib *srcPacking) | |||
| { | |||
| GLint components, numPixels; | |||
| GLint internalFormat, border; | |||
| GLint texComponents; | |||
| ASSERT(ctx); | |||
| ASSERT(texImage); | |||
| ASSERT(!texImage->Data); | |||
| ASSERT(pixels); | |||
| ASSERT(dimensions >= 1 && dimensions <= 3); | |||
| ASSERT(texAddr); | |||
| ASSERT(srcWidth >= 1); | |||
| ASSERT(srcHeight >= 1); | |||
| ASSERT(srcDepth >= 1); | |||
| ASSERT(dstXoffset >= 0); | |||
| ASSERT(dstYoffset >= 0); | |||
| ASSERT(dstZoffset >= 0); | |||
| ASSERT(dstRowStride >= 0); | |||
| ASSERT(dstImageStride >= 0); | |||
| ASSERT(srcAddr); | |||
| ASSERT(srcPacking); | |||
| internalFormat = texImage->IntFormat; | |||
| border = texImage->Border; | |||
| components = components_in_intformat(internalFormat); | |||
| ASSERT(width > 0); | |||
| ASSERT(height > 0); | |||
| ASSERT(depth > 0); | |||
| ASSERT(border == 0 || border == 1); | |||
| ASSERT(components); | |||
| numPixels = width * height * depth; | |||
| texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE); | |||
| if (!texImage->Data) | |||
| return; /* out of memory */ | |||
| /* | |||
| * 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. | |||
| */ | |||
| if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) | |||
| _mesa_update_image_transfer_state(ctx); | |||
| texComponents = components_in_intformat(texFormat); | |||
| /* try common 2D texture cases first */ | |||
| if (!ctx->ImageTransferState && srcType == GL_UNSIGNED_BYTE && depth == 1) { | |||
| if (!ctx->ImageTransferState && dimensions == 2 | |||
| && srcType == GL_UNSIGNED_BYTE) { | |||
| if (srcFormat == internalFormat || | |||
| (srcFormat == GL_LUMINANCE && internalFormat == 1) || | |||
| (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) || | |||
| (srcFormat == GL_RGB && internalFormat == 3) || | |||
| (srcFormat == GL_RGBA && internalFormat == 4)) { | |||
| if (srcFormat == texFormat) { | |||
| /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA, | |||
| * GL_LUMINANCE_ALPHA, etc. texture formats. | |||
| * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy(). | |||
| */ | |||
| const GLubyte *src = (const GLubyte *) _mesa_image_address( | |||
| srcPacking, pixels, width, height, srcFormat, srcType, 0, 0, 0); | |||
| const GLint srcStride = _mesa_image_row_stride(srcPacking, width, | |||
| srcFormat, srcType); | |||
| GLubyte *dst = texImage->Data; | |||
| GLint dstBytesPerRow = width * components * sizeof(GLubyte); | |||
| if (srcStride == dstBytesPerRow) { | |||
| MEMCPY(dst, src, height * dstBytesPerRow); | |||
| srcPacking, srcAddr, srcWidth, srcHeight, | |||
| srcFormat, srcType, 0, 0, 0); | |||
| const GLint srcRowStride = _mesa_image_row_stride(srcPacking, | |||
| srcWidth, srcFormat, srcType); | |||
| const GLint widthInBytes = srcWidth * texComponents; | |||
| GLubyte *dst = texAddr + dstYoffset * dstRowStride | |||
| + dstXoffset * texComponents * sizeof(GLubyte); | |||
| if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) { | |||
| MEMCPY(dst, src, srcHeight * widthInBytes); | |||
| } | |||
| else { | |||
| GLint i; | |||
| for (i = 0; i < height; i++) { | |||
| MEMCPY(dst, src, dstBytesPerRow); | |||
| src += srcStride; | |||
| dst += dstBytesPerRow; | |||
| for (i = 0; i < srcHeight; i++) { | |||
| MEMCPY(dst, src, widthInBytes); | |||
| src += srcRowStride; | |||
| dst += dstRowStride; | |||
| } | |||
| } | |||
| return; /* all done */ | |||
| } | |||
| else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) { | |||
| else if (srcFormat == GL_RGBA && texFormat == GL_RGB) { | |||
| /* commonly used by Quake */ | |||
| const GLubyte *src = (const GLubyte *) _mesa_image_address( | |||
| srcPacking, pixels, width, height, srcFormat, srcType, 0, 0, 0); | |||
| const GLint srcStride = _mesa_image_row_stride(srcPacking, width, | |||
| srcFormat, srcType); | |||
| GLubyte *dst = texImage->Data; | |||
| srcPacking, srcAddr, srcWidth, srcHeight, | |||
| srcFormat, srcType, 0, 0, 0); | |||
| const GLint srcRowStride = _mesa_image_row_stride(srcPacking, | |||
| srcWidth, srcFormat, srcType); | |||
| GLubyte *dst = texAddr + dstYoffset * dstRowStride | |||
| + dstXoffset * texComponents * sizeof(GLubyte); | |||
| GLint i, j; | |||
| for (i = 0; i < height; i++) { | |||
| for (i = 0; i < srcHeight; i++) { | |||
| const GLubyte *s = src; | |||
| for (j = 0; j < width; j++) { | |||
| *dst++ = *s++; /*red*/ | |||
| *dst++ = *s++; /*green*/ | |||
| *dst++ = *s++; /*blue*/ | |||
| s++; /*alpha*/ | |||
| GLubyte *d = dst; | |||
| for (j = 0; j < srcWidth; j++) { | |||
| *d++ = *s++; /*red*/ | |||
| *d++ = *s++; /*green*/ | |||
| *d++ = *s++; /*blue*/ | |||
| s++; /*alpha*/ | |||
| } | |||
| src += srcStride; | |||
| src += srcRowStride; | |||
| dst += dstRowStride; | |||
| } | |||
| return; /* all done */ | |||
| } | |||
| } | |||
| /* | |||
| * General case solutions | |||
| */ | |||
| if (texImage->Format == GL_COLOR_INDEX) { | |||
| if (texFormat == GL_COLOR_INDEX) { | |||
| /* color index texture */ | |||
| const GLint destBytesPerRow = width * components * sizeof(GLubyte); | |||
| const GLenum dstType = GL_UNSIGNED_BYTE; | |||
| GLubyte *destTex = texImage->Data; | |||
| const GLenum texType = GL_UNSIGNED_BYTE; | |||
| GLint img, row; | |||
| for (img = 0; img < depth; img++) { | |||
| for (row = 0; row < height; row++) { | |||
| const GLvoid *srcAddr = _mesa_image_address(srcPacking, | |||
| pixels, width, height, srcFormat, srcType, img, row, 0); | |||
| _mesa_unpack_index_span(ctx, width, dstType, destTex, | |||
| srcType, srcAddr, srcPacking, | |||
| GLubyte *dest = texAddr + dstZoffset * dstImageStride | |||
| + dstYoffset * dstRowStride | |||
| + dstXoffset * texComponents * sizeof(GLubyte); | |||
| for (img = 0; img < srcDepth; img++) { | |||
| GLubyte *destRow = dest; | |||
| for (row = 0; row < srcHeight; row++) { | |||
| const GLvoid *src = _mesa_image_address(srcPacking, | |||
| srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); | |||
| _mesa_unpack_index_span(ctx, srcWidth, texType, destRow, | |||
| srcType, src, srcPacking, | |||
| ctx->ImageTransferState); | |||
| destTex += destBytesPerRow; | |||
| destRow += dstRowStride; | |||
| } | |||
| dest += dstImageStride; | |||
| } | |||
| } | |||
| else { | |||
| /* regular, color texture */ | |||
| GLint destBytesPerRow; | |||
| const GLenum dstFormat = texImage->Format; | |||
| GLubyte *destTex = texImage->Data; | |||
| GLint img, row; | |||
| GLint convWidth = width, convHeight = height; | |||
| if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) || | |||
| (dimensions >= 2 && | |||
| (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) | |||
| )) { | |||
| (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) || | |||
| (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) { | |||
| /* | |||
| * Fill texture image with convolution | |||
| */ | |||
| GLint img, row; | |||
| GLint convWidth = srcWidth, convHeight = srcHeight; | |||
| GLfloat *tmpImage, *convImage; | |||
| tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); | |||
| tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat)); | |||
| if (!tmpImage) { | |||
| gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); | |||
| return; | |||
| } | |||
| convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); | |||
| convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat)); | |||
| if (!convImage) { | |||
| gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); | |||
| FREE(tmpImage); | |||
| return; | |||
| } | |||
| for (img = 0; img < depth; img++) { | |||
| for (img = 0; img < srcDepth; img++) { | |||
| const GLfloat *srcf; | |||
| GLfloat *dstf = tmpImage; | |||
| GLubyte *dest; | |||
| /* unpack and do transfer ops up to convolution */ | |||
| for (row = 0; row < height; row++) { | |||
| const GLvoid *srcAddr = _mesa_image_address(srcPacking, | |||
| pixels, width, height, srcFormat, srcType, img, row, 0); | |||
| _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dstf, | |||
| srcFormat, srcType, srcAddr, srcPacking, | |||
| ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS, | |||
| GL_TRUE); | |||
| dstf += width * 4; | |||
| for (row = 0; row < srcHeight; row++) { | |||
| const GLvoid *src = _mesa_image_address(srcPacking, | |||
| srcAddr, srcWidth, srcHeight, | |||
| srcFormat, srcType, img, row, 0); | |||
| _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf, | |||
| srcFormat, srcType, src, srcPacking, | |||
| ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS, | |||
| GL_TRUE); | |||
| dstf += srcWidth * 4; | |||
| } | |||
| /* convolve */ | |||
| @@ -869,16 +842,17 @@ make_texture_image( GLcontext *ctx, GLuint dimensions, | |||
| /* packing and transfer ops after convolution */ | |||
| srcf = convImage; | |||
| destBytesPerRow = convWidth * components * sizeof(GLubyte); | |||
| dest = texAddr + (dstZoffset + img) * dstImageStride | |||
| + dstYoffset * dstRowStride; | |||
| for (row = 0; row < convHeight; row++) { | |||
| _mesa_pack_float_rgba_span(ctx, convWidth, | |||
| (const GLfloat (*)[4]) srcf, | |||
| dstFormat, GL_UNSIGNED_BYTE, | |||
| destTex, &_mesa_native_packing, | |||
| texFormat, GL_UNSIGNED_BYTE, | |||
| dest, &_mesa_native_packing, | |||
| ctx->ImageTransferState | |||
| & IMAGE_POST_CONVOLUTION_BITS); | |||
| srcf += convWidth * 4; | |||
| destTex += destBytesPerRow; | |||
| dest += dstRowStride; | |||
| } | |||
| } | |||
| @@ -886,17 +860,25 @@ make_texture_image( GLcontext *ctx, GLuint dimensions, | |||
| FREE(tmpImage); | |||
| } | |||
| else { | |||
| /* no convolution */ | |||
| destBytesPerRow = width * components * sizeof(GLubyte); | |||
| for (img = 0; img < depth; img++) { | |||
| for (row = 0; row < height; row++) { | |||
| /* | |||
| * no convolution | |||
| */ | |||
| GLint img, row; | |||
| GLubyte *dest = texAddr + dstZoffset * dstImageStride | |||
| + dstYoffset * dstRowStride | |||
| + dstXoffset * texComponents * sizeof(GLubyte); | |||
| for (img = 0; img < srcDepth; img++) { | |||
| GLubyte *destRow = dest; | |||
| for (row = 0; row < srcHeight; row++) { | |||
| const GLvoid *srcAddr = _mesa_image_address(srcPacking, | |||
| pixels, width, height, srcFormat, srcType, img, row, 0); | |||
| _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destTex, | |||
| srcFormat, srcType, srcAddr, srcPacking, | |||
| ctx->ImageTransferState); | |||
| destTex += destBytesPerRow; | |||
| srcAddr, srcWidth, srcHeight, | |||
| srcFormat, srcType, img, row, 0); | |||
| _mesa_unpack_ubyte_color_span(ctx, srcWidth, texFormat, destRow, | |||
| srcFormat, srcType, srcAddr, srcPacking, | |||
| ctx->ImageTransferState); | |||
| destRow += dstRowStride; | |||
| } | |||
| dest += dstImageStride; | |||
| } | |||
| } | |||
| } | |||
| @@ -904,6 +886,66 @@ make_texture_image( GLcontext *ctx, GLuint dimensions, | |||
| /* Need this to prevent an out-of-bounds memory access when using | |||
| * X86 optimized code. | |||
| */ | |||
| #ifdef USE_X86_ASM | |||
| # define EXTRA_BYTE 1 | |||
| #else | |||
| # define EXTRA_BYTE 0 | |||
| #endif | |||
| /* | |||
| * Called by glTexImage[123]D. Fill in a texture image with data given | |||
| * by the client. All pixel transfer and unpack modes are handled here. | |||
| * Input: dimensions (1, 2, or 3) | |||
| * texImage - destination texture image (we'll malloc the memory) | |||
| * width, height, depth - size of source image | |||
| * srcFormat, srcType - source image format and type | |||
| * pixels - source image data | |||
| * srcPacking - source image packing parameters | |||
| * | |||
| * NOTE: All texture image parameters should have already been error checked. | |||
| * | |||
| * NOTE: the texImage dimensions and source image dimensions must be correct | |||
| * with respect to convolution with border mode = reduce. | |||
| */ | |||
| static void | |||
| make_texture_image( GLcontext *ctx, GLuint dimensions, | |||
| struct gl_texture_image *texImage, | |||
| GLint width, GLint height, GLint depth, | |||
| GLenum srcFormat, GLenum srcType, const GLvoid *pixels, | |||
| const struct gl_pixelstore_attrib *srcPacking) | |||
| { | |||
| const GLint internalFormat = texImage->IntFormat; | |||
| const GLint components = components_in_intformat(internalFormat); | |||
| GLint convWidth = width, convHeight = height; | |||
| if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) { | |||
| _mesa_update_image_transfer_state(ctx); | |||
| } | |||
| if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) { | |||
| adjust_texture_size_for_convolution(ctx, dimensions, | |||
| &convWidth, &convHeight); | |||
| } | |||
| texImage->Data = (GLubyte *) MALLOC(convWidth * convHeight * depth | |||
| * components + EXTRA_BYTE); | |||
| if (!texImage->Data) | |||
| return; /* out of memory */ | |||
| fill_texture_image(ctx, dimensions, texImage->Format, texImage->Data, | |||
| width, height, depth, 0, 0, 0, | |||
| convWidth * components * sizeof(GLubyte), | |||
| convWidth * convHeight * components * sizeof(GLubyte), | |||
| srcFormat, srcType, pixels, srcPacking); | |||
| } | |||
| /* | |||
| * glTexImage[123]D can accept a NULL image pointer. In this case we | |||
| * create a texture image with unspecified image contents per the OpenGL | |||
| @@ -2213,9 +2255,13 @@ _mesa_TexSubImage1D( GLenum target, GLint level, | |||
| struct gl_texture_object *texObj; | |||
| struct gl_texture_image *texImage; | |||
| GLboolean success = GL_FALSE; | |||
| GLsizei postConvWidth; | |||
| postConvWidth = width; | |||
| adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL); | |||
| if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, | |||
| width, 1, 1, format, type)) { | |||
| postConvWidth, 1, 1, format, type)) { | |||
| return; /* error was detected */ | |||
| } | |||
| @@ -2237,10 +2283,6 @@ _mesa_TexSubImage1D( GLenum target, GLint level, | |||
| } | |||
| if (!success) { | |||
| /* XXX if Driver.TexSubImage1D, unpack image and try again? */ | |||
| const GLint texComponents = components_in_intformat(texImage->Format); | |||
| const GLenum texFormat = texImage->Format; | |||
| const GLint xoffsetb = xoffset + texImage->Border; | |||
| GLboolean retain = GL_TRUE; | |||
| if (!texImage->Data) { | |||
| _mesa_get_teximage_from_driver( ctx, target, level, texObj ); | |||
| @@ -2251,25 +2293,10 @@ _mesa_TexSubImage1D( GLenum target, GLint level, | |||
| return; /* we're really out of luck! */ | |||
| } | |||
| if (texFormat == GL_COLOR_INDEX) { | |||
| /* color index texture */ | |||
| GLubyte *dst = texImage->Data + xoffsetb * texComponents; | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width, | |||
| 1, format, type, 0, 0, 0); | |||
| _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, | |||
| type, src, &ctx->Unpack, | |||
| ctx->ImageTransferState); | |||
| } | |||
| else { | |||
| /* color texture */ | |||
| GLubyte *dst = texImage->Data + xoffsetb * texComponents; | |||
| const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width, | |||
| 1, format, type, 0, 0, 0); | |||
| /* XXX change for convolution */ | |||
| _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format, | |||
| type, src, &ctx->Unpack, | |||
| ctx->ImageTransferState); | |||
| } | |||
| fill_texture_image(ctx, 1, texImage->Format, texImage->Data, | |||
| width, 1, 1, xoffset, 0, 0, /* size and offsets */ | |||
| 0, 0, /* strides */ | |||
| format, type, pixels, &ctx->Unpack); | |||
| if (ctx->Driver.TexImage1D) { | |||
| (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, | |||
| @@ -2283,8 +2310,6 @@ _mesa_TexSubImage1D( GLenum target, GLint level, | |||
| texImage->Data = NULL; | |||
| } | |||
| } | |||
| /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/ | |||
| } | |||
| @@ -2300,9 +2325,14 @@ _mesa_TexSubImage2D( GLenum target, GLint level, | |||
| struct gl_texture_object *texObj; | |||
| struct gl_texture_image *texImage; | |||
| GLboolean success = GL_FALSE; | |||
| GLsizei postConvWidth, postConvHeight; | |||
| postConvWidth = width; | |||
| postConvHeight = height; | |||
| adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight); | |||
| if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, | |||
| width, height, 1, format, type)) { | |||
| postConvWidth, postConvHeight, 1, format, type)) { | |||
| return; /* error was detected */ | |||
| } | |||
| @@ -2324,14 +2354,8 @@ _mesa_TexSubImage2D( GLenum target, GLint level, | |||
| } | |||
| if (!success) { | |||
| /* XXX if Driver.TexSubImage2D, unpack image and try again? */ | |||
| const GLint texComponents = components_in_intformat(texImage->Format); | |||
| const GLenum texFormat = texImage->Format; | |||
| const GLint xoffsetb = xoffset + texImage->Border; | |||
| const GLint yoffsetb = yoffset + texImage->Border; | |||
| const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width, | |||
| format, type); | |||
| const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte); | |||
| const GLint texComps = components_in_intformat(texImage->Format); | |||
| const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte); | |||
| GLboolean retain = GL_TRUE; | |||
| if (!texImage->Data) { | |||
| @@ -2343,38 +2367,10 @@ _mesa_TexSubImage2D( GLenum target, GLint level, | |||
| return; /* we're really out of luck! */ | |||
| } | |||
| if (texFormat == GL_COLOR_INDEX) { | |||
| /* color index texture */ | |||
| GLubyte *dst = texImage->Data | |||
| + (yoffsetb * texImage->Width + xoffsetb) * texComponents; | |||
| const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, 0, 0, 0); | |||
| GLint row; | |||
| for (row = 0; row < height; row++) { | |||
| _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type, | |||
| (const GLvoid *) src, &ctx->Unpack, | |||
| ctx->ImageTransferState); | |||
| src += srcStride; | |||
| dst += dstStride; | |||
| } | |||
| } | |||
| else { | |||
| /* color texture */ | |||
| GLubyte *dst = texImage->Data | |||
| + (yoffsetb * texImage->Width + xoffsetb) * texComponents; | |||
| const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, 0, 0, 0); | |||
| GLint row; | |||
| /* XXX change for convolution */ | |||
| for (row = 0; row < height; row++) { | |||
| _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format, | |||
| type, (const GLvoid *) src, | |||
| &ctx->Unpack, | |||
| ctx->ImageTransferState); | |||
| src += srcStride; | |||
| dst += dstStride; | |||
| } | |||
| } | |||
| fill_texture_image(ctx, 2, texImage->Format, texImage->Data, | |||
| width, height, 1, xoffset, yoffset, 0, | |||
| texRowStride, 0, | |||
| format, type, pixels, &ctx->Unpack); | |||
| if (ctx->Driver.TexImage2D) { | |||
| (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format, | |||
| @@ -2441,57 +2437,25 @@ _mesa_TexSubImage3D( GLenum target, GLint level, | |||
| } | |||
| if (!success) { | |||
| /* XXX if Driver.TexSubImage3D, unpack image and try again? */ | |||
| const GLint texComponents = components_in_intformat(texImage->Format); | |||
| const GLenum texFormat = texImage->Format; | |||
| const GLint xoffsetb = xoffset + texImage->Border; | |||
| const GLint yoffsetb = yoffset + texImage->Border; | |||
| const GLint zoffsetb = zoffset + texImage->Border; | |||
| const GLint texWidth = texImage->Width; | |||
| const GLint dstRectArea = texWidth * texImage->Height; | |||
| const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, | |||
| width, format, type); | |||
| const GLint dstStride = texWidth * texComponents * sizeof(GLubyte); | |||
| const GLint texComps = components_in_intformat(texImage->Format); | |||
| const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte); | |||
| const GLint texImgStride = texRowStride * texImage->Height; | |||
| GLboolean retain = GL_TRUE; | |||
| if (texFormat == GL_COLOR_INDEX) { | |||
| /* color index texture */ | |||
| GLint img, row; | |||
| for (img = 0; img < depth; img++) { | |||
| const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, img, 0, 0); | |||
| GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea | |||
| + yoffsetb * texWidth + xoffsetb) * texComponents; | |||
| for (row = 0; row < height; row++) { | |||
| _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, | |||
| type, (const GLvoid *) src, | |||
| &ctx->Unpack, ctx->ImageTransferState); | |||
| src += srcStride; | |||
| dst += dstStride; | |||
| } | |||
| } | |||
| } | |||
| else { | |||
| /* color texture */ | |||
| GLint img, row; | |||
| /* XXX convolution */ | |||
| for (img = 0; img < depth; img++) { | |||
| const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, | |||
| width, height, format, type, img, 0, 0); | |||
| GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea | |||
| + yoffsetb * texWidth + xoffsetb) * texComponents; | |||
| for (row = 0; row < height; row++) { | |||
| _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, | |||
| format, type, | |||
| (const GLvoid *) src, | |||
| &ctx->Unpack, | |||
| ctx->ImageTransferState); | |||
| src += srcStride; | |||
| dst += dstStride; | |||
| } | |||
| if (!texImage->Data) { | |||
| _mesa_get_teximage_from_driver( ctx, target, level, texObj ); | |||
| if (!texImage->Data) { | |||
| make_null_texture(texImage); | |||
| } | |||
| if (!texImage->Data) | |||
| return; /* we're really out of luck! */ | |||
| } | |||
| fill_texture_image(ctx, 3, texImage->Format, texImage->Data, | |||
| width, height, depth, xoffset, yoffset, zoffset, | |||
| texRowStride, texImgStride, | |||
| format, type, pixels, &ctx->Unpack); | |||
| if (ctx->Driver.TexImage3D) { | |||
| (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format, | |||
| GL_UNSIGNED_BYTE, texImage->Data, | |||
| @@ -2510,7 +2474,7 @@ _mesa_TexSubImage3D( GLenum target, GLint level, | |||
| /* | |||
| * Read an RGBA image from the frame buffer. | |||
| * This is used by glCopyTexSubImage[12]D(). | |||
| * This is used by glCopyTex[Sub]Image[12]D(). | |||
| * Input: ctx - the context | |||
| * x, y - lower left corner | |||
| * width, height - size of region to read | |||
| @@ -2531,8 +2495,6 @@ read_color_image( GLcontext *ctx, GLint x, GLint y, | |||
| (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, | |||
| ctx->Pixel.DriverReadBuffer ); | |||
| /* XXX TODO we have to apply pixel transfer ops here! */ | |||
| dst = image; | |||
| stride = width * 4 * sizeof(GLubyte); | |||
| for (i = 0; i < height; i++) { | |||
| @@ -2568,12 +2530,11 @@ _mesa_CopyTexImage1D( GLenum target, GLint level, | |||
| if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D | |||
| || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level, | |||
| internalFormat, x, y, width, border)) | |||
| { | |||
| internalFormat, x, y, width, border)) { | |||
| struct gl_pixelstore_attrib unpackSave; | |||
| /* get image from framebuffer */ | |||
| GLubyte *image = read_color_image( ctx, x, y, width, 1 ); | |||
| GLubyte *image = read_color_image( ctx, x, y, width, 1 ); | |||
| if (!image) { | |||
| gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" ); | |||
| return; | |||
| @@ -2609,12 +2570,11 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, | |||
| if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D | |||
| || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level, | |||
| internalFormat, x, y, width, height, border)) | |||
| { | |||
| internalFormat, x, y, width, height, border)) { | |||
| struct gl_pixelstore_attrib unpackSave; | |||
| /* get image from framebuffer */ | |||
| GLubyte *image = read_color_image( ctx, x, y, width, height ); | |||
| GLubyte *image = read_color_image( ctx, x, y, width, height ); | |||
| if (!image) { | |||
| gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" ); | |||
| return; | |||