#include "main/macros.h"
#include "marshal.h"
#include "dispatch.h"
-#include "marshal_generated.h"
-#ifdef HAVE_PTHREAD
-
-struct marshal_cmd_Flush
-{
- struct marshal_cmd_base cmd_base;
-};
-
-
-void
-_mesa_unmarshal_Flush(struct gl_context *ctx,
- const struct marshal_cmd_Flush *cmd)
+static inline void
+_mesa_post_marshal_hook(struct gl_context *ctx)
{
- CALL_Flush(ctx->CurrentServerDispatch, ());
-}
-
-
-void GLAPIENTRY
-_mesa_marshal_Flush(void)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct marshal_cmd_Flush *cmd =
- _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_Flush,
- sizeof(struct marshal_cmd_Flush));
- (void) cmd;
- _mesa_post_marshal_hook(ctx);
-
- /* Flush() needs to be handled specially. In addition to telling the
- * background thread to flush, we need to ensure that our own buffer is
- * submitted to the background thread so that it will complete in a finite
- * amount of time.
+ /* This can be enabled for debugging whether a failure is a synchronization
+ * problem between the main thread and the worker thread, or a failure in
+ * how we actually marshal.
*/
- _mesa_glthread_flush_batch(ctx);
-}
-
-/* Enable: marshalled asynchronously */
-struct marshal_cmd_Enable
-{
- struct marshal_cmd_base cmd_base;
- GLenum cap;
-};
-
-void
-_mesa_unmarshal_Enable(struct gl_context *ctx,
- const struct marshal_cmd_Enable *cmd)
-{
- const GLenum cap = cmd->cap;
- CALL_Enable(ctx->CurrentServerDispatch, (cap));
-}
-
-void GLAPIENTRY
-_mesa_marshal_Enable(GLenum cap)
-{
- GET_CURRENT_CONTEXT(ctx);
- struct marshal_cmd_Enable *cmd;
- debug_print_marshal("Enable");
-
- if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) {
+ if (false)
_mesa_glthread_finish(ctx);
- _mesa_glthread_restore_dispatch(ctx);
- } else {
- cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_Enable,
- sizeof(*cmd));
- cmd->cap = cap;
- _mesa_post_marshal_hook(ctx);
- return;
- }
-
- _mesa_glthread_finish(ctx);
- debug_print_sync_fallback("Enable");
- CALL_Enable(ctx->CurrentServerDispatch, (cap));
}
+
struct marshal_cmd_ShaderSource
{
struct marshal_cmd_base cmd_base;
}
CALL_ShaderSource(ctx->CurrentServerDispatch,
(cmd->shader, cmd->count, string, cmd_length));
- free(string);
+ free((void *)string);
}
measure_ShaderSource_strings(count, string, length, length_tmp);
size_t total_cmd_size = fixed_cmd_size + length_size + total_string_length;
- if (total_cmd_size <= MARSHAL_MAX_CMD_SIZE) {
+ if (total_cmd_size <= MARSHAL_MAX_CMD_SIZE && count > 0) {
struct marshal_cmd_ShaderSource *cmd =
_mesa_glthread_allocate_command(ctx, DISPATCH_CMD_ShaderSource,
total_cmd_size);
}
-/* BindBufferBase: marshalled asynchronously */
-struct marshal_cmd_BindBufferBase
-{
- struct marshal_cmd_base cmd_base;
- GLenum target;
- GLuint index;
- GLuint buffer;
-};
-
/** Tracks the current bindings for the vertex array and index array buffers.
*
* This is part of what we need to enable glthread on compat-GL contexts that
* feature that if you pass a bad name, it just gens a buffer object for you,
* so we escape without having to know if things are valid or not.
*/
-static void
-track_vbo_binding(struct gl_context *ctx, GLenum target, GLuint buffer)
+void
+_mesa_glthread_BindBuffer(struct gl_context *ctx, GLenum target, GLuint buffer)
{
struct glthread_state *glthread = ctx->GLThread;
* vertex array object instead of the context, so this would need to
* change on vertex array object updates.
*/
- glthread->element_array_is_vbo = (buffer != 0);
+ glthread->CurrentVAO->IndexBufferIsUserPointer = buffer != 0;
+ break;
+ case GL_DRAW_INDIRECT_BUFFER:
+ glthread->draw_indirect_buffer_is_vbo = buffer != 0;
break;
}
}
-struct marshal_cmd_BindBuffer
-{
- struct marshal_cmd_base cmd_base;
- GLenum target;
- GLuint buffer;
-};
-
-/**
- * This is just like the code-generated glBindBuffer() support, except that we
- * call track_vbo_binding().
- */
-void
-_mesa_unmarshal_BindBuffer(struct gl_context *ctx,
- const struct marshal_cmd_BindBuffer *cmd)
-{
- const GLenum target = cmd->target;
- const GLuint buffer = cmd->buffer;
- CALL_BindBuffer(ctx->CurrentServerDispatch, (target, buffer));
-}
-void GLAPIENTRY
-_mesa_marshal_BindBuffer(GLenum target, GLuint buffer)
-{
- GET_CURRENT_CONTEXT(ctx);
- size_t cmd_size = sizeof(struct marshal_cmd_BindBuffer);
- struct marshal_cmd_BindBuffer *cmd;
- debug_print_marshal("BindBuffer");
-
- track_vbo_binding(ctx, target, buffer);
-
- if (cmd_size <= MARSHAL_MAX_CMD_SIZE) {
- cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BindBuffer,
- cmd_size);
- cmd->target = target;
- cmd->buffer = buffer;
- _mesa_post_marshal_hook(ctx);
- } else {
- _mesa_glthread_finish(ctx);
- CALL_BindBuffer(ctx->CurrentServerDispatch, (target, buffer));
- }
-}
-
/* BufferData: marshalled asynchronously */
struct marshal_cmd_BufferData
{
struct marshal_cmd_base cmd_base;
- GLenum target;
+ GLuint target_or_name;
GLsizeiptr size;
GLenum usage;
+ const GLvoid *data_external_mem;
bool data_null; /* If set, no data follows for "data" */
+ bool named;
+ bool ext_dsa;
/* Next size bytes are GLubyte data[size] */
};
_mesa_unmarshal_BufferData(struct gl_context *ctx,
const struct marshal_cmd_BufferData *cmd)
{
- const GLenum target = cmd->target;
- const GLsizeiptr size = cmd->size;
+ const GLuint target_or_name = cmd->target_or_name;
+ const GLsizei size = cmd->size;
const GLenum usage = cmd->usage;
const void *data;
if (cmd->data_null)
data = NULL;
+ else if (!cmd->named && target_or_name == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD)
+ data = cmd->data_external_mem;
else
data = (const void *) (cmd + 1);
- CALL_BufferData(ctx->CurrentServerDispatch, (target, size, data, usage));
-}
-
-void GLAPIENTRY
-_mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data,
- GLenum usage)
-{
- GET_CURRENT_CONTEXT(ctx);
- size_t cmd_size =
- sizeof(struct marshal_cmd_BufferData) + (data ? size : 0);
- debug_print_marshal("BufferData");
-
- if (unlikely(size < 0)) {
- _mesa_glthread_finish(ctx);
- _mesa_error(ctx, GL_INVALID_VALUE, "BufferData(size < 0)");
- return;
- }
-
- if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD &&
- cmd_size <= MARSHAL_MAX_CMD_SIZE) {
- struct marshal_cmd_BufferData *cmd =
- _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferData,
- cmd_size);
-
- cmd->target = target;
- cmd->size = size;
- cmd->usage = usage;
- cmd->data_null = !data;
- if (data) {
- char *variable_data = (char *) (cmd + 1);
- memcpy(variable_data, data, size);
- }
- _mesa_post_marshal_hook(ctx);
+ if (cmd->ext_dsa) {
+ CALL_NamedBufferDataEXT(ctx->CurrentServerDispatch,
+ (target_or_name, size, data, usage));
+ } else if (cmd->named) {
+ CALL_NamedBufferData(ctx->CurrentServerDispatch,
+ (target_or_name, size, data, usage));
} else {
- _mesa_glthread_finish(ctx);
CALL_BufferData(ctx->CurrentServerDispatch,
- (target, size, data, usage));
+ (target_or_name, size, data, usage));
}
}
-/* BufferSubData: marshalled asynchronously */
-struct marshal_cmd_BufferSubData
+void
+_mesa_unmarshal_NamedBufferData(struct gl_context *ctx,
+ const struct marshal_cmd_BufferData *cmd)
{
- struct marshal_cmd_base cmd_base;
- GLenum target;
- GLintptr offset;
- GLsizeiptr size;
- /* Next size bytes are GLubyte data[size] */
-};
+ unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData");
+}
void
-_mesa_unmarshal_BufferSubData(struct gl_context *ctx,
- const struct marshal_cmd_BufferSubData *cmd)
+_mesa_unmarshal_NamedBufferDataEXT(struct gl_context *ctx,
+ const struct marshal_cmd_BufferData *cmd)
{
- const GLenum target = cmd->target;
- const GLintptr offset = cmd->offset;
- const GLsizeiptr size = cmd->size;
- const void *data = (const void *) (cmd + 1);
-
- CALL_BufferSubData(ctx->CurrentServerDispatch,
- (target, offset, size, data));
+ unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData");
}
-void GLAPIENTRY
-_mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
- const GLvoid * data)
+static void
+_mesa_marshal_BufferData_merged(GLuint target_or_name, GLsizeiptr size,
+ const GLvoid *data, GLenum usage, bool named,
+ bool ext_dsa, const char *func)
{
GET_CURRENT_CONTEXT(ctx);
- size_t cmd_size = sizeof(struct marshal_cmd_BufferSubData) + size;
+ bool external_mem = !named &&
+ target_or_name == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD;
+ bool copy_data = data && !external_mem;
+ int cmd_size = sizeof(struct marshal_cmd_BufferData) + (copy_data ? size : 0);
+ debug_print_marshal("BufferData");
- debug_print_marshal("BufferSubData");
- if (unlikely(size < 0)) {
- _mesa_glthread_finish(ctx);
- _mesa_error(ctx, GL_INVALID_VALUE, "BufferSubData(size < 0)");
+ if (unlikely(size < 0 || size > INT_MAX || cmd_size < 0 ||
+ cmd_size > MARSHAL_MAX_CMD_SIZE ||
+ (named && target_or_name == 0))) {
+ _mesa_glthread_finish_before(ctx, func);
+ if (named) {
+ CALL_NamedBufferData(ctx->CurrentServerDispatch,
+ (target_or_name, size, data, usage));
+ } else {
+ CALL_BufferData(ctx->CurrentServerDispatch,
+ (target_or_name, size, data, usage));
+ }
return;
}
- if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD &&
- cmd_size <= MARSHAL_MAX_CMD_SIZE) {
- struct marshal_cmd_BufferSubData *cmd =
- _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferSubData,
- cmd_size);
- cmd->target = target;
- cmd->offset = offset;
- cmd->size = size;
+ struct marshal_cmd_BufferData *cmd =
+ _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferData,
+ cmd_size);
+
+ cmd->target_or_name = target_or_name;
+ cmd->size = size;
+ cmd->usage = usage;
+ cmd->data_null = !data;
+ cmd->named = named;
+ cmd->ext_dsa = ext_dsa;
+ cmd->data_external_mem = data;
+
+ if (copy_data) {
char *variable_data = (char *) (cmd + 1);
memcpy(variable_data, data, size);
- _mesa_post_marshal_hook(ctx);
- } else {
- _mesa_glthread_finish(ctx);
- CALL_BufferSubData(ctx->CurrentServerDispatch,
- (target, offset, size, data));
}
+ _mesa_post_marshal_hook(ctx);
}
-/* NamedBufferData: marshalled asynchronously */
-struct marshal_cmd_NamedBufferData
-{
- struct marshal_cmd_base cmd_base;
- GLuint name;
- GLsizei size;
- GLenum usage;
- /* Next size bytes are GLubyte data[size] */
-};
-
-void
-_mesa_unmarshal_NamedBufferData(struct gl_context *ctx,
- const struct marshal_cmd_NamedBufferData *cmd)
+void GLAPIENTRY
+_mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data,
+ GLenum usage)
{
- const GLuint name = cmd->name;
- const GLsizei size = cmd->size;
- const GLenum usage = cmd->usage;
- const void *data = (const void *) (cmd + 1);
-
- CALL_NamedBufferData(ctx->CurrentServerDispatch,
- (name, size, data, usage));
+ _mesa_marshal_BufferData_merged(target, size, data, usage, false, false,
+ "BufferData");
}
void GLAPIENTRY
_mesa_marshal_NamedBufferData(GLuint buffer, GLsizeiptr size,
const GLvoid * data, GLenum usage)
{
- GET_CURRENT_CONTEXT(ctx);
- size_t cmd_size = sizeof(struct marshal_cmd_NamedBufferData) + size;
-
- debug_print_marshal("NamedBufferData");
- if (unlikely(size < 0)) {
- _mesa_glthread_finish(ctx);
- _mesa_error(ctx, GL_INVALID_VALUE, "NamedBufferData(size < 0)");
- return;
- }
+ _mesa_marshal_BufferData_merged(buffer, size, data, usage, true, false,
+ "NamedBufferData");
+}
- if (buffer > 0 && cmd_size <= MARSHAL_MAX_CMD_SIZE) {
- struct marshal_cmd_NamedBufferData *cmd =
- _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_NamedBufferData,
- cmd_size);
- cmd->name = buffer;
- cmd->size = size;
- cmd->usage = usage;
- char *variable_data = (char *) (cmd + 1);
- memcpy(variable_data, data, size);
- _mesa_post_marshal_hook(ctx);
- } else {
- _mesa_glthread_finish(ctx);
- CALL_NamedBufferData(ctx->CurrentServerDispatch,
- (buffer, size, data, usage));
- }
+void GLAPIENTRY
+_mesa_marshal_NamedBufferDataEXT(GLuint buffer, GLsizeiptr size,
+ const GLvoid *data, GLenum usage)
+{
+ _mesa_marshal_BufferData_merged(buffer, size, data, usage, true, true,
+ "NamedBufferDataEXT");
}
-/* NamedBufferSubData: marshalled asynchronously */
-struct marshal_cmd_NamedBufferSubData
+
+/* BufferSubData: marshalled asynchronously */
+struct marshal_cmd_BufferSubData
{
struct marshal_cmd_base cmd_base;
- GLuint name;
+ GLenum target_or_name;
GLintptr offset;
- GLsizei size;
+ GLsizeiptr size;
+ bool named;
+ bool ext_dsa;
/* Next size bytes are GLubyte data[size] */
};
void
-_mesa_unmarshal_NamedBufferSubData(struct gl_context *ctx,
- const struct marshal_cmd_NamedBufferSubData *cmd)
+_mesa_unmarshal_BufferSubData(struct gl_context *ctx,
+ const struct marshal_cmd_BufferSubData *cmd)
{
- const GLuint name = cmd->name;
+ const GLenum target_or_name = cmd->target_or_name;
const GLintptr offset = cmd->offset;
- const GLsizei size = cmd->size;
+ const GLsizeiptr size = cmd->size;
const void *data = (const void *) (cmd + 1);
- CALL_NamedBufferSubData(ctx->CurrentServerDispatch,
- (name, offset, size, data));
-}
-
-void GLAPIENTRY
-_mesa_marshal_NamedBufferSubData(GLuint buffer, GLintptr offset,
- GLsizeiptr size, const GLvoid * data)
-{
- GET_CURRENT_CONTEXT(ctx);
- size_t cmd_size = sizeof(struct marshal_cmd_NamedBufferSubData) + size;
-
- debug_print_marshal("NamedBufferSubData");
- if (unlikely(size < 0)) {
- _mesa_glthread_finish(ctx);
- _mesa_error(ctx, GL_INVALID_VALUE, "NamedBufferSubData(size < 0)");
- return;
- }
-
- if (buffer > 0 && cmd_size <= MARSHAL_MAX_CMD_SIZE) {
- struct marshal_cmd_NamedBufferSubData *cmd =
- _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_NamedBufferSubData,
- cmd_size);
- cmd->name = buffer;
- cmd->offset = offset;
- cmd->size = size;
- char *variable_data = (char *) (cmd + 1);
- memcpy(variable_data, data, size);
- _mesa_post_marshal_hook(ctx);
- } else {
- _mesa_glthread_finish(ctx);
+ if (cmd->ext_dsa) {
+ CALL_NamedBufferSubDataEXT(ctx->CurrentServerDispatch,
+ (target_or_name, offset, size, data));
+ } else if (cmd->named) {
CALL_NamedBufferSubData(ctx->CurrentServerDispatch,
- (buffer, offset, size, data));
+ (target_or_name, offset, size, data));
+ } else {
+ CALL_BufferSubData(ctx->CurrentServerDispatch,
+ (target_or_name, offset, size, data));
}
}
-/* ClearBufferfv: marshalled asynchronously */
-struct marshal_cmd_ClearBufferfv
+void
+_mesa_unmarshal_NamedBufferSubData(struct gl_context *ctx,
+ const struct marshal_cmd_BufferSubData *cmd)
{
- struct marshal_cmd_base cmd_base;
- GLenum buffer;
- GLint drawbuffer;
-};
+ unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData");
+}
void
-_mesa_unmarshal_ClearBufferfv(struct gl_context *ctx,
- const struct marshal_cmd_ClearBufferfv *cmd)
+_mesa_unmarshal_NamedBufferSubDataEXT(struct gl_context *ctx,
+ const struct marshal_cmd_BufferSubData *cmd)
{
- const GLenum buffer = cmd->buffer;
- const GLint drawbuffer = cmd->drawbuffer;
- const char *variable_data = (const char *) (cmd + 1);
- const GLfloat *value = (const GLfloat *) variable_data;
-
- CALL_ClearBufferfv(ctx->CurrentServerDispatch,
- (buffer, drawbuffer, value));
+ unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData");
}
-void GLAPIENTRY
-_mesa_marshal_ClearBufferfv(GLenum buffer, GLint drawbuffer,
- const GLfloat *value)
+static void
+_mesa_marshal_BufferSubData_merged(GLuint target_or_name, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data,
+ bool named, bool ext_dsa, const char *func)
{
GET_CURRENT_CONTEXT(ctx);
- debug_print_marshal("ClearBufferfv");
-
- size_t size;
- switch (buffer) {
- case GL_DEPTH:
- size = sizeof(GLfloat);
- break;
- case GL_COLOR:
- size = sizeof(GLfloat) * 4;
- break;
- default:
- _mesa_glthread_finish(ctx);
-
- /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
- * of the OpenGL 4.5 spec states:
- *
- * "An INVALID_ENUM error is generated by ClearBufferfv and
- * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
- */
- _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
- _mesa_enum_to_string(buffer));
+ size_t cmd_size = sizeof(struct marshal_cmd_BufferSubData) + size;
+ debug_print_marshal(func);
+
+ if (unlikely(size < 0 || size > INT_MAX || cmd_size < 0 ||
+ cmd_size > MARSHAL_MAX_CMD_SIZE || !data ||
+ (named && target_or_name == 0))) {
+ _mesa_glthread_finish_before(ctx, func);
+ if (named) {
+ CALL_NamedBufferSubData(ctx->CurrentServerDispatch,
+ (target_or_name, offset, size, data));
+ } else {
+ CALL_BufferSubData(ctx->CurrentServerDispatch,
+ (target_or_name, offset, size, data));
+ }
return;
}
- size_t cmd_size = sizeof(struct marshal_cmd_ClearBufferfv) + size;
- if (cmd_size <= MARSHAL_MAX_CMD_SIZE) {
- struct marshal_cmd_ClearBufferfv *cmd =
- _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_ClearBufferfv,
- cmd_size);
- cmd->buffer = buffer;
- cmd->drawbuffer = drawbuffer;
- GLfloat *variable_data = (GLfloat *) (cmd + 1);
- if (buffer == GL_COLOR)
- COPY_4V(variable_data, value);
- else
- *variable_data = *value;
+ struct marshal_cmd_BufferSubData *cmd =
+ _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferSubData,
+ cmd_size);
+ cmd->target_or_name = target_or_name;
+ cmd->offset = offset;
+ cmd->size = size;
+ cmd->named = named;
+ cmd->ext_dsa = ext_dsa;
+
+ char *variable_data = (char *) (cmd + 1);
+ memcpy(variable_data, data, size);
+ _mesa_post_marshal_hook(ctx);
+}
- _mesa_post_marshal_hook(ctx);
- } else {
- debug_print_sync("ClearBufferfv");
- _mesa_glthread_finish(ctx);
- CALL_ClearBufferfv(ctx->CurrentServerDispatch,
- (buffer, drawbuffer, value));
- }
+void GLAPIENTRY
+_mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
+ const GLvoid * data)
+{
+ _mesa_marshal_BufferSubData_merged(target, offset, size, data, false,
+ false, "BufferSubData");
+}
+
+void GLAPIENTRY
+_mesa_marshal_NamedBufferSubData(GLuint buffer, GLintptr offset,
+ GLsizeiptr size, const GLvoid * data)
+{
+ _mesa_marshal_BufferSubData_merged(buffer, offset, size, data, true,
+ false, "NamedBufferSubData");
}
-#endif
+void GLAPIENTRY
+_mesa_marshal_NamedBufferSubDataEXT(GLuint buffer, GLintptr offset,
+ GLsizeiptr size, const GLvoid * data)
+{
+ _mesa_marshal_BufferSubData_merged(buffer, offset, size, data, true,
+ true, "NamedBufferSubDataEXT");
+}