aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa')
-rw-r--r--mesalib/src/mesa/Makefile.sources2
-rw-r--r--mesalib/src/mesa/drivers/common/driverfuncs.c2
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c3
-rwxr-xr-xmesalib/src/mesa/drivers/dri/swrast/swrast.c16
-rw-r--r--mesalib/src/mesa/main/api_arrayelt.c79
-rw-r--r--mesalib/src/mesa/main/api_loopback.c60
-rw-r--r--mesalib/src/mesa/main/api_loopback.h16
-rw-r--r--mesalib/src/mesa/main/arrayobj.c192
-rw-r--r--mesalib/src/mesa/main/arrayobj.h9
-rw-r--r--mesalib/src/mesa/main/blend.c37
-rw-r--r--mesalib/src/mesa/main/blend.h16
-rw-r--r--mesalib/src/mesa/main/blit.c219
-rw-r--r--mesalib/src/mesa/main/blit.h13
-rwxr-xr-xmesalib/src/mesa/main/bufferobj.c105
-rw-r--r--mesalib/src/mesa/main/buffers.c261
-rw-r--r--mesalib/src/mesa/main/buffers.h29
-rw-r--r--mesalib/src/mesa/main/clear.c106
-rw-r--r--mesalib/src/mesa/main/clear.h16
-rw-r--r--mesalib/src/mesa/main/compute.c20
-rw-r--r--mesalib/src/mesa/main/context.c7
-rw-r--r--mesalib/src/mesa/main/context.h20
-rw-r--r--mesalib/src/mesa/main/dd.h20
-rw-r--r--mesalib/src/mesa/main/extensions.c3
-rw-r--r--mesalib/src/mesa/main/fbobject.c1308
-rw-r--r--mesalib/src/mesa/main/fbobject.h81
-rw-r--r--mesalib/src/mesa/main/ffvertex_prog.c2
-rw-r--r--mesalib/src/mesa/main/framebuffer.c23
-rw-r--r--mesalib/src/mesa/main/framebuffer.h7
-rw-r--r--mesalib/src/mesa/main/genmipmap.c7
-rw-r--r--mesalib/src/mesa/main/get.c9
-rw-r--r--mesalib/src/mesa/main/mtypes.h17
-rw-r--r--mesalib/src/mesa/main/pipelineobj.c6
-rwxr-xr-xmesalib/src/mesa/main/queryobj.c19
-rw-r--r--mesalib/src/mesa/main/readpix.c4
-rw-r--r--mesalib/src/mesa/main/samplerobj.c7
-rw-r--r--mesalib/src/mesa/main/shader_query.cpp24
-rw-r--r--mesalib/src/mesa/main/shaderimage.c130
-rw-r--r--mesalib/src/mesa/main/shaderimage.h21
-rw-r--r--mesalib/src/mesa/main/state.c25
-rw-r--r--mesalib/src/mesa/main/texenv.c2
-rw-r--r--mesalib/src/mesa/main/texgetimage.c14
-rw-r--r--mesalib/src/mesa/main/teximage.c74
-rw-r--r--mesalib/src/mesa/main/texobj.c14
-rw-r--r--mesalib/src/mesa/main/texparam.c86
-rw-r--r--mesalib/src/mesa/main/texstorage.c7
-rw-r--r--mesalib/src/mesa/main/transformfeedback.c42
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp4
-rw-r--r--mesalib/src/mesa/main/varray.c857
-rw-r--r--mesalib/src/mesa/main/varray.h55
-rw-r--r--mesalib/src/mesa/main/version.c332
-rw-r--r--mesalib/src/mesa/main/vtxfmt.c12
-rw-r--r--mesalib/src/mesa/program/prog_statevars.c4
-rw-r--r--mesalib/src/mesa/program/prog_to_nir.c2
-rw-r--r--mesalib/src/mesa/program/program.c3
-rw-r--r--mesalib/src/mesa/program/program.h22
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_array.c172
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_framebuffer.c5
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_fbo.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_flush.c35
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_flush.h3
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_perfmon.c425
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_perfmon.h64
-rw-r--r--mesalib/src/mesa/state_tracker/st_context.c16
-rw-r--r--mesalib/src/mesa/state_tracker/st_context.h3
-rw-r--r--mesalib/src/mesa/state_tracker/st_extensions.c10
-rw-r--r--mesalib/src/mesa/state_tracker/st_format.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp30
-rw-r--r--mesalib/src/mesa/state_tracker/st_manager.c4
-rw-r--r--mesalib/src/mesa/state_tracker/st_program.c5
-rw-r--r--mesalib/src/mesa/state_tracker/st_program.h1
-rw-r--r--mesalib/src/mesa/swrast/s_drawpix.c29
-rw-r--r--mesalib/src/mesa/swrast/s_texrender.c2
-rw-r--r--mesalib/src/mesa/vbo/vbo_attrib_tmp.h119
-rw-r--r--mesalib/src/mesa/vbo/vbo_context.h17
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_api.c83
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_api.c14
-rw-r--r--mesalib/src/mesa/vbo/vbo_split_copy.c1
77 files changed, 4462 insertions, 1051 deletions
diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources
index 1293d4135..83f500fbf 100644
--- a/mesalib/src/mesa/Makefile.sources
+++ b/mesalib/src/mesa/Makefile.sources
@@ -434,6 +434,8 @@ STATETRACKER_FILES = \
state_tracker/st_cb_flush.h \
state_tracker/st_cb_msaa.c \
state_tracker/st_cb_msaa.h \
+ state_tracker/st_cb_perfmon.c \
+ state_tracker/st_cb_perfmon.h \
state_tracker/st_cb_program.c \
state_tracker/st_cb_program.h \
state_tracker/st_cb_queryobj.c \
diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c
index 0d094ddf4..71c1a7639 100644
--- a/mesalib/src/mesa/drivers/common/driverfuncs.c
+++ b/mesalib/src/mesa/drivers/common/driverfuncs.c
@@ -172,7 +172,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
driver->UnmapRenderbuffer = _swrast_unmap_soft_renderbuffer;
driver->RenderTexture = _swrast_render_texture;
driver->FinishRenderTexture = _swrast_finish_render_texture;
- driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
+ driver->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw;
driver->ValidateFramebuffer = _mesa_validate_framebuffer;
driver->BlitFramebuffer = _swrast_BlitFramebuffer;
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c
index d2ab7b8de..214a68a91 100644
--- a/mesalib/src/mesa/drivers/common/meta.c
+++ b/mesalib/src/mesa/drivers/common/meta.c
@@ -1211,7 +1211,8 @@ _mesa_meta_end(struct gl_context *ctx)
_mesa_BindRenderbuffer(GL_RENDERBUFFER, save->RenderbufferName);
if (state & MESA_META_DRAW_BUFFERS) {
- _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, save->ColorDrawBuffers, NULL);
+ _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers,
+ save->ColorDrawBuffers, NULL);
}
ctx->Meta->SaveStackDepth--;
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
index d07988a40..edd0c00f0 100755
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -66,6 +66,8 @@
#include "swrast_priv.h"
#include "swrast/s_context.h"
+#include <sys/types.h>
+
PUBLIC const __DRIextension **__driDriverGetExtensions_swrast(void);
const char * const swrast_vendor_string = "Mesa Project";
@@ -142,6 +144,16 @@ swrast_query_renderer_integer(__DRIscreen *psp, int param,
value[0] = 0;
return 0;
case __DRI2_RENDERER_VIDEO_MEMORY: {
+ /* This should probably share code with os_get_total_physical_memory()
+ * from src/gallium/auxiliary/os/os_misc.c
+ */
+#if defined(CTL_HW) && defined(HW_MEMSIZE)
+ int mib[2] = { CTL_HW, HW_MEMSIZE };
+ unsigned long system_memory_bytes;
+ size_t len = sizeof(system_memory_bytes);
+ if (sysctl(mib, 2, &system_memory_bytes, &len, NULL, 0) != 0)
+ return -1;
+#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE)
/* XXX: Do we want to return the full amount of system memory ? */
#ifndef _MSC_VER
const long system_memory_pages = sysconf(_SC_PHYS_PAGES);
@@ -152,6 +164,9 @@ swrast_query_renderer_integer(__DRIscreen *psp, int param,
const uint64_t system_memory_bytes = (uint64_t) system_memory_pages
* (uint64_t) system_page_size;
+#else
+#error "Unsupported platform"
+#endif
const unsigned system_memory_megabytes =
(unsigned) (system_memory_bytes / (1024 * 1024));
@@ -953,6 +968,7 @@ static const __DRIextension *swrast_driver_extensions[] = {
&driCoreExtension.base,
&driSWRastExtension.base,
&driCopySubBufferExtension.base,
+ &dri2ConfigQueryExtension.base,
&swrast_vtable.base,
NULL
};
diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c
index ea015fd65..92d8238f4 100644
--- a/mesalib/src/mesa/main/api_arrayelt.c
+++ b/mesalib/src/mesa/main/api_arrayelt.c
@@ -1258,12 +1258,37 @@ VertexAttribI4uiv(GLuint index, const GLuint *v)
CALL_VertexAttribI4uivEXT(GET_DISPATCH(), (index, v));
}
+/* GL_DOUBLE unconverted attributes */
+
+static void GLAPIENTRY
+VertexAttribL1dv(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttribL1dv(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY
+VertexAttribL2dv(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttribL2dv(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY
+VertexAttribL3dv(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttribL3dv(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY
+VertexAttribL4dv(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttribL4dv(GET_DISPATCH(), (index, v));
+}
/*
* Array [unnormalized/normalized/integer][size][type] of VertexAttrib
* functions
*/
-static attrib_func AttribFuncsARB[3][4][NUM_TYPES] = {
+static attrib_func AttribFuncsARB[4][4][NUM_TYPES] = {
{
/* non-normalized */
{
@@ -1405,7 +1430,55 @@ static attrib_func AttribFuncsARB[3][4][NUM_TYPES] = {
NULL, /* GL_FLOAT */
NULL /* GL_DOUBLE */
}
+ },
+ {
+ /* double-valued */
+ {
+ /* size 1 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (attrib_func) VertexAttribL1dv,
+ },
+ {
+ /* size 2 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (attrib_func) VertexAttribL2dv,
+ },
+ {
+ /* size 3 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (attrib_func) VertexAttribL3dv,
+ },
+ {
+ /* size 4 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (attrib_func) VertexAttribL4dv,
+ }
}
+
};
@@ -1571,7 +1644,9 @@ _ae_update_state(struct gl_context *ctx)
* change from one execution of _ae_ArrayElement() to
* the next. Doing so caused UT to break.
*/
- if (at->array->Integer)
+ if (at->array->Doubles)
+ intOrNorm = 3;
+ else if (at->array->Integer)
intOrNorm = 2;
else if (at->array->Normalized)
intOrNorm = 1;
diff --git a/mesalib/src/mesa/main/api_loopback.c b/mesalib/src/mesa/main/api_loopback.c
index d10ae15ea..9932a8373 100644
--- a/mesalib/src/mesa/main/api_loopback.c
+++ b/mesalib/src/mesa/main/api_loopback.c
@@ -84,6 +84,10 @@
#define ATTRIBI_4UI(index,x,y,z,w) CALL_VertexAttribI4uiEXT(GET_DISPATCH(), (index,x,y,z,w))
+#define ATTRIB1_D(index,x) CALL_VertexAttribL1d(GET_DISPATCH(), (index,x))
+#define ATTRIB2_D(index,x,y) CALL_VertexAttribL2d(GET_DISPATCH(), (index,x,y))
+#define ATTRIB3_D(index,x,y,z) CALL_VertexAttribL3d(GET_DISPATCH(), (index,x,y,z))
+#define ATTRIB4_D(index,x,y,z,w) CALL_VertexAttribL4d(GET_DISPATCH(), (index,x,y,z,w))
void GLAPIENTRY
_mesa_Color3b( GLbyte red, GLbyte green, GLbyte blue )
@@ -1490,8 +1494,53 @@ _mesa_VertexAttribI4usv(GLuint index, const GLushort *v)
ATTRIBI_4UI(index, v[0], v[1], v[2], v[3]);
}
+void GLAPIENTRY
+_mesa_VertexAttribL1d(GLuint index, GLdouble x)
+{
+ ATTRIB1_D(index, x);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL2d(GLuint index, GLdouble x, GLdouble y)
+{
+ ATTRIB2_D(index, x, y);
+}
+void GLAPIENTRY
+_mesa_VertexAttribL3d(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ ATTRIB3_D(index, x, y, z);
+}
+void GLAPIENTRY
+_mesa_VertexAttribL4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ ATTRIB4_D(index, x, y, z, w);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL1dv(GLuint index, const GLdouble *v)
+{
+ ATTRIB1_D(index, v[0]);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL2dv(GLuint index, const GLdouble *v)
+{
+ ATTRIB2_D(index, v[0], v[1]);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL3dv(GLuint index, const GLdouble *v)
+{
+ ATTRIB3_D(index, v[0], v[1], v[2]);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL4dv(GLuint index, const GLdouble *v)
+{
+ ATTRIB4_D(index, v[0], v[1], v[2], v[3]);
+}
/*
* This code never registers handlers for any of the entry points
@@ -1723,5 +1772,16 @@ _mesa_loopback_init_api_table(const struct gl_context *ctx,
SET_VertexAttribI4sv(dest, _mesa_VertexAttribI4sv);
SET_VertexAttribI4ubv(dest, _mesa_VertexAttribI4ubv);
SET_VertexAttribI4usv(dest, _mesa_VertexAttribI4usv);
+
+ /* GL 4.1 / GL_ARB_vertex_attrib_64bit */
+ SET_VertexAttribL1d(dest, _mesa_VertexAttribL1d);
+ SET_VertexAttribL2d(dest, _mesa_VertexAttribL2d);
+ SET_VertexAttribL3d(dest, _mesa_VertexAttribL3d);
+ SET_VertexAttribL4d(dest, _mesa_VertexAttribL4d);
+
+ SET_VertexAttribL1dv(dest, _mesa_VertexAttribL1dv);
+ SET_VertexAttribL2dv(dest, _mesa_VertexAttribL2dv);
+ SET_VertexAttribL3dv(dest, _mesa_VertexAttribL3dv);
+ SET_VertexAttribL4dv(dest, _mesa_VertexAttribL4dv);
}
}
diff --git a/mesalib/src/mesa/main/api_loopback.h b/mesalib/src/mesa/main/api_loopback.h
index 44514405b..026bfd68e 100644
--- a/mesalib/src/mesa/main/api_loopback.h
+++ b/mesalib/src/mesa/main/api_loopback.h
@@ -464,5 +464,21 @@ _mesa_VertexAttribI4ubv(GLuint index, const GLubyte *v);
void GLAPIENTRY
_mesa_VertexAttribI4usv(GLuint index, const GLushort *v);
+void GLAPIENTRY
+_mesa_VertexAttribL1d(GLuint index, GLdouble x);
+void GLAPIENTRY
+_mesa_VertexAttribL2d(GLuint index, GLdouble x, GLdouble y);
+void GLAPIENTRY
+_mesa_VertexAttribL3d(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+void GLAPIENTRY
+_mesa_VertexAttribL4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void GLAPIENTRY
+_mesa_VertexAttribL1dv(GLuint index, const GLdouble *v);
+void GLAPIENTRY
+_mesa_VertexAttribL2dv(GLuint index, const GLdouble *v);
+void GLAPIENTRY
+_mesa_VertexAttribL3dv(GLuint index, const GLdouble *v);
+void GLAPIENTRY
+_mesa_VertexAttribL4dv(GLuint index, const GLdouble *v);
#endif /* API_LOOPBACK_H */
diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c
index 3c8ffb5a4..320f435ea 100644
--- a/mesalib/src/mesa/main/arrayobj.c
+++ b/mesalib/src/mesa/main/arrayobj.c
@@ -75,6 +75,61 @@ _mesa_lookup_vao(struct gl_context *ctx, GLuint id)
/**
+ * Looks up the array object for the given ID.
+ *
+ * Unlike _mesa_lookup_vao, this function generates a GL_INVALID_OPERATION
+ * error if the array object does not exist. It also returns the default
+ * array object when ctx is a compatibility profile context and id is zero.
+ */
+struct gl_vertex_array_object *
+_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller)
+{
+ /* The ARB_direct_state_access specification says:
+ *
+ * "<vaobj> is [compatibility profile:
+ * zero, indicating the default vertex array object, or]
+ * the name of the vertex array object."
+ */
+ if (id == 0) {
+ if (ctx->API == API_OPENGL_CORE) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(zero is not valid vaobj name in a core profile "
+ "context)", caller);
+ return NULL;
+ }
+
+ return ctx->Array.DefaultVAO;
+ } else {
+ struct gl_vertex_array_object *vao;
+
+ if (ctx->Array.LastLookedUpVAO &&
+ ctx->Array.LastLookedUpVAO->Name == id) {
+ vao = ctx->Array.LastLookedUpVAO;
+ } else {
+ vao = (struct gl_vertex_array_object *)
+ _mesa_HashLookup(ctx->Array.Objects, id);
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing
+ * vertex array object."
+ */
+ if (!vao || !vao->EverBound) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(non-existent vaobj=%u)", caller, id);
+ return NULL;
+ }
+
+ _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao);
+ }
+
+ return vao;
+ }
+}
+
+
+/**
* For all the vertex binding points in the array object, unbind any pointers
* to any buffer objects (VBOs).
* This is done just prior to array object destruction.
@@ -200,6 +255,7 @@ init_array(struct gl_context *ctx,
array->Enabled = GL_FALSE;
array->Normalized = GL_FALSE;
array->Integer = GL_FALSE;
+ array->Doubles = GL_FALSE;
array->_ElementSize = size * _mesa_sizeof_type(type);
array->VertexBinding = index;
@@ -469,6 +525,9 @@ _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids)
/* The ID is immediately freed for re-use */
remove_array_object(ctx, obj);
+ if (ctx->Array.LastLookedUpVAO == obj)
+ _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL);
+
/* Unreference the array object.
* If refcount hits zero, the object will be deleted.
*/
@@ -480,19 +539,23 @@ _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids)
/**
* Generate a set of unique array object IDs and store them in \c arrays.
- * Helper for _mesa_GenVertexArrays[APPLE]() functions below.
+ * Helper for _mesa_GenVertexArrays[APPLE]() and _mesa_CreateVertexArrays()
+ * below.
+ *
* \param n Number of IDs to generate.
* \param arrays Array of \c n locations to store the IDs.
- * \param vboOnly Will arrays have to reside in VBOs?
+ * \param create Indicates that the objects should also be created.
+ * \param func The name of the GL entry point.
*/
static void
-gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays)
+gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays,
+ bool create, const char *func)
{
GLuint first;
GLint i;
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArrays");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
return;
}
@@ -502,16 +565,20 @@ gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays)
first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n);
- /* Allocate new, empty array objects and return identifiers */
+ /* For the sake of simplicity we create the array objects in both
+ * the Gen* and Create* cases. The only difference is the value of
+ * EverBound, which is set to true in the Create* case.
+ */
for (i = 0; i < n; i++) {
struct gl_vertex_array_object *obj;
GLuint name = first + i;
obj = (*ctx->Driver.NewArrayObject)( ctx, name );
if (!obj) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArrays");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
return;
}
+ obj->EverBound = create;
save_array_object(ctx, obj);
arrays[i] = first + i;
}
@@ -526,7 +593,7 @@ void GLAPIENTRY
_mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
{
GET_CURRENT_CONTEXT(ctx);
- gen_vertex_arrays(ctx, n, arrays);
+ gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays");
}
@@ -538,7 +605,27 @@ void GLAPIENTRY
_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
{
GET_CURRENT_CONTEXT(ctx);
- gen_vertex_arrays(ctx, n, arrays);
+ gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArraysAPPLE");
+}
+
+
+/**
+ * ARB_direct_state_access
+ * Generates ID's and creates the array objects.
+ */
+void GLAPIENTRY
+_mesa_CreateVertexArrays(GLsizei n, GLuint *arrays)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateVertexArrays(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays");
}
@@ -565,3 +652,92 @@ _mesa_IsVertexArray( GLuint id )
return obj->EverBound;
}
+
+
+/**
+ * Sets the element array buffer binding of a vertex array object.
+ *
+ * This is the ARB_direct_state_access equivalent of
+ * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer).
+ */
+void GLAPIENTRY
+_mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+ struct gl_buffer_object *bufObj;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayElementBuffer(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ /* The GL_ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayElementBuffer
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao =_mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayElementBuffer");
+ if (!vao)
+ return;
+
+ /* The GL_ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <buffer> is not zero or
+ * the name of an existing buffer object."
+ */
+ if (buffer != 0)
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
+ "glVertexArrayElementBuffer");
+ else
+ bufObj = ctx->Shared->NullBufferObj;
+
+ if (bufObj)
+ _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
+}
+
+
+void GLAPIENTRY
+_mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexArrayiv(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The GL_ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing
+ * vertex array object."
+ */
+ vao =_mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayiv");
+ if (!vao)
+ return;
+
+ /* The GL_ARB_direct_state_access specification says:
+ *
+ * "An INVALID_ENUM error is generated if <pname> is not
+ * ELEMENT_ARRAY_BUFFER_BINDING."
+ */
+ if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetVertexArrayiv(pname != "
+ "GL_ELEMENT_ARRAY_BUFFER_BINDING)");
+ return;
+ }
+
+ param[0] = vao->IndexBufferObj->Name;
+}
diff --git a/mesalib/src/mesa/main/arrayobj.h b/mesalib/src/mesa/main/arrayobj.h
index 3c1f91835..6a4247f4a 100644
--- a/mesalib/src/mesa/main/arrayobj.h
+++ b/mesalib/src/mesa/main/arrayobj.h
@@ -49,6 +49,9 @@ extern struct gl_vertex_array_object *
_mesa_lookup_vao(struct gl_context *ctx, GLuint id);
extern struct gl_vertex_array_object *
+_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller);
+
+extern struct gl_vertex_array_object *
_mesa_new_vao(struct gl_context *ctx, GLuint name);
extern void
@@ -93,6 +96,12 @@ void GLAPIENTRY _mesa_GenVertexArrays(GLsizei n, GLuint *arrays);
void GLAPIENTRY _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *buffer);
+void GLAPIENTRY _mesa_CreateVertexArrays(GLsizei n, GLuint *arrays);
+
GLboolean GLAPIENTRY _mesa_IsVertexArray( GLuint id );
+void GLAPIENTRY _mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer);
+
+void GLAPIENTRY _mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param);
+
#endif /* ARRAYOBJ_H */
diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c
index 774fc888e..d869fa2aa 100644
--- a/mesalib/src/mesa/main/blend.c
+++ b/mesalib/src/mesa/main/blend.c
@@ -769,7 +769,7 @@ _mesa_ClampColor(GLenum target, GLenum clamp)
}
FLUSH_VERTICES(ctx, _NEW_LIGHT);
ctx->Light.ClampVertexColor = clamp;
- _mesa_update_clamp_vertex_color(ctx);
+ _mesa_update_clamp_vertex_color(ctx, ctx->DrawBuffer);
break;
case GL_CLAMP_FRAGMENT_COLOR_ARB:
if (ctx->API == API_OPENGL_CORE &&
@@ -778,7 +778,7 @@ _mesa_ClampColor(GLenum target, GLenum clamp)
}
FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP);
ctx->Color.ClampFragmentColor = clamp;
- _mesa_update_clamp_fragment_color(ctx);
+ _mesa_update_clamp_fragment_color(ctx, ctx->DrawBuffer);
break;
case GL_CLAMP_READ_COLOR_ARB:
ctx->Color.ClampReadColor = clamp;
@@ -807,50 +807,55 @@ get_clamp_color(const struct gl_framebuffer *fb, GLenum clamp)
}
GLboolean
-_mesa_get_clamp_fragment_color(const struct gl_context *ctx)
+_mesa_get_clamp_fragment_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb)
{
- return get_clamp_color(ctx->DrawBuffer,
- ctx->Color.ClampFragmentColor);
+ return get_clamp_color(drawFb, ctx->Color.ClampFragmentColor);
}
GLboolean
-_mesa_get_clamp_vertex_color(const struct gl_context *ctx)
+_mesa_get_clamp_vertex_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb)
{
- return get_clamp_color(ctx->DrawBuffer, ctx->Light.ClampVertexColor);
+ return get_clamp_color(drawFb, ctx->Light.ClampVertexColor);
}
GLboolean
-_mesa_get_clamp_read_color(const struct gl_context *ctx)
+_mesa_get_clamp_read_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *readFb)
{
- return get_clamp_color(ctx->ReadBuffer, ctx->Color.ClampReadColor);
+ return get_clamp_color(readFb, ctx->Color.ClampReadColor);
}
/**
* Update the ctx->Color._ClampFragmentColor field
*/
void
-_mesa_update_clamp_fragment_color(struct gl_context *ctx)
+_mesa_update_clamp_fragment_color(struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb)
{
- struct gl_framebuffer *fb = ctx->DrawBuffer;
-
/* Don't clamp if:
* - there is no colorbuffer
* - all colorbuffers are unsigned normalized, so clamping has no effect
* - there is an integer colorbuffer
*/
- if (!fb || !fb->_HasSNormOrFloatColorBuffer || fb->_IntegerColor)
+ if (!drawFb || !drawFb->_HasSNormOrFloatColorBuffer ||
+ drawFb->_IntegerColor)
ctx->Color._ClampFragmentColor = GL_FALSE;
else
- ctx->Color._ClampFragmentColor = _mesa_get_clamp_fragment_color(ctx);
+ ctx->Color._ClampFragmentColor =
+ _mesa_get_clamp_fragment_color(ctx, drawFb);
}
/**
* Update the ctx->Color._ClampVertexColor field
*/
void
-_mesa_update_clamp_vertex_color(struct gl_context *ctx)
+_mesa_update_clamp_vertex_color(struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb)
{
- ctx->Light._ClampVertexColor = _mesa_get_clamp_vertex_color(ctx);
+ ctx->Light._ClampVertexColor =
+ _mesa_get_clamp_vertex_color(ctx, drawFb);
}
/**
diff --git a/mesalib/src/mesa/main/blend.h b/mesalib/src/mesa/main/blend.h
index fe31a7440..8ab9e02fc 100644
--- a/mesalib/src/mesa/main/blend.h
+++ b/mesalib/src/mesa/main/blend.h
@@ -37,6 +37,7 @@
#include "formats.h"
struct gl_context;
+struct gl_framebuffer;
extern void GLAPIENTRY
@@ -101,19 +102,24 @@ extern void GLAPIENTRY
_mesa_ClampColor(GLenum target, GLenum clamp);
extern GLboolean
-_mesa_get_clamp_fragment_color(const struct gl_context *ctx);
+_mesa_get_clamp_fragment_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb);
extern GLboolean
-_mesa_get_clamp_vertex_color(const struct gl_context *ctx);
+_mesa_get_clamp_vertex_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb);
extern GLboolean
-_mesa_get_clamp_read_color(const struct gl_context *ctx);
+_mesa_get_clamp_read_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *readFb);
extern void
-_mesa_update_clamp_fragment_color(struct gl_context *ctx);
+_mesa_update_clamp_fragment_color(struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb);
extern void
-_mesa_update_clamp_vertex_color(struct gl_context *ctx);
+_mesa_update_clamp_vertex_color(struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb);
extern mesa_format
_mesa_get_render_format(const struct gl_context *ctx, mesa_format format);
diff --git a/mesalib/src/mesa/main/blit.c b/mesalib/src/mesa/main/blit.c
index 0694466eb..fac972450 100644
--- a/mesalib/src/mesa/main/blit.c
+++ b/mesalib/src/mesa/main/blit.c
@@ -34,6 +34,7 @@
#include "enums.h"
#include "blit.h"
#include "fbobject.h"
+#include "framebuffer.h"
#include "glformats.h"
#include "mtypes.h"
#include "state.h"
@@ -148,38 +149,25 @@ is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
}
-/**
- * Blit rectangular region, optionally from one framebuffer to another.
- *
- * Note, if the src buffer is multisampled and the dest is not, this is
- * when the samples must be resolved to a single color.
- */
-void GLAPIENTRY
-_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
+void
+_mesa_blit_framebuffer(struct gl_context *ctx,
+ struct gl_framebuffer *readFb,
+ struct gl_framebuffer *drawFb,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter, const char *func)
{
const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
- const struct gl_framebuffer *readFb, *drawFb;
- GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx,
- "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1,
- mask, _mesa_lookup_enum_by_nr(filter));
-
- if (ctx->NewState) {
- _mesa_update_state(ctx);
- }
+ /* Update completeness status of readFb and drawFb. */
+ _mesa_update_framebuffer(ctx, readFb, drawFb);
- readFb = ctx->ReadBuffer;
- drawFb = ctx->DrawBuffer;
+ /* Make sure drawFb has an initialized bounding box. */
+ _mesa_update_draw_buffer_bounds(ctx, drawFb);
if (!readFb || !drawFb) {
/* This will normally never happen but someday we may want to
@@ -192,12 +180,12 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glBlitFramebufferEXT(incomplete draw/read buffers)");
+ "%s(incomplete draw/read buffers)", func);
return;
}
if (!is_valid_blit_filter(ctx, filter)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)",
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func,
_mesa_lookup_enum_by_nr(filter));
return;
}
@@ -205,13 +193,13 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
(readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)",
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func,
_mesa_lookup_enum_by_nr(filter));
return;
}
if (mask & ~legalMaskBits) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func);
return;
}
@@ -219,13 +207,13 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
&& filter != GL_NEAREST) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
+ "%s(depth/stencil requires GL_NEAREST filter)", func);
return;
}
/* get color read/draw renderbuffers */
if (mask & GL_COLOR_BUFFER_BIT) {
- const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers;
+ const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
const struct gl_renderbuffer *colorDrawRb = NULL;
GLuint i;
@@ -241,7 +229,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
}
else {
for (i = 0; i < numColorDrawBuffers; i++) {
- colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+ colorDrawRb = drawFb->_ColorDrawBuffers[i];
if (!colorDrawRb)
continue;
@@ -257,15 +245,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
*/
if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(source and destination color "
- "buffer cannot be the same)");
+ "%s(source and destination color "
+ "buffer cannot be the same)", func);
return;
}
if (!compatible_color_datatypes(colorReadRb->Format,
colorDrawRb->Format)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(color buffer datatypes mismatch)");
+ "%s(color buffer datatypes mismatch)", func);
return;
}
/* extra checks for multisample copies... */
@@ -273,7 +261,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
/* color formats must match */
if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
+ "%s(bad src/dst multisample pixel formats)", func);
return;
}
}
@@ -286,7 +274,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
if (type == GL_INT || type == GL_UNSIGNED_INT) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(integer color type)");
+ "%s(integer color type)", func);
return;
}
}
@@ -306,15 +294,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
* ignored."
*/
if ((readRb == NULL) || (drawRb == NULL)) {
- mask &= ~GL_STENCIL_BUFFER_BIT;
+ mask &= ~GL_STENCIL_BUFFER_BIT;
}
else {
int read_z_bits, draw_z_bits;
if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(source and destination stencil "
- "buffer cannot be the same)");
+ "%s(source and destination stencil "
+ "buffer cannot be the same)", func);
return;
}
@@ -324,7 +312,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
* there is only one: GL_UNSIGNED_INT.
*/
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(stencil attachment format mismatch)");
+ "%s(stencil attachment format mismatch)", func);
return;
}
@@ -340,8 +328,8 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
_mesa_get_format_datatype(readRb->Format) !=
_mesa_get_format_datatype(drawRb->Format))) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
- "(stencil attachment depth format mismatch)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(stencil attachment depth format mismatch)", func);
return;
}
}
@@ -360,15 +348,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
* ignored."
*/
if ((readRb == NULL) || (drawRb == NULL)) {
- mask &= ~GL_DEPTH_BUFFER_BIT;
+ mask &= ~GL_DEPTH_BUFFER_BIT;
}
else {
int read_s_bit, draw_s_bit;
if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(source and destination depth "
- "buffer cannot be the same)");
+ "%s(source and destination depth "
+ "buffer cannot be the same)", func);
return;
}
@@ -377,7 +365,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
(_mesa_get_format_datatype(readRb->Format) !=
_mesa_get_format_datatype(drawRb->Format))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(depth attachment format mismatch)");
+ "%s(depth attachment format mismatch)", func);
return;
}
@@ -389,8 +377,8 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
* we should ignore the stencil format check.
*/
if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
- "(depth attachment stencil bits mismatch)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(depth attachment stencil bits mismatch)", func);
return;
}
}
@@ -406,7 +394,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
*/
if (drawFb->Visual.samples > 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(destination samples must be 0)");
+ "%s(destination samples must be 0)", func);
return;
}
@@ -426,7 +414,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
&& (srcX0 != dstX0 || srcY0 != dstY0
|| srcX1 != dstX1 || srcY1 != dstY1)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(bad src/dst multisample region)");
+ "%s(bad src/dst multisample region)", func);
return;
}
} else {
@@ -434,7 +422,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
drawFb->Visual.samples > 0 &&
readFb->Visual.samples != drawFb->Visual.samples) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(mismatched samples)");
+ "%s(mismatched samples)", func);
return;
}
@@ -445,7 +433,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
+ "%s(bad src/dst multisample region sizes)", func);
return;
}
}
@@ -457,43 +445,44 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
const struct gl_renderbuffer *colorDrawRb = NULL;
GLuint i = 0;
- printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
- " 0x%x, 0x%x)\n",
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1,
- mask, filter);
+ printf("%s(%d, %d, %d, %d, %d, %d, %d, %d,"
+ " 0x%x, 0x%x)\n", func,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+
if (colorReadRb) {
const struct gl_renderbuffer_attachment *att;
att = find_attachment(readFb, colorReadRb);
printf(" Src FBO %u RB %u (%dx%d) ",
- readFb->Name, colorReadRb->Name,
- colorReadRb->Width, colorReadRb->Height);
+ readFb->Name, colorReadRb->Name,
+ colorReadRb->Width, colorReadRb->Height);
if (att && att->Texture) {
printf("Tex %u tgt 0x%x level %u face %u",
- att->Texture->Name,
- att->Texture->Target,
- att->TextureLevel,
- att->CubeMapFace);
+ att->Texture->Name,
+ att->Texture->Target,
+ att->TextureLevel,
+ att->CubeMapFace);
}
printf("\n");
/* Print all active color render buffers */
- for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
- colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+ for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
+ colorDrawRb = drawFb->_ColorDrawBuffers[i];
if (!colorDrawRb)
continue;
att = find_attachment(drawFb, colorDrawRb);
printf(" Dst FBO %u RB %u (%dx%d) ",
- drawFb->Name, colorDrawRb->Name,
- colorDrawRb->Width, colorDrawRb->Height);
+ drawFb->Name, colorDrawRb->Name,
+ colorDrawRb->Width, colorDrawRb->Height);
if (att && att->Texture) {
printf("Tex %u tgt 0x%x level %u face %u",
- att->Texture->Name,
- att->Texture->Target,
- att->TextureLevel,
- att->CubeMapFace);
+ att->Texture->Name,
+ att->Texture->Target,
+ att->TextureLevel,
+ att->CubeMapFace);
}
printf("\n");
}
@@ -507,8 +496,94 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
}
assert(ctx->Driver.BlitFramebuffer);
- ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
+ ctx->Driver.BlitFramebuffer(ctx, readFb, drawFb,
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
mask, filter);
}
+
+
+/**
+ * Blit rectangular region, optionally from one framebuffer to another.
+ *
+ * Note, if the src buffer is multisampled and the dest is not, this is
+ * when the samples must be resolved to a single color.
+ */
+void GLAPIENTRY
+_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx,
+ "glBlitFramebuffer(%d, %d, %d, %d, "
+ " %d, %d, %d, %d, 0x%x, %s)\n",
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, _mesa_lookup_enum_by_nr(filter));
+
+ _mesa_blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter, "glBlitFramebuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *readFb, *drawFb;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitNamedFramebuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx,
+ "glBlitNamedFramebuffer(%u %u %d, %d, %d, %d, "
+ " %d, %d, %d, %d, 0x%x, %s)\n",
+ readFramebuffer, drawFramebuffer,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, _mesa_lookup_enum_by_nr(filter));
+
+ /*
+ * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014,
+ * Section 18.3 Copying Pixels):
+ * "... if readFramebuffer or drawFramebuffer is zero (for
+ * BlitNamedFramebuffer), then the default read or draw framebuffer is
+ * used as the corresponding source or destination framebuffer,
+ * respectively."
+ */
+ if (readFramebuffer) {
+ readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer,
+ "glBlitNamedFramebuffer");
+ if (!readFb)
+ return;
+ }
+ else
+ readFb = ctx->WinSysReadBuffer;
+
+ if (drawFramebuffer) {
+ drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer,
+ "glBlitNamedFramebuffer");
+ if (!drawFb)
+ return;
+ }
+ else
+ drawFb = ctx->WinSysDrawBuffer;
+
+ _mesa_blit_framebuffer(ctx, readFb, drawFb,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter, "glBlitNamedFramebuffer");
+}
diff --git a/mesalib/src/mesa/main/blit.h b/mesalib/src/mesa/main/blit.h
index 01a958af5..54b946e31 100644
--- a/mesalib/src/mesa/main/blit.h
+++ b/mesalib/src/mesa/main/blit.h
@@ -28,11 +28,24 @@
#include "glheader.h"
+extern void
+_mesa_blit_framebuffer(struct gl_context *ctx,
+ struct gl_framebuffer *readFb,
+ struct gl_framebuffer *drawFb,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter, const char *func);
extern void GLAPIENTRY
_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
+extern void GLAPIENTRY
+_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+
#endif /* BLIT_H */
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index 4a116acfe..34d43943f 100755
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -1303,6 +1303,12 @@ create_buffers(GLsizei n, GLuint *buffers, bool dsa)
const char *func = dsa ? "glCreateBuffers" : "glGenBuffers";
+ if (dsa && !ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", func);
+ return;
+ }
+
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "%s(%d)\n", func, n);
@@ -1477,6 +1483,13 @@ _mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedBufferStorage(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferStorage");
if (!bufObj)
return;
@@ -1603,6 +1616,13 @@ _mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid *data,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedBufferData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferData");
if (!bufObj)
return;
@@ -1673,6 +1693,13 @@ _mesa_NamedBufferSubData(GLuint buffer, GLintptr offset,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedBufferSubData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferSubData");
if (!bufObj)
return;
@@ -1710,6 +1737,13 @@ _mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedBufferSubData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glGetNamedBufferSubData");
if (!bufObj)
@@ -1805,6 +1839,13 @@ _mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedBufferData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferData");
if (!bufObj)
return;
@@ -1842,6 +1883,13 @@ _mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedBufferSubData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glClearNamedBufferSubData");
if (!bufObj)
@@ -1930,6 +1978,13 @@ _mesa_UnmapNamedBuffer(GLuint buffer)
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUnmapNamedBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return GL_FALSE;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glUnmapNamedBuffer");
if (!bufObj)
return GL_FALSE;
@@ -2039,6 +2094,13 @@ _mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params)
struct gl_buffer_object *bufObj;
GLint64 parameter;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedBufferParameteriv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glGetNamedBufferParameteriv");
if (!bufObj)
@@ -2059,6 +2121,13 @@ _mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname,
struct gl_buffer_object *bufObj;
GLint64 parameter;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedBufferParameteri64v(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glGetNamedBufferParameteri64v");
if (!bufObj)
@@ -2098,6 +2167,13 @@ _mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params)
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedBufferPointerv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
if (pname != GL_BUFFER_MAP_POINTER) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointerv(pname != "
"GL_BUFFER_MAP_POINTER)");
@@ -2212,6 +2288,13 @@ _mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *src, *dst;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyNamedBufferSubData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
src = _mesa_lookup_bufferobj_err(ctx, readBuffer,
"glCopyNamedBufferSubData");
if (!src)
@@ -2430,6 +2513,13 @@ _mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapNamedBufferRange(GL_ARB_direct_state_access "
+ "is not supported)");
+ return NULL;
+ }
+
if (!ctx->Extensions.ARB_map_buffer_range) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapNamedBufferRange("
@@ -2497,6 +2587,13 @@ _mesa_MapNamedBuffer(GLuint buffer, GLenum access)
struct gl_buffer_object *bufObj;
GLbitfield accessFlags;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapNamedBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return NULL;
+ }
+
if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)");
return NULL;
@@ -2587,6 +2684,14 @@ _mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFlushMappedNamedBufferRange(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glFlushMappedNamedBufferRange");
if (!bufObj)
diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c
index 37a979092..c83459add 100644
--- a/mesalib/src/mesa/main/buffers.c
+++ b/mesalib/src/mesa/main/buffers.c
@@ -242,16 +242,16 @@ read_buffer_enum_to_index(GLenum buffer)
*
* See the GL_EXT_framebuffer_object spec for more info.
*/
-void GLAPIENTRY
-_mesa_DrawBuffer(GLenum buffer)
+void
+_mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, const char *caller)
{
GLbitfield destMask;
- GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
if (MESA_VERBOSE & VERBOSE_API) {
- _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
+ _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer));
}
if (buffer == GL_NONE) {
@@ -259,33 +259,67 @@ _mesa_DrawBuffer(GLenum buffer)
}
else {
const GLbitfield supportedMask
- = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
+ = supported_buffer_bitmask(ctx, fb);
destMask = draw_buffer_enum_to_bitmask(ctx, buffer);
if (destMask == BAD_MASK) {
/* totally bogus buffer */
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glDrawBuffer(buffer=0x%x)", buffer);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", caller,
+ _mesa_lookup_enum_by_nr(buffer));
return;
}
destMask &= supportedMask;
if (destMask == 0x0) {
/* none of the named color buffers exist! */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawBuffer(buffer=0x%x)", buffer);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffer));
return;
}
}
/* if we get here, there's no error so set new state */
- _mesa_drawbuffers(ctx, 1, &buffer, &destMask);
+ _mesa_drawbuffers(ctx, fb, 1, &buffer, &destMask);
+
+ /* Call device driver function only if fb is the bound draw buffer */
+ if (fb == ctx->DrawBuffer) {
+ if (ctx->Driver.DrawBuffers)
+ ctx->Driver.DrawBuffers(ctx, 1, &buffer);
+ else if (ctx->Driver.DrawBuffer)
+ ctx->Driver.DrawBuffer(ctx, buffer);
+ }
+}
- /*
- * Call device driver function.
- */
- if (ctx->Driver.DrawBuffers)
- ctx->Driver.DrawBuffers(ctx, 1, &buffer);
- else if (ctx->Driver.DrawBuffer)
- ctx->Driver.DrawBuffer(ctx, buffer);
+
+void GLAPIENTRY
+_mesa_DrawBuffer(GLenum buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_draw_buffer(ctx, ctx->DrawBuffer, buffer, "glDrawBuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferDrawBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glNamedFramebufferDrawBuffer");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ _mesa_draw_buffer(ctx, fb, buf, "glNamedFramebufferDrawBuffer");
}
@@ -298,13 +332,13 @@ _mesa_DrawBuffer(GLenum buffer)
* names cannot specify more than one buffer. For example,
* GL_FRONT_AND_BACK is illegal.
*/
-void GLAPIENTRY
-_mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
+void
+_mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLsizei n, const GLenum *buffers, const char *caller)
{
GLuint output;
GLbitfield usedBufferMask, supportedMask;
GLbitfield destMask[MAX_DRAW_BUFFERS];
- GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
@@ -315,12 +349,18 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* "An INVALID_VALUE error is generated if n is greater than
* MAX_DRAW_BUFFERS."
*/
- if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)");
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller);
+ return;
+ }
+
+ if (n > (GLsizei) ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(n > maximum number of draw buffers)", caller);
return;
}
- supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
+ supportedMask = supported_buffer_bitmask(ctx, fb);
usedBufferMask = 0x0;
/* From the ES 3.0 specification, page 180:
@@ -328,9 +368,9 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* and the constant must be BACK or NONE."
* (same restriction applies with GL_EXT_draw_buffers specification)
*/
- if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(ctx->DrawBuffer) &&
+ if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(fb) &&
(n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffers)", caller);
return;
}
@@ -362,9 +402,11 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
* INVALID_OPERATION results."
*/
- if (_mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] >=
+ if (_mesa_is_user_fbo(fb) && buffers[output] >=
GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(buffers[%d] >= maximum number of draw buffers)",
+ caller, output);
return;
}
@@ -375,9 +417,10 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* 4.5 or 4.6. Otherwise, an INVALID_ENUM error is generated.
*/
if (destMask[output] == BAD_MASK) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
- }
+ }
/* From the OpenGL 4.0 specification, page 256:
* "For both the default framebuffer and framebuffer objects, the
@@ -390,7 +433,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* but the Khronos conformance tests expect INVALID_ENUM.
*/
if (_mesa_bitcount(destMask[output]) > 1) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
}
@@ -407,7 +451,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
destMask[output] &= supportedMask;
if (destMask[output] == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawBuffersARB(unsupported buffer)");
+ "%s(unsupported buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
}
@@ -416,10 +461,12 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* in bufs must be COLOR_ATTACHMENTi or NONE. [...] INVALID_OPERATION."
* (same restriction applies with GL_EXT_draw_buffers specification)
*/
- if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(ctx->DrawBuffer) &&
+ if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(fb) &&
buffers[output] != GL_NONE &&
buffers[output] != GL_COLOR_ATTACHMENT0 + output) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(unsupported buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
}
@@ -430,7 +477,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
*/
if (destMask[output] & usedBufferMask) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawBuffersARB(duplicated buffer)");
+ "%s(duplicated buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
}
@@ -440,17 +488,55 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
}
/* OK, if we get here, there were no errors so set the new state */
- _mesa_drawbuffers(ctx, n, buffers, destMask);
+ _mesa_drawbuffers(ctx, fb, n, buffers, destMask);
/*
- * Call device driver function. Note that n can be equal to 0,
+ * Call device driver function if fb is the bound draw buffer.
+ * Note that n can be equal to 0,
* in which case we don't want to reference buffers[0], which
* may not be valid.
*/
- if (ctx->Driver.DrawBuffers)
- ctx->Driver.DrawBuffers(ctx, n, buffers);
- else if (ctx->Driver.DrawBuffer)
- ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE);
+ if (fb == ctx->DrawBuffer) {
+ if (ctx->Driver.DrawBuffers)
+ ctx->Driver.DrawBuffers(ctx, n, buffers);
+ else if (ctx->Driver.DrawBuffer)
+ ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_draw_buffers(ctx, ctx->DrawBuffer, n, buffers, "glDrawBuffers");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n,
+ const GLenum *bufs)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferDrawBuffers(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glNamedFramebufferDrawBuffers");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ _mesa_draw_buffers(ctx, fb, n, bufs, "glNamedFramebufferDrawBuffers");
}
@@ -459,13 +545,11 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* actual change.
*/
static void
-updated_drawbuffers(struct gl_context *ctx)
+updated_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb)
{
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (ctx->API == API_OPENGL_COMPAT && !ctx->Extensions.ARB_ES2_compatibility) {
- struct gl_framebuffer *fb = ctx->DrawBuffer;
-
/* Flag the FBO as requiring validation. */
if (_mesa_is_user_fbo(fb)) {
fb->_Status = 0;
@@ -482,6 +566,7 @@ updated_drawbuffers(struct gl_context *ctx)
* so nothing should go wrong at this point.
*
* \param ctx current context
+ * \param fb the desired draw buffer
* \param n number of color outputs to set
* \param buffers array[n] of colorbuffer names, like GL_LEFT.
* \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the
@@ -489,10 +574,9 @@ updated_drawbuffers(struct gl_context *ctx)
* BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
*/
void
-_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
- const GLbitfield *destMask)
+_mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLuint n, const GLenum *buffers, const GLbitfield *destMask)
{
- struct gl_framebuffer *fb = ctx->DrawBuffer;
GLbitfield mask[MAX_DRAW_BUFFERS];
GLuint buf;
@@ -518,7 +602,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
while (destMask0) {
GLint bufIndex = ffs(destMask0) - 1;
if (fb->_ColorDrawBufferIndexes[count] != bufIndex) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
fb->_ColorDrawBufferIndexes[count] = bufIndex;
}
count++;
@@ -535,14 +619,14 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
/* only one bit should be set in the destMask[buf] field */
assert(_mesa_bitcount(destMask[buf]) == 1);
if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
fb->_ColorDrawBufferIndexes[buf] = bufIndex;
}
count = buf + 1;
}
else {
if (fb->_ColorDrawBufferIndexes[buf] != -1) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
fb->_ColorDrawBufferIndexes[buf] = -1;
}
}
@@ -554,7 +638,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
/* set remaining outputs to -1 (GL_NONE) */
for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) {
if (fb->_ColorDrawBufferIndexes[buf] != -1) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
fb->_ColorDrawBufferIndexes[buf] = -1;
}
}
@@ -566,7 +650,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
/* also set context drawbuffer state */
for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf];
}
}
@@ -585,7 +669,7 @@ _mesa_update_draw_buffers(struct gl_context *ctx)
/* should be a window system FBO */
assert(_mesa_is_winsys_fbo(ctx->DrawBuffer));
- _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers,
+ _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers,
ctx->Color.DrawBuffer, NULL);
}
@@ -598,11 +682,10 @@ _mesa_update_draw_buffers(struct gl_context *ctx)
* \param bufferIndex the numerical index corresponding to 'buffer'
*/
void
-_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex)
+_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, GLint bufferIndex)
{
- struct gl_framebuffer *fb = ctx->ReadBuffer;
-
- if (_mesa_is_winsys_fbo(fb)) {
+ if ((fb == ctx->ReadBuffer) && _mesa_is_winsys_fbo(fb)) {
/* Only update the per-context READ_BUFFER state if we're bound to
* a window-system framebuffer.
*/
@@ -621,23 +704,17 @@ _mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex)
* Called by glReadBuffer to set the source renderbuffer for reading pixels.
* \param mode color buffer such as GL_FRONT, GL_BACK, etc.
*/
-void GLAPIENTRY
-_mesa_ReadBuffer(GLenum buffer)
+void
+_mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, const char *caller)
{
- struct gl_framebuffer *fb;
GLbitfield supportedMask;
GLint srcBuffer;
- GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
-
- fb = ctx->ReadBuffer;
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
+ _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer));
if (buffer == GL_NONE) {
/* This is legal--it means that no buffer should be bound for reading. */
@@ -648,24 +725,60 @@ _mesa_ReadBuffer(GLenum buffer)
srcBuffer = read_buffer_enum_to_index(buffer);
if (srcBuffer == -1) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glReadBuffer(buffer=0x%x)", buffer);
+ "%s(invalid buffer %s)", caller,
+ _mesa_lookup_enum_by_nr(buffer));
return;
}
supportedMask = supported_buffer_bitmask(ctx, fb);
if (((1 << srcBuffer) & supportedMask) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadBuffer(buffer=0x%x)", buffer);
+ "%s(invalid buffer %s)", caller,
+ _mesa_lookup_enum_by_nr(buffer));
return;
}
}
/* OK, all error checking has been completed now */
- _mesa_readbuffer(ctx, buffer, srcBuffer);
+ _mesa_readbuffer(ctx, fb, buffer, srcBuffer);
- /*
- * Call device driver function.
- */
- if (ctx->Driver.ReadBuffer)
- (*ctx->Driver.ReadBuffer)(ctx, buffer);
+ /* Call the device driver function only if fb is the bound read buffer */
+ if (fb == ctx->ReadBuffer) {
+ if (ctx->Driver.ReadBuffer)
+ (*ctx->Driver.ReadBuffer)(ctx, buffer);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_ReadBuffer(GLenum buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_read_buffer(ctx, ctx->ReadBuffer, buffer, "glReadBuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferReadBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glNamedFramebufferReadBuffer");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysReadBuffer;
+
+ _mesa_read_buffer(ctx, fb, src, "glNamedFramebufferReadBuffer");
}
diff --git a/mesalib/src/mesa/main/buffers.h b/mesalib/src/mesa/main/buffers.h
index ebcfa1c1e..5aa79fda5 100644
--- a/mesalib/src/mesa/main/buffers.h
+++ b/mesalib/src/mesa/main/buffers.h
@@ -36,26 +36,51 @@
#include "glheader.h"
struct gl_context;
+struct gl_framebuffer;
+
+extern void
+_mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, const char *caller);
extern void GLAPIENTRY
_mesa_DrawBuffer( GLenum mode );
extern void GLAPIENTRY
+_mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf);
+
+extern void
+_mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLsizei n, const GLenum *buffers, const char *caller);
+
+extern void GLAPIENTRY
_mesa_DrawBuffers(GLsizei n, const GLenum *buffers);
+extern void GLAPIENTRY
+_mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n,
+ const GLenum *bufs);
+
extern void
-_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
+_mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLuint n, const GLenum *buffers,
const GLbitfield *destMask);
extern void
-_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex);
+_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, GLint bufferIndex);
extern void
_mesa_update_draw_buffers(struct gl_context *ctx);
+extern void
+_mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, const char *caller);
+
extern void GLAPIENTRY
_mesa_ReadBuffer( GLenum mode );
+extern void GLAPIENTRY
+_mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src);
+
#endif
diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c
index 8d707bc34..c6999f7fd 100644
--- a/mesalib/src/mesa/main/clear.c
+++ b/mesalib/src/mesa/main/clear.c
@@ -34,6 +34,8 @@
#include "clear.h"
#include "context.h"
#include "enums.h"
+#include "fbobject.h"
+#include "get.h"
#include "macros.h"
#include "mtypes.h"
#include "state.h"
@@ -400,6 +402,32 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
/**
+ * The ClearBuffer framework is so complicated and so riddled with the
+ * assumption that the framebuffer is bound that, for now, we will just fake
+ * direct state access clearing for the user.
+ */
+void GLAPIENTRY
+_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLint *value)
+{
+ GLint oldfb;
+
+ GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedFramebufferiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
+ _mesa_ClearBufferiv(buffer, drawbuffer, value);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
+}
+
+
+/**
* New in GL 3.0
* Clear unsigned integer color buffer (not depth, not stencil).
*/
@@ -472,6 +500,32 @@ _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
/**
+ * The ClearBuffer framework is so complicated and so riddled with the
+ * assumption that the framebuffer is bound that, for now, we will just fake
+ * direct state access clearing for the user.
+ */
+void GLAPIENTRY
+_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLuint *value)
+{
+ GLint oldfb;
+
+ GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedFramebufferuiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
+ _mesa_ClearBufferuiv(buffer, drawbuffer, value);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
+}
+
+
+/**
* New in GL 3.0
* Clear fixed-pt or float color buffer or depth buffer (not stencil).
*/
@@ -565,6 +619,32 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
/**
+ * The ClearBuffer framework is so complicated and so riddled with the
+ * assumption that the framebuffer is bound that, for now, we will just fake
+ * direct state access clearing for the user.
+ */
+void GLAPIENTRY
+_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLfloat *value)
+{
+ GLint oldfb;
+
+ GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedFramebufferfv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
+ _mesa_ClearBufferfv(buffer, drawbuffer, value);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
+}
+
+
+/**
* New in GL 3.0
* Clear depth/stencil buffer only.
*/
@@ -626,3 +706,29 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
ctx->Stencil.Clear = clearStencilSave;
}
}
+
+
+/**
+ * The ClearBuffer framework is so complicated and so riddled with the
+ * assumption that the framebuffer is bound that, for now, we will just fake
+ * direct state access clearing for the user.
+ */
+void GLAPIENTRY
+_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
+ GLfloat depth, GLint stencil)
+{
+ GLint oldfb;
+
+ GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedFramebufferfi(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
+ _mesa_ClearBufferfi(buffer, 0, depth, stencil);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
+}
diff --git a/mesalib/src/mesa/main/clear.h b/mesalib/src/mesa/main/clear.h
index 96ce47b92..c29850676 100644
--- a/mesalib/src/mesa/main/clear.h
+++ b/mesalib/src/mesa/main/clear.h
@@ -52,13 +52,29 @@ extern void GLAPIENTRY
_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value);
extern void GLAPIENTRY
+_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLint *value);
+
+extern void GLAPIENTRY
_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value);
extern void GLAPIENTRY
+_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLuint *value);
+
+extern void GLAPIENTRY
_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value);
extern void GLAPIENTRY
+_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLfloat *value);
+
+extern void GLAPIENTRY
_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
GLfloat depth, GLint stencil);
+extern void GLAPIENTRY
+_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
+ GLfloat depth, GLint stencil);
+
#endif
diff --git a/mesalib/src/mesa/main/compute.c b/mesalib/src/mesa/main/compute.c
index 5756666b6..37a4ba70e 100644
--- a/mesalib/src/mesa/main/compute.c
+++ b/mesalib/src/mesa/main/compute.c
@@ -31,9 +31,27 @@ _mesa_DispatchCompute(GLuint num_groups_x,
GLuint num_groups_z)
{
GET_CURRENT_CONTEXT(ctx);
+ int i;
+ struct gl_shader_program *prog;
+ const GLuint num_groups[3] = { num_groups_x, num_groups_y, num_groups_z };
if (ctx->Extensions.ARB_compute_shader) {
- assert(!"TODO");
+ for (i = 0; i < 3; i++) {
+ if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glDispatchCompute(num_groups_%c)", 'x' + i);
+ return;
+ }
+ }
+ if (!_mesa_valid_to_render(ctx, "glDispatchCompute"))
+ return;
+ prog = ctx->Shader.CurrentProgram[MESA_SHADER_COMPUTE];
+ if (prog == NULL || prog->_LinkedShaders[MESA_SHADER_COMPUTE] == NULL) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDispatchCompute(no active compute shader)");
+ return;
+ }
+ ctx->Driver.DispatchCompute(ctx, num_groups);
} else {
_mesa_error(ctx, GL_INVALID_OPERATION,
"unsupported function (glDispatchCompute) called");
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 4aaf8b1af..544cc142f 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -118,6 +118,7 @@
#include "scissor.h"
#include "shared.h"
#include "shaderobj.h"
+#include "shaderimage.h"
#include "util/simple_list.h"
#include "state.h"
#include "stencil.h"
@@ -821,6 +822,7 @@ init_attrib_groups(struct gl_context *ctx)
_mesa_init_feedback( ctx );
_mesa_init_fog( ctx );
_mesa_init_hint( ctx );
+ _mesa_init_image_units( ctx );
_mesa_init_line( ctx );
_mesa_init_lighting( ctx );
_mesa_init_matrix( ctx );
@@ -1563,7 +1565,8 @@ handle_first_current(struct gl_context *ctx)
else
buffer = GL_FRONT;
- _mesa_drawbuffers(ctx, 1, &buffer, NULL /* destMask */);
+ _mesa_drawbuffers(ctx, ctx->DrawBuffer, 1, &buffer,
+ NULL /* destMask */);
}
if (ctx->ReadBuffer != _mesa_get_incomplete_framebuffer()) {
@@ -1576,7 +1579,7 @@ handle_first_current(struct gl_context *ctx)
bufferIndex = BUFFER_FRONT_LEFT;
}
- _mesa_readbuffer(ctx, buffer, bufferIndex);
+ _mesa_readbuffer(ctx, ctx->ReadBuffer, buffer, bufferIndex);
}
}
diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h
index 1cd89a84a..6f3c94101 100644
--- a/mesalib/src/mesa/main/context.h
+++ b/mesalib/src/mesa/main/context.h
@@ -285,7 +285,7 @@ do { \
/**
* Checks if the context is for Desktop GL (Compatibility or Core)
*/
-static inline GLboolean
+static inline bool
_mesa_is_desktop_gl(const struct gl_context *ctx)
{
return ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGL_CORE;
@@ -295,7 +295,7 @@ _mesa_is_desktop_gl(const struct gl_context *ctx)
/**
* Checks if the context is for any GLES version
*/
-static inline GLboolean
+static inline bool
_mesa_is_gles(const struct gl_context *ctx)
{
return ctx->API == API_OPENGLES || ctx->API == API_OPENGLES2;
@@ -303,9 +303,9 @@ _mesa_is_gles(const struct gl_context *ctx)
/**
- * Checks if the context is for GLES 3.x
+ * Checks if the context is for GLES 3.0 or later
*/
-static inline GLboolean
+static inline bool
_mesa_is_gles3(const struct gl_context *ctx)
{
return ctx->API == API_OPENGLES2 && ctx->Version >= 30;
@@ -313,9 +313,19 @@ _mesa_is_gles3(const struct gl_context *ctx)
/**
+ * Checks if the context is for GLES 3.1 or later
+ */
+static inline bool
+_mesa_is_gles31(const struct gl_context *ctx)
+{
+ return ctx->API == API_OPENGLES2 && ctx->Version >= 31;
+}
+
+
+/**
* Checks if the context supports geometry shaders.
*/
-static inline GLboolean
+static inline bool
_mesa_has_geometry_shaders(const struct gl_context *ctx)
{
return _mesa_is_desktop_gl(ctx) &&
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h
index 0c1a13fa4..d783e3422 100644
--- a/mesalib/src/mesa/main/dd.h
+++ b/mesalib/src/mesa/main/dd.h
@@ -1005,6 +1005,13 @@ struct dd_function_table {
void (*MemoryBarrier)(struct gl_context *ctx, GLbitfield barriers);
/** @} */
+
+ /**
+ * \name GL_ARB_compute_shader interface
+ */
+ /*@{*/
+ void (*DispatchCompute)(struct gl_context *ctx, const GLuint *num_groups);
+ /*@}*/
};
@@ -1167,6 +1174,19 @@ typedef struct {
void (GLAPIENTRYP VertexAttribP4uiv)( GLuint index, GLenum type,
GLboolean normalized,
const GLuint *value);
+
+ /* GL_ARB_vertex_attrib_64bit / GL 4.1 */
+ void (GLAPIENTRYP VertexAttribL1d)( GLuint index, GLdouble x);
+ void (GLAPIENTRYP VertexAttribL2d)( GLuint index, GLdouble x, GLdouble y);
+ void (GLAPIENTRYP VertexAttribL3d)( GLuint index, GLdouble x, GLdouble y, GLdouble z);
+ void (GLAPIENTRYP VertexAttribL4d)( GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+
+
+ void (GLAPIENTRYP VertexAttribL1dv)( GLuint index, const GLdouble *v);
+ void (GLAPIENTRYP VertexAttribL2dv)( GLuint index, const GLdouble *v);
+ void (GLAPIENTRYP VertexAttribL3dv)( GLuint index, const GLdouble *v);
+ void (GLAPIENTRYP VertexAttribL4dv)( GLuint index, const GLdouble *v);
+
} GLvertexformat;
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 9be8993b0..c82416aa0 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -104,7 +104,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_depth_clamp", o(ARB_depth_clamp), GL, 2003 },
{ "GL_ARB_depth_texture", o(ARB_depth_texture), GLL, 2001 },
{ "GL_ARB_derivative_control", o(ARB_derivative_control), GL, 2014 },
- { "GL_ARB_direct_state_access", o(dummy_false), GL, 2014 },
+ { "GL_ARB_direct_state_access", o(ARB_direct_state_access), GL, 2014 },
{ "GL_ARB_draw_buffers", o(dummy_true), GL, 2002 },
{ "GL_ARB_draw_buffers_blend", o(ARB_draw_buffers_blend), GL, 2009 },
{ "GL_ARB_draw_elements_base_vertex", o(ARB_draw_elements_base_vertex), GL, 2009 },
@@ -203,6 +203,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_vertex_buffer_object", o(dummy_true), GLL, 2003 },
{ "GL_ARB_vertex_program", o(ARB_vertex_program), GLL, 2002 },
{ "GL_ARB_vertex_shader", o(ARB_vertex_shader), GL, 2002 },
+ { "GL_ARB_vertex_attrib_64bit", o(ARB_vertex_attrib_64bit), GLC, 2010 },
{ "GL_ARB_vertex_type_10f_11f_11f_rev", o(ARB_vertex_type_10f_11f_11f_rev), GL, 2013 },
{ "GL_ARB_vertex_type_2_10_10_10_rev", o(ARB_vertex_type_2_10_10_10_rev), GL, 2009 },
{ "GL_ARB_viewport_array", o(ARB_viewport_array), GLC, 2010 },
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
index 27cf97f17..8db651ca2 100644
--- a/mesalib/src/mesa/main/fbobject.c
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -121,6 +121,27 @@ _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
/**
+ * A convenience function for direct state access that throws
+ * GL_INVALID_OPERATION if the renderbuffer doesn't exist.
+ */
+struct gl_renderbuffer *
+_mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id,
+ const char *func)
+{
+ struct gl_renderbuffer *rb;
+
+ rb = _mesa_lookup_renderbuffer(ctx, id);
+ if (!rb || rb == &DummyRenderbuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(non-existent renderbuffer %u)", func, id);
+ return NULL;
+ }
+
+ return rb;
+}
+
+
+/**
* Helper routine for getting a gl_framebuffer.
*/
struct gl_framebuffer *
@@ -138,6 +159,27 @@ _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
/**
+ * A convenience function for direct state access that throws
+ * GL_INVALID_OPERATION if the framebuffer doesn't exist.
+ */
+struct gl_framebuffer *
+_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id,
+ const char *func)
+{
+ struct gl_framebuffer *fb;
+
+ fb = _mesa_lookup_framebuffer(ctx, id);
+ if (!fb || fb == &DummyFramebuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(non-existent framebuffer %u)", func, id);
+ return NULL;
+ }
+
+ return fb;
+}
+
+
+/**
* Mark the given framebuffer as invalid. This will force the
* test for framebuffer completeness to be done before the framebuffer
* is used.
@@ -423,7 +465,7 @@ set_texture_attachment(struct gl_context *ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att,
struct gl_texture_object *texObj,
- GLenum texTarget, GLuint level, GLuint zoffset,
+ GLenum texTarget, GLuint level, GLuint layer,
GLboolean layered)
{
struct gl_renderbuffer *rb = att->Renderbuffer;
@@ -447,7 +489,7 @@ set_texture_attachment(struct gl_context *ctx,
/* always update these fields */
att->TextureLevel = level;
att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
- att->Zoffset = zoffset;
+ att->Zoffset = layer;
att->Layered = layered;
att->Complete = GL_FALSE;
@@ -479,9 +521,10 @@ set_renderbuffer_attachment(struct gl_context *ctx,
* Attach a renderbuffer object to a framebuffer object.
*/
void
-_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- GLenum attachment, struct gl_renderbuffer *rb)
+_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb)
{
struct gl_renderbuffer_attachment *att;
@@ -1446,6 +1489,14 @@ void GLAPIENTRY
_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
{
GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateRenderbuffers(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
create_render_buffers(ctx, n, renderbuffers, true);
}
@@ -1886,6 +1937,12 @@ renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", func);
+ return;
+ }
+
if (MESA_VERBOSE & VERBOSE_API) {
if (samples == NO_SAMPLES)
_mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
@@ -2140,6 +2197,13 @@ _mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedRenderbufferParameteriv("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
if (!rb || rb == &DummyRenderbuffer) {
/* ID was reserved, but no real renderbuffer object made yet */
@@ -2396,15 +2460,29 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
}
-void GLAPIENTRY
-_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
+/**
+ * This is the implementation for glGenFramebuffers and glCreateFramebuffers.
+ * It is not exposed to the rest of Mesa to encourage the use of
+ * nameless buffers in driver internals.
+ */
+static void
+create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
{
GET_CURRENT_CONTEXT(ctx);
GLuint first;
GLint i;
+ struct gl_framebuffer *fb;
+
+ const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers";
+
+ if (dsa && !ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", func);
+ return;
+ }
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
return;
}
@@ -2416,31 +2494,43 @@ _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
for (i = 0; i < n; i++) {
GLuint name = first + i;
framebuffers[i] = name;
- /* insert dummy placeholder into hash table */
+
+ if (dsa) {
+ fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]);
+ if (!fb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
+ return;
+ }
+ }
+ else
+ fb = &DummyFramebuffer;
+
mtx_lock(&ctx->Shared->Mutex);
- _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
+ _mesa_HashInsert(ctx->Shared->FrameBuffers, name, fb);
mtx_unlock(&ctx->Shared->Mutex);
}
}
-GLenum GLAPIENTRY
-_mesa_CheckFramebufferStatus(GLenum target)
+void GLAPIENTRY
+_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
{
- struct gl_framebuffer *buffer;
- GET_CURRENT_CONTEXT(ctx);
+ create_framebuffers(n, framebuffers, false);
+}
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
- _mesa_lookup_enum_by_nr(target));
+void GLAPIENTRY
+_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers)
+{
+ create_framebuffers(n, framebuffers, true);
+}
- buffer = get_framebuffer_target(ctx, target);
- if (!buffer) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
- return 0;
- }
+
+GLenum
+_mesa_check_framebuffer_status(struct gl_context *ctx,
+ struct gl_framebuffer *buffer)
+{
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
if (_mesa_is_winsys_fbo(buffer)) {
/* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
@@ -2461,6 +2551,74 @@ _mesa_CheckFramebufferStatus(GLenum target)
}
+GLenum GLAPIENTRY
+_mesa_CheckFramebufferStatus(GLenum target)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
+ _mesa_lookup_enum_by_nr(target));
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCheckFramebufferStatus(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return 0;
+ }
+
+ return _mesa_check_framebuffer_status(ctx, fb);
+}
+
+
+GLenum GLAPIENTRY
+_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCheckNamedFramebufferStatus(GL_ARB_direct_state_access "
+ "is not supported)");
+ return 0;
+ }
+
+ /* Validate the target (for conformance's sake) and grab a reference to the
+ * default framebuffer in case framebuffer = 0.
+ * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec
+ * (30.10.2014, PDF page 336) says:
+ * "If framebuffer is zero, then the status of the default read or
+ * draw framebuffer (as determined by target) is returned."
+ */
+ switch (target) {
+ case GL_DRAW_FRAMEBUFFER:
+ case GL_FRAMEBUFFER:
+ fb = ctx->WinSysDrawBuffer;
+ break;
+ case GL_READ_FRAMEBUFFER:
+ fb = ctx->WinSysReadBuffer;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCheckNamedFramebufferStatus(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return 0;
+ }
+
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glCheckNamedFramebufferStatus");
+ if (!fb)
+ return 0;
+ }
+
+ return _mesa_check_framebuffer_status(ctx, fb);
+}
+
+
/**
* Replicate the src attachment point. Used by framebuffer_texture() when
* the same texture is attached at GL_DEPTH_ATTACHMENT and
@@ -2487,144 +2645,301 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
/**
- * Common code called by glFramebufferTexture1D/2D/3D() and
- * glFramebufferTextureLayer().
+ * Common code called by gl*FramebufferTexture*() to retrieve the correct
+ * texture object pointer.
*
- * \param textarget is the textarget that was passed to the
- * glFramebufferTexture...() function, or 0 if the corresponding function
- * doesn't have a textarget parameter.
+ * \param texObj where the pointer to the texture object is returned. Note
+ * that a successful call may return texObj = NULL.
*
- * \param layered is true if this function was called from
- * glFramebufferTexture(), false otherwise.
+ * \return true if no errors, false if errors
*/
-static void
-framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
- GLenum attachment, GLenum textarget, GLuint texture,
- GLint level, GLuint zoffset, GLboolean layered)
+static bool
+get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture,
+ bool layered, const char *caller,
+ struct gl_texture_object **texObj)
{
- struct gl_renderbuffer_attachment *att;
- struct gl_texture_object *texObj = NULL;
- struct gl_framebuffer *fb;
- GLenum maxLevelsTarget;
+ *texObj = NULL; /* This will get returned if texture = 0. */
- fb = get_framebuffer_target(ctx, target);
- if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture%s(target=0x%x)", caller, target);
- return;
+ if (!texture)
+ return true;
+
+ *texObj = _mesa_lookup_texture(ctx, texture);
+ if (*texObj == NULL || (*texObj)->Target == 0) {
+ /* Can't render to a non-existent texture object.
+ *
+ * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
+ * Managing Framebuffer Objects specifies a different error
+ * depending upon the calling function (PDF pages 325-328).
+ * *FramebufferTexture (where layered = GL_TRUE) throws invalid
+ * value, while the other commands throw invalid operation (where
+ * layered = GL_FALSE).
+ */
+ const GLenum error = layered ? GL_INVALID_VALUE :
+ GL_INVALID_OPERATION;
+ _mesa_error(ctx, error,
+ "%s(non-existent texture %u)", caller, texture);
+ return false;
}
- /* check framebuffer binding */
- if (_mesa_is_winsys_fbo(fb)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%s", caller);
- return;
+ return true;
+}
+
+
+/**
+ * Common code called by gl*FramebufferTexture() to verify the texture target
+ * and decide whether or not the attachment should truly be considered
+ * layered.
+ *
+ * \param layered true if attachment should be considered layered, false if
+ * not
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_layered_texture_target(struct gl_context *ctx, GLenum target,
+ const char *caller, GLboolean *layered)
+{
+ *layered = GL_TRUE;
+
+ switch (target) {
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ return true;
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ /* These texture types are valid to pass to
+ * glFramebufferTexture(), but since they aren't layered, it
+ * is equivalent to calling glFramebufferTexture{1D,2D}().
+ */
+ *layered = GL_FALSE;
+ return true;
}
- /* The textarget, level, and zoffset parameters are only validated if
- * texture is non-zero.
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(invalid texture target %s)", caller,
+ _mesa_lookup_enum_by_nr(target));
+ return false;
+}
+
+
+/**
+ * Common code called by gl*FramebufferTextureLayer() to verify the texture
+ * target.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_texture_target(struct gl_context *ctx, GLenum target,
+ const char *caller)
+{
+ /* We're being called by glFramebufferTextureLayer().
+ * The only legal texture types for that function are 3D,
+ * cube-map, and 1D/2D/cube-map array textures.
*/
- if (texture) {
- GLboolean err = GL_TRUE;
-
- texObj = _mesa_lookup_texture(ctx, texture);
- if (texObj != NULL) {
- if (textarget == 0) {
- if (layered) {
- /* We're being called by glFramebufferTexture() and textarget
- * is not used.
- */
- switch (texObj->Target) {
- case GL_TEXTURE_3D:
- case GL_TEXTURE_1D_ARRAY_EXT:
- case GL_TEXTURE_2D_ARRAY_EXT:
- case GL_TEXTURE_CUBE_MAP:
- case GL_TEXTURE_CUBE_MAP_ARRAY:
- case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
- err = false;
- break;
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_RECTANGLE:
- case GL_TEXTURE_2D_MULTISAMPLE:
- /* These texture types are valid to pass to
- * glFramebufferTexture(), but since they aren't layered, it
- * is equivalent to calling glFramebufferTexture{1D,2D}().
- */
- err = false;
- layered = false;
- textarget = texObj->Target;
- break;
- default:
- err = true;
- break;
- }
- } else {
- /* We're being called by glFramebufferTextureLayer() and
- * textarget is not used. The only legal texture types for
- * that function are 3D and 1D/2D arrays textures.
- */
- err = (texObj->Target != GL_TEXTURE_3D) &&
- (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
- (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT) &&
- (texObj->Target != GL_TEXTURE_CUBE_MAP_ARRAY) &&
- (texObj->Target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
- }
- }
- else {
- /* Make sure textarget is consistent with the texture's type */
- err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
- ? !_mesa_is_cube_face(textarget)
- : (texObj->Target != textarget);
- }
+ switch (target) {
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ return true;
+ case GL_TEXTURE_CUBE_MAP:
+ /* This target is valid in TextureLayer when ARB_direct_state_access
+ * or OpenGL 4.5 is supported.
+ */
+ return ctx->Extensions.ARB_direct_state_access;
+ }
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(invalid texture target %s)", caller,
+ _mesa_lookup_enum_by_nr(target));
+ return false;
+}
+
+
+/**
+ * Common code called by glFramebufferTexture*D() to verify the texture
+ * target.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_textarget(struct gl_context *ctx, int dims, GLenum target,
+ GLenum textarget, const char *caller)
+{
+ bool err = false;
+
+ switch (dims) {
+ case 1:
+ switch (textarget) {
+ case GL_TEXTURE_1D:
+ break;
+ case GL_TEXTURE_1D_ARRAY:
+ err = !ctx->Extensions.EXT_texture_array;
+ break;
+ default:
+ err = true;
}
- else {
- /* can't render to a non-existant texture */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%s(non existant texture)",
- caller);
- return;
+ break;
+ case 2:
+ switch (textarget) {
+ case GL_TEXTURE_2D:
+ break;
+ case GL_TEXTURE_RECTANGLE:
+ err = _mesa_is_gles(ctx)
+ || !ctx->Extensions.NV_texture_rectangle;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ err = !ctx->Extensions.ARB_texture_cube_map;
+ break;
+ case GL_TEXTURE_2D_ARRAY:
+ err = (_mesa_is_gles(ctx) && ctx->Version < 30)
+ || !ctx->Extensions.EXT_texture_array;
+ break;
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ err = _mesa_is_gles(ctx)
+ || !ctx->Extensions.ARB_texture_multisample;
+ break;
+ default:
+ err = true;
}
+ break;
+ case 3:
+ if (textarget != GL_TEXTURE_3D)
+ err = true;
+ break;
+ default:
+ err = true;
+ }
- if (err) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%s(texture target mismatch)",
- caller);
- return;
- }
+ if (err) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(invalid textarget %s)",
+ caller, _mesa_lookup_enum_by_nr(textarget));
+ return false;
+ }
- if (texObj->Target == GL_TEXTURE_3D) {
- const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
- if (zoffset >= maxSize) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%s(zoffset)", caller);
- return;
- }
+ /* Make sure textarget is consistent with the texture's type */
+ err = (target == GL_TEXTURE_CUBE_MAP) ?
+ !_mesa_is_cube_face(textarget): (target != textarget);
+
+ if (err) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(mismatched texture target)", caller);
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Common code called by gl*FramebufferTextureLayer() and
+ * glFramebufferTexture3D() to validate the layer.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_layer(struct gl_context *ctx, GLenum target, GLint layer,
+ const char *caller)
+{
+ /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
+ * spec says:
+ *
+ * "An INVALID_VALUE error is generated if texture is non-zero
+ * and layer is negative."
+ */
+ if (layer < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(layer %u < 0)", caller, layer);
+ return false;
+ }
+
+ if (target == GL_TEXTURE_3D) {
+ const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
+ if (layer >= maxSize) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(invalid layer %u)", caller, layer);
+ return false;
}
- else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
- (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT) ||
- (texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
- (texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
- if (zoffset >= ctx->Const.MaxArrayTextureLayers) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%s(layer)", caller);
- return;
- }
+ }
+ else if ((target == GL_TEXTURE_1D_ARRAY) ||
+ (target == GL_TEXTURE_2D_ARRAY) ||
+ (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
+ (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
+ if (layer >= ctx->Const.MaxArrayTextureLayers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
+ caller, layer);
+ return false;
}
-
- maxLevelsTarget = textarget ? textarget : texObj->Target;
- if ((level < 0) ||
- (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) {
+ }
+ else if (target == GL_TEXTURE_CUBE_MAP) {
+ if (layer >= 6) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%s(level)", caller);
- return;
+ "%s(layer %u >= 6)", caller, layer);
+ return false;
}
}
+ return true;
+}
+
+
+/**
+ * Common code called by all gl*FramebufferTexture*() entry points to verify
+ * the level.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_level(struct gl_context *ctx, GLenum target, GLint level,
+ const char *caller)
+{
+ if ((level < 0) ||
+ (level >= _mesa_max_texture_levels(ctx, target))) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(invalid level %d)", caller, level);
+ return false;
+ }
+
+ return true;
+}
+
+
+void
+_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_texture_object *texObj, GLenum textarget,
+ GLint level, GLuint layer, GLboolean layered,
+ const char *caller)
+{
+ struct gl_renderbuffer_attachment *att;
+
+ /* The window-system framebuffer object is immutable */
+ if (_mesa_is_winsys_fbo(fb)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
+ caller);
+ return;
+ }
+
+ /* Not a hash lookup, so we can afford to get the attachment here. */
att = get_attachment(ctx, fb, attachment);
if (att == NULL) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture%s(attachment)", caller);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
+ _mesa_lookup_enum_by_nr(attachment));
return;
}
@@ -2637,7 +2952,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
_mesa_tex_target_to_face(textarget) ==
fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
- zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
+ layer == 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
@@ -2650,13 +2965,14 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
_mesa_tex_target_to_face(textarget) ==
fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
- zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
+ layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
/* 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);
+ level, layer, 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
@@ -2692,36 +3008,50 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
}
-void GLAPIENTRY
-_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture, GLint level)
+static void
+framebuffer_texture_with_dims(int dims, GLenum target,
+ GLenum attachment, GLenum textarget,
+ GLuint texture, GLint level, GLint layer,
+ const char *caller)
{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
- if (texture != 0) {
- GLboolean error;
+ /* Get the framebuffer object */
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
- switch (textarget) {
- case GL_TEXTURE_1D:
- error = GL_FALSE;
- break;
- case GL_TEXTURE_1D_ARRAY:
- error = !ctx->Extensions.EXT_texture_array;
- break;
- default:
- error = GL_TRUE;
- }
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, false, caller, &texObj))
+ return;
- if (error) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture1D(textarget=%s)",
- _mesa_lookup_enum_by_nr(textarget));
+ if (texObj) {
+ if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
+ return;
+
+ if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
return;
- }
}
- framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
- level, 0, GL_FALSE);
+ if (!check_level(ctx, textarget, level, caller))
+ return;
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
+ layer, GL_FALSE, caller);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level)
+{
+ framebuffer_texture_with_dims(1, target, attachment, textarget, texture,
+ level, 0, "glFramebufferTexture1D");
}
@@ -2729,79 +3059,112 @@ void GLAPIENTRY
_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
{
+ framebuffer_texture_with_dims(2, target, attachment, textarget, texture,
+ level, 0, "glFramebufferTexture2D");
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level, GLint layer)
+{
+ framebuffer_texture_with_dims(3, target, attachment, textarget, texture,
+ level, layer, "glFramebufferTexture3D");
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
+{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
+ GLenum textarget = 0;
- if (texture != 0) {
- GLboolean error;
+ const char *func = "glFramebufferTextureLayer";
- switch (textarget) {
- case GL_TEXTURE_2D:
- error = GL_FALSE;
- break;
- case GL_TEXTURE_RECTANGLE:
- error = _mesa_is_gles(ctx)
- || !ctx->Extensions.NV_texture_rectangle;
- break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- error = !ctx->Extensions.ARB_texture_cube_map;
- break;
- case GL_TEXTURE_2D_ARRAY:
- error = (_mesa_is_gles(ctx) && ctx->Version < 30)
- || !ctx->Extensions.EXT_texture_array;
- break;
- case GL_TEXTURE_2D_MULTISAMPLE:
- case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
- error = _mesa_is_gles(ctx)
- || !ctx->Extensions.ARB_texture_multisample;
- break;
- default:
- error = GL_TRUE;
- }
+ /* Get the framebuffer object */
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTextureLayer(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
- if (error) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture2D(textarget=%s)",
- _mesa_lookup_enum_by_nr(textarget));
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj))
+ return;
+
+ if (texObj) {
+ if (!check_texture_target(ctx, texObj->Target, func))
+ return;
+
+ if (!check_layer(ctx, texObj->Target, layer, func))
return;
+
+ if (!check_level(ctx, texObj->Target, level, func))
+ return;
+
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+ assert(layer >= 0 && layer < 6);
+ textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
+ layer = 0;
}
}
- framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
- level, 0, GL_FALSE);
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
+ layer, GL_FALSE, func);
}
void GLAPIENTRY
-_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture,
- GLint level, GLint zoffset)
+_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
+ GLenum textarget = 0;
+
+ const char *func = "glNamedFramebufferTextureLayer";
- if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
+ if (!ctx->Extensions.ARB_direct_state_access) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture3D(textarget)");
+ "%s(GL_ARB_direct_state_access is not supported)", func);
return;
}
- framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
- level, zoffset, GL_FALSE);
-}
+ /* Get the framebuffer object */
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
+ if (!fb)
+ return;
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj))
+ return;
-void GLAPIENTRY
-_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
- GLuint texture, GLint level, GLint layer)
-{
- GET_CURRENT_CONTEXT(ctx);
+ if (texObj) {
+ if (!check_texture_target(ctx, texObj->Target, func))
+ return;
+
+ if (!check_layer(ctx, texObj->Target, layer, func))
+ return;
+
+ if (!check_level(ctx, texObj->Target, level, func))
+ return;
- framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
- level, layer, GL_FALSE);
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+ assert(layer >= 0 && layer < 6);
+ textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
+ layer = 0;
+ }
+ }
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
+ layer, GL_FALSE, func);
}
@@ -2810,82 +3173,121 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment,
GLuint texture, GLint level)
{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
+ GLboolean layered;
+
+ const char *func = "FramebufferTexture";
- if (_mesa_has_geometry_shaders(ctx)) {
- framebuffer_texture(ctx, "", target, attachment, 0, texture,
- level, 0, GL_TRUE);
- } else {
+ if (!_mesa_has_geometry_shaders(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"unsupported function (glFramebufferTexture) called");
+ return;
+ }
+
+ /* Get the framebuffer object */
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
}
+
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj))
+ return;
+
+ if (texObj) {
+ if (!check_layered_texture_target(ctx, texObj->Target, func, &layered))
+ return;
+
+ if (!check_level(ctx, texObj->Target, level, func))
+ return;
+ }
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
+ 0, layered, func);
}
void GLAPIENTRY
-_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
- GLenum renderbufferTarget,
- GLuint renderbuffer)
+_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level)
{
- struct gl_renderbuffer_attachment *att;
- struct gl_framebuffer *fb;
- struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
+ GLboolean layered;
- fb = get_framebuffer_target(ctx, target);
- if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbuffer(target)");
+ const char *func = "glNamedFramebufferTexture";
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", func);
return;
}
- if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbuffer(renderbufferTarget)");
+ if (!_mesa_has_geometry_shaders(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "unsupported function (glNamedFramebufferTexture) called");
return;
}
+ /* Get the framebuffer object */
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
+ if (!fb)
+ return;
+
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj))
+ return;
+
+ if (texObj) {
+ if (!check_layered_texture_target(ctx, texObj->Target, func,
+ &layered))
+ return;
+
+ if (!check_level(ctx, texObj->Target, level, func))
+ return;
+ }
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
+ 0, layered, func);
+}
+
+
+void
+_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb,
+ const char *func)
+{
+ struct gl_renderbuffer_attachment *att;
+
if (_mesa_is_winsys_fbo(fb)) {
/* Can't attach new renderbuffers to a window system framebuffer */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbuffer");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(window-system framebuffer)", func);
return;
}
att = get_attachment(ctx, fb, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbuffer(invalid attachment %s)",
+ "%s(invalid attachment %s)", func,
_mesa_lookup_enum_by_nr(attachment));
return;
}
- if (renderbuffer) {
- rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(non-existant"
- " renderbuffer %u)", renderbuffer);
- return;
- }
- else if (rb == &DummyRenderbuffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(renderbuffer %u)",
- renderbuffer);
- return;
- }
- }
- else {
- /* remove renderbuffer attachment */
- rb = NULL;
- }
-
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
rb && rb->Format != MESA_FORMAT_NONE) {
/* make sure the renderbuffer is a depth/stencil format */
const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
if (baseFormat != GL_DEPTH_STENCIL) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(renderbuffer"
- " is not DEPTH_STENCIL format)");
+ "%s(renderbuffer is not DEPTH_STENCIL format)", func);
return;
}
}
@@ -2903,24 +3305,99 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
void GLAPIENTRY
-_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
- GLenum pname, GLint *params)
+_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
{
- const struct gl_renderbuffer_attachment *att;
- struct gl_framebuffer *buffer;
- GLenum err;
+ struct gl_framebuffer *fb;
+ struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
- /* The error differs in GL and GLES. */
- err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbuffer(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
- buffer = get_framebuffer_target(ctx, target);
- if (!buffer) {
+ if (renderbuffertarget != GL_RENDERBUFFER) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(target)");
+ "glFramebufferRenderbuffer(renderbuffertarget is not "
+ "GL_RENDERBUFFER)");
return;
}
+ if (renderbuffer) {
+ rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer,
+ "glFramebufferRenderbuffer");
+ if (!rb)
+ return;
+ }
+ else {
+ /* remove renderbuffer attachment */
+ rb = NULL;
+ }
+
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb,
+ "glFramebufferRenderbuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
+{
+ struct gl_framebuffer *fb;
+ struct gl_renderbuffer *rb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferRenderbuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glNamedFramebufferRenderbuffer");
+
+ if (renderbuffertarget != GL_RENDERBUFFER) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glNamedFramebufferRenderbuffer(renderbuffertarget is not "
+ "GL_RENDERBUFFER)");
+ return;
+ }
+
+ if (renderbuffer) {
+ rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer,
+ "glNamedFramebufferRenderbuffer");
+ if (!rb)
+ return;
+ }
+ else {
+ /* remove renderbuffer attachment */
+ rb = NULL;
+ }
+
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb,
+ "glNamedFramebufferRenderbuffer");
+}
+
+
+void
+_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
+ struct gl_framebuffer *buffer,
+ GLenum attachment, GLenum pname,
+ GLint *params, const char *caller)
+{
+ const struct gl_renderbuffer_attachment *att;
+ GLenum err;
+
+ /* The error differs in GL and GLES. */
+ err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
+
if (_mesa_is_winsys_fbo(buffer)) {
/* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
* says:
@@ -2936,14 +3413,15 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
!ctx->Extensions.ARB_framebuffer_object)
&& !_mesa_is_gles3(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
+ "%s(window-system framebuffer)", caller);
return;
}
if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
attachment != GL_DEPTH && attachment != GL_STENCIL) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(attachment)");
+ "%s(invalid attachment %s)", caller,
+ _mesa_lookup_enum_by_nr(attachment));
return;
}
/* the default / window-system FBO */
@@ -2955,8 +3433,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
}
if (att == NULL) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(attachment)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
+ _mesa_lookup_enum_by_nr(attachment));
return;
}
@@ -2970,9 +3448,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
* attachment, since it does not have a single format."
*/
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv("
- "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
- " is invalid for depth+stencil attachment)");
+ "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
+ " is invalid for depth+stencil attachment)", caller);
return;
}
/* the depth and stencil attachments must point to the same buffer */
@@ -2980,8 +3457,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(DEPTH/STENCIL"
- " attachments differ)");
+ "%s(DEPTH/STENCIL attachments differ)", caller);
return;
}
}
@@ -3014,8 +3490,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
*params = att->TextureLevel;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else {
goto invalid_pname_enum;
@@ -3031,8 +3507,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
}
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else {
goto invalid_pname_enum;
@@ -3042,8 +3518,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
if (ctx->API == API_OPENGLES) {
goto invalid_pname_enum;
} else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
} else if (att->Type == GL_TEXTURE) {
if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
@@ -3064,8 +3540,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else {
if (ctx->Extensions.EXT_framebuffer_sRGB) {
@@ -3087,8 +3563,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else {
mesa_format format = att->Renderbuffer->Format;
@@ -3103,9 +3579,9 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
if (_mesa_is_gles3(ctx) &&
attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(cannot query "
+ "%s(cannot query "
"GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
- "GL_DEPTH_STENCIL_ATTACHMENT");
+ "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
return;
}
@@ -3139,8 +3615,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else if (att->Texture) {
const struct gl_texture_image *texImage =
@@ -3159,8 +3635,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
att->Renderbuffer->Format);
}
else {
- _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
- " invalid FBO attachment structure");
+ _mesa_problem(ctx, "%s: invalid FBO attachment structure", caller);
}
return;
case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
@@ -3169,8 +3644,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
} else if (att->Type == GL_TEXTURE) {
*params = att->Layered;
} else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
} else {
goto invalid_pname_enum;
}
@@ -3182,30 +3657,145 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
return;
invalid_pname_enum:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
return;
}
+void GLAPIENTRY
+_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *buffer;
+
+ buffer = get_framebuffer_target(ctx, target);
+ if (!buffer) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameteriv(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
+ _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+ params,
+ "glGetFramebufferAttachmentParameteriv");
+}
+
+
+void GLAPIENTRY
+_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
+ GLenum attachment,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *buffer;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedFramebufferAttachmentParameteriv("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ if (framebuffer) {
+ buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glGetNamedFramebufferAttachmentParameteriv");
+ if (!buffer)
+ return;
+ }
+ else {
+ /*
+ * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
+ * 4.5 core spec (30.10.2014, PDF page 314):
+ * "If framebuffer is zero, then the default draw framebuffer is
+ * queried."
+ */
+ buffer = ctx->WinSysDrawBuffer;
+ }
+
+ _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+ params,
+ "glGetNamedFramebufferAttachmentParameteriv");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
+ GLint param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ (void) framebuffer;
+ (void) pname;
+ (void) param;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferParameteri("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferParameteri not supported "
+ "(ARB_framebuffer_no_attachments not implemented)");
+}
+
+
+void GLAPIENTRY
+_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
+ GLint *param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ (void) framebuffer;
+ (void) pname;
+ (void) param;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferParameteriv("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedFramebufferParameteriv not supported "
+ "(ARB_framebuffer_no_attachments not implemented)");
+}
+
+
static void
-invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
+invalidate_framebuffer_storage(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLsizei numAttachments,
const GLenum *attachments, GLint x, GLint y,
GLsizei width, GLsizei height, const char *name)
{
int i;
- struct gl_framebuffer *fb;
- GET_CURRENT_CONTEXT(ctx);
- fb = get_framebuffer_target(ctx, target);
- if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name);
+ /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
+ * Spec (2.2.2015, PDF page 522) says:
+ * "An INVALID_VALUE error is generated if numAttachments, width, or
+ * height is negative."
+ */
+ if (numAttachments < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(numAttachments < 0)", name);
return;
}
- if (numAttachments < 0) {
+ if (width < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "%s(numAttachments < 0)", name);
+ "%s(width < 0)", name);
+ return;
+ }
+
+ if (height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(height < 0)", name);
return;
}
@@ -3301,7 +3891,8 @@ invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
return;
invalid_enum:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
+ _mesa_lookup_enum_by_nr(attachments[i]));
return;
}
@@ -3311,16 +3902,74 @@ _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments, GLint x, GLint y,
GLsizei width, GLsizei height)
{
- invalidate_framebuffer_storage(target, numAttachments, attachments,
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glInvalidateSubFramebuffer(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
x, y, width, height,
"glInvalidateSubFramebuffer");
}
void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glInvalidateNamedFramebufferSubData("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
+ * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
+ * default draw framebuffer is affected."
+ */
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glInvalidateNamedFramebufferSubData");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
+ x, y, width, height,
+ "glInvalidateNamedFramebufferSubData");
+}
+
+
+void GLAPIENTRY
_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments)
{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glInvalidateFramebuffer(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
/* The GL_ARB_invalidate_subdata spec says:
*
* "The command
@@ -3333,7 +3982,7 @@ _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
* <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
* <MAX_VIEWPORT_DIMS[1]> respectively."
*/
- invalidate_framebuffer_storage(target, numAttachments, attachments,
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
0, 0,
MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
"glInvalidateFramebuffer");
@@ -3341,6 +3990,53 @@ _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glInvalidateNamedFramebufferData("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
+ * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
+ * default draw framebuffer is affected."
+ */
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glInvalidateNamedFramebufferData");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ /* The GL_ARB_invalidate_subdata spec says:
+ *
+ * "The command
+ *
+ * void InvalidateFramebuffer(enum target,
+ * sizei numAttachments,
+ * const enum *attachments);
+ *
+ * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
+ * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
+ * <MAX_VIEWPORT_DIMS[1]> respectively."
+ */
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
+ 0, 0,
+ MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
+ "glInvalidateNamedFramebufferData");
+}
+
+
+void GLAPIENTRY
_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
const GLenum *attachments)
{
diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h
index 61aa1f503..9f570db3a 100644
--- a/mesalib/src/mesa/main/fbobject.h
+++ b/mesalib/src/mesa/main/fbobject.h
@@ -64,9 +64,17 @@ _mesa_get_incomplete_framebuffer(void);
extern struct gl_renderbuffer *
_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id);
+extern struct gl_renderbuffer *
+_mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id,
+ const char *func);
+
extern struct gl_framebuffer *
_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id);
+extern struct gl_framebuffer *
+_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id,
+ const char *func);
+
void
_mesa_update_texture_renderbuffer(struct gl_context *ctx,
@@ -74,9 +82,17 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer_attachment *att);
extern void
+_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb);
+
+extern void
_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
struct gl_framebuffer *fb,
- GLenum attachment, struct gl_renderbuffer *rb);
+ GLenum attachment,
+ struct gl_renderbuffer *rb,
+ const char *func);
extern void
_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb);
@@ -99,6 +115,24 @@ _mesa_detach_renderbuffer(struct gl_context *ctx,
struct gl_framebuffer *fb,
const void *att);
+extern void
+_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_texture_object *texObj, GLenum textarget,
+ GLint level, GLuint layer, GLboolean layered,
+ const char *caller);
+
+extern GLenum
+_mesa_check_framebuffer_status(struct gl_context *ctx,
+ struct gl_framebuffer *fb);
+
+extern void
+_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
+ struct gl_framebuffer *buffer,
+ GLenum attachment, GLenum pname,
+ GLint *params, const char *caller);
+
+
extern GLboolean GLAPIENTRY
_mesa_IsRenderbuffer(GLuint renderbuffer);
@@ -165,9 +199,15 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers);
extern void GLAPIENTRY
_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers);
+extern void GLAPIENTRY
+_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers);
+
extern GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus(GLenum target);
+extern GLenum GLAPIENTRY
+_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target);
+
extern void GLAPIENTRY
_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level);
@@ -179,24 +219,49 @@ _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
extern void GLAPIENTRY
_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
- GLint level, GLint zoffset);
+ GLint level, GLint layer);
extern void GLAPIENTRY
_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
GLuint texture, GLint level, GLint layer);
extern void GLAPIENTRY
+_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level, GLint layer);
+
+extern void GLAPIENTRY
_mesa_FramebufferTexture(GLenum target, GLenum attachment,
GLuint texture, GLint level);
extern void GLAPIENTRY
+_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level);
+
+extern void GLAPIENTRY
_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
GLenum renderbuffertarget,
GLuint renderbuffer);
extern void GLAPIENTRY
+_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+
+extern void GLAPIENTRY
_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
GLenum pname, GLint *params);
+extern void GLAPIENTRY
+_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
+ GLenum attachment,
+ GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
+ GLint param);
+
+extern void GLAPIENTRY
+_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
+ GLint *param);
extern void GLAPIENTRY
_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
@@ -204,10 +269,22 @@ _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
GLsizei width, GLsizei height);
extern void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments);
extern void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments);
+
+extern void GLAPIENTRY
_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
const GLenum *attachments);
diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c
index 7fdd9bab6..70adaf885 100644
--- a/mesalib/src/mesa/main/ffvertex_prog.c
+++ b/mesalib/src/mesa/main/ffvertex_prog.c
@@ -135,7 +135,7 @@ static GLboolean check_active_shininess( struct gl_context *ctx,
(key->light_color_material_mask & (1 << attr)))
return GL_TRUE;
- if (key->varying_vp_inputs & VERT_ATTRIB_GENERIC(attr))
+ if (key->varying_vp_inputs & VERT_BIT_GENERIC(attr))
return GL_TRUE;
if (ctx->Light.Material.Attrib[attr][0] != 0.0F)
diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c
index 4f7736a64..665a5ba14 100644
--- a/mesalib/src/mesa/main/framebuffer.c
+++ b/mesalib/src/mesa/main/framebuffer.c
@@ -312,7 +312,7 @@ _mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
if (ctx) {
/* update scissor / window bounds */
- _mesa_update_draw_buffer_bounds(ctx);
+ _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
/* Signal new buffer state so that swrast will update its clipping
* info (the CLIP_BIT flag).
*/
@@ -413,9 +413,9 @@ _mesa_scissor_bounding_box(const struct gl_context *ctx,
* \param ctx the GL context.
*/
void
-_mesa_update_draw_buffer_bounds(struct gl_context *ctx)
+_mesa_update_draw_buffer_bounds(struct gl_context *ctx,
+ struct gl_framebuffer *buffer)
{
- struct gl_framebuffer *buffer = ctx->DrawBuffer;
int bbox[4];
if (!buffer)
@@ -652,7 +652,7 @@ update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
* context state (GL_READ_BUFFER too).
*/
if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) {
- _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers,
+ _mesa_drawbuffers(ctx, fb, ctx->Const.MaxDrawBuffers,
ctx->Color.DrawBuffer, NULL);
}
}
@@ -678,24 +678,21 @@ update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
/**
- * Update state related to the current draw/read framebuffers.
+ * Update state related to the draw/read framebuffers.
*/
void
-_mesa_update_framebuffer(struct gl_context *ctx)
+_mesa_update_framebuffer(struct gl_context *ctx,
+ struct gl_framebuffer *readFb,
+ struct gl_framebuffer *drawFb)
{
- struct gl_framebuffer *drawFb;
- struct gl_framebuffer *readFb;
-
assert(ctx);
- drawFb = ctx->DrawBuffer;
- readFb = ctx->ReadBuffer;
update_framebuffer(ctx, drawFb);
if (readFb != drawFb)
update_framebuffer(ctx, readFb);
- _mesa_update_clamp_vertex_color(ctx);
- _mesa_update_clamp_fragment_color(ctx);
+ _mesa_update_clamp_vertex_color(ctx, drawFb);
+ _mesa_update_clamp_fragment_color(ctx, drawFb);
}
diff --git a/mesalib/src/mesa/main/framebuffer.h b/mesalib/src/mesa/main/framebuffer.h
index a4274216e..d02b86f20 100644
--- a/mesalib/src/mesa/main/framebuffer.h
+++ b/mesalib/src/mesa/main/framebuffer.h
@@ -77,14 +77,17 @@ _mesa_scissor_bounding_box(const struct gl_context *ctx,
unsigned idx, int *bbox);
extern void
-_mesa_update_draw_buffer_bounds(struct gl_context *ctx);
+_mesa_update_draw_buffer_bounds(struct gl_context *ctx,
+ struct gl_framebuffer *drawFb);
extern void
_mesa_update_framebuffer_visual(struct gl_context *ctx,
struct gl_framebuffer *fb);
extern void
-_mesa_update_framebuffer(struct gl_context *ctx);
+_mesa_update_framebuffer(struct gl_context *ctx,
+ struct gl_framebuffer *readFb,
+ struct gl_framebuffer *drawFb);
extern GLboolean
_mesa_source_buffer_exists(struct gl_context *ctx, GLenum format);
diff --git a/mesalib/src/mesa/main/genmipmap.c b/mesalib/src/mesa/main/genmipmap.c
index 9aef09019..32b9460ad 100644
--- a/mesalib/src/mesa/main/genmipmap.c
+++ b/mesalib/src/mesa/main/genmipmap.c
@@ -158,6 +158,13 @@ _mesa_GenerateTextureMipmap(GLuint texture)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGenerateTextureMipmap(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture, "glGenerateTextureMipmap");
if (!texObj)
return;
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index a881bc589..8a6c81aff 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -909,13 +909,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
break;
case GL_FOG_COLOR:
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4FV(v->value_float_4, ctx->Fog.Color);
else
COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped);
break;
case GL_COLOR_CLEAR_VALUE:
- if (_mesa_get_clamp_fragment_color(ctx)) {
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) {
v->value_float_4[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F);
v->value_float_4[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F);
v->value_float_4[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F);
@@ -924,13 +924,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
COPY_4FV(v->value_float_4, ctx->Color.ClearColor.f);
break;
case GL_BLEND_COLOR_EXT:
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4FV(v->value_float_4, ctx->Color.BlendColor);
else
COPY_4FV(v->value_float_4, ctx->Color.BlendColorUnclamped);
break;
case GL_ALPHA_TEST_REF:
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
v->value_float = ctx->Color.AlphaRef;
else
v->value_float = ctx->Color.AlphaRefUnclamped;
@@ -1911,6 +1911,7 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)
if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs)
goto invalid_value;
v->value_int = ctx->Array.VAO->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride;
+ return TYPE_INT;
/* ARB_shader_image_load_store */
case GL_IMAGE_BINDING_NAME: {
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index fb4143086..83425176a 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -695,7 +695,8 @@ struct gl_current_attrib
* \note Index and Edgeflag current values are stored as floats in the
* SIX and SEVEN attribute slots.
*/
- GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */
+ /* we need double storage for this for vertex attrib 64bit */
+ GLfloat Attrib[VERT_ATTRIB_MAX][4*2]; /**< Position, color, texcoords, etc */
/**
* \name Current raster position attributes (always valid).
@@ -1523,6 +1524,7 @@ struct gl_client_array
GLboolean Enabled; /**< Enabled flag is a boolean */
GLboolean Normalized; /**< GL_ARB_vertex_program */
GLboolean Integer; /**< Integer-valued? */
+ GLboolean Doubles; /**< double precision values are not converted to floats */
GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */
struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
@@ -1553,6 +1555,7 @@ struct gl_vertex_attrib_array
GLboolean Enabled; /**< Whether the array is enabled */
GLboolean Normalized; /**< Fixed-point values are normalized when converted to floats */
GLboolean Integer; /**< Fixed-point values are not converted to floats */
+ GLboolean Doubles; /**< double precision values are not converted to floats */
GLuint _ElementSize; /**< Size of each element in bytes */
GLuint VertexBinding; /**< Vertex buffer binding */
};
@@ -1671,6 +1674,9 @@ struct gl_array_attrib
/** The default vertex array object */
struct gl_vertex_array_object *DefaultVAO;
+ /** The last VAO accessed by a DSA function */
+ struct gl_vertex_array_object *LastLookedUpVAO;
+
/** Array objects (GL_ARB/APPLE_vertex_array_object) */
struct _mesa_HashTable *Objects;
@@ -2090,6 +2096,7 @@ struct gl_program
struct nir_shader *nir;
GLbitfield64 InputsRead; /**< Bitmask of which input regs are read */
+ GLbitfield64 DoubleInputsRead; /**< Bitmask of which input regs are read and are doubles */
GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */
GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */
GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */
@@ -2499,6 +2506,12 @@ struct gl_shader
GLuint NumImages;
/**
+ * Whether early fragment tests are enabled as defined by
+ * ARB_shader_image_load_store.
+ */
+ bool EarlyFragmentTests;
+
+ /**
* Compute shader state from ARB_compute_shader layout qualifiers.
*/
struct {
@@ -3608,6 +3621,7 @@ struct gl_extensions
GLboolean ARB_depth_clamp;
GLboolean ARB_depth_texture;
GLboolean ARB_derivative_control;
+ GLboolean ARB_direct_state_access;
GLboolean ARB_draw_buffers_blend;
GLboolean ARB_draw_elements_base_vertex;
GLboolean ARB_draw_indirect;
@@ -3672,6 +3686,7 @@ struct gl_extensions
GLboolean ARB_transform_feedback3;
GLboolean ARB_transform_feedback_instanced;
GLboolean ARB_uniform_buffer_object;
+ GLboolean ARB_vertex_attrib_64bit;
GLboolean ARB_vertex_program;
GLboolean ARB_vertex_shader;
GLboolean ARB_vertex_type_10f_11f_11f_rev;
diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c
index 0fefa7d56..a33cdd139 100644
--- a/mesalib/src/mesa/main/pipelineobj.c
+++ b/mesalib/src/mesa/main/pipelineobj.c
@@ -553,6 +553,12 @@ _mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines)
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glCreateProgramPipelines("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
create_program_pipelines(ctx, n, pipelines, true);
}
diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c
index 12363de7b..e20a37d79 100755
--- a/mesalib/src/mesa/main/queryobj.c
+++ b/mesalib/src/mesa/main/queryobj.c
@@ -284,6 +284,13 @@ _mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids)
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateQueries(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
switch (target) {
case GL_SAMPLES_PASSED:
case GL_ANY_SAMPLES_PASSED:
@@ -776,6 +783,9 @@ _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params)
ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
+ case GL_QUERY_TARGET:
+ *params = q->Target;
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)");
return;
@@ -827,6 +837,9 @@ _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
+ case GL_QUERY_TARGET:
+ *params = q->Target;
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)");
return;
@@ -867,6 +880,9 @@ _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params)
ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
+ case GL_QUERY_TARGET:
+ *params = q->Target;
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)");
return;
@@ -907,6 +923,9 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params)
ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
+ case GL_QUERY_TARGET:
+ *params = q->Target;
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)");
return;
diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c
index ed0104c9e..df46f8361 100644
--- a/mesalib/src/mesa/main/readpix.c
+++ b/mesalib/src/mesa/main/readpix.c
@@ -83,7 +83,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat,
if (uses_blit) {
/* For blit-based ReadPixels packing, the clamping is done automatically
* unless the type is float. */
- if (_mesa_get_clamp_read_color(ctx) &&
+ if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
(type == GL_FLOAT || type == GL_HALF_FLOAT)) {
transferOps |= IMAGE_CLAMP_BIT;
}
@@ -91,7 +91,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat,
else {
/* For CPU-based ReadPixels packing, the clamping must always be done
* for non-float types, */
- if (_mesa_get_clamp_read_color(ctx) ||
+ if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) ||
(type != GL_FLOAT && type != GL_HALF_FLOAT)) {
transferOps |= IMAGE_CLAMP_BIT;
}
diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c
index a3aacc66a..60711a5b5 100644
--- a/mesalib/src/mesa/main/samplerobj.c
+++ b/mesalib/src/mesa/main/samplerobj.c
@@ -221,6 +221,13 @@ void GLAPIENTRY
_mesa_CreateSamplers(GLsizei count, GLuint *samplers)
{
GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glCreateSamplers("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
create_samplers(ctx, count, samplers, "glCreateSamplers");
}
diff --git a/mesalib/src/mesa/main/shader_query.cpp b/mesalib/src/mesa/main/shader_query.cpp
index d2ca49b43..3445f89a3 100644
--- a/mesalib/src/mesa/main/shader_query.cpp
+++ b/mesalib/src/mesa/main/shader_query.cpp
@@ -28,6 +28,7 @@
* \author Ian Romanick <ian.d.romanick@intel.com>
*/
+#include "main/context.h"
#include "main/core.h"
#include "glsl_symbol_table.h"
#include "ir.h"
@@ -809,6 +810,8 @@ stage_from_enum(GLenum ref)
return MESA_SHADER_GEOMETRY;
case GL_REFERENCED_BY_FRAGMENT_SHADER:
return MESA_SHADER_FRAGMENT;
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return MESA_SHADER_COMPUTE;
default:
assert(!"shader stage not supported");
return MESA_SHADER_STAGES;
@@ -824,6 +827,10 @@ is_resource_referenced(struct gl_shader_program *shProg,
struct gl_program_resource *res,
GLuint index, uint8_t stage)
{
+ /* First, check if we even have such a stage active. */
+ if (!shProg->_LinkedShaders[stage])
+ return false;
+
if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
return RESOURCE_ATC(res)->StageReferences[stage];
@@ -979,6 +986,10 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
case GL_NUM_ACTIVE_VARIABLES:
case GL_ACTIVE_VARIABLES:
return get_buffer_property(shProg, res, prop, val, caller);
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ if (!_mesa_has_compute_shaders(ctx))
+ goto invalid_enum;
+ /* fallthrough */
case GL_REFERENCED_BY_VERTEX_SHADER:
case GL_REFERENCED_BY_GEOMETRY_SHADER:
case GL_REFERENCED_BY_FRAGMENT_SHADER:
@@ -1015,17 +1026,18 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
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;
+ goto invalid_enum;
}
#undef VALIDATE_TYPE
+invalid_enum:
+ _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;
+
invalid_operation:
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
_mesa_lookup_enum_by_nr(res->Type),
diff --git a/mesalib/src/mesa/main/shaderimage.c b/mesalib/src/mesa/main/shaderimage.c
index dcbcca623..80b77275f 100644
--- a/mesalib/src/mesa/main/shaderimage.c
+++ b/mesalib/src/mesa/main/shaderimage.c
@@ -58,8 +58,8 @@
# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_R8G8_SNORM
#endif
-static mesa_format
-get_image_format(GLenum format)
+mesa_format
+_mesa_get_shader_image_format(GLenum format)
{
switch (format) {
case GL_RGBA32F:
@@ -331,19 +331,33 @@ get_image_format_class(mesa_format format)
}
}
+void
+_mesa_init_image_units(struct gl_context *ctx)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) {
+ struct gl_image_unit *u = &ctx->ImageUnits[i];
+ u->Access = GL_READ_ONLY;
+ u->Format = GL_R8;
+ u->_ActualFormat = _mesa_get_shader_image_format(u->Format);
+ }
+}
+
static GLboolean
validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u)
{
struct gl_texture_object *t = u->TexObj;
- struct gl_texture_image *img;
+ mesa_format tex_format;
- if (!t || u->Level < t->BaseLevel ||
- u->Level > t->_MaxLevel)
+ if (!t)
return GL_FALSE;
_mesa_test_texobj_completeness(ctx, t);
- if ((u->Level == t->BaseLevel && !t->_BaseComplete) ||
+ if (u->Level < t->BaseLevel ||
+ u->Level > t->_MaxLevel ||
+ (u->Level == t->BaseLevel && !t->_BaseComplete) ||
(u->Level != t->BaseLevel && !t->_MipmapComplete))
return GL_FALSE;
@@ -351,25 +365,32 @@ validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u)
u->Layer >= _mesa_get_texture_layers(t, u->Level))
return GL_FALSE;
- if (t->Target == GL_TEXTURE_CUBE_MAP)
- img = t->Image[u->Layer][u->Level];
- else
- img = t->Image[0][u->Level];
+ if (t->Target == GL_TEXTURE_BUFFER) {
+ tex_format = _mesa_get_shader_image_format(t->BufferObjectFormat);
+
+ } else {
+ struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ?
+ t->Image[u->Layer][u->Level] :
+ t->Image[0][u->Level]);
- if (!img || img->Border ||
- get_image_format_class(img->TexFormat) == IMAGE_FORMAT_CLASS_NONE ||
- img->NumSamples > ctx->Const.MaxImageSamples)
+ if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples)
+ return GL_FALSE;
+
+ tex_format = _mesa_get_shader_image_format(img->InternalFormat);
+ }
+
+ if (!tex_format)
return GL_FALSE;
switch (t->ImageFormatCompatibilityType) {
case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE:
- if (_mesa_get_format_bytes(img->TexFormat) !=
+ if (_mesa_get_format_bytes(tex_format) !=
_mesa_get_format_bytes(u->_ActualFormat))
return GL_FALSE;
break;
case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS:
- if (get_image_format_class(img->TexFormat) !=
+ if (get_image_format_class(tex_format) !=
get_image_format_class(u->_ActualFormat))
return GL_FALSE;
break;
@@ -421,7 +442,7 @@ validate_bind_image_texture(struct gl_context *ctx, GLuint unit,
return GL_FALSE;
}
- if (!get_image_format(format)) {
+ if (!_mesa_get_shader_image_format(format)) {
_mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)");
return GL_FALSE;
}
@@ -435,7 +456,6 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
GLenum format)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_texture_object *t = NULL;
struct gl_image_unit *u;
if (!validate_bind_image_texture(ctx, unit, texture, level,
@@ -448,34 +468,34 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
if (texture) {
- t = _mesa_lookup_texture(ctx, texture);
+ struct gl_texture_object *t = _mesa_lookup_texture(ctx, texture);
+
if (!t) {
_mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)");
return;
}
_mesa_reference_texobj(&u->TexObj, t);
- u->Level = level;
- u->Access = access;
- u->Format = format;
- u->_ActualFormat = get_image_format(format);
-
- if (_mesa_tex_target_is_layered(t->Target)) {
- u->Layered = layered;
- u->Layer = (layered ? 0 : layer);
- } else {
- u->Layered = GL_FALSE;
- u->Layer = 0;
- }
-
} else {
_mesa_reference_texobj(&u->TexObj, NULL);
}
+ u->Level = level;
+ u->Access = access;
+ u->Format = format;
+ u->_ActualFormat = _mesa_get_shader_image_format(format);
u->_Valid = validate_image_unit(ctx, u);
+ if (u->TexObj && _mesa_tex_target_is_layered(u->TexObj->Target)) {
+ u->Layered = layered;
+ u->Layer = (layered ? 0 : layer);
+ } else {
+ u->Layered = GL_FALSE;
+ u->Layer = 0;
+ }
+
if (ctx->Driver.BindImageTexture)
- ctx->Driver.BindImageTexture(ctx, u, t, level, layered,
+ ctx->Driver.BindImageTexture(ctx, u, u->TexObj, level, layered,
layer, access, format);
}
@@ -535,8 +555,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
if (texture != 0) {
struct gl_texture_object *texObj;
- struct gl_texture_image *image;
- mesa_format actualFormat;
+ GLenum tex_format;
if (!u->TexObj || u->TexObj->Name != texture) {
texObj = _mesa_lookup_texture_locked(ctx, texture);
@@ -557,25 +576,30 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
texObj = u->TexObj;
}
- image = texObj->Image[0][0];
+ if (texObj->Target == GL_TEXTURE_BUFFER) {
+ tex_format = texObj->BufferObjectFormat;
+ } else {
+ struct gl_texture_image *image = texObj->Image[0][0];
- if (!image || image->Width == 0 || image->Height == 0 || image->Depth == 0) {
- /* The ARB_multi_bind spec says:
- *
- * "An INVALID_OPERATION error is generated if the width,
- * height, or depth of the level zero texture image of
- * any texture in <textures> is zero (per binding)."
- */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindImageTextures(the width, height or depth "
- "of the level zero texture image of "
- "textures[%d]=%u is zero)", i, texture);
- continue;
- }
+ if (!image || image->Width == 0 || image->Height == 0 ||
+ image->Depth == 0) {
+ /* The ARB_multi_bind spec says:
+ *
+ * "An INVALID_OPERATION error is generated if the width,
+ * height, or depth of the level zero texture image of
+ * any texture in <textures> is zero (per binding)."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindImageTextures(the width, height or depth "
+ "of the level zero texture image of "
+ "textures[%d]=%u is zero)", i, texture);
+ continue;
+ }
- actualFormat = get_image_format(image->InternalFormat);
+ tex_format = image->InternalFormat;
+ }
- if (actualFormat == MESA_FORMAT_NONE) {
+ if (_mesa_get_shader_image_format(tex_format) == MESA_FORMAT_NONE) {
/* The ARB_multi_bind spec says:
*
* "An INVALID_OPERATION error is generated if the internal
@@ -586,7 +610,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
"glBindImageTextures(the internal format %s of "
"the level zero texture image of textures[%d]=%u "
"is not supported)",
- _mesa_lookup_enum_by_nr(image->InternalFormat),
+ _mesa_lookup_enum_by_nr(tex_format),
i, texture);
continue;
}
@@ -597,8 +621,8 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
u->Layered = _mesa_tex_target_is_layered(texObj->Target);
u->Layer = 0;
u->Access = GL_READ_WRITE;
- u->Format = image->InternalFormat;
- u->_ActualFormat = actualFormat;
+ u->Format = tex_format;
+ u->_ActualFormat = _mesa_get_shader_image_format(tex_format);
u->_Valid = validate_image_unit(ctx, u);
} else {
/* Unbind the texture from the unit */
diff --git a/mesalib/src/mesa/main/shaderimage.h b/mesalib/src/mesa/main/shaderimage.h
index 733ac7747..33d8a1eff 100644
--- a/mesalib/src/mesa/main/shaderimage.h
+++ b/mesalib/src/mesa/main/shaderimage.h
@@ -28,10 +28,27 @@
#define SHADERIMAGE_H
#include "glheader.h"
+#include "formats.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
struct gl_context;
/**
+ * Get the matching mesa_format for a shader image format GL enum.
+ */
+mesa_format
+_mesa_get_shader_image_format(GLenum format);
+
+/**
+ * Initialize a context's shader image units to the default state.
+ */
+void
+_mesa_init_image_units(struct gl_context *ctx);
+
+/**
* Recalculate the \c _Valid flag of a context's shader image units.
*
* To be called when the state of any texture bound to an image unit
@@ -51,4 +68,8 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures);
void GLAPIENTRY
_mesa_MemoryBarrier(GLbitfield barriers);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c
index cc84c6148..2657c532f 100644
--- a/mesalib/src/mesa/main/state.c
+++ b/mesalib/src/mesa/main/state.c
@@ -101,9 +101,12 @@ update_program(struct gl_context *ctx)
ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
struct gl_shader_program *fsProg =
ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
+ const struct gl_shader_program *csProg =
+ ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current;
+ const struct gl_compute_program *prevCP = ctx->ComputeProgram._Current;
GLbitfield new_state = 0x0;
/*
@@ -199,6 +202,16 @@ update_program(struct gl_context *ctx)
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
}
+ if (csProg && csProg->LinkStatus
+ && csProg->_LinkedShaders[MESA_SHADER_COMPUTE]) {
+ /* Use GLSL compute shader */
+ _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current,
+ gl_compute_program(csProg->_LinkedShaders[MESA_SHADER_COMPUTE]->Program));
+ } else {
+ /* no compute program */
+ _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current, NULL);
+ }
+
/* Let the driver know what's happening:
*/
if (ctx->FragmentProgram._Current != prevFP) {
@@ -225,6 +238,14 @@ update_program(struct gl_context *ctx)
}
}
+ if (ctx->ComputeProgram._Current != prevCP) {
+ new_state |= _NEW_PROGRAM;
+ if (ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_COMPUTE_PROGRAM_NV,
+ (struct gl_program *) ctx->ComputeProgram._Current);
+ }
+ }
+
return new_state;
}
@@ -368,10 +389,10 @@ _mesa_update_state_locked( struct gl_context *ctx )
update_frontbit( ctx );
if (new_state & _NEW_BUFFERS)
- _mesa_update_framebuffer(ctx);
+ _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer);
if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
- _mesa_update_draw_buffer_bounds( ctx );
+ _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
if (new_state & _NEW_LIGHT)
_mesa_update_lighting( ctx );
diff --git a/mesalib/src/mesa/main/texenv.c b/mesalib/src/mesa/main/texenv.c
index ec521e6c6..3edafc0f7 100644
--- a/mesalib/src/mesa/main/texenv.c
+++ b/mesalib/src/mesa/main/texenv.c
@@ -646,7 +646,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
if (pname == GL_TEXTURE_ENV_COLOR) {
if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
_mesa_update_state(ctx);
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4FV( params, texUnit->EnvColor );
else
COPY_4FV( params, texUnit->EnvColorUnclamped );
diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c
index 92b4d6795..f582a7f78 100644
--- a/mesalib/src/mesa/main/texgetimage.c
+++ b/mesalib/src/mesa/main/texgetimage.c
@@ -1108,6 +1108,13 @@ _mesa_GetTextureImage(GLuint texture, GLint level, GLenum format,
GLenum err;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureImage(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
/*
* This has been moved here because a format/type mismatch can cause a NULL
* texImage object, which in turn causes the mismatch error to be
@@ -1344,6 +1351,13 @@ _mesa_GetCompressedTextureImage(GLuint texture, GLint level,
GLint image_stride;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTextureImage(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glGetCompressedTextureImage");
if (!texObj)
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index 7bc1da7f8..7616fd7ce 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -3624,6 +3624,13 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
_mesa_lookup_enum_by_nr(format),
_mesa_lookup_enum_by_nr(type), pixels);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureSubImage%uD(GL_ARB_direct_state_access "
+ "is not supported)", dims);
+ return;
+ }
+
/* Get the texture object by Name. */
texObj = _mesa_lookup_texture(ctx, texture);
if (!texObj) {
@@ -4183,6 +4190,12 @@ _mesa_CopyTextureSubImage1D(GLuint texture, GLint level,
const char *self = "glCopyTextureSubImage1D";
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", self);
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture, self);
if (!texObj)
return;
@@ -4207,6 +4220,12 @@ _mesa_CopyTextureSubImage2D(GLuint texture, GLint level,
const char *self = "glCopyTextureSubImage2D";
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", self);
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture, self);
if (!texObj)
return;
@@ -4234,6 +4253,12 @@ _mesa_CopyTextureSubImage3D(GLuint texture, GLint level,
const char *self = "glCopyTextureSubImage3D";
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", self);
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture, self);
if (!texObj)
return;
@@ -4829,6 +4854,13 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset,
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTextureSubImage1D(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glCompressedTextureSubImage1D");
if (!texObj)
@@ -4907,6 +4939,13 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset,
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTextureSubImage2D(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glCompressedTextureSubImage2D");
if (!texObj)
@@ -4985,6 +5024,13 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset,
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTextureSubImage3D(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glCompressedTextureSubImage3D");
if (!texObj)
@@ -5469,6 +5515,13 @@ _mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer)
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
if (buffer) {
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBuffer");
if (!bufObj)
@@ -5497,6 +5550,13 @@ _mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer,
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureBufferRange(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
if (buffer) {
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glTextureBufferRange");
@@ -5801,6 +5861,13 @@ _mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples,
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureStorage2DMultisample(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glTextureStorage2DMultisample");
if (!texObj)
@@ -5821,6 +5888,13 @@ _mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples,
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureStorage3DMultisample(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
/* Get the texture object by Name. */
texObj = _mesa_lookup_texture_err(ctx, texture,
"glTextureStorage3DMultisample");
diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c
index c563f1e74..d51e6954b 100644
--- a/mesalib/src/mesa/main/texobj.c
+++ b/mesalib/src/mesa/main/texobj.c
@@ -1317,6 +1317,13 @@ _mesa_CreateTextures(GLenum target, GLsizei n, GLuint *textures)
GLint targetIndex;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateTextures(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
/*
* The 4.5 core profile spec (30.10.2014) doesn't specify what
* glCreateTextures should do with invalid targets, which was probably an
@@ -1808,6 +1815,13 @@ _mesa_BindTextureUnit(GLuint unit, GLuint texture)
_mesa_debug(ctx, "glBindTextureUnit %s %d\n",
_mesa_lookup_enum_by_nr(GL_TEXTURE0+unit), (GLint) texture);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindTextureUnit(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
/* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec
* (20141030) says:
* "When texture is zero, each of the targets enumerated at the
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index b5d42d304..1fa583002 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -1108,6 +1108,13 @@ _mesa_TextureParameterfv(GLuint texture, GLenum pname, const GLfloat *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterfv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1124,6 +1131,13 @@ _mesa_TextureParameterf(GLuint texture, GLenum pname, GLfloat param)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterf(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1140,6 +1154,13 @@ _mesa_TextureParameteri(GLuint texture, GLenum pname, GLint param)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameteri(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1157,6 +1178,13 @@ _mesa_TextureParameteriv(GLuint texture, GLenum pname,
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameteriv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1174,6 +1202,13 @@ _mesa_TextureParameterIiv(GLuint texture, GLenum pname, const GLint *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterIiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1191,6 +1226,13 @@ _mesa_TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterIuiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1650,6 +1692,13 @@ _mesa_GetTextureLevelParameterfv(GLuint texture, GLint level,
GLint iparam;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureLevelParameterfv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glGetTextureLevelParameterfv");
if (!texObj)
@@ -1668,6 +1717,13 @@ _mesa_GetTextureLevelParameteriv(GLuint texture, GLint level,
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureLevelParameteriv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glGetTextureLevelParameteriv");
if (!texObj)
@@ -1709,7 +1765,7 @@ get_tex_parameterfv(struct gl_context *ctx,
if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
_mesa_update_state_locked(ctx);
- if (_mesa_get_clamp_fragment_color(ctx)) {
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) {
params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
@@ -2227,6 +2283,13 @@ _mesa_GetTextureParameterfv(GLuint texture, GLenum pname, GLfloat *params)
struct gl_texture_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureParameterfv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = get_texobj_by_name(ctx, texture, GL_TRUE);
if (!obj) {
/* User passed a non-generated name. */
@@ -2244,6 +2307,13 @@ _mesa_GetTextureParameteriv(GLuint texture, GLenum pname, GLint *params)
struct gl_texture_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureParameteriv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = get_texobj_by_name(ctx, texture, GL_TRUE);
if (!obj) {
/* User passed a non-generated name. */
@@ -2261,6 +2331,13 @@ _mesa_GetTextureParameterIiv(GLuint texture, GLenum pname, GLint *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureParameterIiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_TRUE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -2279,6 +2356,13 @@ _mesa_GetTextureParameterIuiv(GLuint texture, GLenum pname, GLuint *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureParameterIuiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_TRUE);
if (!texObj) {
/* User passed a non-generated name. */
diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c
index 53cb2c091..dee74a825 100644
--- a/mesalib/src/mesa/main/texstorage.c
+++ b/mesalib/src/mesa/main/texstorage.c
@@ -507,6 +507,13 @@ texturestorage(GLuint dims, GLuint texture, GLsizei levels,
_mesa_lookup_enum_by_nr(internalformat),
width, height, depth);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureStorage%uD(GL_ARB_direct_state_access "
+ "is not supported)", dims);
+ return;
+ }
+
/* Check the format to make sure it is sized. */
if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
_mesa_error(ctx, GL_INVALID_ENUM,
diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c
index 103011ce5..642fa9647 100644
--- a/mesalib/src/mesa/main/transformfeedback.c
+++ b/mesalib/src/mesa/main/transformfeedback.c
@@ -706,6 +706,13 @@ _mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer)
struct gl_transform_feedback_object *obj;
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTransformFeedbackBufferBase(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glTransformFeedbackBufferBase");
if(!obj) {
@@ -729,6 +736,13 @@ _mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer,
struct gl_transform_feedback_object *obj;
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTransformFeedbackBufferRange(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glTransformFeedbackBufferRange");
if(!obj) {
@@ -1045,6 +1059,13 @@ _mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names)
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateTransformFeedbacks(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
create_transform_feedbacks(ctx, n, names, true);
}
@@ -1215,6 +1236,13 @@ _mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param)
struct gl_transform_feedback_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTransformFeedbackiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glGetTransformFeedbackiv");
if(!obj) {
@@ -1241,6 +1269,13 @@ _mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index,
struct gl_transform_feedback_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTransformFeedbacki_v(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glGetTransformFeedbacki_v");
if(!obj) {
@@ -1270,6 +1305,13 @@ _mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index,
struct gl_transform_feedback_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTransformFeedbacki64_v(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glGetTransformFeedbacki64_v");
if(!obj) {
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index 3e857ed10..728bd1bac 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -347,7 +347,8 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
&&
(uni->type->base_type == GLSL_TYPE_INT
|| uni->type->base_type == GLSL_TYPE_UINT
- || uni->type->base_type == GLSL_TYPE_SAMPLER))) {
+ || uni->type->base_type == GLSL_TYPE_SAMPLER
+ || uni->type->base_type == GLSL_TYPE_IMAGE))) {
memcpy(paramsOut, src, bytes);
} else {
union gl_constant_value *const dst =
@@ -366,6 +367,7 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
break;
case GLSL_TYPE_INT:
case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE:
dst[i].f = (float) src[i].i;
break;
case GLSL_TYPE_BOOL:
diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c
index 42e7f89b2..da6bbce52 100644
--- a/mesalib/src/mesa/main/varray.c
+++ b/mesalib/src/mesa/main/varray.c
@@ -66,6 +66,21 @@
#define UNSIGNED_INT_10F_11F_11F_REV_BIT (1 << 14)
#define ALL_TYPE_BITS ((1 << 15) - 1)
+#define ATTRIB_FORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \
+ SHORT_BIT | UNSIGNED_SHORT_BIT | \
+ INT_BIT | UNSIGNED_INT_BIT | \
+ HALF_BIT | FLOAT_BIT | DOUBLE_BIT | \
+ FIXED_GL_BIT | \
+ UNSIGNED_INT_2_10_10_10_REV_BIT | \
+ INT_2_10_10_10_REV_BIT | \
+ UNSIGNED_INT_10F_11F_11F_REV_BIT)
+
+#define ATTRIB_IFORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \
+ SHORT_BIT | UNSIGNED_SHORT_BIT | \
+ INT_BIT | UNSIGNED_INT_BIT)
+
+#define ATTRIB_LFORMAT_TYPES_MASK DOUBLE_BIT
+
/** Convert GL datatype enum into a <type>_BIT value seen above */
static GLbitfield
@@ -113,10 +128,11 @@ type_to_bit(const struct gl_context *ctx, GLenum type)
* Sets the VertexBinding field in the vertex attribute given by attribIndex.
*/
static void
-vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex,
+vertex_attrib_binding(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint attribIndex,
GLuint bindingIndex)
{
- struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_vertex_attrib_array *array = &vao->VertexAttrib[attribIndex];
if (array->VertexBinding != bindingIndex) {
@@ -139,11 +155,12 @@ vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex,
* and sets the Offset and Stride fields.
*/
static void
-bind_vertex_buffer(struct gl_context *ctx, GLuint index,
+bind_vertex_buffer(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint index,
struct gl_buffer_object *vbo,
GLintptr offset, GLsizei stride)
{
- struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_vertex_buffer_binding *binding = &vao->VertexBinding[index];
if (binding->BufferObj != vbo ||
@@ -167,10 +184,11 @@ bind_vertex_buffer(struct gl_context *ctx, GLuint index,
* given by bindingIndex.
*/
static void
-vertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex,
+vertex_binding_divisor(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint bindingIndex,
GLuint divisor)
{
- struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_vertex_buffer_binding *binding =
&vao->VertexBinding[bindingIndex];
@@ -243,15 +261,17 @@ get_legal_types_mask(const struct gl_context *ctx)
* \param type Datatype of each component (GL_FLOAT, GL_INT, etc)
* \param normalized Whether integer types are converted to floats in [-1, 1]
* \param integer Integer-valued values (will not be normalized to [-1, 1])
+ * \param doubles Double values not reduced to floats
* \param relativeOffset Offset of the first element relative to the binding offset.
*/
static bool
update_array_format(struct gl_context *ctx,
const char *func,
+ struct gl_vertex_array_object *vao,
GLuint attrib, GLbitfield legalTypesMask,
GLint sizeMin, GLint sizeMax,
GLint size, GLenum type,
- GLboolean normalized, GLboolean integer,
+ GLboolean normalized, GLboolean integer, GLboolean doubles,
GLuint relativeOffset)
{
struct gl_vertex_attrib_array *array;
@@ -362,16 +382,17 @@ update_array_format(struct gl_context *ctx,
elementSize = _mesa_bytes_per_vertex_attrib(size, type);
assert(elementSize != -1);
- array = &ctx->Array.VAO->VertexAttrib[attrib];
+ array = &vao->VertexAttrib[attrib];
array->Size = size;
array->Type = type;
array->Format = format;
array->Normalized = normalized;
array->Integer = integer;
+ array->Doubles = doubles;
array->RelativeOffset = relativeOffset;
array->_ElementSize = elementSize;
- ctx->Array.VAO->NewArrays |= VERT_BIT(attrib);
+ vao->NewArrays |= VERT_BIT(attrib);
ctx->NewState |= _NEW_ARRAY;
return true;
@@ -392,6 +413,7 @@ update_array_format(struct gl_context *ctx,
* \param stride stride between elements, in elements
* \param normalized are integer types converted to floats in [-1, 1]?
* \param integer integer-valued values (will not be normalized to [-1,1])
+ * \param doubles Double values not reduced to floats
* \param ptr the address (or offset inside VBO) of the array data
*/
static void
@@ -400,7 +422,7 @@ update_array(struct gl_context *ctx,
GLuint attrib, GLbitfield legalTypesMask,
GLint sizeMin, GLint sizeMax,
GLint size, GLenum type, GLsizei stride,
- GLboolean normalized, GLboolean integer,
+ GLboolean normalized, GLboolean integer, GLboolean doubles,
const GLvoid *ptr)
{
struct gl_vertex_attrib_array *array;
@@ -453,13 +475,14 @@ update_array(struct gl_context *ctx,
return;
}
- if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin,
- sizeMax, size, type, normalized, integer, 0)) {
+ if (!update_array_format(ctx, func, ctx->Array.VAO, attrib,
+ legalTypesMask, sizeMin, sizeMax,
+ size, type, normalized, integer, doubles, 0)) {
return;
}
/* Reset the vertex attrib binding */
- vertex_attrib_binding(ctx, attrib, attrib);
+ vertex_attrib_binding(ctx, ctx->Array.VAO, attrib, attrib);
/* The Stride and Ptr fields are not set by update_array_format() */
array = &ctx->Array.VAO->VertexAttrib[attrib];
@@ -468,7 +491,7 @@ update_array(struct gl_context *ctx,
/* Update the vertex buffer binding */
effectiveStride = stride != 0 ? stride : array->_ElementSize;
- bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj,
+ bind_vertex_buffer(ctx, ctx->Array.VAO, attrib, ctx->Array.ArrayBufferObj,
(GLintptr) ptr, effectiveStride);
}
@@ -488,7 +511,7 @@ _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glVertexPointer", VERT_ATTRIB_POS,
legalTypes, 2, 4,
- size, type, stride, GL_FALSE, GL_FALSE, ptr);
+ size, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
}
@@ -507,7 +530,7 @@ _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
update_array(ctx, "glNormalPointer", VERT_ATTRIB_NORMAL,
legalTypes, 3, 3,
- 3, type, stride, GL_TRUE, GL_FALSE, ptr);
+ 3, type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
}
@@ -529,7 +552,7 @@ _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glColorPointer", VERT_ATTRIB_COLOR0,
legalTypes, sizeMin, BGRA_OR_4,
- size, type, stride, GL_TRUE, GL_FALSE, ptr);
+ size, type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
}
@@ -543,7 +566,7 @@ _mesa_FogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glFogCoordPointer", VERT_ATTRIB_FOG,
legalTypes, 1, 1,
- 1, type, stride, GL_FALSE, GL_FALSE, ptr);
+ 1, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
}
@@ -558,7 +581,7 @@ _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glIndexPointer", VERT_ATTRIB_COLOR_INDEX,
legalTypes, 1, 1,
- 1, type, stride, GL_FALSE, GL_FALSE, ptr);
+ 1, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
}
@@ -578,7 +601,7 @@ _mesa_SecondaryColorPointer(GLint size, GLenum type,
update_array(ctx, "glSecondaryColorPointer", VERT_ATTRIB_COLOR1,
legalTypes, 3, BGRA_OR_4,
- size, type, stride, GL_TRUE, GL_FALSE, ptr);
+ size, type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
}
@@ -600,7 +623,7 @@ _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
update_array(ctx, "glTexCoordPointer", VERT_ATTRIB_TEX(unit),
legalTypes, sizeMin, 4,
- size, type, stride, GL_FALSE, GL_FALSE,
+ size, type, stride, GL_FALSE, GL_FALSE, GL_FALSE,
ptr);
}
@@ -617,7 +640,7 @@ _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glEdgeFlagPointer", VERT_ATTRIB_EDGEFLAG,
legalTypes, 1, 1,
- 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, ptr);
+ 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, GL_FALSE, ptr);
}
@@ -637,7 +660,7 @@ _mesa_PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glPointSizePointer", VERT_ATTRIB_POINT_SIZE,
legalTypes, 1, 1,
- 1, type, stride, GL_FALSE, GL_FALSE, ptr);
+ 1, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
}
@@ -668,7 +691,7 @@ _mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type,
update_array(ctx, "glVertexAttribPointer", VERT_ATTRIB_GENERIC(index),
legalTypes, 1, BGRA_OR_4,
- size, type, stride, normalized, GL_FALSE, ptr);
+ size, type, stride, normalized, GL_FALSE, GL_FALSE, ptr);
}
@@ -696,24 +719,36 @@ _mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
update_array(ctx, "glVertexAttribIPointer", VERT_ATTRIB_GENERIC(index),
legalTypes, 1, 4,
- size, type, stride, normalized, integer, ptr);
+ size, type, stride, normalized, integer, GL_FALSE, ptr);
}
-
-
void GLAPIENTRY
-_mesa_EnableVertexAttribArray(GLuint index)
+_mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr)
{
- struct gl_vertex_array_object *vao;
GET_CURRENT_CONTEXT(ctx);
-
+ const GLbitfield legalTypes = (DOUBLE_BIT);
if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glEnableVertexAttribArrayARB(index)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribLPointer(index)");
return;
}
- vao = ctx->Array.VAO;
+ update_array(ctx, "glVertexAttribLPointer", VERT_ATTRIB_GENERIC(index),
+ legalTypes, 1, 4,
+ size, type, stride, GL_TRUE, GL_FALSE, GL_TRUE, ptr);
+}
+
+
+static void
+enable_vertex_array_attrib(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint index,
+ const char *func)
+{
+ if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
+ return;
+ }
assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
@@ -728,18 +763,52 @@ _mesa_EnableVertexAttribArray(GLuint index)
void GLAPIENTRY
-_mesa_DisableVertexAttribArray(GLuint index)
+_mesa_EnableVertexAttribArray(GLuint index)
{
- struct gl_vertex_array_object *vao;
GET_CURRENT_CONTEXT(ctx);
+ enable_vertex_array_attrib(ctx, ctx->Array.VAO, index,
+ "glEnableVertexAttribArray");
+}
- if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glDisableVertexAttribArrayARB(index)");
+
+void GLAPIENTRY
+_mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glEnableVertexArrayAttrib(GL_ARB_direct_state_access "
+ "is not supported");
return;
}
- vao = ctx->Array.VAO;
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib
+ * and DisableVertexArrayAttrib if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing vertex
+ * array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glEnableVertexArrayAttrib");
+ if (!vao)
+ return;
+
+ enable_vertex_array_attrib(ctx, vao, index, "glEnableVertexArrayAttrib");
+}
+
+
+static void
+disable_vertex_array_attrib(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint index,
+ const char *func)
+{
+ if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
+ return;
+ }
assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
@@ -753,16 +822,54 @@ _mesa_DisableVertexAttribArray(GLuint index)
}
+void GLAPIENTRY
+_mesa_DisableVertexAttribArray(GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ disable_vertex_array_attrib(ctx, ctx->Array.VAO, index,
+ "glDisableVertexAttribArray");
+}
+
+
+void GLAPIENTRY
+_mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDisableVertexArrayAttrib(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib
+ * and DisableVertexArrayAttrib if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing vertex
+ * array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glDisableVertexArrayAttrib");
+ if (!vao)
+ return;
+
+ disable_vertex_array_attrib(ctx, vao, index, "glDisableVertexArrayAttrib");
+}
+
+
/**
* Return info for a vertex attribute array (no alias with legacy
* vertex attributes (pos, normal, color, etc)). This function does
* not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query.
*/
static GLuint
-get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
- const char *caller)
+get_vertex_array_attrib(struct gl_context *ctx,
+ const struct gl_vertex_array_object *vao,
+ GLuint index, GLenum pname,
+ const char *caller)
{
- const struct gl_vertex_array_object *vao = ctx->Array.VAO;
const struct gl_vertex_attrib_array *array;
if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
@@ -794,6 +901,11 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
return array->Integer;
}
goto error;
+ case GL_VERTEX_ATTRIB_ARRAY_LONG:
+ if (_mesa_is_desktop_gl(ctx)) {
+ return array->Doubles;
+ }
+ goto error;
case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays)
|| _mesa_is_gles3(ctx)) {
@@ -853,7 +965,8 @@ _mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
}
}
else {
- params[0] = (GLfloat) get_vertex_array_attrib(ctx, index, pname,
+ params[0] = (GLfloat) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribfv");
}
}
@@ -874,11 +987,32 @@ _mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params)
}
}
else {
- params[0] = (GLdouble) get_vertex_array_attrib(ctx, index, pname,
+ params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribdv");
}
}
+void GLAPIENTRY
+_mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
+ const GLdouble *v = (const GLdouble *)get_current_attrib(ctx, index, "glGetVertexAttribLdv");
+ if (v != NULL) {
+ params[0] = v[0];
+ params[1] = v[1];
+ params[2] = v[2];
+ params[3] = v[3];
+ }
+ }
+ else {
+ params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
+ "glGetVertexAttribLdv");
+ }
+}
void GLAPIENTRY
_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
@@ -896,7 +1030,8 @@ _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
}
}
else {
- params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
+ params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribiv");
}
}
@@ -916,7 +1051,8 @@ _mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
}
}
else {
- params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
+ params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribIiv");
}
}
@@ -936,7 +1072,8 @@ _mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
}
}
else {
- params[0] = get_vertex_array_attrib(ctx, index, pname,
+ params[0] = get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribIuiv");
}
}
@@ -963,6 +1100,138 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
}
+/** ARB_direct_state_access */
+void GLAPIENTRY
+_mesa_GetVertexArrayIndexediv(GLuint vaobj, GLuint index,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexArrayIndexediv(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing
+ * vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayIndexediv");
+ if (!vao)
+ return;
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "For GetVertexArrayIndexediv, <pname> must be one of
+ * VERTEX_ATTRIB_ARRAY_ENABLED, VERTEX_ATTRIB_ARRAY_SIZE,
+ * VERTEX_ATTRIB_ARRAY_STRIDE, VERTEX_ATTRIB_ARRAY_TYPE,
+ * VERTEX_ATTRIB_ARRAY_NORMALIZED, VERTEX_ATTRIB_ARRAY_INTEGER,
+ * VERTEX_ATTRIB_ARRAY_LONG, VERTEX_ATTRIB_ARRAY_DIVISOR, or
+ * VERTEX_ATTRIB_RELATIVE_OFFSET."
+ *
+ * and:
+ *
+ * "Add GetVertexArrayIndexediv in 'Get Command' for
+ * VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
+ * VERTEX_ATTRIB_BINDING,
+ * VERTEX_ATTRIB_RELATIVE_OFFSET,
+ * VERTEX_BINDING_OFFSET, and
+ * VERTEX_BINDING_STRIDE states"
+ *
+ * The only parameter name common to both lists is
+ * VERTEX_ATTRIB_RELATIVE_OFFSET. Also note that VERTEX_BINDING_BUFFER
+ * and VERTEX_BINDING_DIVISOR are missing from both lists. It seems
+ * pretty clear however that the intent is that it should be possible
+ * to query all vertex attrib and binding states that can be set with
+ * a DSA function.
+ */
+ switch (pname) {
+ case GL_VERTEX_BINDING_OFFSET:
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].Offset;
+ break;
+ case GL_VERTEX_BINDING_STRIDE:
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride;
+ break;
+ case GL_VERTEX_BINDING_DIVISOR:
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].InstanceDivisor;
+ break;
+ case GL_VERTEX_BINDING_BUFFER:
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].BufferObj->Name;
+ break;
+ default:
+ params[0] = get_vertex_array_attrib(ctx, vao, index, pname,
+ "glGetVertexArrayIndexediv");
+ break;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index,
+ GLenum pname, GLint64 *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexArrayIndexed64iv(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing
+ * vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayIndexed64iv");
+ if (!vao)
+ return;
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "For GetVertexArrayIndexed64iv, <pname> must be
+ * VERTEX_BINDING_OFFSET."
+ *
+ * and:
+ *
+ * "An INVALID_ENUM error is generated if <pname> is not one of
+ * the valid values listed above for the corresponding command."
+ */
+ if (pname != GL_VERTEX_BINDING_OFFSET) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayIndexed64iv("
+ "pname != GL_VERTEX_BINDING_OFFSET)");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_VALUE error is generated if <index> is greater than
+ * or equal to the value of MAX_VERTEX_ATTRIBS."
+ *
+ * Since the index refers to a buffer binding in this case, the intended
+ * limit must be MAX_VERTEX_ATTRIB_BINDINGS. Both limits are currently
+ * required to be the same, so in practice this doesn't matter.
+ */
+ if (index >= ctx->Const.MaxVertexAttribBindings) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexArrayIndexed64iv("
+ "index %d >= the value of GL_MAX_VERTEX_ATTRIB_BINDINGS (%d))",
+ index, ctx->Const.MaxVertexAttribBindings);
+ return;
+ }
+
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].Offset;
+}
+
+
void GLAPIENTRY
_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
GLsizei count, const GLvoid *ptr)
@@ -1337,6 +1606,7 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
GET_CURRENT_CONTEXT(ctx);
const GLuint genericIndex = VERT_ATTRIB_GENERIC(index);
+ struct gl_vertex_array_object * const vao = ctx->Array.VAO;
if (!ctx->Extensions.ARB_instanced_arrays) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()");
@@ -1349,7 +1619,7 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
return;
}
- assert(genericIndex < ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
+ assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib));
/* The ARB_vertex_attrib_binding spec says:
*
@@ -1362,8 +1632,8 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
* VertexAttribBinding(index, index);
* VertexBindingDivisor(index, divisor);"
*/
- vertex_attrib_binding(ctx, genericIndex, genericIndex);
- vertex_binding_divisor(ctx, genericIndex, divisor);
+ vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
+ vertex_binding_divisor(ctx, vao, genericIndex, divisor);
}
@@ -1395,38 +1665,25 @@ _mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type)
/**
* GL_ARB_vertex_attrib_binding
*/
-void GLAPIENTRY
-_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
- GLsizei stride)
+static void
+vertex_array_vertex_buffer(struct gl_context *ctx, struct gl_vertex_array_object *vao,
+ GLuint bindingIndex, GLuint buffer, GLintptr offset,
+ GLsizei stride, const char *func)
{
- GET_CURRENT_CONTEXT(ctx);
- const struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_buffer_object *vbo;
ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
- * "An INVALID_OPERATION error is generated if no vertex array object
- * is bound."
- */
- if (ctx->API == API_OPENGL_CORE &&
- ctx->Array.VAO == ctx->Array.DefaultVAO) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindVertexBuffer(No array object bound)");
- return;
- }
-
- /* The ARB_vertex_attrib_binding spec says:
- *
* "An INVALID_VALUE error is generated if <bindingindex> is greater than
* the value of MAX_VERTEX_ATTRIB_BINDINGS."
*/
if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffer(bindingindex=%u > "
+ "%s(bindingindex=%u > "
"GL_MAX_VERTEX_ATTRIB_BINDINGS)",
- bindingIndex);
+ func, bindingIndex);
return;
}
@@ -1437,21 +1694,21 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
*/
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffer(offset=%" PRId64 " < 0)",
- (int64_t) offset);
+ "%s(offset=%" PRId64 " < 0)",
+ func, (int64_t) offset);
return;
}
if (stride < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffer(stride=%d < 0)", stride);
+ "%s(stride=%d < 0)", func, stride);
return;
}
if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 &&
stride > ctx->Const.MaxVertexAttribStride) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindVertexBuffer(stride=%d > "
- "GL_MAX_VERTEX_ATTRIB_STRIDE)", stride);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > "
+ "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride);
return;
}
@@ -1471,7 +1728,7 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
* object references (automatically gen it).
*/
if (!_mesa_handle_bind_buffer_gen(ctx, GL_ARRAY_BUFFER, buffer,
- &vbo, "glBindVertexBuffer"))
+ &vbo, func))
return;
} else {
/* The ARB_vertex_attrib_binding spec says:
@@ -1482,33 +1739,75 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
vbo = ctx->Shared->NullBufferObj;
}
- bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(bindingIndex),
+ bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex),
vbo, offset, stride);
}
void GLAPIENTRY
-_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
- const GLintptr *offsets, const GLsizei *strides)
+_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
+ GLsizei stride)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_vertex_array_object * const vao = ctx->Array.VAO;
- GLuint i;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
- * "An INVALID_OPERATION error is generated if no
- * vertex array object is bound."
+ * "An INVALID_OPERATION error is generated if no vertex array object
+ * is bound."
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.VAO == ctx->Array.DefaultVAO) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindVertexBuffers(No array object bound)");
+ "glBindVertexBuffer(No array object bound)");
return;
}
+ vertex_array_vertex_buffer(ctx, ctx->Array.VAO, bindingIndex,
+ buffer, offset, stride, "glBindVertexBuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingIndex, GLuint buffer,
+ GLintptr offset, GLsizei stride)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayVertexBuffer(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayVertexBuffer");
+ if (!vao)
+ return;
+
+ vertex_array_vertex_buffer(ctx, vao, bindingIndex,
+ buffer, offset, stride,
+ "glVertexArrayVertexBuffer");
+}
+
+
+static void
+vertex_array_vertex_buffers(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint first, GLsizei count, const GLuint *buffers,
+ const GLintptr *offsets, const GLsizei *strides,
+ const char *func)
+{
+ GLuint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
/* The ARB_multi_bind spec says:
*
* "An INVALID_OPERATION error is generated if <first> + <count>
@@ -1516,9 +1815,9 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
*/
if (first + count > ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindVertexBuffers(first=%u + count=%d > the value of "
+ "%s(first=%u + count=%d > the value of "
"GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)",
- first, count, ctx->Const.MaxVertexAttribBindings);
+ func, first, count, ctx->Const.MaxVertexAttribBindings);
return;
}
@@ -1535,7 +1834,8 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
struct gl_buffer_object *vbo = ctx->Shared->NullBufferObj;
for (i = 0; i < count; i++)
- bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo, 0, 16);
+ bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i),
+ vbo, 0, 16);
return;
}
@@ -1571,23 +1871,23 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
*/
if (offsets[i] < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffers(offsets[%u]=%" PRId64 " < 0)",
- i, (int64_t) offsets[i]);
+ "%s(offsets[%u]=%" PRId64 " < 0)",
+ func, i, (int64_t) offsets[i]);
continue;
}
if (strides[i] < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffers(strides[%u]=%d < 0)",
- i, strides[i]);
+ "%s(strides[%u]=%d < 0)",
+ func, i, strides[i]);
continue;
}
if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 &&
strides[i] > ctx->Const.MaxVertexAttribStride) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffers(strides[%u]=%d > "
- "GL_MAX_VERTEX_ATTRIB_STRIDE)", i, strides[i]);
+ "%s(strides[%u]=%d > "
+ "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, i, strides[i]);
continue;
}
@@ -1598,8 +1898,7 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
if (buffers[i] == binding->BufferObj->Name)
vbo = binding->BufferObj;
else
- vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i,
- "glBindVertexBuffers");
+ vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, func);
if (!vbo)
continue;
@@ -1607,8 +1906,8 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
vbo = ctx->Shared->NullBufferObj;
}
- bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo,
- offsets[i], strides[i]);
+ bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i),
+ vbo, offsets[i], strides[i]);
}
_mesa_end_bufferobj_lookups(ctx);
@@ -1616,65 +1915,68 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
void GLAPIENTRY
-_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
- GLboolean normalized, GLuint relativeOffset)
+_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
+ const GLintptr *offsets, const GLsizei *strides)
{
- const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
- SHORT_BIT | UNSIGNED_SHORT_BIT |
- INT_BIT | UNSIGNED_INT_BIT |
- HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
- FIXED_GL_BIT |
- UNSIGNED_INT_2_10_10_10_REV_BIT |
- INT_2_10_10_10_REV_BIT |
- UNSIGNED_INT_10F_11F_11F_REV_BIT);
-
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
- * "An INVALID_OPERATION error is generated under any of the following
- * conditions:
- * - if no vertex array object is currently bound (see section 2.10);
- * - ..."
+ * "An INVALID_OPERATION error is generated if no
+ * vertex array object is bound."
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.VAO == ctx->Array.DefaultVAO) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexAttribFormat(No array object bound)");
+ "glBindVertexBuffers(No array object bound)");
return;
}
- /* The ARB_vertex_attrib_binding spec says:
- *
- * "The error INVALID_VALUE is generated if index is greater than or equal
- * to the value of MAX_VERTEX_ATTRIBS."
- */
- if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribFormat(attribindex=%u > "
- "GL_MAX_VERTEX_ATTRIBS)",
- attribIndex);
+ vertex_array_vertex_buffers(ctx, ctx->Array.VAO, first, count,
+ buffers, offsets, strides,
+ "glBindVertexBuffers");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayVertexBuffers(GLuint vaobj, GLuint first, GLsizei count,
+ const GLuint *buffers,
+ const GLintptr *offsets, const GLsizei *strides)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayVertexBuffers(GL_ARB_direct_state_access "
+ "is not supported");
return;
}
- FLUSH_VERTICES(ctx, 0);
- update_array_format(ctx, "glVertexAttribFormat",
- VERT_ATTRIB_GENERIC(attribIndex),
- legalTypes, 1, BGRA_OR_4, size, type, normalized,
- GL_FALSE, relativeOffset);
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayVertexBuffers");
+ if (!vao)
+ return;
+
+ vertex_array_vertex_buffers(ctx, vao, first, count,
+ buffers, offsets, strides,
+ "glVertexArrayVertexBuffers");
}
-void GLAPIENTRY
-_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
- GLuint relativeOffset)
+static void
+vertex_attrib_format(GLuint attribIndex, GLint size, GLenum type,
+ GLboolean normalized, GLboolean integer,
+ GLboolean doubles, GLbitfield legalTypes,
+ GLsizei maxSize, GLuint relativeOffset,
+ const char *func)
{
- const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
- SHORT_BIT | UNSIGNED_SHORT_BIT |
- INT_BIT | UNSIGNED_INT_BIT);
-
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -1684,33 +1986,59 @@ _mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
* conditions:
* - if no vertex array object is currently bound (see section 2.10);
* - ..."
+ *
+ * This error condition only applies to VertexAttribFormat and
+ * VertexAttribIFormat in the extension spec, but we assume that this
+ * is an oversight. In the OpenGL 4.3 (Core Profile) spec, it applies
+ * to all three functions.
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.VAO == ctx->Array.DefaultVAO) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexAttribIFormat(No array object bound)");
+ "%s(No array object bound)", func);
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
- * "The error INVALID_VALUE is generated if index is greater than
- * or equal to the value of MAX_VERTEX_ATTRIBS."
+ * "The error INVALID_VALUE is generated if index is greater than or equal
+ * to the value of MAX_VERTEX_ATTRIBS."
*/
if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribIFormat(attribindex=%u > "
+ "%s(attribindex=%u > "
"GL_MAX_VERTEX_ATTRIBS)",
- attribIndex);
+ func, attribIndex);
return;
}
FLUSH_VERTICES(ctx, 0);
- update_array_format(ctx, "glVertexAttribIFormat",
+ update_array_format(ctx, func, ctx->Array.VAO,
VERT_ATTRIB_GENERIC(attribIndex),
- legalTypes, 1, 4, size, type, GL_FALSE, GL_TRUE,
- relativeOffset);
+ legalTypes, 1, maxSize, size, type,
+ normalized, integer, doubles, relativeOffset);
+}
+
+
+void GLAPIENTRY
+_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
+ GLboolean normalized, GLuint relativeOffset)
+{
+ vertex_attrib_format(attribIndex, size, type, normalized,
+ GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK,
+ BGRA_OR_4, relativeOffset,
+ "glVertexAttribFormat");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
+ GLuint relativeOffset)
+{
+ vertex_attrib_format(attribIndex, size, type, GL_FALSE,
+ GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK, 4,
+ relativeOffset, "glVertexAttribIFormat");
}
@@ -1718,67 +2046,104 @@ void GLAPIENTRY
_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
GLuint relativeOffset)
{
- const GLbitfield legalTypes = DOUBLE_BIT;
+ vertex_attrib_format(attribIndex, size, type, GL_FALSE, GL_FALSE,
+ GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK, 4,
+ relativeOffset, "glVertexAttribLFormat");
+}
+
+static void
+vertex_array_attrib_format(GLuint vaobj, GLuint attribIndex, GLint size,
+ GLenum type, GLboolean normalized,
+ GLboolean integer, GLboolean doubles,
+ GLbitfield legalTypes, GLsizei maxSize,
+ GLuint relativeOffset, const char *func)
+{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported", func);
+ return;
+ }
+
ASSERT_OUTSIDE_BEGIN_END(ctx);
- /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says:
- *
- * "An INVALID_OPERATION error is generated under any of the following
- * conditions:
- * • if no vertex array object is currently bound (see section 10.4);
- * • ..."
+ /* The ARB_direct_state_access spec says:
*
- * This language is missing from the extension spec, but we assume
- * that this is an oversight.
+ * "An INVALID_OPERATION error is generated by VertexArrayAttrib*Format
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
*/
- if (ctx->API == API_OPENGL_CORE &&
- ctx->Array.VAO == ctx->Array.DefaultVAO) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexAttribLFormat(No array object bound)");
+ vao = _mesa_lookup_vao_err(ctx, vaobj, func);
+ if (!vao)
return;
- }
/* The ARB_vertex_attrib_binding spec says:
*
- * "The error INVALID_VALUE is generated if <attribindex> is greater than
- * or equal to the value of MAX_VERTEX_ATTRIBS."
+ * "The error INVALID_VALUE is generated if index is greater than or equal
+ * to the value of MAX_VERTEX_ATTRIBS."
*/
if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribLFormat(attribindex=%u > "
- "GL_MAX_VERTEX_ATTRIBS)",
- attribIndex);
+ "%s(attribindex=%u > GL_MAX_VERTEX_ATTRIBS)",
+ func, attribIndex);
return;
}
FLUSH_VERTICES(ctx, 0);
- update_array_format(ctx, "glVertexAttribLFormat",
+ update_array_format(ctx, func, vao,
VERT_ATTRIB_GENERIC(attribIndex),
- legalTypes, 1, 4, size, type, GL_FALSE, GL_FALSE,
- relativeOffset);
+ legalTypes, 1, maxSize, size, type, normalized,
+ integer, doubles, relativeOffset);
}
void GLAPIENTRY
-_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
+_mesa_VertexArrayAttribFormat(GLuint vaobj, GLuint attribIndex, GLint size,
+ GLenum type, GLboolean normalized,
+ GLuint relativeOffset)
{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ vertex_array_attrib_format(vaobj, attribIndex, size, type, normalized,
+ GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK,
+ BGRA_OR_4, relativeOffset,
+ "glVertexArrayAttribFormat");
+}
- /* The ARB_vertex_attrib_binding spec says:
- *
- * "An INVALID_OPERATION error is generated if no vertex array object
- * is bound."
- */
- if (ctx->API == API_OPENGL_CORE &&
- ctx->Array.VAO == ctx->Array.DefaultVAO) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexAttribBinding(No array object bound)");
- return;
- }
+
+void GLAPIENTRY
+_mesa_VertexArrayAttribIFormat(GLuint vaobj, GLuint attribIndex,
+ GLint size, GLenum type,
+ GLuint relativeOffset)
+{
+ vertex_array_attrib_format(vaobj, attribIndex, size, type, GL_FALSE,
+ GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK,
+ 4, relativeOffset,
+ "glVertexArrayAttribIFormat");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayAttribLFormat(GLuint vaobj, GLuint attribIndex,
+ GLint size, GLenum type,
+ GLuint relativeOffset)
+{
+ vertex_array_attrib_format(vaobj, attribIndex, size, type, GL_FALSE,
+ GL_FALSE, GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK,
+ 4, relativeOffset,
+ "glVertexArrayAttribLFormat");
+}
+
+
+static void
+vertex_array_attrib_binding(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint attribIndex, GLuint bindingIndex,
+ const char *func)
+{
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
@@ -1789,38 +2154,32 @@ _mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
*/
if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribBinding(attribindex=%u >= "
+ "%s(attribindex=%u >= "
"GL_MAX_VERTEX_ATTRIBS)",
- attribIndex);
+ func, attribIndex);
return;
}
if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribBinding(bindingindex=%u >= "
+ "%s(bindingindex=%u >= "
"GL_MAX_VERTEX_ATTRIB_BINDINGS)",
- bindingIndex);
+ func, bindingIndex);
return;
}
- assert(VERT_ATTRIB_GENERIC(attribIndex) <
- ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
+ assert(VERT_ATTRIB_GENERIC(attribIndex) < ARRAY_SIZE(vao->VertexAttrib));
- vertex_attrib_binding(ctx, VERT_ATTRIB_GENERIC(attribIndex),
+ vertex_attrib_binding(ctx, vao,
+ VERT_ATTRIB_GENERIC(attribIndex),
VERT_ATTRIB_GENERIC(bindingIndex));
}
void GLAPIENTRY
-_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
{
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (!ctx->Extensions.ARB_instanced_arrays) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexBindingDivisor()");
- return;
- }
/* The ARB_vertex_attrib_binding spec says:
*
@@ -1830,7 +2189,54 @@ _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.VAO == ctx->Array.DefaultVAO) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexBindingDivisor(No array object bound)");
+ "glVertexAttribBinding(No array object bound)");
+ return;
+ }
+
+ vertex_array_attrib_binding(ctx, ctx->Array.VAO,
+ attribIndex, bindingIndex,
+ "glVertexAttribBinding");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex, GLuint bindingIndex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayAttribBinding(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayAttribBinding
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayAttribBinding");
+ if (!vao)
+ return;
+
+ vertex_array_attrib_binding(ctx, vao, attribIndex, bindingIndex,
+ "glVertexArrayAttribBinding");
+}
+
+
+static void
+vertex_array_binding_divisor(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint bindingIndex, GLuint divisor,
+ const char *func)
+{
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ARB_instanced_arrays) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", func);
return;
}
@@ -1841,13 +2247,64 @@ _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
*/
if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexBindingDivisor(bindingindex=%u > "
+ "%s(bindingindex=%u > "
"GL_MAX_VERTEX_ATTRIB_BINDINGS)",
- bindingIndex);
+ func, bindingIndex);
return;
}
- vertex_binding_divisor(ctx, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
+ vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
+}
+
+
+void GLAPIENTRY
+_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* The ARB_vertex_attrib_binding spec says:
+ *
+ * "An INVALID_OPERATION error is generated if no vertex array object
+ * is bound."
+ */
+ if (ctx->API == API_OPENGL_CORE &&
+ ctx->Array.VAO == ctx->Array.DefaultVAO) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexBindingDivisor(No array object bound)");
+ return;
+ }
+
+ vertex_array_binding_divisor(ctx, ctx->Array.VAO,
+ bindingIndex, divisor,
+ "glVertexBindingDivisor");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex, GLuint divisor)
+{
+ struct gl_vertex_array_object *vao;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayBindingDivisor(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayBindingDivisor
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayBindingDivisor");
+ if (!vao)
+ return;
+
+ vertex_array_binding_divisor(ctx, vao, bindingIndex, divisor,
+ "glVertexArrayBindingDivisor");
}
@@ -1868,6 +2325,7 @@ _mesa_copy_client_array(struct gl_context *ctx,
dst->Enabled = src->Enabled;
dst->Normalized = src->Normalized;
dst->Integer = src->Integer;
+ dst->Doubles = src->Doubles;
dst->InstanceDivisor = src->InstanceDivisor;
dst->_ElementSize = src->_ElementSize;
_mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
@@ -1885,6 +2343,7 @@ _mesa_copy_vertex_attrib_array(struct gl_context *ctx,
dst->RelativeOffset = src->RelativeOffset;
dst->Format = src->Format;
dst->Integer = src->Integer;
+ dst->Doubles = src->Doubles;
dst->Normalized = src->Normalized;
dst->Ptr = src->Ptr;
dst->Enabled = src->Enabled;
diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h
index 4e4bd5f80..5583ed5a1 100644
--- a/mesalib/src/mesa/main/varray.h
+++ b/mesalib/src/mesa/main/varray.h
@@ -68,6 +68,7 @@ _mesa_update_client_array(struct gl_context *ctx,
dst->Enabled = src->Enabled;
dst->Normalized = src->Normalized;
dst->Integer = src->Integer;
+ dst->Doubles = src->Doubles;
dst->InstanceDivisor = binding->InstanceDivisor;
dst->_ElementSize = src->_ElementSize;
_mesa_reference_buffer_object(ctx, &dst->BufferObj, binding->BufferObj);
@@ -166,22 +167,34 @@ void GLAPIENTRY
_mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
GLsizei stride, const GLvoid *ptr);
+extern void GLAPIENTRY
+_mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *pointer);
extern void GLAPIENTRY
_mesa_EnableVertexAttribArray(GLuint index);
extern void GLAPIENTRY
+_mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index);
+
+
+extern void GLAPIENTRY
_mesa_DisableVertexAttribArray(GLuint index);
extern void GLAPIENTRY
-_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params);
+_mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index);
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params);
extern void GLAPIENTRY
_mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
+extern void GLAPIENTRY
+_mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params);
extern void GLAPIENTRY
_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
@@ -199,6 +212,16 @@ extern void GLAPIENTRY
_mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer);
+void GLAPIENTRY
+_mesa_GetVertexArrayIndexediv(GLuint vaobj, GLuint index,
+ GLenum pname, GLint *param);
+
+
+void GLAPIENTRY
+_mesa_GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index,
+ GLenum pname, GLint64 *param);
+
+
extern void GLAPIENTRY
_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer);
@@ -278,27 +301,57 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
GLsizei stride);
extern void GLAPIENTRY
+_mesa_VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingIndex, GLuint buffer,
+ GLintptr offset, GLsizei stride);
+
+extern void GLAPIENTRY
_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
const GLintptr *offsets, const GLsizei *strides);
extern void GLAPIENTRY
+_mesa_VertexArrayVertexBuffers(GLuint vaobj, GLuint first, GLsizei count,
+ const GLuint *buffers,
+ const GLintptr *offsets, const GLsizei *strides);
+
+extern void GLAPIENTRY
_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
GLboolean normalized, GLuint relativeOffset);
extern void GLAPIENTRY
+_mesa_VertexArrayAttribFormat(GLuint vaobj, GLuint attribIndex, GLint size,
+ GLenum type, GLboolean normalized,
+ GLuint relativeOffset);
+
+extern void GLAPIENTRY
_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
GLuint relativeOffset);
extern void GLAPIENTRY
+_mesa_VertexArrayAttribIFormat(GLuint vaobj, GLuint attribIndex,
+ GLint size, GLenum type,
+ GLuint relativeOffset);
+
+extern void GLAPIENTRY
_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
GLuint relativeOffset);
extern void GLAPIENTRY
+_mesa_VertexArrayAttribLFormat(GLuint vaobj, GLuint attribIndex,
+ GLint size, GLenum type,
+ GLuint relativeOffset);
+
+extern void GLAPIENTRY
_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex);
extern void GLAPIENTRY
+_mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex,
+ GLuint bindingIndex);
+
+extern void GLAPIENTRY
_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor);
+extern void GLAPIENTRY
+_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex, GLuint divisor);
extern void
_mesa_copy_client_array(struct gl_context *ctx,
diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c
index c561ab3cb..eb0b136a8 100644
--- a/mesalib/src/mesa/main/version.c
+++ b/mesalib/src/mesa/main/version.c
@@ -32,23 +32,16 @@
/**
* Scans 'string' to see if it ends with 'ending'.
*/
-static GLboolean
+static bool
check_for_ending(const char *string, const char *ending)
{
- int len1, len2;
+ const size_t len1 = strlen(string);
+ const size_t len2 = strlen(ending);
- len1 = strlen(string);
- len2 = strlen(ending);
+ if (len2 > len1)
+ return false;
- if (len2 > len1) {
- return GL_FALSE;
- }
-
- if (strcmp(string + (len1 - len2), ending) == 0) {
- return GL_TRUE;
- } else {
- return GL_FALSE;
- }
+ return strcmp(string + (len1 - len2), ending) == 0;
}
/**
@@ -58,15 +51,14 @@ check_for_ending(const char *string, const char *ending)
* fwd_context is only valid if version > 0
*/
static void
-get_gl_override(int *version, GLboolean *fwd_context,
- GLboolean *compat_context)
+get_gl_override(int *version, bool *fwd_context, bool *compat_context)
{
const char *env_var = "MESA_GL_VERSION_OVERRIDE";
const char *version_str;
int major, minor, n;
static int override_version = -1;
- static GLboolean fc_suffix = GL_FALSE;
- static GLboolean compat_suffix = GL_FALSE;
+ static bool fc_suffix = false;
+ static bool compat_suffix = false;
if (override_version < 0) {
override_version = 0;
@@ -78,12 +70,14 @@ get_gl_override(int *version, GLboolean *fwd_context,
n = sscanf(version_str, "%u.%u", &major, &minor);
if (n != 2) {
- fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str);
+ fprintf(stderr, "error: invalid value for %s: %s\n",
+ env_var, version_str);
override_version = 0;
} else {
override_version = major * 10 + minor;
if (override_version < 30 && fc_suffix) {
- fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str);
+ fprintf(stderr, "error: invalid value for %s: %s\n",
+ env_var, version_str);
}
}
}
@@ -134,7 +128,7 @@ _mesa_override_gl_version_contextless(struct gl_constants *consts,
gl_api *apiOut, GLuint *versionOut)
{
int version;
- GLboolean fwd_context, compat_context;
+ bool fwd_context, compat_context;
get_gl_override(&version, &fwd_context, &compat_context);
@@ -148,9 +142,9 @@ _mesa_override_gl_version_contextless(struct gl_constants *consts,
} else {
*apiOut = API_OPENGL_COMPAT;
}
- return GL_TRUE;
+ return true;
}
- return GL_FALSE;
+ return false;
}
void
@@ -171,7 +165,7 @@ int
_mesa_get_gl_version_override(void)
{
int version;
- GLboolean fwd_context, compat_context;
+ bool fwd_context, compat_context;
get_gl_override(&version, &fwd_context, &compat_context);
@@ -211,121 +205,121 @@ compute_version(const struct gl_extensions *extensions,
{
GLuint major, minor, version;
- const GLboolean ver_1_3 = (extensions->ARB_texture_border_clamp &&
- extensions->ARB_texture_cube_map &&
- extensions->ARB_texture_env_combine &&
- extensions->ARB_texture_env_dot3);
- const GLboolean ver_1_4 = (ver_1_3 &&
- extensions->ARB_depth_texture &&
- extensions->ARB_shadow &&
- extensions->ARB_texture_env_crossbar &&
- extensions->EXT_blend_color &&
- extensions->EXT_blend_func_separate &&
- extensions->EXT_blend_minmax &&
- extensions->EXT_point_parameters);
- const GLboolean ver_1_5 = (ver_1_4 &&
- extensions->ARB_occlusion_query);
- const GLboolean ver_2_0 = (ver_1_5 &&
- extensions->ARB_point_sprite &&
- extensions->ARB_vertex_shader &&
- extensions->ARB_fragment_shader &&
- extensions->ARB_texture_non_power_of_two &&
- extensions->EXT_blend_equation_separate &&
-
- /* Technically, 2.0 requires the functionality
- * of the EXT version. Enable 2.0 if either
- * extension is available, and assume that a
- * driver that only exposes the ATI extension
- * will fallback to software when necessary.
- */
- (extensions->EXT_stencil_two_side
- || extensions->ATI_separate_stencil));
- const GLboolean ver_2_1 = (ver_2_0 &&
- extensions->EXT_pixel_buffer_object &&
- extensions->EXT_texture_sRGB);
- const GLboolean ver_3_0 = (ver_2_1 &&
- consts->GLSLVersion >= 130 &&
- (consts->MaxSamples >= 4 || consts->FakeSWMSAA) &&
- (api == API_OPENGL_CORE ||
- extensions->ARB_color_buffer_float) &&
- extensions->ARB_depth_buffer_float &&
- extensions->ARB_half_float_vertex &&
- extensions->ARB_map_buffer_range &&
- extensions->ARB_shader_texture_lod &&
- extensions->ARB_texture_float &&
- extensions->ARB_texture_rg &&
- extensions->ARB_texture_compression_rgtc &&
- extensions->EXT_draw_buffers2 &&
- extensions->ARB_framebuffer_object &&
- extensions->EXT_framebuffer_sRGB &&
- extensions->EXT_packed_float &&
- extensions->EXT_texture_array &&
- extensions->EXT_texture_shared_exponent &&
- extensions->EXT_transform_feedback &&
- extensions->NV_conditional_render);
- const GLboolean ver_3_1 = (ver_3_0 &&
- consts->GLSLVersion >= 140 &&
- extensions->ARB_draw_instanced &&
- extensions->ARB_texture_buffer_object &&
- extensions->ARB_uniform_buffer_object &&
- extensions->EXT_texture_snorm &&
- extensions->NV_primitive_restart &&
- extensions->NV_texture_rectangle &&
- consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16);
- const GLboolean ver_3_2 = (ver_3_1 &&
- consts->GLSLVersion >= 150 &&
- extensions->ARB_depth_clamp &&
- extensions->ARB_draw_elements_base_vertex &&
- extensions->ARB_fragment_coord_conventions &&
- extensions->EXT_provoking_vertex &&
- extensions->ARB_seamless_cube_map &&
- extensions->ARB_sync &&
- extensions->ARB_texture_multisample &&
- extensions->EXT_vertex_array_bgra);
- const GLboolean ver_3_3 = (ver_3_2 &&
- consts->GLSLVersion >= 330 &&
- extensions->ARB_blend_func_extended &&
- extensions->ARB_explicit_attrib_location &&
- extensions->ARB_instanced_arrays &&
- extensions->ARB_occlusion_query2 &&
- extensions->ARB_shader_bit_encoding &&
- extensions->ARB_texture_rgb10_a2ui &&
- extensions->ARB_timer_query &&
- extensions->ARB_vertex_type_2_10_10_10_rev &&
- extensions->EXT_texture_swizzle);
- /* ARB_sampler_objects is always enabled in mesa */
-
- const GLboolean ver_4_0 = (ver_3_3 &&
- consts->GLSLVersion >= 400 &&
- extensions->ARB_draw_buffers_blend &&
- extensions->ARB_draw_indirect &&
- extensions->ARB_gpu_shader5 &&
- extensions->ARB_gpu_shader_fp64 &&
- extensions->ARB_sample_shading &&
- 0/*extensions->ARB_shader_subroutine*/ &&
- extensions->ARB_tessellation_shader &&
- extensions->ARB_texture_buffer_object_rgb32 &&
- extensions->ARB_texture_cube_map_array &&
- extensions->ARB_texture_query_lod &&
- extensions->ARB_transform_feedback2 &&
- extensions->ARB_transform_feedback3);
- const GLboolean ver_4_1 = (ver_4_0 &&
- consts->GLSLVersion >= 410 &&
- extensions->ARB_ES2_compatibility &&
- extensions->ARB_shader_precision &&
- 0/*extensions->ARB_vertex_attrib_64bit*/ &&
- extensions->ARB_viewport_array);
- const GLboolean ver_4_2 = (ver_4_1 &&
- consts->GLSLVersion >= 420 &&
- extensions->ARB_base_instance &&
- extensions->ARB_conservative_depth &&
- extensions->ARB_internalformat_query &&
- extensions->ARB_shader_atomic_counters &&
- extensions->ARB_shader_image_load_store &&
- extensions->ARB_shading_language_420pack &&
- extensions->ARB_shading_language_packing &&
- extensions->ARB_texture_compression_bptc &&
- extensions->ARB_transform_feedback_instanced);
+ const bool ver_1_3 = (extensions->ARB_texture_border_clamp &&
+ extensions->ARB_texture_cube_map &&
+ extensions->ARB_texture_env_combine &&
+ extensions->ARB_texture_env_dot3);
+ const bool ver_1_4 = (ver_1_3 &&
+ extensions->ARB_depth_texture &&
+ extensions->ARB_shadow &&
+ extensions->ARB_texture_env_crossbar &&
+ extensions->EXT_blend_color &&
+ extensions->EXT_blend_func_separate &&
+ extensions->EXT_blend_minmax &&
+ extensions->EXT_point_parameters);
+ const bool ver_1_5 = (ver_1_4 &&
+ extensions->ARB_occlusion_query);
+ const bool ver_2_0 = (ver_1_5 &&
+ extensions->ARB_point_sprite &&
+ extensions->ARB_vertex_shader &&
+ extensions->ARB_fragment_shader &&
+ extensions->ARB_texture_non_power_of_two &&
+ extensions->EXT_blend_equation_separate &&
+
+ /* Technically, 2.0 requires the functionality of the
+ * EXT version. Enable 2.0 if either extension is
+ * available, and assume that a driver that only
+ * exposes the ATI extension will fallback to
+ * software when necessary.
+ */
+ (extensions->EXT_stencil_two_side
+ || extensions->ATI_separate_stencil));
+ const bool ver_2_1 = (ver_2_0 &&
+ extensions->EXT_pixel_buffer_object &&
+ extensions->EXT_texture_sRGB);
+ const bool ver_3_0 = (ver_2_1 &&
+ consts->GLSLVersion >= 130 &&
+ (consts->MaxSamples >= 4 || consts->FakeSWMSAA) &&
+ (api == API_OPENGL_CORE ||
+ extensions->ARB_color_buffer_float) &&
+ extensions->ARB_depth_buffer_float &&
+ extensions->ARB_half_float_vertex &&
+ extensions->ARB_map_buffer_range &&
+ extensions->ARB_shader_texture_lod &&
+ extensions->ARB_texture_float &&
+ extensions->ARB_texture_rg &&
+ extensions->ARB_texture_compression_rgtc &&
+ extensions->EXT_draw_buffers2 &&
+ extensions->ARB_framebuffer_object &&
+ extensions->EXT_framebuffer_sRGB &&
+ extensions->EXT_packed_float &&
+ extensions->EXT_texture_array &&
+ extensions->EXT_texture_shared_exponent &&
+ extensions->EXT_transform_feedback &&
+ extensions->NV_conditional_render);
+ const bool ver_3_1 = (ver_3_0 &&
+ consts->GLSLVersion >= 140 &&
+ extensions->ARB_draw_instanced &&
+ extensions->ARB_texture_buffer_object &&
+ extensions->ARB_uniform_buffer_object &&
+ extensions->EXT_texture_snorm &&
+ extensions->NV_primitive_restart &&
+ extensions->NV_texture_rectangle &&
+ consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16);
+ const bool ver_3_2 = (ver_3_1 &&
+ consts->GLSLVersion >= 150 &&
+ extensions->ARB_depth_clamp &&
+ extensions->ARB_draw_elements_base_vertex &&
+ extensions->ARB_fragment_coord_conventions &&
+ extensions->EXT_provoking_vertex &&
+ extensions->ARB_seamless_cube_map &&
+ extensions->ARB_sync &&
+ extensions->ARB_texture_multisample &&
+ extensions->EXT_vertex_array_bgra);
+ const bool ver_3_3 = (ver_3_2 &&
+ consts->GLSLVersion >= 330 &&
+ extensions->ARB_blend_func_extended &&
+ extensions->ARB_explicit_attrib_location &&
+ extensions->ARB_instanced_arrays &&
+ extensions->ARB_occlusion_query2 &&
+ extensions->ARB_shader_bit_encoding &&
+ extensions->ARB_texture_rgb10_a2ui &&
+ extensions->ARB_timer_query &&
+ extensions->ARB_vertex_type_2_10_10_10_rev &&
+ extensions->EXT_texture_swizzle);
+ /* ARB_sampler_objects is always enabled in mesa */
+
+ const bool ver_4_0 = (ver_3_3 &&
+ consts->GLSLVersion >= 400 &&
+ extensions->ARB_draw_buffers_blend &&
+ extensions->ARB_draw_indirect &&
+ extensions->ARB_gpu_shader5 &&
+ extensions->ARB_gpu_shader_fp64 &&
+ extensions->ARB_sample_shading &&
+ false /*extensions->ARB_shader_subroutine*/ &&
+ extensions->ARB_tessellation_shader &&
+ extensions->ARB_texture_buffer_object_rgb32 &&
+ extensions->ARB_texture_cube_map_array &&
+ extensions->ARB_texture_query_lod &&
+ extensions->ARB_transform_feedback2 &&
+ extensions->ARB_transform_feedback3);
+ const bool ver_4_1 = (ver_4_0 &&
+ consts->GLSLVersion >= 410 &&
+ extensions->ARB_ES2_compatibility &&
+ extensions->ARB_shader_precision &&
+ extensions->ARB_vertex_attrib_64bit &&
+ extensions->ARB_viewport_array);
+ const bool ver_4_2 = (ver_4_1 &&
+ consts->GLSLVersion >= 420 &&
+ extensions->ARB_base_instance &&
+ extensions->ARB_conservative_depth &&
+ extensions->ARB_internalformat_query &&
+ extensions->ARB_shader_atomic_counters &&
+ extensions->ARB_shader_image_load_store &&
+ extensions->ARB_shading_language_420pack &&
+ extensions->ARB_shading_language_packing &&
+ extensions->ARB_texture_compression_bptc &&
+ extensions->ARB_transform_feedback_instanced);
if (ver_4_2) {
major = 4;
@@ -392,11 +386,11 @@ static GLuint
compute_version_es1(const struct gl_extensions *extensions)
{
/* OpenGL ES 1.0 is derived from OpenGL 1.3 */
- const GLboolean ver_1_0 = (extensions->ARB_texture_env_combine &&
- extensions->ARB_texture_env_dot3);
+ const bool ver_1_0 = (extensions->ARB_texture_env_combine &&
+ extensions->ARB_texture_env_dot3);
/* OpenGL ES 1.1 is derived from OpenGL 1.5 */
- const GLboolean ver_1_1 = (ver_1_0 &&
- extensions->EXT_point_parameters);
+ const bool ver_1_1 = (ver_1_0 &&
+ extensions->EXT_point_parameters);
if (ver_1_1) {
return 11;
@@ -411,34 +405,34 @@ static GLuint
compute_version_es2(const struct gl_extensions *extensions)
{
/* OpenGL ES 2.0 is derived from OpenGL 2.0 */
- const GLboolean ver_2_0 = (extensions->ARB_texture_cube_map &&
- extensions->EXT_blend_color &&
- extensions->EXT_blend_func_separate &&
- extensions->EXT_blend_minmax &&
- extensions->ARB_vertex_shader &&
- extensions->ARB_fragment_shader &&
- extensions->ARB_texture_non_power_of_two &&
- extensions->EXT_blend_equation_separate);
+ const bool ver_2_0 = (extensions->ARB_texture_cube_map &&
+ extensions->EXT_blend_color &&
+ extensions->EXT_blend_func_separate &&
+ extensions->EXT_blend_minmax &&
+ extensions->ARB_vertex_shader &&
+ extensions->ARB_fragment_shader &&
+ extensions->ARB_texture_non_power_of_two &&
+ extensions->EXT_blend_equation_separate);
/* FINISHME: This list isn't quite right. */
- const GLboolean ver_3_0 = (extensions->ARB_half_float_vertex &&
- extensions->ARB_internalformat_query &&
- extensions->ARB_map_buffer_range &&
- 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 &&
- extensions->EXT_packed_float &&
- extensions->EXT_texture_array &&
- extensions->EXT_texture_shared_exponent &&
- extensions->EXT_transform_feedback &&
- extensions->ARB_draw_instanced &&
- extensions->ARB_uniform_buffer_object &&
- extensions->EXT_texture_snorm &&
- extensions->NV_primitive_restart &&
- extensions->OES_depth_texture_cube_map);
+ const bool ver_3_0 = (extensions->ARB_half_float_vertex &&
+ extensions->ARB_internalformat_query &&
+ extensions->ARB_map_buffer_range &&
+ 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 &&
+ extensions->EXT_packed_float &&
+ extensions->EXT_texture_array &&
+ extensions->EXT_texture_shared_exponent &&
+ extensions->EXT_transform_feedback &&
+ extensions->ARB_draw_instanced &&
+ extensions->ARB_uniform_buffer_object &&
+ extensions->EXT_texture_snorm &&
+ extensions->NV_primitive_restart &&
+ extensions->OES_depth_texture_cube_map);
if (ver_3_0) {
return 30;
} else if (ver_2_0) {
diff --git a/mesalib/src/mesa/main/vtxfmt.c b/mesalib/src/mesa/main/vtxfmt.c
index fc0a01edf..d7ef7e278 100644
--- a/mesalib/src/mesa/main/vtxfmt.c
+++ b/mesalib/src/mesa/main/vtxfmt.c
@@ -206,6 +206,18 @@ install_vtxfmt(struct gl_context *ctx, struct _glapi_table *tab,
SET_VertexAttribP3uiv(tab, vfmt->VertexAttribP3uiv);
SET_VertexAttribP4uiv(tab, vfmt->VertexAttribP4uiv);
}
+
+ if (_mesa_is_desktop_gl(ctx)) {
+ SET_VertexAttribL1d(tab, vfmt->VertexAttribL1d);
+ SET_VertexAttribL2d(tab, vfmt->VertexAttribL2d);
+ SET_VertexAttribL3d(tab, vfmt->VertexAttribL3d);
+ SET_VertexAttribL4d(tab, vfmt->VertexAttribL4d);
+
+ SET_VertexAttribL1dv(tab, vfmt->VertexAttribL1dv);
+ SET_VertexAttribL2dv(tab, vfmt->VertexAttribL2dv);
+ SET_VertexAttribL3dv(tab, vfmt->VertexAttribL3dv);
+ SET_VertexAttribL4dv(tab, vfmt->VertexAttribL4dv);
+ }
}
diff --git a/mesalib/src/mesa/program/prog_statevars.c b/mesalib/src/mesa/program/prog_statevars.c
index 0c0c87faa..bdb335e4b 100644
--- a/mesalib/src/mesa/program/prog_statevars.c
+++ b/mesalib/src/mesa/program/prog_statevars.c
@@ -244,14 +244,14 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
{
/* state[1] is the texture unit */
const GLuint unit = (GLuint) state[1];
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
else
COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped);
}
return;
case STATE_FOG_COLOR:
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4V(value, ctx->Fog.Color);
else
COPY_4V(value, ctx->Fog.ColorUnclamped);
diff --git a/mesalib/src/mesa/program/prog_to_nir.c b/mesalib/src/mesa/program/prog_to_nir.c
index ff3d9f3be..6c5fa51ec 100644
--- a/mesalib/src/mesa/program/prog_to_nir.c
+++ b/mesalib/src/mesa/program/prog_to_nir.c
@@ -710,7 +710,7 @@ static const nir_op op_trans[MAX_OPCODE] = {
[OPCODE_DST] = 0,
[OPCODE_END] = 0,
[OPCODE_EX2] = nir_op_fexp2,
- [OPCODE_EXP] = nir_op_fexp,
+ [OPCODE_EXP] = 0,
[OPCODE_FLR] = nir_op_ffloor,
[OPCODE_FRC] = nir_op_ffract,
[OPCODE_LG2] = nir_op_flog2,
diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c
index 4f28e2a3b..fb61f4d36 100644
--- a/mesalib/src/mesa/program/program.c
+++ b/mesalib/src/mesa/program/program.c
@@ -102,6 +102,8 @@ _mesa_init_program(struct gl_context *ctx)
_mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current,
NULL);
+ _mesa_reference_compprog(ctx, &ctx->ComputeProgram.Current, NULL);
+
/* XXX probably move this stuff */
ctx->ATIFragmentShader.Enabled = GL_FALSE;
ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
@@ -121,6 +123,7 @@ _mesa_free_program_data(struct gl_context *ctx)
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
_mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache);
_mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL);
+ _mesa_reference_compprog(ctx, &ctx->ComputeProgram.Current, NULL);
/* XXX probably move this stuff */
if (ctx->ATIFragmentShader.Current) {
diff --git a/mesalib/src/mesa/program/program.h b/mesalib/src/mesa/program/program.h
index 0b0d1ac6f..2d92ab2f1 100644
--- a/mesalib/src/mesa/program/program.h
+++ b/mesalib/src/mesa/program/program.h
@@ -138,6 +138,15 @@ _mesa_reference_geomprog(struct gl_context *ctx,
(struct gl_program *) prog);
}
+static inline void
+_mesa_reference_compprog(struct gl_context *ctx,
+ struct gl_compute_program **ptr,
+ struct gl_compute_program *prog)
+{
+ _mesa_reference_program(ctx, (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
extern struct gl_program *
_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog);
@@ -276,6 +285,19 @@ gl_geometry_program_const(const struct gl_program *prog)
}
+static inline struct gl_compute_program *
+gl_compute_program(struct gl_program *prog)
+{
+ return (struct gl_compute_program *) prog;
+}
+
+static inline const struct gl_compute_program *
+gl_compute_program_const(const struct gl_program *prog)
+{
+ return (const struct gl_compute_program *) prog;
+}
+
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/mesalib/src/mesa/state_tracker/st_atom_array.c b/mesalib/src/mesa/state_tracker/st_atom_array.c
index d4fb8b862..56b8019a3 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_array.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_array.c
@@ -44,7 +44,6 @@
#include "cso_cache/cso_context.h"
#include "util/u_math.h"
-
#include "main/bufferobj.h"
#include "main/glformats.h"
@@ -311,6 +310,18 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
return PIPE_FORMAT_NONE; /* silence compiler warning */
}
+static const struct gl_client_array *
+get_client_array(const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ int attr)
+{
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ /* st_program uses 0xffffffff to denote a double placeholder attribute */
+ if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER)
+ return NULL;
+ return arrays[mesaAttr];
+}
+
/**
* Examine the active arrays to determine if we have interleaved
* vertex arrays all living in one VBO, or all living in user space.
@@ -327,11 +338,16 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
GLboolean userSpaceBuffer = GL_FALSE;
for (attr = 0; attr < vpv->num_inputs; attr++) {
- const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- const struct gl_buffer_object *bufObj = array->BufferObj;
- const GLsizei stride = array->StrideB; /* in bytes */
+ const struct gl_client_array *array;
+ const struct gl_buffer_object *bufObj;
+ GLsizei stride;
+
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+ stride = array->StrideB; /* in bytes */
+ bufObj = array->BufferObj;
if (attr == 0) {
/* save info about the first array */
firstStride = stride;
@@ -358,6 +374,55 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
return GL_TRUE;
}
+static void init_velement(struct pipe_vertex_element *velement,
+ int src_offset, int format,
+ int instance_divisor, int vbo_index)
+{
+ velement->src_offset = src_offset;
+ velement->src_format = format;
+ velement->instance_divisor = instance_divisor;
+ velement->vertex_buffer_index = vbo_index;
+ assert(velement->src_format);
+}
+
+static void init_velement_lowered(struct st_context *st,
+ struct pipe_vertex_element *velements,
+ int src_offset, int format,
+ int instance_divisor, int vbo_index,
+ int nr_components, GLboolean doubles,
+ GLuint *attr_idx)
+{
+ int idx = *attr_idx;
+ if (doubles) {
+ int lower_format;
+
+ if (nr_components == 1)
+ lower_format = PIPE_FORMAT_R32G32_UINT;
+ else if (nr_components >= 2)
+ lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+
+ init_velement(&velements[idx], src_offset,
+ lower_format, instance_divisor, vbo_index);
+ idx++;
+
+ if (nr_components > 2) {
+ if (nr_components == 3)
+ lower_format = PIPE_FORMAT_R32G32_UINT;
+ else if (nr_components >= 4)
+ lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+
+ init_velement(&velements[idx], src_offset + 4 * sizeof(float),
+ lower_format, instance_divisor, vbo_index);
+ idx++;
+ }
+ } else {
+ init_velement(&velements[idx], src_offset,
+ format, instance_divisor, vbo_index);
+ idx++;
+ }
+ *attr_idx = idx;
+}
+
/**
* Set up for drawing interleaved arrays that all live in one VBO
* or all live in user space.
@@ -365,13 +430,15 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
* \param velements returns vertex element info
*/
static boolean
-setup_interleaved_attribs(const struct st_vertex_program *vp,
+setup_interleaved_attribs(struct st_context *st,
+ const struct st_vertex_program *vp,
const struct st_vp_variant *vpv,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer *vbuffer,
- struct pipe_vertex_element velements[])
+ struct pipe_vertex_element velements[],
+ unsigned *num_velements)
{
- GLuint attr;
+ GLuint attr, attr_idx;
const GLubyte *low_addr = NULL;
GLboolean usingVBO; /* all arrays in a VBO? */
struct gl_buffer_object *bufobj;
@@ -381,8 +448,10 @@ setup_interleaved_attribs(const struct st_vertex_program *vp,
* Init bufobj and stride.
*/
if (vpv->num_inputs) {
- const GLuint mesaAttr0 = vp->index_to_input[0];
- const struct gl_client_array *array = arrays[mesaAttr0];
+ const struct gl_client_array *array;
+
+ array = get_client_array(vp, arrays, 0);
+ assert(array);
/* Since we're doing interleaved arrays, we know there'll be at most
* one buffer object and the stride will be the same for all arrays.
@@ -394,7 +463,11 @@ setup_interleaved_attribs(const struct st_vertex_program *vp,
low_addr = arrays[vp->index_to_input[0]]->Ptr;
for (attr = 1; attr < vpv->num_inputs; attr++) {
- const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr;
+ const GLubyte *start;
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+ start = array->Ptr;
low_addr = MIN2(low_addr, start);
}
}
@@ -408,25 +481,33 @@ setup_interleaved_attribs(const struct st_vertex_program *vp,
/* are the arrays in user space? */
usingVBO = _mesa_is_bufferobj(bufobj);
+ attr_idx = 0;
for (attr = 0; attr < vpv->num_inputs; attr++) {
- const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- unsigned src_offset = (unsigned) (array->Ptr - low_addr);
+ const struct gl_client_array *array;
+ unsigned src_offset;
+ unsigned src_format;
+
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+ src_offset = (unsigned) (array->Ptr - low_addr);
assert(array->_ElementSize ==
_mesa_bytes_per_vertex_attrib(array->Size, array->Type));
- velements[attr].src_offset = src_offset;
- velements[attr].instance_divisor = array->InstanceDivisor;
- velements[attr].vertex_buffer_index = 0;
- velements[attr].src_format = st_pipe_vertex_format(array->Type,
- array->Size,
- array->Format,
- array->Normalized,
- array->Integer);
- assert(velements[attr].src_format);
+ src_format = st_pipe_vertex_format(array->Type,
+ array->Size,
+ array->Format,
+ array->Normalized,
+ array->Integer);
+
+ init_velement_lowered(st, velements, src_offset, src_format,
+ array->InstanceDivisor, 0,
+ array->Size, array->Doubles, &attr_idx);
}
+ *num_velements = attr_idx;
+
/*
* Return the vbuffer info and setup user-space attrib info, if needed.
*/
@@ -472,17 +553,25 @@ setup_non_interleaved_attribs(struct st_context *st,
const struct st_vp_variant *vpv,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer vbuffer[],
- struct pipe_vertex_element velements[])
+ struct pipe_vertex_element velements[],
+ unsigned *num_velements)
{
struct gl_context *ctx = st->ctx;
- GLuint attr;
+ GLuint attr, attr_idx = 0;
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- struct gl_buffer_object *bufobj = array->BufferObj;
- GLsizei stride = array->StrideB;
+ const struct gl_client_array *array;
+ struct gl_buffer_object *bufobj;
+ GLsizei stride;
+ unsigned src_format;
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+
+ stride = array->StrideB;
+ bufobj = array->BufferObj;
assert(array->_ElementSize ==
_mesa_bytes_per_vertex_attrib(array->Size, array->Type));
@@ -524,16 +613,19 @@ setup_non_interleaved_attribs(struct st_context *st,
/* common-case setup */
vbuffer[attr].stride = stride; /* in bytes */
- velements[attr].src_offset = 0;
- velements[attr].instance_divisor = array->InstanceDivisor;
- velements[attr].vertex_buffer_index = attr;
- velements[attr].src_format = st_pipe_vertex_format(array->Type,
- array->Size,
- array->Format,
- array->Normalized,
- array->Integer);
- assert(velements[attr].src_format);
+ src_format = st_pipe_vertex_format(array->Type,
+ array->Size,
+ array->Format,
+ array->Normalized,
+ array->Integer);
+
+ init_velement_lowered(st, velements, 0, src_format,
+ array->InstanceDivisor, attr,
+ array->Size, array->Doubles, &attr_idx);
+
}
+
+ *num_velements = attr_idx;
return TRUE;
}
@@ -563,25 +655,23 @@ static void update_array(struct st_context *st)
* Setup the vbuffer[] and velements[] arrays.
*/
if (is_interleaved_arrays(vp, vpv, arrays)) {
- if (!setup_interleaved_attribs(vp, vpv, arrays, vbuffer, velements)) {
+ if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements, &num_velements)) {
st->vertex_array_out_of_memory = TRUE;
return;
}
num_vbuffers = 1;
- num_velements = vpv->num_inputs;
if (num_velements == 0)
num_vbuffers = 0;
}
else {
if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer,
- velements)) {
+ velements, &num_velements)) {
st->vertex_array_out_of_memory = TRUE;
return;
}
num_vbuffers = vpv->num_inputs;
- num_velements = vpv->num_inputs;
}
cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer);
diff --git a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
index b195c55b3..ae883a253 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -134,7 +134,10 @@ update_framebuffer_state( struct st_context *st )
else {
strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
if (strb) {
- assert(strb->surface);
+ if (strb->is_rtt) {
+ /* rendering to a GL texture, may have to update surface */
+ st_update_renderbuffer_surface(st, strb);
+ }
pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
update_framebuffer_size(framebuffer, strb->surface);
}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
index 296ea1e0d..0399eef72 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
@@ -842,7 +842,7 @@ void st_init_fbo_functions(struct dd_function_table *functions)
functions->NewFramebuffer = st_new_framebuffer;
functions->NewRenderbuffer = st_new_renderbuffer;
functions->BindFramebuffer = st_bind_framebuffer;
- functions->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
+ functions->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw;
functions->RenderTexture = st_render_texture;
functions->FinishRenderTexture = st_finish_render_texture;
functions->ValidateFramebuffer = st_validate_framebuffer;
diff --git a/mesalib/src/mesa/state_tracker/st_cb_flush.c b/mesalib/src/mesa/state_tracker/st_cb_flush.c
index ca51eeee3..82affd2de 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_flush.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_flush.c
@@ -141,11 +141,44 @@ static void st_glFinish(struct gl_context *ctx)
}
-void st_init_flush_functions(struct dd_function_table *functions)
+/**
+ * Query information about GPU resets observed by this context
+ *
+ * Called via \c dd_function_table::GetGraphicsResetStatus.
+ */
+static GLenum
+st_get_graphics_reset_status(struct gl_context *ctx)
+{
+ struct st_context *st = st_context(ctx);
+ enum pipe_reset_status status;
+
+ status = st->pipe->get_device_reset_status(st->pipe);
+
+ switch (status) {
+ case PIPE_NO_RESET:
+ return GL_NO_ERROR;
+ case PIPE_GUILTY_CONTEXT_RESET:
+ return GL_GUILTY_CONTEXT_RESET_ARB;
+ case PIPE_INNOCENT_CONTEXT_RESET:
+ return GL_INNOCENT_CONTEXT_RESET_ARB;
+ case PIPE_UNKNOWN_CONTEXT_RESET:
+ return GL_UNKNOWN_CONTEXT_RESET_ARB;
+ default:
+ assert(0);
+ return GL_NO_ERROR;
+ }
+}
+
+
+void st_init_flush_functions(struct pipe_screen *screen,
+ struct dd_function_table *functions)
{
functions->Flush = st_glFlush;
functions->Finish = st_glFinish;
+ if (screen->get_param(screen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY))
+ functions->GetGraphicsResetStatus = st_get_graphics_reset_status;
+
/* Windows opengl32.dll calls glFinish prior to every swapbuffers.
* This is unnecessary and degrades performance. Luckily we have some
* scope to work around this, as the externally-visible behaviour of
diff --git a/mesalib/src/mesa/state_tracker/st_cb_flush.h b/mesalib/src/mesa/state_tracker/st_cb_flush.h
index 84ffc63ae..f92dcd56b 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_flush.h
+++ b/mesalib/src/mesa/state_tracker/st_cb_flush.h
@@ -37,7 +37,8 @@ struct pipe_fence_handle;
struct st_context;
extern void
-st_init_flush_functions(struct dd_function_table *functions);
+st_init_flush_functions(struct pipe_screen *screen,
+ struct dd_function_table *functions);
extern void
st_flush(struct st_context *st,
diff --git a/mesalib/src/mesa/state_tracker/st_cb_perfmon.c b/mesalib/src/mesa/state_tracker/st_cb_perfmon.c
new file mode 100644
index 000000000..1bb5be397
--- /dev/null
+++ b/mesalib/src/mesa/state_tracker/st_cb_perfmon.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2013 Christoph Bumiller
+ * Copyright (C) 2015 Samuel Pitoiset
+ *
+ * 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.
+ */
+
+/**
+ * Performance monitoring counters interface to gallium.
+ */
+
+#include "st_debug.h"
+#include "st_context.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_perfmon.h"
+
+#include "util/bitset.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "util/u_memory.h"
+
+/**
+ * Return a PIPE_QUERY_x type >= PIPE_QUERY_DRIVER_SPECIFIC, or -1 if
+ * the driver-specific query doesn't exist.
+ */
+static int
+find_query_type(struct pipe_screen *screen, const char *name)
+{
+ int num_queries;
+ int type = -1;
+ int i;
+
+ num_queries = screen->get_driver_query_info(screen, 0, NULL);
+ if (!num_queries)
+ return type;
+
+ for (i = 0; i < num_queries; i++) {
+ struct pipe_driver_query_info info;
+
+ if (!screen->get_driver_query_info(screen, i, &info))
+ continue;
+
+ if (!strncmp(info.name, name, strlen(name))) {
+ type = info.query_type;
+ break;
+ }
+ }
+ return type;
+}
+
+/**
+ * Return TRUE if the underlying driver expose GPU counters.
+ */
+static bool
+has_gpu_counters(struct pipe_screen *screen)
+{
+ int num_groups, gid;
+
+ num_groups = screen->get_driver_query_group_info(screen, 0, NULL);
+ for (gid = 0; gid < num_groups; gid++) {
+ struct pipe_driver_query_group_info group_info;
+
+ if (!screen->get_driver_query_group_info(screen, gid, &group_info))
+ continue;
+
+ if (group_info.type == PIPE_DRIVER_QUERY_GROUP_TYPE_GPU)
+ return true;
+ }
+ return false;
+}
+
+static bool
+init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_screen *screen = st_context(ctx)->pipe->screen;
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ int gid, cid;
+
+ st_flush_bitmap_cache(st_context(ctx));
+
+ /* Create a query for each active counter. */
+ for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) {
+ const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid];
+
+ if (m->ActiveGroups[gid] > g->MaxActiveCounters) {
+ /* Maximum number of counters reached. Cannot start the session. */
+ if (ST_DEBUG & DEBUG_MESA) {
+ debug_printf("Maximum number of counters reached. "
+ "Cannot start the session!\n");
+ }
+ return false;
+ }
+
+ for (cid = 0; cid < g->NumCounters; cid++) {
+ const struct gl_perf_monitor_counter *c = &g->Counters[cid];
+ struct st_perf_counter_object *cntr;
+ int query_type;
+
+ if (!BITSET_TEST(m->ActiveCounters[gid], cid))
+ continue;
+
+ query_type = find_query_type(screen, c->Name);
+ assert(query_type != -1);
+
+ cntr = CALLOC_STRUCT(st_perf_counter_object);
+ if (!cntr)
+ return false;
+
+ cntr->query = pipe->create_query(pipe, query_type, 0);
+ cntr->id = cid;
+ cntr->group_id = gid;
+
+ list_addtail(&cntr->list, &stm->active_counters);
+ }
+ }
+ return true;
+}
+
+static void
+reset_perf_monitor(struct st_perf_monitor_object *stm,
+ struct pipe_context *pipe)
+{
+ struct st_perf_counter_object *cntr, *tmp;
+
+ LIST_FOR_EACH_ENTRY_SAFE(cntr, tmp, &stm->active_counters, list) {
+ if (cntr->query)
+ pipe->destroy_query(pipe, cntr->query);
+ list_del(&cntr->list);
+ free(cntr);
+ }
+}
+
+static struct gl_perf_monitor_object *
+st_NewPerfMonitor(struct gl_context *ctx)
+{
+ struct st_perf_monitor_object *stq = ST_CALLOC_STRUCT(st_perf_monitor_object);
+ if (stq) {
+ list_inithead(&stq->active_counters);
+ return &stq->base;
+ }
+ return NULL;
+}
+
+static void
+st_DeletePerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+
+ reset_perf_monitor(stm, pipe);
+ FREE(stm);
+}
+
+static GLboolean
+st_BeginPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_perf_counter_object *cntr;
+
+ if (LIST_IS_EMPTY(&stm->active_counters)) {
+ /* Create a query for each active counter before starting
+ * a new monitoring session. */
+ if (!init_perf_monitor(ctx, m))
+ goto fail;
+ }
+
+ /* Start the query for each active counter. */
+ LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) {
+ if (!pipe->begin_query(pipe, cntr->query))
+ goto fail;
+ }
+ return true;
+
+fail:
+ /* Failed to start the monitoring session. */
+ reset_perf_monitor(stm, pipe);
+ return false;
+}
+
+static void
+st_EndPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_perf_counter_object *cntr;
+
+ /* Stop the query for each active counter. */
+ LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list)
+ pipe->end_query(pipe, cntr->query);
+}
+
+static void
+st_ResetPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+
+ if (!m->Ended)
+ st_EndPerfMonitor(ctx, m);
+
+ reset_perf_monitor(stm, pipe);
+
+ if (m->Active)
+ st_BeginPerfMonitor(ctx, m);
+}
+
+static GLboolean
+st_IsPerfMonitorResultAvailable(struct gl_context *ctx,
+ struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_perf_counter_object *cntr;
+
+ if (LIST_IS_EMPTY(&stm->active_counters))
+ return false;
+
+ /* The result of a monitoring session is only available if the query of
+ * each active counter is idle. */
+ LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) {
+ union pipe_query_result result;
+ if (!pipe->get_query_result(pipe, cntr->query, FALSE, &result)) {
+ /* The query is busy. */
+ return false;
+ }
+ }
+ return true;
+}
+
+static void
+st_GetPerfMonitorResult(struct gl_context *ctx,
+ struct gl_perf_monitor_object *m,
+ GLsizei dataSize,
+ GLuint *data,
+ GLint *bytesWritten)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_perf_counter_object *cntr;
+
+ /* Copy data to the supplied array (data).
+ *
+ * The output data format is: <group ID, counter ID, value> for each
+ * active counter. The API allows counters to appear in any order.
+ */
+ GLsizei offset = 0;
+
+ /* Read query results for each active counter. */
+ LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) {
+ union pipe_query_result result = { 0 };
+ int gid, cid;
+ GLenum type;
+
+ cid = cntr->id;
+ gid = cntr->group_id;
+ type = ctx->PerfMonitor.Groups[gid].Counters[cid].Type;
+
+ if (!pipe->get_query_result(pipe, cntr->query, TRUE, &result))
+ continue;
+
+ data[offset++] = gid;
+ data[offset++] = cid;
+ switch (type) {
+ case GL_UNSIGNED_INT64_AMD:
+ *(uint64_t *)&data[offset] = result.u64;
+ offset += sizeof(uint64_t) / sizeof(GLuint);
+ break;
+ case GL_UNSIGNED_INT:
+ *(uint32_t *)&data[offset] = result.u32;
+ offset += sizeof(uint32_t) / sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ case GL_PERCENTAGE_AMD:
+ *(GLfloat *)&data[offset] = result.f;
+ offset += sizeof(GLfloat) / sizeof(GLuint);
+ break;
+ }
+ }
+
+ if (bytesWritten)
+ *bytesWritten = offset * sizeof(GLuint);
+}
+
+
+bool
+st_init_perfmon(struct st_context *st)
+{
+ struct gl_perf_monitor_state *perfmon = &st->ctx->PerfMonitor;
+ struct pipe_screen *screen = st->pipe->screen;
+ struct gl_perf_monitor_group *groups = NULL;
+ int num_counters, num_groups;
+ int gid, cid;
+
+ if (!screen->get_driver_query_info || !screen->get_driver_query_group_info)
+ return false;
+
+ if (!has_gpu_counters(screen)) {
+ /* According to the spec, GL_AMD_performance_monitor must only
+ * expose GPU counters. */
+ return false;
+ }
+
+ /* Get the number of available queries. */
+ num_counters = screen->get_driver_query_info(screen, 0, NULL);
+ if (!num_counters)
+ return false;
+
+ /* Get the number of available groups. */
+ num_groups = screen->get_driver_query_group_info(screen, 0, NULL);
+ if (num_groups)
+ groups = CALLOC(num_groups, sizeof(*groups));
+ if (!groups)
+ return false;
+
+ for (gid = 0; gid < num_groups; gid++) {
+ struct gl_perf_monitor_group *g = &groups[perfmon->NumGroups];
+ struct pipe_driver_query_group_info group_info;
+ struct gl_perf_monitor_counter *counters = NULL;
+
+ if (!screen->get_driver_query_group_info(screen, gid, &group_info))
+ continue;
+
+ if (group_info.type != PIPE_DRIVER_QUERY_GROUP_TYPE_GPU)
+ continue;
+
+ g->Name = group_info.name;
+ g->MaxActiveCounters = group_info.max_active_queries;
+ g->NumCounters = 0;
+ g->Counters = NULL;
+
+ if (group_info.num_queries)
+ counters = CALLOC(group_info.num_queries, sizeof(*counters));
+ if (!counters)
+ goto fail;
+
+ for (cid = 0; cid < num_counters; cid++) {
+ struct gl_perf_monitor_counter *c = &counters[g->NumCounters];
+ struct pipe_driver_query_info info;
+
+ if (!screen->get_driver_query_info(screen, cid, &info))
+ continue;
+ if (info.group_id != gid)
+ continue;
+
+ c->Name = info.name;
+ switch (info.type) {
+ case PIPE_DRIVER_QUERY_TYPE_UINT64:
+ c->Minimum.u64 = 0;
+ c->Maximum.u64 = info.max_value.u64 ? info.max_value.u64 : -1;
+ c->Type = GL_UNSIGNED_INT64_AMD;
+ break;
+ case PIPE_DRIVER_QUERY_TYPE_UINT:
+ c->Minimum.u32 = 0;
+ c->Maximum.u32 = info.max_value.u32 ? info.max_value.u32 : -1;
+ c->Type = GL_UNSIGNED_INT;
+ break;
+ case PIPE_DRIVER_QUERY_TYPE_FLOAT:
+ c->Minimum.f = 0.0;
+ c->Maximum.f = info.max_value.f ? info.max_value.f : -1;
+ c->Type = GL_FLOAT;
+ break;
+ case PIPE_DRIVER_QUERY_TYPE_PERCENTAGE:
+ c->Minimum.f = 0.0f;
+ c->Maximum.f = 100.0f;
+ c->Type = GL_PERCENTAGE_AMD;
+ break;
+ default:
+ unreachable("Invalid driver query type!");
+ }
+ g->NumCounters++;
+ }
+ g->Counters = counters;
+ perfmon->NumGroups++;
+ }
+ perfmon->Groups = groups;
+
+ return true;
+
+fail:
+ for (gid = 0; gid < num_groups; gid++)
+ FREE((void *)groups[gid].Counters);
+ FREE(groups);
+ return false;
+}
+
+void
+st_destroy_perfmon(struct st_context *st)
+{
+ struct gl_perf_monitor_state *perfmon = &st->ctx->PerfMonitor;
+ int gid;
+
+ for (gid = 0; gid < perfmon->NumGroups; gid++)
+ FREE((void *)perfmon->Groups[gid].Counters);
+ FREE((void *)perfmon->Groups);
+}
+
+void st_init_perfmon_functions(struct dd_function_table *functions)
+{
+ functions->NewPerfMonitor = st_NewPerfMonitor;
+ functions->DeletePerfMonitor = st_DeletePerfMonitor;
+ functions->BeginPerfMonitor = st_BeginPerfMonitor;
+ functions->EndPerfMonitor = st_EndPerfMonitor;
+ functions->ResetPerfMonitor = st_ResetPerfMonitor;
+ functions->IsPerfMonitorResultAvailable = st_IsPerfMonitorResultAvailable;
+ functions->GetPerfMonitorResult = st_GetPerfMonitorResult;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_perfmon.h b/mesalib/src/mesa/state_tracker/st_cb_perfmon.h
new file mode 100644
index 000000000..13d3627de
--- /dev/null
+++ b/mesalib/src/mesa/state_tracker/st_cb_perfmon.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Christoph Bumiller
+ * Copyright (C) 2015 Samuel Pitoiset
+ *
+ * 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 ST_CB_PERFMON_H
+#define ST_CB_PERFMON_H
+
+#include "util/list.h"
+
+/**
+ * Subclass of gl_perf_monitor_object
+ */
+struct st_perf_monitor_object
+{
+ struct gl_perf_monitor_object base;
+ struct list_head active_counters;
+};
+
+struct st_perf_counter_object
+{
+ struct list_head list;
+ struct pipe_query *query;
+ int id;
+ int group_id;
+};
+
+/**
+ * Cast wrapper
+ */
+static INLINE struct st_perf_monitor_object *
+st_perf_monitor_object(struct gl_perf_monitor_object *q)
+{
+ return (struct st_perf_monitor_object *)q;
+}
+
+bool
+st_init_perfmon(struct st_context *st);
+
+void
+st_destroy_perfmon(struct st_context *st);
+
+extern void
+st_init_perfmon_functions(struct dd_function_table *functions);
+
+#endif
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c
index 5fe132ac2..69e0f929d 100644
--- a/mesalib/src/mesa/state_tracker/st_context.c
+++ b/mesalib/src/mesa/state_tracker/st_context.c
@@ -51,6 +51,7 @@
#include "st_cb_fbo.h"
#include "st_cb_feedback.h"
#include "st_cb_msaa.h"
+#include "st_cb_perfmon.h"
#include "st_cb_program.h"
#include "st_cb_queryobj.h"
#include "st_cb_readpixels.h"
@@ -116,6 +117,7 @@ st_destroy_context_priv(struct st_context *st)
st_destroy_bitmap(st);
st_destroy_drawpix(st);
st_destroy_drawtex(st);
+ st_destroy_perfmon(st);
for (shader = 0; shader < ARRAY_SIZE(st->state.sampler_views); shader++) {
for (i = 0; i < ARRAY_SIZE(st->state.sampler_views[0]); i++) {
@@ -250,6 +252,12 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,
st_init_extensions(st->pipe->screen, &ctx->Const,
&ctx->Extensions, &st->options, ctx->Mesa_DXTn);
+ if (st_init_perfmon(st)) {
+ /* GL_AMD_performance_monitor is only enabled when the underlying
+ * driver expose GPU hardware performance counters. */
+ ctx->Extensions.AMD_performance_monitor = GL_TRUE;
+ }
+
/* Enable shader-based fallbacks for ARB_color_buffer_float if needed. */
if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) {
if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) {
@@ -313,7 +321,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
struct st_context *st;
memset(&funcs, 0, sizeof(funcs));
- st_init_driver_functions(&funcs);
+ st_init_driver_functions(pipe->screen, &funcs);
ctx = _mesa_create_context(api, visual, shareCtx, &funcs);
if (!ctx) {
@@ -393,7 +401,8 @@ void st_destroy_context( struct st_context *st )
}
-void st_init_driver_functions(struct dd_function_table *functions)
+void st_init_driver_functions(struct pipe_screen *screen,
+ struct dd_function_table *functions)
{
_mesa_init_shader_object_functions(functions);
_mesa_init_sampler_object_functions(functions);
@@ -414,13 +423,14 @@ void st_init_driver_functions(struct dd_function_table *functions)
st_init_fbo_functions(functions);
st_init_feedback_functions(functions);
st_init_msaa_functions(functions);
+ st_init_perfmon_functions(functions);
st_init_program_functions(functions);
st_init_query_functions(functions);
st_init_cond_render_functions(functions);
st_init_readpixels_functions(functions);
st_init_texture_functions(functions);
st_init_texture_barrier_functions(functions);
- st_init_flush_functions(functions);
+ st_init_flush_functions(screen, functions);
st_init_string_functions(functions);
st_init_viewport_functions(functions);
diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h
index 8a9504bb7..dac5a4b90 100644
--- a/mesalib/src/mesa/state_tracker/st_context.h
+++ b/mesalib/src/mesa/state_tracker/st_context.h
@@ -237,7 +237,8 @@ struct st_framebuffer
};
-extern void st_init_driver_functions(struct dd_function_table *functions);
+extern void st_init_driver_functions(struct pipe_screen *screen,
+ struct dd_function_table *functions);
void st_invalidate_state(struct gl_context * ctx, GLuint new_state);
diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c
index 82e4a3009..23a45883d 100644
--- a/mesalib/src/mesa/state_tracker/st_extensions.c
+++ b/mesalib/src/mesa/state_tracker/st_extensions.c
@@ -650,6 +650,12 @@ void st_init_extensions(struct pipe_screen *screen,
ARRAY_SIZE(vertex_mapping), PIPE_BUFFER,
PIPE_BIND_VERTEX_BUFFER);
+ /* ARB_direct_state_access requires OpenGL 2.0. Assume that all drivers
+ * that support NPOT textures are able to support GL 2.0.
+ */
+ if (extensions->ARB_texture_non_power_of_two)
+ extensions->ARB_direct_state_access = GL_TRUE;
+
if (extensions->ARB_stencil_texturing)
extensions->ARB_texture_stencil8 = GL_TRUE;
@@ -909,6 +915,8 @@ void st_init_extensions(struct pipe_screen *screen,
if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
PIPE_SHADER_CAP_DOUBLES) &&
screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
- PIPE_SHADER_CAP_DOUBLES))
+ PIPE_SHADER_CAP_DOUBLES)) {
extensions->ARB_gpu_shader_fp64 = GL_TRUE;
+ extensions->ARB_vertex_attrib_64bit = GL_TRUE;
+ }
}
diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c
index 181465dd8..db7b5b71d 100644
--- a/mesalib/src/mesa/state_tracker/st_format.c
+++ b/mesalib/src/mesa/state_tracker/st_format.c
@@ -991,7 +991,7 @@ static const struct format_mapping format_map[] = {
{
{ GL_RGB10, 0 },
{ PIPE_FORMAT_B10G10R10X2_UNORM, PIPE_FORMAT_B10G10R10A2_UNORM,
- DEFAULT_RGB_FORMATS }
+ PIPE_FORMAT_R10G10B10A2_UNORM, DEFAULT_RGB_FORMATS }
},
{
{ GL_RGB10_A2, 0 },
diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 93671ba9c..f0f2a77d0 100644
--- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -88,6 +88,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_src_reg(gl_register_file file, int index, int type)
@@ -101,6 +102,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_src_reg(gl_register_file file, int index, int type, int index2D)
@@ -114,6 +116,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_src_reg()
@@ -127,6 +130,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
explicit st_src_reg(st_dst_reg reg);
@@ -141,6 +145,11 @@ public:
st_src_reg *reladdr;
st_src_reg *reladdr2;
bool has_index2;
+ /*
+ * Is this the second half of a double register pair?
+ * currently used for input mapping only.
+ */
+ bool double_reg2;
};
class st_dst_reg {
@@ -197,6 +206,7 @@ st_src_reg::st_src_reg(st_dst_reg reg)
this->index2D = 0;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_dst_reg::st_dst_reg(st_src_reg reg)
@@ -677,8 +687,10 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
if (dinst->src[j].type == GLSL_TYPE_DOUBLE) {
dinst->src[j].index = initial_src_idx[j];
- if (swz > 1)
+ if (swz > 1) {
+ dinst->src[j].double_reg2 = true;
dinst->src[j].index++;
+ }
if (swz & 1)
dinst->src[j].swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W);
@@ -1941,7 +1953,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
break;
case ir_unop_i2b:
if (native_integers)
- emit(ir, TGSI_OPCODE_INEG, result_dst, op[0]);
+ emit(ir, TGSI_OPCODE_USNE, result_dst, op[0], st_src_reg_for_int(0));
else
emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_float(0.0));
break;
@@ -2611,6 +2623,7 @@ glsl_to_tgsi_visitor::visit(ir_assignment *ir)
assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
l.writemask = WRITEMASK_XYZW;
} else if (ir->lhs->type->is_scalar() &&
+ !ir->lhs->type->is_double() &&
ir->lhs->variable_referenced()->data.mode == ir_var_shader_out) {
/* FINISHME: This hack makes writing to gl_FragDepth, which lives in the
* FINISHME: W component of fragment shader output zero, work correctly.
@@ -3704,6 +3717,7 @@ glsl_to_tgsi_visitor::copy_propagate(void)
} else {
if (first->src[0].file != copy_chan->src[0].file ||
first->src[0].index != copy_chan->src[0].index ||
+ first->src[0].double_reg2 != copy_chan->src[0].double_reg2 ||
first->src[0].index2D != copy_chan->src[0].index2D) {
good = false;
break;
@@ -3719,6 +3733,7 @@ glsl_to_tgsi_visitor::copy_propagate(void)
inst->src[r].index = first->src[0].index;
inst->src[r].index2D = first->src[0].index2D;
inst->src[r].has_index2 = first->src[0].has_index2;
+ inst->src[r].double_reg2 = first->src[0].double_reg2;
int swizzle = 0;
for (int i = 0; i < 4; i++) {
@@ -4551,6 +4566,9 @@ dst_register(struct st_translate *t,
static struct ureg_src
src_register(struct st_translate *t, const st_src_reg *reg)
{
+ int index = reg->index;
+ int double_reg2 = reg->double_reg2 ? 1 : 0;
+
switch(reg->file) {
case PROGRAM_UNDEFINED:
return ureg_imm4f(t->ureg, 0, 0, 0, 0);
@@ -4576,8 +4594,12 @@ src_register(struct st_translate *t, const st_src_reg *reg)
return t->immediates[reg->index];
case PROGRAM_INPUT:
- assert(t->inputMapping[reg->index] < ARRAY_SIZE(t->inputs));
- return t->inputs[t->inputMapping[reg->index]];
+ /* GLSL inputs are 64-bit containers, so we have to
+ * map back to the original index and add the offset after
+ * mapping. */
+ index -= double_reg2;
+ assert(t->inputMapping[index] < ARRAY_SIZE(t->inputs));
+ return t->inputs[t->inputMapping[index] + double_reg2];
case PROGRAM_OUTPUT:
assert(t->outputMapping[reg->index] < ARRAY_SIZE(t->outputs));
diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c
index 840f76a13..0376954f7 100644
--- a/mesalib/src/mesa/state_tracker/st_manager.c
+++ b/mesalib/src/mesa/state_tracker/st_manager.c
@@ -680,6 +680,10 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE)
st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
+ if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS)
+ st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB;
+ if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED)
+ st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB;
/* need to perform version check */
if (attribs->major > 1 || attribs->minor > 0) {
diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c
index d93b3c7bc..a9110d3c6 100644
--- a/mesalib/src/mesa/state_tracker/st_program.c
+++ b/mesalib/src/mesa/state_tracker/st_program.c
@@ -194,6 +194,11 @@ st_prepare_vertex_program(struct gl_context *ctx,
stvp->input_to_index[attr] = stvp->num_inputs;
stvp->index_to_input[stvp->num_inputs] = attr;
stvp->num_inputs++;
+ if ((stvp->Base.Base.DoubleInputsRead & BITFIELD64_BIT(attr)) != 0) {
+ /* add placeholder for second part of a double attribute */
+ stvp->index_to_input[stvp->num_inputs] = ST_DOUBLE_ATTRIB_PLACEHOLDER;
+ stvp->num_inputs++;
+ }
}
}
/* bit of a hack, presetup potentially unused edgeflag input */
diff --git a/mesalib/src/mesa/state_tracker/st_program.h b/mesalib/src/mesa/state_tracker/st_program.h
index b2c86faec..a2c56062d 100644
--- a/mesalib/src/mesa/state_tracker/st_program.h
+++ b/mesalib/src/mesa/state_tracker/st_program.h
@@ -45,6 +45,7 @@
extern "C" {
#endif
+#define ST_DOUBLE_ATTRIB_PLACEHOLDER 0xffffffff
/** Fragment program variant key */
struct st_fp_variant_key
diff --git a/mesalib/src/mesa/swrast/s_drawpix.c b/mesalib/src/mesa/swrast/s_drawpix.c
index bf427266c..fb677ee1b 100644
--- a/mesalib/src/mesa/swrast/s_drawpix.c
+++ b/mesalib/src/mesa/swrast/s_drawpix.c
@@ -448,14 +448,34 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y,
{
const GLbitfield interpMask = span.interpMask;
const GLbitfield arrayMask = span.arrayMask;
- const GLint srcStride
- = _mesa_image_row_stride(unpack, width, format, type);
GLint skipPixels = 0;
/* use span array for temp color storage */
GLfloat *rgba = (GLfloat *) span.array->attribs[VARYING_SLOT_COL0];
void *tempImage = NULL;
- if (unpack->SwapBytes) {
+ /* We have to deal with GL_COLOR_INDEX manually because
+ * _mesa_format_convert does not handle this format. So what we do here is
+ * convert it to RGBA ubyte first and then convert from that to dst as
+ * usual.
+ */
+ if (format == GL_COLOR_INDEX) {
+ /* This will handle byte swapping and transferops if needed */
+ tempImage =
+ _mesa_unpack_color_index_to_rgba_ubyte(ctx, 2,
+ pixels, format, type,
+ width, height, 1,
+ unpack,
+ transferOps);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+ return;
+ }
+
+ transferOps = 0;
+ pixels = tempImage;
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ } else if (unpack->SwapBytes) {
/* We have to handle byte-swapping scenarios before calling
* _mesa_format_convert
*/
@@ -476,6 +496,9 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y,
}
}
+ const GLint srcStride
+ = _mesa_image_row_stride(unpack, width, format, type);
+
/* if the span is wider than SWRAST_MAX_WIDTH we have to do it in chunks */
while (skipPixels < width) {
const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
diff --git a/mesalib/src/mesa/swrast/s_texrender.c b/mesalib/src/mesa/swrast/s_texrender.c
index fa853c919..4e41b3b72 100644
--- a/mesalib/src/mesa/swrast/s_texrender.c
+++ b/mesalib/src/mesa/swrast/s_texrender.c
@@ -72,7 +72,7 @@ update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
* \param fb the framebuffer object the texture is being bound to
* \param att the fb attachment point of the texture
*
- * \sa _mesa_framebuffer_renderbuffer
+ * \sa _mesa_FramebufferRenderbuffer_sw
*/
void
_swrast_render_texture(struct gl_context *ctx,
diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
index 17e057836..e73b8fb5f 100644
--- a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
@@ -31,14 +31,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* ATTR */
#define ATTRI( A, N, V0, V1, V2, V3 ) \
- ATTR_UNION(A, N, GL_INT, INT_AS_UNION(V0), INT_AS_UNION(V1), \
+ ATTR_UNION(A, N, GL_INT, fi_type, INT_AS_UNION(V0), INT_AS_UNION(V1), \
INT_AS_UNION(V2), INT_AS_UNION(V3))
#define ATTRUI( A, N, V0, V1, V2, V3 ) \
- ATTR_UNION(A, N, GL_UNSIGNED_INT, UINT_AS_UNION(V0), UINT_AS_UNION(V1), \
+ ATTR_UNION(A, N, GL_UNSIGNED_INT, fi_type, UINT_AS_UNION(V0), UINT_AS_UNION(V1), \
UINT_AS_UNION(V2), UINT_AS_UNION(V3))
#define ATTRF( A, N, V0, V1, V2, V3 ) \
- ATTR_UNION(A, N, GL_FLOAT, FLOAT_AS_UNION(V0), FLOAT_AS_UNION(V1),\
+ ATTR_UNION(A, N, GL_FLOAT, fi_type, FLOAT_AS_UNION(V0), FLOAT_AS_UNION(V1),\
FLOAT_AS_UNION(V2), FLOAT_AS_UNION(V3))
+#define ATTRD( A, N, V0, V1, V2, V3 ) \
+ ATTR_UNION(A, N, GL_DOUBLE, double, V0, V1, V2, V3)
/* float */
@@ -232,6 +234,19 @@ static inline float conv_i2_to_norm_float(const struct gl_context *ctx, int i2)
ERROR(GL_INVALID_VALUE); \
} while(0)
+
+/* Doubles */
+#define ATTR1DV( A, V ) ATTRD( A, 1, (V)[0], 0, 0, 1 )
+#define ATTR2DV( A, V ) ATTRD( A, 2, (V)[0], (V)[1], 0, 1 )
+#define ATTR3DV( A, V ) ATTRD( A, 3, (V)[0], (V)[1], (V)[2], 1 )
+#define ATTR4DV( A, V ) ATTRD( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
+
+#define ATTR1D( A, X ) ATTRD( A, 1, X, 0, 0, 1 )
+#define ATTR2D( A, X, Y ) ATTRD( A, 2, X, Y, 0, 1 )
+#define ATTR3D( A, X, Y, Z ) ATTRD( A, 3, X, Y, Z, 1 )
+#define ATTR4D( A, X, Y, Z, W ) ATTRD( A, 4, X, Y, Z, W )
+
+
static void GLAPIENTRY
TAG(Vertex2f)(GLfloat x, GLfloat y)
{
@@ -1190,6 +1205,104 @@ TAG(VertexAttribP4uiv)(GLuint index, GLenum type, GLboolean normalized,
}
+
+static void GLAPIENTRY
+TAG(VertexAttribL1d)(GLuint index, GLdouble x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR1D(0, x);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1D(VBO_ATTRIB_GENERIC0 + index, x);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL1dv)(GLuint index, const GLdouble * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR1DV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1DV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL2d)(GLuint index, GLdouble x, GLdouble y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR2D(0, x, y);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2D(VBO_ATTRIB_GENERIC0 + index, x, y);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL2dv)(GLuint index, const GLdouble * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR2DV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2DV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL3d)(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR3D(0, x, y, z);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3D(VBO_ATTRIB_GENERIC0 + index, x, y, z);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL3dv)(GLuint index, const GLdouble * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR3DV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3DV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL4d)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR4D(0, x, y, z, w);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4D(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL4dv)(GLuint index, const GLdouble * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR4DV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4DV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+
#undef ATTR1FV
#undef ATTR2FV
#undef ATTR3FV
diff --git a/mesalib/src/mesa/vbo/vbo_context.h b/mesalib/src/mesa/vbo/vbo_context.h
index 6099b56e6..a376efe34 100644
--- a/mesalib/src/mesa/vbo/vbo_context.h
+++ b/mesalib/src/mesa/vbo/vbo_context.h
@@ -146,6 +146,7 @@ vbo_attrtype_to_integer_flag(GLenum format)
{
switch (format) {
case GL_FLOAT:
+ case GL_DOUBLE:
return GL_FALSE;
case GL_INT:
case GL_UNSIGNED_INT:
@@ -156,6 +157,22 @@ vbo_attrtype_to_integer_flag(GLenum format)
}
}
+static inline GLboolean
+vbo_attrtype_to_double_flag(GLenum format)
+{
+ switch (format) {
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ return GL_FALSE;
+ case GL_DOUBLE:
+ return GL_TRUE;
+ default:
+ assert(0);
+ return GL_FALSE;
+ }
+}
+
/**
* Return default component values for the given format.
* The return type is an array of fi_types, because that's how we declare
diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c
index 48680ec88..138cd6051 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_api.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_api.c
@@ -159,27 +159,36 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
* ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
*/
GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
- fi_type tmp[4];
+ fi_type tmp[8]; /* space for doubles */
+ int dmul = exec->vtx.attrtype[i] == GL_DOUBLE ? 2 : 1;
+
+ if (exec->vtx.attrtype[i] == GL_DOUBLE) {
+ memset(tmp, 0, sizeof(tmp));
+ memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attrsz[i] * sizeof(GLfloat));
+ } else {
+ COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
+ exec->vtx.attrsz[i],
+ exec->vtx.attrptr[i],
+ exec->vtx.attrtype[i]);
+ }
- COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
- exec->vtx.attrsz[i],
- exec->vtx.attrptr[i],
- exec->vtx.attrtype[i]);
-
if (exec->vtx.attrtype[i] != vbo->currval[i].Type ||
- memcmp(current, tmp, sizeof(tmp)) != 0) {
- memcpy(current, tmp, sizeof(tmp));
+ memcmp(current, tmp, 4 * sizeof(GLfloat) * dmul) != 0) {
+ memcpy(current, tmp, 4 * sizeof(GLfloat) * dmul);
/* Given that we explicitly state size here, there is no need
* for the COPY_CLEAN above, could just copy 16 bytes and be
* done. The only problem is when Mesa accesses ctx->Current
* directly.
*/
- vbo->currval[i].Size = exec->vtx.attrsz[i];
- vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
+ /* Size here is in components - not bytes */
+ vbo->currval[i].Size = exec->vtx.attrsz[i] / dmul;
+ vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat) * dmul;
vbo->currval[i].Type = exec->vtx.attrtype[i];
vbo->currval[i].Integer =
vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]);
+ vbo->currval[i].Doubles =
+ vbo_attrtype_to_double_flag(exec->vtx.attrtype[i]);
/* This triggers rather too much recalculation of Mesa state
* that doesn't get used (eg light positions).
@@ -214,13 +223,17 @@ vbo_exec_copy_from_current(struct vbo_exec_context *exec)
GLint i;
for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) {
- const fi_type *current = (fi_type *) vbo->currval[i].Ptr;
- switch (exec->vtx.attrsz[i]) {
- case 4: exec->vtx.attrptr[i][3] = current[3];
- case 3: exec->vtx.attrptr[i][2] = current[2];
- case 2: exec->vtx.attrptr[i][1] = current[1];
- case 1: exec->vtx.attrptr[i][0] = current[0];
- break;
+ if (exec->vtx.attrtype[i] == GL_DOUBLE) {
+ memcpy(exec->vtx.attrptr[i], vbo->currval[i].Ptr, exec->vtx.attrsz[i] * sizeof(GLfloat));
+ } else {
+ const fi_type *current = (fi_type *) vbo->currval[i].Ptr;
+ switch (exec->vtx.attrsz[i]) {
+ case 4: exec->vtx.attrptr[i][3] = current[3];
+ case 3: exec->vtx.attrptr[i][2] = current[2];
+ case 2: exec->vtx.attrptr[i][1] = current[1];
+ case 1: exec->vtx.attrptr[i][0] = current[0];
+ break;
+ }
}
}
}
@@ -364,11 +377,11 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
* glTexCoord4f() call. We promote the array from size=2 to size=4.
*/
static void
-vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize)
+vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize, GLenum newType)
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- if (newSize > exec->vtx.attrsz[attr]) {
+ if (newSize > exec->vtx.attrsz[attr] || newType != exec->vtx.attrtype[attr]) {
/* New size is larger. Need to flush existing vertices and get
* an enlarged vertex format.
*/
@@ -401,18 +414,19 @@ vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize)
* This macro is used to implement all the glVertex, glColor, glTexCoord,
* glVertexAttrib, etc functions.
*/
-#define ATTR_UNION( A, N, T, V0, V1, V2, V3 ) \
+#define ATTR_UNION( A, N, T, C, V0, V1, V2, V3 ) \
do { \
struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
- \
+ int sz = (sizeof(C) / sizeof(GLfloat)); \
if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \
ctx->Driver.BeginVertices( ctx ); \
- \
- if (unlikely(exec->vtx.active_sz[A] != N)) \
- vbo_exec_fixup_vertex(ctx, A, N); \
- \
+ \
+ if (unlikely(exec->vtx.active_sz[A] != N * sz) || \
+ unlikely(exec->vtx.attrtype[A] != T)) \
+ vbo_exec_fixup_vertex(ctx, A, N * sz, T); \
+ \
{ \
- fi_type *dest = exec->vtx.attrptr[A]; \
+ C *dest = (C *)exec->vtx.attrptr[A]; \
if (N>0) dest[0] = V0; \
if (N>1) dest[1] = V1; \
if (N>2) dest[2] = V2; \
@@ -438,7 +452,6 @@ do { \
} \
} while (0)
-
#define ERROR(err) _mesa_error( ctx, err, __func__ )
#define TAG(x) vbo_##x
@@ -575,7 +588,7 @@ static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
if (exec->eval.map1[i].map)
if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
- vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
+ vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz, GL_FLOAT );
}
}
@@ -602,12 +615,12 @@ static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
if (exec->eval.map2[i].map)
if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
- vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
+ vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz, GL_FLOAT );
}
if (ctx->Eval.AutoNormal)
if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
- vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
+ vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3, GL_FLOAT );
}
memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
@@ -968,6 +981,16 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
vfmt->VertexAttribP3uiv = vbo_VertexAttribP3uiv;
vfmt->VertexAttribP4ui = vbo_VertexAttribP4ui;
vfmt->VertexAttribP4uiv = vbo_VertexAttribP4uiv;
+
+ vfmt->VertexAttribL1d = vbo_VertexAttribL1d;
+ vfmt->VertexAttribL2d = vbo_VertexAttribL2d;
+ vfmt->VertexAttribL3d = vbo_VertexAttribL3d;
+ vfmt->VertexAttribL4d = vbo_VertexAttribL4d;
+
+ vfmt->VertexAttribL1dv = vbo_VertexAttribL1dv;
+ vfmt->VertexAttribL2dv = vbo_VertexAttribL2dv;
+ vfmt->VertexAttribL3dv = vbo_VertexAttribL3dv;
+ vfmt->VertexAttribL4dv = vbo_VertexAttribL4dv;
}
diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c
index 5927beeb3..29de3d38a 100644
--- a/mesalib/src/mesa/vbo/vbo_save_api.c
+++ b/mesalib/src/mesa/vbo/vbo_save_api.c
@@ -772,7 +772,7 @@ _save_reset_vertex(struct gl_context *ctx)
* 3f version won't otherwise set color[3] to 1.0 -- this is the job
* of the chooser function when switching between Color4f and Color3f.
*/
-#define ATTR_UNION(A, N, T, V0, V1, V2, V3) \
+#define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
do { \
struct vbo_save_context *save = &vbo_context(ctx)->save; \
\
@@ -780,7 +780,7 @@ do { \
save_fixup_vertex(ctx, A, N); \
\
{ \
- fi_type *dest = save->attrptr[A]; \
+ C *dest = (C *)save->attrptr[A]; \
if (N>0) dest[0] = V0; \
if (N>1) dest[1] = V1; \
if (N>2) dest[2] = V2; \
@@ -1372,6 +1372,16 @@ _save_vtxfmt_init(struct gl_context *ctx)
vfmt->VertexAttribP3uiv = _save_VertexAttribP3uiv;
vfmt->VertexAttribP4uiv = _save_VertexAttribP4uiv;
+ vfmt->VertexAttribL1d = _save_VertexAttribL1d;
+ vfmt->VertexAttribL2d = _save_VertexAttribL2d;
+ vfmt->VertexAttribL3d = _save_VertexAttribL3d;
+ vfmt->VertexAttribL4d = _save_VertexAttribL4d;
+
+ vfmt->VertexAttribL1dv = _save_VertexAttribL1dv;
+ vfmt->VertexAttribL2dv = _save_VertexAttribL2dv;
+ vfmt->VertexAttribL3dv = _save_VertexAttribL3dv;
+ vfmt->VertexAttribL4dv = _save_VertexAttribL4dv;
+
/* This will all require us to fallback to saving the list as opcodes:
*/
vfmt->CallList = _save_CallList;
diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c
index d1107dd84..7b1e20b18 100644
--- a/mesalib/src/mesa/vbo/vbo_split_copy.c
+++ b/mesalib/src/mesa/vbo/vbo_split_copy.c
@@ -533,6 +533,7 @@ replay_init( struct copy_context *copy )
dst->Enabled = GL_TRUE;
dst->Normalized = src->Normalized;
dst->Integer = src->Integer;
+ dst->Doubles = src->Doubles;
dst->BufferObj = ctx->Shared->NullBufferObj;
dst->_ElementSize = src->_ElementSize;