X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fteximage.c;h=64b25a82decf7df82762d1e3556912c58bd9d45f;hb=f609cf782ab5e90ddf045dc4b0da8cebf99be0d1;hp=6acff240e456d8a61255717c8a6a31a7f9b4a8fe;hpb=6f3d91840945fbd9221a247e4f95b32c4051f202;p=mesa.git diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 6acff240e45..64b25a82dec 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -43,6 +43,7 @@ #include "state.h" #include "texcompress.h" #include "teximage.h" +#include "texobj.h" #include "texstate.h" #include "texpal.h" #include "mtypes.h" @@ -69,8 +70,6 @@ * * This is the format which is used during texture application (i.e. the * texture format and env mode determine the arithmetic used. - * - * XXX this could be static */ GLint _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) @@ -139,6 +138,15 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) } } + if (ctx->Extensions.ARB_ES2_compatibility) { + switch (internalFormat) { + case GL_RGB565: + return GL_RGB; + default: + ; /* fallthrough */ + } + } + if (ctx->Extensions.ARB_depth_texture) { switch (internalFormat) { case GL_DEPTH_COMPONENT: @@ -531,6 +539,32 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) } +/** + * Is the given texture format a generic compressed format? + */ +static GLboolean +is_generic_compressed_format(GLenum format) +{ + switch (format) { + case GL_COMPRESSED_RED: + case GL_COMPRESSED_RG: + case GL_COMPRESSED_RGB: + case GL_COMPRESSED_RGBA: + case GL_COMPRESSED_ALPHA: + case GL_COMPRESSED_LUMINANCE: + case GL_COMPRESSED_LUMINANCE_ALPHA: + case GL_COMPRESSED_INTENSITY: + case GL_COMPRESSED_SRGB: + case GL_COMPRESSED_SRGB_ALPHA: + case GL_COMPRESSED_SLUMINANCE: + case GL_COMPRESSED_SLUMINANCE_ALPHA: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + /** * For cube map faces, return a face index in [0,5]. * For other targets return 0; @@ -830,7 +864,7 @@ _mesa_get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level) struct gl_texture_image *texImage; GLuint texIndex; - if (level < 0 ) + if (level < 0) return NULL; switch (target) { @@ -917,7 +951,6 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: - case GL_TEXTURE_CUBE_MAP_ARB: case GL_PROXY_TEXTURE_CUBE_MAP_ARB: return ctx->Extensions.ARB_texture_cube_map ? ctx->Const.MaxCubeTextureLevels : 0; @@ -1083,11 +1116,13 @@ _mesa_init_teximage_fields(struct gl_context *ctx, GLint border, GLenum internalFormat, gl_format format) { + GLenum target; ASSERT(img); ASSERT(width >= 0); ASSERT(height >= 0); ASSERT(depth >= 0); + target = img->TexObject->Target; img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat ); ASSERT(img->_BaseFormat > 0); img->InternalFormat = internalFormat; @@ -1099,26 +1134,72 @@ _mesa_init_teximage_fields(struct gl_context *ctx, img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ img->WidthLog2 = _mesa_logbase2(img->Width2); - if (height == 1) { /* 1-D texture */ - img->Height2 = 1; + switch(target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_BUFFER: + case GL_PROXY_TEXTURE_1D: + if (height == 0) + img->Height2 = 0; + else + img->Height2 = 1; img->HeightLog2 = 0; - } - else { + if (depth == 0) + img->Depth2 = 0; + else + img->Depth2 = 1; + img->DepthLog2 = 0; + break; + case GL_TEXTURE_1D_ARRAY: + case GL_PROXY_TEXTURE_1D_ARRAY: + img->Height2 = height; /* no border */ + img->HeightLog2 = 0; /* not used */ + if (depth == 0) + img->Depth2 = 0; + else + img->Depth2 = 1; + img->DepthLog2 = 0; + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + case GL_TEXTURE_EXTERNAL_OES: + case GL_PROXY_TEXTURE_2D: + case GL_PROXY_TEXTURE_RECTANGLE: + case GL_PROXY_TEXTURE_CUBE_MAP: img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ img->HeightLog2 = _mesa_logbase2(img->Height2); - } - - if (depth == 1) { /* 2-D texture */ - img->Depth2 = 1; + if (depth == 0) + img->Depth2 = 0; + else + img->Depth2 = 1; img->DepthLog2 = 0; - } - else { + break; + case GL_TEXTURE_2D_ARRAY: + case GL_PROXY_TEXTURE_2D_ARRAY: + img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ + img->HeightLog2 = _mesa_logbase2(img->Height2); + img->Depth2 = depth; /* no border */ + img->DepthLog2 = 0; /* not used */ + break; + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ + img->HeightLog2 = _mesa_logbase2(img->Height2); img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ img->DepthLog2 = _mesa_logbase2(img->Depth2); + break; + default: + _mesa_problem(NULL, "invalid target 0x%x in _mesa_init_teximage_fields()", + target); } img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); - img->TexFormat = format; } @@ -1659,7 +1740,8 @@ texture_error_check( struct gl_context *ctx, } /* additional checks for compressed textures */ - if (_mesa_is_compressed_format(ctx, internalFormat)) { + if (_mesa_is_compressed_format(ctx, internalFormat) || + is_generic_compressed_format(internalFormat)) { if (!target_can_be_compressed(ctx, target, internalFormat)) { if (!isProxy) _mesa_error(ctx, GL_INVALID_ENUM, @@ -1798,23 +1880,25 @@ subtexture_error_check2( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } if (dimensions > 1) { - if (yoffset < -((GLint)destTex->Border)) { + GLint yBorder = (target == GL_TEXTURE_1D_ARRAY) ? 0 : destTex->Border; + if (yoffset < -yBorder) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", dimensions); return GL_TRUE; } - if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { + if (yoffset + height > (GLint) destTex->Height + yBorder) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", dimensions); return GL_TRUE; } } if (dimensions > 2) { - if (zoffset < -((GLint)destTex->Border)) { + GLint zBorder = (target == GL_TEXTURE_2D_ARRAY) ? 0 : destTex->Border; + if (zoffset < -zBorder) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); return GL_TRUE; } - if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { + if (zoffset + depth > (GLint) destTex->Depth + zBorder) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); return GL_TRUE; } @@ -1921,7 +2005,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, } if (ctx->ReadBuffer->Visual.samples > 0) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION, + _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexImage%dD(multisample FBO)", dimensions); return GL_TRUE; @@ -1988,7 +2072,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } - if (_mesa_is_compressed_format(ctx, internalFormat)) { + if (_mesa_is_compressed_format(ctx, internalFormat) || + is_generic_compressed_format(internalFormat)) { if (!target_can_be_compressed(ctx, target, internalFormat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%dD(target)", dimensions); @@ -2045,7 +2130,7 @@ copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions, } if (ctx->ReadBuffer->Visual.samples > 0) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION, + _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage%dD(multisample FBO)", dimensions); return GL_TRUE; @@ -2117,13 +2202,14 @@ copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } if (dimensions > 1) { - if (yoffset < -((GLint)teximage->Border)) { + GLint yBorder = (target == GL_TEXTURE_1D_ARRAY) ? 0 : teximage->Border; + if (yoffset < -yBorder) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); return GL_TRUE; } /* NOTE: we're adding the border here, not subtracting! */ - if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { + if (yoffset + height > (GLint) teximage->Height + yBorder) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexSubImage%dD(yoffset+height)", dimensions); return GL_TRUE; @@ -2132,12 +2218,13 @@ copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, /* check z offset */ if (dimensions > 2) { - if (zoffset < -((GLint)teximage->Border)) { + GLint zBorder = (target == GL_TEXTURE_2D_ARRAY) ? 0 : teximage->Border; + if (zoffset < -zBorder) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexSubImage%dD(zoffset)", dimensions); return GL_TRUE; } - if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { + if (zoffset > (GLint) teximage->Depth + zBorder) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexSubImage%dD(zoffset+depth)", dimensions); return GL_TRUE; @@ -2372,7 +2459,7 @@ _mesa_choose_texture_format(struct gl_context *ctx, /** * Adjust pixel unpack params and image dimensions to strip off the - * texture border. + * one-pixel texture border. * * Gallium and intel don't support texture borders. They've seldem been used * and seldom been implemented correctly anyway. @@ -2380,34 +2467,37 @@ _mesa_choose_texture_format(struct gl_context *ctx, * \param unpackNew returns the new pixel unpack parameters */ static void -strip_texture_border(GLint *border, +strip_texture_border(GLenum target, GLint *width, GLint *height, GLint *depth, const struct gl_pixelstore_attrib *unpack, struct gl_pixelstore_attrib *unpackNew) { - assert(*border > 0); /* sanity check */ + assert(width); + assert(height); + assert(depth); *unpackNew = *unpack; if (unpackNew->RowLength == 0) unpackNew->RowLength = *width; - if (depth && unpackNew->ImageHeight == 0) + if (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; + unpackNew->SkipPixels++; /* skip the border */ + *width = *width - 2; /* reduce the width by two border pixels */ + + /* The min height of a texture with a border is 3 */ + if (*height >= 3 && target != GL_TEXTURE_1D_ARRAY) { + unpackNew->SkipRows++; /* skip the border */ + *height = *height - 2; /* reduce the height by two border pixels */ + } + + if (*depth >= 3 && target != GL_TEXTURE_2D_ARRAY) { + unpackNew->SkipImages++; /* skip the border */ + *depth = *depth - 2; /* reduce the depth by two border pixels */ + } } /** @@ -2492,8 +2582,9 @@ teximage(struct gl_context *ctx, GLuint dims, * rarely-tested software fallback rendering. */ if (border && ctx->Const.StripTextureBorder) { - strip_texture_border(&border, &width, &height, &depth, unpack, + strip_texture_border(target, &width, &height, &depth, unpack, &unpack_no_border); + border = 0; unpack = &unpack_no_border; } @@ -2524,34 +2615,15 @@ teximage(struct gl_context *ctx, GLuint dims, border, internalFormat, texFormat); /* Give the texture to the driver. may be null. */ - ASSERT(ctx->Driver.TexImage3D); - switch (dims) { - case 1: - ctx->Driver.TexImage1D(ctx, texImage, internalFormat, - width, border, format, - type, pixels, unpack); - break; - case 2: - ctx->Driver.TexImage2D(ctx, texImage, internalFormat, - width, height, border, format, - type, pixels, unpack); - break; - case 3: - ctx->Driver.TexImage3D(ctx, texImage, internalFormat, - width, height, depth, border, format, - type, pixels, unpack); - break; - default: - _mesa_problem(ctx, "invalid dims=%u in teximage()", dims); - } + ctx->Driver.TexImage(ctx, dims, texImage, internalFormat, + width, height, depth, border, format, + type, pixels, unpack); check_gen_mipmap(ctx, target, texObj, level); _mesa_update_fbo_texture(ctx, texObj, face, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); @@ -2640,6 +2712,13 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); + if (texObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEGLImageTargetTexture2D(texture is immutable)"); + _mesa_unlock_texture(ctx, texObj); + return; + } + texImage = _mesa_get_tex_image(ctx, texObj, target, 0); if (!texImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D"); @@ -2649,9 +2728,7 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) ctx->Driver.EGLImageTargetTexture2D(ctx, target, texObj, texImage, image); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); } _mesa_unlock_texture(ctx, texObj); @@ -2713,35 +2790,21 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, /* If we have a border, offset=-1 is legal. Bias by border width. */ switch (dims) { case 3: - zoffset += texImage->Border; + if (target != GL_TEXTURE_2D_ARRAY) + zoffset += texImage->Border; /* fall-through */ case 2: - yoffset += texImage->Border; + if (target != GL_TEXTURE_1D_ARRAY) + yoffset += texImage->Border; /* fall-through */ case 1: xoffset += texImage->Border; } - switch (dims) { - case 1: - ctx->Driver.TexSubImage1D(ctx, texImage, - xoffset, width, - format, type, pixels, &ctx->Unpack); - break; - case 2: - ctx->Driver.TexSubImage2D(ctx, texImage, - xoffset, yoffset, width, height, - format, type, pixels, &ctx->Unpack); - break; - case 3: - ctx->Driver.TexSubImage3D(ctx, texImage, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, &ctx->Unpack); - break; - default: - _mesa_problem(ctx, "unexpected dims in subteximage()"); - } + ctx->Driver.TexSubImage(ctx, dims, texImage, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, &ctx->Unpack); check_gen_mipmap(ctx, target, texObj, level); @@ -2872,7 +2935,7 @@ copyteximage(struct gl_context *ctx, GLuint dims, GL_NONE, GL_NONE); if (legal_texture_size(ctx, texFormat, width, height, 1)) { - GLint srcX = x, srcY = y, dstX = 0, dstY = 0; + GLint srcX = x, srcY = y, dstX = 0, dstY = 0, dstZ = 0; /* Free old texture image */ ctx->Driver.FreeTextureImageBuffer(ctx, texImage); @@ -2881,38 +2944,24 @@ copyteximage(struct gl_context *ctx, GLuint dims, border, internalFormat, texFormat); /* Allocate texture memory (no pixel data yet) */ - if (dims == 1) { - ctx->Driver.TexImage1D(ctx, texImage, internalFormat, - width, border, GL_NONE, GL_NONE, NULL, - &ctx->Unpack); - } - else { - ctx->Driver.TexImage2D(ctx, texImage, internalFormat, - width, height, border, GL_NONE, GL_NONE, - NULL, &ctx->Unpack); - } + ctx->Driver.TexImage(ctx, dims, texImage, internalFormat, + width, height, 1, border, GL_NONE, GL_NONE, + NULL, &ctx->Unpack); if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY, &width, &height)) { struct gl_renderbuffer *srcRb = get_copy_tex_image_source(ctx, texImage->TexFormat); - if (dims == 1) - ctx->Driver.CopyTexSubImage1D(ctx, texImage, dstX, - srcRb, srcX, srcY, width); - - else - ctx->Driver.CopyTexSubImage2D(ctx, texImage, dstX, dstY, - srcRb, srcX, srcY, width, height); + ctx->Driver.CopyTexSubImage(ctx, dims, texImage, dstX, dstY, dstZ, + srcRb, srcX, srcY, width, height); } check_gen_mipmap(ctx, target, texObj, level); _mesa_update_fbo_texture(ctx, texObj, face, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); } else { /* probably too large of image */ @@ -2988,10 +3037,12 @@ copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, /* If we have a border, offset=-1 is legal. Bias by border width. */ switch (dims) { case 3: - zoffset += texImage->Border; + if (target != GL_TEXTURE_2D_ARRAY) + zoffset += texImage->Border; /* fall-through */ case 2: - yoffset += texImage->Border; + if (target != GL_TEXTURE_1D_ARRAY) + yoffset += texImage->Border; /* fall-through */ case 1: xoffset += texImage->Border; @@ -3002,23 +3053,9 @@ copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, struct gl_renderbuffer *srcRb = get_copy_tex_image_source(ctx, texImage->TexFormat); - switch (dims) { - case 1: - ctx->Driver.CopyTexSubImage1D(ctx, texImage, xoffset, - srcRb, x, y, width); - break; - case 2: - ctx->Driver.CopyTexSubImage2D(ctx, texImage, xoffset, yoffset, - srcRb, x, y, width, height); - break; - case 3: - ctx->Driver.CopyTexSubImage3D(ctx, texImage, - xoffset, yoffset, zoffset, - srcRb, x, y, width, height); - break; - default: - _mesa_problem(ctx, "bad dims in copytexsubimage()"); - } + ctx->Driver.CopyTexSubImage(ctx, dims, texImage, + xoffset, yoffset, zoffset, + srcRb, x, y, width, height); check_gen_mipmap(ctx, target, texObj, level); @@ -3513,37 +3550,14 @@ compressedteximage(struct gl_context *ctx, GLuint dims, width, height, depth, border, internalFormat, texFormat); - switch (dims) { - case 1: - ASSERT(ctx->Driver.CompressedTexImage1D); - ctx->Driver.CompressedTexImage1D(ctx, texImage, - internalFormat, - width, - border, imageSize, data); - break; - case 2: - ASSERT(ctx->Driver.CompressedTexImage2D); - ctx->Driver.CompressedTexImage2D(ctx, texImage, - internalFormat, - width, height, - border, imageSize, data); - break; - case 3: - ASSERT(ctx->Driver.CompressedTexImage3D); - ctx->Driver.CompressedTexImage3D(ctx, texImage, - internalFormat, - width, height, depth, - border, imageSize, data); - break; - default: - _mesa_problem(ctx, "bad dims in compressedteximage"); - } + ctx->Driver.CompressedTexImage(ctx, dims, texImage, + internalFormat, + width, height, depth, + border, imageSize, data); check_gen_mipmap(ctx, target, texObj, level); - /* state update */ - texObj->_Complete = GL_FALSE; - ctx->NewState |= _NEW_TEXTURE; + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, @@ -3628,33 +3642,10 @@ compressed_tex_sub_image(GLuint dims, GLenum target, GLint level, /* error was recorded */ } else if (width > 0 && height > 0 && depth > 0) { - switch (dims) { - case 1: - if (ctx->Driver.CompressedTexSubImage1D) { - ctx->Driver.CompressedTexSubImage1D(ctx, texImage, - xoffset, width, - format, imageSize, data); - } - break; - case 2: - if (ctx->Driver.CompressedTexSubImage2D) { - ctx->Driver.CompressedTexSubImage2D(ctx, texImage, - xoffset, yoffset, - width, height, - format, imageSize, data); - } - break; - case 3: - if (ctx->Driver.CompressedTexSubImage3D) { - ctx->Driver.CompressedTexSubImage3D(ctx, texImage, - xoffset, yoffset, zoffset, - width, height, depth, - format, imageSize, data); - } - break; - default: - ; - } + ctx->Driver.CompressedTexSubImage(ctx, dims, texImage, + xoffset, yoffset, zoffset, + width, height, depth, + format, imageSize, data); check_gen_mipmap(ctx, target, texObj, level); @@ -3696,228 +3687,186 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, width, height, depth, format, imageSize, data); } - -/** - * Helper for glTexBuffer(). Check if internalFormat is legal. If so, - * return the basic data type and number of components for the format. - * \param return GL_TRUE if internalFormat is legal, GL_FALSE otherwise - */ -static GLboolean -get_sized_format_info(const struct gl_context *ctx, GLenum internalFormat, - GLenum *datatype, GLuint *components) +static gl_format +get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) { switch (internalFormat) { case GL_ALPHA8: - *datatype = GL_UNSIGNED_BYTE; - *components = 1; - break; + return MESA_FORMAT_A8; case GL_ALPHA16: - *datatype = GL_UNSIGNED_SHORT; - *components = 1; - break; + return MESA_FORMAT_A16; case GL_ALPHA16F_ARB: - *datatype = GL_HALF_FLOAT; - *components = 1; - break; + return MESA_FORMAT_ALPHA_FLOAT16; case GL_ALPHA32F_ARB: - *datatype = GL_FLOAT; - *components = 1; - break; + return MESA_FORMAT_ALPHA_FLOAT32; case GL_ALPHA8I_EXT: - *datatype = GL_BYTE; - *components = 1; - break; + return MESA_FORMAT_ALPHA_INT8; case GL_ALPHA16I_EXT: - *datatype = GL_SHORT; - *components = 1; - break; + return MESA_FORMAT_ALPHA_INT16; case GL_ALPHA32I_EXT: - *datatype = GL_INT; - *components = 1; - break; + return MESA_FORMAT_ALPHA_INT32; case GL_ALPHA8UI_EXT: - *datatype = GL_UNSIGNED_BYTE; - *components = 1; - break; + return MESA_FORMAT_ALPHA_UINT8; case GL_ALPHA16UI_EXT: - *datatype = GL_UNSIGNED_SHORT; - *components = 1; - break; + return MESA_FORMAT_ALPHA_UINT16; case GL_ALPHA32UI_EXT: - *datatype = GL_UNSIGNED_INT; - *components = 1; - break; + return MESA_FORMAT_ALPHA_UINT32; case GL_LUMINANCE8: - *datatype = GL_UNSIGNED_BYTE; - *components = 1; - break; + return MESA_FORMAT_L8; case GL_LUMINANCE16: - *datatype = GL_UNSIGNED_SHORT; - *components = 1; - break; + return MESA_FORMAT_L16; case GL_LUMINANCE16F_ARB: - *datatype = GL_HALF_FLOAT; - *components = 1; - break; + return MESA_FORMAT_LUMINANCE_FLOAT16; case GL_LUMINANCE32F_ARB: - *datatype = GL_FLOAT; - *components = 1; - break; + return MESA_FORMAT_LUMINANCE_FLOAT32; case GL_LUMINANCE8I_EXT: - *datatype = GL_BYTE; - *components = 1; - break; + return MESA_FORMAT_LUMINANCE_INT8; case GL_LUMINANCE16I_EXT: - *datatype = GL_SHORT; - *components = 1; - break; + return MESA_FORMAT_LUMINANCE_INT16; case GL_LUMINANCE32I_EXT: - *datatype = GL_INT; - *components = 1; - break; + return MESA_FORMAT_LUMINANCE_INT32; case GL_LUMINANCE8UI_EXT: - *datatype = GL_UNSIGNED_BYTE; - *components = 1; - break; + return MESA_FORMAT_LUMINANCE_UINT8; case GL_LUMINANCE16UI_EXT: - *datatype = GL_UNSIGNED_SHORT; - *components = 1; - break; + return MESA_FORMAT_LUMINANCE_UINT16; case GL_LUMINANCE32UI_EXT: - *datatype = GL_UNSIGNED_INT; - *components = 1; - break; + return MESA_FORMAT_LUMINANCE_UINT32; case GL_LUMINANCE8_ALPHA8: - *datatype = GL_UNSIGNED_BYTE; - *components = 2; - break; + return MESA_FORMAT_AL88; case GL_LUMINANCE16_ALPHA16: - *datatype = GL_UNSIGNED_SHORT; - *components = 2; - break; + return MESA_FORMAT_AL1616; case GL_LUMINANCE_ALPHA16F_ARB: - *datatype = GL_HALF_FLOAT; - *components = 2; - break; + return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16; case GL_LUMINANCE_ALPHA32F_ARB: - *datatype = GL_FLOAT; - *components = 2; - break; + return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32; case GL_LUMINANCE_ALPHA8I_EXT: - *datatype = GL_BYTE; - *components = 2; - break; + return MESA_FORMAT_LUMINANCE_ALPHA_INT8; case GL_LUMINANCE_ALPHA16I_EXT: - *datatype = GL_SHORT; - *components = 2; - break; + return MESA_FORMAT_LUMINANCE_ALPHA_INT8; case GL_LUMINANCE_ALPHA32I_EXT: - *datatype = GL_INT; - *components = 2; - break; + return MESA_FORMAT_LUMINANCE_ALPHA_INT16; case GL_LUMINANCE_ALPHA8UI_EXT: - *datatype = GL_UNSIGNED_BYTE; - *components = 2; - break; + return MESA_FORMAT_LUMINANCE_ALPHA_UINT8; case GL_LUMINANCE_ALPHA16UI_EXT: - *datatype = GL_UNSIGNED_SHORT; - *components = 2; - break; + return MESA_FORMAT_LUMINANCE_ALPHA_UINT16; case GL_LUMINANCE_ALPHA32UI_EXT: - *datatype = GL_UNSIGNED_INT; - *components = 2; - break; + return MESA_FORMAT_LUMINANCE_ALPHA_UINT32; case GL_INTENSITY8: - *datatype = GL_UNSIGNED_BYTE; - *components = 1; - break; + return MESA_FORMAT_I8; case GL_INTENSITY16: - *datatype = GL_UNSIGNED_SHORT; - *components = 1; - break; + return MESA_FORMAT_I16; case GL_INTENSITY16F_ARB: - *datatype = GL_HALF_FLOAT; - *components = 1; - break; + return MESA_FORMAT_INTENSITY_FLOAT16; case GL_INTENSITY32F_ARB: - *datatype = GL_FLOAT; - *components = 1; - break; + return MESA_FORMAT_INTENSITY_FLOAT32; case GL_INTENSITY8I_EXT: - *datatype = GL_BYTE; - *components = 1; - break; + return MESA_FORMAT_INTENSITY_INT8; case GL_INTENSITY16I_EXT: - *datatype = GL_SHORT; - *components = 1; - break; + return MESA_FORMAT_INTENSITY_INT16; case GL_INTENSITY32I_EXT: - *datatype = GL_INT; - *components = 1; - break; + return MESA_FORMAT_INTENSITY_INT32; case GL_INTENSITY8UI_EXT: - *datatype = GL_UNSIGNED_BYTE; - *components = 1; - break; + return MESA_FORMAT_INTENSITY_UINT8; case GL_INTENSITY16UI_EXT: - *datatype = GL_UNSIGNED_SHORT; - *components = 1; - break; + return MESA_FORMAT_INTENSITY_UINT16; case GL_INTENSITY32UI_EXT: - *datatype = GL_UNSIGNED_INT; - *components = 1; - break; + return MESA_FORMAT_INTENSITY_UINT32; case GL_RGBA8: - *datatype = GL_UNSIGNED_BYTE; - *components = 4; - break; + return MESA_FORMAT_RGBA8888_REV; case GL_RGBA16: - *datatype = GL_UNSIGNED_SHORT; - *components = 4; - break; + return MESA_FORMAT_RGBA_16; case GL_RGBA16F_ARB: - *datatype = GL_HALF_FLOAT; - *components = 4; - break; + return MESA_FORMAT_RGBA_FLOAT16; case GL_RGBA32F_ARB: - *datatype = GL_FLOAT; - *components = 4; - break; + return MESA_FORMAT_RGBA_FLOAT32; case GL_RGBA8I_EXT: - *datatype = GL_BYTE; - *components = 4; - break; + return MESA_FORMAT_RGBA_INT8; case GL_RGBA16I_EXT: - *datatype = GL_SHORT; - *components = 4; - break; + return MESA_FORMAT_RGBA_INT16; case GL_RGBA32I_EXT: - *datatype = GL_INT; - *components = 4; - break; + return MESA_FORMAT_RGBA_INT32; case GL_RGBA8UI_EXT: - *datatype = GL_UNSIGNED_BYTE; - *components = 4; - break; + return MESA_FORMAT_RGBA_UINT8; case GL_RGBA16UI_EXT: - *datatype = GL_UNSIGNED_SHORT; - *components = 4; - break; + return MESA_FORMAT_RGBA_UINT16; case GL_RGBA32UI_EXT: - *datatype = GL_UNSIGNED_INT; - *components = 4; - break; + return MESA_FORMAT_RGBA_UINT32; + + case GL_RG8: + return MESA_FORMAT_GR88; + case GL_RG16: + return MESA_FORMAT_RG1616; + case GL_RG16F: + return MESA_FORMAT_RG_FLOAT16; + case GL_RG32F: + return MESA_FORMAT_RG_FLOAT32; + case GL_RG8I: + return MESA_FORMAT_RG_INT8; + case GL_RG16I: + return MESA_FORMAT_RG_INT16; + case GL_RG32I: + return MESA_FORMAT_RG_INT32; + case GL_RG8UI: + return MESA_FORMAT_RG_UINT8; + case GL_RG16UI: + return MESA_FORMAT_RG_UINT16; + case GL_RG32UI: + return MESA_FORMAT_RG_UINT32; + + case GL_R8: + return MESA_FORMAT_R8; + case GL_R16: + return MESA_FORMAT_R16; + case GL_R16F: + return MESA_FORMAT_R_FLOAT16; + case GL_R32F: + return MESA_FORMAT_R_FLOAT32; + case GL_R8I: + return MESA_FORMAT_R_INT8; + case GL_R16I: + return MESA_FORMAT_R_INT16; + case GL_R32I: + return MESA_FORMAT_R_INT32; + case GL_R8UI: + return MESA_FORMAT_R_UINT8; + case GL_R16UI: + return MESA_FORMAT_R_UINT16; + case GL_R32UI: + return MESA_FORMAT_R_UINT32; + default: - return GL_FALSE; + return MESA_FORMAT_NONE; } +} - if (*datatype == GL_FLOAT && !ctx->Extensions.ARB_texture_float) - return GL_FALSE; +static gl_format +validate_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) +{ + gl_format format = get_texbuffer_format(ctx, internalFormat); + GLenum datatype; - if (*datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel) - return GL_FALSE; + if (format == MESA_FORMAT_NONE) + return MESA_FORMAT_NONE; - return GL_TRUE; + datatype = _mesa_get_format_datatype(format); + if (datatype == GL_FLOAT && !ctx->Extensions.ARB_texture_float) + return MESA_FORMAT_NONE; + + if (datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel) + return MESA_FORMAT_NONE; + + /* The GL_ARB_texture_rg and GL_ARB_texture_buffer_object specs don't make + * any mention of R/RG formats, but they appear in the GL 3.1 core + * specification. + */ + if (ctx->VersionMajor < 3 || + (ctx->VersionMajor == 3 && ctx->VersionMinor == 0)) { + GLenum base_format = _mesa_get_format_base_format(format); + + if (base_format == GL_R || base_format == GL_RG) + return MESA_FORMAT_NONE; + } + return format; } @@ -3927,8 +3876,7 @@ _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) { struct gl_texture_object *texObj; struct gl_buffer_object *bufObj; - GLenum dataType; - GLuint comps; + gl_format format; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); @@ -3943,7 +3891,8 @@ _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) return; } - if (!get_sized_format_info(ctx, internalFormat, &dataType, &comps)) { + format = validate_texbuffer_format(ctx, internalFormat); + if (format == MESA_FORMAT_NONE) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(internalFormat 0x%x)", internalFormat); return; @@ -3961,6 +3910,7 @@ _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) { _mesa_reference_buffer_object(ctx, &texObj->BufferObject, bufObj); texObj->BufferObjectFormat = internalFormat; + texObj->_BufferObjectFormat = format; } _mesa_unlock_texture(ctx, texObj); }