aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main')
-rwxr-xr-xmesalib/src/mesa/main/.gitignore1
-rw-r--r--mesalib/src/mesa/main/atifragshader.c4
-rw-r--r--mesalib/src/mesa/main/attrib.c1
-rwxr-xr-xmesalib/src/mesa/main/bufferobj.c11
-rw-r--r--mesalib/src/mesa/main/colormac.h45
-rw-r--r--mesalib/src/mesa/main/context.c12
-rw-r--r--mesalib/src/mesa/main/debug.c2
-rwxr-xr-x[-rw-r--r--]mesalib/src/mesa/main/dlopen.h0
-rw-r--r--mesalib/src/mesa/main/errors.c43
-rw-r--r--mesalib/src/mesa/main/errors.h7
-rw-r--r--mesalib/src/mesa/main/extensions.c1
-rw-r--r--mesalib/src/mesa/main/fbobject.c439
-rw-r--r--mesalib/src/mesa/main/fbobject.h16
-rw-r--r--mesalib/src/mesa/main/ffvertex_prog.c6
-rw-r--r--mesalib/src/mesa/main/format_pack.py1
-rw-r--r--mesalib/src/mesa/main/format_unpack.h2
-rw-r--r--mesalib/src/mesa/main/format_unpack.py5
-rw-r--r--mesalib/src/mesa/main/glformats.c2
-rwxr-xr-xmesalib/src/mesa/main/imports.h24
-rwxr-xr-xmesalib/src/mesa/main/macros.h7
-rw-r--r--mesalib/src/mesa/main/mtypes.h184
-rw-r--r--mesalib/src/mesa/main/multisample.c9
-rw-r--r--mesalib/src/mesa/main/pipelineobj.c35
-rw-r--r--mesalib/src/mesa/main/pipelineobj.h3
-rw-r--r--mesalib/src/mesa/main/pixel.c1
-rw-r--r--mesalib/src/mesa/main/pixeltransfer.c2
-rw-r--r--mesalib/src/mesa/main/program_resource.c417
-rw-r--r--mesalib/src/mesa/main/program_resource.h58
-rwxr-xr-xmesalib/src/mesa/main/queryobj.c131
-rw-r--r--mesalib/src/mesa/main/queryobj.h14
-rw-r--r--mesalib/src/mesa/main/samplerobj.c25
-rw-r--r--mesalib/src/mesa/main/samplerobj.h5
-rw-r--r--mesalib/src/mesa/main/shader_query.cpp764
-rw-r--r--mesalib/src/mesa/main/shaderapi.c25
-rw-r--r--mesalib/src/mesa/main/shaderapi.h45
-rw-r--r--mesalib/src/mesa/main/shaderobj.c6
-rw-r--r--mesalib/src/mesa/main/state.c27
-rw-r--r--mesalib/src/mesa/main/texcompress.c1
-rw-r--r--mesalib/src/mesa/main/texcompress_fxt1.c1
-rw-r--r--mesalib/src/mesa/main/texcompress_rgtc.c1
-rw-r--r--mesalib/src/mesa/main/texcompress_s3tc.c9
-rw-r--r--mesalib/src/mesa/main/texparam.c1
-rw-r--r--mesalib/src/mesa/main/texstate.c2
-rw-r--r--mesalib/src/mesa/main/texstore.c1
-rw-r--r--mesalib/src/mesa/main/transformfeedback.c386
-rw-r--r--mesalib/src/mesa/main/transformfeedback.h30
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp138
-rw-r--r--mesalib/src/mesa/main/uniforms.c294
-rw-r--r--mesalib/src/mesa/main/uniforms.h5
-rw-r--r--mesalib/src/mesa/main/version.c1
-rw-r--r--mesalib/src/mesa/main/viewport.c48
-rw-r--r--mesalib/src/mesa/main/viewport.h3
52 files changed, 2325 insertions, 976 deletions
diff --git a/mesalib/src/mesa/main/.gitignore b/mesalib/src/mesa/main/.gitignore
index 54885405f..58c73d333 100755
--- a/mesalib/src/mesa/main/.gitignore
+++ b/mesalib/src/mesa/main/.gitignore
@@ -8,5 +8,6 @@ get_hash.h
get_hash.h.tmp
format_info.h
glapitable.h
+format_info.c
format_pack.c
format_unpack.c
diff --git a/mesalib/src/mesa/main/atifragshader.c b/mesalib/src/mesa/main/atifragshader.c
index 9d967b9e6..9fc35520a 100644
--- a/mesalib/src/mesa/main/atifragshader.c
+++ b/mesalib/src/mesa/main/atifragshader.c
@@ -476,7 +476,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
curI->swizzle = swizzle;
#if MESA_DEBUG_ATI_FS
- _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
+ _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
_mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
_mesa_lookup_enum_by_nr(swizzle));
#endif
@@ -549,7 +549,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
curI->swizzle = swizzle;
#if MESA_DEBUG_ATI_FS
- _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
+ _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
_mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
_mesa_lookup_enum_by_nr(swizzle));
#endif
diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c
index 20216a87d..b163c0aa6 100644
--- a/mesalib/src/mesa/main/attrib.c
+++ b/mesalib/src/mesa/main/attrib.c
@@ -32,7 +32,6 @@
#include "buffers.h"
#include "bufferobj.h"
#include "clear.h"
-#include "colormac.h"
#include "context.h"
#include "depth.h"
#include "enable.h"
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index 25110c33b..4a116acfe 100755
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -1333,6 +1333,7 @@ create_buffers(GLsizei n, GLuint *buffers, bool dsa)
buf = ctx->Driver.NewBufferObject(ctx, buffers[i]);
if (!buf) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
+ mtx_unlock(&ctx->Shared->Mutex);
return;
}
}
@@ -3885,8 +3886,10 @@ _mesa_BindBufferRange(GLenum target, GLuint index,
switch (target) {
case GL_TRANSFORM_FEEDBACK_BUFFER:
- _mesa_bind_buffer_range_transform_feedback(ctx, index, bufObj,
- offset, size);
+ _mesa_bind_buffer_range_transform_feedback(ctx,
+ ctx->TransformFeedback.CurrentObject,
+ index, bufObj, offset, size,
+ false);
return;
case GL_UNIFORM_BUFFER:
bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
@@ -3950,7 +3953,9 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
switch (target) {
case GL_TRANSFORM_FEEDBACK_BUFFER:
- _mesa_bind_buffer_base_transform_feedback(ctx, index, bufObj);
+ _mesa_bind_buffer_base_transform_feedback(ctx,
+ ctx->TransformFeedback.CurrentObject,
+ index, bufObj, false);
return;
case GL_UNIFORM_BUFFER:
bind_buffer_base_uniform_buffer(ctx, index, bufObj);
diff --git a/mesalib/src/mesa/main/colormac.h b/mesalib/src/mesa/main/colormac.h
index bc69f4673..33ca5af07 100644
--- a/mesalib/src/mesa/main/colormac.h
+++ b/mesalib/src/mesa/main/colormac.h
@@ -52,70 +52,25 @@ _mesa_unclamped_float_rgba_to_ubyte(GLubyte dst[4], const GLfloat src[4])
/**
* \name Generic color packing macros. All inputs should be GLubytes.
- *
- * \todo We may move these into texstore.h at some point.
*/
/*@{*/
#define PACK_COLOR_8888( X, Y, Z, W ) \
(((X) << 24) | ((Y) << 16) | ((Z) << 8) | (W))
-#define PACK_COLOR_8888_REV( X, Y, Z, W ) \
- (((W) << 24) | ((Z) << 16) | ((Y) << 8) | (X))
-
-#define PACK_COLOR_888( X, Y, Z ) \
- (((X) << 16) | ((Y) << 8) | (Z))
-
#define PACK_COLOR_565( X, Y, Z ) \
((((X) & 0xf8) << 8) | (((Y) & 0xfc) << 3) | (((Z) & 0xf8) >> 3))
-#define PACK_COLOR_5551( R, G, B, A ) \
- ((((R) & 0xf8) << 8) | (((G) & 0xf8) << 3) | (((B) & 0xf8) >> 2) | \
- ((A) >> 7))
-
#define PACK_COLOR_1555( A, B, G, R ) \
((((B) & 0xf8) << 7) | (((G) & 0xf8) << 2) | (((R) & 0xf8) >> 3) | \
(((A) & 0x80) << 8))
-#define PACK_COLOR_1555_REV( A, B, G, R ) \
- ((((B) & 0xf8) >> 1) | (((G) & 0xc0) >> 6) | (((G) & 0x38) << 10) | (((R) & 0xf8) << 5) | \
- ((A) ? 0x80 : 0))
-
-#define PACK_COLOR_2101010_UB( A, B, G, R ) \
- (((B) << 22) | ((G) << 12) | ((R) << 2) | \
- (((A) & 0xc0) << 24))
-
-#define PACK_COLOR_2101010_US( A, B, G, R ) \
- ((((B) >> 6) << 20) | (((G) >> 6) << 10) | ((R) >> 6) | \
- (((A) >> 14) << 30))
-
#define PACK_COLOR_4444( R, G, B, A ) \
((((R) & 0xf0) << 8) | (((G) & 0xf0) << 4) | ((B) & 0xf0) | ((A) >> 4))
-#define PACK_COLOR_4444_REV( R, G, B, A ) \
- ((((B) & 0xf0) << 8) | (((A) & 0xf0) << 4) | ((R) & 0xf0) | ((G) >> 4))
-
-#define PACK_COLOR_44( L, A ) \
- (((L) & 0xf0) | (((A) & 0xf0) >> 4))
-
#define PACK_COLOR_88( L, A ) \
(((L) << 8) | (A))
-#define PACK_COLOR_88_REV( L, A ) \
- (((A) << 8) | (L))
-
-#define PACK_COLOR_1616( L, A ) \
- (((L) << 16) | (A))
-
-#define PACK_COLOR_1616_REV( L, A ) \
- (((A) << 16) | (L))
-
-#define PACK_COLOR_332( R, G, B ) \
- (((R) & 0xe0) | (((G) & 0xe0) >> 3) | (((B) & 0xc0) >> 6))
-
-#define PACK_COLOR_233( B, G, R ) \
- (((B) & 0xc0) | (((G) & 0xe0) >> 2) | (((R) & 0xe0) >> 5))
-
/*@}*/
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index c1acda980..adf64976e 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -1288,7 +1288,6 @@ _mesa_free_context_data( struct gl_context *ctx )
_mesa_free_eval_data( ctx );
_mesa_free_texture_data( ctx );
_mesa_free_matrix_data( ctx );
- _mesa_free_viewport_data( ctx );
_mesa_free_pipeline_data(ctx);
_mesa_free_program_data(ctx);
_mesa_free_shader_state(ctx);
@@ -1449,17 +1448,10 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst,
dst->Transform = src->Transform;
}
if (mask & GL_VIEWPORT_BIT) {
- /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */
unsigned i;
for (i = 0; i < src->Const.MaxViewports; i++) {
- dst->ViewportArray[i].X = src->ViewportArray[i].X;
- dst->ViewportArray[i].Y = src->ViewportArray[i].Y;
- dst->ViewportArray[i].Width = src->ViewportArray[i].Width;
- dst->ViewportArray[i].Height = src->ViewportArray[i].Height;
- dst->ViewportArray[i].Near = src->ViewportArray[i].Near;
- dst->ViewportArray[i].Far = src->ViewportArray[i].Far;
- _math_matrix_copy(&dst->ViewportArray[i]._WindowMap,
- &src->ViewportArray[i]._WindowMap);
+ /* OK to memcpy */
+ dst->ViewportArray[i] = src->ViewportArray[i];
}
}
diff --git a/mesalib/src/mesa/main/debug.c b/mesalib/src/mesa/main/debug.c
index b50d79e0c..c93e84a04 100644
--- a/mesalib/src/mesa/main/debug.c
+++ b/mesalib/src/mesa/main/debug.c
@@ -26,11 +26,11 @@
#include <stdio.h>
#include "mtypes.h"
#include "attrib.h"
-#include "colormac.h"
#include "enums.h"
#include "formats.h"
#include "hash.h"
#include "imports.h"
+#include "macros.h"
#include "debug.h"
#include "get.h"
#include "pixelstore.h"
diff --git a/mesalib/src/mesa/main/dlopen.h b/mesalib/src/mesa/main/dlopen.h
index 93d1258cf..93d1258cf 100644..100755
--- a/mesalib/src/mesa/main/dlopen.h
+++ b/mesalib/src/mesa/main/dlopen.h
diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c
index 8ffbf413c..2aa1deb63 100644
--- a/mesalib/src/mesa/main/errors.c
+++ b/mesalib/src/mesa/main/errors.c
@@ -1232,12 +1232,14 @@ _mesa_free_errors_data(struct gl_context *ctx)
/** \name Diagnostics */
/*@{*/
+static FILE *LogFile = NULL;
+
+
static void
output_if_debug(const char *prefixString, const char *outputString,
GLboolean newline)
{
static int debug = -1;
- static FILE *fout = NULL;
/* Init the local 'debug' var once.
* Note: the _mesa_init_debug() function should have been called
@@ -1249,9 +1251,9 @@ output_if_debug(const char *prefixString, const char *outputString,
*/
const char *logFile = getenv("MESA_LOG_FILE");
if (logFile)
- fout = fopen(logFile, "w");
- if (!fout)
- fout = stderr;
+ LogFile = fopen(logFile, "w");
+ if (!LogFile)
+ LogFile = stderr;
#ifdef DEBUG
/* in debug builds, print messages unless MESA_DEBUG="silent" */
if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
@@ -1266,10 +1268,13 @@ output_if_debug(const char *prefixString, const char *outputString,
/* Now only print the string if we're required to do so. */
if (debug) {
- fprintf(fout, "%s: %s", prefixString, outputString);
+ if (prefixString)
+ fprintf(LogFile, "%s: %s", prefixString, outputString);
+ else
+ fprintf(LogFile, "%s", outputString);
if (newline)
- fprintf(fout, "\n");
- fflush(fout);
+ fprintf(LogFile, "\n");
+ fflush(LogFile);
#if defined(_WIN32)
/* stderr from windows applications without console is not usually
@@ -1285,6 +1290,18 @@ output_if_debug(const char *prefixString, const char *outputString,
/**
+ * Return the file handle to use for debug/logging. Defaults to stderr
+ * unless MESA_LOG_FILE is defined.
+ */
+FILE *
+_mesa_get_log_file(void)
+{
+ assert(LogFile);
+ return LogFile;
+}
+
+
+/**
* When a new type of error is recorded, print a message describing
* previous errors which were accumulated.
*/
@@ -1525,6 +1542,18 @@ _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
}
+void
+_mesa_log(const char *fmtString, ...)
+{
+ char s[MAX_DEBUG_MESSAGE_LENGTH];
+ va_list args;
+ va_start(args, fmtString);
+ _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
+ va_end(args);
+ output_if_debug("", s, GL_FALSE);
+}
+
+
/**
* Report debug information from the shader compiler via GL_ARB_debug_output.
*
diff --git a/mesalib/src/mesa/main/errors.h b/mesalib/src/mesa/main/errors.h
index 0c521c0d0..e6dc9b5f1 100644
--- a/mesalib/src/mesa/main/errors.h
+++ b/mesalib/src/mesa/main/errors.h
@@ -36,6 +36,7 @@
#define ERRORS_H
+#include <stdio.h>
#include "compiler.h"
#include "glheader.h"
#include "mtypes.h"
@@ -69,6 +70,12 @@ extern void
_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3);
extern void
+_mesa_log(const char *fmtString, ...) PRINTFLIKE(1, 2);
+
+extern FILE *
+_mesa_get_log_file(void);
+
+extern void
_mesa_gl_debug(struct gl_context *ctx,
GLuint *id,
enum mesa_debug_source source,
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index f21201538..861b15006 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -139,6 +139,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_pixel_buffer_object", o(EXT_pixel_buffer_object), GL, 2004 },
{ "GL_ARB_point_parameters", o(EXT_point_parameters), GLL, 1997 },
{ "GL_ARB_point_sprite", o(ARB_point_sprite), GL, 2003 },
+ { "GL_ARB_program_interface_query", o(dummy_true), GL, 2012 },
{ "GL_ARB_provoking_vertex", o(EXT_provoking_vertex), GL, 2009 },
{ "GL_ARB_robustness", o(dummy_true), GL, 2010 },
{ "GL_ARB_sample_shading", o(ARB_sample_shading), GL, 2009 },
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
index f8d0d92bf..8032585ab 100644
--- a/mesalib/src/mesa/main/fbobject.c
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -212,13 +212,13 @@ get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
*/
i = attachment - GL_COLOR_ATTACHMENT0_EXT;
if (i >= ctx->Const.MaxColorAttachments
- || (i > 0 && ctx->API == API_OPENGLES)) {
- return NULL;
+ || (i > 0 && ctx->API == API_OPENGLES)) {
+ return NULL;
}
return &fb->Attachment[BUFFER_COLOR0 + i];
case GL_DEPTH_STENCIL_ATTACHMENT:
if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
- return NULL;
+ return NULL;
/* fall-through */
case GL_DEPTH_ATTACHMENT_EXT:
return &fb->Attachment[BUFFER_DEPTH];
@@ -1122,28 +1122,28 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
/* Check that all DrawBuffers are present */
for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
- if (fb->ColorDrawBuffer[j] != GL_NONE) {
- const struct gl_renderbuffer_attachment *att
- = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
- assert(att);
- if (att->Type == GL_NONE) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
- fbo_incomplete(ctx, "missing drawbuffer", j);
- return;
- }
- }
+ if (fb->ColorDrawBuffer[j] != GL_NONE) {
+ const struct gl_renderbuffer_attachment *att
+ = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
+ assert(att);
+ if (att->Type == GL_NONE) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
+ fbo_incomplete(ctx, "missing drawbuffer", j);
+ return;
+ }
+ }
}
/* Check that the ReadBuffer is present */
if (fb->ColorReadBuffer != GL_NONE) {
- const struct gl_renderbuffer_attachment *att
- = get_attachment(ctx, fb, fb->ColorReadBuffer);
- assert(att);
- if (att->Type == GL_NONE) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
+ const struct gl_renderbuffer_attachment *att
+ = get_attachment(ctx, fb, fb->ColorReadBuffer);
+ assert(att);
+ if (att->Type == GL_NONE) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
fbo_incomplete(ctx, "missing readbuffer", -1);
- return;
- }
+ return;
+ }
}
}
@@ -1205,6 +1205,28 @@ _mesa_IsRenderbuffer(GLuint renderbuffer)
}
+static struct gl_renderbuffer *
+allocate_renderbuffer(struct gl_context *ctx, GLuint renderbuffer,
+ const char *func)
+{
+ struct gl_renderbuffer *newRb;
+
+ /* create new renderbuffer object */
+ newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
+ if (!newRb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
+ return NULL;
+ }
+ assert(newRb->AllocStorage);
+ mtx_lock(&ctx->Shared->Mutex);
+ _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
+ newRb->RefCount = 1; /* referenced by hash table */
+ mtx_unlock(&ctx->Shared->Mutex);
+
+ return newRb;
+}
+
+
static void
bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
{
@@ -1233,15 +1255,7 @@ bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
}
if (!newRb) {
- /* create new renderbuffer object */
- newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
- if (!newRb) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
- return;
- }
- assert(newRb->AllocStorage);
- _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
- newRb->RefCount = 1; /* referenced by hash table */
+ newRb = allocate_renderbuffer(ctx, renderbuffer, "glBindRenderbufferEXT");
}
}
else {
@@ -1333,9 +1347,9 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
for (i = 0; i < n; i++) {
if (renderbuffers[i] > 0) {
- struct gl_renderbuffer *rb;
- rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
- if (rb) {
+ struct gl_renderbuffer *rb;
+ rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
+ if (rb) {
/* check if deleting currently bound renderbuffer object */
if (rb == ctx->CurrentRenderbuffer) {
/* bind default */
@@ -1368,31 +1382,31 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
_mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
}
- /* Remove from hash table immediately, to free the ID.
+ /* Remove from hash table immediately, to free the ID.
* But the object will not be freed until it's no longer
* referenced anywhere else.
*/
- _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
+ _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
if (rb != &DummyRenderbuffer) {
/* no longer referenced by hash table */
_mesa_reference_renderbuffer(&rb, NULL);
- }
- }
+ }
+ }
}
}
}
-
-void GLAPIENTRY
-_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+static void
+create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
+ bool dsa)
{
- GET_CURRENT_CONTEXT(ctx);
+ const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
GLuint first;
GLint i;
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
return;
}
@@ -1404,14 +1418,35 @@ _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
for (i = 0; i < n; i++) {
GLuint name = first + i;
renderbuffers[i] = name;
- /* insert dummy placeholder into hash table */
- mtx_lock(&ctx->Shared->Mutex);
- _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
- mtx_unlock(&ctx->Shared->Mutex);
+
+ if (dsa) {
+ allocate_renderbuffer(ctx, name, func);
+ } else {
+ /* insert a dummy renderbuffer into the hash table */
+ mtx_lock(&ctx->Shared->Mutex);
+ _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
+ mtx_unlock(&ctx->Shared->Mutex);
+ }
}
}
+void GLAPIENTRY
+_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_render_buffers(ctx, n, renderbuffers, false);
+}
+
+
+void GLAPIENTRY
+_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_render_buffers(ctx, n, renderbuffers, true);
+}
+
+
/**
* Given an internal format token for a render buffer, return the
* corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
@@ -1749,40 +1784,17 @@ invalidate_rb(GLuint key, void *data, void *userData)
/**
- * Helper function used by _mesa_RenderbufferStorage() and
- * _mesa_RenderbufferStorageMultisample().
- * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
+ * Helper function used by renderbuffer_storage_direct() and
+ * renderbuffer_storage_target().
+ * samples will be NO_SAMPLES if called by a non-multisample function.
*/
static void
-renderbuffer_storage(GLenum target, GLenum internalFormat,
- GLsizei width, GLsizei height, GLsizei samples)
+renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei samples, const char *func)
{
- const char *func = samples == NO_SAMPLES ?
- "glRenderbufferStorage" : "glRenderbufferStorageMultisample";
- struct gl_renderbuffer *rb;
GLenum baseFormat;
GLenum sample_count_error;
- GET_CURRENT_CONTEXT(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API) {
- if (samples == NO_SAMPLES)
- _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
- func,
- _mesa_lookup_enum_by_nr(target),
- _mesa_lookup_enum_by_nr(internalFormat),
- width, height);
- else
- _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
- func,
- _mesa_lookup_enum_by_nr(target),
- _mesa_lookup_enum_by_nr(internalFormat),
- width, height, samples);
- }
-
- if (target != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
- return;
- }
baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
if (baseFormat == 0) {
@@ -1792,12 +1804,14 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
}
if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func,
+ width);
return;
}
if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func,
+ height);
return;
}
@@ -1809,7 +1823,7 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
/* check the sample count;
* note: driver may choose to use more samples than what's requested
*/
- sample_count_error = _mesa_check_sample_count(ctx, target,
+ sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
internalFormat, samples);
if (sample_count_error != GL_NO_ERROR) {
_mesa_error(ctx, sample_count_error, "%s(samples)", func);
@@ -1817,12 +1831,6 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
}
}
- rb = ctx->CurrentRenderbuffer;
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
- return;
- }
-
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (rb->InternalFormat == internalFormat &&
@@ -1864,6 +1872,83 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
}
}
+/**
+ * Helper function used by _mesa_NamedRenderbufferStorage*().
+ * samples will be NO_SAMPLES if called by a non-multisample function.
+ */
+static void
+renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei samples,
+ const char *func)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API) {
+ if (samples == NO_SAMPLES)
+ _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
+ func, renderbuffer,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height);
+ else
+ _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n",
+ func, renderbuffer,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height, samples);
+ }
+
+ struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (!rb || rb == &DummyRenderbuffer) {
+ /* ID was reserved, but no real renderbuffer object made yet */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)",
+ func, renderbuffer);
+ return;
+ }
+
+ renderbuffer_storage(ctx, rb, internalFormat, width, height, samples, func);
+}
+
+/**
+ * Helper function used by _mesa_RenderbufferStorage() and
+ * _mesa_RenderbufferStorageMultisample().
+ * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
+ */
+static void
+renderbuffer_storage_target(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei samples,
+ const char *func)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API) {
+ if (samples == NO_SAMPLES)
+ _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
+ func,
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height);
+ else
+ _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
+ func,
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height, samples);
+ }
+
+ if (target != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
+ return;
+ }
+
+ if (!ctx->CurrentRenderbuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)",
+ func);
+ return;
+ }
+
+ renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
+ height, samples, func);
+}
+
void GLAPIENTRY
_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
@@ -1923,7 +2008,8 @@ _mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
* glRenderbufferStorageMultisample() with samples=0. We pass in
* a token value here just for error reporting purposes.
*/
- renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
+ renderbuffer_storage_target(target, internalFormat, width, height,
+ NO_SAMPLES, "glRenderbufferStorage");
}
@@ -1932,7 +2018,8 @@ _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalFormat,
GLsizei width, GLsizei height)
{
- renderbuffer_storage(target, internalFormat, width, height, samples);
+ renderbuffer_storage_target(target, internalFormat, width, height,
+ samples, "glRenderbufferStorageMultisample");
}
@@ -1941,7 +2028,7 @@ _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
*/
void GLAPIENTRY
_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
- GLsizei width, GLsizei height)
+ GLsizei width, GLsizei height)
{
switch (internalFormat) {
case GL_RGB565:
@@ -1953,29 +2040,38 @@ _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
break;
}
- renderbuffer_storage(target, internalFormat, width, height, 0);
+ renderbuffer_storage_target(target, internalFormat, width, height, 0,
+ "glRenderbufferStorageEXT");
}
-
void GLAPIENTRY
-_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
+ GLsizei width, GLsizei height)
{
- struct gl_renderbuffer *rb;
- GET_CURRENT_CONTEXT(ctx);
+ /* GL_ARB_fbo says calling this function is equivalent to calling
+ * glRenderbufferStorageMultisample() with samples=0. We pass in
+ * a token value here just for error reporting purposes.
+ */
+ renderbuffer_storage_named(renderbuffer, internalformat, width, height,
+ NO_SAMPLES, "glNamedRenderbufferStorage");
+}
- if (target != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetRenderbufferParameterivEXT(target)");
- return;
- }
+void GLAPIENTRY
+_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
+ GLenum internalformat,
+ GLsizei width, GLsizei height)
+{
+ renderbuffer_storage_named(renderbuffer, internalformat, width, height,
+ samples,
+ "glNamedRenderbufferStorageMultisample");
+}
- rb = ctx->CurrentRenderbuffer;
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetRenderbufferParameterivEXT");
- return;
- }
+static void
+get_render_buffer_parameteriv(struct gl_context *ctx,
+ struct gl_renderbuffer *rb, GLenum pname,
+ GLint *params, const char *func)
+{
/* No need to flush here since we're just quering state which is
* not effected by rendering.
*/
@@ -2006,10 +2102,51 @@ _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
}
/* fallthrough */
default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
+ _mesa_lookup_enum_by_nr(pname));
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (target != GL_RENDERBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetRenderbufferParameterivEXT(target)");
return;
}
+
+ if (!ctx->CurrentRenderbuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT"
+ "(no renderbuffer bound)");
+ return;
+ }
+
+ get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname,
+ params, "glGetRenderbufferParameteriv");
+}
+
+
+void GLAPIENTRY
+_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
+ GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (!rb || rb == &DummyRenderbuffer) {
+ /* ID was reserved, but no real renderbuffer object made yet */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv"
+ "(invalid renderbuffer %i)", renderbuffer);
+ return;
+ }
+
+ get_render_buffer_parameteriv(ctx, rb, pname, params,
+ "glGetNamedRenderbufferParameteriv");
}
@@ -2116,12 +2253,12 @@ bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names)
}
if (!newDrawFb) {
- /* create new framebuffer object */
- newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
- if (!newDrawFb) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
- return;
- }
+ /* create new framebuffer object */
+ newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
+ if (!newDrawFb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
+ return;
+ }
_mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
}
newReadFb = newDrawFb;
@@ -2224,9 +2361,9 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
for (i = 0; i < n; i++) {
if (framebuffers[i] > 0) {
- struct gl_framebuffer *fb;
- fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
- if (fb) {
+ struct gl_framebuffer *fb;
+ fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
+ if (fb) {
assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
/* check if deleting currently bound framebuffer object */
@@ -2241,16 +2378,16 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
_mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
- /* remove from hash table immediately, to free the ID */
- _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
+ /* remove from hash table immediately, to free the ID */
+ _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
if (fb != &DummyFramebuffer) {
/* But the object will not be freed until it's no longer
* bound in any context.
*/
_mesa_reference_framebuffer(&fb, NULL);
- }
- }
+ }
+ }
}
}
}
@@ -2498,34 +2635,34 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
_mesa_tex_target_to_face(textarget) ==
fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
- /* The texture object is already attached to the stencil attachment
- * point. Don't create a new renderbuffer; just reuse the stencil
- * attachment's. This is required to prevent a GL error in
- * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
- */
- reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
- BUFFER_STENCIL);
+ /* The texture object is already attached to the stencil attachment
+ * point. Don't create a new renderbuffer; just reuse the stencil
+ * attachment's. This is required to prevent a GL error in
+ * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
+ */
+ reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
+ BUFFER_STENCIL);
} else if (attachment == GL_STENCIL_ATTACHMENT &&
- texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
+ texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
_mesa_tex_target_to_face(textarget) ==
fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
- /* As above, but with depth and stencil transposed. */
- reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
- BUFFER_DEPTH);
+ /* As above, but with depth and stencil transposed. */
+ reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
+ BUFFER_DEPTH);
} else {
- set_texture_attachment(ctx, fb, att, texObj, textarget,
- level, zoffset, layered);
- if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
- /* Above we created a new renderbuffer and attached it to the
- * depth attachment point. Now attach it to the stencil attachment
- * point too.
- */
- assert(att == &fb->Attachment[BUFFER_DEPTH]);
- reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
- BUFFER_DEPTH);
- }
+ set_texture_attachment(ctx, fb, att, texObj, textarget,
+ level, zoffset, layered);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* Above we created a new renderbuffer and attached it to the
+ * depth attachment point. Now attach it to the stencil attachment
+ * point too.
+ */
+ assert(att == &fb->Attachment[BUFFER_DEPTH]);
+ reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
+ BUFFER_DEPTH);
+ }
}
/* Set the render-to-texture flag. We'll check this flag in
@@ -2541,8 +2678,8 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
else {
remove_attachment(ctx, att);
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
- assert(att == &fb->Attachment[BUFFER_DEPTH]);
- remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
+ assert(att == &fb->Attachment[BUFFER_DEPTH]);
+ remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
}
}
@@ -2721,16 +2858,16 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
if (renderbuffer) {
rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(non-existant"
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbuffer(non-existant"
" renderbuffer %u)", renderbuffer);
- return;
+ return;
}
else if (rb == &DummyRenderbuffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(renderbuffer %u)",
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbuffer(renderbuffer %u)",
renderbuffer);
- return;
+ return;
}
}
else {
@@ -2795,9 +2932,9 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
if ((!_mesa_is_desktop_gl(ctx) ||
!ctx->Extensions.ARB_framebuffer_object)
&& !_mesa_is_gles3(ctx)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
- return;
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
+ return;
}
if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
@@ -2855,10 +2992,10 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
return;
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
if (att->Type == GL_RENDERBUFFER_EXT) {
- *params = att->Renderbuffer->Name;
+ *params = att->Renderbuffer->Name;
}
else if (att->Type == GL_TEXTURE) {
- *params = att->Texture->Name;
+ *params = att->Texture->Name;
}
else {
assert(att->Type == GL_NONE);
@@ -2871,7 +3008,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
return;
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
if (att->Type == GL_TEXTURE) {
- *params = att->TextureLevel;
+ *params = att->TextureLevel;
}
else if (att->Type == GL_NONE) {
_mesa_error(ctx, err,
diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h
index 77fdef415..61aa1f503 100644
--- a/mesalib/src/mesa/main/fbobject.h
+++ b/mesalib/src/mesa/main/fbobject.h
@@ -115,6 +115,9 @@ extern void GLAPIENTRY
_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers);
extern void GLAPIENTRY
+_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers);
+
+extern void GLAPIENTRY
_mesa_RenderbufferStorage(GLenum target, GLenum internalformat,
GLsizei width, GLsizei height);
@@ -128,12 +131,25 @@ _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
GLsizei width, GLsizei height);
extern void GLAPIENTRY
+_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
+ GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
+_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
+ GLenum internalformat,
+ GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
extern void GLAPIENTRY
_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname,
GLint *params);
+void GLAPIENTRY
+_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
+ GLint *params);
+
extern GLboolean GLAPIENTRY
_mesa_IsFramebuffer(GLuint framebuffer);
diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c
index 395b00e15..edf7e3390 100644
--- a/mesalib/src/mesa/main/ffvertex_prog.c
+++ b/mesalib/src/mesa/main/ffvertex_prog.c
@@ -619,13 +619,13 @@ static void emit_op3fn(struct tnl_program *p,
#define emit_op3(p, op, dst, mask, src0, src1, src2) \
- emit_op3fn(p, op, dst, mask, src0, src1, src2, __FUNCTION__, __LINE__)
+ emit_op3fn(p, op, dst, mask, src0, src1, src2, __func__, __LINE__)
#define emit_op2(p, op, dst, mask, src0, src1) \
- emit_op3fn(p, op, dst, mask, src0, src1, undef, __FUNCTION__, __LINE__)
+ emit_op3fn(p, op, dst, mask, src0, src1, undef, __func__, __LINE__)
#define emit_op1(p, op, dst, mask, src0) \
- emit_op3fn(p, op, dst, mask, src0, undef, undef, __FUNCTION__, __LINE__)
+ emit_op3fn(p, op, dst, mask, src0, undef, undef, __func__, __LINE__)
static struct ureg make_temp( struct tnl_program *p, struct ureg reg )
diff --git a/mesalib/src/mesa/main/format_pack.py b/mesalib/src/mesa/main/format_pack.py
index f141da83c..2f43a30dd 100644
--- a/mesalib/src/mesa/main/format_pack.py
+++ b/mesalib/src/mesa/main/format_pack.py
@@ -43,7 +43,6 @@ string = """/*
#include <stdint.h>
-#include "colormac.h"
#include "format_pack.h"
#include "format_utils.h"
#include "macros.h"
diff --git a/mesalib/src/mesa/main/format_unpack.h b/mesalib/src/mesa/main/format_unpack.h
index eba3c6650..964c6077a 100644
--- a/mesalib/src/mesa/main/format_unpack.h
+++ b/mesalib/src/mesa/main/format_unpack.h
@@ -25,6 +25,8 @@
#ifndef FORMAT_UNPACK_H
#define FORMAT_UNPACK_H
+#include "formats.h"
+
extern void
_mesa_unpack_rgba_row(mesa_format format, GLuint n,
const void *src, GLfloat dst[][4]);
diff --git a/mesalib/src/mesa/main/format_unpack.py b/mesalib/src/mesa/main/format_unpack.py
index 53bdf641d..0ae73b897 100644
--- a/mesalib/src/mesa/main/format_unpack.py
+++ b/mesalib/src/mesa/main/format_unpack.py
@@ -43,7 +43,6 @@ string = """/*
#include <stdint.h>
-#include "colormac.h"
#include "format_unpack.h"
#include "format_utils.h"
#include "macros.h"
@@ -333,7 +332,7 @@ _mesa_unpack_rgba_row(mesa_format format, GLuint n,
unpack_float_ycbcr_rev(src, dst, n);
break;
default:
- _mesa_problem(NULL, "%s: bad format %s", __FUNCTION__,
+ _mesa_problem(NULL, "%s: bad format %s", __func__,
_mesa_get_format_name(format));
return;
}
@@ -402,7 +401,7 @@ _mesa_unpack_uint_rgba_row(mesa_format format, GLuint n,
break;
%endfor
default:
- _mesa_problem(NULL, "%s: bad format %s", __FUNCTION__,
+ _mesa_problem(NULL, "%s: bad format %s", __func__,
_mesa_get_format_name(format));
return;
}
diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c
index 4e05229cf..8ced57949 100644
--- a/mesalib/src/mesa/main/glformats.c
+++ b/mesalib/src/mesa/main/glformats.c
@@ -1393,7 +1393,7 @@ _mesa_base_format_has_channel(GLenum base_format, GLenum pname)
return GL_FALSE;
default:
_mesa_warning(NULL, "%s: Unexpected channel token 0x%x\n",
- __FUNCTION__, pname);
+ __func__, pname);
return GL_FALSE;
}
diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h
index 8877966ec..27f54d585 100755
--- a/mesalib/src/mesa/main/imports.h
+++ b/mesalib/src/mesa/main/imports.h
@@ -432,6 +432,30 @@ _mesa_fls(unsigned int n)
#endif
}
+/**
+ * Find the last (most significant) bit set in a uint64_t value.
+ *
+ * Essentially ffsll() in the reverse direction.
+ */
+static inline unsigned int
+_mesa_flsll(uint64_t n)
+{
+#ifdef HAVE___BUILTIN_CLZLL
+ return n == 0 ? 0 : 64 - __builtin_clzll(n);
+#else
+ unsigned int v = 1;
+
+ if (n == 0)
+ return 0;
+
+ while (n >>= 1)
+ v++;
+
+ return v;
+#endif
+}
+
+
extern GLhalfARB
_mesa_float_to_half(float f);
diff --git a/mesalib/src/mesa/main/macros.h b/mesalib/src/mesa/main/macros.h
index b22510965..5680b2ee1 100755
--- a/mesalib/src/mesa/main/macros.h
+++ b/mesalib/src/mesa/main/macros.h
@@ -789,7 +789,14 @@ NORMALIZE_3FV(GLfloat v[3])
static inline GLboolean
DIFFERENT_SIGNS(GLfloat x, GLfloat y)
{
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 6334 ) /* sizeof operator applied to an expression with an operator may yield unexpected results */
+#endif
return signbit(x) != signbit(y);
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
}
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 8e1dba6f0..1c751cfff 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -42,6 +42,7 @@
#include "main/config.h"
#include "glapi/glapi.h"
#include "math/m_matrix.h" /* GLmatrix */
+#include "glsl/shader_enums.h"
#include "util/simple_list.h" /* struct simple_node */
#include "main/formats.h" /* MESA_FORMAT_COUNT */
@@ -280,13 +281,6 @@ typedef enum
/*@}*/
/**
- * Bitflags for system values.
- */
-#define SYSTEM_BIT_SAMPLE_ID BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_ID)
-#define SYSTEM_BIT_SAMPLE_POS BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_POS)
-#define SYSTEM_BIT_SAMPLE_MASK_IN BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_MASK_IN)
-
-/**
* Determine if the given gl_varying_slot appears in the fragment shader.
*/
static inline GLboolean
@@ -395,25 +389,6 @@ typedef enum
BUFFER_BIT_COLOR6 | \
BUFFER_BIT_COLOR7)
-
-/**
- * Shader stages. Note that these will become 5 with tessellation.
- *
- * The order must match how shaders are ordered in the pipeline.
- * The GLSL linker assumes that if i<j, then the j-th shader is
- * executed later than the i-th shader.
- */
-typedef enum
-{
- MESA_SHADER_VERTEX = 0,
- MESA_SHADER_GEOMETRY = 1,
- MESA_SHADER_FRAGMENT = 2,
- MESA_SHADER_COMPUTE = 3,
-} gl_shader_stage;
-
-#define MESA_SHADER_STAGES (MESA_SHADER_COMPUTE + 1)
-
-
/**
* Framebuffer configuration (aka visual / pixelformat)
* Note: some of these fields should be boolean, but it appears that
@@ -1456,7 +1431,6 @@ struct gl_viewport_attrib
GLfloat X, Y; /**< position */
GLfloat Width, Height; /**< size */
GLdouble Near, Far; /**< Depth buffer range */
- GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */
};
@@ -2082,140 +2056,6 @@ typedef enum
/**
- * If the register file is PROGRAM_SYSTEM_VALUE, the register index will be
- * one of these values.
- */
-typedef enum
-{
- /**
- * \name Vertex shader system values
- */
- /*@{*/
- /**
- * OpenGL-style vertex ID.
- *
- * Section 2.11.7 (Shader Execution), subsection Shader Inputs, of the
- * OpenGL 3.3 core profile spec says:
- *
- * "gl_VertexID holds the integer index i implicitly passed by
- * DrawArrays or one of the other drawing commands defined in section
- * 2.8.3."
- *
- * Section 2.8.3 (Drawing Commands) of the same spec says:
- *
- * "The commands....are equivalent to the commands with the same base
- * name (without the BaseVertex suffix), except that the ith element
- * transferred by the corresponding draw call will be taken from
- * element indices[i] + basevertex of each enabled array."
- *
- * Additionally, the overview in the GL_ARB_shader_draw_parameters spec
- * says:
- *
- * "In unextended GL, vertex shaders have inputs named gl_VertexID and
- * gl_InstanceID, which contain, respectively the index of the vertex
- * and instance. The value of gl_VertexID is the implicitly passed
- * index of the vertex being processed, which includes the value of
- * baseVertex, for those commands that accept it."
- *
- * gl_VertexID gets basevertex added in. This differs from DirectX where
- * SV_VertexID does \b not get basevertex added in.
- *
- * \note
- * If all system values are available, \c SYSTEM_VALUE_VERTEX_ID will be
- * equal to \c SYSTEM_VALUE_VERTEX_ID_ZERO_BASE plus
- * \c SYSTEM_VALUE_BASE_VERTEX.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, SYSTEM_VALUE_BASE_VERTEX
- */
- SYSTEM_VALUE_VERTEX_ID,
-
- /**
- * Instanced ID as supplied to gl_InstanceID
- *
- * Values assigned to gl_InstanceID always begin with zero, regardless of
- * the value of baseinstance.
- *
- * Section 11.1.3.9 (Shader Inputs) of the OpenGL 4.4 core profile spec
- * says:
- *
- * "gl_InstanceID holds the integer instance number of the current
- * primitive in an instanced draw call (see section 10.5)."
- *
- * Through a big chain of pseudocode, section 10.5 describes that
- * baseinstance is not counted by gl_InstanceID. In that section, notice
- *
- * "If an enabled vertex attribute array is instanced (it has a
- * non-zero divisor as specified by VertexAttribDivisor), the element
- * index that is transferred to the GL, for all vertices, is given by
- *
- * floor(instance/divisor) + baseinstance
- *
- * If an array corresponding to an attribute required by a vertex
- * shader is not enabled, then the corresponding element is taken from
- * the current attribute state (see section 10.2)."
- *
- * Note that baseinstance is \b not included in the value of instance.
- */
- SYSTEM_VALUE_INSTANCE_ID,
-
- /**
- * DirectX-style vertex ID.
- *
- * Unlike \c SYSTEM_VALUE_VERTEX_ID, this system value does \b not include
- * the value of basevertex.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_BASE_VERTEX
- */
- SYSTEM_VALUE_VERTEX_ID_ZERO_BASE,
-
- /**
- * Value of \c basevertex passed to \c glDrawElementsBaseVertex and similar
- * functions.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE
- */
- SYSTEM_VALUE_BASE_VERTEX,
- /*@}*/
-
- /**
- * \name Geometry shader system values
- */
- /*@{*/
- SYSTEM_VALUE_INVOCATION_ID,
- /*@}*/
-
- /**
- * \name Fragment shader system values
- */
- /*@{*/
- SYSTEM_VALUE_FRONT_FACE, /**< (not done yet) */
- SYSTEM_VALUE_SAMPLE_ID,
- SYSTEM_VALUE_SAMPLE_POS,
- SYSTEM_VALUE_SAMPLE_MASK_IN,
- /*@}*/
-
- SYSTEM_VALUE_MAX /**< Number of values */
-} gl_system_value;
-
-
-/**
- * The possible interpolation qualifiers that can be applied to a fragment
- * shader input in GLSL.
- *
- * Note: INTERP_QUALIFIER_NONE must be 0 so that memsetting the
- * gl_fragment_program data structure to 0 causes the default behavior.
- */
-enum glsl_interp_qualifier
-{
- INTERP_QUALIFIER_NONE = 0,
- INTERP_QUALIFIER_SMOOTH,
- INTERP_QUALIFIER_FLAT,
- INTERP_QUALIFIER_NOPERSPECTIVE,
- INTERP_QUALIFIER_COUNT /**< Number of interpolation qualifiers */
-};
-
-
-/**
* \brief Layout qualifiers for gl_FragDepth.
*
* Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with
@@ -2247,6 +2087,8 @@ struct gl_program
struct prog_instruction *Instructions;
+ struct nir_shader *nir;
+
GLbitfield64 InputsRead; /**< Bitmask of which input regs are read */
GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */
GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */
@@ -2762,6 +2604,16 @@ struct gl_active_atomic_buffer
};
/**
+ * Active resource in a gl_shader_program
+ */
+struct gl_program_resource
+{
+ GLenum Type; /** Program interface type. */
+ const void *Data; /** Pointer to resource associated data structure. */
+ uint8_t StageReferences; /** Bitmask of shader stage references. */
+};
+
+/**
* A GLSL program object.
* Basically a linked collection of vertex and fragment shaders.
*/
@@ -2935,6 +2787,10 @@ struct gl_shader_program
*/
struct gl_shader *_LinkedShaders[MESA_SHADER_STAGES];
+ /** List of all active resources after linking. */
+ struct gl_program_resource *ProgramResourceList;
+ unsigned NumProgramResourceList;
+
/* True if any of the fragment shaders attached to this program use:
* #extension ARB_fragment_coord_conventions: enable
*/
@@ -3527,8 +3383,8 @@ struct gl_constants
GLboolean ForceGLSLExtensionsWarn;
/**
- * If non-zero, forces GLSL shaders without the #version directive to behave
- * as if they began with "#version ForceGLSLVersion".
+ * If non-zero, forces GLSL shaders to behave as if they began
+ * with "#version ForceGLSLVersion".
*/
GLuint ForceGLSLVersion;
@@ -4523,7 +4379,7 @@ struct gl_context
#ifdef DEBUG
extern int MESA_VERBOSE;
extern int MESA_DEBUG_FLAGS;
-# define MESA_FUNCTION __FUNCTION__
+# define MESA_FUNCTION __func__
#else
# define MESA_VERBOSE 0
# define MESA_DEBUG_FLAGS 0
diff --git a/mesalib/src/mesa/main/multisample.c b/mesalib/src/mesa/main/multisample.c
index 0e9207bc1..816837b95 100644
--- a/mesalib/src/mesa/main/multisample.c
+++ b/mesalib/src/mesa/main/multisample.c
@@ -150,6 +150,15 @@ GLenum
_mesa_check_sample_count(struct gl_context *ctx, GLenum target,
GLenum internalFormat, GLsizei samples)
{
+ /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
+ *
+ * "If a negative number is provided where an argument of type sizei or
+ * sizeiptr is specified, the error INVALID VALUE is generated."
+ */
+ if (samples < 0) {
+ return GL_INVALID_VALUE;
+ }
+
/* Section 4.4 (Framebuffer objects), page 198 of the OpenGL ES 3.0.0
* specification says:
*
diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c
index fb241af1e..0fefa7d56 100644
--- a/mesalib/src/mesa/main/pipelineobj.c
+++ b/mesalib/src/mesa/main/pipelineobj.c
@@ -498,16 +498,18 @@ _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines)
* \param n Number of IDs to generate.
* \param pipelines pipeline of \c n locations to store the IDs.
*/
-void GLAPIENTRY
-_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
+static void
+create_program_pipelines(struct gl_context *ctx, GLsizei n, GLuint *pipelines,
+ bool dsa)
{
- GET_CURRENT_CONTEXT(ctx);
-
+ const char *func;
GLuint first;
GLint i;
+ func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines";
+
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramPipelines(n<0)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func);
return;
}
@@ -523,16 +525,37 @@ _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
obj = _mesa_new_pipeline_object(ctx, name);
if (!obj) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramPipelines");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
return;
}
+ if (dsa) {
+ /* make dsa-allocated objects behave like program objects */
+ obj->EverBound = GL_TRUE;
+ }
+
save_pipeline_object(ctx, obj);
pipelines[i] = first + i;
}
}
+void GLAPIENTRY
+_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ create_program_pipelines(ctx, n, pipelines, false);
+}
+
+void GLAPIENTRY
+_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ create_program_pipelines(ctx, n, pipelines, true);
+}
+
/**
* Determine if ID is the name of an pipeline object.
*
diff --git a/mesalib/src/mesa/main/pipelineobj.h b/mesalib/src/mesa/main/pipelineobj.h
index 7285a78f1..b57bcb99e 100644
--- a/mesalib/src/mesa/main/pipelineobj.h
+++ b/mesalib/src/mesa/main/pipelineobj.h
@@ -82,6 +82,9 @@ _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines);
extern void GLAPIENTRY
_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines);
+void GLAPIENTRY
+_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines);
+
extern GLboolean GLAPIENTRY
_mesa_IsProgramPipeline(GLuint pipeline);
diff --git a/mesalib/src/mesa/main/pixel.c b/mesalib/src/mesa/main/pixel.c
index 7162c6fef..ecda2694f 100644
--- a/mesalib/src/mesa/main/pixel.c
+++ b/mesalib/src/mesa/main/pixel.c
@@ -30,7 +30,6 @@
#include "glheader.h"
#include "bufferobj.h"
-#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "pixel.h"
diff --git a/mesalib/src/mesa/main/pixeltransfer.c b/mesalib/src/mesa/main/pixeltransfer.c
index 8bbeeb853..94464ea67 100644
--- a/mesalib/src/mesa/main/pixeltransfer.c
+++ b/mesalib/src/mesa/main/pixeltransfer.c
@@ -31,7 +31,7 @@
#include "glheader.h"
-#include "colormac.h"
+#include "macros.h"
#include "pixeltransfer.h"
#include "imports.h"
#include "mtypes.h"
diff --git a/mesalib/src/mesa/main/program_resource.c b/mesalib/src/mesa/main/program_resource.c
new file mode 100644
index 000000000..b15a13210
--- /dev/null
+++ b/mesalib/src/mesa/main/program_resource.c
@@ -0,0 +1,417 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
+#include "program_resource.h"
+
+static bool
+supported_interface_enum(GLenum iface)
+{
+ switch (iface) {
+ case GL_UNIFORM:
+ case GL_UNIFORM_BLOCK:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return true;
+ case GL_VERTEX_SUBROUTINE:
+ case GL_TESS_CONTROL_SUBROUTINE:
+ case GL_TESS_EVALUATION_SUBROUTINE:
+ case GL_GEOMETRY_SUBROUTINE:
+ case GL_FRAGMENT_SUBROUTINE:
+ case GL_COMPUTE_SUBROUTINE:
+ case GL_VERTEX_SUBROUTINE_UNIFORM:
+ case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+ case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
+ case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+ case GL_FRAGMENT_SUBROUTINE_UNIFORM:
+ case GL_COMPUTE_SUBROUTINE_UNIFORM:
+ case GL_BUFFER_VARIABLE:
+ case GL_SHADER_STORAGE_BLOCK:
+ default:
+ return false;
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ unsigned i;
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "glGetProgramInterfaceiv");
+ if (!shProg)
+ return;
+
+ if (!params) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramInterfaceiv(params NULL)");
+ return;
+ }
+
+ /* Validate interface. */
+ if (!supported_interface_enum(programInterface)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
+ _mesa_lookup_enum_by_nr(programInterface));
+ return;
+ }
+
+ /* Validate pname against interface. */
+ switch(pname) {
+ case GL_ACTIVE_RESOURCES:
+ for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++)
+ if (shProg->ProgramResourceList[i].Type == programInterface)
+ (*params)++;
+ break;
+ case GL_MAX_NAME_LENGTH:
+ if (programInterface == GL_ATOMIC_COUNTER_BUFFER) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramInterfaceiv(%s pname %s)",
+ _mesa_lookup_enum_by_nr(programInterface),
+ _mesa_lookup_enum_by_nr(pname));
+ return;
+ }
+ /* Name length consists of base name, 3 additional chars '[0]' if
+ * resource is an array and finally 1 char for string terminator.
+ */
+ for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+ if (shProg->ProgramResourceList[i].Type != programInterface)
+ continue;
+ const char *name =
+ _mesa_program_resource_name(&shProg->ProgramResourceList[i]);
+ unsigned array_size =
+ _mesa_program_resource_array_size(&shProg->ProgramResourceList[i]);
+ *params = MAX2(*params, strlen(name) + (array_size ? 3 : 0) + 1);
+ }
+ break;
+ case GL_MAX_NUM_ACTIVE_VARIABLES:
+ switch (programInterface) {
+ case GL_UNIFORM_BLOCK:
+ for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+ if (shProg->ProgramResourceList[i].Type == programInterface) {
+ struct gl_uniform_block *block =
+ (struct gl_uniform_block *)
+ shProg->ProgramResourceList[i].Data;
+ *params = MAX2(*params, block->NumUniforms);
+ }
+ }
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+ if (shProg->ProgramResourceList[i].Type == programInterface) {
+ struct gl_active_atomic_buffer *buffer =
+ (struct gl_active_atomic_buffer *)
+ shProg->ProgramResourceList[i].Data;
+ *params = MAX2(*params, buffer->NumUniforms);
+ }
+ }
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramInterfaceiv(%s pname %s)",
+ _mesa_lookup_enum_by_nr(programInterface),
+ _mesa_lookup_enum_by_nr(pname));
+ };
+ break;
+ case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
+ default:
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramInterfaceiv(pname %s)",
+ _mesa_lookup_enum_by_nr(pname));
+ }
+}
+
+static bool
+is_xfb_marker(const char *str)
+{
+ static const char *markers[] = {
+ "gl_NextBuffer",
+ "gl_SkipComponents1",
+ "gl_SkipComponents2",
+ "gl_SkipComponents3",
+ "gl_SkipComponents4",
+ NULL
+ };
+ const char **m = markers;
+
+ if (strncmp(str, "gl_", 3) != 0)
+ return false;
+
+ for (; *m; m++)
+ if (strcmp(*m, str) == 0)
+ return true;
+
+ return false;
+}
+
+/**
+ * Checks if given name index is legal for GetProgramResourceIndex,
+ * check is written to be compatible with GL_ARB_array_of_arrays.
+ */
+static bool
+valid_program_resource_index_name(const GLchar *name)
+{
+ const char *array = strstr(name, "[");
+ const char *close = strrchr(name, ']');
+
+ /* Not array, no need for the check. */
+ if (!array)
+ return true;
+
+ /* Last array index has to be zero. */
+ if (!close || *--close != '0')
+ return false;
+
+ return true;
+}
+
+GLuint GLAPIENTRY
+_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
+ const GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_program_resource *res;
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "glGetProgramResourceIndex");
+ if (!shProg || !name)
+ return GL_INVALID_INDEX;
+
+ /*
+ * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
+ * should be returned when querying the index assigned to the special names
+ * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
+ * "gl_SkipComponents3", and "gl_SkipComponents4".
+ */
+ if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING &&
+ is_xfb_marker(name))
+ return GL_INVALID_INDEX;
+
+ switch (programInterface) {
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_UNIFORM:
+ case GL_UNIFORM_BLOCK:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ /* Validate name syntax for arrays. */
+ if (!valid_program_resource_index_name(name))
+ return GL_INVALID_INDEX;
+
+ res = _mesa_program_resource_find_name(shProg, programInterface, name);
+ if (!res)
+ return GL_INVALID_INDEX;
+
+ return _mesa_program_resource_index(shProg, res);
+ case GL_ATOMIC_COUNTER_BUFFER:
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
+ _mesa_lookup_enum_by_nr(programInterface));
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+void GLAPIENTRY
+_mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
+ GLuint index, GLsizei bufSize, GLsizei *length,
+ GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "glGetProgramResourceName");
+
+ /* Set user friendly return values in case of errors. */
+ if (name)
+ *name = '\0';
+ if (length)
+ *length = 0;
+
+ if (!shProg || !name)
+ return;
+
+ if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
+ !supported_interface_enum(programInterface)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
+ _mesa_lookup_enum_by_nr(programInterface));
+ return;
+ }
+
+ _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
+ length, name, "glGetProgramResourceName");
+}
+
+void GLAPIENTRY
+_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
+ GLuint index, GLsizei propCount,
+ const GLenum *props, GLsizei bufSize,
+ GLsizei *length, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
+
+ if (!shProg || !params)
+ return;
+
+ /* The error INVALID_VALUE is generated if <propCount> is zero.
+ * Note that we check < 0 here because it makes sense to bail early.
+ */
+ if (propCount <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetProgramResourceiv(propCount <= 0)");
+ return;
+ }
+
+ /* No need to write any properties, user requested none. */
+ if (bufSize == 0)
+ return;
+
+ _mesa_get_program_resourceiv(shProg, programInterface, index,
+ propCount, props, bufSize, length, params);
+}
+
+/**
+ * Function verifies syntax of given name for GetProgramResourceLocation
+ * and GetProgramResourceLocationIndex for the following cases:
+ *
+ * "array element portion of a string passed to GetProgramResourceLocation
+ * or GetProgramResourceLocationIndex must not have, a "+" sign, extra
+ * leading zeroes, or whitespace".
+ *
+ * Check is written to be compatible with GL_ARB_array_of_arrays.
+ */
+static bool
+invalid_array_element_syntax(const GLchar *name)
+{
+ char *first = strchr(name, '[');
+ char *last = strrchr(name, '[');
+
+ if (!first)
+ return false;
+
+ /* No '+' or ' ' allowed anywhere. */
+ if (strchr(first, '+') || strchr(first, ' '))
+ return true;
+
+ /* Check that last array index is 0. */
+ if (last[1] == '0' && last[2] != ']')
+ return true;
+
+ return false;
+}
+
+static struct gl_shader_program *
+lookup_linked_program(GLuint program, const char *caller)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *prog =
+ _mesa_lookup_shader_program_err(ctx, program, caller);
+
+ if (!prog)
+ return NULL;
+
+ if (prog->LinkStatus == GL_FALSE) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
+ caller);
+ return NULL;
+ }
+ return prog;
+}
+
+GLint GLAPIENTRY
+_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
+ const GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ lookup_linked_program(program, "glGetProgramResourceLocation");
+
+ if (!shProg || !name || invalid_array_element_syntax(name))
+ return -1;
+
+ /* Validate programInterface. */
+ switch (programInterface) {
+ case GL_UNIFORM:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ break;
+
+ /* For reference valid cases requiring additional extension support:
+ * GL_ARB_shader_subroutine
+ * GL_ARB_tessellation_shader
+ * GL_ARB_compute_shader
+ */
+ case GL_VERTEX_SUBROUTINE_UNIFORM:
+ case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+ case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
+ case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+ case GL_FRAGMENT_SUBROUTINE_UNIFORM:
+ case GL_COMPUTE_SUBROUTINE_UNIFORM:
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
+ _mesa_lookup_enum_by_nr(programInterface), name);
+ }
+
+ return _mesa_program_resource_location(shProg, programInterface, name);
+}
+
+/**
+ * Returns output index for dual source blending.
+ */
+GLint GLAPIENTRY
+_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
+ const GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ lookup_linked_program(program, "glGetProgramResourceLocationIndex");
+
+ if (!shProg || !name || invalid_array_element_syntax(name))
+ return -1;
+
+ /* From the GL_ARB_program_interface_query spec:
+ *
+ * "For GetProgramResourceLocationIndex, <programInterface> must be
+ * PROGRAM_OUTPUT."
+ */
+ if (programInterface != GL_PROGRAM_OUTPUT) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetProgramResourceLocationIndex(%s)",
+ _mesa_lookup_enum_by_nr(programInterface));
+ return -1;
+ }
+
+ return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
+ name);
+}
diff --git a/mesalib/src/mesa/main/program_resource.h b/mesalib/src/mesa/main/program_resource.h
new file mode 100644
index 000000000..326ae1f93
--- /dev/null
+++ b/mesalib/src/mesa/main/program_resource.h
@@ -0,0 +1,58 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef PROGRAM_RESOURCE_H
+#define PROGRAM_RESOURCE_H
+
+#include "glheader.h"
+
+extern void GLAPIENTRY
+_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
+ GLenum pname, GLint *params);
+
+extern GLuint GLAPIENTRY
+_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
+ const GLchar *name);
+
+extern void GLAPIENTRY
+_mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
+ GLuint index, GLsizei bufSize, GLsizei *length,
+ GLchar *name);
+
+extern void GLAPIENTRY
+_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
+ GLuint index, GLsizei propCount,
+ const GLenum *props, GLsizei bufSize,
+ GLsizei *length, GLint *params);
+
+extern GLint GLAPIENTRY
+_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
+ const GLchar *name);
+
+extern GLint GLAPIENTRY
+_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
+ const GLchar *name);
+
+#endif
diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c
index 9ecc7d3b5..12363de7b 100755
--- a/mesalib/src/mesa/main/queryobj.c
+++ b/mesalib/src/mesa/main/queryobj.c
@@ -233,18 +233,22 @@ get_query_binding_point(struct gl_context *ctx, GLenum target, GLuint index)
}
}
-
-void GLAPIENTRY
-_mesa_GenQueries(GLsizei n, GLuint *ids)
+/**
+ * Create $n query objects and store them in *ids. Make them of type $target
+ * if dsa is set. Called from _mesa_GenQueries() and _mesa_CreateQueries().
+ */
+static void
+create_queries(struct gl_context *ctx, GLenum target, GLsizei n, GLuint *ids,
+ bool dsa)
{
+ const char *func = dsa ? "glGenQueries" : "glCreateQueries";
GLuint first;
- GET_CURRENT_CONTEXT(ctx);
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glGenQueries(%d)\n", n);
+ _mesa_debug(ctx, "%s(%d)\n", func, n);
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
return;
}
@@ -255,8 +259,12 @@ _mesa_GenQueries(GLsizei n, GLuint *ids)
struct gl_query_object *q
= ctx->Driver.NewQueryObject(ctx, first + i);
if (!q) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
return;
+ } else if (dsa) {
+ /* Do the equivalent of binding the buffer with a target */
+ q->Target = target;
+ q->EverBound = GL_TRUE;
}
ids[i] = first + i;
_mesa_HashInsert(ctx->Query.QueryObjects, first + i, q);
@@ -264,6 +272,36 @@ _mesa_GenQueries(GLsizei n, GLuint *ids)
}
}
+void GLAPIENTRY
+_mesa_GenQueries(GLsizei n, GLuint *ids)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_queries(ctx, 0, n, ids, false);
+}
+
+void GLAPIENTRY
+_mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ switch (target) {
+ case GL_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ case GL_TIME_ELAPSED:
+ case GL_TIMESTAMP:
+ case GL_PRIMITIVES_GENERATED:
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCreateQueries(invalid target = %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
+ create_queries(ctx, target, n, ids, true);
+}
+
void GLAPIENTRY
_mesa_DeleteQueries(GLsizei n, const GLuint *ids)
@@ -424,6 +462,18 @@ _mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id)
}
}
+ /* This possibly changes the target of a buffer allocated by
+ * CreateQueries. Issue 39) in the ARB_direct_state_access extension states
+ * the following:
+ *
+ * "CreateQueries adds a <target>, so strictly speaking the <target>
+ * command isn't needed for BeginQuery/EndQuery, but in the end, this also
+ * isn't a selector, so we decided not to change it."
+ *
+ * Updating the target of the query object should be acceptable, so let's
+ * do that.
+ */
+
q->Target = target;
q->Active = GL_TRUE;
q->Result = 0;
@@ -541,6 +591,18 @@ _mesa_QueryCounter(GLuint id, GLenum target)
return;
}
+ /* This possibly changes the target of a buffer allocated by
+ * CreateQueries. Issue 39) in the ARB_direct_state_access extension states
+ * the following:
+ *
+ * "CreateQueries adds a <target>, so strictly speaking the <target>
+ * command isn't needed for BeginQuery/EndQuery, but in the end, this also
+ * isn't a selector, so we decided not to change it."
+ *
+ * Updating the target of the query object should be acceptable, so let's
+ * do that.
+ */
+
q->Target = target;
q->Result = 0;
q->Ready = GL_FALSE;
@@ -710,8 +772,8 @@ _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params)
}
break;
case GL_QUERY_RESULT_AVAILABLE_ARB:
- if (!q->Ready)
- ctx->Driver.CheckQuery( ctx, q );
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
default:
@@ -761,8 +823,8 @@ _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
}
break;
case GL_QUERY_RESULT_AVAILABLE_ARB:
- if (!q->Ready)
- ctx->Driver.CheckQuery( ctx, q );
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
default:
@@ -801,8 +863,8 @@ _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params)
*params = q->Result;
break;
case GL_QUERY_RESULT_AVAILABLE_ARB:
- if (!q->Ready)
- ctx->Driver.CheckQuery( ctx, q );
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
default:
@@ -841,8 +903,8 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params)
*params = q->Result;
break;
case GL_QUERY_RESULT_AVAILABLE_ARB:
- if (!q->Ready)
- ctx->Driver.CheckQuery( ctx, q );
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
default:
@@ -852,6 +914,45 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params)
}
/**
+ * New with GL_ARB_query_buffer_object
+ */
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectiv");
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectuiv");
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjecti64v");
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectui64v");
+}
+
+
+/**
* Allocate/init the context state related to query objects.
*/
void
diff --git a/mesalib/src/mesa/main/queryobj.h b/mesalib/src/mesa/main/queryobj.h
index 6cbcabd46..d1036fcce 100644
--- a/mesalib/src/mesa/main/queryobj.h
+++ b/mesalib/src/mesa/main/queryobj.h
@@ -51,6 +51,8 @@ _mesa_free_queryobj_data(struct gl_context *ctx);
void GLAPIENTRY
_mesa_GenQueries(GLsizei n, GLuint *ids);
void GLAPIENTRY
+_mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids);
+void GLAPIENTRY
_mesa_DeleteQueries(GLsizei n, const GLuint *ids);
GLboolean GLAPIENTRY
_mesa_IsQuery(GLuint id);
@@ -77,5 +79,17 @@ void GLAPIENTRY
_mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params);
void GLAPIENTRY
_mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params);
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset);
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset);
+void GLAPIENTRY
+_mesa_GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset);
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset);
#endif /* QUERYOBJ_H */
diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c
index d66b0b5e8..a3aacc66a 100644
--- a/mesalib/src/mesa/main/samplerobj.c
+++ b/mesalib/src/mesa/main/samplerobj.c
@@ -181,19 +181,18 @@ _mesa_delete_sampler_object(struct gl_context *ctx,
free(sampObj);
}
-
-void GLAPIENTRY
-_mesa_GenSamplers(GLsizei count, GLuint *samplers)
+static void
+create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers,
+ const char *caller)
{
- GET_CURRENT_CONTEXT(ctx);
GLuint first;
GLint i;
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glGenSamplers(%d)\n", count);
+ _mesa_debug(ctx, "%s(%d)\n", caller, count);
if (count < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller);
return;
}
@@ -211,6 +210,20 @@ _mesa_GenSamplers(GLsizei count, GLuint *samplers)
}
}
+void GLAPIENTRY
+_mesa_GenSamplers(GLsizei count, GLuint *samplers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_samplers(ctx, count, samplers, "glGenSamplers");
+}
+
+void GLAPIENTRY
+_mesa_CreateSamplers(GLsizei count, GLuint *samplers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_samplers(ctx, count, samplers, "glCreateSamplers");
+}
+
void GLAPIENTRY
_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
diff --git a/mesalib/src/mesa/main/samplerobj.h b/mesalib/src/mesa/main/samplerobj.h
index 1bb3193e4..7bea91114 100644
--- a/mesalib/src/mesa/main/samplerobj.h
+++ b/mesalib/src/mesa/main/samplerobj.h
@@ -32,6 +32,9 @@ extern "C" {
#endif
+#include "mtypes.h"
+
+
struct dd_function_table;
static inline struct gl_sampler_object *
@@ -80,6 +83,8 @@ _mesa_init_sampler_object_functions(struct dd_function_table *driver);
void GLAPIENTRY
_mesa_GenSamplers(GLsizei count, GLuint *samplers);
void GLAPIENTRY
+_mesa_CreateSamplers(GLsizei count, GLuint *samplers);
+void GLAPIENTRY
_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers);
GLboolean GLAPIENTRY
_mesa_IsSampler(GLuint sampler);
diff --git a/mesalib/src/mesa/main/shader_query.cpp b/mesalib/src/mesa/main/shader_query.cpp
index df9081b73..b5f1d082c 100644
--- a/mesalib/src/mesa/main/shader_query.cpp
+++ b/mesalib/src/mesa/main/shader_query.cpp
@@ -34,11 +34,33 @@
#include "shaderobj.h"
#include "program/hash_table.h"
#include "../glsl/program.h"
+#include "uniforms.h"
+#include "main/enums.h"
extern "C" {
#include "shaderapi.h"
}
+static GLint
+program_resource_location(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, const char *name);
+
+/**
+ * Declare convenience functions to return resource data in a given type.
+ * Warning! this is not type safe so be *very* careful when using these.
+ */
+#define DECL_RESOURCE_FUNC(name, type) \
+const type * RESOURCE_ ## name (gl_program_resource *res) { \
+ assert(res->Data); \
+ return (type *) res->Data; \
+}
+
+DECL_RESOURCE_FUNC(VAR, ir_variable);
+DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
+DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
+DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
+DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info);
+
void GLAPIENTRY
_mesa_BindAttribLocation(GLhandleARB program, GLuint index,
const GLcharARB *name)
@@ -129,45 +151,41 @@ _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index,
return;
}
- exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
- unsigned current_index = 0;
-
- foreach_in_list(ir_instruction, node, ir) {
- const ir_variable *const var = node->as_variable();
-
- if (!is_active_attrib(var))
- continue;
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
+ desired_index);
- if (current_index == desired_index) {
- const char *var_name = var->name;
+ /* User asked for index that does not exist. */
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
+ return;
+ }
- /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to
- * consider gl_VertexIDMESA as gl_VertexID for purposes of checking
- * active attributes.
- */
- if (var->data.mode == ir_var_system_value &&
- var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
- var_name = "gl_VertexID";
- }
+ const ir_variable *const var = RESOURCE_VAR(res);
- _mesa_copy_string(name, maxLength, length, var_name);
+ if (!is_active_attrib(var))
+ return;
- if (size)
- *size = (var->type->is_array()) ? var->type->length : 1;
+ const char *var_name = var->name;
- if (type)
- *type = var->type->gl_type;
+ /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to
+ * consider gl_VertexIDMESA as gl_VertexID for purposes of checking
+ * active attributes.
+ */
+ if (var->data.mode == ir_var_system_value &&
+ var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
+ var_name = "gl_VertexID";
+ }
- return;
- }
+ _mesa_copy_string(name, maxLength, length, var_name);
- current_index++;
- }
+ if (size)
+ _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
+ size, "glGetActiveAttrib");
- /* If the loop did not return early, the caller must have asked for
- * an index that did not exit. Set an error.
- */
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
+ if (type)
+ _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
+ (GLint *) type, "glGetActiveAttrib");
}
/* Locations associated with shader variables (array or non-array) can be
@@ -252,31 +270,25 @@ _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name)
if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
return -1;
- exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
- foreach_in_list(ir_instruction, node, ir) {
- const ir_variable *const var = node->as_variable();
-
- /* The extra check against VERT_ATTRIB_GENERIC0 is because
- * glGetAttribLocation cannot be used on "conventional" attributes.
- *
- * From page 95 of the OpenGL 3.0 spec:
- *
- * "If name is not an active attribute, if name is a conventional
- * attribute, or if an error occurs, -1 will be returned."
- */
- if (var == NULL
- || var->data.mode != ir_var_shader_in
- || var->data.location == -1
- || var->data.location < VERT_ATTRIB_GENERIC0)
- continue;
-
- int index = get_matching_index(var, (const char *) name);
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name);
- if (index >= 0)
- return var->data.location + index - VERT_ATTRIB_GENERIC0;
- }
+ if (!res)
+ return -1;
- return -1;
+ GLint loc = program_resource_location(shProg, res, name);
+
+ /* The extra check against against 0 is made because of builtin-attribute
+ * locations that have offset applied. Function program_resource_location
+ * can return built-in attribute locations < 0 and glGetAttribLocation
+ * cannot be used on "conventional" attributes.
+ *
+ * From page 95 of the OpenGL 3.0 spec:
+ *
+ * "If name is not an active attribute, if name is a conventional
+ * attribute, or if an error occurs, -1 will be returned."
+ */
+ return (loc >= 0) ? loc : -1;
}
@@ -416,29 +428,8 @@ _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
return -1;
- exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
- foreach_in_list(ir_instruction, node, ir) {
- const ir_variable *const var = node->as_variable();
-
- /* The extra check against FRAG_RESULT_DATA0 is because
- * glGetFragDataLocation cannot be used on "conventional" attributes.
- *
- * From page 95 of the OpenGL 3.0 spec:
- *
- * "If name is not an active attribute, if name is a conventional
- * attribute, or if an error occurs, -1 will be returned."
- */
- if (var == NULL
- || var->data.mode != ir_var_shader_out
- || var->data.location == -1
- || var->data.location < FRAG_RESULT_DATA0)
- continue;
-
- if (get_matching_index(var, (const char *) name) >= 0)
- return var->data.index;
- }
-
- return -1;
+ return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
+ name);
}
GLint GLAPIENTRY
@@ -472,29 +463,612 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
return -1;
- exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
- foreach_in_list(ir_instruction, node, ir) {
- const ir_variable *const var = node->as_variable();
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name);
- /* The extra check against FRAG_RESULT_DATA0 is because
- * glGetFragDataLocation cannot be used on "conventional" attributes.
- *
- * From page 95 of the OpenGL 3.0 spec:
+ if (!res)
+ return -1;
+
+ GLint loc = program_resource_location(shProg, res, name);
+
+ /* The extra check against against 0 is made because of builtin-attribute
+ * locations that have offset applied. Function program_resource_location
+ * can return built-in attribute locations < 0 and glGetFragDataLocation
+ * cannot be used on "conventional" attributes.
+ *
+ * From page 95 of the OpenGL 3.0 spec:
+ *
+ * "If name is not an active attribute, if name is a conventional
+ * attribute, or if an error occurs, -1 will be returned."
+ */
+ return (loc >= 0) ? loc : -1;
+}
+
+const char*
+_mesa_program_resource_name(struct gl_program_resource *res)
+{
+ switch (res->Type) {
+ case GL_UNIFORM_BLOCK:
+ return RESOURCE_UBO(res)->Name;
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ return RESOURCE_XFB(res)->Name;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ return RESOURCE_VAR(res)->name;
+ case GL_UNIFORM:
+ return RESOURCE_UNI(res)->name;
+ default:
+ assert(!"support for resource type not implemented");
+ }
+ return NULL;
+}
+
+
+unsigned
+_mesa_program_resource_array_size(struct gl_program_resource *res)
+{
+ switch (res->Type) {
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ return RESOURCE_XFB(res)->Size > 1 ?
+ RESOURCE_XFB(res)->Size : 0;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ return RESOURCE_VAR(res)->data.max_array_access;
+ case GL_UNIFORM:
+ return RESOURCE_UNI(res)->array_elements;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_UNIFORM_BLOCK:
+ return 0;
+ default:
+ assert(!"support for resource type not implemented");
+ }
+ return 0;
+}
+
+static int
+array_index_of_resource(struct gl_program_resource *res,
+ const char *name)
+{
+ assert(res->Data);
+
+ switch (res->Type) {
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ return get_matching_index(RESOURCE_VAR(res), name);
+ default:
+ assert(!"support for resource type not implemented");
+ }
+}
+
+/* Find a program resource with specific name in given interface.
+ */
+struct gl_program_resource *
+_mesa_program_resource_find_name(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name)
+{
+ struct gl_program_resource *res = shProg->ProgramResourceList;
+ for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
+ if (res->Type != programInterface)
+ continue;
+
+ /* Resource basename. */
+ const char *rname = _mesa_program_resource_name(res);
+ unsigned baselen = strlen(rname);
+
+ switch (programInterface) {
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_UNIFORM_BLOCK:
+ case GL_UNIFORM:
+ if (strncmp(rname, name, baselen) == 0) {
+ /* Basename match, check if array or struct. */
+ if (name[baselen] == '\0' ||
+ name[baselen] == '[' ||
+ name[baselen] == '.') {
+ return res;
+ }
+ }
+ break;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ if (array_index_of_resource(res, name) >= 0)
+ return res;
+ break;
+ default:
+ assert(!"not implemented for given interface");
+ }
+ }
+ return NULL;
+}
+
+static GLuint
+calc_resource_index(struct gl_shader_program *shProg,
+ struct gl_program_resource *res)
+{
+ unsigned i;
+ GLuint index = 0;
+ for (i = 0; i < shProg->NumProgramResourceList; i++) {
+ if (&shProg->ProgramResourceList[i] == res)
+ return index;
+ if (shProg->ProgramResourceList[i].Type == res->Type)
+ index++;
+ }
+ return GL_INVALID_INDEX;
+}
+
+/**
+ * Calculate index for the given resource.
+ */
+GLuint
+_mesa_program_resource_index(struct gl_shader_program *shProg,
+ struct gl_program_resource *res)
+{
+ if (!res)
+ return GL_INVALID_INDEX;
+
+ switch (res->Type) {
+ case GL_UNIFORM_BLOCK:
+ return RESOURCE_UBO(res)- shProg->UniformBlocks;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return RESOURCE_ATC(res) - shProg->AtomicBuffers;
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ default:
+ return calc_resource_index(shProg, res);
+ }
+}
+
+/* Find a program resource with specific index in given interface.
+ */
+struct gl_program_resource *
+_mesa_program_resource_find_index(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index)
+{
+ struct gl_program_resource *res = shProg->ProgramResourceList;
+ int idx = -1;
+
+ for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
+ if (res->Type != programInterface)
+ continue;
+
+ switch (res->Type) {
+ case GL_UNIFORM_BLOCK:
+ case GL_ATOMIC_COUNTER_BUFFER:
+ if (_mesa_program_resource_index(shProg, res) == index)
+ return res;
+
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_UNIFORM:
+ if (++idx == (int) index)
+ return res;
+ break;
+ default:
+ assert(!"not implemented for given interface");
+ }
+ }
+ return NULL;
+}
+
+/* Get full name of a program resource.
+ */
+bool
+_mesa_get_program_resource_name(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index,
+ GLsizei bufSize, GLsizei *length,
+ GLchar *name, const char *caller)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* Find resource with given interface and index. */
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_index(shProg, programInterface, index);
+
+ /* The error INVALID_VALUE is generated if <index> is greater than
+ * or equal to the number of entries in the active resource list for
+ * <programInterface>.
+ */
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index);
+ return false;
+ }
+
+ if (bufSize < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize);
+ return false;
+ }
+
+ GLsizei localLength;
+
+ if (length == NULL)
+ length = &localLength;
+
+ _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
+
+ /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
+ * spec says:
+ *
+ * "If the active uniform is an array, the uniform name returned in
+ * name will always be the name of the uniform array appended with
+ * "[0]"."
+ *
+ * The same text also appears in the OpenGL 4.2 spec. It does not,
+ * however, appear in any previous spec. Previous specifications are
+ * ambiguous in this regard. However, either name can later be passed
+ * to glGetUniformLocation (and related APIs), so there shouldn't be any
+ * harm in always appending "[0]" to uniform array names.
+ *
+ * Geometry shader stage has different naming convention where the 'normal'
+ * condition is an array, therefore for variables referenced in geometry
+ * stage we do not add '[0]'.
+ *
+ * Note, that TCS outputs and TES inputs should not have index appended
+ * either.
+ */
+ bool add_index = !(((programInterface == GL_PROGRAM_INPUT) &&
+ res->StageReferences & (1 << MESA_SHADER_GEOMETRY)));
+
+ if (add_index && _mesa_program_resource_array_size(res)) {
+ int i;
+
+ /* The comparison is strange because *length does *NOT* include the
+ * terminating NUL, but maxLength does.
+ */
+ for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
+ name[*length + i] = "[0]"[i];
+
+ name[*length + i] = '\0';
+ *length += i;
+ }
+ return true;
+}
+
+static GLint
+program_resource_location(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, const char *name)
+{
+ unsigned index, offset;
+ int array_index = -1;
+
+ if (res->Type == GL_PROGRAM_INPUT || res->Type == GL_PROGRAM_OUTPUT) {
+ array_index = array_index_of_resource(res, name);
+ if (array_index < 0)
+ return -1;
+ }
+
+ /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these
+ * offsets are used internally to differentiate between built-in attributes
+ * and user-defined attributes.
+ */
+ switch (res->Type) {
+ case GL_PROGRAM_INPUT:
+ return RESOURCE_VAR(res)->data.location + array_index - VERT_ATTRIB_GENERIC0;
+ case GL_PROGRAM_OUTPUT:
+ return RESOURCE_VAR(res)->data.location + array_index - FRAG_RESULT_DATA0;
+ case GL_UNIFORM:
+ index = _mesa_get_uniform_location(shProg, name, &offset);
+
+ if (index == GL_INVALID_INDEX)
+ return -1;
+
+ /* From the GL_ARB_uniform_buffer_object spec:
*
- * "If name is not an active attribute, if name is a conventional
- * attribute, or if an error occurs, -1 will be returned."
+ * "The value -1 will be returned if <name> does not correspond to an
+ * active uniform variable name in <program>, if <name> is associated
+ * with a named uniform block, or if <name> starts with the reserved
+ * prefix "gl_"."
*/
- if (var == NULL
- || var->data.mode != ir_var_shader_out
- || var->data.location == -1
- || var->data.location < FRAG_RESULT_DATA0)
- continue;
+ if (RESOURCE_UNI(res)->block_index != -1 ||
+ RESOURCE_UNI(res)->atomic_buffer_index != -1)
+ return -1;
- int index = get_matching_index(var, (const char *) name);
+ /* location in remap table + array element offset */
+ return RESOURCE_UNI(res)->remap_location + offset;
- if (index >= 0)
- return var->data.location + index - FRAG_RESULT_DATA0;
+ default:
+ return -1;
}
+}
- return -1;
+/**
+ * Function implements following location queries:
+ * glGetAttribLocation
+ * glGetFragDataLocation
+ * glGetUniformLocation
+ */
+GLint
+_mesa_program_resource_location(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name)
+{
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, programInterface, name);
+
+ /* Resource not found. */
+ if (!res)
+ return -1;
+
+ return program_resource_location(shProg, res, name);
+}
+
+/**
+ * Function implements following index queries:
+ * glGetFragDataIndex
+ */
+GLint
+_mesa_program_resource_location_index(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name)
+{
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, programInterface, name);
+
+ /* Non-existent variable or resource is not referenced by fragment stage. */
+ if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
+ return -1;
+
+ return RESOURCE_VAR(res)->data.index;
+}
+
+static uint8_t
+stage_from_enum(GLenum ref)
+{
+ switch (ref) {
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return MESA_SHADER_VERTEX;
+ case GL_REFERENCED_BY_GEOMETRY_SHADER:
+ return MESA_SHADER_GEOMETRY;
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ return MESA_SHADER_FRAGMENT;
+ default:
+ assert(!"shader stage not supported");
+ return MESA_SHADER_STAGES;
+ }
+}
+
+/**
+ * Check if resource is referenced by given 'referenced by' stage enum.
+ * ATC and UBO resources hold stage references of their own.
+ */
+static bool
+is_resource_referenced(struct gl_shader_program *shProg,
+ struct gl_program_resource *res,
+ GLuint index, uint8_t stage)
+{
+ if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
+ return RESOURCE_ATC(res)->StageReferences[stage];
+
+ if (res->Type == GL_UNIFORM_BLOCK)
+ return shProg->UniformBlockStageIndex[stage][index] != -1;
+
+ return res->StageReferences & (1 << stage);
+}
+
+static unsigned
+get_buffer_property(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, const GLenum prop,
+ GLint *val, const char *caller)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (res->Type != GL_UNIFORM_BLOCK &&
+ res->Type != GL_ATOMIC_COUNTER_BUFFER)
+ goto invalid_operation;
+
+ if (res->Type == GL_UNIFORM_BLOCK) {
+ switch (prop) {
+ case GL_BUFFER_BINDING:
+ *val = RESOURCE_UBO(res)->Binding;
+ return 1;
+ case GL_BUFFER_DATA_SIZE:
+ *val = RESOURCE_UBO(res)->UniformBufferSize;
+ return 1;
+ case GL_NUM_ACTIVE_VARIABLES:
+ *val = RESOURCE_UBO(res)->NumUniforms;
+ return 1;
+ case GL_ACTIVE_VARIABLES:
+ for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
+ const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
+ struct gl_program_resource *uni =
+ _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname);
+ *val++ =
+ _mesa_program_resource_index(shProg, uni);
+ }
+ return RESOURCE_UBO(res)->NumUniforms;
+ }
+ } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
+ switch (prop) {
+ case GL_BUFFER_BINDING:
+ *val = RESOURCE_ATC(res)->Binding;
+ return 1;
+ case GL_BUFFER_DATA_SIZE:
+ *val = RESOURCE_ATC(res)->MinimumSize;
+ return 1;
+ case GL_NUM_ACTIVE_VARIABLES:
+ *val = RESOURCE_ATC(res)->NumUniforms;
+ return 1;
+ case GL_ACTIVE_VARIABLES:
+ for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++)
+ *val++ = RESOURCE_ATC(res)->Uniforms[i];
+ return RESOURCE_ATC(res)->NumUniforms;
+ }
+ }
+ assert(!"support for property type not implemented");
+
+invalid_operation:
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
+ _mesa_lookup_enum_by_nr(res->Type),
+ _mesa_lookup_enum_by_nr(prop));
+
+ return 0;
+}
+
+unsigned
+_mesa_program_resource_prop(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, GLuint index,
+ const GLenum prop, GLint *val, const char *caller)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+#define VALIDATE_TYPE(type)\
+ if (res->Type != type)\
+ goto invalid_operation;
+
+ switch(prop) {
+ case GL_NAME_LENGTH:
+ if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
+ goto invalid_operation;
+ /* Base name +3 if array '[0]' + terminator. */
+ *val = strlen(_mesa_program_resource_name(res)) +
+ (_mesa_program_resource_array_size(res) > 0 ? 3 : 0) + 1;
+ return 1;
+ case GL_TYPE:
+ switch (res->Type) {
+ case GL_UNIFORM:
+ *val = RESOURCE_UNI(res)->type->gl_type;
+ return 1;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ *val = RESOURCE_VAR(res)->type->gl_type;
+ return 1;
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ *val = RESOURCE_XFB(res)->Type;
+ return 1;
+ default:
+ goto invalid_operation;
+ }
+ case GL_ARRAY_SIZE:
+ switch (res->Type) {
+ case GL_UNIFORM:
+ *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
+ return 1;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ *val = MAX2(RESOURCE_VAR(res)->type->length, 1);
+ return 1;
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ *val = MAX2(RESOURCE_XFB(res)->Size, 1);
+ return 1;
+ default:
+ goto invalid_operation;
+ }
+ case GL_OFFSET:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->offset;
+ return 1;
+ case GL_BLOCK_INDEX:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->block_index;
+ return 1;
+ case GL_ARRAY_STRIDE:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->array_stride;
+ return 1;
+ case GL_MATRIX_STRIDE:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->matrix_stride;
+ return 1;
+ case GL_IS_ROW_MAJOR:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->row_major;
+ return 1;
+ case GL_ATOMIC_COUNTER_BUFFER_INDEX:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->atomic_buffer_index;
+ return 1;
+ case GL_BUFFER_BINDING:
+ case GL_BUFFER_DATA_SIZE:
+ case GL_NUM_ACTIVE_VARIABLES:
+ case GL_ACTIVE_VARIABLES:
+ return get_buffer_property(shProg, res, prop, val, caller);
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ case GL_REFERENCED_BY_GEOMETRY_SHADER:
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ switch (res->Type) {
+ case GL_UNIFORM:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_UNIFORM_BLOCK:
+ case GL_ATOMIC_COUNTER_BUFFER:
+ *val = is_resource_referenced(shProg, res, index,
+ stage_from_enum(prop));
+ return 1;
+ default:
+ goto invalid_operation;
+ }
+ case GL_LOCATION:
+ switch (res->Type) {
+ case GL_UNIFORM:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ *val = program_resource_location(shProg, res,
+ _mesa_program_resource_name(res));
+ return 1;
+ default:
+ goto invalid_operation;
+ }
+ case GL_LOCATION_INDEX:
+ if (res->Type != GL_PROGRAM_OUTPUT)
+ goto invalid_operation;
+ *val = RESOURCE_VAR(res)->data.index;
+ return 1;
+
+ /* GL_ARB_tessellation_shader */
+ case GL_IS_PER_PATCH:
+ case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
+ case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
+ /* GL_ARB_compute_shader */
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
+ _mesa_lookup_enum_by_nr(res->Type),
+ _mesa_lookup_enum_by_nr(prop));
+ return 0;
+ }
+
+#undef VALIDATE_TYPE
+
+invalid_operation:
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
+ _mesa_lookup_enum_by_nr(res->Type),
+ _mesa_lookup_enum_by_nr(prop));
+ return 0;
+}
+
+extern void
+_mesa_get_program_resourceiv(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index, GLsizei propCount,
+ const GLenum *props, GLsizei bufSize,
+ GLsizei *length, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint *val = (GLint *) params;
+ const GLenum *prop = props;
+ GLsizei amount = 0;
+
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_index(shProg, programInterface, index);
+
+ /* No such resource found or bufSize negative. */
+ if (!res || bufSize < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetProgramResourceiv(%s index %d bufSize %d)",
+ _mesa_lookup_enum_by_nr(programInterface), index, bufSize);
+ return;
+ }
+
+ /* Write propCount values until error occurs or bufSize reached. */
+ for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
+ int props_written =
+ _mesa_program_resource_prop(shProg, res, index, *prop, val,
+ "glGetProgramResourceiv");
+
+ /* Error happened. */
+ if (props_written == 0)
+ return;
+
+ amount += props_written;
+ }
+
+ /* If <length> is not NULL, the actual number of integer values
+ * written to <params> will be written to <length>.
+ */
+ if (length)
+ *length = amount;
}
diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index 30716f5e3..77e2b8745 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -882,10 +882,9 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj)
sh->CompileStatus = GL_FALSE;
} else {
if (ctx->_Shader->Flags & GLSL_DUMP) {
- fprintf(stderr, "GLSL source for %s shader %d:\n",
+ _mesa_log("GLSL source for %s shader %d:\n",
_mesa_shader_stage_to_string(sh->Stage), sh->Name);
- fprintf(stderr, "%s\n", sh->Source);
- fflush(stderr);
+ _mesa_log("%s\n", sh->Source);
}
/* this call will set the shader->CompileStatus field to indicate if
@@ -899,27 +898,25 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj)
if (ctx->_Shader->Flags & GLSL_DUMP) {
if (sh->CompileStatus) {
- fprintf(stderr, "GLSL IR for shader %d:\n", sh->Name);
- _mesa_print_ir(stderr, sh->ir, NULL);
- fprintf(stderr, "\n\n");
+ _mesa_log("GLSL IR for shader %d:\n", sh->Name);
+ _mesa_print_ir(_mesa_get_log_file(), sh->ir, NULL);
+ _mesa_log("\n\n");
} else {
- fprintf(stderr, "GLSL shader %d failed to compile.\n", sh->Name);
+ _mesa_log("GLSL shader %d failed to compile.\n", sh->Name);
}
if (sh->InfoLog && sh->InfoLog[0] != 0) {
- fprintf(stderr, "GLSL shader %d info log:\n", sh->Name);
- fprintf(stderr, "%s\n", sh->InfoLog);
+ _mesa_log("GLSL shader %d info log:\n", sh->Name);
+ _mesa_log("%s\n", sh->InfoLog);
}
- fflush(stderr);
}
}
if (!sh->CompileStatus) {
if (ctx->_Shader->Flags & GLSL_DUMP_ON_ERROR) {
- fprintf(stderr, "GLSL source for %s shader %d:\n",
+ _mesa_log("GLSL source for %s shader %d:\n",
_mesa_shader_stage_to_string(sh->Stage), sh->Name);
- fprintf(stderr, "%s\n", sh->Source);
- fprintf(stderr, "Info Log:\n%s\n", sh->InfoLog);
- fflush(stderr);
+ _mesa_log("%s\n", sh->Source);
+ _mesa_log("Info Log:\n%s\n", sh->InfoLog);
}
if (ctx->_Shader->Flags & GLSL_REPORT_ERRORS) {
diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h
index 047d2562d..aba6d5d83 100644
--- a/mesalib/src/mesa/main/shaderapi.h
+++ b/mesalib/src/mesa/main/shaderapi.h
@@ -219,6 +219,51 @@ extern GLuint GLAPIENTRY
_mesa_CreateShaderProgramv(GLenum type, GLsizei count,
const GLchar* const *strings);
+/* GL_ARB_program_resource_query */
+extern const char*
+_mesa_program_resource_name(struct gl_program_resource *res);
+
+extern unsigned
+_mesa_program_resource_array_size(struct gl_program_resource *res);
+
+extern GLuint
+_mesa_program_resource_index(struct gl_shader_program *shProg,
+ struct gl_program_resource *res);
+
+extern struct gl_program_resource *
+_mesa_program_resource_find_name(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name);
+
+extern struct gl_program_resource *
+_mesa_program_resource_find_index(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index);
+
+extern bool
+_mesa_get_program_resource_name(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index,
+ GLsizei bufSize, GLsizei *length,
+ GLchar *name, const char *caller);
+
+extern GLint
+_mesa_program_resource_location(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name);
+
+extern GLint
+_mesa_program_resource_location_index(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name);
+
+extern unsigned
+_mesa_program_resource_prop(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, GLuint index,
+ const GLenum prop, GLint *val, const char *caller);
+
+extern void
+_mesa_get_program_resourceiv(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index,
+ GLsizei propCount, const GLenum *props,
+ GLsizei bufSize, GLsizei *length,
+ GLint *params);
+
#ifdef __cplusplus
}
#endif
diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c
index d7620c8ef..e42896036 100644
--- a/mesalib/src/mesa/main/shaderobj.c
+++ b/mesalib/src/mesa/main/shaderobj.c
@@ -315,6 +315,12 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg)
ralloc_free(shProg->AtomicBuffers);
shProg->AtomicBuffers = NULL;
shProg->NumAtomicBuffers = 0;
+
+ if (shProg->ProgramResourceList) {
+ ralloc_free(shProg->ProgramResourceList);
+ shProg->ProgramResourceList = NULL;
+ shProg->NumProgramResourceList = 0;
+ }
}
diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c
index dadfb3c8c..cc84c6148 100644
--- a/mesalib/src/mesa/main/state.c
+++ b/mesalib/src/mesa/main/state.c
@@ -269,28 +269,6 @@ update_program_constants(struct gl_context *ctx)
-static void
-update_viewport_matrix(struct gl_context *ctx)
-{
- const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
- unsigned i;
-
- assert(depthMax > 0);
-
- /* Compute scale and bias values. This is really driver-specific
- * and should be maintained elsewhere if at all.
- * NOTE: RasterPos uses this.
- */
- for (i = 0; i < ctx->Const.MaxViewports; i++) {
- double scale[3], translate[3];
-
- _mesa_get_viewport_xform(ctx, i, scale, translate);
- _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap,
- scale, translate, depthMax);
- }
-}
-
-
/**
* Update the ctx->Polygon._FrontBit flag.
*/
@@ -407,9 +385,6 @@ _mesa_update_state_locked( struct gl_context *ctx )
if (new_state & _NEW_PIXEL)
_mesa_update_pixel( ctx, new_state );
- if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT))
- update_viewport_matrix(ctx);
-
if (new_state & (_NEW_MULTISAMPLE | _NEW_BUFFERS))
update_multisample( ctx );
@@ -507,7 +482,7 @@ _mesa_set_varying_vp_inputs( struct gl_context *ctx,
ctx->FragmentProgram._TexEnvProgram) {
ctx->NewState |= _NEW_VARYING_VP_INPUTS;
}
- /*printf("%s %x\n", __FUNCTION__, varying_inputs);*/
+ /*printf("%s %x\n", __func__, varying_inputs);*/
}
}
diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c
index 00234d4cc..0fd1a3683 100644
--- a/mesalib/src/mesa/main/texcompress.c
+++ b/mesalib/src/mesa/main/texcompress.c
@@ -32,7 +32,6 @@
#include "glheader.h"
#include "imports.h"
-#include "colormac.h"
#include "context.h"
#include "formats.h"
#include "mtypes.h"
diff --git a/mesalib/src/mesa/main/texcompress_fxt1.c b/mesalib/src/mesa/main/texcompress_fxt1.c
index 562359410..f06f04882 100644
--- a/mesalib/src/mesa/main/texcompress_fxt1.c
+++ b/mesalib/src/mesa/main/texcompress_fxt1.c
@@ -31,7 +31,6 @@
#include "glheader.h"
#include "imports.h"
-#include "colormac.h"
#include "image.h"
#include "macros.h"
#include "mipmap.h"
diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c
index f40e4e6c0..66de1f17d 100644
--- a/mesalib/src/mesa/main/texcompress_rgtc.c
+++ b/mesalib/src/mesa/main/texcompress_rgtc.c
@@ -35,7 +35,6 @@
#include "glheader.h"
#include "imports.h"
-#include "colormac.h"
#include "image.h"
#include "macros.h"
#include "mipmap.h"
diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c
index 41d00d4e9..7ce3cb88e 100644
--- a/mesalib/src/mesa/main/texcompress_s3tc.c
+++ b/mesalib/src/mesa/main/texcompress_s3tc.c
@@ -29,13 +29,8 @@
* GL_EXT_texture_compression_s3tc support.
*/
-#ifndef USE_EXTERNAL_DXTN_LIB
-#define USE_EXTERNAL_DXTN_LIB 1
-#endif
-
#include "glheader.h"
#include "imports.h"
-#include "colormac.h"
#include "dlopen.h"
#include "image.h"
#include "macros.h"
@@ -77,7 +72,6 @@ _mesa_init_texture_s3tc( struct gl_context *ctx )
{
/* called during context initialization */
ctx->Mesa_DXTn = GL_FALSE;
-#if USE_EXTERNAL_DXTN_LIB
if (!dxtlibhandle) {
dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0);
if (!dxtlibhandle) {
@@ -118,9 +112,6 @@ _mesa_init_texture_s3tc( struct gl_context *ctx )
if (dxtlibhandle) {
ctx->Mesa_DXTn = GL_TRUE;
}
-#else
- (void) ctx;
-#endif
}
/**
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index 1ef728660..b5d42d304 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -32,7 +32,6 @@
#include <stdbool.h>
#include "main/glheader.h"
#include "main/blend.h"
-#include "main/colormac.h"
#include "main/context.h"
#include "main/enums.h"
#include "main/formats.h"
diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c
index 0a7f983fb..1af9d47f0 100644
--- a/mesalib/src/mesa/main/texstate.c
+++ b/mesalib/src/mesa/main/texstate.c
@@ -31,8 +31,6 @@
#include <stdio.h>
#include "glheader.h"
#include "bufferobj.h"
-#include "colormac.h"
-#include "colortab.h"
#include "context.h"
#include "enums.h"
#include "macros.h"
diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c
index 7ad9d2b68..152520598 100644
--- a/mesalib/src/mesa/main/texstore.c
+++ b/mesalib/src/mesa/main/texstore.c
@@ -53,7 +53,6 @@
#include "glheader.h"
#include "bufferobj.h"
-#include "colormac.h"
#include "format_pack.h"
#include "format_utils.h"
#include "image.h"
diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c
index ce678c864..103011ce5 100644
--- a/mesalib/src/mesa/main/transformfeedback.c
+++ b/mesalib/src/mesa/main/transformfeedback.c
@@ -514,22 +514,24 @@ _mesa_EndTransformFeedback(void)
* Helper used by BindBufferRange() and BindBufferBase().
*/
static void
-bind_buffer_range(struct gl_context *ctx, GLuint index,
+bind_buffer_range(struct gl_context *ctx,
+ struct gl_transform_feedback_object *obj,
+ GLuint index,
struct gl_buffer_object *bufObj,
- GLintptr offset, GLsizeiptr size)
+ GLintptr offset, GLsizeiptr size,
+ bool dsa)
{
- struct gl_transform_feedback_object *obj =
- ctx->TransformFeedback.CurrentObject;
-
/* Note: no need to FLUSH_VERTICES or flag NewTransformFeedback, because
* transform feedback buffers can't be changed while transform feedback is
* active.
*/
- /* The general binding point */
- _mesa_reference_buffer_object(ctx,
- &ctx->TransformFeedback.CurrentBuffer,
- bufObj);
+ if (!dsa) {
+ /* The general binding point */
+ _mesa_reference_buffer_object(ctx,
+ &ctx->TransformFeedback.CurrentBuffer,
+ bufObj);
+ }
/* The per-attribute binding point */
_mesa_set_transform_feedback_binding(ctx, obj, index, bufObj, offset, size);
@@ -539,75 +541,209 @@ bind_buffer_range(struct gl_context *ctx, GLuint index,
/**
* Specify a buffer object to receive transform feedback results. Plus,
* specify the starting offset to place the results, and max size.
- * Called from the glBindBufferRange() function.
+ * Called from the glBindBufferRange() and glTransformFeedbackBufferRange
+ * functions.
*/
void
_mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
- GLuint index,
- struct gl_buffer_object *bufObj,
- GLintptr offset,
- GLsizeiptr size)
+ struct gl_transform_feedback_object *obj,
+ GLuint index,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset,
+ GLsizeiptr size,
+ bool dsa)
{
- struct gl_transform_feedback_object *obj;
+ const char *gl_methd_name;
+ if (dsa)
+ gl_methd_name = "glTransformFeedbackBufferRange";
+ else
+ gl_methd_name = "glBindBufferRange";
- obj = ctx->TransformFeedback.CurrentObject;
if (obj->Active) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindBufferRange(transform feedback active)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(transform feedback active)",
+ gl_methd_name);
return;
}
if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
+ /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is
+ * generated if index is greater than or equal to the number of binding
+ * points for transform feedback, as described in section 6.7.1."
+ */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)",
+ gl_methd_name, index);
return;
}
if (size & 0x3) {
- /* must a multiple of four */
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", (int) size);
+ /* OpenGL 4.5 core profile, 6.7, pdf page 103: multiple of 4 */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be a multiple of "
+ "four)", gl_methd_name, (int) size);
return;
}
if (offset & 0x3) {
- /* must be multiple of four */
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glBindBufferRange(offset=%d)", (int) offset);
+ /* OpenGL 4.5 core profile, 6.7, pdf page 103: multiple of 4 */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d must be a multiple "
+ "of four)", gl_methd_name, (int) offset);
return;
- }
+ }
+
+ if (offset < 0) {
+ /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is
+ * generated by BindBufferRange if offset is negative."
+ *
+ * OpenGL 4.5 core profile, 13.2, pdf page 445: "An INVALID_VALUE error
+ * is generated by TransformFeedbackBufferRange if offset is negative."
+ */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d must be >= 0)",
+ gl_methd_name,
+ (int) offset);
+ return;
+ }
- bind_buffer_range(ctx, index, bufObj, offset, size);
+ if (size <= 0 && (dsa || bufObj != ctx->Shared->NullBufferObj)) {
+ /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is
+ * generated by BindBufferRange if buffer is non-zero and size is less
+ * than or equal to zero."
+ *
+ * OpenGL 4.5 core profile, 13.2, pdf page 445: "An INVALID_VALUE error
+ * is generated by TransformFeedbackBufferRange if size is less than or
+ * equal to zero."
+ */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be > 0)",
+ gl_methd_name, (int) size);
+ return;
+ }
+
+ bind_buffer_range(ctx, obj, index, bufObj, offset, size, dsa);
}
/**
* Specify a buffer object to receive transform feedback results.
* As above, but start at offset = 0.
- * Called from the glBindBufferBase() function.
+ * Called from the glBindBufferBase() and glTransformFeedbackBufferBase()
+ * functions.
*/
void
_mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx,
- GLuint index,
- struct gl_buffer_object *bufObj)
+ struct gl_transform_feedback_object *obj,
+ GLuint index,
+ struct gl_buffer_object *bufObj,
+ bool dsa)
{
- struct gl_transform_feedback_object *obj;
-
- obj = ctx->TransformFeedback.CurrentObject;
-
if (obj->Active) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindBufferBase(transform feedback active)");
+ "%s(transform feedback active)",
+ dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase");
return;
}
if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)",
+ dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase",
+ index);
+ return;
+ }
+
+ bind_buffer_range(ctx, obj, index, bufObj, 0, 0, dsa);
+}
+
+/**
+ * Wrapper around lookup_transform_feedback_object that throws
+ * GL_INVALID_OPERATION if id is not in the hash table. After calling
+ * _mesa_error, it returns NULL.
+ */
+static struct gl_transform_feedback_object *
+lookup_transform_feedback_object_err(struct gl_context *ctx,
+ GLuint xfb, const char* func)
+{
+ struct gl_transform_feedback_object *obj;
+
+ obj = _mesa_lookup_transform_feedback_object(ctx, xfb);
+ if (!obj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(xfb=%u: non-generated object name)", func, xfb);
+ }
+
+ return obj;
+}
+
+/**
+ * Wrapper around _mesa_lookup_bufferobj that throws GL_INVALID_VALUE if id
+ * is not in the hash table. Specialised version for the
+ * transform-feedback-related functions. After calling _mesa_error, it
+ * returns NULL.
+ */
+static struct gl_buffer_object *
+lookup_transform_feedback_bufferobj_err(struct gl_context *ctx,
+ GLuint buffer, const char* func)
+{
+ struct gl_buffer_object *bufObj;
+
+ /* OpenGL 4.5 core profile, 13.2, pdf page 444: buffer must be zero or the
+ * name of an existing buffer object.
+ */
+ if (buffer == 0) {
+ bufObj = ctx->Shared->NullBufferObj;
+ } else {
+ bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid buffer=%u)", func,
+ buffer);
+ }
+ }
+
+ return bufObj;
+}
+
+void GLAPIENTRY
+_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj;
+ struct gl_buffer_object *bufObj;
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glTransformFeedbackBufferBase");
+ if(!obj) {
+ return;
+ }
+
+ bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer,
+ "glTransformFeedbackBufferBase");
+ if(!bufObj) {
return;
}
- bind_buffer_range(ctx, index, bufObj, 0, 0);
+ _mesa_bind_buffer_base_transform_feedback(ctx, obj, index, bufObj, true);
}
+void GLAPIENTRY
+_mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer,
+ GLintptr offset, GLsizeiptr size)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj;
+ struct gl_buffer_object *bufObj;
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glTransformFeedbackBufferRange");
+ if(!obj) {
+ return;
+ }
+
+ bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer,
+ "glTransformFeedbackBufferRange");
+ if(!bufObj) {
+ return;
+ }
+
+ _mesa_bind_buffer_range_transform_feedback(ctx, obj, index, bufObj, offset,
+ size, true);
+}
/**
* Specify a buffer object to receive transform feedback results, plus the
@@ -660,7 +796,7 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
return;
}
- bind_buffer_range(ctx, index, bufObj, offset, 0);
+ bind_buffer_range(ctx, obj, index, bufObj, offset, 0, false);
}
@@ -784,7 +920,7 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
GLsizei *size, GLenum *type, GLchar *name)
{
const struct gl_shader_program *shProg;
- const struct gl_transform_feedback_info *linked_xfb_info;
+ struct gl_program_resource *res;
GET_CURRENT_CONTEXT(ctx);
shProg = _mesa_lookup_shader_program(ctx, program);
@@ -794,22 +930,27 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
return;
}
- linked_xfb_info = &shProg->LinkedTransformFeedback;
- if (index >= (GLuint) linked_xfb_info->NumVarying) {
+ res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg,
+ GL_TRANSFORM_FEEDBACK_VARYING,
+ index);
+ if (!res) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetTransformFeedbackVarying(index=%u)", index);
return;
}
/* return the varying's name and length */
- _mesa_copy_string(name, bufSize, length,
- linked_xfb_info->Varyings[index].Name);
+ _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
/* return the datatype and value's size (in datatype units) */
if (type)
- *type = linked_xfb_info->Varyings[index].Type;
+ _mesa_program_resource_prop((struct gl_shader_program *) shProg,
+ res, index, GL_TYPE, (GLint*) type,
+ "glGetTransformFeedbackVarying");
if (size)
- *size = linked_xfb_info->Varyings[index].Size;
+ _mesa_program_resource_prop((struct gl_shader_program *) shProg,
+ res, index, GL_ARRAY_SIZE, (GLint*) size,
+ "glGetTransformFeedbackVarying");
}
@@ -817,6 +958,10 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
struct gl_transform_feedback_object *
_mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name)
{
+ /* OpenGL 4.5 core profile, 13.2 pdf page 444: "xfb must be zero, indicating
+ * the default transform feedback object, or the name of an existing
+ * transform feedback object."
+ */
if (name == 0) {
return ctx->TransformFeedback.DefaultObject;
}
@@ -825,25 +970,24 @@ _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name)
_mesa_HashLookup(ctx->TransformFeedback.Objects, name);
}
-
-/**
- * Create new transform feedback objects. Transform feedback objects
- * encapsulate the state related to transform feedback to allow quickly
- * switching state (and drawing the results, below).
- * Part of GL_ARB_transform_feedback2.
- */
-void GLAPIENTRY
-_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names)
+static void
+create_transform_feedbacks(struct gl_context *ctx, GLsizei n, GLuint *ids,
+ bool dsa)
{
GLuint first;
- GET_CURRENT_CONTEXT(ctx);
+ const char* func;
+
+ if (dsa)
+ func = "glCreateTransformFeedbacks";
+ else
+ func = "glGenTransformFeedbacks";
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenTransformFeedbacks(n < 0)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
return;
}
- if (!names)
+ if (!ids)
return;
/* we don't need contiguous IDs, but this might be faster */
@@ -854,18 +998,56 @@ _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names)
struct gl_transform_feedback_object *obj
= ctx->Driver.NewTransformFeedback(ctx, first + i);
if (!obj) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
return;
}
- names[i] = first + i;
+ ids[i] = first + i;
_mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj);
+ if (dsa) {
+ /* this is normally done at bind time in the non-dsa case */
+ obj->EverBound = GL_TRUE;
+ }
}
}
else {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
}
}
+/**
+ * Create new transform feedback objects. Transform feedback objects
+ * encapsulate the state related to transform feedback to allow quickly
+ * switching state (and drawing the results, below).
+ * Part of GL_ARB_transform_feedback2.
+ */
+void GLAPIENTRY
+_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* GenTransformFeedbacks should just reserve the object names that a
+ * subsequent call to BindTransformFeedback should actively create. For
+ * the sake of simplicity, we reserve the names and create the objects
+ * straight away.
+ */
+
+ create_transform_feedbacks(ctx, n, names, false);
+}
+
+/**
+ * Create new transform feedback objects. Transform feedback objects
+ * encapsulate the state related to transform feedback to allow quickly
+ * switching state (and drawing the results, below).
+ * Part of GL_ARB_direct_state_access.
+ */
+void GLAPIENTRY
+_mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ create_transform_feedbacks(ctx, n, names, true);
+}
+
/**
* Is the given ID a transform feedback object?
@@ -1026,3 +1208,89 @@ _mesa_ResumeTransformFeedback(void)
assert(ctx->Driver.ResumeTransformFeedback);
ctx->Driver.ResumeTransformFeedback(ctx, obj);
}
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param)
+{
+ struct gl_transform_feedback_object *obj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glGetTransformFeedbackiv");
+ if(!obj) {
+ return;
+ }
+
+ switch(pname) {
+ case GL_TRANSFORM_FEEDBACK_PAUSED:
+ *param = obj->Paused;
+ break;
+ case GL_TRANSFORM_FEEDBACK_ACTIVE:
+ *param = obj->Active;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTransformFeedbackiv(pname=%i)", pname);
+ }
+}
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index,
+ GLint *param)
+{
+ struct gl_transform_feedback_object *obj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glGetTransformFeedbacki_v");
+ if(!obj) {
+ return;
+ }
+
+ if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTransformFeedbacki_v(index=%i)", index);
+ return;
+ }
+
+ switch(pname) {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ *param = obj->BufferNames[index];
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTransformFeedbacki_v(pname=%i)", pname);
+ }
+}
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index,
+ GLint64 *param)
+{
+ struct gl_transform_feedback_object *obj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glGetTransformFeedbacki64_v");
+ if(!obj) {
+ return;
+ }
+
+ if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTransformFeedbacki64_v(index=%i)", index);
+ return;
+ }
+
+ switch(pname) {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ *param = obj->Offset[index];
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ *param = obj->RequestedSize[index];
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTransformFeedbacki64_v(pname=%i)", pname);
+ }
+}
diff --git a/mesalib/src/mesa/main/transformfeedback.h b/mesalib/src/mesa/main/transformfeedback.h
index 87f4080e0..bb9729cdb 100644
--- a/mesalib/src/mesa/main/transformfeedback.h
+++ b/mesalib/src/mesa/main/transformfeedback.h
@@ -65,15 +65,18 @@ _mesa_EndTransformFeedback(void);
extern void
_mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
+ struct gl_transform_feedback_object *obj,
GLuint index,
struct gl_buffer_object *bufObj,
GLintptr offset,
- GLsizeiptr size);
+ GLsizeiptr size, bool dsa);
extern void
_mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx,
+ struct gl_transform_feedback_object *obj,
GLuint index,
- struct gl_buffer_object *bufObj);
+ struct gl_buffer_object *bufObj,
+ bool dsa);
extern void GLAPIENTRY
_mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
@@ -102,6 +105,9 @@ _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name);
extern void GLAPIENTRY
_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names);
+extern void GLAPIENTRY
+_mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names);
+
extern GLboolean GLAPIENTRY
_mesa_IsTransformFeedback(GLuint name);
@@ -141,4 +147,24 @@ _mesa_set_transform_feedback_binding(struct gl_context *ctx,
tfObj->RequestedSize[index] = size;
}
+/*** GL_ARB_direct_state_access ***/
+
+extern void GLAPIENTRY
+_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer);
+
+extern void GLAPIENTRY
+_mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer,
+ GLintptr offset, GLsizeiptr size);
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param);
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index,
+ GLint *param);
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index,
+ GLint64 *param);
+
#endif /* TRANSFORM_FEEDBACK_H */
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index 2ab5528c3..4e77b3284 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -46,6 +46,7 @@ _mesa_GetActiveUniform(GLuint program, GLuint index,
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
+ struct gl_program_resource *res;
if (maxLength < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(maxLength < 0)");
@@ -56,26 +57,51 @@ _mesa_GetActiveUniform(GLuint program, GLuint index,
if (!shProg)
return;
- if (index >= shProg->NumUserUniformStorage) {
+ res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg,
+ GL_UNIFORM, index);
+
+ if (!res) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
return;
}
- const struct gl_uniform_storage *const uni = &shProg->UniformStorage[index];
-
- if (nameOut) {
- _mesa_get_uniform_name(uni, maxLength, length, nameOut);
- }
-
- if (size) {
- /* array_elements is zero for non-arrays, but the API requires that 1 be
- * returned.
- */
- *size = MAX2(1, uni->array_elements);
- }
+ if (nameOut)
+ _mesa_get_program_resource_name(shProg, GL_UNIFORM, index, maxLength,
+ length, nameOut, "glGetActiveUniform");
+ if (type)
+ _mesa_program_resource_prop((struct gl_shader_program *) shProg,
+ res, index, GL_TYPE, (GLint*) type,
+ "glGetActiveUniform");
+ if (size)
+ _mesa_program_resource_prop((struct gl_shader_program *) shProg,
+ res, index, GL_ARRAY_SIZE, (GLint*) size,
+ "glGetActiveUniform");
+}
- if (type) {
- *type = uni->type->gl_type;
+static GLenum
+resource_prop_from_uniform_prop(GLenum uni_prop)
+{
+ switch (uni_prop) {
+ case GL_UNIFORM_TYPE:
+ return GL_TYPE;
+ case GL_UNIFORM_SIZE:
+ return GL_ARRAY_SIZE;
+ case GL_UNIFORM_NAME_LENGTH:
+ return GL_NAME_LENGTH;
+ case GL_UNIFORM_BLOCK_INDEX:
+ return GL_BLOCK_INDEX;
+ case GL_UNIFORM_OFFSET:
+ return GL_OFFSET;
+ case GL_UNIFORM_ARRAY_STRIDE:
+ return GL_ARRAY_STRIDE;
+ case GL_UNIFORM_MATRIX_STRIDE:
+ return GL_MATRIX_STRIDE;
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ return GL_IS_ROW_MAJOR;
+ case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
+ return GL_ATOMIC_COUNTER_BUFFER_INDEX;
+ default:
+ return 0;
}
}
@@ -88,7 +114,8 @@ _mesa_GetActiveUniformsiv(GLuint program,
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
- GLsizei i;
+ struct gl_program_resource *res;
+ GLenum res_prop;
if (uniformCount < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
@@ -100,80 +127,21 @@ _mesa_GetActiveUniformsiv(GLuint program,
if (!shProg)
return;
- for (i = 0; i < uniformCount; i++) {
- GLuint index = uniformIndices[i];
+ res_prop = resource_prop_from_uniform_prop(pname);
- if (index >= shProg->NumUserUniformStorage) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
- return;
+ for (int i = 0; i < uniformCount; i++) {
+ res = _mesa_program_resource_find_index(shProg, GL_UNIFORM,
+ uniformIndices[i]);
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
+ break;
}
- }
-
- for (i = 0; i < uniformCount; i++) {
- GLuint index = uniformIndices[i];
- const struct gl_uniform_storage *uni = &shProg->UniformStorage[index];
-
- switch (pname) {
- case GL_UNIFORM_TYPE:
- params[i] = uni->type->gl_type;
- break;
-
- case GL_UNIFORM_SIZE:
- /* array_elements is zero for non-arrays, but the API requires that 1 be
- * returned.
- */
- params[i] = MAX2(1, uni->array_elements);
- break;
- case GL_UNIFORM_NAME_LENGTH:
- params[i] = strlen(uni->name) + 1;
-
- /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
- * spec says:
- *
- * "If the active uniform is an array, the uniform name returned
- * in name will always be the name of the uniform array appended
- * with "[0]"."
- */
- if (uni->array_elements != 0)
- params[i] += 3;
- break;
-
- case GL_UNIFORM_BLOCK_INDEX:
- params[i] = uni->block_index;
- break;
-
- case GL_UNIFORM_OFFSET:
- params[i] = uni->offset;
- break;
-
- case GL_UNIFORM_ARRAY_STRIDE:
- params[i] = uni->array_stride;
- break;
-
- case GL_UNIFORM_MATRIX_STRIDE:
- params[i] = uni->matrix_stride;
- break;
-
- case GL_UNIFORM_IS_ROW_MAJOR:
- params[i] = uni->row_major;
- break;
-
- case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
- if (!ctx->Extensions.ARB_shader_atomic_counters)
- goto invalid_enum;
- params[i] = uni->atomic_buffer_index;
+ if (!_mesa_program_resource_prop(shProg, res, uniformIndices[i],
+ res_prop, &params[i],
+ "glGetActiveUniformsiv"))
break;
-
- default:
- goto invalid_enum;
- }
}
-
- return;
-
- invalid_enum:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
}
static struct gl_uniform_storage *
diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c
index fb1482f9c..5548d1d02 100644
--- a/mesalib/src/mesa/main/uniforms.c
+++ b/mesalib/src/mesa/main/uniforms.c
@@ -911,7 +911,6 @@ GLint GLAPIENTRY
_mesa_GetUniformLocation(GLuint programObj, const GLcharARB *name)
{
struct gl_shader_program *shProg;
- GLuint index, offset;
GET_CURRENT_CONTEXT(ctx);
@@ -931,23 +930,7 @@ _mesa_GetUniformLocation(GLuint programObj, const GLcharARB *name)
return -1;
}
- index = _mesa_get_uniform_location(shProg, name, &offset);
- if (index == GL_INVALID_INDEX)
- return -1;
-
- /* From the GL_ARB_uniform_buffer_object spec:
- *
- * "The value -1 will be returned if <name> does not correspond to an
- * active uniform variable name in <program>, if <name> is associated
- * with a named uniform block, or if <name> starts with the reserved
- * prefix "gl_"."
- */
- if (shProg->UniformStorage[index].block_index != -1 ||
- shProg->UniformStorage[index].atomic_buffer_index != -1)
- return -1;
-
- /* location in remap table + array element offset */
- return shProg->UniformStorage[index].remap_location + offset;
+ return _mesa_program_resource_location(shProg, GL_UNIFORM, name);
}
GLuint GLAPIENTRY
@@ -955,7 +938,6 @@ _mesa_GetUniformBlockIndex(GLuint program,
const GLchar *uniformBlockName)
{
GET_CURRENT_CONTEXT(ctx);
- GLuint i;
struct gl_shader_program *shProg;
if (!ctx->Extensions.ARB_uniform_buffer_object) {
@@ -968,12 +950,13 @@ _mesa_GetUniformBlockIndex(GLuint program,
if (!shProg)
return GL_INVALID_INDEX;
- for (i = 0; i < shProg->NumUniformBlocks; i++) {
- if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName))
- return i;
- }
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, GL_UNIFORM_BLOCK,
+ uniformBlockName);
+ if (!res)
+ return GL_INVALID_INDEX;
- return GL_INVALID_INDEX;
+ return _mesa_program_resource_index(shProg, res);
}
void GLAPIENTRY
@@ -1003,9 +986,9 @@ _mesa_GetUniformIndices(GLuint program,
}
for (i = 0; i < uniformCount; i++) {
- unsigned offset;
- uniformIndices[i] = _mesa_get_uniform_location(shProg,
- uniformNames[i], &offset);
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, GL_UNIFORM, uniformNames[i]);
+ uniformIndices[i] = _mesa_program_resource_index(shProg, res);
}
}
@@ -1061,104 +1044,104 @@ _mesa_UniformBlockBinding(GLuint program,
}
}
-void GLAPIENTRY
-_mesa_GetActiveUniformBlockiv(GLuint program,
- GLuint uniformBlockIndex,
- GLenum pname,
- GLint *params)
+
+/**
+ * Generic program resource property query.
+ */
+static void
+mesa_bufferiv(struct gl_shader_program *shProg, GLenum type,
+ GLuint index, GLenum pname, GLint *params, const char *caller)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_shader_program *shProg;
- struct gl_uniform_block *block;
- unsigned i;
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_index(shProg, type, index);
- if (!ctx->Extensions.ARB_uniform_buffer_object) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufferindex %d)", caller, index);
return;
}
- shProg = _mesa_lookup_shader_program_err(ctx, program,
- "glGetActiveUniformBlockiv");
- if (!shProg)
- return;
-
- if (uniformBlockIndex >= shProg->NumUniformBlocks) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetActiveUniformBlockiv(block index %u >= %u)",
- uniformBlockIndex, shProg->NumUniformBlocks);
- return;
- }
-
- block = &shProg->UniformBlocks[uniformBlockIndex];
-
switch (pname) {
case GL_UNIFORM_BLOCK_BINDING:
- params[0] = block->Binding;
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ _mesa_program_resource_prop(shProg, res, index, GL_BUFFER_BINDING,
+ params, caller);
return;
-
case GL_UNIFORM_BLOCK_DATA_SIZE:
- params[0] = block->UniformBufferSize;
+ case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE:
+ _mesa_program_resource_prop(shProg, res, index, GL_BUFFER_DATA_SIZE,
+ params, caller);
return;
-
case GL_UNIFORM_BLOCK_NAME_LENGTH:
- params[0] = strlen(block->Name) + 1;
+ _mesa_program_resource_prop(shProg, res, index, GL_NAME_LENGTH,
+ params, caller);
return;
-
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: {
- unsigned count = 0;
-
- for (i = 0; i < block->NumUniforms; i++) {
- unsigned offset;
- const int idx =
- _mesa_get_uniform_location(shProg,
- block->Uniforms[i].IndexName,
- &offset);
- if (idx != -1)
- count++;
- }
-
- params[0] = count;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS:
+ _mesa_program_resource_prop(shProg, res, index, GL_NUM_ACTIVE_VARIABLES,
+ params, caller);
return;
- }
-
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: {
- unsigned count = 0;
-
- for (i = 0; i < block->NumUniforms; i++) {
- unsigned offset;
- const int idx =
- _mesa_get_uniform_location(shProg,
- block->Uniforms[i].IndexName,
- &offset);
-
- if (idx != -1)
- params[count++] = idx;
- }
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES:
+ _mesa_program_resource_prop(shProg, res, index, GL_ACTIVE_VARIABLES,
+ params, caller);
return;
- }
-
case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
- params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER:
+ _mesa_program_resource_prop(shProg, res, index,
+ GL_REFERENCED_BY_VERTEX_SHADER, params,
+ caller);
return;
-
case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
- if (!_mesa_has_geometry_shaders(ctx))
- break;
- params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_GEOMETRY][uniformBlockIndex] != -1;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER:
+ _mesa_program_resource_prop(shProg, res, index,
+ GL_REFERENCED_BY_GEOMETRY_SHADER, params,
+ caller);
return;
-
case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
- params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_FRAGMENT][uniformBlockIndex] != -1;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER:
+ _mesa_program_resource_prop(shProg, res, index,
+ GL_REFERENCED_BY_FRAGMENT_SHADER, params,
+ caller);
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER:
+ params[0] = GL_FALSE;
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER:
+ params[0] = GL_FALSE;
return;
-
default:
_mesa_error(ctx, GL_INVALID_ENUM,
- "glGetActiveUniformBlockiv(pname 0x%x (%s))",
- pname, _mesa_lookup_enum_by_nr(pname));
+ "%s(pname 0x%x (%s))", caller, pname,
+ _mesa_lookup_enum_by_nr(pname));
return;
}
}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformBlockiv(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg;
+
+ if (!ctx->Extensions.ARB_uniform_buffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
+ return;
+ }
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glGetActiveUniformBlockiv");
+ if (!shProg)
+ return;
+
+ mesa_bufferiv(shProg, GL_UNIFORM_BLOCK, uniformBlockIndex, pname, params,
+ "glGetActiveUniformBlockiv");
+}
+
void GLAPIENTRY
_mesa_GetActiveUniformBlockName(GLuint program,
GLuint uniformBlockIndex,
@@ -1168,7 +1151,6 @@ _mesa_GetActiveUniformBlockName(GLuint program,
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
- struct gl_uniform_block *block;
if (!ctx->Extensions.ARB_uniform_buffer_object) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
@@ -1187,18 +1169,11 @@ _mesa_GetActiveUniformBlockName(GLuint program,
if (!shProg)
return;
- if (uniformBlockIndex >= shProg->NumUniformBlocks) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetActiveUniformBlockiv(block index %u >= %u)",
- uniformBlockIndex, shProg->NumUniformBlocks);
- return;
- }
-
- block = &shProg->UniformBlocks[uniformBlockIndex];
-
- if (uniformBlockName) {
- _mesa_copy_string(uniformBlockName, bufSize, length, block->Name);
- }
+ if (uniformBlockName)
+ _mesa_get_program_resource_name(shProg, GL_UNIFORM_BLOCK,
+ uniformBlockIndex, bufSize, length,
+ uniformBlockName,
+ "glGetActiveUniformBlockName");
}
void GLAPIENTRY
@@ -1226,54 +1201,8 @@ _mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex,
if (!shProg)
return;
- if (uniformIndex >= shProg->NumUserUniformStorage) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
- return;
- }
-
- if (uniformName) {
- _mesa_get_uniform_name(& shProg->UniformStorage[uniformIndex],
- bufSize, length, uniformName);
- }
-}
-
-void
-_mesa_get_uniform_name(const struct gl_uniform_storage *uni,
- GLsizei maxLength, GLsizei *length,
- GLchar *nameOut)
-{
- GLsizei localLength;
-
- if (length == NULL)
- length = &localLength;
-
- _mesa_copy_string(nameOut, maxLength, length, uni->name);
-
- /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
- * spec says:
- *
- * "If the active uniform is an array, the uniform name returned in
- * name will always be the name of the uniform array appended with
- * "[0]"."
- *
- * The same text also appears in the OpenGL 4.2 spec. It does not,
- * however, appear in any previous spec. Previous specifications are
- * ambiguous in this regard. However, either name can later be passed
- * to glGetUniformLocation (and related APIs), so there shouldn't be any
- * harm in always appending "[0]" to uniform array names.
- */
- if (uni->array_elements != 0) {
- int i;
-
- /* The comparison is strange because *length does *NOT* include the
- * terminating NUL, but maxLength does.
- */
- for (i = 0; i < 3 && (*length + i + 1) < maxLength; i++)
- nameOut[*length + i] = "[0]"[i];
-
- nameOut[*length + i] = '\0';
- *length += i;
- }
+ _mesa_get_program_resource_name(shProg, GL_UNIFORM, uniformIndex, bufSize,
+ length, uniformName, "glGetActiveUniformName");
}
void GLAPIENTRY
@@ -1282,8 +1211,6 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
- struct gl_active_atomic_buffer *ab;
- GLuint i;
if (!ctx->Extensions.ARB_shader_atomic_counters) {
_mesa_error(ctx, GL_INVALID_OPERATION,
@@ -1296,49 +1223,8 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
if (!shProg)
return;
- if (bufferIndex >= shProg->NumAtomicBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetActiveAtomicCounterBufferiv(bufferIndex)");
- return;
- }
-
- ab = &shProg->AtomicBuffers[bufferIndex];
-
- switch (pname) {
- case GL_ATOMIC_COUNTER_BUFFER_BINDING:
- params[0] = ab->Binding;
- return;
- case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE:
- params[0] = ab->MinimumSize;
- return;
- case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS:
- params[0] = ab->NumUniforms;
- return;
- case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES:
- for (i = 0; i < ab->NumUniforms; ++i)
- params[i] = ab->Uniforms[i];
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER:
- params[0] = ab->StageReferences[MESA_SHADER_VERTEX];
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER:
- params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY];
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER:
- params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT];
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER:
- params[0] = GL_FALSE;
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER:
- params[0] = GL_FALSE;
- return;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))",
- pname, _mesa_lookup_enum_by_nr(pname));
- return;
- }
+ mesa_bufferiv(shProg, GL_ATOMIC_COUNTER_BUFFER, bufferIndex, pname, params,
+ "glGetActiveAtomicCounterBufferiv");
}
void GLAPIENTRY
diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h
index 0e6113fe9..55fa2357e 100644
--- a/mesalib/src/mesa/main/uniforms.h
+++ b/mesalib/src/mesa/main/uniforms.h
@@ -398,11 +398,6 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *);
extern const struct gl_program_parameter *
get_uniform_parameter(struct gl_shader_program *shProg, GLint index);
-extern void
-_mesa_get_uniform_name(const struct gl_uniform_storage *uni,
- GLsizei maxLength, GLsizei *length,
- GLchar *nameOut);
-
struct gl_builtin_uniform_element {
const char *field;
int tokens[STATE_LENGTH];
diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c
index d8e22d438..5df5a2922 100644
--- a/mesalib/src/mesa/main/version.c
+++ b/mesalib/src/mesa/main/version.c
@@ -382,6 +382,7 @@ compute_version_es2(const struct gl_extensions *extensions)
extensions->ARB_shader_texture_lod &&
extensions->ARB_texture_float &&
extensions->ARB_texture_rg &&
+ extensions->ARB_depth_buffer_float &&
extensions->EXT_draw_buffers2 &&
/* extensions->ARB_framebuffer_object && */
extensions->EXT_framebuffer_sRGB &&
diff --git a/mesalib/src/mesa/main/viewport.c b/mesalib/src/mesa/main/viewport.c
index 0adce9c78..b27063031 100644
--- a/mesalib/src/mesa/main/viewport.c
+++ b/mesalib/src/mesa/main/viewport.c
@@ -40,8 +40,6 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx,
GLfloat x, GLfloat y,
GLfloat width, GLfloat height)
{
- double scale[3], translate[3];
-
/* clamp width and height to the implementation dependent range */
width = MIN2(width, (GLfloat) ctx->Const.MaxViewportWidth);
height = MIN2(height, (GLfloat) ctx->Const.MaxViewportHeight);
@@ -72,16 +70,6 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx,
ctx->ViewportArray[idx].Y = y;
ctx->ViewportArray[idx].Height = height;
ctx->NewState |= _NEW_VIEWPORT;
-
-#if 1
- /* XXX remove this someday. Currently the DRI drivers rely on
- * the WindowMap matrix being up to date in the driver's Viewport
- * and DepthRange functions.
- */
- _mesa_get_viewport_xform(ctx, idx, scale, translate);
- _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap,
- scale, translate, ctx->DrawBuffer->_DepthMaxF);
-#endif
}
struct gl_viewport_inputs {
@@ -140,8 +128,8 @@ _mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
/**
- * Set new viewport parameters and update derived state (the _WindowMap
- * matrix). Usually called from _mesa_Viewport().
+ * Set new viewport parameters and update derived state.
+ * Usually called from _mesa_Viewport().
*
* \param ctx GL context.
* \param idx Index of the viewport to be updated.
@@ -246,8 +234,6 @@ static void
set_depth_range_no_notify(struct gl_context *ctx, unsigned idx,
GLclampd nearval, GLclampd farval)
{
- double scale[3], translate[3];
-
if (ctx->ViewportArray[idx].Near == nearval &&
ctx->ViewportArray[idx].Far == farval)
return;
@@ -255,16 +241,6 @@ set_depth_range_no_notify(struct gl_context *ctx, unsigned idx,
ctx->ViewportArray[idx].Near = CLAMP(nearval, 0.0, 1.0);
ctx->ViewportArray[idx].Far = CLAMP(farval, 0.0, 1.0);
ctx->NewState |= _NEW_VIEWPORT;
-
-#if 1
- /* XXX remove this someday. Currently the DRI drivers rely on
- * the WindowMap matrix being up to date in the driver's Viewport
- * and DepthRange functions.
- */
- _mesa_get_viewport_xform(ctx, idx, scale, translate);
- _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap,
- scale, translate, ctx->DrawBuffer->_DepthMaxF);
-#endif
}
void
@@ -388,7 +364,6 @@ _mesa_DepthRangeIndexed(GLuint index, GLclampd nearval, GLclampd farval)
*/
void _mesa_init_viewport(struct gl_context *ctx)
{
- GLfloat depthMax = 65535.0F; /* sorf of arbitrary */
unsigned i;
ctx->Transform.ClipOrigin = GL_LOWER_LEFT;
@@ -398,8 +373,6 @@ void _mesa_init_viewport(struct gl_context *ctx)
* so just initialize all of them.
*/
for (i = 0; i < MAX_VIEWPORTS; i++) {
- double scale[3], translate[3];
-
/* Viewport group */
ctx->ViewportArray[i].X = 0;
ctx->ViewportArray[i].Y = 0;
@@ -407,27 +380,10 @@ void _mesa_init_viewport(struct gl_context *ctx)
ctx->ViewportArray[i].Height = 0;
ctx->ViewportArray[i].Near = 0.0;
ctx->ViewportArray[i].Far = 1.0;
- _math_matrix_ctr(&ctx->ViewportArray[i]._WindowMap);
-
- _mesa_get_viewport_xform(ctx, i, scale, translate);
- _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap,
- scale, translate, depthMax);
}
}
-/**
- * Free the context viewport attribute group data.
- * \param ctx the GL context.
- */
-void _mesa_free_viewport_data(struct gl_context *ctx)
-{
- unsigned i;
-
- for (i = 0; i < MAX_VIEWPORTS; i++)
- _math_matrix_dtr(&ctx->ViewportArray[i]._WindowMap);
-}
-
extern void GLAPIENTRY
_mesa_ClipControl(GLenum origin, GLenum depth)
{
diff --git a/mesalib/src/mesa/main/viewport.h b/mesalib/src/mesa/main/viewport.h
index 426e194bd..899dc2d0b 100644
--- a/mesalib/src/mesa/main/viewport.h
+++ b/mesalib/src/mesa/main/viewport.h
@@ -68,9 +68,6 @@ extern void
_mesa_init_viewport(struct gl_context *ctx);
-extern void
-_mesa_free_viewport_data(struct gl_context *ctx);
-
extern void GLAPIENTRY
_mesa_ClipControl(GLenum origin, GLenum depth);