X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fmarshal.c;h=b2935f63753aa0486ea172b94ab6ca36155e6717;hb=57a9c1ee478c5af8cc2f9ffe78b24917deebb1b3;hp=ae4efb5ecbb76465d8a020ed3c03545fe042cf76;hpb=bdb53e240ba70b24263bd1e5fb7d24c12b804016;p=mesa.git diff --git a/src/mesa/main/marshal.c b/src/mesa/main/marshal.c index ae4efb5ecbb..b2935f63753 100644 --- a/src/mesa/main/marshal.c +++ b/src/mesa/main/marshal.c @@ -31,80 +31,19 @@ #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) -{ - CALL_Flush(ctx->CurrentServerDispatch, ()); -} - - -void GLAPIENTRY -_mesa_marshal_Flush(void) +static inline void +_mesa_post_marshal_hook(struct gl_context *ctx) { - 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; @@ -132,7 +71,7 @@ _mesa_unmarshal_ShaderSource(struct gl_context *ctx, } CALL_ShaderSource(ctx->CurrentServerDispatch, (cmd->shader, cmd->count, string, cmd_length)); - free(string); + free((void *)string); } @@ -172,7 +111,7 @@ _mesa_marshal_ShaderSource(GLuint shader, GLsizei count, 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); @@ -197,15 +136,6 @@ _mesa_marshal_ShaderSource(GLuint shader, GLsizei count, } -/* 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 @@ -229,8 +159,8 @@ struct marshal_cmd_BindBufferBase * 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; @@ -243,61 +173,26 @@ track_vbo_binding(struct gl_context *ctx, GLenum target, GLuint buffer) * 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] */ }; @@ -305,63 +200,123 @@ void _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)); + 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 { + CALL_BufferData(ctx->CurrentServerDispatch, + (target_or_name, size, data, usage)); + } } -void GLAPIENTRY -_mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data, - GLenum usage) +void +_mesa_unmarshal_NamedBufferData(struct gl_context *ctx, + const struct marshal_cmd_BufferData *cmd) +{ + unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData"); +} + +void +_mesa_unmarshal_NamedBufferDataEXT(struct gl_context *ctx, + const struct marshal_cmd_BufferData *cmd) +{ + unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData"); +} + +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_BufferData) + (data ? size : 0); + 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"); - if (unlikely(size < 0)) { - _mesa_glthread_finish(ctx); - _mesa_error(ctx, GL_INVALID_VALUE, "BufferData(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_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); - } else { - _mesa_glthread_finish(ctx); - CALL_BufferData(ctx->CurrentServerDispatch, - (target, size, data, usage)); + 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); +} + +void GLAPIENTRY +_mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data, + GLenum 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) +{ + _mesa_marshal_BufferData_merged(buffer, size, data, usage, true, false, + "NamedBufferData"); +} + +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"); +} + + /* BufferSubData: marshalled asynchronously */ struct marshal_cmd_BufferSubData { struct marshal_cmd_base cmd_base; - GLenum target; + GLenum target_or_name; GLintptr offset; GLsizeiptr size; + bool named; + bool ext_dsa; /* Next size bytes are GLubyte data[size] */ }; @@ -369,117 +324,94 @@ void _mesa_unmarshal_BufferSubData(struct gl_context *ctx, const struct marshal_cmd_BufferSubData *cmd) { - const GLenum target = cmd->target; + const GLenum target_or_name = cmd->target_or_name; 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)); -} - -void GLAPIENTRY -_mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, - const GLvoid * data) -{ - GET_CURRENT_CONTEXT(ctx); - size_t cmd_size = sizeof(struct marshal_cmd_BufferSubData) + size; - - debug_print_marshal("BufferSubData"); - if (unlikely(size < 0)) { - _mesa_glthread_finish(ctx); - _mesa_error(ctx, GL_INVALID_VALUE, "BufferSubData(size < 0)"); - 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; - char *variable_data = (char *) (cmd + 1); - memcpy(variable_data, data, size); - _mesa_post_marshal_hook(ctx); + if (cmd->ext_dsa) { + CALL_NamedBufferSubDataEXT(ctx->CurrentServerDispatch, + (target_or_name, offset, size, data)); + } else if (cmd->named) { + CALL_NamedBufferSubData(ctx->CurrentServerDispatch, + (target_or_name, offset, size, data)); } else { - _mesa_glthread_finish(ctx); CALL_BufferSubData(ctx->CurrentServerDispatch, - (target, offset, size, data)); + (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"); } -#endif +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"); +} + +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"); +}