1/* 2 * Copyright © 2012 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24/** \file marshal.h 25 * 26 * Declarations of functions related to marshalling GL calls from a client 27 * thread to a server thread. 28 */ 29 30#ifndef MARSHAL_H 31#define MARSHAL_H 32 33#include "main/glthread.h" 34#include "main/context.h" 35#include "main/macros.h" 36 37struct marshal_cmd_base 38{ 39 /** 40 * Type of command. See enum marshal_dispatch_cmd_id. 41 */ 42 uint16_t cmd_id; 43 44 /** 45 * Size of command, in multiples of 4 bytes, including cmd_base. 46 */ 47 uint16_t cmd_size; 48}; 49 50static inline void * 51_mesa_glthread_allocate_command(struct gl_context *ctx, 52 uint16_t cmd_id, 53 size_t size) 54{ 55 struct glthread_state *glthread = ctx->GLThread; 56 struct glthread_batch *next = &glthread->batches[glthread->next]; 57 struct marshal_cmd_base *cmd_base; 58 const size_t aligned_size = ALIGN(size, 8); 59 60 if (unlikely(next->used + size > MARSHAL_MAX_CMD_SIZE)) { 61 _mesa_glthread_flush_batch(ctx); 62 next = &glthread->batches[glthread->next]; 63 } 64 65 cmd_base = (struct marshal_cmd_base *)&next->buffer[next->used]; 66 next->used += aligned_size; 67 cmd_base->cmd_id = cmd_id; 68 cmd_base->cmd_size = aligned_size; 69 return cmd_base; 70} 71 72/** 73 * Instead of conditionally handling marshaling previously-bound user vertex 74 * array data in draw calls (deprecated and removed in GL core), we just 75 * disable threading at the point where the user sets a user vertex array. 76 */ 77static inline bool 78_mesa_glthread_is_non_vbo_vertex_attrib_pointer(const struct gl_context *ctx) 79{ 80 struct glthread_state *glthread = ctx->GLThread; 81 82 return ctx->API != API_OPENGL_CORE && !glthread->vertex_array_is_vbo; 83} 84 85/** 86 * Instead of conditionally handling marshaling immediate index data in draw 87 * calls (deprecated and removed in GL core), we just disable threading. 88 */ 89static inline bool 90_mesa_glthread_is_non_vbo_draw_elements(const struct gl_context *ctx) 91{ 92 struct glthread_state *glthread = ctx->GLThread; 93 94 return ctx->API != API_OPENGL_CORE && !glthread->element_array_is_vbo; 95} 96 97#define DEBUG_MARSHAL_PRINT_CALLS 0 98 99/** 100 * This is printed when we have fallen back to a sync. This can happen when 101 * MARSHAL_MAX_CMD_SIZE is exceeded. 102 */ 103static inline void 104debug_print_sync_fallback(const char *func) 105{ 106#if DEBUG_MARSHAL_PRINT_CALLS 107 printf("fallback to sync: %s\n", func); 108#endif 109} 110 111 112static inline void 113debug_print_sync(const char *func) 114{ 115#if DEBUG_MARSHAL_PRINT_CALLS 116 printf("sync: %s\n", func); 117#endif 118} 119 120static inline void 121debug_print_marshal(const char *func) 122{ 123#if DEBUG_MARSHAL_PRINT_CALLS 124 printf("marshal: %s\n", func); 125#endif 126} 127 128static inline void 129debug_print_unmarshal(const char *func) 130{ 131#if DEBUG_MARSHAL_PRINT_CALLS 132 printf("unmarshal: %s\n", func); 133#endif 134} 135 136struct _glapi_table * 137_mesa_create_marshal_table(const struct gl_context *ctx); 138 139size_t 140_mesa_unmarshal_dispatch_cmd(struct gl_context *ctx, const void *cmd); 141 142static inline void 143_mesa_post_marshal_hook(struct gl_context *ctx) 144{ 145 /* This can be enabled for debugging whether a failure is a synchronization 146 * problem between the main thread and the worker thread, or a failure in 147 * how we actually marshal. 148 */ 149 if (false) 150 _mesa_glthread_finish(ctx); 151} 152 153 154/** 155 * Checks whether we're on a compat context for code-generated 156 * glBindVertexArray(). 157 * 158 * In order to decide whether a draw call uses only VBOs for vertex and index 159 * buffers, we track the current vertex and index buffer bindings by 160 * glBindBuffer(). However, the index buffer binding is stored in the vertex 161 * array as opposed to the context. If we were to accurately track whether 162 * the index buffer was a user pointer ot not, we'd have to track it per 163 * vertex array, which would mean synchronizing with the client thread and 164 * looking into the hash table to find the actual vertex array object. That's 165 * more tracking than we'd like to do in the main thread, if possible. 166 * 167 * Instead, just punt for now and disable threading on apps using vertex 168 * arrays and compat contexts. Apps using vertex arrays can probably use a 169 * core context. 170 */ 171static inline bool 172_mesa_glthread_is_compat_bind_vertex_array(const struct gl_context *ctx) 173{ 174 return ctx->API != API_OPENGL_CORE; 175} 176 177struct marshal_cmd_Enable; 178struct marshal_cmd_ShaderSource; 179struct marshal_cmd_Flush; 180struct marshal_cmd_BindBuffer; 181struct marshal_cmd_BufferData; 182struct marshal_cmd_BufferSubData; 183struct marshal_cmd_NamedBufferData; 184struct marshal_cmd_NamedBufferSubData; 185struct marshal_cmd_ClearBuffer; 186#define marshal_cmd_ClearBufferfv marshal_cmd_ClearBuffer 187#define marshal_cmd_ClearBufferiv marshal_cmd_ClearBuffer 188#define marshal_cmd_ClearBufferuiv marshal_cmd_ClearBuffer 189#define marshal_cmd_ClearBufferfi marshal_cmd_ClearBuffer 190 191void 192_mesa_unmarshal_Enable(struct gl_context *ctx, 193 const struct marshal_cmd_Enable *cmd); 194 195void GLAPIENTRY 196_mesa_marshal_Enable(GLenum cap); 197 198void GLAPIENTRY 199_mesa_marshal_ShaderSource(GLuint shader, GLsizei count, 200 const GLchar * const *string, const GLint *length); 201 202void 203_mesa_unmarshal_ShaderSource(struct gl_context *ctx, 204 const struct marshal_cmd_ShaderSource *cmd); 205 206void GLAPIENTRY 207_mesa_marshal_Flush(void); 208 209void 210_mesa_unmarshal_Flush(struct gl_context *ctx, 211 const struct marshal_cmd_Flush *cmd); 212 213void GLAPIENTRY 214_mesa_marshal_BindBuffer(GLenum target, GLuint buffer); 215 216void 217_mesa_unmarshal_BindBuffer(struct gl_context *ctx, 218 const struct marshal_cmd_BindBuffer *cmd); 219 220void 221_mesa_unmarshal_BufferData(struct gl_context *ctx, 222 const struct marshal_cmd_BufferData *cmd); 223 224void GLAPIENTRY 225_mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data, 226 GLenum usage); 227 228void 229_mesa_unmarshal_BufferSubData(struct gl_context *ctx, 230 const struct marshal_cmd_BufferSubData *cmd); 231 232void GLAPIENTRY 233_mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, 234 const GLvoid * data); 235 236void 237_mesa_unmarshal_NamedBufferData(struct gl_context *ctx, 238 const struct marshal_cmd_NamedBufferData *cmd); 239 240void GLAPIENTRY 241_mesa_marshal_NamedBufferData(GLuint buffer, GLsizeiptr size, 242 const GLvoid * data, GLenum usage); 243 244void 245_mesa_unmarshal_NamedBufferSubData(struct gl_context *ctx, 246 const struct marshal_cmd_NamedBufferSubData *cmd); 247 248void GLAPIENTRY 249_mesa_marshal_NamedBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size, 250 const GLvoid * data); 251 252void 253_mesa_unmarshal_ClearBufferfv(struct gl_context *ctx, 254 const struct marshal_cmd_ClearBuffer *cmd); 255 256void GLAPIENTRY 257_mesa_marshal_ClearBufferfv(GLenum buffer, GLint drawbuffer, 258 const GLfloat *value); 259 260void 261_mesa_unmarshal_ClearBufferiv(struct gl_context *ctx, 262 const struct marshal_cmd_ClearBuffer *cmd); 263 264void GLAPIENTRY 265_mesa_marshal_ClearBufferiv(GLenum buffer, GLint drawbuffer, 266 const GLint *value); 267 268void 269_mesa_unmarshal_ClearBufferuiv(struct gl_context *ctx, 270 const struct marshal_cmd_ClearBuffer *cmd); 271 272void GLAPIENTRY 273_mesa_marshal_ClearBufferuiv(GLenum buffer, GLint drawbuffer, 274 const GLuint *value); 275 276void 277_mesa_unmarshal_ClearBufferfi(struct gl_context *ctx, 278 const struct marshal_cmd_ClearBuffer *cmd); 279 280void GLAPIENTRY 281_mesa_marshal_ClearBufferfi(GLenum buffer, GLint drawbuffer, 282 const GLfloat depth, const GLint stencil); 283 284#endif /* MARSHAL_H */ 285