X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fteximage.c;h=8a002b6755c6c1d742ea22e5d2e3d86ca8b3a868;hb=29a7d7784def4f37d3fe38a123a17836dd7fafc0;hp=a005d2935fa2f86f184057db93576ad1d7db8f43;hpb=f8e6d19f3f40931be741b44d3edf210c38e13f0f;p=mesa.git diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index a005d2935fa..8a002b6755c 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -42,7 +42,6 @@ #include "mfeatures.h" #include "state.h" #include "texcompress.h" -#include "texfetch.h" #include "teximage.h" #include "texstate.h" #include "texpal.h" @@ -58,27 +57,6 @@ -/** - * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE - * elsewhere. - */ -void * -_mesa_alloc_texmemory(GLsizei bytes) -{ - return _mesa_align_malloc(bytes, 512); -} - - -/** - * Free texture memory allocated with _mesa_alloc_texmemory() - */ -void -_mesa_free_texmemory(void *m) -{ - _mesa_align_free(m); -} - - /** * Return the simple base format for a given internal texture format. * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. @@ -150,30 +128,17 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) ; /* fallthrough */ } - if (ctx->Extensions.EXT_texture_format_BGRA8888) { + /* GL_BGRA can be an internal format *only* in OpenGL ES (1.x or 2.0). + */ + if (ctx->API != API_OPENGL) { switch (internalFormat) { - case GL_BGRA_EXT: + case GL_BGRA: return GL_RGBA; default: ; /* fallthrough */ } } - if (ctx->Extensions.EXT_paletted_texture) { - switch (internalFormat) { - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - return GL_COLOR_INDEX; - default: - ; /* fallthrough */ - } - } - if (ctx->Extensions.ARB_depth_texture) { switch (internalFormat) { case GL_DEPTH_COMPONENT: @@ -366,6 +331,7 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) case GL_RGBA8I_EXT: case GL_RGBA16I_EXT: case GL_RGBA32I_EXT: + case GL_RGB10_A2UI: return GL_RGBA; case GL_RGB8UI_EXT: case GL_RGB16UI_EXT: @@ -527,6 +493,34 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) } } + if (ctx->Extensions.OES_compressed_ETC1_RGB8_texture) { + switch (internalFormat) { + case GL_ETC1_RGB8_OES: + return GL_RGB; + default: + ; /* fallthrough */ + } + } + + if (ctx->API == API_OPENGLES) { + switch (internalFormat) { + case GL_PALETTE4_RGB8_OES: + case GL_PALETTE4_R5_G6_B5_OES: + case GL_PALETTE8_RGB8_OES: + case GL_PALETTE8_R5_G6_B5_OES: + return GL_RGB; + case GL_PALETTE4_RGBA8_OES: + case GL_PALETTE8_RGB5_A1_OES: + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE4_RGB5_A1_OES: + case GL_PALETTE8_RGBA8_OES: + case GL_PALETTE8_RGBA4_OES: + return GL_RGBA; + default: + ; /* fallthrough */ + } + } + return -1; /* error */ } @@ -538,8 +532,7 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) GLuint _mesa_tex_target_to_face(GLenum target) { - if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) + if (_mesa_is_cube_face(target)) return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; else return 0; @@ -565,7 +558,8 @@ _mesa_set_tex_image(struct gl_texture_object *tObj, ASSERT(tObj); ASSERT(texImage); - ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0); + if (target == GL_TEXTURE_RECTANGLE_NV || target == GL_TEXTURE_EXTERNAL_OES) + assert(level == 0); tObj->Image[face][level] = texImage; @@ -594,30 +588,8 @@ _mesa_new_texture_image( struct gl_context *ctx ) /** - * Free texture image data. - * This function is a fallback called via ctx->Driver.FreeTexImageData(). - * - * \param texImage texture image. - * - * Free the texture image data if it's not marked as client data. - */ -void -_mesa_free_texture_image_data(struct gl_context *ctx, - struct gl_texture_image *texImage) -{ - (void) ctx; - - if (texImage->Data && !texImage->IsClientData) { - /* free the old texture data */ - _mesa_free_texmemory(texImage->Data); - } - - texImage->Data = NULL; -} - - -/** - * Free texture image. + * Free a gl_texture_image and associated data. + * This function is a fallback called via ctx->Driver.DeleteTextureImage(). * * \param texImage texture image. * @@ -630,13 +602,8 @@ _mesa_delete_texture_image(struct gl_context *ctx, /* Free texImage->Data and/or any other driver-specific texture * image storage. */ - ASSERT(ctx->Driver.FreeTexImageData); - ctx->Driver.FreeTexImageData( ctx, texImage ); - - ASSERT(texImage->Data == NULL); - if (texImage->ImageOffsets) - free(texImage->ImageOffsets); - free(texImage); + ASSERT(ctx->Driver.FreeTextureImageBuffer); + ctx->Driver.FreeTextureImageBuffer( ctx, texImage ); } @@ -650,10 +617,11 @@ _mesa_delete_texture_image(struct gl_context *ctx, GLboolean _mesa_is_proxy_texture(GLenum target) { - /* NUM_TEXTURE_TARGETS should match number of terms below, - * except there's no proxy for GL_TEXTURE_BUFFER. + /* + * NUM_TEXTURE_TARGETS should match number of terms below, except there's no + * proxy for GL_TEXTURE_BUFFER and GL_TEXTURE_EXTERNAL_OES. */ - assert(NUM_TEXTURE_TARGETS == 8); + assert(NUM_TEXTURE_TARGETS == 7 + 2); return (target == GL_PROXY_TEXTURE_1D || target == GL_PROXY_TEXTURE_2D || @@ -766,6 +734,9 @@ _mesa_select_tex_object(struct gl_context *ctx, case GL_TEXTURE_BUFFER: return ctx->Extensions.ARB_texture_buffer_object ? texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL; + case GL_TEXTURE_EXTERNAL_OES: + return ctx->Extensions.OES_EGL_image_external + ? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL; default: _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); return NULL; @@ -954,6 +925,7 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) ctx->Extensions.EXT_texture_array) ? ctx->Const.MaxTextureLevels : 0; case GL_TEXTURE_BUFFER: + case GL_TEXTURE_EXTERNAL_OES: /* fall-through */ default: return 0; /* bad target */ @@ -985,6 +957,7 @@ _mesa_get_texture_dimensions(GLenum target) case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: case GL_TEXTURE_1D_ARRAY: case GL_PROXY_TEXTURE_1D_ARRAY: + case GL_TEXTURE_EXTERNAL_OES: return 2; case GL_TEXTURE_3D: case GL_PROXY_TEXTURE_3D: @@ -1058,15 +1031,8 @@ make_null_texture(GLint width, GLint height, GLint depth, GLenum format) /** - * Reset the fields of a gl_texture_image struct to zero. - * - * \param img texture image structure. - * - * This is called when a proxy texture test fails, we set all the - * image members (except DriverData) to zero. - * It's also used in glTexImage[123]D as a safeguard to be sure all - * required fields get initialized properly by the Driver.TexImage[123]D - * functions. + * Set the size and format-related fields of a gl_texture_image struct + * to zero. This is used when a proxy texture test fails. */ static void clear_teximage_fields(struct gl_texture_image *img) @@ -1078,21 +1044,13 @@ clear_teximage_fields(struct gl_texture_image *img) img->Width = 0; img->Height = 0; img->Depth = 0; - img->RowStride = 0; - if (img->ImageOffsets) { - free(img->ImageOffsets); - img->ImageOffsets = NULL; - } img->Width2 = 0; img->Height2 = 0; img->Depth2 = 0; img->WidthLog2 = 0; img->HeightLog2 = 0; img->DepthLog2 = 0; - img->Data = NULL; img->TexFormat = MESA_FORMAT_NONE; - img->FetchTexelc = NULL; - img->FetchTexelf = NULL; } @@ -1119,8 +1077,6 @@ _mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, GLint border, GLenum internalFormat, gl_format format) { - GLint i, dims; - ASSERT(img); ASSERT(width >= 0); ASSERT(height >= 0); @@ -1157,44 +1113,7 @@ _mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); - if ((width == 1 || _mesa_is_pow_two(img->Width2)) && - (height == 1 || _mesa_is_pow_two(img->Height2)) && - (depth == 1 || _mesa_is_pow_two(img->Depth2))) - img->_IsPowerOfTwo = GL_TRUE; - else - img->_IsPowerOfTwo = GL_FALSE; - - /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ - img->RowStride = width; - /* Allocate the ImageOffsets array and initialize to typical values. - * We allocate the array for 1D/2D textures too in order to avoid special- - * case code in the texstore routines. - */ - if (img->ImageOffsets) - free(img->ImageOffsets); - img->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint)); - for (i = 0; i < depth; i++) { - img->ImageOffsets[i] = i * width * height; - } - - /* Compute Width/Height/DepthScale for mipmap lod computation */ - if (target == GL_TEXTURE_RECTANGLE_NV) { - /* scale = 1.0 since texture coords directly map to texels */ - img->WidthScale = 1.0; - img->HeightScale = 1.0; - img->DepthScale = 1.0; - } - else { - img->WidthScale = (GLfloat) img->Width; - img->HeightScale = (GLfloat) img->Height; - img->DepthScale = (GLfloat) img->Depth; - } - img->TexFormat = format; - - dims = _mesa_get_texture_dimensions(target); - - _mesa_set_fetch_functions(img, dims); } @@ -1211,7 +1130,7 @@ void _mesa_clear_texture_image(struct gl_context *ctx, struct gl_texture_image *texImage) { - ctx->Driver.FreeTexImageData(ctx, texImage); + ctx->Driver.FreeTextureImageBuffer(ctx, texImage); clear_teximage_fields(texImage); } @@ -1382,6 +1301,20 @@ legal_texture_size(struct gl_context *ctx, gl_format format, } +/** + * Return true if the format is only valid for glCompressedTexImage. + */ +static GLboolean +compressedteximage_only_format(const struct gl_context *ctx, GLenum format) +{ + switch (format) { + case GL_ETC1_RGB8_OES: + return GL_TRUE; + default: + return GL_FALSE; + } +} + /** * Helper function to determine whether a target and specific compression @@ -1522,6 +1455,23 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) } +/** + * Helper function to determine if a texture object is mutable (in terms + * of GL_ARB_texture_storage). + */ +static GLboolean +mutable_tex_object(struct gl_context *ctx, GLenum target) +{ + if (ctx->Extensions.ARB_texture_storage) { + struct gl_texture_object *texObj = + _mesa_get_current_tex_object(ctx, target); + return !texObj->Immutable; + } + return GL_TRUE; +} + + + /** * Test the glTexImage[123]D() parameters for errors. * @@ -1554,7 +1504,13 @@ texture_error_check( struct gl_context *ctx, const GLenum proxyTarget = get_proxy_target(target); const GLboolean isProxy = target == proxyTarget; GLboolean sizeOK = GL_TRUE; - GLboolean colorFormat, indexFormat; + GLboolean colorFormat; + + /* Even though there are no color-index textures, we still have to support + * uploading color-index data and remapping it to RGB via the + * GL_PIXEL_MAP_I_TO_[RGBA] tables. + */ + const GLboolean indexFormat = (format == GL_COLOR_INDEX); /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ if (level < 0 || level >= MAX_TEXTURE_LEVELS) { @@ -1635,9 +1591,7 @@ texture_error_check( struct gl_context *ctx, /* make sure internal format and format basically agree */ colorFormat = _mesa_is_color_format(format); - indexFormat = _mesa_is_index_format(format); if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || - (_mesa_is_index_format(internalFormat) && !indexFormat) || (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) || (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) || (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) || @@ -1682,7 +1636,8 @@ texture_error_check( struct gl_context *ctx, /* additional checks for depth textures */ if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { - /* Only 1D, 2D, rect and array textures supported, not 3D or cubes */ + /* Only 1D, 2D, rect, array and cube textures supported, not 3D + * Cubemaps are only supported for GL version > 3.0 or with EXT_gpu_shader4 */ if (target != GL_TEXTURE_1D && target != GL_PROXY_TEXTURE_1D && target != GL_TEXTURE_2D && @@ -1692,7 +1647,9 @@ texture_error_check( struct gl_context *ctx, target != GL_TEXTURE_2D_ARRAY && target != GL_PROXY_TEXTURE_2D_ARRAY && target != GL_TEXTURE_RECTANGLE_ARB && - target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { + target != GL_PROXY_TEXTURE_RECTANGLE_ARB && + !((_mesa_is_cube_face(target) || target == GL_PROXY_TEXTURE_CUBE_MAP) && + (ctx->VersionMajor >= 3 || ctx->Extensions.EXT_gpu_shader4))) { if (!isProxy) _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target/internalFormat)"); @@ -1708,6 +1665,11 @@ texture_error_check( struct gl_context *ctx, "glTexImage%dD(target)", dimensions); return GL_TRUE; } + if (compressedteximage_only_format(ctx, internalFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage%dD(no compression for format)", dimensions); + return GL_TRUE; + } if (border != 0) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -1729,6 +1691,12 @@ texture_error_check( struct gl_context *ctx, return GL_TRUE; } + if (!mutable_tex_object(ctx, target)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage%dD(immutable texture)", dimensions); + return GL_TRUE; + } + /* if we get here, the parameters are OK */ return GL_FALSE; } @@ -1856,6 +1824,12 @@ subtexture_error_check2( struct gl_context *ctx, GLuint dimensions, if (_mesa_is_format_compressed(destTex->TexFormat)) { GLuint bw, bh; + if (compressedteximage_only_format(ctx, destTex->InternalFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage%dD(no compression for format)", dimensions); + return GL_TRUE; + } + /* do tests which depend on compression block size */ _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh); @@ -1909,7 +1883,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, const GLenum proxyTarget = get_proxy_target(target); const GLenum type = GL_FLOAT; GLboolean sizeOK; - GLint format; + GLint baseFormat; /* check target */ if (!legal_texsubimage_target(ctx, dimensions, target)) { @@ -1944,14 +1918,14 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } - format = _mesa_base_tex_format(ctx, internalFormat); - if (format < 0) { + baseFormat = _mesa_base_tex_format(ctx, internalFormat); + if (baseFormat < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage%dD(internalFormat)", dimensions); return GL_TRUE; } - if (!_mesa_source_buffer_exists(ctx, format)) { + if (!_mesa_source_buffer_exists(ctx, baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexImage%dD(missing readbuffer)", dimensions); return GL_TRUE; @@ -1962,7 +1936,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, ? (width == height) : 1; sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, - internalFormat, format, + internalFormat, baseFormat, type, width, height, 1, border); @@ -1985,27 +1959,22 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, "glCopyTexImage%dD(target)", dimensions); return GL_TRUE; } - if (border != 0) { + if (compressedteximage_only_format(ctx, internalFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%dD(border!=0)", dimensions); + "glCopyTexImage%dD(no compression for format)", dimensions); return GL_TRUE; } - } - else if (_mesa_is_depth_format(internalFormat)) { - /* make sure we have depth/stencil buffers */ - if (!ctx->ReadBuffer->_DepthBuffer) { + if (border != 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%dD(no depth)", dimensions); + "glCopyTexImage%dD(border!=0)", dimensions); return GL_TRUE; } } - else if (_mesa_is_depthstencil_format(internalFormat)) { - /* make sure we have depth/stencil buffers */ - if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%dD(no depth/stencil buffer)", dimensions); - return GL_TRUE; - } + + if (!mutable_tex_object(ctx, target)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%dD(immutable texture)", dimensions); + return GL_TRUE; } /* if we get here, the parameters are OK */ @@ -2134,6 +2103,11 @@ copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, } if (_mesa_is_format_compressed(teximage->TexFormat)) { + if (compressedteximage_only_format(ctx, teximage->InternalFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexSubImage%dD(no compression for format)", dimensions); + return GL_TRUE; + } /* offset must be multiple of 4 */ if ((xoffset & 3) || (yoffset & 3)) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -2165,23 +2139,6 @@ copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } - if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { - if (!ctx->ReadBuffer->_DepthBuffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexSubImage%dD(no depth buffer)", - dimensions); - return GL_TRUE; - } - } - else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { - if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexSubImage%dD(no depth/stencil buffer)", - dimensions); - return GL_TRUE; - } - } - /* If copying into an integer texture, the source buffer must also be * integer-valued. */ @@ -2269,7 +2226,7 @@ update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj, * changed the texture base level image, regenerate the rest of the * mipmap levels now. */ -static INLINE void +static inline void check_gen_mipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj, GLint level) { @@ -2365,6 +2322,45 @@ _mesa_choose_texture_format(struct gl_context *ctx, return f; } +/** + * Adjust pixel unpack params and image dimensions to strip off the + * texture border. + * + * Gallium and intel don't support texture borders. They've seldem been used + * and seldom been implemented correctly anyway. + * + * \param unpackNew returns the new pixel unpack parameters + */ +static void +strip_texture_border(GLint *border, + GLint *width, GLint *height, GLint *depth, + const struct gl_pixelstore_attrib *unpack, + struct gl_pixelstore_attrib *unpackNew) +{ + assert(*border > 0); /* sanity check */ + + *unpackNew = *unpack; + + if (unpackNew->RowLength == 0) + unpackNew->RowLength = *width; + + if (depth && unpackNew->ImageHeight == 0) + unpackNew->ImageHeight = *height; + + unpackNew->SkipPixels += *border; + if (height) + unpackNew->SkipRows += *border; + if (depth) + unpackNew->SkipImages += *border; + + assert(*width >= 3); + *width = *width - 2 * *border; + if (height && *height >= 3) + *height = *height - 2 * *border; + if (depth && *depth >= 3) + *depth = *depth - 2 * *border; + *border = 0; +} /** * Common code to implement all the glTexImage1D/2D/3D functions. @@ -2377,6 +2373,8 @@ teximage(struct gl_context *ctx, GLuint dims, const GLvoid *pixels) { GLboolean error; + struct gl_pixelstore_attrib unpack_no_border; + const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); @@ -2441,6 +2439,16 @@ teximage(struct gl_context *ctx, GLuint dims, return; /* error was recorded */ } + /* Allow a hardware driver to just strip out the border, to provide + * reliable but slightly incorrect hardware rendering instead of + * rarely-tested software fallback rendering. + */ + if (border && ctx->Const.StripTextureBorder) { + strip_texture_border(&border, &width, &height, &depth, unpack, + &unpack_no_border); + unpack = &unpack_no_border; + } + if (ctx->NewState & _NEW_PIXEL) _mesa_update_state(ctx); @@ -2456,11 +2464,8 @@ teximage(struct gl_context *ctx, GLuint dims, else { gl_format texFormat; - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } + ctx->Driver.FreeTextureImageBuffer(ctx, texImage); - ASSERT(texImage->Data == NULL); texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, internalFormat, format, type); @@ -2476,19 +2481,19 @@ teximage(struct gl_context *ctx, GLuint dims, case 1: ctx->Driver.TexImage1D(ctx, target, level, internalFormat, width, border, format, - type, pixels, &ctx->Unpack, texObj, + type, pixels, unpack, texObj, texImage); break; case 2: ctx->Driver.TexImage2D(ctx, target, level, internalFormat, width, height, border, format, - type, pixels, &ctx->Unpack, texObj, + type, pixels, unpack, texObj, texImage); break; case 3: ctx->Driver.TexImage3D(ctx, target, level, internalFormat, width, height, depth, border, format, - type, pixels, &ctx->Unpack, texObj, + type, pixels, unpack, texObj, texImage); break; default: @@ -2575,13 +2580,10 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - if (!ctx->Extensions.OES_EGL_image) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glEGLImageTargetTexture2DOES(unsupported)"); - return; - } - - if (target != GL_TEXTURE_2D) { + if ((target == GL_TEXTURE_2D && + !ctx->Extensions.OES_EGL_image) || + (target == GL_TEXTURE_EXTERNAL_OES && + !ctx->Extensions.OES_EGL_image_external)) { _mesa_error(ctx, GL_INVALID_ENUM, "glEGLImageTargetTexture2D(target=%d)", target); return; @@ -2597,10 +2599,8 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D"); } else { - if (texImage->Data) - ctx->Driver.FreeTexImageData( ctx, texImage ); + ctx->Driver.FreeTextureImageBuffer(ctx, texImage); - ASSERT(texImage->Data == NULL); ctx->Driver.EGLImageTargetTexture2D(ctx, target, texObj, texImage, image); @@ -2786,6 +2786,16 @@ copyteximage(struct gl_context *ctx, GLuint dims, texObj = _mesa_get_current_tex_object(ctx, target); + if (border && ctx->Const.StripTextureBorder) { + x += border; + width -= border * 2; + if (dims == 2) { + y += border; + height -= border * 2; + } + border = 0; + } + _mesa_lock_texture(ctx, texObj); { texImage = _mesa_get_tex_image(ctx, texObj, target, level); @@ -2804,7 +2814,7 @@ copyteximage(struct gl_context *ctx, GLuint dims, GLint srcX = x, srcY = y, dstX = 0, dstY = 0; /* Free old texture image */ - ctx->Driver.FreeTexImageData(ctx, texImage); + ctx->Driver.FreeTextureImageBuffer(ctx, texImage); _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, border, internalFormat, texFormat); @@ -3032,15 +3042,12 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, const GLenum proxyTarget = get_proxy_target(target); const GLint maxLevels = _mesa_max_texture_levels(ctx, target); GLint expectedSize; + GLenum choose_format; + GLenum choose_type; + GLenum proxy_format; *reason = ""; /* no error */ - /* check level */ - if (level < 0 || level >= maxLevels) { - *reason = "level"; - return GL_INVALID_VALUE; - } - if (!target_can_be_compressed(ctx, target, internalFormat)) { *reason = "target"; return GL_INVALID_ENUM; @@ -3052,6 +3059,68 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, return GL_INVALID_ENUM; } + switch (internalFormat) { +#if FEATURE_ES + case GL_PALETTE4_RGB8_OES: + case GL_PALETTE4_RGBA8_OES: + case GL_PALETTE4_R5_G6_B5_OES: + case GL_PALETTE4_RGBA4_OES: + case GL_PALETTE4_RGB5_A1_OES: + case GL_PALETTE8_RGB8_OES: + case GL_PALETTE8_RGBA8_OES: + case GL_PALETTE8_R5_G6_B5_OES: + case GL_PALETTE8_RGBA4_OES: + case GL_PALETTE8_RGB5_A1_OES: + _mesa_cpal_compressed_format_type(internalFormat, &choose_format, + &choose_type); + proxy_format = choose_format; + + /* check level */ + if (level > 0 || level < -maxLevels) { + *reason = "level"; + return GL_INVALID_VALUE; + } + + if (dimensions != 2) { + *reason = "compressed paletted textures must be 2D"; + return GL_INVALID_OPERATION; + } + + /* Figure out the expected texture size (in bytes). This will be + * checked against the actual size later. + */ + expectedSize = _mesa_cpal_compressed_size(level, internalFormat, + width, height); + + /* This is for the benefit of the TestProxyTexImage below. It expects + * level to be non-negative. OES_compressed_paletted_texture uses a + * weird mechanism where the level specified to glCompressedTexImage2D + * is -(n-1) number of levels in the texture, and the data specifies the + * complete mipmap stack. This is done to ensure the palette is the + * same for all levels. + */ + level = -level; + break; +#endif + + default: + choose_format = GL_NONE; + choose_type = GL_NONE; + proxy_format = internalFormat; + + /* check level */ + if (level < 0 || level >= maxLevels) { + *reason = "level"; + return GL_INVALID_VALUE; + } + + /* Figure out the expected texture size (in bytes). This will be + * checked against the actual size later. + */ + expectedSize = compressed_tex_size(width, height, depth, internalFormat); + break; + } + /* This should really never fail */ if (_mesa_base_tex_format(ctx, internalFormat) < 0) { *reason = "internalFormat"; @@ -3065,8 +3134,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, } /* For cube map, width must equal height */ - if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) { + if (_mesa_is_cube_face(target) && width != height) { *reason = "width != height"; return GL_INVALID_VALUE; } @@ -3074,8 +3142,8 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, /* check image size against compression block size */ { gl_format texFormat = - ctx->Driver.ChooseTextureFormat(ctx, internalFormat, - GL_NONE, GL_NONE); + ctx->Driver.ChooseTextureFormat(ctx, proxy_format, + choose_format, choose_type); GLuint bw, bh; _mesa_get_format_block_size(texFormat, &bw, &bh); @@ -3093,15 +3161,15 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, /* check image sizes */ if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, - internalFormat, GL_NONE, GL_NONE, - width, height, depth, border)) { + proxy_format, choose_format, + choose_type, + width, height, depth, border)) { /* See error comment above */ *reason = "invalid width, height or format"; return GL_INVALID_OPERATION; } /* check image size in bytes */ - expectedSize = compressed_tex_size(width, height, depth, internalFormat); if (expectedSize != imageSize) { /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...] * if is not consistent with the format, dimensions, and @@ -3111,6 +3179,11 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, return GL_INVALID_VALUE; } + if (!mutable_tex_object(ctx, target)) { + *reason = "immutable texture"; + return GL_INVALID_OPERATION; + } + return GL_NO_ERROR; } @@ -3149,8 +3222,7 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions, return GL_INVALID_ENUM; /*target*/ maxLevels = ctx->Const.MaxCubeTextureLevels; } - else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + else if (_mesa_is_cube_face(target)) { if (!ctx->Extensions.ARB_texture_cube_map) return GL_INVALID_ENUM; /*target*/ maxLevels = ctx->Const.MaxCubeTextureLevels; @@ -3219,6 +3291,13 @@ compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims, return GL_TRUE; } + if (compressedteximage_only_format(ctx, format)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTexSubImage%uD(format=0x%x cannot be updated)" + , dims, format); + return GL_TRUE; + } + if (((width == 1 || width == 2) && width != (GLsizei) texImage->Width) || (width > (GLsizei) texImage->Width)) { @@ -3285,14 +3364,9 @@ compressedteximage(struct gl_context *ctx, GLuint dims, internalFormat, width, height, depth, border, imageSize, &reason); - if (error) { - _mesa_error(ctx, error, "glCompressedTexImage%uD(%s)", dims, reason); - return; - } - #if FEATURE_ES /* XXX this is kind of a hack */ - if (dims == 2) { + if (!error && dims == 2) { switch (internalFormat) { case GL_PALETTE4_RGB8_OES: case GL_PALETTE4_RGBA8_OES: @@ -3346,7 +3420,7 @@ compressedteximage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *texImage; if (error) { - _mesa_error(ctx, error, "glCompressedTexImage%uD", dims); + _mesa_error(ctx, error, "glCompressedTexImage%uD(%s)", dims, reason); return; } @@ -3362,10 +3436,7 @@ compressedteximage(struct gl_context *ctx, GLuint dims, else { gl_format texFormat; - if (texImage->Data) { - ctx->Driver.FreeTexImageData( ctx, texImage ); - } - ASSERT(texImage->Data == NULL); + ctx->Driver.FreeTextureImageBuffer(ctx, texImage); texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, internalFormat, GL_NONE,