X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fteximage.c;h=7cf15f5be63f43e4f7ac8e53fc19fdca5bf14618;hb=30e437bd76c6eb9a8e46b1c96e313b8eafd0b798;hp=3a556a6ad6e9b17028e2a0b066d9208882aa800b;hpb=6a7ca4ef2cd3f39d3b5e77051cb3f3175e9e60df;p=mesa.git diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 3a556a6ad6e..7cf15f5be63 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -116,527 +116,6 @@ adjust_for_oes_float_texture(GLenum format, GLenum type) return format; } -/** - * Return the simple base format for a given internal texture format. - * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. - * - * \param ctx GL context. - * \param internalFormat the internal texture format token or 1, 2, 3, or 4. - * - * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE, - * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum. - * - * This is the format which is used during texture application (i.e. the - * texture format and env mode determine the arithmetic used. - */ -GLint -_mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) -{ - switch (internalFormat) { - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: - return (ctx->API != API_OPENGL_CORE) ? GL_ALPHA : -1; - case 1: - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - return (ctx->API != API_OPENGL_CORE) ? GL_LUMINANCE : -1; - case 2: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - return (ctx->API != API_OPENGL_CORE) ? GL_LUMINANCE_ALPHA : -1; - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: - return (ctx->API != API_OPENGL_CORE) ? GL_INTENSITY : -1; - case 3: - return (ctx->API != API_OPENGL_CORE) ? GL_RGB : -1; - case GL_RGB: - case GL_R3_G3_B2: - case GL_RGB4: - case GL_RGB5: - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - return GL_RGB; - case 4: - return (ctx->API != API_OPENGL_CORE) ? GL_RGBA : -1; - case GL_RGBA: - case GL_RGBA2: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - return GL_RGBA; - default: - ; /* fallthrough */ - } - - /* GL_BGRA can be an internal format *only* in OpenGL ES (1.x or 2.0). - */ - if (_mesa_is_gles(ctx)) { - switch (internalFormat) { - case GL_BGRA: - return GL_RGBA; - default: - ; /* fallthrough */ - } - } - - 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: - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - return GL_DEPTH_COMPONENT; - case GL_DEPTH_STENCIL: - case GL_DEPTH24_STENCIL8: - return GL_DEPTH_STENCIL; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.ARB_texture_stencil8) { - switch (internalFormat) { - case GL_STENCIL_INDEX: - case GL_STENCIL_INDEX1: - case GL_STENCIL_INDEX4: - case GL_STENCIL_INDEX8: - case GL_STENCIL_INDEX16: - return GL_STENCIL_INDEX; - default: - ; /* fallthrough */ - } - } - - switch (internalFormat) { - case GL_COMPRESSED_ALPHA: - return GL_ALPHA; - case GL_COMPRESSED_LUMINANCE: - return GL_LUMINANCE; - case GL_COMPRESSED_LUMINANCE_ALPHA: - return GL_LUMINANCE_ALPHA; - case GL_COMPRESSED_INTENSITY: - return GL_INTENSITY; - case GL_COMPRESSED_RGB: - return GL_RGB; - case GL_COMPRESSED_RGBA: - return GL_RGBA; - default: - ; /* fallthrough */ - } - - if (ctx->Extensions.TDFX_texture_compression_FXT1) { - switch (internalFormat) { - case GL_COMPRESSED_RGB_FXT1_3DFX: - return GL_RGB; - case GL_COMPRESSED_RGBA_FXT1_3DFX: - return GL_RGBA; - default: - ; /* fallthrough */ - } - } - - /* Assume that the ANGLE flag will always be set if the EXT flag is set. - */ - if (ctx->Extensions.ANGLE_texture_compression_dxt) { - switch (internalFormat) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - return GL_RGB; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - return GL_RGBA; - default: - ; /* fallthrough */ - } - } - - if (_mesa_is_desktop_gl(ctx) - && ctx->Extensions.ANGLE_texture_compression_dxt) { - switch (internalFormat) { - case GL_RGB_S3TC: - case GL_RGB4_S3TC: - return GL_RGB; - case GL_RGBA_S3TC: - case GL_RGBA4_S3TC: - return GL_RGBA; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.MESA_ycbcr_texture) { - if (internalFormat == GL_YCBCR_MESA) - return GL_YCBCR_MESA; - } - - if (ctx->Extensions.ARB_texture_float) { - switch (internalFormat) { - case GL_ALPHA16F_ARB: - case GL_ALPHA32F_ARB: - return GL_ALPHA; - case GL_RGBA16F_ARB: - case GL_RGBA32F_ARB: - return GL_RGBA; - case GL_RGB16F_ARB: - case GL_RGB32F_ARB: - return GL_RGB; - case GL_INTENSITY16F_ARB: - case GL_INTENSITY32F_ARB: - return GL_INTENSITY; - case GL_LUMINANCE16F_ARB: - case GL_LUMINANCE32F_ARB: - return GL_LUMINANCE; - case GL_LUMINANCE_ALPHA16F_ARB: - case GL_LUMINANCE_ALPHA32F_ARB: - return GL_LUMINANCE_ALPHA; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_texture_snorm) { - switch (internalFormat) { - case GL_RED_SNORM: - case GL_R8_SNORM: - case GL_R16_SNORM: - return GL_RED; - case GL_RG_SNORM: - case GL_RG8_SNORM: - case GL_RG16_SNORM: - return GL_RG; - case GL_RGB_SNORM: - case GL_RGB8_SNORM: - case GL_RGB16_SNORM: - return GL_RGB; - case GL_RGBA_SNORM: - case GL_RGBA8_SNORM: - case GL_RGBA16_SNORM: - return GL_RGBA; - case GL_ALPHA_SNORM: - case GL_ALPHA8_SNORM: - case GL_ALPHA16_SNORM: - return GL_ALPHA; - case GL_LUMINANCE_SNORM: - case GL_LUMINANCE8_SNORM: - case GL_LUMINANCE16_SNORM: - return GL_LUMINANCE; - case GL_LUMINANCE_ALPHA_SNORM: - case GL_LUMINANCE8_ALPHA8_SNORM: - case GL_LUMINANCE16_ALPHA16_SNORM: - return GL_LUMINANCE_ALPHA; - case GL_INTENSITY_SNORM: - case GL_INTENSITY8_SNORM: - case GL_INTENSITY16_SNORM: - return GL_INTENSITY; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_texture_sRGB) { - switch (internalFormat) { - case GL_SRGB_EXT: - case GL_SRGB8_EXT: - case GL_COMPRESSED_SRGB_EXT: - return GL_RGB; - case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - return ctx->Extensions.EXT_texture_compression_s3tc ? GL_RGB : -1; - case GL_SRGB_ALPHA_EXT: - case GL_SRGB8_ALPHA8_EXT: - case GL_COMPRESSED_SRGB_ALPHA_EXT: - return GL_RGBA; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - return ctx->Extensions.EXT_texture_compression_s3tc ? GL_RGBA : -1; - case GL_SLUMINANCE_ALPHA_EXT: - case GL_SLUMINANCE8_ALPHA8_EXT: - case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: - return GL_LUMINANCE_ALPHA; - case GL_SLUMINANCE_EXT: - case GL_SLUMINANCE8_EXT: - case GL_COMPRESSED_SLUMINANCE_EXT: - return GL_LUMINANCE; - default: - ; /* fallthrough */ - } - } - - if (ctx->Version >= 30 || - ctx->Extensions.EXT_texture_integer) { - switch (internalFormat) { - case GL_RGBA8UI_EXT: - case GL_RGBA16UI_EXT: - case GL_RGBA32UI_EXT: - 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: - case GL_RGB32UI_EXT: - case GL_RGB8I_EXT: - case GL_RGB16I_EXT: - case GL_RGB32I_EXT: - return GL_RGB; - } - } - - if (ctx->Extensions.EXT_texture_integer) { - switch (internalFormat) { - case GL_ALPHA8UI_EXT: - case GL_ALPHA16UI_EXT: - case GL_ALPHA32UI_EXT: - case GL_ALPHA8I_EXT: - case GL_ALPHA16I_EXT: - case GL_ALPHA32I_EXT: - return GL_ALPHA; - case GL_INTENSITY8UI_EXT: - case GL_INTENSITY16UI_EXT: - case GL_INTENSITY32UI_EXT: - case GL_INTENSITY8I_EXT: - case GL_INTENSITY16I_EXT: - case GL_INTENSITY32I_EXT: - return GL_INTENSITY; - case GL_LUMINANCE8UI_EXT: - case GL_LUMINANCE16UI_EXT: - case GL_LUMINANCE32UI_EXT: - case GL_LUMINANCE8I_EXT: - case GL_LUMINANCE16I_EXT: - case GL_LUMINANCE32I_EXT: - return GL_LUMINANCE; - case GL_LUMINANCE_ALPHA8UI_EXT: - case GL_LUMINANCE_ALPHA16UI_EXT: - case GL_LUMINANCE_ALPHA32UI_EXT: - case GL_LUMINANCE_ALPHA8I_EXT: - case GL_LUMINANCE_ALPHA16I_EXT: - case GL_LUMINANCE_ALPHA32I_EXT: - return GL_LUMINANCE_ALPHA; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.ARB_texture_rg) { - switch (internalFormat) { - case GL_R16F: - case GL_R32F: - if (!ctx->Extensions.ARB_texture_float) - break; - return GL_RED; - case GL_R8I: - case GL_R8UI: - case GL_R16I: - case GL_R16UI: - case GL_R32I: - case GL_R32UI: - if (ctx->Version < 30 && !ctx->Extensions.EXT_texture_integer) - break; - /* FALLTHROUGH */ - case GL_R8: - case GL_R16: - case GL_RED: - case GL_COMPRESSED_RED: - return GL_RED; - - case GL_RG16F: - case GL_RG32F: - if (!ctx->Extensions.ARB_texture_float) - break; - return GL_RG; - case GL_RG8I: - case GL_RG8UI: - case GL_RG16I: - case GL_RG16UI: - case GL_RG32I: - case GL_RG32UI: - if (ctx->Version < 30 && !ctx->Extensions.EXT_texture_integer) - break; - /* FALLTHROUGH */ - case GL_RG: - case GL_RG8: - case GL_RG16: - case GL_COMPRESSED_RG: - return GL_RG; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_texture_shared_exponent) { - switch (internalFormat) { - case GL_RGB9_E5_EXT: - return GL_RGB; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_packed_float) { - switch (internalFormat) { - case GL_R11F_G11F_B10F_EXT: - return GL_RGB; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.ARB_depth_buffer_float) { - switch (internalFormat) { - case GL_DEPTH_COMPONENT32F: - return GL_DEPTH_COMPONENT; - case GL_DEPTH32F_STENCIL8: - return GL_DEPTH_STENCIL; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.ARB_texture_compression_rgtc) { - switch (internalFormat) { - case GL_COMPRESSED_RED_RGTC1: - case GL_COMPRESSED_SIGNED_RED_RGTC1: - return GL_RED; - case GL_COMPRESSED_RG_RGTC2: - case GL_COMPRESSED_SIGNED_RG_RGTC2: - return GL_RG; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.EXT_texture_compression_latc) { - switch (internalFormat) { - case GL_COMPRESSED_LUMINANCE_LATC1_EXT: - case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: - return GL_LUMINANCE; - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: - return GL_LUMINANCE_ALPHA; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.ATI_texture_compression_3dc) { - switch (internalFormat) { - case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: - return GL_LUMINANCE_ALPHA; - default: - ; /* fallthrough */ - } - } - - if (ctx->Extensions.OES_compressed_ETC1_RGB8_texture) { - switch (internalFormat) { - case GL_ETC1_RGB8_OES: - return GL_RGB; - default: - ; /* fallthrough */ - } - } - - if (_mesa_is_gles3(ctx) || ctx->Extensions.ARB_ES3_compatibility) { - switch (internalFormat) { - case GL_COMPRESSED_RGB8_ETC2: - case GL_COMPRESSED_SRGB8_ETC2: - return GL_RGB; - case GL_COMPRESSED_RGBA8_ETC2_EAC: - case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: - case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: - case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: - return GL_RGBA; - case GL_COMPRESSED_R11_EAC: - case GL_COMPRESSED_SIGNED_R11_EAC: - return GL_RED; - case GL_COMPRESSED_RG11_EAC: - case GL_COMPRESSED_SIGNED_RG11_EAC: - return GL_RG; - default: - ; /* fallthrough */ - } - } - - if (_mesa_is_desktop_gl(ctx) && - ctx->Extensions.ARB_texture_compression_bptc) { - switch (internalFormat) { - case GL_COMPRESSED_RGBA_BPTC_UNORM: - case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: - return GL_RGBA; - case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: - case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: - 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 */ -} - - -/** - * For cube map faces, return a face index in [0,5]. - * For other targets return 0; - */ -GLuint -_mesa_tex_target_to_face(GLenum target) -{ - if (_mesa_is_cube_face(target)) - return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; - else - return 0; -} - - /** * Install gl_texture_image in a gl_texture_object according to the target @@ -763,6 +242,24 @@ _mesa_is_array_texture(GLenum target) }; } +/** + * Test if a target is a cube map. + * + * \param target texture target. + * + * \return true if the target is a cube map, false otherwise. + */ +bool +_mesa_is_cube_map_texture(GLenum target) +{ + switch(target) { + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_ARRAY: + return true; + default: + return false; + } +} /** * Return the proxy target which corresponds to the given texture target @@ -780,15 +277,15 @@ proxy_target(GLenum target) case GL_TEXTURE_3D: case GL_PROXY_TEXTURE_3D: return GL_PROXY_TEXTURE_3D; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - 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 GL_PROXY_TEXTURE_CUBE_MAP_ARB; + 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_CUBE_MAP: + case GL_PROXY_TEXTURE_CUBE_MAP: + return GL_PROXY_TEXTURE_CUBE_MAP; case GL_TEXTURE_RECTANGLE_NV: case GL_PROXY_TEXTURE_RECTANGLE_NV: return GL_PROXY_TEXTURE_RECTANGLE_NV; @@ -979,13 +476,13 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) case GL_PROXY_TEXTURE_3D: return ctx->Const.Max3DTextureLevels; case GL_TEXTURE_CUBE_MAP: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - 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_PROXY_TEXTURE_CUBE_MAP_ARB: + 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_PROXY_TEXTURE_CUBE_MAP: return ctx->Extensions.ARB_texture_cube_map ? ctx->Const.MaxCubeTextureLevels : 0; case GL_TEXTURE_RECTANGLE_NV: @@ -1002,8 +499,8 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) return ctx->Extensions.ARB_texture_cube_map_array ? ctx->Const.MaxCubeTextureLevels : 0; case GL_TEXTURE_BUFFER: - return ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object ? 1 : 0; + return (_mesa_has_ARB_texture_buffer_object(ctx) || + _mesa_has_OES_texture_buffer(ctx)) ? 1 : 0; case GL_TEXTURE_2D_MULTISAMPLE: case GL_PROXY_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: @@ -1523,7 +1020,7 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target, case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + case GL_PROXY_TEXTURE_CUBE_MAP: maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); maxSize >>= level; if (width != height) @@ -1615,7 +1112,7 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, GLsizei subDepth, const char *func) { const GLenum target = destImage->TexObject->Target; - GLuint bw, bh; + GLuint bw, bh, bd; /* Check size */ if (subWidth < 0) { @@ -1688,14 +1185,14 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, * compressed formats supported by Mesa allow sub-textures to be updated * along compressed block boundaries. */ - _mesa_get_format_block_size(destImage->TexFormat, &bw, &bh); + _mesa_get_format_block_size_3d(destImage->TexFormat, &bw, &bh, &bd); - if (bw != 1 || bh != 1) { + if (bw != 1 || bh != 1 || bd != 1) { /* offset must be multiple of block size */ - if ((xoffset % bw != 0) || (yoffset % bh != 0)) { + if ((xoffset % bw != 0) || (yoffset % bh != 0) || (zoffset % bd != 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(xoffset = %d, yoffset = %d)", - func, xoffset, yoffset); + "%s(xoffset = %d, yoffset = %d, zoffset = %d)", + func, xoffset, yoffset, zoffset); return GL_TRUE; } @@ -1717,6 +1214,13 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, "%s(height = %d)", func, subHeight); return GL_TRUE; } + + if ((subDepth % bd != 0) && + (zoffset + subDepth != (GLint) destImage->Depth)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(depth = %d)", func, subDepth); + return GL_TRUE; + } } return GL_FALSE; @@ -1763,7 +1267,7 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level, /** * Return true if the format is only valid for glCompressedTexImage. */ -static GLboolean +static bool compressedteximage_only_format(const struct gl_context *ctx, GLenum format) { switch (format) { @@ -1778,25 +1282,52 @@ compressedteximage_only_format(const struct gl_context *ctx, GLenum format) case GL_PALETTE8_R5_G6_B5_OES: case GL_PALETTE8_RGBA4_OES: case GL_PALETTE8_RGB5_A1_OES: - return GL_TRUE; + return true; default: - return GL_FALSE; + return false; } } +/** + * Return true if the format doesn't support online compression. + */ +bool +_mesa_format_no_online_compression(const struct gl_context *ctx, GLenum format) +{ + return _mesa_is_astc_format(format) || + compressedteximage_only_format(ctx, format); +} + +/* Writes to an GL error pointer if non-null and returns whether or not the + * error is GL_NO_ERROR */ +static bool +write_error(GLenum *err_ptr, GLenum error) +{ + if (err_ptr) + *err_ptr = error; + + return error == GL_NO_ERROR; +} /** * Helper function to determine whether a target and specific compression - * format are supported. + * format are supported. The error parameter returns GL_NO_ERROR if the + * target can be compressed. Otherwise it returns either GL_INVALID_OPERATION + * or GL_INVALID_ENUM, whichever is more appropriate. */ GLboolean _mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target, - GLenum intFormat) + GLenum intFormat, GLenum *error) { + GLboolean target_can_be_compresed = GL_FALSE; + mesa_format format = _mesa_glenum_to_compressed_format(intFormat); + enum mesa_format_layout layout = _mesa_get_format_layout(format); + switch (target) { case GL_TEXTURE_2D: case GL_PROXY_TEXTURE_2D: - return GL_TRUE; /* true for any compressed format so far */ + target_can_be_compresed = GL_TRUE; /* true for any compressed format so far */ + break; case GL_PROXY_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -1805,26 +1336,82 @@ _mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target, case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - return ctx->Extensions.ARB_texture_cube_map; + target_can_be_compresed = ctx->Extensions.ARB_texture_cube_map; + break; case GL_PROXY_TEXTURE_2D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: - return ctx->Extensions.EXT_texture_array; + target_can_be_compresed = ctx->Extensions.EXT_texture_array; + break; case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: - return ctx->Extensions.ARB_texture_cube_map_array; + /* From the KHR_texture_compression_astc_hdr spec: + * + * Add a second new column "3D Tex." which is empty for all non-ASTC + * formats. If only the LDR profile is supported by the + * implementation, this column is also empty for all ASTC formats. If + * both the LDR and HDR profiles are supported only, this column is + * checked for all ASTC formats. + * + * Add a third new column "Cube Map Array Tex." which is empty for all + * non-ASTC formats, and checked for all ASTC formats. + * + * and, + * + * 'An INVALID_OPERATION error is generated by CompressedTexImage3D + * if is TEXTURE_CUBE_MAP_ARRAY and the + * "Cube Map Array" column of table 8.19 is *not* checked, or if + * is TEXTURE_3D and the "3D Tex." column of table + * 8.19 is *not* checked' + * + * The instances of above should say . + * + * ETC2/EAC formats are the only alternative in GLES and thus such errors + * have already been handled by normal ETC2/EAC behavior. + */ + + /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec: + * + * "The ETC2/EAC texture compression algorithm supports only + * two-dimensional images. If internalformat is an ETC2/EAC format, + * glCompressedTexImage3D will generate an INVALID_OPERATION error if + * target is not TEXTURE_2D_ARRAY." + * + * This should also be applicable for glTexStorage3D(). Other available + * targets for these functions are: TEXTURE_3D and TEXTURE_CUBE_MAP_ARRAY. + */ + if (layout == MESA_FORMAT_LAYOUT_ETC2 && _mesa_is_gles3(ctx)) + return write_error(error, GL_INVALID_OPERATION); + target_can_be_compresed = ctx->Extensions.ARB_texture_cube_map_array; + break; case GL_TEXTURE_3D: - switch (intFormat) { - case GL_COMPRESSED_RGBA_BPTC_UNORM: - case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: - case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: - case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: - return ctx->Extensions.ARB_texture_compression_bptc; + switch (layout) { + case MESA_FORMAT_LAYOUT_ETC2: + /* See ETC2/EAC comment in case GL_TEXTURE_CUBE_MAP_ARRAY. */ + if (_mesa_is_gles3(ctx)) + return write_error(error, GL_INVALID_OPERATION); + break; + case MESA_FORMAT_LAYOUT_BPTC: + target_can_be_compresed = ctx->Extensions.ARB_texture_compression_bptc; + break; + case MESA_FORMAT_LAYOUT_ASTC: + target_can_be_compresed = + ctx->Extensions.KHR_texture_compression_astc_hdr; + + /* Throw an INVALID_OPERATION error if the target is TEXTURE_3D and + * and the hdr extension is not supported. + * See comment in switch case GL_TEXTURE_CUBE_MAP_ARRAY for more info. + */ + if (!target_can_be_compresed) + return write_error(error, GL_INVALID_OPERATION); + break; default: - return GL_FALSE; + break; } default: - return GL_FALSE; + break; } + return write_error(error, + target_can_be_compresed ? GL_NO_ERROR : GL_INVALID_ENUM); } @@ -1990,19 +1577,12 @@ compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, * \param ctx GL context * \param target Texture target * \param internalFormat Internal format of the texture image - * \param dimensions Dimensionality at the caller. This is \b not used - * in the validation. It is only used when logging - * error messages. - * \param caller Base name of the calling function (e.g., - * "glTexImage" or "glTexStorage"). * * \returns true if the combination is legal, false otherwise. */ bool _mesa_legal_texture_base_format_for_target(struct gl_context *ctx, - GLenum target, GLenum internalFormat, - unsigned dimensions, - const char *caller) + GLenum target, GLenum internalFormat) { if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT || _mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_STENCIL @@ -2041,9 +1621,6 @@ _mesa_legal_texture_base_format_for_target(struct gl_context *ctx, !((target == GL_TEXTURE_CUBE_MAP_ARRAY || target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY) && ctx->Extensions.ARB_texture_cube_map_array)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s%dD(bad target for depth texture)", - caller, dimensions); return false; } } @@ -2123,7 +1700,7 @@ texture_format_error_check_gles(struct gl_context *ctx, GLenum format, } } else { - err = _mesa_es_error_check_format_and_type(format, type, dimensions); + err = _mesa_es_error_check_format_and_type(ctx, format, type, dimensions); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "%s(format = %s, type = %s)", callerName, _mesa_enum_to_string(format), @@ -2201,15 +1778,23 @@ texture_error_check( struct gl_context *ctx, return GL_TRUE; } - /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the - * combinations of format, internalFormat, and type that can be used. - * Formats and types that require additional extensions (e.g., GL_FLOAT - * requires GL_OES_texture_float) are filtered elsewhere. - */ - if (_mesa_is_gles(ctx) && - texture_format_error_check_gles(ctx, format, type, internalFormat, - dimensions, "glTexImage%dD")) { - return GL_TRUE; + /* Check incoming image format and type */ + err = _mesa_error_check_format_and_type(ctx, format, type); + if (err != GL_NO_ERROR) { + /* Prior to OpenGL-ES 2.0, an INVALID_VALUE is expected instead of + * INVALID_ENUM. From page 73 OpenGL ES 1.1 spec: + * + * "Specifying a value for internalformat that is not one of the + * above (acceptable) values generates the error INVALID VALUE." + */ + if (err == GL_INVALID_ENUM && _mesa_is_gles(ctx) && ctx->Version < 20) + err = GL_INVALID_VALUE; + + _mesa_error(ctx, err, + "glTexImage%dD(incompatible format = %s, type = %s)", + dimensions, _mesa_enum_to_string(format), + _mesa_enum_to_string(type)); + return GL_TRUE; } /* Check internalFormat */ @@ -2220,13 +1805,14 @@ texture_error_check( struct gl_context *ctx, return GL_TRUE; } - /* Check incoming image format and type */ - err = _mesa_error_check_format_and_type(ctx, format, type); - if (err != GL_NO_ERROR) { - _mesa_error(ctx, err, - "glTexImage%dD(incompatible format = %s, type = %s)", - dimensions, _mesa_enum_to_string(format), - _mesa_enum_to_string(type)); + /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the + * combinations of format, internalFormat, and type that can be used. + * Formats and types that require additional extensions (e.g., GL_FLOAT + * requires GL_OES_texture_float) are filtered elsewhere. + */ + if (_mesa_is_gles(ctx) && + texture_format_error_check_gles(ctx, format, type, internalFormat, + dimensions, "glTexImage%dD")) { return GL_TRUE; } @@ -2278,18 +1864,21 @@ texture_error_check( struct gl_context *ctx, } /* additional checks for depth textures */ - if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalFormat, - dimensions, "glTexImage")) + if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage%dD(bad target for texture)", dimensions); return GL_TRUE; + } /* additional checks for compressed textures */ if (_mesa_is_compressed_format(ctx, internalFormat)) { - if (!_mesa_target_can_be_compressed(ctx, target, internalFormat)) { - _mesa_error(ctx, GL_INVALID_ENUM, + GLenum err; + if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) { + _mesa_error(ctx, err, "glTexImage%dD(target can't be compressed)", dimensions); return GL_TRUE; } - if (compressedteximage_only_format(ctx, internalFormat)) { + if (_mesa_format_no_online_compression(ctx, internalFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexImage%dD(no compression for format)", dimensions); return GL_TRUE; @@ -2340,16 +1929,8 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, GLenum error = GL_NO_ERROR; char *reason = ""; /* no error */ - if (!_mesa_target_can_be_compressed(ctx, target, internalFormat)) { + if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &error)) { reason = "target"; - /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec: - * - * "The ETC2/EAC texture compression algorithm supports only - * two-dimensional images. If internalformat is an ETC2/EAC format, - * CompressedTexImage3D will generate an INVALID_OPERATION error if - * target is not TEXTURE_2D_ARRAY." - */ - error = _mesa_is_desktop_gl(ctx) ? GL_INVALID_ENUM : GL_INVALID_OPERATION; goto error; } @@ -2450,7 +2031,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, * if is not consistent with the format, dimensions, and * contents of the specified image. */ - reason = "imageSize inconsistant with width/height/format"; + reason = "imageSize inconsistent with width/height/format"; error = GL_INVALID_VALUE; goto error; } @@ -2561,7 +2142,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions, } if (_mesa_is_format_compressed(texImage->TexFormat)) { - if (compressedteximage_only_format(ctx, texImage->InternalFormat)) { + if (_mesa_format_no_online_compression(ctx, texImage->InternalFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no compression for format)", callerName); return GL_TRUE; @@ -2669,6 +2250,22 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, _mesa_enum_to_string(internalFormat)); return GL_TRUE; } + } else { + /* + * Section 8.6 (Alternate Texture Image Specification Commands) of the + * OpenGL 4.5 (Compatibility Profile) spec says: + * + * "Parameters level, internalformat, and border are specified using + * the same values, with the same meanings, as the corresponding + * arguments of TexImage2D, except that internalformat may not be + * specified as 1, 2, 3, or 4." + */ + if (internalFormat >= 1 && internalFormat <= 4) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glCopyTexImage%dD(internalFormat=%d)", dimensions, + internalFormat); + return GL_TRUE; + } } baseFormat = _mesa_base_tex_format(ctx, internalFormat); @@ -2705,8 +2302,10 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, } if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL || + baseFormat == GL_STENCIL_INDEX || rb_base_format == GL_DEPTH_COMPONENT || rb_base_format == GL_DEPTH_STENCIL || + rb_base_format == GL_STENCIL_INDEX || ((baseFormat == GL_LUMINANCE_ALPHA || baseFormat == GL_ALPHA) && rb_base_format != GL_RGBA) || @@ -2813,12 +2412,13 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, } if (_mesa_is_compressed_format(ctx, internalFormat)) { - if (!_mesa_target_can_be_compressed(ctx, target, internalFormat)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glCopyTexImage%dD(target)", dimensions); + GLenum err; + if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) { + _mesa_error(ctx, err, + "glCopyTexImage%dD(target can't be compressed)", dimensions); return GL_TRUE; } - if (compressedteximage_only_format(ctx, internalFormat)) { + if (_mesa_format_no_online_compression(ctx, internalFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexImage%dD(no compression for format)", dimensions); return GL_TRUE; @@ -2899,7 +2499,7 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, } if (_mesa_is_format_compressed(texImage->TexFormat)) { - if (compressedteximage_only_format(ctx, texImage->InternalFormat)) { + if (_mesa_format_no_online_compression(ctx, texImage->InternalFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no compression for format)", caller); return GL_TRUE; @@ -2913,8 +2513,8 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, if (!_mesa_source_buffer_exists(ctx, texImage->_BaseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(missing readbuffer, format=0x%x)", caller, - texImage->_BaseFormat); + "%s(missing readbuffer, format=%s)", caller, + _mesa_enum_to_string(texImage->_BaseFormat)); return GL_TRUE; } @@ -2937,6 +2537,15 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, } } + /* In the ES 3.2 specification's Table 8.13 (Valid CopyTexImage source + * framebuffer/destination texture base internal format combinations), + * all the entries for stencil are left blank (unsupported). + */ + if (_mesa_is_gles(ctx) && _mesa_is_stencil_format(texImage->_BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(stencil disallowed)", caller); + return GL_TRUE; + } + /* if we get here, the parameters are OK */ return GL_FALSE; } @@ -3670,7 +3279,7 @@ texturesubimage(struct gl_context *ctx, GLuint dims, /* Must handle special case GL_TEXTURE_CUBE_MAP. */ if (texObj->Target == GL_TEXTURE_CUBE_MAP) { - GLint rowStride; + GLint imageStride; /* * What do we do if the user created a texture with the following code @@ -3708,18 +3317,18 @@ texturesubimage(struct gl_context *ctx, GLuint dims, return; } - rowStride = _mesa_image_image_stride(&ctx->Unpack, width, height, - format, type); + imageStride = _mesa_image_image_stride(&ctx->Unpack, width, height, + format, type); /* Copy in each face. */ - for (i = 0; i < 6; ++i) { + for (i = zoffset; i < zoffset + depth; ++i) { texImage = texObj->Image[i][level]; assert(texImage); _mesa_texture_sub_image(ctx, 3, texObj, texImage, texObj->Target, - level, xoffset, yoffset, zoffset, + level, xoffset, yoffset, 0, width, height, 1, format, type, pixels, true); - pixels = (GLubyte *) pixels + rowStride; + pixels = (GLubyte *) pixels + imageStride; } } else { @@ -3832,8 +3441,9 @@ get_copy_tex_image_source(struct gl_context *ctx, mesa_format texFormat) if (_mesa_get_format_bits(texFormat, GL_DEPTH_BITS) > 0) { /* reading from depth/stencil buffer */ return ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; - } - else { + } else if (_mesa_get_format_bits(texFormat, GL_STENCIL_BITS) > 0) { + return ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; + } else { /* copying from color buffer */ return ctx->ReadBuffer->_ColorReadBuffer; } @@ -3891,6 +3501,24 @@ formats_differ_in_component_sizes(mesa_format f1, mesa_format f2) return GL_FALSE; } +static bool +can_avoid_reallocation(struct gl_texture_image *texImage, GLenum internalFormat, + mesa_format texFormat, GLint x, GLint y, GLsizei width, + GLsizei height, GLint border) +{ + if (texImage->InternalFormat != internalFormat) + return false; + if (texImage->TexFormat != texFormat) + return false; + if (texImage->Border != border) + return false; + if (texImage->Width2 != width) + return false; + if (texImage->Height2 != height) + return false; + return true; +} + /** * Implement the glCopyTexImage1/2D() functions. */ @@ -3934,6 +3562,24 @@ copyteximage(struct gl_context *ctx, GLuint dims, texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, internalFormat, GL_NONE, GL_NONE); + /* First check if reallocating the texture buffer can be avoided. + * Without the realloc the copy can be 20x faster. + */ + _mesa_lock_texture(ctx, texObj); + { + texImage = _mesa_select_tex_image(texObj, target, level); + if (texImage && can_avoid_reallocation(texImage, internalFormat, texFormat, + x, y, width, height, border)) { + _mesa_unlock_texture(ctx, texObj); + return _mesa_copy_texture_sub_image(ctx, dims, texObj, target, level, + 0, 0, 0, x, y, width, height, + "CopyTexImage"); + } + } + _mesa_unlock_texture(ctx, texObj); + _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_LOW, "glCopyTexImage " + "can't avoid reallocating texture storage\n"); + rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); if (_mesa_is_gles3(ctx)) { @@ -4724,15 +4370,15 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, if ((GLint) format != texImage->InternalFormat) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(format=0x%x)", - callerName, format); + "%s(format=%s)", + callerName, _mesa_enum_to_string(format)); return GL_TRUE; } if (compressedteximage_only_format(ctx, format)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(format=0x%x cannot be updated)", - callerName, format); + "%s(format=%s cannot be updated)", + callerName, _mesa_enum_to_string(format)); return GL_TRUE; } @@ -5088,7 +4734,7 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset, static mesa_format get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) { - if (ctx->API != API_OPENGL_CORE) { + if (ctx->API == API_OPENGL_COMPAT) { switch (internalFormat) { case GL_ALPHA8: return MESA_FORMAT_A_UNORM8; @@ -5175,8 +4821,8 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) } } - if (ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object_rgb32) { + if (_mesa_has_ARB_texture_buffer_object_rgb32(ctx) || + _mesa_has_OES_texture_buffer(ctx)) { switch (internalFormat) { case GL_RGB32F: return MESA_FORMAT_RGB_FLOAT32; @@ -5193,6 +4839,8 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) case GL_RGBA8: return MESA_FORMAT_R8G8B8A8_UNORM; case GL_RGBA16: + if (_mesa_is_gles(ctx)) + return MESA_FORMAT_NONE; return MESA_FORMAT_RGBA_UNORM16; case GL_RGBA16F_ARB: return MESA_FORMAT_RGBA_FLOAT16; @@ -5214,6 +4862,8 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) case GL_RG8: return MESA_FORMAT_R8G8_UNORM; case GL_RG16: + if (_mesa_is_gles(ctx)) + return MESA_FORMAT_NONE; return MESA_FORMAT_R16G16_UNORM; case GL_RG16F: return MESA_FORMAT_RG_FLOAT16; @@ -5235,6 +4885,8 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) case GL_R8: return MESA_FORMAT_R_UNORM8; case GL_R16: + if (_mesa_is_gles(ctx)) + return MESA_FORMAT_NONE; return MESA_FORMAT_R_UNORM16; case GL_R16F: return MESA_FORMAT_R_FLOAT16; @@ -5312,8 +4964,8 @@ _mesa_texture_buffer_range(struct gl_context *ctx, /* NOTE: ARB_texture_buffer_object has interactions with * the compatibility profile that are not implemented. */ - if (!(ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object)) { + if (!_mesa_has_ARB_texture_buffer_object(ctx) && + !_mesa_has_OES_texture_buffer(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(ARB_texture_buffer_object is not" " implemented for the compatibility profile)", caller); @@ -5322,8 +4974,8 @@ _mesa_texture_buffer_range(struct gl_context *ctx, format = _mesa_validate_texbuffer_format(ctx, internalFormat); if (format == MESA_FORMAT_NONE) { - _mesa_error(ctx, GL_INVALID_ENUM, - "%s(internalFormat 0x%x)", caller, internalFormat); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat %s)", + caller, _mesa_enum_to_string(internalFormat)); return; } @@ -5565,14 +5217,17 @@ _mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer, bufObj, offset, size, "glTextureBufferRange"); } -static GLboolean -is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat) +GLboolean +_mesa_is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat) { /* Everything that is allowed for renderbuffers, - * except for a base format of GL_STENCIL_INDEX. + * except for a base format of GL_STENCIL_INDEX, unless supported. */ GLenum baseFormat = _mesa_base_fbo_format(ctx, internalformat); - return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX; + if (ctx->Extensions.ARB_texture_stencil8) + return baseFormat != 0; + else + return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX; } @@ -5596,13 +5251,13 @@ check_multisample_target(GLuint dims, GLenum target, bool dsa) static void -_mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, - struct gl_texture_object *texObj, - GLenum target, GLsizei samples, - GLint internalformat, GLsizei width, - GLsizei height, GLsizei depth, - GLboolean fixedsamplelocations, - GLboolean immutable, const char *func) +texture_image_multisample(struct gl_context *ctx, GLuint dims, + struct gl_texture_object *texObj, + GLenum target, GLsizei samples, + GLint internalformat, GLsizei width, + GLsizei height, GLsizei depth, + GLboolean fixedsamplelocations, + GLboolean immutable, const char *func) { struct gl_texture_image *texImage; GLboolean sizeOK, dimensionsOK, samplesOK; @@ -5616,6 +5271,11 @@ _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, return; } + if (samples < 1) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples < 1)", func); + return; + } + if (!check_multisample_target(dims, target, dsa)) { if (dsa) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(target)", func); @@ -5638,7 +5298,7 @@ _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, return; } - if (!is_renderable_texture_format(ctx, internalformat)) { + if (!_mesa_is_renderable_texture_format(ctx, internalformat)) { /* Page 172 of OpenGL ES 3.1 spec says: * "An INVALID_ENUM error is generated if sizedinternalformat is not * color-renderable, depth-renderable, or stencil-renderable (as @@ -5763,10 +5423,10 @@ _mesa_TexImage2DMultisample(GLenum target, GLsizei samples, if (!texObj) return; - _mesa_texture_image_multisample(ctx, 2, texObj, target, samples, - internalformat, width, height, 1, - fixedsamplelocations, GL_FALSE, - "glTexImage2DMultisample"); + texture_image_multisample(ctx, 2, texObj, target, samples, + internalformat, width, height, 1, + fixedsamplelocations, GL_FALSE, + "glTexImage2DMultisample"); } @@ -5783,12 +5443,26 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples, if (!texObj) return; - _mesa_texture_image_multisample(ctx, 3, texObj, target, samples, - internalformat, width, height, depth, - fixedsamplelocations, GL_FALSE, - "glTexImage3DMultisample"); + texture_image_multisample(ctx, 3, texObj, target, samples, + internalformat, width, height, depth, + fixedsamplelocations, GL_FALSE, + "glTexImage3DMultisample"); } +static bool +valid_texstorage_ms_parameters(GLsizei width, GLsizei height, GLsizei depth, + GLsizei samples, unsigned dims) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!_mesa_valid_tex_storage_dim(width, height, depth)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexStorage%uDMultisample(width=%d,height=%d,depth=%d)", + dims, width, height, depth); + return false; + } + return true; +} void GLAPIENTRY _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples, @@ -5802,10 +5476,13 @@ _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples, if (!texObj) return; - _mesa_texture_image_multisample(ctx, 2, texObj, target, samples, - internalformat, width, height, 1, - fixedsamplelocations, GL_TRUE, - "glTexStorage2DMultisample"); + if (!valid_texstorage_ms_parameters(width, height, 1, samples, 2)) + return; + + texture_image_multisample(ctx, 2, texObj, target, samples, + internalformat, width, height, 1, + fixedsamplelocations, GL_TRUE, + "glTexStorage2DMultisample"); } void GLAPIENTRY @@ -5821,10 +5498,13 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, if (!texObj) return; - _mesa_texture_image_multisample(ctx, 3, texObj, target, samples, - internalformat, width, height, depth, - fixedsamplelocations, GL_TRUE, - "glTexStorage3DMultisample"); + if (!valid_texstorage_ms_parameters(width, height, depth, samples, 3)) + return; + + texture_image_multisample(ctx, 3, texObj, target, samples, + internalformat, width, height, depth, + fixedsamplelocations, GL_TRUE, + "glTexStorage3DMultisample"); } void GLAPIENTRY @@ -5841,10 +5521,13 @@ _mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples, if (!texObj) return; - _mesa_texture_image_multisample(ctx, 2, texObj, texObj->Target, samples, - internalformat, width, height, 1, - fixedsamplelocations, GL_TRUE, - "glTextureStorage2DMultisample"); + if (!valid_texstorage_ms_parameters(width, height, 1, samples, 2)) + return; + + texture_image_multisample(ctx, 2, texObj, texObj->Target, samples, + internalformat, width, height, 1, + fixedsamplelocations, GL_TRUE, + "glTextureStorage2DMultisample"); } void GLAPIENTRY @@ -5862,8 +5545,11 @@ _mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples, if (!texObj) return; - _mesa_texture_image_multisample(ctx, 3, texObj, texObj->Target, samples, - internalformat, width, height, depth, - fixedsamplelocations, GL_TRUE, - "glTextureStorage3DMultisample"); + if (!valid_texstorage_ms_parameters(width, height, depth, samples, 3)) + return; + + texture_image_multisample(ctx, 3, texObj, texObj->Target, samples, + internalformat, width, height, depth, + fixedsamplelocations, GL_TRUE, + "glTextureStorage3DMultisample"); }