diff options
author | marha <marha@users.sourceforge.net> | 2012-09-27 15:15:06 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2012-09-27 15:15:06 +0200 |
commit | 24703f26d8ed55b1971aa2e94d33636e871bff0b (patch) | |
tree | 3e57b600f4446a1db1d8e73cb8a83519570eb678 /mesalib/src | |
parent | 94ef26cb962261d0b47daf7ef3c856510999bd4c (diff) | |
parent | 2cf1e3de4759264eac2fa8ac758ea750636542f8 (diff) | |
download | vcxsrv-24703f26d8ed55b1971aa2e94d33636e871bff0b.tar.gz vcxsrv-24703f26d8ed55b1971aa2e94d33636e871bff0b.tar.bz2 vcxsrv-24703f26d8ed55b1971aa2e94d33636e871bff0b.zip |
Merge remote-tracking branch 'origin/released'
* origin/released:
mesa xserver pixman xkeyboard-config git update 27 sep 2012
Diffstat (limited to 'mesalib/src')
-rw-r--r-- | mesalib/src/mesa/drivers/common/meta.c | 47 | ||||
-rw-r--r-- | mesalib/src/mesa/drivers/common/meta.h | 1 | ||||
-rw-r--r-- | mesalib/src/mesa/main/blend.c | 7 | ||||
-rw-r--r-- | mesalib/src/mesa/main/enable.c | 26 | ||||
-rw-r--r-- | mesalib/src/mesa/main/enable.h | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/main/ff_fragment_shader.cpp | 26 | ||||
-rw-r--r-- | mesalib/src/mesa/main/glformats.c | 69 | ||||
-rw-r--r-- | mesalib/src/mesa/main/glformats.h | 4 | ||||
-rw-r--r-- | mesalib/src/mesa/main/glheader.h | 7 | ||||
-rw-r--r-- | mesalib/src/mesa/main/imports.h | 7 | ||||
-rw-r--r-- | mesalib/src/mesa/main/macros.h | 21 | ||||
-rw-r--r-- | mesalib/src/mesa/main/readpix.c | 6 | ||||
-rw-r--r-- | mesalib/src/mesa/main/teximage.c | 697 | ||||
-rw-r--r-- | mesalib/src/mesa/main/teximage.h | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_cb_texture.c | 5 |
15 files changed, 423 insertions, 506 deletions
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 28a79b0a0..6689337e3 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -187,6 +187,9 @@ struct save_state /** MESA_META_MULTISAMPLE */ GLboolean MultisampleEnabled; + /** MESA_META_FRAMEBUFFER_SRGB */ + GLboolean sRGBEnabled; + /** Miscellaneous (always disabled) */ GLboolean Lighting; GLboolean RasterDiscard; @@ -773,6 +776,12 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) _mesa_set_multisample(ctx, GL_FALSE); } + if (state & MESA_META_FRAMEBUFFER_SRGB) { + save->sRGBEnabled = ctx->Color.sRGBEnabled; + if (ctx->Color.sRGBEnabled) + _mesa_set_framebuffer_srgb(ctx, GL_FALSE); + } + /* misc */ { save->Lighting = ctx->Light.Enabled; @@ -1075,6 +1084,11 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_set_multisample(ctx, save->MultisampleEnabled); } + if (state & MESA_META_FRAMEBUFFER_SRGB) { + if (ctx->Color.sRGBEnabled != save->sRGBEnabled) + _mesa_set_framebuffer_srgb(ctx, save->sRGBEnabled); + } + /* misc */ if (save->Lighting) { _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE); @@ -1394,7 +1408,6 @@ blitframebuffer_texture(struct gl_context *ctx, const GLuint srcLevel = readAtt->TextureLevel; const GLint baseLevelSave = texObj->BaseLevel; const GLint maxLevelSave = texObj->MaxLevel; - const GLenum fbo_srgb_save = ctx->Color.sRGBEnabled; const GLenum target = texObj->Target; GLuint sampler, samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? @@ -1433,15 +1446,14 @@ blitframebuffer_texture(struct gl_context *ctx, _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - /* Always do our blits with no sRGB decode or encode.*/ + /* Always do our blits with no sRGB decode or encode. Note that + * GL_FRAMEBUFFER_SRGB has already been disabled by + * _mesa_meta_begin(). + */ if (ctx->Extensions.EXT_texture_sRGB_decode) { _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); } - if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_framebuffer_sRGB) - || _mesa_is_gles3(ctx)) { - _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE); - } _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); _mesa_set_enable(ctx, target, GL_TRUE); @@ -1500,9 +1512,6 @@ blitframebuffer_texture(struct gl_context *ctx, _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); } - if (ctx->Extensions.EXT_framebuffer_sRGB && fbo_srgb_save) { - _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE); - } _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); _mesa_DeleteSamplers(1, &sampler); @@ -1713,7 +1722,8 @@ _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) GLbitfield metaSave = (MESA_META_ALL - MESA_META_SCISSOR - MESA_META_PIXEL_STORE - - MESA_META_CONDITIONAL_RENDER); + MESA_META_CONDITIONAL_RENDER - + MESA_META_FRAMEBUFFER_SRGB); const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; if (buffers & BUFFER_BITS_COLOR) { @@ -3236,7 +3246,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, const GLuint maxLevel = texObj->MaxLevel; const GLint maxLevelSave = texObj->MaxLevel; const GLboolean genMipmapSave = texObj->GenerateMipmap; - const GLenum srgbBufferSave = ctx->Color.sRGBEnabled; const GLuint fboSave = ctx->DrawBuffer->Name; const GLuint currentTexUnitSave = ctx->Texture.CurrentUnit; const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && @@ -3330,12 +3339,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, else assert(!genMipmapSave); - if ((ctx->Extensions.EXT_framebuffer_sRGB && - _mesa_is_desktop_gl(ctx)) || - _mesa_is_gles3(ctx)) { - _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE); - } - /* Setup texture coordinates */ setup_texture_coords(faceTarget, slice, @@ -3452,10 +3455,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); } - if (ctx->Extensions.EXT_framebuffer_sRGB && srgbBufferSave) { - _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE); - } - _mesa_lock_texture(ctx, texObj); /* relock */ _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); @@ -3734,12 +3733,6 @@ decompress_texture_image(struct gl_context *ctx, _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, texImage->Level); } - /* No sRGB decode or encode.*/ - if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_framebuffer_sRGB) - || _mesa_is_gles3(ctx)) { - _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE); - } - /* render quad w/ texture into renderbuffer */ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h index d8dfb56f9..6ffc5b56a 100644 --- a/mesalib/src/mesa/drivers/common/meta.h +++ b/mesalib/src/mesa/drivers/common/meta.h @@ -56,6 +56,7 @@ #define MESA_META_CLIP 0x40000 #define MESA_META_SELECT_FEEDBACK 0x80000 #define MESA_META_MULTISAMPLE 0x100000 +#define MESA_META_FRAMEBUFFER_SRGB 0x200000 /**\}*/ extern void diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c index de871a92a..5d553118c 100644 --- a/mesalib/src/mesa/main/blend.c +++ b/mesalib/src/mesa/main/blend.c @@ -858,6 +858,13 @@ void _mesa_init_color( struct gl_context * ctx ) ctx->Color._ClampFragmentColor = GL_TRUE; ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB; ctx->Color._ClampReadColor = GL_TRUE; + + if (ctx->API == API_OPENGLES2) { + /* GLES 3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled. */ + ctx->Color.sRGBEnabled = GL_TRUE; + } else { + ctx->Color.sRGBEnabled = GL_FALSE; + } } /*@}*/ diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index 3643cfb52..a607bdc10 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -264,6 +264,23 @@ _mesa_set_multisample(struct gl_context *ctx, GLboolean state) } /** + * Helper function to enable or disable GL_FRAMEBUFFER_SRGB, skipping the + * check for whether the API supports it (GLES doesn't). + */ +void +_mesa_set_framebuffer_srgb(struct gl_context *ctx, GLboolean state) +{ + if (ctx->Color.sRGBEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + ctx->Color.sRGBEnabled = state; + + if (ctx->Driver.Enable) { + ctx->Driver.Enable(ctx, GL_FRAMEBUFFER_SRGB, state); + } +} + +/** * Helper function to enable or disable state. * * \param ctx GL context. @@ -1044,12 +1061,11 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) /* GL3.0 - GL_framebuffer_sRGB */ case GL_FRAMEBUFFER_SRGB_EXT: - if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) + if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; CHECK_EXTENSION(EXT_framebuffer_sRGB, cap); - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - ctx->Color.sRGBEnabled = state; - break; + _mesa_set_framebuffer_srgb(ctx, state); + return; /* GL_OES_EGL_image_external */ case GL_TEXTURE_EXTERNAL_OES: @@ -1699,7 +1715,7 @@ _mesa_IsEnabled( GLenum cap ) /* GL3.0 - GL_framebuffer_sRGB */ case GL_FRAMEBUFFER_SRGB_EXT: - if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) + if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; CHECK_EXTENSION(EXT_framebuffer_sRGB); return ctx->Color.sRGBEnabled; diff --git a/mesalib/src/mesa/main/enable.h b/mesalib/src/mesa/main/enable.h index c49b4948d..be7909459 100644 --- a/mesalib/src/mesa/main/enable.h +++ b/mesalib/src/mesa/main/enable.h @@ -70,6 +70,9 @@ _mesa_DisableClientState( GLenum cap ); extern void _mesa_set_multisample(struct gl_context *ctx, GLboolean state); +extern void +_mesa_set_framebuffer_srgb(struct gl_context *ctx, GLboolean state); + #endif diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp index f21cf80ae..3a80ab7f3 100644 --- a/mesalib/src/mesa/main/ff_fragment_shader.cpp +++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp @@ -539,7 +539,7 @@ public: }; static ir_rvalue * -get_current_attrib(struct texenv_fragment_program *p, GLuint attrib) +get_current_attrib(texenv_fragment_program *p, GLuint attrib) { ir_variable *current; ir_rvalue *val; @@ -552,7 +552,7 @@ get_current_attrib(struct texenv_fragment_program *p, GLuint attrib) } static ir_rvalue * -get_gl_Color(struct texenv_fragment_program *p) +get_gl_Color(texenv_fragment_program *p) { if (p->state->inputs_available & FRAG_BIT_COL0) { ir_variable *var = p->shader->symbols->get_variable("gl_Color"); @@ -564,7 +564,7 @@ get_gl_Color(struct texenv_fragment_program *p) } static ir_rvalue * -get_source(struct texenv_fragment_program *p, +get_source(texenv_fragment_program *p, GLuint src, GLuint unit) { ir_variable *var; @@ -615,7 +615,7 @@ get_source(struct texenv_fragment_program *p, } static ir_rvalue * -emit_combine_source(struct texenv_fragment_program *p, +emit_combine_source(texenv_fragment_program *p, GLuint unit, GLuint source, GLuint operand) @@ -690,7 +690,7 @@ static GLboolean args_match( const struct state_key *key, GLuint unit ) } static ir_rvalue * -smear(struct texenv_fragment_program *p, ir_rvalue *val) +smear(texenv_fragment_program *p, ir_rvalue *val) { if (!val->type->is_scalar()) return val; @@ -699,7 +699,7 @@ smear(struct texenv_fragment_program *p, ir_rvalue *val) } static ir_rvalue * -emit_combine(struct texenv_fragment_program *p, +emit_combine(texenv_fragment_program *p, GLuint unit, GLuint nr, GLuint mode, @@ -780,7 +780,7 @@ emit_combine(struct texenv_fragment_program *p, * Generate instructions for one texture unit's env/combiner mode. */ static ir_rvalue * -emit_texenv(struct texenv_fragment_program *p, GLuint unit) +emit_texenv(texenv_fragment_program *p, GLuint unit) { const struct state_key *key = p->state; GLboolean rgb_saturate, alpha_saturate; @@ -909,7 +909,7 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit) /** * Generate instruction for getting a texture source term. */ -static void load_texture( struct texenv_fragment_program *p, GLuint unit ) +static void load_texture( texenv_fragment_program *p, GLuint unit ) { ir_dereference *deref; @@ -1039,7 +1039,7 @@ static void load_texture( struct texenv_fragment_program *p, GLuint unit ) } static void -load_texenv_source(struct texenv_fragment_program *p, +load_texenv_source(texenv_fragment_program *p, GLuint src, GLuint unit) { switch (src) { @@ -1069,7 +1069,7 @@ load_texenv_source(struct texenv_fragment_program *p, * Generate instructions for loading all texture source terms. */ static GLboolean -load_texunit_sources( struct texenv_fragment_program *p, GLuint unit ) +load_texunit_sources( texenv_fragment_program *p, GLuint unit ) { const struct state_key *key = p->state; GLuint i; @@ -1089,7 +1089,7 @@ load_texunit_sources( struct texenv_fragment_program *p, GLuint unit ) * Generate instructions for loading bump map textures. */ static void -load_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit ) +load_texunit_bumpmap( texenv_fragment_program *p, GLuint unit ) { const struct state_key *key = p->state; GLuint bumpedUnitNr = key->unit[unit].OptRGB[1].Source - SRC_TEXTURE0; @@ -1141,7 +1141,7 @@ load_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit ) * GL_FOG_COORDINATE_EXT is set to GL_FRAGMENT_DEPTH_EXT. */ static ir_rvalue * -emit_fog_instructions(struct texenv_fragment_program *p, +emit_fog_instructions(texenv_fragment_program *p, ir_rvalue *fragcolor) { struct state_key *key = p->state; @@ -1214,7 +1214,7 @@ emit_fog_instructions(struct texenv_fragment_program *p, } static void -emit_instructions(struct texenv_fragment_program *p) +emit_instructions(texenv_fragment_program *p) { struct state_key *key = p->state; GLuint unit; diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 047a613a1..04029c07c 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -1372,3 +1372,72 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, } return GL_NO_ERROR; } + + +/** + * Do error checking of format/type combinations for OpenGL ES glReadPixels + * and glTex[Sub]Image. + * \return error code, or GL_NO_ERROR. + */ +GLenum +_mesa_es_error_check_format_and_type(GLenum format, GLenum type, + unsigned dimensions) +{ + GLboolean type_valid = GL_TRUE; + + switch (format) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + type_valid = (type == GL_UNSIGNED_BYTE + || type == GL_FLOAT + || type == GL_HALF_FLOAT_OES); + break; + + case GL_RGB: + type_valid = (type == GL_UNSIGNED_BYTE + || type == GL_UNSIGNED_SHORT_5_6_5 + || type == GL_FLOAT + || type == GL_HALF_FLOAT_OES); + break; + + case GL_RGBA: + type_valid = (type == GL_UNSIGNED_BYTE + || type == GL_UNSIGNED_SHORT_4_4_4_4 + || type == GL_UNSIGNED_SHORT_5_5_5_1 + || type == GL_FLOAT + || type == GL_HALF_FLOAT_OES + || type == GL_UNSIGNED_INT_2_10_10_10_REV); + break; + + case GL_DEPTH_COMPONENT: + /* This format is filtered against invalid dimensionalities elsewhere. + */ + type_valid = (type == GL_UNSIGNED_SHORT + || type == GL_UNSIGNED_INT); + break; + + case GL_DEPTH_STENCIL: + /* This format is filtered against invalid dimensionalities elsewhere. + */ + type_valid = (type == GL_UNSIGNED_INT_24_8); + break; + + case GL_BGRA_EXT: + type_valid = (type == GL_UNSIGNED_BYTE); + + /* This feels like a bug in the EXT_texture_format_BGRA8888 spec, but + * the format does not appear to be allowed for 3D textures in OpenGL + * ES. + */ + if (dimensions != 2) + return GL_INVALID_VALUE; + + break; + + default: + return GL_INVALID_VALUE; + } + + return type_valid ? GL_NO_ERROR : GL_INVALID_OPERATION; +} diff --git a/mesalib/src/mesa/main/glformats.h b/mesalib/src/mesa/main/glformats.h index 24fbda991..e5b63a963 100644 --- a/mesalib/src/mesa/main/glformats.h +++ b/mesalib/src/mesa/main/glformats.h @@ -98,6 +98,10 @@ extern GLenum _mesa_error_check_format_and_type(const struct gl_context *ctx, GLenum format, GLenum type); +extern GLenum +_mesa_es_error_check_format_and_type(GLenum format, GLenum type, + unsigned dimensions); + #ifdef __cplusplus } diff --git a/mesalib/src/mesa/main/glheader.h b/mesalib/src/mesa/main/glheader.h index 315232371..e93ca30e7 100644 --- a/mesalib/src/mesa/main/glheader.h +++ b/mesalib/src/mesa/main/glheader.h @@ -144,6 +144,13 @@ typedef void *GLeglImageOES; #endif +/* Inexplicably, GL_HALF_FLOAT_OES has a different value than GL_HALF_FLOAT. + */ +#ifndef GL_HALF_FLOAT_OES +#define GL_HALF_FLOAT_OES 0x8D61 +#endif + + /** * Internal token to represent a GLSL shader program (a collection of * one or more shaders that get linked together). Note that GLSL diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index 81da51047..a78d67966 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -145,6 +145,13 @@ static inline int isblank(int ch) { return ch == ' ' || ch == '\t'; } /*@}*/ +/* + * signbit() is a macro on Linux. Not available on Windows. + */ +#ifndef signbit +#define signbit(x) ((x) < 0.0f) +#endif + /** single-precision inverse square root */ static inline float diff --git a/mesalib/src/mesa/main/macros.h b/mesalib/src/mesa/main/macros.h index 04d59d79c..7b7fd1b6d 100644 --- a/mesalib/src/mesa/main/macros.h +++ b/mesalib/src/mesa/main/macros.h @@ -693,31 +693,14 @@ NORMALIZE_3FV(GLfloat v[3]) static inline GLboolean IS_NEGATIVE(float x) { -#if defined(USE_IEEE) - fi_type fi; - fi.f = x; - return fi.i < 0; -#else - return x < 0.0F; -#endif + return signbit(x) != 0; } - /** Test two floats have opposite signs */ static inline GLboolean DIFFERENT_SIGNS(GLfloat x, GLfloat y) { -#if defined(USE_IEEE) - fi_type xfi, yfi; - xfi.f = x; - yfi.f = y; - return !!((xfi.i ^ yfi.i) & (1u << 31)); -#else - /* Could just use (x*y<0) except for the flatshading requirements. - * Maybe there's a better way? - */ - return ((x) * (y) <= 0.0F && (x) - (y) != 0.0F); -#endif + return signbit(x) != signbit(y); } diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index e10f921d2..f6680c91f 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -38,13 +38,7 @@ #include "state.h" #include "glformats.h" #include "fbobject.h" -#include "teximage.h" -/* Inexplicably, GL_HALF_FLOAT_OES has a different value than GL_HALF_FLOAT. - */ -#ifndef GL_HALF_FLOAT_OES -#define GL_HALF_FLOAT_OES 0x8D61 -#endif /** * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 08af66893..afda0eaaf 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -50,12 +50,6 @@ #include "glformats.h" -/* Inexplicably, GL_HALF_FLOAT_OES has a different value than GL_HALF_FLOAT. - */ -#ifndef GL_HALF_FLOAT_OES -#define GL_HALF_FLOAT_OES 0x8D61 -#endif - /** * State changes which we care about for glCopyTex[Sub]Image() calls. * In particular, we care about pixel transfer state and buffer state @@ -1343,6 +1337,121 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target, /** + * Do error checking of xoffset, yoffset, zoffset, width, height and depth + * for glTexSubImage, glCopyTexSubImage and glCompressedTexSubImage. + * \param destImage the destination texture image. + * \return GL_TRUE if error found, GL_FALSE otherwise. + */ +static GLboolean +error_check_subtexture_dimensions(struct gl_context *ctx, + const char *function, GLuint dims, + const struct gl_texture_image *destImage, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei subWidth, GLsizei subHeight, + GLsizei subDepth) +{ + const GLenum target = destImage->TexObject->Target; + GLuint bw, bh; + + /* Check size */ + if (subWidth < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s%dD(width=%d)", function, dims, subWidth); + return GL_TRUE; + } + + if (dims > 1 && subHeight < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s%dD(height=%d)", function, dims, subHeight); + return GL_TRUE; + } + + if (dims > 2 && subDepth < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s%dD(depth=%d)", function, dims, subDepth); + return GL_TRUE; + } + + /* check xoffset and width */ + if (xoffset < -destImage->Border) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset)", + function, dims); + return GL_TRUE; + } + + if (xoffset + subWidth > destImage->Width) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset+width)", + function, dims); + return GL_TRUE; + } + + /* check yoffset and height */ + if (dims > 1) { + GLint yBorder = (target == GL_TEXTURE_1D_ARRAY) ? 0 : destImage->Border; + if (yoffset < -yBorder) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(yoffset)", + function, dims); + return GL_TRUE; + } + if (yoffset + subHeight > destImage->Height) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(yoffset+height)", + function, dims); + return GL_TRUE; + } + } + + /* check zoffset and depth */ + if (dims > 2) { + GLint zBorder = (target == GL_TEXTURE_2D_ARRAY) ? 0 : destImage->Border; + if (zoffset < -zBorder) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s3D(zoffset)", function); + return GL_TRUE; + } + if (zoffset + subDepth > (GLint) destImage->Depth) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s3D(zoffset+depth)", function); + return GL_TRUE; + } + } + + /* + * The OpenGL spec (and GL_ARB_texture_compression) says only whole + * compressed texture images can be updated. But, that restriction may be + * relaxed for particular compressed formats. At this time, all the + * compressed formats supported by Mesa allow sub-textures to be updated + * along compressed block boundaries. + */ + _mesa_get_format_block_size(destImage->TexFormat, &bw, &bh); + + if (bw != 1 || bh != 1) { + /* offset must be multiple of block size */ + if ((xoffset % bw != 0) || (yoffset % bh != 0)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s%dD(xoffset = %d, yoffset = %d)", + function, dims, xoffset, yoffset); + return GL_TRUE; + } + + /* size must be multiple of bw by bh or equal to whole texture size */ + if ((subWidth % bw != 0) && subWidth != destImage->Width) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s%dD(width = %d)", function, dims, subWidth); + return GL_TRUE; + } + + if ((subHeight % bh != 0) && subHeight != destImage->Height) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s%dD(height = %d)", function, dims, subHeight); + return GL_TRUE; + } + } + + return GL_FALSE; +} + + + + +/** * This is the fallback for Driver.TestProxyTexImage() for doing device- * specific texture image size checks. * @@ -1572,71 +1681,6 @@ mutable_tex_object(struct gl_context *ctx, GLenum target) } -GLenum -_mesa_es_error_check_format_and_type(GLenum format, GLenum type, - unsigned dimensions) -{ - bool type_valid = true; - - switch (format) { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - type_valid = (type == GL_UNSIGNED_BYTE - || type == GL_FLOAT - || type == GL_HALF_FLOAT_OES); - break; - - case GL_RGB: - type_valid = (type == GL_UNSIGNED_BYTE - || type == GL_UNSIGNED_SHORT_5_6_5 - || type == GL_FLOAT - || type == GL_HALF_FLOAT_OES); - break; - - case GL_RGBA: - type_valid = (type == GL_UNSIGNED_BYTE - || type == GL_UNSIGNED_SHORT_4_4_4_4 - || type == GL_UNSIGNED_SHORT_5_5_5_1 - || type == GL_FLOAT - || type == GL_HALF_FLOAT_OES - || type == GL_UNSIGNED_INT_2_10_10_10_REV); - break; - - case GL_DEPTH_COMPONENT: - /* This format is filtered against invalid dimensionalities elsewhere. - */ - type_valid = (type == GL_UNSIGNED_SHORT - || type == GL_UNSIGNED_INT); - break; - - case GL_DEPTH_STENCIL: - /* This format is filtered against invalid dimensionalities elsewhere. - */ - type_valid = (type == GL_UNSIGNED_INT_24_8); - break; - - case GL_BGRA_EXT: - type_valid = (type == GL_UNSIGNED_BYTE); - - /* This feels like a bug in the EXT_texture_format_BGRA8888 spec, but - * the format does not appear to be allowed for 3D textures in OpenGL - * ES. - */ - if (dimensions != 2) - return GL_INVALID_VALUE; - - break; - - default: - return GL_INVALID_VALUE; - } - - return type_valid ? GL_NO_ERROR : GL_INVALID_OPERATION; -} - - - /** * Return expected size of a compressed texture. */ @@ -1649,17 +1693,6 @@ compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, } -/* - * Return compressed texture block size, in pixels. - */ -static void -get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh) -{ - gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); - _mesa_get_format_block_size(mesaFormat, bw, bh); -} - - /** * Test the glTexImage[123]D() parameters for errors. * @@ -2081,34 +2114,27 @@ error: * to the OpenGL specification. */ static GLboolean -subtexture_error_check( struct gl_context *ctx, GLuint dimensions, +texsubimage_error_check(struct gl_context *ctx, GLuint dimensions, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint width, GLint height, GLint depth, - GLenum format, GLenum type ) + GLenum format, GLenum type) { + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; GLenum err; - /* level check */ - if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); + /* check target (proxies not allowed) */ + if (!legal_texsubimage_target(ctx, dimensions, target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)", + dimensions, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } - /* Check for negative sizes */ - if (width < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexSubImage%dD(width=%d)", dimensions, width); - return GL_TRUE; - } - if (height < 0 && dimensions > 1) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexSubImage%dD(height=%d)", dimensions, height); - return GL_TRUE; - } - if (depth < 0 && dimensions > 2) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexSubImage%dD(depth=%d)", dimensions, depth); + /* level check */ + if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(level=%d)", + dimensions, level); return GL_TRUE; } @@ -2137,98 +2163,39 @@ subtexture_error_check( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } - return GL_FALSE; -} - - -/** - * Do second part of glTexSubImage which depends on the destination texture. - * \return GL_TRUE if error recorded, GL_FALSE otherwise - */ -static GLboolean -subtexture_error_check2( struct gl_context *ctx, GLuint dimensions, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint width, GLint height, GLint depth, - GLenum format, GLenum type, - const struct gl_texture_image *destTex ) -{ - if (!destTex) { - /* undefined image level */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); + /* Get dest texture object / image pointers */ + texObj = _mesa_get_current_tex_object(ctx, target); + if (!texObj) { + /* must be out of memory */ + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage%dD()", dimensions); return GL_TRUE; } - if (xoffset < -((GLint)destTex->Border)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", - dimensions); + texImage = _mesa_select_tex_image(ctx, texObj, target, level); + if (!texImage) { + /* non-existant texture level */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage%dD(invalid texture image)", dimensions); return GL_TRUE; } - if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", - dimensions); + + if (error_check_subtexture_dimensions(ctx, "glTexSubImage", dimensions, + texImage, xoffset, yoffset, 0, + width, height, 1)) { return GL_TRUE; } - if (dimensions > 1) { - 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 + yBorder) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", - dimensions); - return GL_TRUE; - } - } - if (dimensions > 2) { - 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 + zBorder) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); - return GL_TRUE; - } - } - - if (_mesa_is_format_compressed(destTex->TexFormat)) { - GLuint bw, bh; - if (compressedteximage_only_format(ctx, destTex->InternalFormat)) { + if (_mesa_is_format_compressed(texImage->TexFormat)) { + if (compressedteximage_only_format(ctx, texImage->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); - - /* offset must be multiple of block size */ - if ((xoffset % bw != 0) || (yoffset % bh != 0)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexSubImage%dD(xoffset = %d, yoffset = %d)", - dimensions, xoffset, yoffset); - return GL_TRUE; - } - /* size must be multiple of bw by bh or equal to whole texture size */ - if ((width % bw != 0) && (GLuint) width != destTex->Width) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexSubImage%dD(width = %d)", dimensions, width); - return GL_TRUE; - } - if ((height % bh != 0) && (GLuint) height != destTex->Height) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexSubImage%dD(height = %d)", dimensions, height); - return GL_TRUE; - } } if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) { /* both source and dest must be integer-valued, or neither */ - if (_mesa_is_format_integer_color(destTex->TexFormat) != + if (_mesa_is_format_integer_color(texImage->TexFormat) != _mesa_is_enum_format_integer(format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD(integer/non-integer format mismatch)", @@ -2396,20 +2363,17 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, /** * Test glCopyTexSubImage[12]D() parameters for errors. - * Note that this is the first part of error checking. - * See also copytexsubimage_error_check2() below for the second part. - * - * \param ctx GL context. - * \param dimensions texture image dimensions (must be 1, 2 or 3). - * \param target texture target given by the user. - * \param level image level given by the user. - * * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. */ static GLboolean -copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions, - GLenum target, GLint level) +copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height) { + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + /* Check that the source buffer is complete */ if (_mesa_is_user_fbo(ctx->ReadBuffer)) { if (ctx->ReadBuffer->_Status == 0) { @@ -2443,120 +2407,45 @@ copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } - return GL_FALSE; -} - - -/** - * Second part of error checking for glCopyTexSubImage[12]D(). - * \param xoffset sub-image x offset given by the user. - * \param yoffset sub-image y offset given by the user. - * \param zoffset sub-image z offset given by the user. - * \param width image width given by the user. - * \param height image height given by the user. - */ -static GLboolean -copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, - const struct gl_texture_image *teximage ) -{ - /* check that dest tex image exists */ - if (!teximage) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexSubImage%dD(undefined texture level: %d)", - dimensions, level); + /* Get dest texture object / image pointers */ + texObj = _mesa_get_current_tex_object(ctx, target); + if (!texObj) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%dD()", dimensions); return GL_TRUE; } - /* Check size */ - if (width < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexSubImage%dD(width=%d)", dimensions, width); - return GL_TRUE; - } - if (dimensions > 1 && height < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexSubImage%dD(height=%d)", dimensions, height); + texImage = _mesa_select_tex_image(ctx, texObj, target, level); + if (!texImage) { + /* destination image does not exist */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexSubImage%dD(invalid texture image)", dimensions); return GL_TRUE; } - /* check x/y offsets */ - if (xoffset < -((GLint)teximage->Border)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); - return GL_TRUE; - } - if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexSubImage%dD(xoffset+width)", dimensions); + if (error_check_subtexture_dimensions(ctx, "glCopyTexSubImage", + dimensions, texImage, + xoffset, yoffset, zoffset, + width, height, 1)) { return GL_TRUE; } - if (dimensions > 1) { - 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 + yBorder) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexSubImage%dD(yoffset+height)", dimensions); - return GL_TRUE; - } - } - /* check z offset */ - if (dimensions > 2) { - 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 + zBorder) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexSubImage%dD(zoffset+depth)", dimensions); - return GL_TRUE; - } - } - - if (_mesa_is_format_compressed(teximage->TexFormat)) { - if (compressedteximage_only_format(ctx, teximage->InternalFormat)) { + 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, - "glCopyTexSubImage%dD(xoffset or yoffset)", dimensions); - return GL_TRUE; - } - /* size must be multiple of 4 */ - if ((width & 3) != 0 && (GLuint) width != teximage->Width) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexSubImage%dD(width)", dimensions); - return GL_TRUE; - } - if ((height & 3) != 0 && (GLuint) height != teximage->Height) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexSubImage%dD(height)", dimensions); - return GL_TRUE; - } } - if (teximage->InternalFormat == GL_YCBCR_MESA) { + if (texImage->InternalFormat == GL_YCBCR_MESA) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); return GL_TRUE; } - if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { + if (!_mesa_source_buffer_exists(ctx, texImage->_BaseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)", - dimensions, teximage->_BaseFormat); + dimensions, texImage->_BaseFormat); return GL_TRUE; } @@ -2567,11 +2456,11 @@ copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, * buffer is not an integer format, or if the internalformat is not an * integer format and the read color buffer is an integer format." */ - if (_mesa_is_color_format(teximage->InternalFormat)) { + if (_mesa_is_color_format(texImage->InternalFormat)) { struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; if (_mesa_is_format_integer_color(rb->Format) != - _mesa_is_format_integer_color(teximage->TexFormat)) { + _mesa_is_format_integer_color(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexImage%dD(integer vs non-integer)", dimensions); return GL_TRUE; @@ -3157,8 +3046,9 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, if (ctx->NewState & _NEW_PIXEL) _mesa_update_state(ctx); - if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset, - width, height, depth, format, type)) { + if (texsubimage_error_check(ctx, dims, target, level, + xoffset, yoffset, zoffset, + width, height, depth, format, type)) { return; /* error was detected */ } @@ -3168,13 +3058,7 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, { texImage = _mesa_select_tex_image(ctx, texObj, target, level); - if (subtexture_error_check2(ctx, dims, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, texImage)) { - /* error was recorded */ - } - else if (width > 0 && height > 0 && depth > 0) { + if (width > 0 && height > 0 && depth > 0) { /* If we have a border, offset=-1 is legal. Bias by border width. */ switch (dims) { case 3: @@ -3417,8 +3301,10 @@ copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, if (ctx->NewState & NEW_COPY_TEX_STATE) _mesa_update_state(ctx); - if (copytexsubimage_error_check1(ctx, dims, target, level)) + if (copytexsubimage_error_check(ctx, dims, target, level, + xoffset, yoffset, zoffset, width, height)) { return; + } texObj = _mesa_get_current_tex_object(ctx, target); @@ -3426,38 +3312,32 @@ copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, { texImage = _mesa_select_tex_image(ctx, texObj, target, level); - if (copytexsubimage_error_check2(ctx, dims, target, level, xoffset, yoffset, - zoffset, width, height, texImage)) { - /* error was recored */ + /* If we have a border, offset=-1 is legal. Bias by border width. */ + switch (dims) { + case 3: + if (target != GL_TEXTURE_2D_ARRAY) + zoffset += texImage->Border; + /* fall-through */ + case 2: + if (target != GL_TEXTURE_1D_ARRAY) + yoffset += texImage->Border; + /* fall-through */ + case 1: + xoffset += texImage->Border; } - else { - /* If we have a border, offset=-1 is legal. Bias by border width. */ - switch (dims) { - case 3: - if (target != GL_TEXTURE_2D_ARRAY) - zoffset += texImage->Border; - /* fall-through */ - case 2: - if (target != GL_TEXTURE_1D_ARRAY) - yoffset += texImage->Border; - /* fall-through */ - case 1: - xoffset += texImage->Border; - } - if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, - &width, &height)) { - struct gl_renderbuffer *srcRb = - get_copy_tex_image_source(ctx, texImage->TexFormat); + if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, + &width, &height)) { + struct gl_renderbuffer *srcRb = + get_copy_tex_image_source(ctx, texImage->TexFormat); - ctx->Driver.CopyTexSubImage(ctx, dims, texImage, - xoffset, yoffset, zoffset, - srcRb, x, y, width, height); + ctx->Driver.CopyTexSubImage(ctx, dims, texImage, + xoffset, yoffset, zoffset, + srcRb, x, y, width, height); - check_gen_mipmap(ctx, target, texObj, level); + check_gen_mipmap(ctx, target, texObj, level); - ctx->NewState |= _NEW_TEXTURE; - } + ctx->NewState |= _NEW_TEXTURE; } } _mesa_unlock_texture(ctx, texObj); @@ -3506,100 +3386,80 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, /** * Error checking for glCompressedTexSubImage[123]D(). - * \warning There are some bad assumptions here about the size of compressed - * texture tiles (multiple of 4) used to test the validity of the - * offset and size parameters. * \return error code or GL_NO_ERROR. */ static GLenum -compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions, +compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize) { - GLint expectedSize, maxLevels = 0, maxTextureSize; - GLuint bw, bh; - (void) zoffset; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLint expectedSize; + GLboolean targetOK; - if (dimensions == 1) { - /* 1D compressed textures not allowed */ - return GL_INVALID_ENUM; - } - else if (dimensions == 2) { - if (target == GL_PROXY_TEXTURE_2D) { - maxLevels = ctx->Const.MaxTextureLevels; - } - else if (target == GL_TEXTURE_2D) { - maxLevels = ctx->Const.MaxTextureLevels; - } - else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { - if (!ctx->Extensions.ARB_texture_cube_map) - return GL_INVALID_ENUM; /*target*/ - maxLevels = ctx->Const.MaxCubeTextureLevels; - } - else if (_mesa_is_cube_face(target)) { - if (!ctx->Extensions.ARB_texture_cube_map) - return GL_INVALID_ENUM; /*target*/ - maxLevels = ctx->Const.MaxCubeTextureLevels; - } - else { - return GL_INVALID_ENUM; /*target*/ - } - } - else if (dimensions == 3) { - /* 3D compressed textures not allowed */ - return GL_INVALID_ENUM; + if (dims == 2) { + switch (target) { + case GL_TEXTURE_2D: + 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: + targetOK = GL_TRUE; + break; + default: + targetOK = GL_FALSE; + } + } + else { + assert(dims == 1 || dims == 3); + /* no 1D or 3D compressed textures at this time */ + targetOK = GL_FALSE; + } + + if (!targetOK) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target)", + dims); + return GL_TRUE; } - maxTextureSize = 1 << (maxLevels - 1); - /* this will catch any invalid compressed format token */ - if (!_mesa_is_compressed_format(ctx, format)) - return GL_INVALID_ENUM; - - if (width < 1 || width > maxTextureSize) - return GL_INVALID_VALUE; - - if ((height < 1 || height > maxTextureSize) - && dimensions > 1) - return GL_INVALID_VALUE; - - if (level < 0 || level >= maxLevels) - return GL_INVALID_VALUE; - - /* - * do checks which depend on compression block size - */ - get_compressed_block_size(format, &bw, &bh); - - if ((xoffset % bw != 0) || (yoffset % bh != 0)) - return GL_INVALID_VALUE; - - if ((width % bw != 0) && width != 2 && width != 1) - return GL_INVALID_VALUE; + if (!_mesa_is_compressed_format(ctx, format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(format)", + dims); + return GL_TRUE; + } - if ((height % bh != 0) && height != 2 && height != 1) - return GL_INVALID_VALUE; + if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage%uD(level=%d)", + dims, level); + return GL_TRUE; + } expectedSize = compressed_tex_size(width, height, depth, format); - if (expectedSize != imageSize) - return GL_INVALID_VALUE; - - return GL_NO_ERROR; -} + if (expectedSize != imageSize) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage%uD(size=%d)", + dims, imageSize); + return GL_TRUE; + } + texObj = _mesa_get_current_tex_object(ctx, target); + if (!texObj) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, + "glCompressedTexSubImage%uD()", dims); + return GL_TRUE; + } -/** - * Do second part of glCompressedTexSubImage error checking. - * \return GL_TRUE if error found, GL_FALSE otherwise. - */ -static GLboolean -compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims, - GLsizei width, GLsizei height, - GLsizei depth, GLenum format, - struct gl_texture_image *texImage) -{ + texImage = _mesa_select_tex_image(ctx, texObj, target, level); + if (!texImage) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTexSubImage%uD(invalid texture image)", dims); + return GL_TRUE; + } if ((GLint) format != texImage->InternalFormat) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -3614,34 +3474,12 @@ compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims, return GL_TRUE; } - if (((width == 1 || width == 2) && - width != (GLsizei) texImage->Width) || - (width > (GLsizei) texImage->Width)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCompressedTexSubImage%uD(width=%d)", dims, width); + if (error_check_subtexture_dimensions(ctx, "glCompressedTexSubImage", dims, + texImage, xoffset, yoffset, zoffset, + width, height, depth)) { return GL_TRUE; } - if (dims >= 2) { - if (((height == 1 || height == 2) && - height != (GLsizei) texImage->Height) || - (height > (GLsizei) texImage->Height)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCompressedTexSubImage%uD(height=%d)", dims, height); - return GL_TRUE; - } - } - - if (dims >= 3) { - if (((depth == 1 || depth == 2) && - depth != (GLsizei) texImage->Depth) || - (depth > (GLsizei) texImage->Depth)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCompressedTexSubImage%uD(depth=%d)", dims, depth); - return GL_TRUE; - } - } - return GL_FALSE; } @@ -3693,16 +3531,13 @@ compressed_tex_sub_image(GLuint dims, GLenum target, GLint level, { struct gl_texture_object *texObj; struct gl_texture_image *texImage; - GLenum error; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - error = compressed_subtexture_error_check(ctx, dims, target, level, - xoffset, 0, 0, /* pos */ - width, height, depth, /* size */ - format, imageSize); - if (error) { - _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims); + if (compressed_subtexture_error_check(ctx, dims, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, imageSize)) { return; } @@ -3713,11 +3548,7 @@ compressed_tex_sub_image(GLuint dims, GLenum target, GLint level, texImage = _mesa_select_tex_image(ctx, texObj, target, level); assert(texImage); - if (compressed_subtexture_error_check2(ctx, dims, width, height, depth, - format, texImage)) { - /* error was recorded */ - } - else if (width > 0 && height > 0 && depth > 0) { + if (width > 0 && height > 0 && depth > 0) { ctx->Driver.CompressedTexSubImage(ctx, dims, texImage, xoffset, yoffset, zoffset, width, height, depth, diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index c7c32d8ac..e1b15d252 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -138,9 +138,6 @@ _mesa_tex_target_to_face(GLenum target); extern GLint _mesa_get_texture_dimensions(GLenum target); -extern GLenum -_mesa_es_error_check_format_and_type(GLenum format, GLenum type, - unsigned dimensions); extern GLboolean _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target, diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 4f4fe77da..5634a3e6e 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -1379,6 +1379,11 @@ st_TestProxyTexImage(struct gl_context *ctx, GLenum target, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; + if (width == 0 || height == 0 || depth == 0) { + /* zero-sized images are legal, and always fit! */ + return GL_TRUE; + } + if (pipe->screen->can_create_resource) { /* Ask the gallium driver if the texture is too large */ struct gl_texture_object *texObj = |