diff options
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r-- | mesalib/src/mesa/main/api_validate.c | 94 | ||||
-rw-r--r-- | mesalib/src/mesa/main/arrayobj.c | 8 | ||||
-rw-r--r-- | mesalib/src/mesa/main/buffers.c | 4 | ||||
-rw-r--r-- | mesalib/src/mesa/main/fbobject.c | 44 | ||||
-rw-r--r-- | mesalib/src/mesa/main/get.c | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/main/mtypes.h | 27 | ||||
-rw-r--r-- | mesalib/src/mesa/main/pbo.c | 15 | ||||
-rw-r--r-- | mesalib/src/mesa/main/pbo.h | 3 | ||||
-rw-r--r-- | mesalib/src/mesa/main/samplerobj.c | 20 | ||||
-rw-r--r-- | mesalib/src/mesa/main/samplerobj.h | 7 | ||||
-rw-r--r-- | mesalib/src/mesa/main/shaderapi.c | 8 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texcompress.c | 4 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texcompress_rgtc.c | 5 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texcompress_s3tc.c | 82 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texgetimage.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/teximage.c | 16 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texstore.c | 58 | ||||
-rw-r--r-- | mesalib/src/mesa/main/transformfeedback.c | 135 | ||||
-rw-r--r-- | mesalib/src/mesa/main/transformfeedback.h | 14 | ||||
-rw-r--r-- | mesalib/src/mesa/main/uniform_query.cpp | 26 |
20 files changed, 438 insertions, 137 deletions
diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c index e47db23e0..133fb6370 100644 --- a/mesalib/src/mesa/main/api_validate.c +++ b/mesalib/src/mesa/main/api_validate.c @@ -32,6 +32,7 @@ #include "mtypes.h" #include "enums.h" #include "vbo/vbo.h" +#include "transformfeedback.h" #include <stdbool.h> @@ -252,8 +253,7 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) * current transform feedback state as given by table X.1. * */ - if (ctx->TransformFeedback.CurrentObject->Active && - !ctx->TransformFeedback.CurrentObject->Paused) { + if (_mesa_is_xfb_active_and_unpaused(ctx)) { GLboolean pass = GL_TRUE; switch (mode) { @@ -316,6 +316,19 @@ _mesa_validate_DrawElements(struct gl_context *ctx, ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is also generated by DrawElements, + * DrawElementsInstanced, and DrawRangeElements while transform feedback + * is active and not paused, regardless of mode. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawElements(transform feedback active)"); + return GL_FALSE; + } + if (count <= 0) { if (count < 0) _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" ); @@ -434,6 +447,19 @@ _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode, ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is also generated by DrawElements, + * DrawElementsInstanced, and DrawRangeElements while transform feedback + * is active and not paused, regardless of mode. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawElements(transform feedback active)"); + return GL_FALSE; + } + if (count <= 0) { if (count < 0) _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" ); @@ -486,6 +512,8 @@ GLboolean _mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLint start, GLsizei count) { + struct gl_transform_feedback_object *xfb_obj + = ctx->TransformFeedback.CurrentObject; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); @@ -507,6 +535,29 @@ _mesa_validate_DrawArrays(struct gl_context *ctx, return GL_FALSE; } + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is generated by DrawArrays and + * DrawArraysInstanced if recording the vertices of a primitive to the + * buffer objects being used for transform feedback purposes would result + * in either exceeding the limits of any buffer object’s size, or in + * exceeding the end position offset + size − 1, as set by + * BindBufferRange. + * + * This is in contrast to the behaviour of desktop GL, where the extra + * primitives are silently dropped from the transform feedback buffer. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + size_t prim_count = vbo_count_tessellated_primitives(mode, count, 1); + if (xfb_obj->GlesRemainingPrims < prim_count) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawArrays(exceeds transform feedback size)"); + return GL_FALSE; + } + xfb_obj->GlesRemainingPrims -= prim_count; + } + return GL_TRUE; } @@ -515,6 +566,8 @@ GLboolean _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first, GLsizei count, GLsizei numInstances) { + struct gl_transform_feedback_object *xfb_obj + = ctx->TransformFeedback.CurrentObject; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); @@ -550,6 +603,30 @@ _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint fi return GL_FALSE; } + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is generated by DrawArrays and + * DrawArraysInstanced if recording the vertices of a primitive to the + * buffer objects being used for transform feedback purposes would result + * in either exceeding the limits of any buffer object’s size, or in + * exceeding the end position offset + size − 1, as set by + * BindBufferRange. + * + * This is in contrast to the behaviour of desktop GL, where the extra + * primitives are silently dropped from the transform feedback buffer. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + size_t prim_count + = vbo_count_tessellated_primitives(mode, count, numInstances); + if (xfb_obj->GlesRemainingPrims < prim_count) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawArraysInstanced(exceeds transform feedback size)"); + return GL_FALSE; + } + xfb_obj->GlesRemainingPrims -= prim_count; + } + return GL_TRUE; } @@ -563,6 +640,19 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx, ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is also generated by DrawElements, + * DrawElementsInstanced, and DrawRangeElements while transform feedback + * is active and not paused, regardless of mode. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawElements(transform feedback active)"); + return GL_FALSE; + } + if (count <= 0) { if (count < 0) _mesa_error(ctx, GL_INVALID_VALUE, diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index a909e0eff..032af43b5 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -373,7 +373,7 @@ bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired) save_array_object(ctx, newObj); } - if (!newObj->_Used) { + if (!newObj->EverBound) { /* The "Interactions with APPLE_vertex_array_object" section of the * GL_ARB_vertex_array_object spec says: * @@ -381,7 +381,7 @@ bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired) * BindVertexArrayAPPLE, determines the semantic of the object." */ newObj->ARBsemantics = genRequired; - newObj->_Used = GL_TRUE; + newObj->EverBound = GL_TRUE; } } @@ -551,6 +551,8 @@ _mesa_IsVertexArray( GLuint id ) return GL_FALSE; obj = lookup_arrayobj(ctx, id); + if (obj == NULL) + return GL_FALSE; - return (obj != NULL) ? GL_TRUE : GL_FALSE; + return obj->EverBound; } diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c index 76f0d4671..d10a57394 100644 --- a/mesalib/src/mesa/main/buffers.c +++ b/mesalib/src/mesa/main/buffers.c @@ -532,8 +532,8 @@ _mesa_ReadBuffer(GLenum buffer) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - if (_mesa_is_user_fbo(fb) && buffer == GL_NONE) { - /* This is legal for user-created framebuffer objects */ + if (buffer == GL_NONE) { + /* This is legal--it means that no buffer should be bound for reading. */ srcBuffer = -1; } else { diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index ce77b9f77..281cdd05c 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -1169,35 +1169,23 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg ? GL_RG : 0; /* signed normalized texture formats */ - case GL_R8_SNORM: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm) - ? GL_RED : 0; case GL_RED_SNORM: + case GL_R8_SNORM: case GL_R16_SNORM: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm ? GL_RED : 0; - case GL_RG8_SNORM: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm) - ? GL_RG : 0; case GL_RG_SNORM: + case GL_RG8_SNORM: case GL_RG16_SNORM: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm ? GL_RG : 0; - case GL_RGB8_SNORM: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm) - ? GL_RGB : 0; case GL_RGB_SNORM: + case GL_RGB8_SNORM: case GL_RGB16_SNORM: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm ? GL_RGB : 0; - case GL_RGBA8_SNORM: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm) - ? GL_RGBA : 0; case GL_RGBA_SNORM: + case GL_RGBA8_SNORM: case GL_RGBA16_SNORM: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm ? GL_RGBA : 0; @@ -1207,24 +1195,6 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm && ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; - case GL_LUMINANCE_SNORM: - case GL_LUMINANCE8_SNORM: - case GL_LUMINANCE16_SNORM: - return ctx->API == API_OPENGL_COMPAT && - ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; - case GL_LUMINANCE_ALPHA_SNORM: - case GL_LUMINANCE8_ALPHA8_SNORM: - case GL_LUMINANCE16_ALPHA16_SNORM: - return ctx->API == API_OPENGL_COMPAT && - ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; - case GL_INTENSITY_SNORM: - case GL_INTENSITY8_SNORM: - case GL_INTENSITY16_SNORM: - return ctx->API == API_OPENGL_COMPAT && - ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; case GL_R16F: case GL_R32F: return ctx->Version >= 30 @@ -1291,10 +1261,8 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_RGB8I_EXT: case GL_RGB16I_EXT: case GL_RGB32I_EXT: - return ctx->Version >= 30 - || (_mesa_is_desktop_gl(ctx) && - ctx->Extensions.EXT_texture_integer) ? GL_RGB : 0; - + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer + ? GL_RGB : 0; case GL_R8UI: case GL_R8I: case GL_R16UI: diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index f3dbda2d3..273a79f7f 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -1574,7 +1574,8 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) goto invalid_value; if (!ctx->Extensions.EXT_transform_feedback) goto invalid_enum; - v->value_int64 = ctx->TransformFeedback.CurrentObject->Size[index]; + v->value_int64 + = ctx->TransformFeedback.CurrentObject->RequestedSize[index]; return TYPE_INT64; case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 67eaadd9f..7c513a1c5 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1595,7 +1595,7 @@ struct gl_array_object /** * Has this array object been bound? */ - GLboolean _Used; + GLboolean EverBound; /** Vertex attribute arrays */ struct gl_client_array VertexAttrib[VERT_ATTRIB_MAX]; @@ -1807,6 +1807,18 @@ struct gl_transform_feedback_object GLboolean Paused; /**< Is transform feedback paused? */ GLboolean EndedAnytime; /**< Has EndTransformFeedback been called at least once? */ + GLboolean EverBound; /**< Has this object been bound? */ + + /** + * GLES: if Active is true, remaining number of primitives which can be + * rendered without overflow. This is necessary to track because GLES + * requires us to generate INVALID_OPERATION if a call to glDrawArrays or + * glDrawArraysInstanced would overflow transform feedback buffers. + * Undefined if Active is false. + * + * Not tracked for desktop GL since it's unnecessary. + */ + unsigned GlesRemainingPrims; /** The feedback buffers */ GLuint BufferNames[MAX_FEEDBACK_BUFFERS]; @@ -1814,8 +1826,19 @@ struct gl_transform_feedback_object /** Start of feedback data in dest buffer */ GLintptr Offset[MAX_FEEDBACK_BUFFERS]; - /** Max data to put into dest buffer (in bytes) */ + + /** + * Max data to put into dest buffer (in bytes). Computed based on + * RequestedSize and the actual size of the buffer. + */ GLsizeiptr Size[MAX_FEEDBACK_BUFFERS]; + + /** + * Size that was specified when the buffer was bound. If the buffer was + * bound with glBindBufferBase() or glBindBufferOffsetEXT(), this value is + * zero. + */ + GLsizeiptr RequestedSize[MAX_FEEDBACK_BUFFERS]; }; diff --git a/mesalib/src/mesa/main/pbo.c b/mesalib/src/mesa/main/pbo.c index c73d7492f..0dc4c04eb 100644 --- a/mesalib/src/mesa/main/pbo.c +++ b/mesalib/src/mesa/main/pbo.c @@ -342,7 +342,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, } if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, format, type, INT_MAX, pixels)) { - _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", + funcName, dimensions); return NULL; } @@ -351,7 +352,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, GL_MAP_READ_BIT, unpack->BufferObj); if (!buf) { - _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, + dimensions); return NULL; } @@ -368,7 +370,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, */ const GLvoid * _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, - GLsizei imageSize, const GLvoid *pixels, + GLuint dimensions, GLsizei imageSize, + const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, const char *funcName) { @@ -381,7 +384,8 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, if ((const GLubyte *) pixels + imageSize > ((const GLubyte *) 0) + packing->BufferObj->Size) { /* out of bounds read! */ - _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", + funcName, dimensions); return NULL; } @@ -390,7 +394,8 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, GL_MAP_READ_BIT, packing->BufferObj); if (!buf) { - _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, + dimensions); return NULL; } diff --git a/mesalib/src/mesa/main/pbo.h b/mesalib/src/mesa/main/pbo.h index 00a6e617f..9eba33514 100644 --- a/mesalib/src/mesa/main/pbo.h +++ b/mesalib/src/mesa/main/pbo.h @@ -81,7 +81,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, extern const GLvoid * _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, - GLsizei imageSize, const GLvoid *pixels, + GLuint dimensions, GLsizei imageSize, + const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, const char *funcName); diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index 3c3bfffd4..773bebf26 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -110,7 +110,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, /** * Initialize the fields of the given sampler object. */ -void +static void _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name) { sampObj->Name = name; @@ -151,7 +151,7 @@ _mesa_new_sampler_object(struct gl_context *ctx, GLuint name) /** * Fallback for ctx->Driver.DeleteSamplerObject(); */ -void +static void _mesa_delete_sampler_object(struct gl_context *ctx, struct gl_sampler_object *sampObj) { @@ -606,6 +606,8 @@ _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) GLuint res; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(sampler %u)", @@ -777,6 +779,8 @@ _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params) GLuint res; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(sampler %u)", @@ -956,6 +960,8 @@ _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params) GLuint res; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(sampler %u)", @@ -1042,6 +1048,8 @@ _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params) GLuint res; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(sampler %u)", @@ -1127,6 +1135,8 @@ _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameteriv(sampler %u)", @@ -1205,6 +1215,8 @@ _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameterfv(sampler %u)", @@ -1283,6 +1295,8 @@ _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -1362,6 +1376,8 @@ _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, diff --git a/mesalib/src/mesa/main/samplerobj.h b/mesalib/src/mesa/main/samplerobj.h index ecff032c9..dce7c6c30 100644 --- a/mesalib/src/mesa/main/samplerobj.h +++ b/mesalib/src/mesa/main/samplerobj.h @@ -63,17 +63,10 @@ _mesa_reference_sampler_object(struct gl_context *ctx, } -extern void -_mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name); - extern struct gl_sampler_object * _mesa_new_sampler_object(struct gl_context *ctx, GLuint name); extern void -_mesa_delete_sampler_object(struct gl_context *ctx, - struct gl_sampler_object *sampObj); - -extern void _mesa_init_sampler_object_functions(struct dd_function_table *driver); extern void diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 53e9d0486..1f0002f6f 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -45,6 +45,7 @@ #include "main/mtypes.h" #include "main/shaderapi.h" #include "main/shaderobj.h" +#include "main/transformfeedback.h" #include "main/uniforms.h" #include "program/program.h" #include "program/prog_parameter.h" @@ -1383,12 +1384,10 @@ _mesa_UseProgram(GLhandleARB program) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; - struct gl_transform_feedback_object *obj = - ctx->TransformFeedback.CurrentObject; ASSERT_OUTSIDE_BEGIN_END(ctx); - if (obj->Active && !obj->Paused) { + if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram(transform feedback active)"); return; @@ -1590,8 +1589,7 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program) return; } - if (ctx->TransformFeedback.CurrentObject->Active && - !ctx->TransformFeedback.CurrentObject->Paused) { + if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseShaderProgramEXT(transform feedback is active)"); return; diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c index 33c580a88..077a967da 100644 --- a/mesalib/src/mesa/main/texcompress.c +++ b/mesalib/src/mesa/main/texcompress.c @@ -533,6 +533,10 @@ _mesa_get_compressed_fetch_func(gl_format format) case MESA_FORMAT_RGBA_DXT1: case MESA_FORMAT_RGBA_DXT3: case MESA_FORMAT_RGBA_DXT5: + case MESA_FORMAT_SRGB_DXT1: + case MESA_FORMAT_SRGBA_DXT1: + case MESA_FORMAT_SRGBA_DXT3: + case MESA_FORMAT_SRGBA_DXT5: return _mesa_get_dxt_fetch_func(format); case MESA_FORMAT_RGB_FXT1: case MESA_FORMAT_RGBA_FXT1: diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c index fa9172aa2..1f8de25ec 100644 --- a/mesalib/src/mesa/main/texcompress_rgtc.c +++ b/mesalib/src/mesa/main/texcompress_rgtc.c @@ -364,9 +364,10 @@ fetch_signed_l_latc1(const GLubyte *map, const GLuint imageOffsets[], GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) { - GLubyte red; + GLbyte red; GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; - unsigned_fetch_texel_rgtc(rowStride, map + sliceOffset, i, j, &red, 1); + signed_fetch_texel_rgtc(rowStride, (GLbyte *) map + sliceOffset, + i, j, &red, 1); texel[RCOMP] = texel[GCOMP] = texel[BCOMP] = BYTE_TO_FLOAT(red); diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c index 23a5a0868..4a81ad803 100644 --- a/mesalib/src/mesa/main/texcompress_s3tc.c +++ b/mesalib/src/mesa/main/texcompress_s3tc.c @@ -417,6 +417,80 @@ fetch_rgba_dxt5(const GLubyte *map, const GLuint imageOffsets[], } +static void +fetch_srgb_dxt1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + if (fetch_ext_rgb_dxt1) { + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + GLubyte tex[4]; + fetch_ext_rgb_dxt1(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("srgb_dxt1"); + } +} + +static void +fetch_srgba_dxt1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + if (fetch_ext_rgba_dxt1) { + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + GLubyte tex[4]; + fetch_ext_rgba_dxt1(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("srgba_dxt1"); + } +} + +static void +fetch_srgba_dxt3(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + if (fetch_ext_rgba_dxt3) { + GLuint sliceOffset = k ? imageOffsets[k] : 0; + GLubyte tex[4]; + fetch_ext_rgba_dxt3(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("srgba_dxt3"); + } +} + +static void +fetch_srgba_dxt5(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + if (fetch_ext_rgba_dxt5) { + GLuint sliceOffset = k ? imageOffsets[k] : 0; + GLubyte tex[4]; + fetch_ext_rgba_dxt5(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("srgba_dxt5"); + } +} + + + compressed_fetch_func _mesa_get_dxt_fetch_func(gl_format format) { @@ -429,6 +503,14 @@ _mesa_get_dxt_fetch_func(gl_format format) return fetch_rgba_dxt3; case MESA_FORMAT_RGBA_DXT5: return fetch_rgba_dxt5; + case MESA_FORMAT_SRGB_DXT1: + return fetch_srgb_dxt1; + case MESA_FORMAT_SRGBA_DXT1: + return fetch_srgba_dxt1; + case MESA_FORMAT_SRGBA_DXT3: + return fetch_srgba_dxt3; + case MESA_FORMAT_SRGBA_DXT5: + return fetch_srgba_dxt5; default: return NULL; } diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 69067df9f..d435c8269 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -683,6 +683,8 @@ legal_getteximage_target(struct gl_context *ctx, GLenum target) case GL_TEXTURE_2D_ARRAY_EXT: return (ctx->Extensions.MESA_texture_array || ctx->Extensions.EXT_texture_array); + case GL_TEXTURE_CUBE_MAP_ARRAY: + return ctx->Extensions.ARB_texture_cube_map_array; default: return GL_FALSE; } diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 7a0d944fd..33f81a25c 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -3507,7 +3507,8 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, GLint expectedSize; GLboolean targetOK; - if (dims == 2) { + switch (dims) { + case 2: switch (target) { case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -3520,12 +3521,17 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, break; default: targetOK = GL_FALSE; + break; } - } - else { - assert(dims == 1 || dims == 3); - /* no 1D or 3D compressed textures at this time */ + break; + case 3: + targetOK = (target == GL_TEXTURE_2D_ARRAY); + break; + default: + assert(dims == 1); + /* no 1D compressed textures at this time */ targetOK = GL_FALSE; + break; } if (!targetOK) { diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 26c5b6703..751150937 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -4441,9 +4441,9 @@ _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *texImage, GLsizei imageSize, const GLvoid *data) { - /* only 2D compressed images are supported at this time */ - if (dims != 2) { - _mesa_problem(ctx, "Unexpected glCompressedTexImage1D/3D call"); + /* only 2D and 3D compressed images are supported at this time */ + if (dims == 1) { + _mesa_problem(ctx, "Unexpected glCompressedTexImage1D call"); return; } @@ -4454,11 +4454,11 @@ _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims, ASSERT(texImage); ASSERT(texImage->Width > 0); ASSERT(texImage->Height > 0); - ASSERT(texImage->Depth == 1); + ASSERT(texImage->Depth > 0); /* allocate storage for texture data */ if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage%uD", dims); return; } @@ -4487,45 +4487,49 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, const GLubyte *src; const gl_format texFormat = texImage->TexFormat; GLuint bw, bh; + GLuint slice; - if (dims != 2) { - _mesa_problem(ctx, "Unexpected 1D/3D compressed texsubimage call"); + if (dims == 1) { + _mesa_problem(ctx, "Unexpected 1D compressed texsubimage call"); return; } _mesa_get_format_block_size(texFormat, &bw, &bh); /* get pointer to src pixels (may be in a pbo which we'll map here) */ - data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, + data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data, &ctx->Unpack, - "glCompressedTexSubImage2D"); + "glCompressedTexSubImage"); if (!data) return; srcRowStride = _mesa_format_row_stride(texFormat, width); src = (const GLubyte *) data; - /* Map dest texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, 0, - xoffset, yoffset, width, height, - GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, - &dstMap, &dstRowStride); + for (slice = 0; slice < depth; slice++) { + /* Map dest texture buffer */ + ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset, + xoffset, yoffset, width, height, + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, + &dstMap, &dstRowStride); - if (dstMap) { - bytesPerRow = srcRowStride; /* bytes per row of blocks */ - rows = (height + bh - 1) / bh; /* rows in blocks */ + if (dstMap) { + bytesPerRow = srcRowStride; /* bytes per row of blocks */ + rows = (height + bh - 1) / bh; /* rows in blocks */ - /* copy rows of blocks */ - for (i = 0; i < rows; i++) { - memcpy(dstMap, src, bytesPerRow); - dstMap += dstRowStride; - src += srcRowStride; - } + /* copy rows of blocks */ + for (i = 0; i < rows; i++) { + memcpy(dstMap, src, bytesPerRow); + dstMap += dstRowStride; + src += srcRowStride; + } - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); - } - else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D"); + ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset); + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage%uD", + dims); + } } _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index 22060c34c..1bf4beaeb 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -34,6 +34,7 @@ #include "bufferobj.h" #include "context.h" #include "hash.h" +#include "macros.h" #include "mfeatures.h" #include "mtypes.h" #include "transformfeedback.h" @@ -79,6 +80,7 @@ reference_transform_feedback_object(struct gl_transform_feedback_object **ptr, } else { obj->RefCount++; + obj->EverBound = GL_TRUE; *ptr = obj; } } @@ -177,6 +179,7 @@ new_transform_feedback(struct gl_context *ctx, GLuint name) if (obj) { obj->Name = name; obj->RefCount = 1; + obj->EverBound = GL_FALSE; } return obj; } @@ -246,6 +249,83 @@ _mesa_init_transform_feedback_functions(struct dd_function_table *driver) /** + * Fill in the correct Size value for each buffer in \c obj. + * + * From the GL 4.3 spec, section 6.1.1 ("Binding Buffer Objects to Indexed + * Targets"): + * + * BindBufferBase binds the entire buffer, even when the size of the buffer + * is changed after the binding is established. It is equivalent to calling + * BindBufferRange with offset zero, while size is determined by the size of + * the bound buffer at the time the binding is used. + * + * Regardless of the size specified with BindBufferRange, or indirectly with + * BindBufferBase, the GL will never read or write beyond the end of a bound + * buffer. In some cases this constraint may result in visibly different + * behavior when a buffer overflow would otherwise result, such as described + * for transform feedback operations in section 13.2.2. + */ +static void +compute_transform_feedback_buffer_sizes( + struct gl_transform_feedback_object *obj) +{ + unsigned i = 0; + for (i = 0; i < MAX_FEEDBACK_BUFFERS; ++i) { + GLintptr offset = obj->Offset[i]; + GLsizeiptr buffer_size + = obj->Buffers[i] == NULL ? 0 : obj->Buffers[i]->Size; + GLsizeiptr available_space + = buffer_size <= offset ? 0 : buffer_size - offset; + GLsizeiptr computed_size; + if (obj->RequestedSize[i] == 0) { + /* No size was specified at the time the buffer was bound, so allow + * writing to all available space in the buffer. + */ + computed_size = available_space; + } else { + /* A size was specified at the time the buffer was bound, however + * it's possible that the buffer has shrunk since then. So only + * allow writing to the minimum of the specified size and the space + * available. + */ + computed_size = MIN2(available_space, obj->RequestedSize[i]); + } + + /* Legal sizes must be multiples of four, so round down if necessary. */ + obj->Size[i] = computed_size & ~0x3; + } +} + + +/** + * Compute the maximum number of vertices that can be written to the currently + * enabled transform feedback buffers without overflowing any of them. + */ +unsigned +_mesa_compute_max_transform_feedback_vertices( + const struct gl_transform_feedback_object *obj, + const struct gl_transform_feedback_info *info) +{ + unsigned max_index = 0xffffffff; + unsigned i; + + for (i = 0; i < info->NumBuffers; ++i) { + unsigned stride = info->BufferStride[i]; + unsigned max_for_this_buffer; + + /* Skip any inactive buffers, which have a stride of 0. */ + if (stride == 0) + continue; + + max_for_this_buffer = obj->Size[i] / (4 * stride); + max_index = MIN2(max_index, max_for_this_buffer); + } + + return max_index; +} + + +/** ** Begin API functions **/ @@ -256,6 +336,7 @@ _mesa_BeginTransformFeedback(GLenum mode) struct gl_transform_feedback_object *obj; struct gl_transform_feedback_info *info; GLuint i; + unsigned vertices_per_prim; GET_CURRENT_CONTEXT(ctx); obj = ctx->TransformFeedback.CurrentObject; @@ -276,9 +357,13 @@ _mesa_BeginTransformFeedback(GLenum mode) switch (mode) { case GL_POINTS: + vertices_per_prim = 1; + break; case GL_LINES: + vertices_per_prim = 2; + break; case GL_TRIANGLES: - /* legal */ + vertices_per_prim = 3; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)"); @@ -304,6 +389,20 @@ _mesa_BeginTransformFeedback(GLenum mode) obj->Active = GL_TRUE; ctx->TransformFeedback.Mode = mode; + compute_transform_feedback_buffer_sizes(obj); + + if (_mesa_is_gles3(ctx)) { + /* In GLES3, we are required to track the usage of the transform + * feedback buffer and report INVALID_OPERATION if a draw call tries to + * exceed it. So compute the maximum number of vertices that we can + * write without overflowing any of the buffers currently being used for + * feedback. + */ + unsigned max_vertices + = _mesa_compute_max_transform_feedback_vertices(obj, info); + obj->GlesRemainingPrims = max_vertices / vertices_per_prim; + } + assert(ctx->Driver.BeginTransformFeedback); ctx->Driver.BeginTransformFeedback(ctx, mode, obj); } @@ -362,7 +461,7 @@ bind_buffer_range(struct gl_context *ctx, GLuint index, obj->BufferNames[index] = bufObj->Name; obj->Offset[index] = offset; - obj->Size[index] = size; + obj->RequestedSize[index] = size; } @@ -421,7 +520,6 @@ _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx, struct gl_buffer_object *bufObj) { struct gl_transform_feedback_object *obj; - GLsizeiptr size; obj = ctx->TransformFeedback.CurrentObject; @@ -436,12 +534,7 @@ _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx, return; } - /* default size is the buffer size rounded down to nearest - * multiple of four. - */ - size = bufObj->Size & ~0x3; - - bind_buffer_range(ctx, index, bufObj, 0, size); + bind_buffer_range(ctx, index, bufObj, 0, 0); } @@ -457,7 +550,6 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, struct gl_transform_feedback_object *obj; struct gl_buffer_object *bufObj; GET_CURRENT_CONTEXT(ctx); - GLsizeiptr size; if (target != GL_TRANSFORM_FEEDBACK_BUFFER) { _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferOffsetEXT(target)"); @@ -497,12 +589,7 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, return; } - /* default size is the buffer size rounded down to nearest - * multiple of four. - */ - size = (bufObj->Size - offset) & ~0x3; - - bind_buffer_range(ctx, index, bufObj, offset, size); + bind_buffer_range(ctx, index, bufObj, offset, 0); } @@ -708,14 +795,19 @@ _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) GLboolean GLAPIENTRY _mesa_IsTransformFeedback(GLuint name) { + struct gl_transform_feedback_object *obj; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - if (name && _mesa_lookup_transform_feedback_object(ctx, name)) - return GL_TRUE; - else + if (name == 0) return GL_FALSE; + + obj = _mesa_lookup_transform_feedback_object(ctx, name); + if (obj == NULL) + return GL_FALSE; + + return obj->EverBound; } @@ -734,8 +826,7 @@ _mesa_BindTransformFeedback(GLenum target, GLuint name) return; } - if (ctx->TransformFeedback.CurrentObject->Active && - !ctx->TransformFeedback.CurrentObject->Paused) { + if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTransformFeedback(transform is active, or not paused)"); return; @@ -805,7 +896,7 @@ _mesa_PauseTransformFeedback(void) obj = ctx->TransformFeedback.CurrentObject; - if (!obj->Active || obj->Paused) { + if (!_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glPauseTransformFeedback(feedback not active or already paused)"); return; diff --git a/mesalib/src/mesa/main/transformfeedback.h b/mesalib/src/mesa/main/transformfeedback.h index 01c2af359..c128746b3 100644 --- a/mesalib/src/mesa/main/transformfeedback.h +++ b/mesalib/src/mesa/main/transformfeedback.h @@ -25,9 +25,11 @@ #ifndef TRANSFORM_FEEDBACK_H #define TRANSFORM_FEEDBACK_H +#include <stdbool.h> #include "compiler.h" #include "glheader.h" #include "mfeatures.h" +#include "mtypes.h" struct _glapi_table; struct dd_function_table; @@ -46,6 +48,11 @@ _mesa_validate_transform_feedback_buffers(struct gl_context *ctx); extern void _mesa_init_transform_feedback_functions(struct dd_function_table *driver); +extern unsigned +_mesa_compute_max_transform_feedback_vertices( + const struct gl_transform_feedback_object *obj, + const struct gl_transform_feedback_info *info); + /*** GL_EXT_transform_feedback ***/ @@ -106,4 +113,11 @@ _mesa_PauseTransformFeedback(void); extern void GLAPIENTRY _mesa_ResumeTransformFeedback(void); +static inline bool +_mesa_is_xfb_active_and_unpaused(const struct gl_context *ctx) +{ + return ctx->TransformFeedback.CurrentObject->Active && + !ctx->TransformFeedback.CurrentObject->Paused; +} + #endif /* TRANSFORM_FEEDBACK_H */ diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index b6b73d16f..afe9a08c1 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -241,11 +241,14 @@ validate_uniform_parameters(struct gl_context *ctx, return false; } - /* This case should be impossible. The implication is that a call like - * glGetUniformLocation(prog, "foo[8]") was successful but "foo" is not an - * array. + /* If the uniform is an array, check that array_index is in bounds. + * If not an array, check that array_index is zero. + * array_index is unsigned so no need to check for less than zero. */ - if (*array_index != 0 && shProg->UniformStorage[*loc].array_elements == 0) { + unsigned limit = shProg->UniformStorage[*loc].array_elements; + if (limit == 0) + limit = 1; + if (*array_index >= limit) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)", caller, location); return false; @@ -732,9 +735,6 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, * will have already generated an error. */ if (uni->array_elements != 0) { - if (offset >= uni->array_elements) - return; - count = MIN2(count, (int) (uni->array_elements - offset)); } @@ -889,9 +889,6 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg, * will have already generated an error. */ if (uni->array_elements != 0) { - if (offset >= uni->array_elements) - return; - count = MIN2(count, (int) (uni->array_elements - offset)); } @@ -1025,10 +1022,13 @@ _mesa_get_uniform_location(struct gl_context *ctx, if (!found) return GL_INVALID_INDEX; - /* Since array_elements is 0 for non-arrays, this causes look-ups of 'a[0]' - * to (correctly) fail if 'a' is not an array. + /* If the uniform is an array, fail if the index is out of bounds. + * (A negative index is caught above.) This also fails if the uniform + * is not an array, but the user is trying to index it, because + * array_elements is zero and offset >= 0. */ - if (array_lookup && shProg->UniformStorage[location].array_elements == 0) { + if (array_lookup + && offset >= (long) shProg->UniformStorage[location].array_elements) { return GL_INVALID_INDEX; } |