aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r--mesalib/src/mesa/main/api_validate.c94
-rw-r--r--mesalib/src/mesa/main/arrayobj.c8
-rw-r--r--mesalib/src/mesa/main/buffers.c4
-rw-r--r--mesalib/src/mesa/main/fbobject.c44
-rw-r--r--mesalib/src/mesa/main/get.c3
-rw-r--r--mesalib/src/mesa/main/mtypes.h27
-rw-r--r--mesalib/src/mesa/main/pbo.c15
-rw-r--r--mesalib/src/mesa/main/pbo.h3
-rw-r--r--mesalib/src/mesa/main/samplerobj.c20
-rw-r--r--mesalib/src/mesa/main/samplerobj.h7
-rw-r--r--mesalib/src/mesa/main/shaderapi.c8
-rw-r--r--mesalib/src/mesa/main/texcompress.c4
-rw-r--r--mesalib/src/mesa/main/texcompress_rgtc.c5
-rw-r--r--mesalib/src/mesa/main/texcompress_s3tc.c82
-rw-r--r--mesalib/src/mesa/main/texgetimage.c2
-rw-r--r--mesalib/src/mesa/main/teximage.c16
-rw-r--r--mesalib/src/mesa/main/texstore.c58
-rw-r--r--mesalib/src/mesa/main/transformfeedback.c135
-rw-r--r--mesalib/src/mesa/main/transformfeedback.h14
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp26
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;
}