aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2015-03-22 14:10:47 +0100
committermarha <marha@users.sourceforge.net>2015-03-22 14:10:47 +0100
commit3bc24b271f45f9f33484b8cf53b44f33f7e8a237 (patch)
tree193651a94adb3804e800747e993d07b92688e4d4 /mesalib/src/mesa/main
parentc646056120fe14e4c4ccf81bac5d78d61225a8e8 (diff)
parent82c8df11062f72a7d467e26cedbbd8b322ff7a70 (diff)
downloadvcxsrv-3bc24b271f45f9f33484b8cf53b44f33f7e8a237.tar.gz
vcxsrv-3bc24b271f45f9f33484b8cf53b44f33f7e8a237.tar.bz2
vcxsrv-3bc24b271f45f9f33484b8cf53b44f33f7e8a237.zip
Merge remote-tracking branch 'origin/released'
Conflicts: mesalib/src/mapi/glapi/glapi.h mesalib/src/mapi/glapi/glapi_nop.c mesalib/src/mesa/main/bufferobj.c
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r--mesalib/src/mesa/main/api_exec.h4
-rwxr-xr-xmesalib/src/mesa/main/bufferobj.c1160
-rw-r--r--mesalib/src/mesa/main/bufferobj.h144
-rw-r--r--mesalib/src/mesa/main/compiler.h59
-rw-r--r--mesalib/src/mesa/main/context.c76
-rw-r--r--mesalib/src/mesa/main/context.h3
-rw-r--r--mesalib/src/mesa/main/copyimage.c151
-rw-r--r--mesalib/src/mesa/main/formats.c2
-rw-r--r--mesalib/src/mesa/main/imports.c43
-rwxr-xr-xmesalib/src/mesa/main/imports.h6
-rw-r--r--mesalib/src/mesa/main/mtypes.h119
-rw-r--r--mesalib/src/mesa/main/objectlabel.c2
-rw-r--r--mesalib/src/mesa/main/pbo.c119
-rw-r--r--mesalib/src/mesa/main/pbo.h14
-rw-r--r--mesalib/src/mesa/main/querymatrix.c279
-rw-r--r--mesalib/src/mesa/main/scissor.c4
-rw-r--r--mesalib/src/mesa/main/shaderapi.c27
-rw-r--r--mesalib/src/mesa/main/texgetimage.c61
-rw-r--r--mesalib/src/mesa/main/teximage.c681
-rw-r--r--mesalib/src/mesa/main/teximage.h16
-rw-r--r--mesalib/src/mesa/main/transformfeedback.c2
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp69
22 files changed, 1876 insertions, 1165 deletions
diff --git a/mesalib/src/mesa/main/api_exec.h b/mesalib/src/mesa/main/api_exec.h
index 1e4a9d61a..12249fec2 100644
--- a/mesalib/src/mesa/main/api_exec.h
+++ b/mesalib/src/mesa/main/api_exec.h
@@ -30,12 +30,8 @@
extern "C" {
#endif
-struct _glapi_table;
struct gl_context;
-extern struct _glapi_table *
-_mesa_alloc_dispatch_table(void);
-
extern void
_mesa_initialize_exec_table(struct gl_context *ctx);
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index 008d1aa5f..25110c33b 100755
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -232,67 +232,62 @@ bufferobj_range_mapped(const struct gl_buffer_object *obj,
* \c glClearBufferSubData.
*
* \param ctx GL context.
- * \param target Buffer object target on which to operate.
+ * \param bufObj The buffer object.
* \param offset Offset of the first byte of the subdata range.
* \param size Size, in bytes, of the subdata range.
* \param mappedRange If true, checks if an overlapping range is mapped.
* If false, checks if buffer is mapped.
- * \param errorNoBuffer Error code if no buffer is bound to target.
* \param caller Name of calling function for recording errors.
- * \return A pointer to the buffer object bound to \c target in the
- * specified context or \c NULL if any of the parameter or state
- * conditions are invalid.
+ * \return false if error, true otherwise
*
* \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData
*/
-static struct gl_buffer_object *
-buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target,
- GLintptrARB offset, GLsizeiptrARB size,
- bool mappedRange, GLenum errorNoBuffer,
- const char *caller)
+static bool
+buffer_object_subdata_range_good(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size,
+ bool mappedRange, const char *caller)
{
- struct gl_buffer_object *bufObj;
-
if (size < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller);
- return NULL;
+ return false;
}
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller);
- return NULL;
+ return false;
}
- bufObj = get_buffer(ctx, caller, target, errorNoBuffer);
- if (!bufObj)
- return NULL;
-
if (offset + size > bufObj->Size) {
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(offset %lu + size %lu > buffer size %lu)", caller,
(unsigned long) offset,
(unsigned long) size,
(unsigned long) bufObj->Size);
- return NULL;
+ return false;
}
if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT)
- return bufObj;
+ return true;
if (mappedRange) {
if (bufferobj_range_mapped(bufObj, offset, size)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
- return NULL;
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(range is mapped without persistent bit)",
+ caller);
+ return false;
}
}
else {
if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
- return NULL;
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(buffer is mapped without persistent bit)",
+ caller);
+ return false;
}
}
- return bufObj;
+ return true;
}
@@ -561,9 +556,9 @@ _mesa_total_buffer_object_memory(struct gl_context *ctx)
* \sa glBufferDataARB, dd_function_table::BufferData.
*/
GLboolean
-_mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size,
- const GLvoid * data, GLenum usage, GLenum storageFlags,
- struct gl_buffer_object * bufObj )
+buffer_data_fallback(struct gl_context *ctx, GLenum target, GLsizeiptr size,
+ const GLvoid *data, GLenum usage, GLenum storageFlags,
+ struct gl_buffer_object *bufObj)
{
void * new_data;
@@ -607,9 +602,9 @@ _mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size,
* \sa glBufferSubDataARB, dd_function_table::BufferSubData.
*/
void
-_mesa_buffer_subdata( struct gl_context *ctx, GLintptrARB offset,
- GLsizeiptrARB size, const GLvoid * data,
- struct gl_buffer_object * bufObj )
+buffer_sub_data_fallback(struct gl_context *ctx, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data,
+ struct gl_buffer_object *bufObj)
{
(void) ctx;
@@ -670,11 +665,11 @@ _mesa_buffer_get_subdata( struct gl_context *ctx, GLintptrARB offset,
* dd_function_table::ClearBufferSubData.
*/
void
-_mesa_buffer_clear_subdata(struct gl_context *ctx,
- GLintptr offset, GLsizeiptr size,
- const GLvoid *clearValue,
- GLsizeiptr clearValueSize,
- struct gl_buffer_object *bufObj)
+_mesa_ClearBufferSubData_sw(struct gl_context *ctx,
+ GLintptr offset, GLsizeiptr size,
+ const GLvoid *clearValue,
+ GLsizeiptr clearValueSize,
+ struct gl_buffer_object *bufObj)
{
GLsizeiptr i;
GLubyte *dest;
@@ -711,10 +706,10 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx,
* Called via glMapBufferRange().
*/
static void *
-_mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset,
- GLsizeiptr length, GLbitfield access,
- struct gl_buffer_object *bufObj,
- gl_map_buffer_index index)
+map_buffer_range_fallback(struct gl_context *ctx, GLintptr offset,
+ GLsizeiptr length, GLbitfield access,
+ struct gl_buffer_object *bufObj,
+ gl_map_buffer_index index)
{
(void) ctx;
assert(!_mesa_bufferobj_mapped(bufObj, index));
@@ -732,10 +727,10 @@ _mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset,
* Called via glFlushMappedBufferRange().
*/
static void
-_mesa_buffer_flush_mapped_range( struct gl_context *ctx,
- GLintptr offset, GLsizeiptr length,
- struct gl_buffer_object *obj,
- gl_map_buffer_index index)
+flush_mapped_buffer_range_fallback(struct gl_context *ctx,
+ GLintptr offset, GLsizeiptr length,
+ struct gl_buffer_object *obj,
+ gl_map_buffer_index index)
{
(void) ctx;
(void) offset;
@@ -746,15 +741,15 @@ _mesa_buffer_flush_mapped_range( struct gl_context *ctx,
/**
- * Default callback for \c dd_function_table::MapBuffer().
+ * Default callback for \c dd_function_table::UnmapBuffer().
*
* The input parameters will have been already tested for errors.
*
* \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
*/
GLboolean
-_mesa_buffer_unmap(struct gl_context *ctx, struct gl_buffer_object *bufObj,
- gl_map_buffer_index index)
+unmap_buffer_fallback(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ gl_map_buffer_index index)
{
(void) ctx;
/* XXX we might assert here that bufObj->Pointer is non-null */
@@ -771,11 +766,11 @@ _mesa_buffer_unmap(struct gl_context *ctx, struct gl_buffer_object *bufObj,
* Called via glCopyBufferSubData().
*/
static void
-_mesa_copy_buffer_subdata(struct gl_context *ctx,
- struct gl_buffer_object *src,
- struct gl_buffer_object *dst,
- GLintptr readOffset, GLintptr writeOffset,
- GLsizeiptr size)
+copy_buffer_sub_data_fallback(struct gl_context *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
{
GLubyte *srcPtr, *dstPtr;
@@ -1006,6 +1001,27 @@ _mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer)
_mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer);
}
+/**
+ * A convenience function for direct state access functions that throws
+ * GL_INVALID_OPERATION if buffer is not the name of an existing
+ * buffer object.
+ */
+struct gl_buffer_object *
+_mesa_lookup_bufferobj_err(struct gl_context *ctx, GLuint buffer,
+ const char *caller)
+{
+ struct gl_buffer_object *bufObj;
+
+ bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+ if (!bufObj || bufObj == &DummyBufferObject) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(non-existent buffer object %u)", caller, buffer);
+ return NULL;
+ }
+
+ return bufObj;
+}
+
void
_mesa_begin_bufferobj_lookups(struct gl_context *ctx)
@@ -1098,20 +1114,20 @@ _mesa_init_buffer_object_functions(struct dd_function_table *driver)
/* GL_ARB_vertex/pixel_buffer_object */
driver->NewBufferObject = _mesa_new_buffer_object;
driver->DeleteBuffer = _mesa_delete_buffer_object;
- driver->BufferData = _mesa_buffer_data;
- driver->BufferSubData = _mesa_buffer_subdata;
+ driver->BufferData = buffer_data_fallback;
+ driver->BufferSubData = buffer_sub_data_fallback;
driver->GetBufferSubData = _mesa_buffer_get_subdata;
- driver->UnmapBuffer = _mesa_buffer_unmap;
+ driver->UnmapBuffer = unmap_buffer_fallback;
/* GL_ARB_clear_buffer_object */
- driver->ClearBufferSubData = _mesa_buffer_clear_subdata;
+ driver->ClearBufferSubData = _mesa_ClearBufferSubData_sw;
/* GL_ARB_map_buffer_range */
- driver->MapBufferRange = _mesa_buffer_map_range;
- driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range;
+ driver->MapBufferRange = map_buffer_range_fallback;
+ driver->FlushMappedBufferRange = flush_mapped_buffer_range_fallback;
/* GL_ARB_copy_buffer */
- driver->CopyBufferSubData = _mesa_copy_buffer_subdata;
+ driver->CopyBufferSubData = copy_buffer_sub_data_fallback;
}
@@ -1273,27 +1289,29 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
/**
- * Generate a set of unique buffer object IDs and store them in \c buffer.
- *
- * \param n Number of IDs to generate.
- * \param buffer Array of \c n locations to store the IDs.
+ * This is the implementation for glGenBuffers and glCreateBuffers. It is not
+ * exposed to the rest of Mesa to encourage the use of nameless buffers in
+ * driver internals.
*/
-void GLAPIENTRY
-_mesa_GenBuffers(GLsizei n, GLuint *buffer)
+static void
+create_buffers(GLsizei n, GLuint *buffers, bool dsa)
{
GET_CURRENT_CONTEXT(ctx);
GLuint first;
GLint i;
+ struct gl_buffer_object *buf;
+
+ const char *func = dsa ? "glCreateBuffers" : "glGenBuffers";
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glGenBuffers(%d)\n", n);
+ _mesa_debug(ctx, "%s(%d)\n", func, n);
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n %d < 0)", func, n);
return;
}
- if (!buffer) {
+ if (!buffers) {
return;
}
@@ -1304,16 +1322,53 @@ _mesa_GenBuffers(GLsizei n, GLuint *buffer)
first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
- /* Insert the ID and pointer to dummy buffer object into hash table */
+ /* Insert the ID and pointer into the hash table. If non-DSA, insert a
+ * DummyBufferObject. Otherwise, create a new buffer object and insert
+ * it.
+ */
for (i = 0; i < n; i++) {
- _mesa_HashInsert(ctx->Shared->BufferObjects, first + i,
- &DummyBufferObject);
- buffer[i] = first + i;
+ buffers[i] = first + i;
+ if (dsa) {
+ assert(ctx->Driver.NewBufferObject);
+ buf = ctx->Driver.NewBufferObject(ctx, buffers[i]);
+ if (!buf) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
+ return;
+ }
+ }
+ else
+ buf = &DummyBufferObject;
+
+ _mesa_HashInsert(ctx->Shared->BufferObjects, buffers[i], buf);
}
mtx_unlock(&ctx->Shared->Mutex);
}
+/**
+ * Generate a set of unique buffer object IDs and store them in \c buffers.
+ *
+ * \param n Number of IDs to generate.
+ * \param buffers Array of \c n locations to store the IDs.
+ */
+void GLAPIENTRY
+_mesa_GenBuffers(GLsizei n, GLuint *buffers)
+{
+ create_buffers(n, buffers, false);
+}
+
+/**
+ * Create a set of buffer objects and store their unique IDs in \c buffers.
+ *
+ * \param n Number of IDs to generate.
+ * \param buffers Array of \c n locations to store the IDs.
+ */
+void GLAPIENTRY
+_mesa_CreateBuffers(GLsizei n, GLuint *buffers)
+{
+ create_buffers(n, buffers, true);
+}
+
/**
* Determine if ID is the name of a buffer object.
@@ -1337,15 +1392,13 @@ _mesa_IsBuffer(GLuint id)
}
-void GLAPIENTRY
-_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
- GLbitfield flags)
+void
+_mesa_buffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLenum target, GLsizeiptr size, const GLvoid *data,
+ GLbitfield flags, const char *func)
{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object *bufObj;
-
if (size <= 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(size <= 0)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(size <= 0)", func);
return;
}
@@ -1355,27 +1408,25 @@ _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
GL_MAP_COHERENT_BIT |
GL_DYNAMIC_STORAGE_BIT |
GL_CLIENT_STORAGE_BIT)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid flag bits set)", func);
return;
}
if (flags & GL_MAP_PERSISTENT_BIT &&
!(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=READ/WRITE)");
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(PERSISTENT and flags!=READ/WRITE)", func);
return;
}
if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=PERSISTENT)");
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(COHERENT and flags!=PERSISTENT)", func);
return;
}
- bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION);
- if (!bufObj)
- return;
-
if (bufObj->Immutable) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferStorage(immutable)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
return;
}
@@ -1395,31 +1446,65 @@ _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
* glBufferStorage is not described in the spec, Graham Sellers
* said that it should behave the same as glBufferData.
*/
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferStorage()");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
}
else {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferStorage()");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
}
}
}
+void GLAPIENTRY
+_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
+ GLbitfield flags)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+
+ bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION);
+ if (!bufObj)
+ return;
+
+ _mesa_buffer_storage(ctx, bufObj, target, size, data, flags,
+ "glBufferStorage");
+}
void GLAPIENTRY
-_mesa_BufferData(GLenum target, GLsizeiptrARB size,
- const GLvoid * data, GLenum usage)
+_mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data,
+ GLbitfield flags)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferStorage");
+ if (!bufObj)
+ return;
+
+ /*
+ * In direct state access, buffer objects have an unspecified target since
+ * they are not required to be bound.
+ */
+ _mesa_buffer_storage(ctx, bufObj, GL_NONE, size, data, flags,
+ "glNamedBufferStorage");
+}
+
+
+void
+_mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLenum target, GLsizeiptr size, const GLvoid *data,
+ GLenum usage, const char *func)
+{
bool valid_usage;
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBufferData(%s, %ld, %p, %s)\n",
+ _mesa_debug(ctx, "%s(%s, %ld, %p, %s)\n",
+ func,
_mesa_lookup_enum_by_nr(target),
(long int) size, data,
_mesa_lookup_enum_by_nr(usage));
if (size < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", func);
return;
}
@@ -1448,16 +1533,13 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size,
}
if (!valid_usage) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBufferData(usage)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid usage: %s)", func,
+ _mesa_lookup_enum_by_nr(usage));
return;
}
- bufObj = get_buffer(ctx, "glBufferDataARB", target, GL_INVALID_OPERATION);
- if (!bufObj)
- return;
-
if (bufObj->Immutable) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferData(immutable)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
return;
}
@@ -1490,33 +1572,73 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size,
* EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, and the store cannot be
* mapped to the GPU address space.
*/
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferData()");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
}
else {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferData()");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
}
}
}
+void GLAPIENTRY
+_mesa_BufferData(GLenum target, GLsizeiptr size,
+ const GLvoid *data, GLenum usage)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+
+ bufObj = get_buffer(ctx, "glBufferData", target, GL_INVALID_OPERATION);
+ if (!bufObj)
+ return;
+
+ _mesa_buffer_data(ctx, bufObj, target, size, data, usage,
+ "glBufferData");
+}
void GLAPIENTRY
-_mesa_BufferSubData(GLenum target, GLintptrARB offset,
- GLsizeiptrARB size, const GLvoid * data)
+_mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid *data,
+ GLenum usage)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
- bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
- false, GL_INVALID_OPERATION,
- "glBufferSubDataARB" );
- if (!bufObj) {
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferData");
+ if (!bufObj)
+ return;
+
+ /* In direct state access, buffer objects have an unspecified target since
+ * they are not required to be bound.
+ */
+ _mesa_buffer_data(ctx, bufObj, GL_NONE, size, data, usage,
+ "glNamedBufferData");
+}
+
+
+/**
+ * Implementation for glBufferSubData and glNamedBufferSubData.
+ *
+ * \param ctx GL context.
+ * \param bufObj The buffer object.
+ * \param offset Offset of the first byte of the subdata range.
+ * \param size Size, in bytes, of the subdata range.
+ * \param data The data store.
+ * \param func Name of calling function for recording errors.
+ *
+ */
+void
+_mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size, const GLvoid *data,
+ const char *func)
+{
+ if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size,
+ false, func)) {
/* error already recorded */
return;
}
if (bufObj->Immutable &&
!(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferSubData");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
return;
}
@@ -1526,105 +1648,107 @@ _mesa_BufferSubData(GLenum target, GLintptrARB offset,
bufObj->Written = GL_TRUE;
assert(ctx->Driver.BufferSubData);
- ctx->Driver.BufferSubData( ctx, offset, size, data, bufObj );
+ ctx->Driver.BufferSubData(ctx, offset, size, data, bufObj);
}
+void GLAPIENTRY
+_mesa_BufferSubData(GLenum target, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+
+ bufObj = get_buffer(ctx, "glBufferSubData", target, GL_INVALID_OPERATION);
+ if (!bufObj)
+ return;
+
+ _mesa_buffer_sub_data(ctx, bufObj, offset, size, data, "glBufferSubData");
+}
void GLAPIENTRY
-_mesa_GetBufferSubData(GLenum target, GLintptrARB offset,
- GLsizeiptrARB size, void * data)
+_mesa_NamedBufferSubData(GLuint buffer, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
- bufObj = buffer_object_subdata_range_good(ctx, target, offset, size,
- false, GL_INVALID_OPERATION,
- "glGetBufferSubDataARB");
- if (!bufObj) {
- /* error already recorded */
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferSubData");
+ if (!bufObj)
return;
- }
- assert(ctx->Driver.GetBufferSubData);
- ctx->Driver.GetBufferSubData( ctx, offset, size, data, bufObj );
+ _mesa_buffer_sub_data(ctx, bufObj, offset, size, data,
+ "glNamedBufferSubData");
}
void GLAPIENTRY
-_mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format,
- GLenum type, const GLvoid* data)
+_mesa_GetBufferSubData(GLenum target, GLintptr offset,
+ GLsizeiptr size, GLvoid *data)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object* bufObj;
- mesa_format mesaFormat;
- GLubyte clearValue[MAX_PIXEL_BYTES];
- GLsizeiptr clearValueSize;
+ struct gl_buffer_object *bufObj;
- bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE);
- if (!bufObj) {
+ bufObj = get_buffer(ctx, "glGetBufferSubData", target,
+ GL_INVALID_OPERATION);
+ if (!bufObj)
return;
- }
- if (_mesa_check_disallowed_mapping(bufObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glClearBufferData(buffer currently mapped)");
+ if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false,
+ "glGetBufferSubData")) {
return;
}
- mesaFormat = validate_clear_buffer_format(ctx, internalformat,
- format, type,
- "glClearBufferData");
- if (mesaFormat == MESA_FORMAT_NONE) {
- return;
- }
+ assert(ctx->Driver.GetBufferSubData);
+ ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj);
+}
- clearValueSize = _mesa_get_format_bytes(mesaFormat);
- if (bufObj->Size % clearValueSize != 0) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glClearBufferData(size is not a multiple of "
- "internalformat size)");
- return;
- }
+void GLAPIENTRY
+_mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset,
+ GLsizeiptr size, GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
- if (data == NULL) {
- /* clear to zeros, per the spec */
- ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size,
- NULL, clearValueSize, bufObj);
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
+ "glGetNamedBufferSubData");
+ if (!bufObj)
return;
- }
- if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue,
- format, type, data, "glClearBufferData")) {
+ if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false,
+ "glGetNamedBufferSubData")) {
return;
}
- ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size,
- clearValue, clearValueSize, bufObj);
+ assert(ctx->Driver.GetBufferSubData);
+ ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj);
}
-void GLAPIENTRY
-_mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
- GLintptr offset, GLsizeiptr size,
- GLenum format, GLenum type,
- const GLvoid* data)
+/**
+ * \param subdata true if caller is *SubData, false if *Data
+ */
+void
+_mesa_clear_buffer_sub_data(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLenum internalformat,
+ GLintptr offset, GLsizeiptr size,
+ GLenum format, GLenum type,
+ const GLvoid *data,
+ const char *func, bool subdata)
{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object* bufObj;
mesa_format mesaFormat;
GLubyte clearValue[MAX_PIXEL_BYTES];
GLsizeiptr clearValueSize;
- bufObj = buffer_object_subdata_range_good(ctx, target, offset, size,
- true, GL_INVALID_VALUE,
- "glClearBufferSubData");
- if (!bufObj) {
+ /* This checks for disallowed mappings. */
+ if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size,
+ subdata, func)) {
return;
}
mesaFormat = validate_clear_buffer_format(ctx, internalformat,
- format, type,
- "glClearBufferSubData");
+ format, type, func);
+
if (mesaFormat == MESA_FORMAT_NONE) {
return;
}
@@ -1632,8 +1756,8 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
clearValueSize = _mesa_get_format_bytes(mesaFormat);
if (offset % clearValueSize != 0 || size % clearValueSize != 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glClearBufferSubData(offset or size is not a multiple of "
- "internalformat size)");
+ "%s(offset or size is not a multiple of "
+ "internalformat size)", func);
return;
}
@@ -1647,8 +1771,7 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
}
if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue,
- format, type, data,
- "glClearBufferSubData")) {
+ format, type, data, func)) {
return;
}
@@ -1658,131 +1781,87 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
}
}
-
-void * GLAPIENTRY
-_mesa_MapBuffer(GLenum target, GLenum access)
+void GLAPIENTRY
+_mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format,
+ GLenum type, const GLvoid *data)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object * bufObj;
- GLbitfield accessFlags;
- void *map;
- bool valid_access;
+ struct gl_buffer_object *bufObj;
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
+ bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE);
+ if (!bufObj)
+ return;
- switch (access) {
- case GL_READ_ONLY_ARB:
- accessFlags = GL_MAP_READ_BIT;
- valid_access = _mesa_is_desktop_gl(ctx);
- break;
- case GL_WRITE_ONLY_ARB:
- accessFlags = GL_MAP_WRITE_BIT;
- valid_access = true;
- break;
- case GL_READ_WRITE_ARB:
- accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
- valid_access = _mesa_is_desktop_gl(ctx);
- break;
- default:
- valid_access = false;
- break;
- }
+ _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size,
+ format, type, data,
+ "glClearBufferData", false);
+}
- if (!valid_access) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)");
- return NULL;
- }
+void GLAPIENTRY
+_mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat,
+ GLenum format, GLenum type, const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
- bufObj = get_buffer(ctx, "glMapBufferARB", target, GL_INVALID_OPERATION);
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferData");
if (!bufObj)
- return NULL;
+ return;
- if (accessFlags & GL_MAP_READ_BIT &&
- !(bufObj->StorageFlags & GL_MAP_READ_BIT)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBuffer(invalid read flag)");
- return NULL;
- }
+ _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size,
+ format, type, data,
+ "glClearNamedBufferData", false);
+}
- if (accessFlags & GL_MAP_WRITE_BIT &&
- !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBuffer(invalid write flag)");
- return NULL;
- }
- if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)");
- return NULL;
- }
-
- if (!bufObj->Size) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "glMapBuffer(buffer size = 0)");
- return NULL;
- }
+void GLAPIENTRY
+_mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
+ GLintptr offset, GLsizeiptr size,
+ GLenum format, GLenum type,
+ const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
- assert(ctx->Driver.MapBufferRange);
- map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj,
- MAP_USER);
- if (!map) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
- return NULL;
- }
- else {
- /* The driver callback should have set these fields.
- * This is important because other modules (like VBO) might call
- * the driver function directly.
- */
- assert(bufObj->Mappings[MAP_USER].Pointer == map);
- assert(bufObj->Mappings[MAP_USER].Length == bufObj->Size);
- assert(bufObj->Mappings[MAP_USER].Offset == 0);
- bufObj->Mappings[MAP_USER].AccessFlags = accessFlags;
- }
+ bufObj = get_buffer(ctx, "glClearBufferSubData", target, GL_INVALID_VALUE);
+ if (!bufObj)
+ return;
- if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
- bufObj->Written = GL_TRUE;
+ _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size,
+ format, type, data,
+ "glClearBufferSubData", true);
+}
-#ifdef VBO_DEBUG
- printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n",
- bufObj->Name, bufObj->Size, access);
- if (access == GL_WRITE_ONLY_ARB) {
- GLuint i;
- GLubyte *b = (GLubyte *) bufObj->Pointer;
- for (i = 0; i < bufObj->Size; i++)
- b[i] = i & 0xff;
- }
-#endif
+void GLAPIENTRY
+_mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat,
+ GLintptr offset, GLsizeiptr size,
+ GLenum format, GLenum type,
+ const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
-#ifdef BOUNDS_CHECK
- {
- GLubyte *buf = (GLubyte *) bufObj->Pointer;
- GLuint i;
- /* buffer is 100 bytes larger than requested, fill with magic value */
- for (i = 0; i < 100; i++) {
- buf[bufObj->Size - i - 1] = 123;
- }
- }
-#endif
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
+ "glClearNamedBufferSubData");
+ if (!bufObj)
+ return;
- return bufObj->Mappings[MAP_USER].Pointer;
+ _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size,
+ format, type, data,
+ "glClearNamedBufferSubData", true);
}
-GLboolean GLAPIENTRY
-_mesa_UnmapBuffer(GLenum target)
+GLboolean
+_mesa_unmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ const char *func)
{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object *bufObj;
GLboolean status = GL_TRUE;
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
- bufObj = get_buffer(ctx, "glUnmapBufferARB", target, GL_INVALID_OPERATION);
- if (!bufObj)
- return GL_FALSE;
-
if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(buffer is not mapped)", func);
return GL_FALSE;
}
@@ -1831,129 +1910,164 @@ _mesa_UnmapBuffer(GLenum target)
return status;
}
+GLboolean GLAPIENTRY
+_mesa_UnmapBuffer(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
-void GLAPIENTRY
-_mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
+ bufObj = get_buffer(ctx, "glUnmapBuffer", target, GL_INVALID_OPERATION);
+ if (!bufObj)
+ return GL_FALSE;
+
+ return _mesa_unmap_buffer(ctx, bufObj, "glUnmapBuffer");
+}
+
+GLboolean GLAPIENTRY
+_mesa_UnmapNamedBuffer(GLuint buffer)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
- bufObj = get_buffer(ctx, "glGetBufferParameterivARB", target,
- GL_INVALID_OPERATION);
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glUnmapNamedBuffer");
if (!bufObj)
- return;
+ return GL_FALSE;
+ return _mesa_unmap_buffer(ctx, bufObj, "glUnmapNamedBuffer");
+}
+
+
+static bool
+get_buffer_parameter(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj, GLenum pname,
+ GLint64 *params, const char *func)
+{
switch (pname) {
case GL_BUFFER_SIZE_ARB:
- *params = (GLint) bufObj->Size;
- return;
+ *params = bufObj->Size;
+ break;
case GL_BUFFER_USAGE_ARB:
*params = bufObj->Usage;
- return;
+ break;
case GL_BUFFER_ACCESS_ARB:
*params = simplified_access_mode(ctx,
bufObj->Mappings[MAP_USER].AccessFlags);
- return;
+ break;
case GL_BUFFER_MAPPED_ARB:
*params = _mesa_bufferobj_mapped(bufObj, MAP_USER);
- return;
+ break;
case GL_BUFFER_ACCESS_FLAGS:
if (!ctx->Extensions.ARB_map_buffer_range)
goto invalid_pname;
*params = bufObj->Mappings[MAP_USER].AccessFlags;
- return;
+ break;
case GL_BUFFER_MAP_OFFSET:
if (!ctx->Extensions.ARB_map_buffer_range)
goto invalid_pname;
- *params = (GLint) bufObj->Mappings[MAP_USER].Offset;
- return;
+ *params = bufObj->Mappings[MAP_USER].Offset;
+ break;
case GL_BUFFER_MAP_LENGTH:
if (!ctx->Extensions.ARB_map_buffer_range)
goto invalid_pname;
- *params = (GLint) bufObj->Mappings[MAP_USER].Length;
- return;
+ *params = bufObj->Mappings[MAP_USER].Length;
+ break;
case GL_BUFFER_IMMUTABLE_STORAGE:
if (!ctx->Extensions.ARB_buffer_storage)
goto invalid_pname;
*params = bufObj->Immutable;
- return;
+ break;
case GL_BUFFER_STORAGE_FLAGS:
if (!ctx->Extensions.ARB_buffer_storage)
goto invalid_pname;
*params = bufObj->StorageFlags;
- return;
+ break;
default:
- ; /* fall-through */
+ goto invalid_pname;
}
+ return true;
+
invalid_pname:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname=%s)",
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname: %s)", func,
_mesa_lookup_enum_by_nr(pname));
+ return false;
}
+void GLAPIENTRY
+_mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ GLint64 parameter;
+
+ bufObj = get_buffer(ctx, "glGetBufferParameteriv", target,
+ GL_INVALID_OPERATION);
+ if (!bufObj)
+ return;
+
+ if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
+ "glGetBufferParameteriv"))
+ return; /* Error already recorded. */
+
+ *params = (GLint) parameter;
+}
-/**
- * New in GL 3.2
- * This is pretty much a duplicate of GetBufferParameteriv() but the
- * GL_BUFFER_SIZE_ARB attribute will be 64-bits on a 64-bit system.
- */
void GLAPIENTRY
_mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ GLint64 parameter;
bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target,
GL_INVALID_OPERATION);
if (!bufObj)
return;
- switch (pname) {
- case GL_BUFFER_SIZE_ARB:
- *params = bufObj->Size;
- return;
- case GL_BUFFER_USAGE_ARB:
- *params = bufObj->Usage;
- return;
- case GL_BUFFER_ACCESS_ARB:
- *params = simplified_access_mode(ctx,
- bufObj->Mappings[MAP_USER].AccessFlags);
- return;
- case GL_BUFFER_ACCESS_FLAGS:
- if (!ctx->Extensions.ARB_map_buffer_range)
- goto invalid_pname;
- *params = bufObj->Mappings[MAP_USER].AccessFlags;
- return;
- case GL_BUFFER_MAPPED_ARB:
- *params = _mesa_bufferobj_mapped(bufObj, MAP_USER);
- return;
- case GL_BUFFER_MAP_OFFSET:
- if (!ctx->Extensions.ARB_map_buffer_range)
- goto invalid_pname;
- *params = bufObj->Mappings[MAP_USER].Offset;
- return;
- case GL_BUFFER_MAP_LENGTH:
- if (!ctx->Extensions.ARB_map_buffer_range)
- goto invalid_pname;
- *params = bufObj->Mappings[MAP_USER].Length;
- return;
- case GL_BUFFER_IMMUTABLE_STORAGE:
- if (!ctx->Extensions.ARB_buffer_storage)
- goto invalid_pname;
- *params = bufObj->Immutable;
+ if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
+ "glGetBufferParameteri64v"))
+ return; /* Error already recorded. */
+
+ *params = parameter;
+}
+
+void GLAPIENTRY
+_mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ GLint64 parameter;
+
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
+ "glGetNamedBufferParameteriv");
+ if (!bufObj)
return;
- case GL_BUFFER_STORAGE_FLAGS:
- if (!ctx->Extensions.ARB_buffer_storage)
- goto invalid_pname;
- *params = bufObj->StorageFlags;
+
+ if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
+ "glGetNamedBufferParameteriv"))
+ return; /* Error already recorded. */
+
+ *params = (GLint) parameter;
+}
+
+void GLAPIENTRY
+_mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname,
+ GLint64 *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ GLint64 parameter;
+
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
+ "glGetNamedBufferParameteri64v");
+ if (!bufObj)
return;
- default:
- ; /* fall-through */
- }
-invalid_pname:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname=%s)",
- _mesa_lookup_enum_by_nr(pname));
+ if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
+ "glGetNamedBufferParameteri64v"))
+ return; /* Error already recorded. */
+
+ *params = parameter;
}
@@ -1961,14 +2075,15 @@ void GLAPIENTRY
_mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object * bufObj;
+ struct gl_buffer_object *bufObj;
- if (pname != GL_BUFFER_MAP_POINTER_ARB) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
+ if (pname != GL_BUFFER_MAP_POINTER) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointerv(pname != "
+ "GL_BUFFER_MAP_POINTER)");
return;
}
- bufObj = get_buffer(ctx, "glGetBufferPointervARB", target,
+ bufObj = get_buffer(ctx, "glGetBufferPointerv", target,
GL_INVALID_OPERATION);
if (!bufObj)
return;
@@ -1976,66 +2091,75 @@ _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params)
*params = bufObj->Mappings[MAP_USER].Pointer;
}
-
void GLAPIENTRY
-_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
- GLintptr readOffset, GLintptr writeOffset,
- GLsizeiptr size)
+_mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object *src, *dst;
+ struct gl_buffer_object *bufObj;
- src = get_buffer(ctx, "glCopyBufferSubData", readTarget,
- GL_INVALID_OPERATION);
- if (!src)
+ if (pname != GL_BUFFER_MAP_POINTER) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointerv(pname != "
+ "GL_BUFFER_MAP_POINTER)");
return;
+ }
- dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget,
- GL_INVALID_OPERATION);
- if (!dst)
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
+ "glGetNamedBufferPointerv");
+ if (!bufObj)
return;
+ *params = bufObj->Mappings[MAP_USER].Pointer;
+}
+
+
+void
+_mesa_copy_buffer_sub_data(struct gl_context *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size, const char *func)
+{
if (_mesa_check_disallowed_mapping(src)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyBufferSubData(readBuffer is mapped)");
+ "%s(readBuffer is mapped)", func);
return;
}
if (_mesa_check_disallowed_mapping(dst)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyBufferSubData(writeBuffer is mapped)");
+ "%s(writeBuffer is mapped)", func);
return;
}
if (readOffset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyBufferSubData(readOffset = %d)", (int) readOffset);
+ "%s(readOffset %d < 0)", func, (int) readOffset);
return;
}
if (writeOffset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyBufferSubData(writeOffset = %d)", (int) writeOffset);
+ "%s(writeOffset %d < 0)", func, (int) writeOffset);
return;
}
if (size < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyBufferSubData(writeOffset = %d)", (int) size);
+ "%s(size %d < 0)", func, (int) size);
return;
}
if (readOffset + size > src->Size) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyBufferSubData(readOffset + size = %d)",
- (int) (readOffset + size));
+ "%s(readOffset %d + size %d > src_buffer_size %d)", func,
+ (int) readOffset, (int) size, (int) src->Size);
return;
}
if (writeOffset + size > dst->Size) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyBufferSubData(writeOffset + size = %d)",
- (int) (writeOffset + size));
+ "%s(writeOffset %d + size %d > dst_buffer_size %d)", func,
+ (int) writeOffset, (int) size, (int) dst->Size);
return;
}
@@ -2049,7 +2173,7 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
else {
/* overlapping src/dst is illegal */
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyBufferSubData(overlapping src/dst)");
+ "%s(overlapping src/dst)", func);
return;
}
}
@@ -2057,36 +2181,71 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
}
+void GLAPIENTRY
+_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *src, *dst;
+
+ src = get_buffer(ctx, "glCopyBufferSubData", readTarget,
+ GL_INVALID_OPERATION);
+ if (!src)
+ return;
-/**
- * See GL_ARB_map_buffer_range spec
- */
-void * GLAPIENTRY
-_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
- GLbitfield access)
+ dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget,
+ GL_INVALID_OPERATION);
+ if (!dst)
+ return;
+
+ _mesa_copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
+ "glCopyBufferSubData");
+}
+
+void GLAPIENTRY
+_mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object *bufObj;
+ struct gl_buffer_object *src, *dst;
+
+ src = _mesa_lookup_bufferobj_err(ctx, readBuffer,
+ "glCopyNamedBufferSubData");
+ if (!src)
+ return;
+
+ dst = _mesa_lookup_bufferobj_err(ctx, writeBuffer,
+ "glCopyNamedBufferSubData");
+ if (!dst)
+ return;
+
+ _mesa_copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
+ "glCopyNamedBufferSubData");
+}
+
+
+void *
+_mesa_map_buffer_range(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr length,
+ GLbitfield access, const char *func)
+{
void *map;
GLbitfield allowed_access;
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
- if (!ctx->Extensions.ARB_map_buffer_range) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(extension not supported)");
- return NULL;
- }
-
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glMapBufferRange(offset = %ld)", (long)offset);
+ "%s(offset %ld < 0)", func, (long) offset);
return NULL;
}
if (length < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glMapBufferRange(length = %ld)", (long)length);
+ "%s(length %ld < 0)", func, (long) length);
return NULL;
}
@@ -2096,10 +2255,13 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
* conditions:
*
* * <length> is zero."
+ *
+ * Additionally, page 94 of the PDF of the OpenGL 4.5 core spec
+ * (30.10.2014) also says this, so it's no longer allowed for desktop GL,
+ * either.
*/
- if (_mesa_is_gles(ctx) && length == 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(length = 0)");
+ if (length == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(length = 0)", func);
return NULL;
}
@@ -2116,14 +2278,15 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
}
if (access & ~allowed_access) {
- /* generate an error if any other than allowed bit is set */
- _mesa_error(ctx, GL_INVALID_VALUE, "glMapBufferRange(access)");
+ /* generate an error if any bits other than those allowed are set */
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(access has undefined bits set)", func);
return NULL;
}
if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(access indicates neither read or write)");
+ "%s(access indicates neither read or write)", func);
return NULL;
}
@@ -2132,82 +2295,69 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
GL_MAP_INVALIDATE_BUFFER_BIT |
GL_MAP_UNSYNCHRONIZED_BIT))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(invalid access flags)");
+ "%s(read access with disallowed bits)", func);
return NULL;
}
if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
((access & GL_MAP_WRITE_BIT) == 0)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(invalid access flags)");
+ "%s(access has flush explicit without write)", func);
return NULL;
}
- bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION);
- if (!bufObj)
- return NULL;
-
if (access & GL_MAP_READ_BIT &&
!(bufObj->StorageFlags & GL_MAP_READ_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(invalid read flag)");
+ "%s(buffer does not allow read access)", func);
return NULL;
}
if (access & GL_MAP_WRITE_BIT &&
!(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(invalid write flag)");
+ "%s(buffer does not allow write access)", func);
return NULL;
}
if (access & GL_MAP_COHERENT_BIT &&
!(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(invalid coherent flag)");
+ "%s(buffer does not allow coherent access)", func);
return NULL;
}
if (access & GL_MAP_PERSISTENT_BIT &&
!(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(invalid persistent flag)");
+ "%s(buffer does not allow persistent access)", func);
return NULL;
}
if (offset + length > bufObj->Size) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glMapBufferRange(offset + length > size)");
+ "%s(offset %ld + length %ld > buffer_size %ld)", func,
+ offset, length, bufObj->Size);
return NULL;
}
if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glMapBufferRange(buffer already mapped)");
+ "%s(buffer already mapped)", func);
return NULL;
}
if (!bufObj->Size) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "glMapBufferRange(buffer size = 0)");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func);
return NULL;
}
- /* Mapping zero bytes should return a non-null pointer. */
- if (!length) {
- static long dummy = 0;
- bufObj->Mappings[MAP_USER].Pointer = &dummy;
- bufObj->Mappings[MAP_USER].Length = length;
- bufObj->Mappings[MAP_USER].Offset = offset;
- bufObj->Mappings[MAP_USER].AccessFlags = access;
- return bufObj->Mappings[MAP_USER].Pointer;
- }
assert(ctx->Driver.MapBufferRange);
map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj,
MAP_USER);
if (!map) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(map failed)", func);
}
else {
/* The driver callback should have set all these fields.
@@ -2220,61 +2370,189 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
assert(bufObj->Mappings[MAP_USER].AccessFlags == access);
}
+ if (access & GL_MAP_WRITE_BIT)
+ bufObj->Written = GL_TRUE;
+
+#ifdef VBO_DEBUG
+ if (strstr(func, "Range") == NULL) { /* If not MapRange */
+ printf("glMapBuffer(%u, sz %ld, access 0x%x)\n",
+ bufObj->Name, bufObj->Size, access);
+ /* Access must be write only */
+ if ((access & GL_MAP_WRITE_BIT) && (!(access & ~GL_MAP_WRITE_BIT))) {
+ GLuint i;
+ GLubyte *b = (GLubyte *) bufObj->Pointer;
+ for (i = 0; i < bufObj->Size; i++)
+ b[i] = i & 0xff;
+ }
+ }
+#endif
+
+#ifdef BOUNDS_CHECK
+ if (strstr(func, "Range") == NULL) { /* If not MapRange */
+ GLubyte *buf = (GLubyte *) bufObj->Pointer;
+ GLuint i;
+ /* buffer is 100 bytes larger than requested, fill with magic value */
+ for (i = 0; i < 100; i++) {
+ buf[bufObj->Size - i - 1] = 123;
+ }
+ }
+#endif
+
return map;
}
+void * GLAPIENTRY
+_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
+ GLbitfield access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+
+ if (!ctx->Extensions.ARB_map_buffer_range) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(ARB_map_buffer_range not supported)");
+ return NULL;
+ }
+
+ bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION);
+ if (!bufObj)
+ return NULL;
+
+ return _mesa_map_buffer_range(ctx, bufObj, offset, length, access,
+ "glMapBufferRange");
+}
+
+void * GLAPIENTRY
+_mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
+ GLbitfield access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+
+ if (!ctx->Extensions.ARB_map_buffer_range) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapNamedBufferRange("
+ "ARB_map_buffer_range not supported)");
+ return NULL;
+ }
+
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBufferRange");
+ if (!bufObj)
+ return NULL;
+
+ return _mesa_map_buffer_range(ctx, bufObj, offset, length, access,
+ "glMapNamedBufferRange");
+}
/**
- * See GL_ARB_map_buffer_range spec
+ * Converts GLenum access from MapBuffer and MapNamedBuffer into
+ * flags for input to _mesa_map_buffer_range.
+ *
+ * \return true if the type of requested access is permissible.
*/
-void GLAPIENTRY
-_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+static bool
+get_map_buffer_access_flags(struct gl_context *ctx, GLenum access,
+ GLbitfield *flags)
+{
+ switch (access) {
+ case GL_READ_ONLY_ARB:
+ *flags = GL_MAP_READ_BIT;
+ return _mesa_is_desktop_gl(ctx);
+ case GL_WRITE_ONLY_ARB:
+ *flags = GL_MAP_WRITE_BIT;
+ return true;
+ case GL_READ_WRITE_ARB:
+ *flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
+ return _mesa_is_desktop_gl(ctx);
+ default:
+ return false;
+ }
+}
+
+void * GLAPIENTRY
+_mesa_MapBuffer(GLenum target, GLenum access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ GLbitfield accessFlags;
+
+ if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glMapBuffer(invalid access)");
+ return NULL;
+ }
+
+ bufObj = get_buffer(ctx, "glMapBuffer", target, GL_INVALID_OPERATION);
+ if (!bufObj)
+ return NULL;
+
+ return _mesa_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
+ "glMapBuffer");
+}
+
+void * GLAPIENTRY
+_mesa_MapNamedBuffer(GLuint buffer, GLenum access)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ GLbitfield accessFlags;
+ if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)");
+ return NULL;
+ }
+
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBuffer");
+ if (!bufObj)
+ return NULL;
+
+ return _mesa_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
+ "glMapNamedBuffer");
+}
+
+
+void
+_mesa_flush_mapped_buffer_range(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr length,
+ const char *func)
+{
if (!ctx->Extensions.ARB_map_buffer_range) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFlushMappedBufferRange(extension not supported)");
+ "%s(ARB_map_buffer_range not supported)", func);
return;
}
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glFlushMappedBufferRange(offset = %ld)", (long)offset);
+ "%s(offset %ld < 0)", func, (long) offset);
return;
}
if (length < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glFlushMappedBufferRange(length = %ld)", (long)length);
+ "%s(length %ld < 0)", func, (long) length);
return;
}
- bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target,
- GL_INVALID_OPERATION);
- if (!bufObj)
- return;
-
if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
/* buffer is not mapped */
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFlushMappedBufferRange(buffer is not mapped)");
+ "%s(buffer is not mapped)", func);
return;
}
if ((bufObj->Mappings[MAP_USER].AccessFlags &
GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFlushMappedBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)");
+ "%s(GL_MAP_FLUSH_EXPLICIT_BIT not set)", func);
return;
}
if (offset + length > bufObj->Mappings[MAP_USER].Length) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glFlushMappedBufferRange(offset %ld + length %ld > mapped length %ld)",
- (long)offset, (long)length,
- (long)bufObj->Mappings[MAP_USER].Length);
+ "%s(offset %ld + length %ld > mapped length %ld)", func,
+ (long) offset, (long) length,
+ (long) bufObj->Mappings[MAP_USER].Length);
return;
}
@@ -2285,6 +2563,38 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
MAP_USER);
}
+void GLAPIENTRY
+_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset,
+ GLsizeiptr length)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+
+ bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target,
+ GL_INVALID_OPERATION);
+ if (!bufObj)
+ return;
+
+ _mesa_flush_mapped_buffer_range(ctx, bufObj, offset, length,
+ "glFlushMappedBufferRange");
+}
+
+void GLAPIENTRY
+_mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset,
+ GLsizeiptr length)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
+ "glFlushMappedNamedBufferRange");
+ if (!bufObj)
+ return;
+
+ _mesa_flush_mapped_buffer_range(ctx, bufObj, offset, length,
+ "glFlushMappedNamedBufferRange");
+}
+
static GLenum
buffer_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option)
diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h
index fe294fc0b..b5d73aec0 100644
--- a/mesalib/src/mesa/main/bufferobj.h
+++ b/mesalib/src/mesa/main/bufferobj.h
@@ -89,6 +89,10 @@ _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer);
extern struct gl_buffer_object *
_mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer);
+extern struct gl_buffer_object *
+_mesa_lookup_bufferobj_err(struct gl_context *ctx, GLuint buffer,
+ const char *caller);
+
extern void
_mesa_begin_bufferobj_lookups(struct gl_context *ctx);
@@ -126,15 +130,62 @@ extern void
_mesa_init_buffer_object_functions(struct dd_function_table *driver);
extern void
+_mesa_buffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLenum target, GLsizeiptr size, const GLvoid *data,
+ GLbitfield flags, const char *func);
+
+extern void
+_mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLenum target, GLsizeiptr size, const GLvoid *data,
+ GLenum usage, const char *func);
+
+extern void
+_mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size, const GLvoid *data,
+ const char *func);
+
+extern void
_mesa_buffer_unmap_all_mappings(struct gl_context *ctx,
struct gl_buffer_object *bufObj);
extern void
-_mesa_buffer_clear_subdata(struct gl_context *ctx,
- GLintptr offset, GLsizeiptr size,
- const GLvoid *clearValue,
- GLsizeiptr clearValueSize,
- struct gl_buffer_object *bufObj);
+_mesa_copy_buffer_sub_data(struct gl_context *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size, const char *func);
+
+extern void *
+_mesa_map_buffer_range(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr length,
+ GLbitfield access, const char *func);
+
+extern void
+_mesa_flush_mapped_buffer_range(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr length,
+ const char *func);
+
+extern void
+_mesa_ClearBufferSubData_sw(struct gl_context *ctx,
+ GLintptr offset, GLsizeiptr size,
+ const GLvoid *clearValue,
+ GLsizeiptr clearValueSize,
+ struct gl_buffer_object *bufObj);
+
+extern void
+_mesa_clear_buffer_sub_data(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLenum internalformat,
+ GLintptr offset, GLsizeiptr size,
+ GLenum format, GLenum type,
+ const GLvoid *data,
+ const char *func, bool subdata);
+
+extern GLboolean
+_mesa_unmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ const char *func);
/*
* API functions
@@ -146,7 +197,10 @@ void GLAPIENTRY
_mesa_DeleteBuffers(GLsizei n, const GLuint * buffer);
void GLAPIENTRY
-_mesa_GenBuffers(GLsizei n, GLuint * buffer);
+_mesa_GenBuffers(GLsizei n, GLuint *buffers);
+
+void GLAPIENTRY
+_mesa_CreateBuffers(GLsizei n, GLuint *buffers);
GLboolean GLAPIENTRY
_mesa_IsBuffer(GLuint buffer);
@@ -156,34 +210,61 @@ _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
GLbitfield flags);
void GLAPIENTRY
-_mesa_BufferData(GLenum target, GLsizeiptrARB size,
- const GLvoid * data, GLenum usage);
+_mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data,
+ GLbitfield flags);
+
+void GLAPIENTRY
+_mesa_BufferData(GLenum target, GLsizeiptr size,
+ const GLvoid *data, GLenum usage);
+
+void GLAPIENTRY
+_mesa_NamedBufferData(GLuint buffer, GLsizeiptr size,
+ const GLvoid *data, GLenum usage);
+
+void GLAPIENTRY
+_mesa_BufferSubData(GLenum target, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data);
void GLAPIENTRY
-_mesa_BufferSubData(GLenum target, GLintptrARB offset,
- GLsizeiptrARB size, const GLvoid * data);
+_mesa_NamedBufferSubData(GLuint buffer, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data);
void GLAPIENTRY
-_mesa_GetBufferSubData(GLenum target, GLintptrARB offset,
- GLsizeiptrARB size, void * data);
+_mesa_GetBufferSubData(GLenum target, GLintptr offset,
+ GLsizeiptr size, GLvoid *data);
+
+void GLAPIENTRY
+_mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset,
+ GLsizeiptr size, GLvoid *data);
void GLAPIENTRY
_mesa_ClearBufferData(GLenum target, GLenum internalformat,
GLenum format, GLenum type,
- const GLvoid * data);
+ const GLvoid *data);
+
+void GLAPIENTRY
+_mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat,
+ GLenum format, GLenum type,
+ const GLvoid *data);
void GLAPIENTRY
_mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
GLintptr offset, GLsizeiptr size,
GLenum format, GLenum type,
- const GLvoid * data);
+ const GLvoid *data);
-void * GLAPIENTRY
-_mesa_MapBuffer(GLenum target, GLenum access);
+void GLAPIENTRY
+_mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat,
+ GLintptr offset, GLsizeiptr size,
+ GLenum format, GLenum type,
+ const GLvoid *data);
GLboolean GLAPIENTRY
_mesa_UnmapBuffer(GLenum target);
+GLboolean GLAPIENTRY
+_mesa_UnmapNamedBuffer(GLuint buffer);
+
void GLAPIENTRY
_mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params);
@@ -191,21 +272,52 @@ void GLAPIENTRY
_mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params);
void GLAPIENTRY
+_mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params);
+
+void GLAPIENTRY
+_mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname,
+ GLint64 *params);
+
+void GLAPIENTRY
_mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params);
void GLAPIENTRY
+_mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params);
+
+
+void GLAPIENTRY
_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
GLintptr readOffset, GLintptr writeOffset,
GLsizeiptr size);
+void GLAPIENTRY
+_mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size);
+
void * GLAPIENTRY
_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
GLbitfield access);
+void * GLAPIENTRY
+_mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
+ GLbitfield access);
+
+void * GLAPIENTRY
+_mesa_MapBuffer(GLenum target, GLenum access);
+
+void * GLAPIENTRY
+_mesa_MapNamedBuffer(GLuint buffer, GLenum access);
+
+
void GLAPIENTRY
_mesa_FlushMappedBufferRange(GLenum target,
GLintptr offset, GLsizeiptr length);
+void GLAPIENTRY
+_mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset,
+ GLsizeiptr length);
+
GLenum GLAPIENTRY
_mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option);
diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h
index 95581fb49..55152fdef 100644
--- a/mesalib/src/mesa/main/compiler.h
+++ b/mesalib/src/mesa/main/compiler.h
@@ -57,29 +57,6 @@ extern "C" {
# elif !defined(__sparc__) && defined(__sparc)
# define __sparc__
# endif
-# if !defined(__volatile)
-# define __volatile volatile
-# endif
-#endif
-
-
-/**
- * Disable assorted warnings
- */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-# if !defined(__GNUC__) /* mingw environment */
-# pragma warning( disable : 4068 ) /* unknown pragma */
-# pragma warning( disable : 4710 ) /* function 'foo' not inlined */
-# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */
-# pragma warning( disable : 4127 ) /* conditional expression is constant */
-# if defined(MESA_MINWARN)
-# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */
-# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */
-# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */
-# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */
-# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */
-# endif
-# endif
#endif
@@ -101,14 +78,6 @@ extern "C" {
#elif defined(__APPLE__)
#include <CoreFoundation/CFByteOrder.h>
#define CPU_TO_LE32( x ) CFSwapInt32HostToLittle( x )
-#elif (defined(_AIX))
-static inline GLuint CPU_TO_LE32(GLuint x)
-{
- return (((x & 0x000000ff) << 24) |
- ((x & 0x0000ff00) << 8) |
- ((x & 0x00ff0000) >> 8) |
- ((x & 0xff000000) >> 24));
-}
#elif defined(__OpenBSD__)
#include <sys/types.h>
#define CPU_TO_LE32( x ) htole32( x )
@@ -125,34 +94,6 @@ static inline GLuint CPU_TO_LE32(GLuint x)
-/**
- * Create a macro so that asm functions can be linked into compilers other
- * than GNU C
- */
-#ifndef _ASMAPI
-#if defined(_WIN32)
-#define _ASMAPI __cdecl
-#else
-#define _ASMAPI
-#endif
-#ifdef PTR_DECL_IN_FRONT
-#define _ASMAPIP * _ASMAPI
-#else
-#define _ASMAPIP _ASMAPI *
-#endif
-#endif
-
-
-/**
- * LONGSTRING macro
- * gcc -pedantic warns about long string literals, LONGSTRING silences that.
- */
-#if !defined(__GNUC__)
-# define LONGSTRING
-#else
-# define LONGSTRING __extension__
-#endif
-
#define IEEE_ONE 0x3f800000
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 22c2341d6..c1acda980 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -882,18 +882,35 @@ update_default_objects(struct gl_context *ctx)
/**
- * This is the default function we plug into all dispatch table slots
- * This helps prevents a segfault when someone calls a GL function without
- * first checking if the extension's supported.
+ * This function is called by the glapi no-op functions. For each OpenGL
+ * function/entrypoint there's a simple no-op function. These "no-op"
+ * functions call this function.
+ *
+ * If there's a current OpenGL context for the calling thread, we record a
+ * GL_INVALID_OPERATION error. This can happen either because the app's
+ * calling an unsupported extension function, or calling an illegal function
+ * (such as glClear between glBegin/glEnd).
+ *
+ * If there's no current OpenGL context for the calling thread, we can
+ * print a message to stderr.
+ *
+ * \param name the name of the OpenGL function, without the "gl" prefix
*/
-int
-_mesa_generic_nop(void)
+static void
+nop_handler(const char *name)
{
GET_CURRENT_CONTEXT(ctx);
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "unsupported function called "
- "(unsupported extension or deprecated function?)");
- return 0;
+ if (ctx) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "gl%s(invalid call)", name);
+ }
+#if defined(DEBUG)
+ else if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) {
+ fprintf(stderr,
+ "GL User Error: gl%s called without a rendering context\n",
+ name);
+ fflush(stderr);
+ }
+#endif
}
@@ -909,16 +926,13 @@ nop_glFlush(void)
#endif
-extern void (*__glapi_noop_table[])(void);
-
-
/**
- * Allocate and initialize a new dispatch table. All the dispatch
- * function pointers will point at the _mesa_generic_nop() function
- * which raises GL_INVALID_OPERATION.
+ * Allocate and initialize a new dispatch table. The table will be
+ * populated with pointers to "no-op" functions. In turn, the no-op
+ * functions will call nop_handler() above.
*/
-struct _glapi_table *
-_mesa_alloc_dispatch_table(void)
+static struct _glapi_table *
+alloc_dispatch_table(void)
{
/* Find the larger of Mesa's dispatch table and libGL's dispatch table.
* In practice, this'll be the same for stand-alone Mesa. But for DRI
@@ -926,23 +940,10 @@ _mesa_alloc_dispatch_table(void)
* DRI drivers.
*/
GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
- struct _glapi_table *table;
-
- table = malloc(numEntries * sizeof(_glapi_proc));
- if (table) {
- _glapi_proc *entry = (_glapi_proc *) table;
- GLint i;
- for (i = 0; i < numEntries; i++) {
-#if defined(_WIN32)
- /* FIXME: This will not generate an error, but at least it won't
- * corrupt the stack like _mesa_generic_nop does. */
- entry[i] = __glapi_noop_table[i];
-#else
- entry[i] = (_glapi_proc) _mesa_generic_nop;
-#endif
- }
+ struct _glapi_table *table = _glapi_new_nop_table(numEntries);
#if defined(_WIN32)
+ if (table) {
/* This is a special case for Windows in the event that
* wglGetProcAddress is called between glBegin/End().
*
@@ -960,8 +961,11 @@ _mesa_alloc_dispatch_table(void)
* assertion passes and the test continues.
*/
SET_Flush(table, nop_glFlush);
-#endif
}
+#endif
+
+ _glapi_set_nop_handler(nop_handler);
+
return table;
}
@@ -997,7 +1001,7 @@ create_beginend_table(const struct gl_context *ctx)
{
struct _glapi_table *table;
- table = _mesa_alloc_dispatch_table();
+ table = alloc_dispatch_table();
if (!table)
return NULL;
@@ -1136,7 +1140,7 @@ _mesa_initialize_context(struct gl_context *ctx,
goto fail;
/* setup the API dispatch tables with all nop functions */
- ctx->OutsideBeginEnd = _mesa_alloc_dispatch_table();
+ ctx->OutsideBeginEnd = alloc_dispatch_table();
if (!ctx->OutsideBeginEnd)
goto fail;
ctx->Exec = ctx->OutsideBeginEnd;
@@ -1163,7 +1167,7 @@ _mesa_initialize_context(struct gl_context *ctx,
switch (ctx->API) {
case API_OPENGL_COMPAT:
ctx->BeginEnd = create_beginend_table(ctx);
- ctx->Save = _mesa_alloc_dispatch_table();
+ ctx->Save = alloc_dispatch_table();
if (!ctx->BeginEnd || !ctx->Save)
goto fail;
diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h
index d5650877e..1cd89a84a 100644
--- a/mesalib/src/mesa/main/context.h
+++ b/mesalib/src/mesa/main/context.h
@@ -175,9 +175,6 @@ _mesa_finish(struct gl_context *ctx);
extern void
_mesa_flush(struct gl_context *ctx);
-extern int
-_mesa_generic_nop(void);
-
extern void GLAPIENTRY
_mesa_Finish( void );
diff --git a/mesalib/src/mesa/main/copyimage.c b/mesalib/src/mesa/main/copyimage.c
index 455929dc2..fd22f2889 100644
--- a/mesalib/src/mesa/main/copyimage.c
+++ b/mesalib/src/mesa/main/copyimage.c
@@ -33,6 +33,12 @@
#include "texobj.h"
#include "fbobject.h"
#include "textureview.h"
+#include "glformats.h"
+
+enum mesa_block_class {
+ BLOCK_CLASS_128_BITS,
+ BLOCK_CLASS_64_BITS
+};
static bool
prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level,
@@ -253,6 +259,124 @@ check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image,
return true;
}
+static bool
+compressed_format_compatible(struct gl_context *ctx,
+ GLenum compressedFormat, GLenum otherFormat)
+{
+ enum mesa_block_class compressedClass, otherClass;
+
+ /* Two view-incompatible compressed formats are never compatible. */
+ if (_mesa_is_compressed_format(ctx, otherFormat)) {
+ return false;
+ }
+
+ /*
+ * From ARB_copy_image spec:
+ * Table 4.X.1 (Compatible internal formats for copying between
+ * compressed and uncompressed internal formats)
+ * ---------------------------------------------------------------------
+ * | Texel / | Uncompressed | |
+ * | Block | internal format | Compressed internal format |
+ * | size | | |
+ * ---------------------------------------------------------------------
+ * | 128-bit | RGBA32UI, | COMPRESSED_RGBA_S3TC_DXT3_EXT, |
+ * | | RGBA32I, | COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,|
+ * | | RGBA32F | COMPRESSED_RGBA_S3TC_DXT5_EXT, |
+ * | | | COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,|
+ * | | | COMPRESSED_RG_RGTC2, |
+ * | | | COMPRESSED_SIGNED_RG_RGTC2, |
+ * | | | COMPRESSED_RGBA_BPTC_UNORM, |
+ * | | | COMPRESSED_SRGB_ALPHA_BPTC_UNORM, |
+ * | | | COMPRESSED_RGB_BPTC_SIGNED_FLOAT, |
+ * | | | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT |
+ * ---------------------------------------------------------------------
+ * | 64-bit | RGBA16F, RG32F, | COMPRESSED_RGB_S3TC_DXT1_EXT, |
+ * | | RGBA16UI, RG32UI, | COMPRESSED_SRGB_S3TC_DXT1_EXT, |
+ * | | RGBA16I, RG32I, | COMPRESSED_RGBA_S3TC_DXT1_EXT, |
+ * | | RGBA16, | COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,|
+ * | | RGBA16_SNORM | COMPRESSED_RED_RGTC1, |
+ * | | | COMPRESSED_SIGNED_RED_RGTC1 |
+ * ---------------------------------------------------------------------
+ */
+
+ switch (compressedFormat) {
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RG_RGTC2:
+ case GL_COMPRESSED_SIGNED_RG_RGTC2:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
+ compressedClass = BLOCK_CLASS_128_BITS;
+ break;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RED_RGTC1:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1:
+ compressedClass = BLOCK_CLASS_64_BITS;
+ break;
+ default:
+ return false;
+ }
+
+ switch (otherFormat) {
+ case GL_RGBA32UI:
+ case GL_RGBA32I:
+ case GL_RGBA32F:
+ otherClass = BLOCK_CLASS_128_BITS;
+ break;
+ case GL_RGBA16F:
+ case GL_RG32F:
+ case GL_RGBA16UI:
+ case GL_RG32UI:
+ case GL_RGBA16I:
+ case GL_RG32I:
+ case GL_RGBA16:
+ case GL_RGBA16_SNORM:
+ otherClass = BLOCK_CLASS_64_BITS;
+ break;
+ default:
+ return false;
+ }
+
+ return compressedClass == otherClass;
+}
+
+static bool
+copy_format_compatible(struct gl_context *ctx,
+ GLenum srcFormat, GLenum dstFormat)
+{
+ /*
+ * From ARB_copy_image spec:
+ * For the purposes of CopyImageSubData, two internal formats
+ * are considered compatible if any of the following conditions are
+ * met:
+ * * the formats are the same,
+ * * the formats are considered compatible according to the
+ * compatibility rules used for texture views as defined in
+ * section 3.9.X. In particular, if both internal formats are listed
+ * in the same entry of Table 3.X.2, they are considered compatible, or
+ * * one format is compressed and the other is uncompressed and
+ * Table 4.X.1 lists the two formats in the same row.
+ */
+
+ if (_mesa_texture_view_compatible_format(ctx, srcFormat, dstFormat)) {
+ /* Also checks if formats are equal. */
+ return true;
+ } else if (_mesa_is_compressed_format(ctx, srcFormat)) {
+ return compressed_format_compatible(ctx, srcFormat, dstFormat);
+ } else if (_mesa_is_compressed_format(ctx, dstFormat)) {
+ return compressed_format_compatible(ctx, dstFormat, srcFormat);
+ }
+
+ return false;
+}
+
void GLAPIENTRY
_mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
GLint srcX, GLint srcY, GLint srcZ,
@@ -265,7 +389,7 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
struct gl_texture_object *srcTexObj, *dstTexObj;
struct gl_texture_image *srcTexImage, *dstTexImage;
GLuint src_bw, src_bh, dst_bw, dst_bh;
- int i, srcNewZ, dstNewZ, Bpt;
+ int i, srcNewZ, dstNewZ;
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
@@ -306,15 +430,6 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
goto cleanup;
}
- /* Very simple sanity check. This is sufficient if one of the textures
- * is compressed. */
- Bpt = _mesa_get_format_bytes(srcTexImage->TexFormat);
- if (_mesa_get_format_bytes(dstTexImage->TexFormat) != Bpt) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(internalFormat mismatch)");
- goto cleanup;
- }
-
if (!check_region_bounds(ctx, srcTexImage, srcX, srcY, srcZ,
srcWidth, srcHeight, srcDepth, "src"))
goto cleanup;
@@ -324,17 +439,11 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
(srcHeight / src_bh) * dst_bh, srcDepth, "dst"))
goto cleanup;
- if (_mesa_is_format_compressed(srcTexImage->TexFormat)) {
- /* XXX: Technically, we should probaby do some more specific checking
- * here. However, this should be sufficient for all compressed
- * formats that mesa supports since it is a direct memory copy.
- */
- } else if (_mesa_is_format_compressed(dstTexImage->TexFormat)) {
- } else if (_mesa_texture_view_compatible_format(ctx,
- srcTexImage->InternalFormat,
- dstTexImage->InternalFormat)) {
- } else {
- return; /* Error logged by _mesa_texture_view_compatible_format */
+ if (!copy_format_compatible(ctx, srcTexImage->InternalFormat,
+ dstTexImage->InternalFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyImageSubData(internalFormat mismatch)");
+ goto cleanup;
}
for (i = 0; i < srcDepth; ++i) {
diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c
index 422c9dc46..2bc8bcad9 100644
--- a/mesalib/src/mesa/main/formats.c
+++ b/mesalib/src/mesa/main/formats.c
@@ -388,7 +388,7 @@ array_formats_equal(const void *a, const void *b)
}
static void
-format_array_format_table_init()
+format_array_format_table_init(void)
{
const struct gl_format_info *info;
mesa_array_format array_format;
diff --git a/mesalib/src/mesa/main/imports.c b/mesalib/src/mesa/main/imports.c
index a7ffe2296..68c731657 100644
--- a/mesalib/src/mesa/main/imports.c
+++ b/mesalib/src/mesa/main/imports.c
@@ -45,6 +45,7 @@
#include <stdio.h>
#include <stdarg.h>
#include "c99_math.h"
+#include "util/rounding.h" /* for _mesa_roundeven */
#include "imports.h"
#include "context.h"
#include "mtypes.h"
@@ -307,26 +308,6 @@ _mesa_bitcount_64(uint64_t n)
#endif
-/* Using C99 rounding functions for roundToEven() implementation is
- * difficult, because round(), rint, and nearbyint() are affected by
- * fesetenv(), which the application may have done for its own
- * purposes. Mesa's IROUND macro is close to what we want, but it
- * rounds away from 0 on n + 0.5.
- */
-int
-_mesa_round_to_even(float val)
-{
- int rounded = IROUND(val);
-
- if (val - floor(val) == 0.5) {
- if (rounded % 2 != 0)
- rounded += val > 0 ? -1 : 1;
- }
-
- return rounded;
-}
-
-
/**
* Convert a 4-byte float to a 2-byte half float.
*
@@ -388,7 +369,7 @@ _mesa_float_to_half(float val)
* or normal.
*/
e = 0;
- m = _mesa_round_to_even((1 << 24) * fabsf(fi.f));
+ m = (int) _mesa_roundevenf((1 << 24) * fabsf(fi.f));
}
else if (new_exp > 15) {
/* map this value to infinity */
@@ -402,7 +383,7 @@ _mesa_float_to_half(float val)
* either normal or infinite.
*/
e = new_exp + 15;
- m = _mesa_round_to_even(flt_m / (float) (1 << 13));
+ m = (int) _mesa_roundevenf(flt_m / (float) (1 << 13));
}
}
@@ -481,24 +462,6 @@ _mesa_half_to_float(GLhalfARB val)
/** \name String */
/*@{*/
-/**
- * Implemented using malloc() and strcpy.
- * Note that NULL is handled accordingly.
- */
-char *
-_mesa_strdup( const char *s )
-{
- if (s) {
- size_t l = strlen(s);
- char *s2 = malloc(l + 1);
- if (s2)
- strcpy(s2, s);
- return s2;
- }
- else {
- return NULL;
- }
-}
/** Compute simple checksum/hash for a string */
unsigned int
diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h
index c211b1555..8877966ec 100755
--- a/mesalib/src/mesa/main/imports.h
+++ b/mesalib/src/mesa/main/imports.h
@@ -432,9 +432,6 @@ _mesa_fls(unsigned int n)
#endif
}
-extern int
-_mesa_round_to_even(float val);
-
extern GLhalfARB
_mesa_float_to_half(float f);
@@ -447,9 +444,6 @@ _mesa_half_is_negative(GLhalfARB h)
return h & 0x8000;
}
-extern char *
-_mesa_strdup( const char *s );
-
extern unsigned int
_mesa_str_checksum(const char *str);
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index efeee8bff..8e1dba6f0 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -693,15 +693,16 @@ struct gl_colorbuffer_attrib
* \name Logic op
*/
/*@{*/
- GLenum LogicOp; /**< Logic operator */
GLboolean IndexLogicOpEnabled; /**< Color index logic op enabled flag */
GLboolean ColorLogicOpEnabled; /**< RGBA logic op enabled flag */
+ GLenum LogicOp; /**< Logic operator */
+
/*@}*/
GLboolean DitherFlag; /**< Dither enable flag */
- GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
GLboolean _ClampFragmentColor; /** < with GL_FIXED_ONLY_ARB resolved */
+ GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
GLenum ClampReadColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
GLboolean sRGBEnabled; /**< Framebuffer sRGB blending/updating requested */
@@ -799,6 +800,7 @@ struct gl_eval_attrib
struct gl_fog_attrib
{
GLboolean Enabled; /**< Fog enabled flag */
+ GLboolean ColorSumEnabled;
GLfloat ColorUnclamped[4]; /**< Fog color */
GLfloat Color[4]; /**< Fog color */
GLfloat Density; /**< Density >= 0.0 */
@@ -806,7 +808,6 @@ struct gl_fog_attrib
GLfloat End; /**< End distance in eye coords */
GLfloat Index; /**< Fog index */
GLenum Mode; /**< Fog mode */
- GLboolean ColorSumEnabled;
GLenum FogCoordinateSource; /**< GL_EXT_fog_coord */
GLfloat _Scale; /**< (End == Start) ? 1.0 : 1.0 / (End - Start) */
GLenum FogDistanceMode; /**< GL_NV_fog_distance */
@@ -846,16 +847,17 @@ struct gl_light_attrib
struct gl_material Material;
GLboolean Enabled; /**< Lighting enabled flag */
+ GLboolean ColorMaterialEnabled;
+
GLenum ShadeModel; /**< GL_FLAT or GL_SMOOTH */
GLenum ProvokingVertex; /**< GL_EXT_provoking_vertex */
GLenum ColorMaterialFace; /**< GL_FRONT, BACK or FRONT_AND_BACK */
GLenum ColorMaterialMode; /**< GL_AMBIENT, GL_DIFFUSE, etc */
GLbitfield _ColorMaterialBitmask; /**< bitmask formed from Face and Mode */
- GLboolean ColorMaterialEnabled;
- GLenum ClampVertexColor; /**< GL_TRUE, GL_FALSE, GL_FIXED_ONLY */
- GLboolean _ClampVertexColor;
- struct gl_light EnabledList; /**< List sentinel */
+
+ GLboolean _ClampVertexColor;
+ GLenum ClampVertexColor; /**< GL_TRUE, GL_FALSE, GL_FIXED_ONLY */
/**
* Derived state for optimizations:
@@ -863,6 +865,8 @@ struct gl_light_attrib
/*@{*/
GLboolean _NeedEyeCoords;
GLboolean _NeedVertices; /**< Use fast shader? */
+ struct gl_light EnabledList; /**< List sentinel */
+
GLfloat _BaseColor[2][3];
/*@}*/
};
@@ -900,13 +904,15 @@ struct gl_multisample_attrib
GLboolean SampleAlphaToCoverage;
GLboolean SampleAlphaToOne;
GLboolean SampleCoverage;
- GLfloat SampleCoverageValue;
GLboolean SampleCoverageInvert;
GLboolean SampleShading;
- GLfloat MinSampleShadingValue;
/* ARB_texture_multisample / GL3.2 additions */
GLboolean SampleMask;
+
+ GLfloat SampleCoverageValue;
+ GLfloat MinSampleShadingValue;
+
/** The GL spec defines this as an array but >32x MSAA is madness */
GLbitfield SampleMaskValue;
};
@@ -977,11 +983,11 @@ struct gl_pixel_attrib
*/
struct gl_point_attrib
{
- GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */
GLfloat Size; /**< User-specified point size */
GLfloat Params[3]; /**< GL_EXT_point_parameters */
GLfloat MinSize, MaxSize; /**< GL_EXT_point_parameters */
GLfloat Threshold; /**< GL_EXT_point_parameters */
+ GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */
GLboolean _Attenuated; /**< True if Params != [1, 0, 0] */
GLboolean PointSprite; /**< GL_NV/ARB_point_sprite */
GLboolean CoordReplace[MAX_TEXTURE_COORD_UNITS]; /**< GL_ARB_point_sprite*/
@@ -1347,6 +1353,9 @@ struct gl_texture_unit
GLfloat LodBias; /**< for biasing mipmap levels */
+ /** Texture targets that have a non-default texture bound */
+ GLbitfield _BoundTextures;
+
/** Current sampler object (GL_ARB_sampler_objects) */
struct gl_sampler_object *Sampler;
@@ -1373,8 +1382,6 @@ struct gl_texture_unit
/** Points to highest priority, complete and enabled texture object */
struct gl_texture_object *_Current;
- /** Texture targets that have a non-default texture bound */
- GLbitfield _BoundTextures;
};
@@ -1384,16 +1391,15 @@ struct gl_texture_unit
struct gl_texture_attrib
{
GLuint CurrentUnit; /**< GL_ACTIVE_TEXTURE */
- struct gl_texture_unit Unit[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
+
+ /** GL_ARB_seamless_cubemap */
+ GLboolean CubeMapSeamless;
struct gl_texture_object *ProxyTex[NUM_TEXTURE_TARGETS];
/** GL_ARB_texture_buffer_object */
struct gl_buffer_object *BufferObject;
- /** GL_ARB_seamless_cubemap */
- GLboolean CubeMapSeamless;
-
/** Texture coord units/sets used for fragment texturing */
GLbitfield _EnabledCoordUnits;
@@ -1411,6 +1417,8 @@ struct gl_texture_attrib
/** Largest index + 1 of texture units that have had any CurrentTex set. */
GLint NumCurrentTexUsed;
+
+ struct gl_texture_unit Unit[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
};
@@ -1536,12 +1544,12 @@ struct gl_client_array
GLenum Format; /**< default: GL_RGBA, but may be GL_BGRA */
GLsizei Stride; /**< user-specified stride */
GLsizei StrideB; /**< actual stride in bytes */
+ GLuint _ElementSize; /**< size of each element in bytes */
const GLubyte *Ptr; /**< Points to array data */
GLboolean Enabled; /**< Enabled flag is a boolean */
GLboolean Normalized; /**< GL_ARB_vertex_program */
GLboolean Integer; /**< Integer-valued? */
GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */
- GLuint _ElementSize; /**< size of each element in bytes */
struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
};
@@ -1600,9 +1608,11 @@ struct gl_vertex_array_object
{
/** Name of the VAO as received from glGenVertexArray. */
GLuint Name;
- GLchar *Label; /**< GL_KHR_debug */
GLint RefCount;
+
+ GLchar *Label; /**< GL_KHR_debug */
+
mtx_t Mutex;
/**
@@ -1707,6 +1717,9 @@ struct gl_array_attrib
GLuint RestartIndex;
/*@}*/
+ /** One of the DRAW_xxx flags, not consumed by drivers */
+ gl_draw_method DrawMethod;
+
/* GL_ARB_vertex_buffer_object */
struct gl_buffer_object *ArrayBufferObj;
@@ -1716,9 +1729,6 @@ struct gl_array_attrib
*/
const struct gl_client_array **_DrawArrays; /**< 0..VERT_ATTRIB_MAX-1 */
- /** One of the DRAW_xxx flags, not consumed by drivers */
- gl_draw_method DrawMethod;
-
/** Legal array datatypes and the API for which they have been computed */
GLbitfield LegalTypesMask;
gl_api LegalTypesMaskAPI;
@@ -1880,8 +1890,8 @@ struct gl_transform_feedback_info
struct gl_transform_feedback_object
{
GLuint Name; /**< AKA the object ID */
- GLchar *Label; /**< GL_KHR_debug */
GLint RefCount;
+ GLchar *Label; /**< GL_KHR_debug */
GLboolean Active; /**< Is transform feedback enabled? */
GLboolean Paused; /**< Is transform feedback paused? */
GLboolean EndedAnytime; /**< Has EndTransformFeedback been called
@@ -1889,14 +1899,6 @@ struct gl_transform_feedback_object
GLboolean EverBound; /**< Has this object been bound? */
/**
- * The shader program active when BeginTransformFeedback() was called.
- * When active and unpaused, this equals ctx->Shader.CurrentProgram[stage],
- * where stage is the pipeline stage that is the source of data for
- * transform feedback.
- */
- struct gl_shader_program *shader_program;
-
- /**
* GLES: if Active is true, remaining number of primitives which can be
* rendered without overflow. This is necessary to track because GLES
* requires us to generate INVALID_OPERATION if a call to glDrawArrays or
@@ -1907,6 +1909,14 @@ struct gl_transform_feedback_object
*/
unsigned GlesRemainingPrims;
+ /**
+ * The shader program active when BeginTransformFeedback() was called.
+ * When active and unpaused, this equals ctx->Shader.CurrentProgram[stage],
+ * where stage is the pipeline stage that is the source of data for
+ * transform feedback.
+ */
+ struct gl_shader_program *shader_program;
+
/** The feedback buffers */
GLuint BufferNames[MAX_FEEDBACK_BUFFERS];
struct gl_buffer_object *Buffers[MAX_FEEDBACK_BUFFERS];
@@ -2229,8 +2239,9 @@ enum gl_frag_depth_layout
struct gl_program
{
GLuint Id;
- GLubyte *String; /**< Null-terminated program text */
GLint RefCount;
+ GLubyte *String; /**< Null-terminated program text */
+
GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_GEOMETRY_PROGRAM_NV */
GLenum Format; /**< String encoding format */
@@ -2533,18 +2544,20 @@ struct gl_shader
GLenum Type;
gl_shader_stage Stage;
GLuint Name; /**< AKA the handle */
- GLchar *Label; /**< GL_KHR_debug */
GLint RefCount; /**< Reference count */
+ GLchar *Label; /**< GL_KHR_debug */
GLboolean DeletePending;
GLboolean CompileStatus;
- const GLchar *Source; /**< Source code string */
+ bool IsES; /**< True if this shader uses GLSL ES */
+
GLuint SourceChecksum; /**< for debug/logging purposes */
+ const GLchar *Source; /**< Source code string */
+
struct gl_program *Program; /**< Post-compile assembly code */
GLchar *InfoLog;
struct gl_sl_pragmas Pragmas;
unsigned Version; /**< GLSL version used for linking */
- GLboolean IsES; /**< True if this shader uses GLSL ES */
/**
* \name Sampler tracking
@@ -2588,8 +2601,8 @@ struct gl_shader
*
* These fields are only set post-linking.
*/
- struct gl_uniform_block *UniformBlocks;
unsigned NumUniformBlocks;
+ struct gl_uniform_block *UniformBlocks;
struct exec_list *ir;
struct glsl_symbol_table *symbols;
@@ -2879,8 +2892,8 @@ struct gl_shader_program
*/
unsigned LastClipDistanceArraySize;
- struct gl_uniform_block *UniformBlocks;
unsigned NumUniformBlocks;
+ struct gl_uniform_block *UniformBlocks;
/**
* Indices into the _LinkedShaders's UniformBlocks[] array for each stage
@@ -2911,7 +2924,7 @@ struct gl_shader_program
GLchar *InfoLog;
unsigned Version; /**< GLSL version used for linking */
- GLboolean IsES; /**< True if this program uses GLSL ES */
+ bool IsES; /**< True if this program uses GLSL ES */
/**
* Per-stage shaders resulting from the first stage of linking.
@@ -3036,7 +3049,7 @@ struct gl_shader_compiler_options
struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
- struct nir_shader_compiler_options *NirOptions;
+ const struct nir_shader_compiler_options *NirOptions;
};
@@ -3265,9 +3278,10 @@ struct gl_framebuffer
* polygon face orientation, and polygon stipple will have to be inverted.
*/
GLuint Name;
+ GLint RefCount;
+
GLchar *Label; /**< GL_KHR_debug */
- GLint RefCount;
GLboolean DeletePending;
/**
@@ -3301,6 +3315,13 @@ struct gl_framebuffer
GLboolean _AllColorBuffersFixedPoint; /* no integer, no float */
GLboolean _HasSNormOrFloatColorBuffer;
+ /**
+ * The maximum number of layers in the framebuffer, or 0 if the framebuffer
+ * is not layered. For cube maps and cube map arrays, each cube face
+ * counts as a layer.
+ */
+ GLuint MaxNumLayers;
+
/** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */
struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT];
@@ -3317,13 +3338,6 @@ struct gl_framebuffer
struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS];
struct gl_renderbuffer *_ColorReadBuffer;
- /**
- * The maximum number of layers in the framebuffer, or 0 if the framebuffer
- * is not layered. For cube maps and cube map arrays, each cube face
- * counts as a layer.
- */
- GLuint MaxNumLayers;
-
/** Delete this framebuffer */
void (*Delete)(struct gl_framebuffer *fb);
};
@@ -4161,6 +4175,13 @@ struct gl_image_unit
GLboolean Layered;
/**
+ * GL_TRUE if the state of this image unit is valid and access from
+ * the shader is allowed. Otherwise loads from this unit should
+ * return zero and stores should have no effect.
+ */
+ GLboolean _Valid;
+
+ /**
* Layer of the texture object bound to this unit, or zero if the
* whole level is bound.
*/
@@ -4184,12 +4205,6 @@ struct gl_image_unit
*/
mesa_format _ActualFormat;
- /**
- * GL_TRUE if the state of this image unit is valid and access from
- * the shader is allowed. Otherwise loads from this unit should
- * return zero and stores should have no effect.
- */
- GLboolean _Valid;
};
/**
diff --git a/mesalib/src/mesa/main/objectlabel.c b/mesalib/src/mesa/main/objectlabel.c
index 78df96b9b..aecb5b1fa 100644
--- a/mesalib/src/mesa/main/objectlabel.c
+++ b/mesalib/src/mesa/main/objectlabel.c
@@ -76,7 +76,7 @@ set_label(struct gl_context *ctx, char **labelPtr, const char *label,
MAX_LABEL_LENGTH);
/* null-terminated string */
- *labelPtr = _mesa_strdup(label);
+ *labelPtr = strdup(label);
}
}
}
diff --git a/mesalib/src/mesa/main/pbo.c b/mesalib/src/mesa/main/pbo.c
index 5c906ed74..0c1602532 100644
--- a/mesalib/src/mesa/main/pbo.c
+++ b/mesalib/src/mesa/main/pbo.c
@@ -80,7 +80,7 @@ _mesa_validate_pbo_access(GLuint dimensions,
*/
if (!_mesa_is_bufferobj(pack->BufferObj)) {
offset = 0;
- size = clientMemSize;
+ size = (clientMemSize == INT_MAX) ? UINTPTR_MAX : clientMemSize;
} else {
offset = (uintptr_t)ptr;
size = pack->BufferObj->Size;
@@ -164,23 +164,18 @@ _mesa_map_pbo_source(struct gl_context *ctx,
return buf;
}
-
/**
- * Combine PBO-read validation and mapping.
- * If any GL errors are detected, they'll be recorded and NULL returned.
+ * Perform PBO validation for read operations with uncompressed textures.
+ * If any GL errors are detected, false is returned, otherwise returns true.
* \sa _mesa_validate_pbo_access
- * \sa _mesa_map_pbo_source
- * A call to this function should have a matching call to
- * _mesa_unmap_pbo_source().
*/
-const GLvoid *
-_mesa_map_validate_pbo_source(struct gl_context *ctx,
- GLuint dimensions,
- const struct gl_pixelstore_attrib *unpack,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type,
- GLsizei clientMemSize,
- const GLvoid *ptr, const char *where)
+bool
+_mesa_validate_pbo_source(struct gl_context *ctx, GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ GLsizei clientMemSize,
+ const GLvoid *ptr, const char *where)
{
assert(dimensions == 1 || dimensions == 2 || dimensions == 3);
@@ -188,24 +183,85 @@ _mesa_map_validate_pbo_source(struct gl_context *ctx,
format, type, clientMemSize, ptr)) {
if (_mesa_is_bufferobj(unpack->BufferObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(out of bounds PBO access)", where);
+ "%s(out of bounds PBO access)",
+ where);
} else {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(out of bounds access: bufSize (%d) is too small)",
where, clientMemSize);
}
- return NULL;
+ return false;
}
if (!_mesa_is_bufferobj(unpack->BufferObj)) {
/* non-PBO access: no further validation to be done */
- return ptr;
+ return true;
}
if (_mesa_check_disallowed_mapping(unpack->BufferObj)) {
/* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
- return NULL;
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)",
+ where);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Perform PBO validation for read operations with compressed textures.
+ * If any GL errors are detected, false is returned, otherwise returns true.
+ */
+bool
+_mesa_validate_pbo_source_compressed(struct gl_context *ctx, GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei imageSize, const GLvoid *pixels,
+ const char *where)
+{
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* not using a PBO */
+ return true;
+ }
+
+ if ((const GLubyte *) pixels + imageSize >
+ ((const GLubyte *) 0) + unpack->BufferObj->Size) {
+ /* out of bounds read! */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid PBO access)",
+ where);
+ return false;
+ }
+
+ if (_mesa_check_disallowed_mapping(unpack->BufferObj)) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)",
+ where);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Perform PBO-read mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_source
+ * \sa _mesa_map_pbo_source
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_source().
+ */
+const GLvoid *
+_mesa_map_validate_pbo_source(struct gl_context *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ GLsizei clientMemSize,
+ const GLvoid *ptr, const char *where)
+{
+ if (!_mesa_validate_pbo_source(ctx, dimensions, unpack,
+ width, height, depth, format, type,
+ clientMemSize, ptr, where)) {
+ return NULL;
}
ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
@@ -381,28 +437,27 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
{
GLubyte *buf;
+ if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, packing,
+ imageSize, pixels, funcName)) {
+ /* error is already set during validation */
+ return NULL;
+ }
+
if (!_mesa_is_bufferobj(packing->BufferObj)) {
/* not using a PBO - return pointer unchanged */
return pixels;
}
- if ((const GLubyte *) pixels + imageSize >
- ((const GLubyte *) 0) + packing->BufferObj->Size) {
- /* out of bounds read! */
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)",
- funcName, dimensions);
- return NULL;
- }
buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0,
packing->BufferObj->Size,
GL_MAP_READ_BIT,
packing->BufferObj,
MAP_INTERNAL);
- if (!buf) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName,
- dimensions);
- return NULL;
- }
+
+ /* Validation above already checked that PBO is not mapped, so buffer
+ * should not be null.
+ */
+ assert(buf);
return ADD_POINTERS(buf, pixels);
}
diff --git a/mesalib/src/mesa/main/pbo.h b/mesalib/src/mesa/main/pbo.h
index 9851ef1a1..b3f24e62b 100644
--- a/mesalib/src/mesa/main/pbo.h
+++ b/mesalib/src/mesa/main/pbo.h
@@ -92,4 +92,18 @@ _mesa_unmap_teximage_pbo(struct gl_context *ctx,
const struct gl_pixelstore_attrib *unpack);
+extern bool
+_mesa_validate_pbo_source(struct gl_context *ctx, GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ GLsizei clientMemSize,
+ const GLvoid *ptr, const char *where);
+
+extern bool
+_mesa_validate_pbo_source_compressed(struct gl_context *ctx, GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei imageSize, const GLvoid *ptr,
+ const char *where);
+
#endif
diff --git a/mesalib/src/mesa/main/querymatrix.c b/mesalib/src/mesa/main/querymatrix.c
index ef8517571..18361c929 100644
--- a/mesalib/src/mesa/main/querymatrix.c
+++ b/mesalib/src/mesa/main/querymatrix.c
@@ -13,7 +13,7 @@
#include <stdlib.h>
-#include <math.h>
+#include "c99_math.h"
#include "glheader.h"
#include "querymatrix.h"
#include "main/get.h"
@@ -37,169 +37,120 @@
#define INT_TO_FIXED(x) ((GLfixed) ((x) << 16))
#define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0))
-#if defined(fpclassify)
-/* ISO C99 says that fpclassify is a macro. Assume that any implementation
- * of fpclassify, whether it's in a C99 compiler or not, will be a macro.
- */
-#elif defined(_MSC_VER)
-/* Not required on VS2013 and above. */
-/* Oddly, the fpclassify() function doesn't exist in such a form
- * on MSVC. This is an implementation using slightly different
- * lower-level Windows functions.
- */
-#include <float.h>
-
-enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
-fpclassify(double x)
-{
- switch(_fpclass(x)) {
- case _FPCLASS_SNAN: /* signaling NaN */
- case _FPCLASS_QNAN: /* quiet NaN */
- return FP_NAN;
- case _FPCLASS_NINF: /* negative infinity */
- case _FPCLASS_PINF: /* positive infinity */
- return FP_INFINITE;
- case _FPCLASS_NN: /* negative normal */
- case _FPCLASS_PN: /* positive normal */
- return FP_NORMAL;
- case _FPCLASS_ND: /* negative denormalized */
- case _FPCLASS_PD: /* positive denormalized */
- return FP_SUBNORMAL;
- case _FPCLASS_NZ: /* negative zero */
- case _FPCLASS_PZ: /* positive zero */
- return FP_ZERO;
- default:
- /* Should never get here; but if we do, this will guarantee
- * that the pattern is not treated like a number.
- */
- return FP_NAN;
- }
-}
-
-#else
-
-enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
-fpclassify(double x)
-{
- /* XXX do something better someday */
- return FP_NORMAL;
-}
-
-#endif
-GLbitfield GLAPIENTRY _mesa_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16])
+GLbitfield GLAPIENTRY
+_mesa_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16])
{
- GLfloat matrix[16];
- GLint tmp;
- GLenum currentMode = GL_FALSE;
- GLenum desiredMatrix = GL_FALSE;
- /* The bitfield returns 1 for each component that is invalid (i.e.
- * NaN or Inf). In case of error, everything is invalid.
- */
- GLbitfield rv;
- register unsigned int i;
- unsigned int bit;
-
- /* This data structure defines the mapping between the current matrix
- * mode and the desired matrix identifier.
- */
- static struct {
- GLenum currentMode;
- GLenum desiredMatrix;
- } modes[] = {
- {GL_MODELVIEW, GL_MODELVIEW_MATRIX},
- {GL_PROJECTION, GL_PROJECTION_MATRIX},
- {GL_TEXTURE, GL_TEXTURE_MATRIX},
- };
-
- /* Call Mesa to get the current matrix in floating-point form. First,
- * we have to figure out what the current matrix mode is.
- */
- _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp);
- currentMode = (GLenum) tmp;
-
- /* The mode is either GL_FALSE, if for some reason we failed to query
- * the mode, or a given mode from the above table. Search for the
- * returned mode to get the desired matrix; if we don't find it,
- * we can return immediately, as _mesa_GetInteger() will have
- * logged the necessary error already.
- */
- for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
- if (modes[i].currentMode == currentMode) {
- desiredMatrix = modes[i].desiredMatrix;
- break;
- }
- }
- if (desiredMatrix == GL_FALSE) {
- /* Early error means all values are invalid. */
- return 0xffff;
- }
-
- /* Now pull the matrix itself. */
- _mesa_GetFloatv(desiredMatrix, matrix);
-
- rv = 0;
- for (i = 0, bit = 1; i < 16; i++, bit<<=1) {
- float normalizedFraction;
- int exp;
-
- switch (fpclassify(matrix[i])) {
- /* A "subnormal" or denormalized number is too small to be
- * represented in normal format; but despite that it's a
- * valid floating point number. FP_ZERO and FP_NORMAL
- * are both valid as well. We should be fine treating
- * these three cases as legitimate floating-point numbers.
- */
- case FP_SUBNORMAL:
- case FP_NORMAL:
- case FP_ZERO:
- normalizedFraction = (GLfloat)frexp(matrix[i], &exp);
- mantissa[i] = FLOAT_TO_FIXED(normalizedFraction);
- exponent[i] = (GLint) exp;
- break;
-
- /* If the entry is not-a-number or an infinity, then the
- * matrix component is invalid. The invalid flag for
- * the component is already set; might as well set the
- * other return values to known values. We'll set
- * distinct values so that a savvy end user could determine
- * whether the matrix component was a NaN or an infinity,
- * but this is more useful for debugging than anything else
- * since the standard doesn't specify any such magic
- * values to return.
- */
- case FP_NAN:
- mantissa[i] = INT_TO_FIXED(0);
- exponent[i] = (GLint) 0;
- rv |= bit;
- break;
-
- case FP_INFINITE:
- /* Return +/- 1 based on whether it's a positive or
- * negative infinity.
- */
- if (matrix[i] > 0) {
- mantissa[i] = INT_TO_FIXED(1);
- }
- else {
- mantissa[i] = -INT_TO_FIXED(1);
- }
- exponent[i] = (GLint) 0;
- rv |= bit;
- break;
-
- /* We should never get here; but here's a catching case
- * in case fpclassify() is returnings something unexpected.
- */
- default:
- mantissa[i] = INT_TO_FIXED(2);
- exponent[i] = (GLint) 0;
- rv |= bit;
- break;
- }
-
- } /* for each component */
-
- /* All done */
- return rv;
+ GLfloat matrix[16];
+ GLint tmp;
+ GLenum currentMode = GL_FALSE;
+ GLenum desiredMatrix = GL_FALSE;
+ /* The bitfield returns 1 for each component that is invalid (i.e.
+ * NaN or Inf). In case of error, everything is invalid.
+ */
+ GLbitfield rv;
+ unsigned i, bit;
+
+ /* This data structure defines the mapping between the current matrix
+ * mode and the desired matrix identifier.
+ */
+ static const struct {
+ GLenum currentMode;
+ GLenum desiredMatrix;
+ } modes[] = {
+ {GL_MODELVIEW, GL_MODELVIEW_MATRIX},
+ {GL_PROJECTION, GL_PROJECTION_MATRIX},
+ {GL_TEXTURE, GL_TEXTURE_MATRIX},
+ };
+
+ /* Call Mesa to get the current matrix in floating-point form. First,
+ * we have to figure out what the current matrix mode is.
+ */
+ _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp);
+ currentMode = (GLenum) tmp;
+
+ /* The mode is either GL_FALSE, if for some reason we failed to query
+ * the mode, or a given mode from the above table. Search for the
+ * returned mode to get the desired matrix; if we don't find it,
+ * we can return immediately, as _mesa_GetInteger() will have
+ * logged the necessary error already.
+ */
+ for (i = 0; i < ARRAY_SIZE(modes); i++) {
+ if (modes[i].currentMode == currentMode) {
+ desiredMatrix = modes[i].desiredMatrix;
+ break;
+ }
+ }
+ if (desiredMatrix == GL_FALSE) {
+ /* Early error means all values are invalid. */
+ return 0xffff;
+ }
+
+ /* Now pull the matrix itself. */
+ _mesa_GetFloatv(desiredMatrix, matrix);
+
+ rv = 0;
+ for (i = 0, bit = 1; i < 16; i++, bit<<=1) {
+ float normalizedFraction;
+ int exp;
+
+ switch (fpclassify(matrix[i])) {
+ case FP_SUBNORMAL:
+ case FP_NORMAL:
+ case FP_ZERO:
+ /* A "subnormal" or denormalized number is too small to be
+ * represented in normal format; but despite that it's a
+ * valid floating point number. FP_ZERO and FP_NORMAL
+ * are both valid as well. We should be fine treating
+ * these three cases as legitimate floating-point numbers.
+ */
+ normalizedFraction = (GLfloat)frexp(matrix[i], &exp);
+ mantissa[i] = FLOAT_TO_FIXED(normalizedFraction);
+ exponent[i] = (GLint) exp;
+ break;
+
+ case FP_NAN:
+ /* If the entry is not-a-number or an infinity, then the
+ * matrix component is invalid. The invalid flag for
+ * the component is already set; might as well set the
+ * other return values to known values. We'll set
+ * distinct values so that a savvy end user could determine
+ * whether the matrix component was a NaN or an infinity,
+ * but this is more useful for debugging than anything else
+ * since the standard doesn't specify any such magic
+ * values to return.
+ */
+ mantissa[i] = INT_TO_FIXED(0);
+ exponent[i] = (GLint) 0;
+ rv |= bit;
+ break;
+
+ case FP_INFINITE:
+ /* Return +/- 1 based on whether it's a positive or
+ * negative infinity.
+ */
+ if (matrix[i] > 0) {
+ mantissa[i] = INT_TO_FIXED(1);
+ }
+ else {
+ mantissa[i] = -INT_TO_FIXED(1);
+ }
+ exponent[i] = (GLint) 0;
+ rv |= bit;
+ break;
+
+ default:
+ /* We should never get here; but here's a catching case
+ * in case fpclassify() is returnings something unexpected.
+ */
+ mantissa[i] = INT_TO_FIXED(2);
+ exponent[i] = (GLint) 0;
+ rv |= bit;
+ break;
+ }
+
+ } /* for each component */
+
+ /* All done */
+ return rv;
}
diff --git a/mesalib/src/mesa/main/scissor.c b/mesalib/src/mesa/main/scissor.c
index 83f39e2a0..bc8224c7d 100644
--- a/mesalib/src/mesa/main/scissor.c
+++ b/mesalib/src/mesa/main/scissor.c
@@ -201,13 +201,13 @@ void GLAPIENTRY
_mesa_ScissorIndexed(GLuint index, GLint left, GLint bottom,
GLsizei width, GLsizei height)
{
- ScissorIndexed(index, left, bottom, width, height, "glScissorIndexd");
+ ScissorIndexed(index, left, bottom, width, height, "glScissorIndexed");
}
void GLAPIENTRY
_mesa_ScissorIndexedv(GLuint index, const GLint *v)
{
- ScissorIndexed(index, v[0], v[1], v[2], v[3], "glScissorIndexdv");
+ ScissorIndexed(index, v[0], v[1], v[2], v[3], "glScissorIndexedv");
}
/**
diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index 5731d581a..30716f5e3 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -1027,15 +1027,14 @@ _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
static void
-use_shader_program(struct gl_context *ctx, GLenum type,
+use_shader_program(struct gl_context *ctx, gl_shader_stage stage,
struct gl_shader_program *shProg,
struct gl_pipeline_object *shTarget)
{
struct gl_shader_program **target;
- gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type);
target = &shTarget->CurrentProgram[stage];
- if ((shProg == NULL) || (shProg->_LinkedShaders[stage] == NULL))
+ if ((shProg != NULL) && (shProg->_LinkedShaders[stage] == NULL))
shProg = NULL;
if (*target != shProg) {
@@ -1048,17 +1047,17 @@ use_shader_program(struct gl_context *ctx, GLenum type,
* it from that binding point as well. This ensures that the correct
* semantics of glDeleteProgram are maintained.
*/
- switch (type) {
- case GL_VERTEX_SHADER:
+ switch (stage) {
+ case MESA_SHADER_VERTEX:
/* Empty for now. */
break;
- case GL_GEOMETRY_SHADER_ARB:
+ case MESA_SHADER_GEOMETRY:
/* Empty for now. */
break;
- case GL_COMPUTE_SHADER:
+ case MESA_SHADER_COMPUTE:
/* Empty for now. */
break;
- case GL_FRAGMENT_SHADER:
+ case MESA_SHADER_FRAGMENT:
if (*target == ctx->_Shader->_CurrentFragmentProgram) {
_mesa_reference_shader_program(ctx,
&ctx->_Shader->_CurrentFragmentProgram,
@@ -1079,10 +1078,9 @@ use_shader_program(struct gl_context *ctx, GLenum type,
void
_mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
{
- use_shader_program(ctx, GL_VERTEX_SHADER, shProg, &ctx->Shader);
- use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg, &ctx->Shader);
- use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg, &ctx->Shader);
- use_shader_program(ctx, GL_COMPUTE_SHADER, shProg, &ctx->Shader);
+ int i;
+ for (i = 0; i < MESA_SHADER_STAGES; i++)
+ use_shader_program(ctx, i, shProg, &ctx->Shader);
_mesa_active_program(ctx, shProg, "glUseProgram");
if (ctx->Driver.UseProgram)
@@ -1460,7 +1458,7 @@ read_shader(const char *fname)
fclose(f);
- shader = _mesa_strdup(buffer);
+ shader = strdup(buffer);
free(buffer);
return shader;
@@ -1889,7 +1887,8 @@ _mesa_use_shader_program(struct gl_context *ctx, GLenum type,
struct gl_shader_program *shProg,
struct gl_pipeline_object *shTarget)
{
- use_shader_program(ctx, type, shProg, shTarget);
+ gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type);
+ use_shader_program(ctx, stage, shProg, shTarget);
if (ctx->Driver.UseProgram)
ctx->Driver.UseProgram(ctx, shProg);
diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c
index f975c160e..255d36559 100644
--- a/mesalib/src/mesa/main/texgetimage.c
+++ b/mesalib/src/mesa/main/texgetimage.c
@@ -1088,48 +1088,9 @@ _mesa_GetTextureImage(GLuint texture, GLint level, GLenum format,
/* Must handle special case GL_TEXTURE_CUBE_MAP. */
if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
- /* Error checking */
- if (texObj->NumLayers < 6) {
- /* Not enough image planes for a cube map. The spec does not say
- * what should happen in this case because the user has always
- * specified each cube face separately (using
- * GL_TEXTURE_CUBE_MAP_POSITIVE_X+i) in previous GL versions.
- * This is addressed in Khronos Bug 13223.
- */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetTextureImage(insufficient cube map storage)");
- return;
- }
-
- /*
- * What do we do if the user created a texture with the following code
- * and then called this function with its handle?
- *
- * GLuint tex;
- * glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &tex);
- * glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
- * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, ...);
- * glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, ...);
- * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, ...);
- * // Note: GL_TEXTURE_CUBE_MAP_NEGATIVE_Y not set, or given the
- * // wrong format, or given the wrong size, etc.
- * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, ...);
- * glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, ...);
- *
- * A bug has been filed against the spec for this case. In the
- * meantime, we will check for cube completeness.
- *
- * According to Section 8.17 Texture Completeness in the OpenGL 4.5
- * Core Profile spec (30.10.2014):
- * "[A] cube map texture is cube complete if the
- * following conditions all hold true: The [base level] texture
- * images of each of the six cube map faces have identical, positive,
- * and square dimensions. The [base level] images were each specified
- * with the same internal format."
- *
- * It seems reasonable to check for cube completeness of an arbitrary
- * level here so that the returned data has a consistent format and size
- * and therefore fits in the user's buffer.
+ /* Make sure the texture object is a proper cube.
+ * (See texturesubimage in teximage.c for details on why this check is
+ * performed.)
*/
if (!_mesa_cube_level_complete(texObj, level)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
@@ -1140,6 +1101,8 @@ _mesa_GetTextureImage(GLuint texture, GLint level, GLenum format,
/* Copy each face. */
for (i = 0; i < 6; ++i) {
texImage = texObj->Image[i][level];
+ assert(texImage);
+
_mesa_get_texture_image(ctx, texObj, texImage, texObj->Target, level,
format, type, bufSize, pixels, true);
@@ -1340,13 +1303,21 @@ _mesa_GetCompressedTextureImage(GLuint texture, GLint level,
/* Must handle special case GL_TEXTURE_CUBE_MAP. */
if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
- assert(texObj->NumLayers >= 6);
+
+ /* Make sure the texture object is a proper cube.
+ * (See texturesubimage in teximage.c for details on why this check is
+ * performed.)
+ */
+ if (!_mesa_cube_level_complete(texObj, level)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTextureImage(cube map incomplete)");
+ return;
+ }
/* Copy each face. */
for (i = 0; i < 6; ++i) {
texImage = texObj->Image[i][level];
- if (!texImage)
- return;
+ assert(texImage);
_mesa_get_compressed_texture_image(ctx, texObj, texImage,
texObj->Target, level,
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index 611d664b6..8d9d7cfc1 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -53,6 +53,7 @@
#include "mtypes.h"
#include "glformats.h"
#include "texstore.h"
+#include "pbo.h"
/**
@@ -1619,32 +1620,30 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
/* Check size */
if (subWidth < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "%s%dD(width=%d)", func, dims, subWidth);
+ "%s(width=%d)", func, subWidth);
return GL_TRUE;
}
if (dims > 1 && subHeight < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "%s%dD(height=%d)", func, dims, subHeight);
+ "%s(height=%d)", func, subHeight);
return GL_TRUE;
}
if (dims > 2 && subDepth < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "%s%dD(depth=%d)", func, dims, subDepth);
+ "%s(depth=%d)", func, subDepth);
return GL_TRUE;
}
/* check xoffset and width */
if (xoffset < - (GLint) destImage->Border) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset)",
- func, dims);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset)", func);
return GL_TRUE;
}
if (xoffset + subWidth > (GLint) destImage->Width) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset+width)",
- func, dims);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset+width)", func);
return GL_TRUE;
}
@@ -1652,13 +1651,11 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
if (dims > 1) {
GLint yBorder = (target == GL_TEXTURE_1D_ARRAY) ? 0 : destImage->Border;
if (yoffset < -yBorder) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(yoffset)",
- func, dims);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset)", func);
return GL_TRUE;
}
if (yoffset + subHeight > (GLint) destImage->Height) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(yoffset+height)",
- func, dims);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset+height)", func);
return GL_TRUE;
}
}
@@ -1671,7 +1668,7 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
0 : destImage->Border;
if (zoffset < -zBorder) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s3D(zoffset)", func);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset)", func);
return GL_TRUE;
}
@@ -1679,7 +1676,7 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
if (target == GL_TEXTURE_CUBE_MAP)
depth = 6;
if (zoffset + subDepth > depth) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s3D(zoffset+depth)", func);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset+depth)", func);
return GL_TRUE;
}
}
@@ -1697,8 +1694,8 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
/* offset must be multiple of block size */
if ((xoffset % bw != 0) || (yoffset % bh != 0)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "%s%dD(xoffset = %d, yoffset = %d)",
- func, dims, xoffset, yoffset);
+ "%s(xoffset = %d, yoffset = %d)",
+ func, xoffset, yoffset);
return GL_TRUE;
}
@@ -1710,14 +1707,14 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
if ((subWidth % bw != 0) &&
(xoffset + subWidth != (GLint) destImage->Width)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "%s%dD(width = %d)", func, dims, subWidth);
+ "%s(width = %d)", func, subWidth);
return GL_TRUE;
}
if ((subHeight % bh != 0) &&
(yoffset + subHeight != (GLint) destImage->Height)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "%s%dD(height = %d)", func, dims, subHeight);
+ "%s(height = %d)", func, subHeight);
return GL_TRUE;
}
}
@@ -2113,7 +2110,8 @@ texture_error_check( struct gl_context *ctx,
GLint level, GLint internalFormat,
GLenum format, GLenum type,
GLint width, GLint height,
- GLint depth, GLint border )
+ GLint depth, GLint border,
+ const GLvoid *pixels )
{
GLenum err;
@@ -2198,6 +2196,13 @@ texture_error_check( struct gl_context *ctx,
return GL_TRUE;
}
+ /* validate the bound PBO, if any */
+ if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack,
+ width, height, depth, format, type,
+ INT_MAX, pixels, "glTexImage")) {
+ return GL_TRUE;
+ }
+
/* make sure internal format and format basically agree */
if (!texture_formats_agree(internalFormat, format)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
@@ -2294,7 +2299,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
GLenum target, GLint level,
GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth, GLint border,
- GLsizei imageSize)
+ GLsizei imageSize, const GLvoid *data)
{
const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
GLint expectedSize;
@@ -2322,6 +2327,13 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
return GL_TRUE;
}
+ /* validate the bound PBO, if any */
+ if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, &ctx->Unpack,
+ imageSize, data,
+ "glCompressedTexImage")) {
+ return GL_TRUE;
+ }
+
switch (internalFormat) {
case GL_PALETTE4_RGB8_OES:
case GL_PALETTE4_RGBA8_OES:
@@ -2454,30 +2466,28 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
- GLenum format, GLenum type, bool dsa)
+ GLenum format, GLenum type, const GLvoid *pixels,
+ bool dsa, const char *callerName)
{
struct gl_texture_image *texImage;
GLenum err;
- const char* suffix = dsa ? "ture" : "";
if (!texObj) {
/* must be out of memory */
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sSubImage%dD()",
- suffix, dimensions);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", callerName);
return GL_TRUE;
}
/* check target (proxies not allowed) */
if (!legal_texsubimage_target(ctx, dimensions, target, dsa)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sSubImage%uD(target=%s)",
- suffix, dimensions, _mesa_lookup_enum_by_nr(target));
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%s)",
+ callerName, _mesa_lookup_enum_by_nr(target));
return GL_TRUE;
}
/* level check */
if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sSubImage%uD(level=%d)",
- suffix, dimensions, level);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", callerName, level);
return GL_TRUE;
}
@@ -2489,9 +2499,8 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
if (_mesa_is_gles(ctx) && !_mesa_is_gles3(ctx)) {
err = _mesa_es_error_check_format_and_type(format, type, dimensions);
if (err != GL_NO_ERROR) {
- _mesa_error(ctx, err,
- "glTex%sSubImage%dD(format = %s, type = %s)",
- suffix, dimensions, _mesa_lookup_enum_by_nr(format),
+ _mesa_error(ctx, err, "%s(format = %s, type = %s)",
+ callerName, _mesa_lookup_enum_by_nr(format),
_mesa_lookup_enum_by_nr(type));
return GL_TRUE;
}
@@ -2500,34 +2509,37 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
err = _mesa_error_check_format_and_type(ctx, format, type);
if (err != GL_NO_ERROR) {
_mesa_error(ctx, err,
- "glTex%sSubImage%dD(incompatible format = %s, type = %s)",
- suffix, dimensions, _mesa_lookup_enum_by_nr(format),
+ "%s(incompatible format = %s, type = %s)",
+ callerName, _mesa_lookup_enum_by_nr(format),
_mesa_lookup_enum_by_nr(type));
return GL_TRUE;
}
+ /* validate the bound PBO, if any */
+ if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack,
+ width, height, depth, format, type,
+ INT_MAX, pixels, callerName)) {
+ return GL_TRUE;
+ }
+
texImage = _mesa_select_tex_image(texObj, target, level);
if (!texImage) {
/* non-existant texture level */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTex%sSubImage%dD(invalid texture image)", suffix,
- dimensions);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture image)",
+ callerName);
return GL_TRUE;
}
if (error_check_subtexture_dimensions(ctx, dimensions,
texImage, xoffset, yoffset, zoffset,
- width, height, depth,
- dsa ? "glTextureSubImage" :
- "glTexSubImage")) {
+ width, height, depth, callerName)) {
return GL_TRUE;
}
if (_mesa_is_format_compressed(texImage->TexFormat)) {
if (compressedteximage_only_format(ctx, texImage->InternalFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glTex%sSubImage%dD(no compression for format)",
- suffix, dimensions);
+ "%s(no compression for format)", callerName);
return GL_TRUE;
}
}
@@ -2537,8 +2549,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
if (_mesa_is_format_integer_color(texImage->TexFormat) !=
_mesa_is_enum_format_integer(format)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glTex%sSubImage%dD(integer/non-integer format mismatch)",
- suffix, dimensions);
+ "%s(integer/non-integer format mismatch)", callerName);
return GL_TRUE;
}
}
@@ -2815,10 +2826,9 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
const struct gl_texture_object *texObj,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
- GLint width, GLint height, bool dsa)
+ GLint width, GLint height, const char *caller)
{
struct gl_texture_image *texImage;
- const char *suffix = dsa ? "ture" : "";
/* Check that the source buffer is complete */
if (_mesa_is_user_fbo(ctx->ReadBuffer)) {
@@ -2827,31 +2837,26 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
}
if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glCopyTex%sSubImage%dD(invalid readbuffer)",
- suffix, dimensions);
+ "%s(invalid readbuffer)", caller);
return GL_TRUE;
}
if (ctx->ReadBuffer->Visual.samples > 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTex%sSubImage%dD(multisample FBO)", suffix,
- dimensions);
+ "%s(multisample FBO)", caller);
return GL_TRUE;
}
}
/* Check level */
if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyTex%sSubImage%dD(level=%d)", suffix,
- dimensions, level);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", caller, level);
return GL_TRUE;
}
/* Get dest image pointers */
if (!texObj) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTex%sSubImage%dD()",
- suffix, dimensions);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", caller);
return GL_TRUE;
}
@@ -2859,37 +2864,33 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
if (!texImage) {
/* destination image does not exist */
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTex%sSubImage%dD(invalid texture image)",
- suffix, dimensions);
+ "%s(invalid texture image)", caller);
return GL_TRUE;
}
if (error_check_subtexture_dimensions(ctx, dimensions, texImage,
xoffset, yoffset, zoffset,
- width, height, 1, dsa ?
- "glCompressedTextureSubImage" :
- "glCompressedTexSubImage")) {
+ width, height, 1, caller)) {
return GL_TRUE;
}
if (_mesa_is_format_compressed(texImage->TexFormat)) {
if (compressedteximage_only_format(ctx, texImage->InternalFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTex%sSubImage%dD(no compression for format)",
- suffix, dimensions);
+ "%s(no compression for format)", caller);
return GL_TRUE;
}
}
if (texImage->InternalFormat == GL_YCBCR_MESA) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTex%sSubImage2D", suffix);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", caller);
return GL_TRUE;
}
if (!_mesa_source_buffer_exists(ctx, texImage->_BaseFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTex%sSubImage%dD(missing readbuffer, format=0x%x)",
- suffix, dimensions, texImage->_BaseFormat);
+ "%s(missing readbuffer, format=0x%x)", caller,
+ texImage->_BaseFormat);
return GL_TRUE;
}
@@ -2907,8 +2908,7 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
if (_mesa_is_format_integer_color(rb->Format) !=
_mesa_is_format_integer_color(texImage->TexFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTex%sSubImage%dD(integer vs non-integer)",
- suffix, dimensions);
+ "%s(integer vs non-integer)", caller);
return GL_TRUE;
}
}
@@ -3218,12 +3218,13 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
if (compressed_texture_error_check(ctx, dims, target, level,
internalFormat,
width, height, depth,
- border, imageSize))
+ border, imageSize, pixels))
return;
}
else {
if (texture_error_check(ctx, dims, target, level, internalFormat,
- format, type, width, height, depth, border))
+ format, type, width, height, depth, border,
+ pixels))
return;
}
@@ -3562,7 +3563,8 @@ static void
texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *pixels)
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const char *callerName)
{
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
@@ -3573,7 +3575,8 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
if (texsubimage_error_check(ctx, dims, texObj, target, level,
xoffset, yoffset, zoffset,
- width, height, depth, format, type, false)) {
+ width, height, depth, format, type,
+ pixels, false, callerName)) {
return; /* error was detected */
}
@@ -3603,7 +3606,8 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
GLuint texture, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid *pixels)
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const char *callerName)
{
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
@@ -3627,7 +3631,8 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
if (texsubimage_error_check(ctx, dims, texObj, texObj->Target, level,
xoffset, yoffset, zoffset,
- width, height, depth, format, type, true)) {
+ width, height, depth, format, type,
+ pixels, true, callerName)) {
return; /* error was detected */
}
@@ -3636,20 +3641,6 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
GLint rowStride;
- /* Error checking */
- if (texObj->NumLayers < 6) {
- /* Not enough image planes for a cube map. The spec does not say
- * what should happen in this case because the user has always
- * specified each cube face separately (using
- * GL_TEXTURE_CUBE_MAP_POSITIVE_X+i) in previous GL versions.
- * This is addressed in Khronos Bug 13223.
- */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glTextureSubImage%uD(insufficient cube map storage)",
- dims);
- return;
- }
-
/*
* What do we do if the user created a texture with the following code
* and then called this function with its handle?
@@ -3691,6 +3682,8 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
/* Copy in each face. */
for (i = 0; i < 6; ++i) {
texImage = texObj->Image[i][level];
+ assert(texImage);
+
_mesa_texture_sub_image(ctx, 3, texObj, texImage, texObj->Target,
level, xoffset, yoffset, zoffset,
width, height, 1, format,
@@ -3700,8 +3693,7 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
}
else {
texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
- if (!texImage)
- return;
+ assert(texImage);
_mesa_texture_sub_image(ctx, dims, texObj, texImage, texObj->Target,
level, xoffset, yoffset, zoffset,
@@ -3721,7 +3713,7 @@ _mesa_TexSubImage1D( GLenum target, GLint level,
texsubimage(ctx, 1, target, level,
xoffset, 0, 0,
width, 1, 1,
- format, type, pixels);
+ format, type, pixels, "glTexSubImage1D");
}
@@ -3736,7 +3728,7 @@ _mesa_TexSubImage2D( GLenum target, GLint level,
texsubimage(ctx, 2, target, level,
xoffset, yoffset, 0,
width, height, 1,
- format, type, pixels);
+ format, type, pixels, "glTexSubImage2D");
}
@@ -3752,7 +3744,7 @@ _mesa_TexSubImage3D( GLenum target, GLint level,
texsubimage(ctx, 3, target, level,
xoffset, yoffset, zoffset,
width, height, depth,
- format, type, pixels);
+ format, type, pixels, "glTexSubImage3D");
}
void GLAPIENTRY
@@ -3765,7 +3757,7 @@ _mesa_TextureSubImage1D(GLuint texture, GLint level,
texturesubimage(ctx, 1, texture, level,
xoffset, 0, 0,
width, 1, 1,
- format, type, pixels);
+ format, type, pixels, "glTextureSubImage1D");
}
@@ -3780,7 +3772,7 @@ _mesa_TextureSubImage2D(GLuint texture, GLint level,
texturesubimage(ctx, 2, texture, level,
xoffset, yoffset, 0,
width, height, 1,
- format, type, pixels);
+ format, type, pixels, "glTextureSubImage2D");
}
@@ -3795,7 +3787,7 @@ _mesa_TextureSubImage3D(GLuint texture, GLint level,
texturesubimage(ctx, 3, texture, level,
xoffset, yoffset, zoffset,
width, height, depth,
- format, type, pixels);
+ format, type, pixels, "glTextureSubImage3D");
}
@@ -4040,15 +4032,14 @@ _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y,
GLsizei width, GLsizei height,
- bool dsa)
+ const char *caller)
{
struct gl_texture_image *texImage;
FLUSH_VERTICES(ctx, 0);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glCopyTex%sSubImage%uD %s %d %d %d %d %d %d %d %d\n",
- dsa ? "ture" : "", dims,
+ _mesa_debug(ctx, "%s %s %d %d %d %d %d %d %d %d\n", caller,
_mesa_lookup_enum_by_nr(target),
level, xoffset, yoffset, zoffset, x, y, width, height);
@@ -4057,7 +4048,7 @@ _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims,
if (copytexsubimage_error_check(ctx, dims, texObj, target, level,
xoffset, yoffset, zoffset,
- width, height, dsa)) {
+ width, height, caller)) {
return;
}
@@ -4103,14 +4094,14 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
GLint xoffset, GLint x, GLint y, GLsizei width )
{
struct gl_texture_object* texObj;
+ const char *self = "glCopyTexSubImage1D";
GET_CURRENT_CONTEXT(ctx);
/* Check target (proxies not allowed). Target must be checked prior to
* calling _mesa_get_current_tex_object.
*/
if (!legal_texsubimage_target(ctx, 1, target, false)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyTexSubImage1D(invalid target %s)",
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
_mesa_lookup_enum_by_nr(target));
return;
}
@@ -4120,7 +4111,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
return;
_mesa_copy_texture_sub_image(ctx, 1, texObj, target, level, xoffset, 0, 0,
- x, y, width, 1, false);
+ x, y, width, 1, self);
}
@@ -4131,14 +4122,14 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_object* texObj;
+ const char *self = "glCopyTexSubImage2D";
GET_CURRENT_CONTEXT(ctx);
/* Check target (proxies not allowed). Target must be checked prior to
* calling _mesa_get_current_tex_object.
*/
if (!legal_texsubimage_target(ctx, 2, target, false)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyTexSubImage2D(invalid target %s)",
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
_mesa_lookup_enum_by_nr(target));
return;
}
@@ -4149,7 +4140,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
_mesa_copy_texture_sub_image(ctx, 2, texObj, target, level,
xoffset, yoffset, 0,
- x, y, width, height, false);
+ x, y, width, height, self);
}
@@ -4160,14 +4151,14 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_object* texObj;
+ const char *self = "glCopyTexSubImage3D";
GET_CURRENT_CONTEXT(ctx);
/* Check target (proxies not allowed). Target must be checked prior to
* calling _mesa_get_current_tex_object.
*/
if (!legal_texsubimage_target(ctx, 3, target, false)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyTexSubImage3D(invalid target %s)",
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
_mesa_lookup_enum_by_nr(target));
return;
}
@@ -4178,7 +4169,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
_mesa_copy_texture_sub_image(ctx, 3, texObj, target, level,
xoffset, yoffset, zoffset,
- x, y, width, height, false);
+ x, y, width, height, self);
}
void GLAPIENTRY
@@ -4186,22 +4177,22 @@ _mesa_CopyTextureSubImage1D(GLuint texture, GLint level,
GLint xoffset, GLint x, GLint y, GLsizei width)
{
struct gl_texture_object* texObj;
+ const char *self = "glCopyTextureSubImage1D";
GET_CURRENT_CONTEXT(ctx);
- texObj = _mesa_lookup_texture_err(ctx, texture, "glCopyTextureSubImage1D");
+ texObj = _mesa_lookup_texture_err(ctx, texture, self);
if (!texObj)
return;
/* Check target (proxies not allowed). */
if (!legal_texsubimage_target(ctx, 1, texObj->Target, true)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyTextureSubImage1D(invalid target %s)",
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
_mesa_lookup_enum_by_nr(texObj->Target));
return;
}
_mesa_copy_texture_sub_image(ctx, 1, texObj, texObj->Target, level,
- xoffset, 0, 0, x, y, width, 1, true);
+ xoffset, 0, 0, x, y, width, 1, self);
}
void GLAPIENTRY
@@ -4210,23 +4201,23 @@ _mesa_CopyTextureSubImage2D(GLuint texture, GLint level,
GLint x, GLint y, GLsizei width, GLsizei height)
{
struct gl_texture_object* texObj;
+ const char *self = "glCopyTextureSubImage2D";
GET_CURRENT_CONTEXT(ctx);
- texObj = _mesa_lookup_texture_err(ctx, texture, "glCopyTextureSubImage2D");
+ texObj = _mesa_lookup_texture_err(ctx, texture, self);
if (!texObj)
return;
/* Check target (proxies not allowed). */
if (!legal_texsubimage_target(ctx, 2, texObj->Target, true)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyTextureSubImage2D(invalid target %s)",
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
_mesa_lookup_enum_by_nr(texObj->Target));
return;
}
_mesa_copy_texture_sub_image(ctx, 2, texObj, texObj->Target, level,
xoffset, yoffset, 0,
- x, y, width, height, true);
+ x, y, width, height, self);
}
@@ -4237,23 +4228,31 @@ _mesa_CopyTextureSubImage3D(GLuint texture, GLint level,
GLint x, GLint y, GLsizei width, GLsizei height)
{
struct gl_texture_object* texObj;
+ const char *self = "glCopyTextureSubImage3D";
GET_CURRENT_CONTEXT(ctx);
- texObj = _mesa_lookup_texture_err(ctx, texture, "glCopyTextureSubImage3D");
+ texObj = _mesa_lookup_texture_err(ctx, texture, self);
if (!texObj)
return;
/* Check target (proxies not allowed). */
if (!legal_texsubimage_target(ctx, 3, texObj->Target, true)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyTextureSubImage3D(invalid target %s)",
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
_mesa_lookup_enum_by_nr(texObj->Target));
return;
}
- _mesa_copy_texture_sub_image(ctx, 3, texObj, texObj->Target, level,
- xoffset, yoffset, zoffset,
- x, y, width, height, true);
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+ /* Act like CopyTexSubImage2D */
+ _mesa_copy_texture_sub_image(ctx, 2, texObj,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset,
+ level, xoffset, yoffset, 0,
+ x, y, width, height, self);
+ }
+ else
+ _mesa_copy_texture_sub_image(ctx, 3, texObj, texObj->Target, level,
+ xoffset, yoffset, zoffset,
+ x, y, width, height, self);
}
static bool
@@ -4636,68 +4635,72 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLsizei imageSize, bool dsa)
+ GLenum format, GLsizei imageSize,
+ const GLvoid *data, const char *callerName)
{
struct gl_texture_image *texImage;
GLint expectedSize;
- const char *suffix = dsa ? "ture" : "";
/* this will catch any invalid compressed format token */
if (!_mesa_is_compressed_format(ctx, format)) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glCompressedTex%sSubImage%uD(format)", suffix, dims);
+ "%s(format)", callerName);
return GL_TRUE;
}
if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCompressedTex%sSubImage%uD(level=%d)",
- suffix, dims, level);
+ "%s(level=%d)",
+ callerName, level);
+ return GL_TRUE;
+ }
+
+ /* validate the bound PBO, if any */
+ if (!_mesa_validate_pbo_source_compressed(ctx, dims, &ctx->Unpack,
+ imageSize, data, callerName)) {
return GL_TRUE;
}
/* Check for invalid pixel storage modes */
if (!_mesa_compressed_pixel_storage_error_check(ctx, dims,
- &ctx->Unpack,
- dsa ? "glCompressedTextureSubImage" :
- "glCompressedTexSubImage")) {
+ &ctx->Unpack, callerName)) {
return GL_TRUE;
}
expectedSize = compressed_tex_size(width, height, depth, format);
if (expectedSize != imageSize) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCompressedTex%sSubImage%uD(size=%d)",
- suffix, dims, imageSize);
+ "%s(size=%d)",
+ callerName, imageSize);
return GL_TRUE;
}
texImage = _mesa_select_tex_image(texObj, target, level);
if (!texImage) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCompressedTex%sSubImage%uD(invalid texture image)",
- suffix, dims);
+ "%s(invalid texture image)",
+ callerName);
return GL_TRUE;
}
if ((GLint) format != texImage->InternalFormat) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCompressedTex%sSubImage%uD(format=0x%x)",
- suffix, dims, format);
+ "%s(format=0x%x)",
+ callerName, format);
return GL_TRUE;
}
if (compressedteximage_only_format(ctx, format)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCompressedTex%sSubImage%uD(format=0x%x cannot be updated)",
- suffix, dims, format);
+ "%s(format=0x%x cannot be updated)",
+ callerName, format);
return GL_TRUE;
}
if (error_check_subtexture_dimensions(ctx, dims,
texImage, xoffset, yoffset, zoffset,
width, height, depth,
- "glCompressedTexSubImage")) {
+ callerName)) {
return GL_TRUE;
}
@@ -4748,30 +4751,19 @@ _mesa_CompressedTexImage3D(GLenum target, GLint level,
void
_mesa_compressed_texture_sub_image(struct gl_context *ctx, GLuint dims,
struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint zoffset,
GLsizei width, GLsizei height,
GLsizei depth,
GLenum format, GLsizei imageSize,
- const GLvoid *data, bool dsa)
+ const GLvoid *data)
{
- struct gl_texture_image *texImage;
-
- if (compressed_subtexture_error_check(ctx, dims, texObj, target,
- level, xoffset, yoffset, zoffset,
- width, height, depth,
- format, imageSize, dsa)) {
- return;
- }
-
FLUSH_VERTICES(ctx, 0);
_mesa_lock_texture(ctx, texObj);
{
- texImage = _mesa_select_tex_image(texObj, target, level);
- assert(texImage);
-
if (width > 0 && height > 0 && depth > 0) {
ctx->Driver.CompressedTexSubImage(ctx, dims, texImage,
xoffset, yoffset, zoffset,
@@ -4795,6 +4787,8 @@ _mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset,
GLsizei imageSize, const GLvoid *data)
{
struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
GET_CURRENT_CONTEXT(ctx);
if (compressed_subtexture_target_check(ctx, target, 1, format, false,
@@ -4806,9 +4800,20 @@ _mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset,
if (!texObj)
return;
- _mesa_compressed_texture_sub_image(ctx, 1, texObj, target, level,
+ if (compressed_subtexture_error_check(ctx, 1, texObj, target,
+ level, xoffset, 0, 0,
+ width, 1, 1,
+ format, imageSize, data,
+ "glCompressedTexSubImage1D")) {
+ return;
+ }
+
+ texImage = _mesa_select_tex_image(texObj, target, level);
+ assert(texImage);
+
+ _mesa_compressed_texture_sub_image(ctx, 1, texObj, texImage, target, level,
xoffset, 0, 0, width, 1, 1,
- format, imageSize, data, false);
+ format, imageSize, data);
}
void GLAPIENTRY
@@ -4817,6 +4822,8 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset,
GLsizei imageSize, const GLvoid *data)
{
struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
GET_CURRENT_CONTEXT(ctx);
texObj = _mesa_lookup_texture_err(ctx, texture,
@@ -4830,9 +4837,21 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset,
return;
}
- _mesa_compressed_texture_sub_image(ctx, 1, texObj, texObj->Target, level,
+ if (compressed_subtexture_error_check(ctx, 1, texObj, texObj->Target,
+ level, xoffset, 0, 0,
+ width, 1, 1,
+ format, imageSize, data,
+ "glCompressedTextureSubImage1D")) {
+ return;
+ }
+
+ texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
+ assert(texImage);
+
+ _mesa_compressed_texture_sub_image(ctx, 1, texObj, texImage,
+ texObj->Target, level,
xoffset, 0, 0, width, 1, 1,
- format, imageSize, data, true);
+ format, imageSize, data);
}
@@ -4843,6 +4862,8 @@ _mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
const GLvoid *data)
{
struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
GET_CURRENT_CONTEXT(ctx);
if (compressed_subtexture_target_check(ctx, target, 2, format, false,
@@ -4854,9 +4875,21 @@ _mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
if (!texObj)
return;
- _mesa_compressed_texture_sub_image(ctx, 2, texObj, target, level,
+ if (compressed_subtexture_error_check(ctx, 2, texObj, target,
+ level, xoffset, yoffset, 0,
+ width, height, 1,
+ format, imageSize, data,
+ "glCompressedTexSubImage2D")) {
+ return;
+ }
+
+
+ texImage = _mesa_select_tex_image(texObj, target, level);
+ assert(texImage);
+
+ _mesa_compressed_texture_sub_image(ctx, 2, texObj, texImage, target, level,
xoffset, yoffset, 0, width, height, 1,
- format, imageSize, data, false);
+ format, imageSize, data);
}
void GLAPIENTRY
@@ -4867,6 +4900,8 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset,
const GLvoid *data)
{
struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
GET_CURRENT_CONTEXT(ctx);
texObj = _mesa_lookup_texture_err(ctx, texture,
@@ -4880,9 +4915,21 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset,
return;
}
- _mesa_compressed_texture_sub_image(ctx, 2, texObj, texObj->Target, level,
+ if (compressed_subtexture_error_check(ctx, 2, texObj, texObj->Target,
+ level, xoffset, yoffset, 0,
+ width, height, 1,
+ format, imageSize, data,
+ "glCompressedTextureSubImage2D")) {
+ return;
+ }
+
+ texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
+ assert(texImage);
+
+ _mesa_compressed_texture_sub_image(ctx, 2, texObj, texImage,
+ texObj->Target, level,
xoffset, yoffset, 0, width, height, 1,
- format, imageSize, data, true);
+ format, imageSize, data);
}
void GLAPIENTRY
@@ -4892,6 +4939,8 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
GLsizei imageSize, const GLvoid *data)
{
struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
GET_CURRENT_CONTEXT(ctx);
if (compressed_subtexture_target_check(ctx, target, 3, format, false,
@@ -4903,10 +4952,22 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
if (!texObj)
return;
- _mesa_compressed_texture_sub_image(ctx, 3, texObj, target, level,
+ if (compressed_subtexture_error_check(ctx, 3, texObj, target,
+ level, xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, imageSize, data,
+ "glCompressedTexSubImage3D")) {
+ return;
+ }
+
+
+ texImage = _mesa_select_tex_image(texObj, target, level);
+ assert(texImage);
+
+ _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage, target, level,
xoffset, yoffset, zoffset,
width, height, depth,
- format, imageSize, data, false);
+ format, imageSize, data);
}
void GLAPIENTRY
@@ -4917,6 +4978,8 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset,
const GLvoid *data)
{
struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
GET_CURRENT_CONTEXT(ctx);
texObj = _mesa_lookup_texture_err(ctx, texture,
@@ -4930,10 +4993,60 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset,
return;
}
- _mesa_compressed_texture_sub_image(ctx, 3, texObj, texObj->Target, level,
- xoffset, yoffset, zoffset,
- width, height, depth,
- format, imageSize, data, true);
+ if (compressed_subtexture_error_check(ctx, 3, texObj, texObj->Target,
+ level, xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, imageSize, data,
+ "glCompressedTextureSubImage3D")) {
+ return;
+ }
+
+ /* Must handle special case GL_TEXTURE_CUBE_MAP. */
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+ const char *pixels = data;
+ int i;
+ GLint image_stride;
+
+ /* Make sure the texture object is a proper cube.
+ * (See texturesubimage in teximage.c for details on why this check is
+ * performed.)
+ */
+ if (!_mesa_cube_level_complete(texObj, level)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTextureSubImage3D(cube map incomplete)");
+ return;
+ }
+
+ /* Copy in each face. */
+ for (i = 0; i < 6; ++i) {
+ texImage = texObj->Image[i][level];
+ assert(texImage);
+
+ _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage,
+ texObj->Target, level,
+ xoffset, yoffset, zoffset,
+ width, height, 1,
+ format, imageSize, pixels);
+
+ /* Compressed images don't have a client format */
+ image_stride = _mesa_format_image_size(texImage->TexFormat,
+ texImage->Width,
+ texImage->Height, 1);
+
+ pixels += image_stride;
+ imageSize -= image_stride;
+ }
+ }
+ else {
+ texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
+ assert(texImage);
+
+ _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage,
+ texObj->Target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, imageSize, data);
+ }
}
static mesa_format
@@ -5152,24 +5265,34 @@ _mesa_validate_texbuffer_format(const struct gl_context *ctx,
void
_mesa_texture_buffer_range(struct gl_context *ctx,
- struct gl_texture_object *texObj, GLenum target,
+ struct gl_texture_object *texObj,
GLenum internalFormat,
struct gl_buffer_object *bufObj,
- GLintptr offset, GLsizeiptr size, bool range,
- bool dsa)
+ GLintptr offset, GLsizeiptr size,
+ const char *caller)
{
mesa_format format;
- FLUSH_VERTICES(ctx, 0);
+ /* NOTE: ARB_texture_buffer_object has interactions with
+ * the compatibility profile that are not implemented.
+ */
+ if (!(ctx->API == API_OPENGL_CORE &&
+ ctx->Extensions.ARB_texture_buffer_object)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(ARB_texture_buffer_object is not"
+ " implemented for the compatibility profile)", caller);
+ return;
+ }
format = _mesa_validate_texbuffer_format(ctx, internalFormat);
if (format == MESA_FORMAT_NONE) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glTex%sBuffer%s(internalFormat 0x%x)", dsa ? "ture" : "",
- range ? "Range" : "", internalFormat);
+ "%s(internalFormat 0x%x)", caller, internalFormat);
return;
}
+ FLUSH_VERTICES(ctx, 0);
+
_mesa_lock_texture(ctx, texObj);
{
_mesa_reference_buffer_object(ctx, &texObj->BufferObject, bufObj);
@@ -5188,6 +5311,75 @@ _mesa_texture_buffer_range(struct gl_context *ctx,
}
+/**
+ * Make sure the texture buffer target is GL_TEXTURE_BUFFER.
+ * Return true if it is, and return false if it is not
+ * (and throw INVALID ENUM as dictated in the OpenGL 4.5
+ * core spec, 02.02.2015, PDF page 245).
+ */
+static bool
+check_texture_buffer_target(struct gl_context *ctx, GLenum target,
+ const char *caller)
+{
+ if (target != GL_TEXTURE_BUFFER_ARB) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(texture target is not GL_TEXTURE_BUFFER)", caller);
+ return false;
+ }
+ else
+ return true;
+}
+
+/**
+ * Check for errors related to the texture buffer range.
+ * Return false if errors are found, true if none are found.
+ */
+static bool
+check_texture_buffer_range(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size,
+ const char *caller)
+{
+ /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer
+ * Textures (PDF page 245):
+ * "An INVALID_VALUE error is generated if offset is negative, if
+ * size is less than or equal to zero, or if offset + size is greater
+ * than the value of BUFFER_SIZE for the buffer bound to target."
+ */
+ if (offset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d < 0)", caller,
+ (int) offset);
+ return false;
+ }
+
+ if (size <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d <= 0)", caller,
+ (int) size);
+ return false;
+ }
+
+ if (offset + size > bufObj->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(offset=%d + size=%d > buffer_size=%d)", caller,
+ (int) offset, (int) size, (int) bufObj->Size);
+ return false;
+ }
+
+ /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer
+ * Textures (PDF page 245):
+ * "An INVALID_VALUE error is generated if offset is not an integer
+ * multiple of the value of TEXTURE_BUFFER_OFFSET_ALIGNMENT."
+ */
+ if (offset % ctx->Const.TextureBufferOffsetAlignment) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(invalid offset alignment)", caller);
+ return false;
+ }
+
+ return true;
+}
+
+
/** GL_ARB_texture_buffer_object */
void GLAPIENTRY
_mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
@@ -5197,33 +5389,25 @@ _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
GET_CURRENT_CONTEXT(ctx);
- /* Need to catch this before it gets to _mesa_get_current_tex_object */
- if (target != GL_TEXTURE_BUFFER_ARB) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(target)");
- return;
- }
-
- /* NOTE: ARB_texture_buffer_object has interactions with
- * the compatibility profile that are not implemented.
+ /* Need to catch a bad target before it gets to
+ * _mesa_get_current_tex_object.
*/
- if (!(ctx->API == API_OPENGL_CORE &&
- ctx->Extensions.ARB_texture_buffer_object)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer");
+ if (!check_texture_buffer_target(ctx, target, "glTexBuffer"))
return;
- }
- bufObj = _mesa_lookup_bufferobj(ctx, buffer);
- if (!bufObj && buffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer(buffer %u)", buffer);
- return;
- }
+ if (buffer) {
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBuffer");
+ if (!bufObj)
+ return;
+ } else
+ bufObj = NULL;
texObj = _mesa_get_current_tex_object(ctx, target);
if (!texObj)
return;
- _mesa_texture_buffer_range(ctx, texObj, target, internalFormat, bufObj, 0,
- buffer ? -1 : 0, false, false);
+ _mesa_texture_buffer_range(ctx, texObj, internalFormat, bufObj, 0,
+ buffer ? -1 : 0, "glTexBuffer");
}
@@ -5237,46 +5421,41 @@ _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
GET_CURRENT_CONTEXT(ctx);
- /* Need to catch this before it gets to _mesa_get_current_tex_object */
- if (target != GL_TEXTURE_BUFFER_ARB) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexBufferRange(target)");
- return;
- }
-
- if (!(ctx->API == API_OPENGL_CORE &&
- ctx->Extensions.ARB_texture_buffer_range)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBufferRange");
+ /* Need to catch a bad target before it gets to
+ * _mesa_get_current_tex_object.
+ */
+ if (!check_texture_buffer_target(ctx, target, "glTexBufferRange"))
return;
- }
- bufObj = _mesa_lookup_bufferobj(ctx, buffer);
- if (bufObj) {
- if (offset < 0 ||
- size <= 0 ||
- (offset + size) > bufObj->Size) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexBufferRange");
+ if (buffer) {
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBufferRange");
+ if (!bufObj)
return;
- }
- if (offset % ctx->Const.TextureBufferOffsetAlignment) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glTexBufferRange(invalid offset alignment)");
+
+ if (!check_texture_buffer_range(ctx, bufObj, offset, size,
+ "glTexBufferRange"))
return;
- }
- } else if (buffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBufferRange(buffer %u)",
- buffer);
- return;
+
} else {
+
+ /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer
+ * Textures (PDF page 254):
+ * "If buffer is zero, then any buffer object attached to the buffer
+ * texture is detached, the values offset and size are ignored and
+ * the state for offset and size for the buffer texture are reset to
+ * zero."
+ */
offset = 0;
size = 0;
+ bufObj = NULL;
}
texObj = _mesa_get_current_tex_object(ctx, target);
if (!texObj)
return;
- _mesa_texture_buffer_range(ctx, texObj, target, internalFormat, bufObj,
- offset, size, true, false);
+ _mesa_texture_buffer_range(ctx, texObj, internalFormat, bufObj,
+ offset, size, "glTexBufferRange");
}
void GLAPIENTRY
@@ -5287,35 +5466,69 @@ _mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer)
GET_CURRENT_CONTEXT(ctx);
- /* NOTE: ARB_texture_buffer_object has interactions with
- * the compatibility profile that are not implemented.
- */
- if (!(ctx->API == API_OPENGL_CORE &&
- ctx->Extensions.ARB_texture_buffer_object)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureBuffer");
+ if (buffer) {
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBuffer");
+ if (!bufObj)
+ return;
+ } else
+ bufObj = NULL;
+
+ /* Get the texture object by Name. */
+ texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBuffer");
+ if (!texObj)
return;
- }
- bufObj = _mesa_lookup_bufferobj(ctx, buffer);
- if (!bufObj && buffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureBuffer(buffer %u)",
- buffer);
+ if (!check_texture_buffer_target(ctx, texObj->Target, "glTextureBuffer"))
return;
+
+ _mesa_texture_buffer_range(ctx, texObj, internalFormat,
+ bufObj, 0, buffer ? -1 : 0, "glTextureBuffer");
+}
+
+void GLAPIENTRY
+_mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer,
+ GLintptr offset, GLsizeiptr size)
+{
+ struct gl_texture_object *texObj;
+ struct gl_buffer_object *bufObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (buffer) {
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
+ "glTextureBufferRange");
+ if (!bufObj)
+ return;
+
+ if (!check_texture_buffer_range(ctx, bufObj, offset, size,
+ "glTextureBufferRange"))
+ return;
+
+ } else {
+
+ /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer
+ * Textures (PDF page 254):
+ * "If buffer is zero, then any buffer object attached to the buffer
+ * texture is detached, the values offset and size are ignored and
+ * the state for offset and size for the buffer texture are reset to
+ * zero."
+ */
+ offset = 0;
+ size = 0;
+ bufObj = NULL;
}
/* Get the texture object by Name. */
- texObj = _mesa_lookup_texture_err(ctx, texture,
- "glTextureBuffer(texture)");
+ texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBufferRange");
if (!texObj)
return;
- if (texObj->Target != GL_TEXTURE_BUFFER_ARB) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTextureBuffer(target)");
+ if (!check_texture_buffer_target(ctx, texObj->Target,
+ "glTextureBufferRange"))
return;
- }
- _mesa_texture_buffer_range(ctx, texObj, texObj->Target, internalFormat,
- bufObj, 0, buffer ? -1 : 0, false, true);
+ _mesa_texture_buffer_range(ctx, texObj, internalFormat,
+ bufObj, offset, size, "glTextureBufferRange");
}
static GLboolean
diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h
index b7336bc6c..1eebaa8b6 100644
--- a/mesalib/src/mesa/main/teximage.h
+++ b/mesalib/src/mesa/main/teximage.h
@@ -181,13 +181,14 @@ _mesa_texture_sub_image(struct gl_context *ctx, GLuint dims,
extern void
_mesa_compressed_texture_sub_image(struct gl_context *ctx, GLuint dims,
struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint zoffset,
GLsizei width, GLsizei height,
GLsizei depth,
GLenum format, GLsizei imageSize,
- const GLvoid *data, bool dsa);
+ const GLvoid *data);
extern void
_mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims,
@@ -195,7 +196,8 @@ _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y,
- GLsizei width, GLsizei height, bool dsa);
+ GLsizei width, GLsizei height,
+ const char *caller);
extern void
_mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims,
@@ -208,11 +210,11 @@ _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims,
extern void
_mesa_texture_buffer_range(struct gl_context *ctx,
- struct gl_texture_object *texObj, GLenum target,
+ struct gl_texture_object *texObj,
GLenum internalFormat,
struct gl_buffer_object *bufObj,
- GLintptr offset, GLsizeiptr size, bool range,
- bool dsa);
+ GLintptr offset, GLsizeiptr size,
+ const char *caller);
/*@}*/
@@ -408,6 +410,10 @@ _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
extern void GLAPIENTRY
_mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer);
+extern void GLAPIENTRY
+_mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer,
+ GLintptr offset, GLsizeiptr size);
+
extern void GLAPIENTRY
_mesa_TexImage2DMultisample(GLenum target, GLsizei samples,
diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c
index a3e23ced5..ce678c864 100644
--- a/mesalib/src/mesa/main/transformfeedback.c
+++ b/mesalib/src/mesa/main/transformfeedback.c
@@ -762,7 +762,7 @@ _mesa_TransformFeedbackVaryings(GLuint program, GLsizei count,
/* Save the new names and the count */
for (i = 0; i < count; i++) {
- shProg->TransformFeedback.VaryingNames[i] = _mesa_strdup(varyings[i]);
+ shProg->TransformFeedback.VaryingNames[i] = strdup(varyings[i]);
}
shProg->TransformFeedback.NumVarying = count;
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index 9f82de952..2ab5528c3 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -260,8 +260,8 @@ validate_uniform_parameters(struct gl_context *ctx,
if (uni->array_elements == 0) {
if (count > 1) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(count > 1 for non-array, location=%d)",
- caller, location);
+ "%s(count = %u for non-array \"%s\"@%d)",
+ caller, count, uni->name, location);
return NULL;
}
@@ -601,6 +601,46 @@ _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni,
}
}
+
+/**
+ * Return printable string for a given GLSL_TYPE_x
+ */
+static const char *
+glsl_type_name(enum glsl_base_type type)
+{
+ switch (type) {
+ case GLSL_TYPE_UINT:
+ return "uint";
+ case GLSL_TYPE_INT:
+ return "int";
+ case GLSL_TYPE_FLOAT:
+ return "float";
+ case GLSL_TYPE_DOUBLE:
+ return "double";
+ case GLSL_TYPE_BOOL:
+ return "bool";
+ case GLSL_TYPE_SAMPLER:
+ return "sampler";
+ case GLSL_TYPE_IMAGE:
+ return "image";
+ case GLSL_TYPE_ATOMIC_UINT:
+ return "atomic_uint";
+ case GLSL_TYPE_STRUCT:
+ return "struct";
+ case GLSL_TYPE_INTERFACE:
+ return "interface";
+ case GLSL_TYPE_ARRAY:
+ return "array";
+ case GLSL_TYPE_VOID:
+ return "void";
+ case GLSL_TYPE_ERROR:
+ return "error";
+ default:
+ return "other";
+ }
+}
+
+
/**
* Called via glUniform*() functions.
*/
@@ -620,11 +660,28 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
if (uni == NULL)
return;
+ if (uni->type->is_matrix()) {
+ /* Can't set matrix uniforms (like mat4) with glUniform */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniform%u(uniform \"%s\"@%d is matrix)",
+ src_components, uni->name, location);
+ return;
+ }
+
/* Verify that the types are compatible.
*/
const unsigned components = uni->type->is_sampler()
? 1 : uni->type->vector_elements;
+ if (components != src_components) {
+ /* glUniformN() must match float/vecN type */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniform%u(\"%s\"@%u has %u components, not %u)",
+ src_components, uni->name, location,
+ components, src_components);
+ return;
+ }
+
bool match;
switch (uni->type->base_type) {
case GLSL_TYPE_BOOL:
@@ -639,8 +696,12 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
break;
}
- if (uni->type->is_matrix() || components != src_components || !match) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
+ if (!match) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniform%u(\"%s\"@%d is %s, not %s)",
+ src_components, uni->name, location,
+ glsl_type_name(uni->type->base_type),
+ glsl_type_name(basicType));
return;
}