/* * Copyright © 2012 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #ifndef _GLTHREAD_H #define _GLTHREAD_H /* The size of one batch and the maximum size of one call. * * This should be as low as possible, so that: * - multiple synchronizations within a frame don't slow us down much * - a smaller number of calls per frame can still get decent parallelism * - the memory footprint of the queue is low, and with that comes a lower * chance of experiencing CPU cache thrashing * but it should be high enough so that u_queue overhead remains negligible. */ #define MARSHAL_MAX_CMD_BUFFER_SIZE (8 * 1024) /* We need to leave 1 slot at the end to insert the END marker for unmarshal * calls that look ahead to know where the batch ends. */ #define MARSHAL_MAX_CMD_SIZE (MARSHAL_MAX_CMD_BUFFER_SIZE - 8) /* The number of batch slots in memory. * * One batch is being executed, one batch is being filled, the rest are * waiting batches. There must be at least 1 slot for a waiting batch, * so the minimum number of batches is 3. */ #define MARSHAL_MAX_BATCHES 8 /* Special value for glEnableClientState(GL_PRIMITIVE_RESTART_NV). */ #define VERT_ATTRIB_PRIMITIVE_RESTART_NV -1 #include #include #include "util/u_queue.h" #include "compiler/shader_enums.h" #include "main/config.h" #include "main/hash.h" #include "util/glheader.h" #ifdef __cplusplus extern "C" { #endif struct gl_context; struct gl_buffer_object; struct _glapi_table; /** * Client pixel packing/unpacking attributes */ struct gl_pixelstore_attrib { GLint Alignment; GLint RowLength; GLint SkipPixels; GLint SkipRows; GLint ImageHeight; GLint SkipImages; GLboolean SwapBytes; GLboolean LsbFirst; GLboolean Invert; /**< GL_MESA_pack_invert */ GLint CompressedBlockWidth; /**< GL_ARB_compressed_texture_pixel_storage */ GLint CompressedBlockHeight; GLint CompressedBlockDepth; GLint CompressedBlockSize; struct gl_buffer_object *BufferObj; /**< GL_ARB_pixel_buffer_object */ }; /* Used by both glthread and gl_context. */ union gl_vertex_format_user { struct { GLenum16 Type; /**< datatype: GL_FLOAT, GL_INT, etc */ bool Bgra; /**< true if GL_BGRA, else GL_RGBA */ uint8_t Size:5; /**< components per element (1,2,3,4) */ bool Normalized:1; /**< GL_ARB_vertex_program */ bool Integer:1; /**< Integer-valued? */ bool Doubles:1; /**< double values are not converted to floats */ }; uint32_t All; }; #define MESA_PACK_VFORMAT(type, size, normalized, integer, doubles) \ (union gl_vertex_format_user){{ \ .Type = MIN2(type, 0xffff), /* 0xffff means invalid value */ \ .Bgra = size == GL_BGRA, \ .Size = size == GL_BGRA ? 4 : MIN2(size, 5), /* 5 means invalid value */ \ .Normalized = normalized, \ .Integer = integer, \ .Doubles = doubles \ }} struct glthread_attrib { /* Per attrib: */ uint8_t ElementSize; /**< max 32 */ uint8_t BufferIndex; /**< Referring to Attrib[BufferIndex]. */ uint16_t RelativeOffset; /**< max 0xffff in Mesa */ union gl_vertex_format_user Format; /* Per buffer binding: */ GLuint Divisor; int16_t Stride; /**< max 2048 */ int8_t EnabledAttribCount; /**< Number of enabled attribs using this buffer. */ const void *Pointer; }; struct glthread_vao { GLuint Name; GLuint CurrentElementBufferName; GLbitfield UserEnabled; /**< Vertex attribs enabled by the user. */ GLbitfield Enabled; /**< UserEnabled with POS vs GENERIC0 aliasing resolved. */ GLbitfield BufferEnabled; /**< "Enabled" converted to buffer bindings. */ GLbitfield BufferInterleaved; /**< Bitmask of buffers used by multiple attribs. */ GLbitfield UserPointerMask; /**< Bitmask of buffer bindings. */ GLbitfield NonNullPointerMask; /**< Bitmask of buffer bindings with non-NULL user pointers. */ GLbitfield NonZeroDivisorMask; /**< Bitmask of buffer bindings. */ struct glthread_attrib Attrib[VERT_ATTRIB_MAX]; }; /** A single batch of commands queued up for execution. */ struct glthread_batch { /** Batch fence for waiting for the execution to finish. */ struct util_queue_fence fence; /** The worker thread will access the context with this. */ struct gl_context *ctx; /** * Number of uint64_t elements filled already. * This is 0 when it's being filled because glthread::used holds the real * value temporarily, and glthread::used is copied to this variable when * the batch is submitted. */ unsigned used; /** Data contained in the command buffer. */ uint64_t buffer[MARSHAL_MAX_CMD_BUFFER_SIZE / 8]; }; struct glthread_client_attrib { struct glthread_vao VAO; GLuint CurrentArrayBufferName; int ClientActiveTexture; GLuint RestartIndex; bool PrimitiveRestart; bool PrimitiveRestartFixedIndex; /** Whether this element of the client attrib stack contains saved state. */ bool Valid; }; /* For glPushAttrib / glPopAttrib. */ struct glthread_attrib_node { GLbitfield Mask; int ActiveTexture; GLenum16 MatrixMode; bool Blend; bool CullFace; bool DepthTest; bool Lighting; bool PolygonStipple; }; typedef enum { M_MODELVIEW, M_PROJECTION, M_PROGRAM0, M_PROGRAM_LAST = M_PROGRAM0 + MAX_PROGRAM_MATRICES - 1, M_TEXTURE0, M_TEXTURE_LAST = M_TEXTURE0 + MAX_TEXTURE_UNITS - 1, M_DUMMY, /* used instead of reporting errors */ M_NUM_MATRIX_STACKS, } gl_matrix_index; struct glthread_state { /** Multithreaded queue. */ struct util_queue queue; /** This is sent to the driver for framebuffer overlay / HUD. */ struct util_queue_monitoring stats; /** Whether GLThread is enabled. */ bool enabled; bool inside_begin_end; bool thread_sched_enabled; /** Display lists. */ GLenum16 ListMode; /**< Zero if not inside display list, else list mode. */ unsigned ListBase; unsigned ListCallDepth; /** For L3 cache pinning. */ unsigned pin_thread_counter; unsigned thread_sched_state; /** The ring of batches in memory. */ struct glthread_batch batches[MARSHAL_MAX_BATCHES]; /** Pointer to the batch currently being filled. */ struct glthread_batch *next_batch; /** Index of the last submitted batch. */ unsigned last; /** Index of the batch being filled and about to be submitted. */ unsigned next; /** Number of uint64_t elements filled already. */ unsigned used; /** Upload buffer. */ struct gl_buffer_object *upload_buffer; uint8_t *upload_ptr; unsigned upload_offset; int upload_buffer_private_refcount; /** Primitive restart state. */ bool PrimitiveRestart; bool PrimitiveRestartFixedIndex; bool _PrimitiveRestart; GLuint RestartIndex; GLuint _RestartIndex[4]; /**< Restart index for index_size = 1,2,4. */ /** Vertex Array objects tracked by glthread independently of Mesa. */ struct _mesa_HashTable VAOs; struct glthread_vao *CurrentVAO; struct glthread_vao *LastLookedUpVAO; struct glthread_vao DefaultVAO; struct glthread_client_attrib ClientAttribStack[MAX_CLIENT_ATTRIB_STACK_DEPTH]; int ClientAttribStackTop; int ClientActiveTexture; /** Currently-bound buffer object IDs. */ GLuint CurrentArrayBufferName; GLuint CurrentDrawIndirectBufferName; GLuint CurrentPixelPackBufferName; GLuint CurrentPixelUnpackBufferName; GLuint CurrentQueryBufferName; /** * The batch index of the last occurence of glLinkProgram or * glDeleteProgram or -1 if there is no such enqueued call. */ int LastProgramChangeBatch; /** * The batch index of the last occurence of glEndList or * glDeleteLists or -1 if there is no such enqueued call. */ int LastDListChangeBatchIndex; /** Basic matrix state tracking. */ int ActiveTexture; GLenum16 MatrixMode; gl_matrix_index MatrixIndex; struct glthread_attrib_node AttribStack[MAX_ATTRIB_STACK_DEPTH]; int AttribStackDepth; int MatrixStackDepth[M_NUM_MATRIX_STACKS]; /** Enable states. */ bool Blend; bool DepthTest; bool CullFace; bool DebugOutputSynchronous; bool Lighting; bool PolygonStipple; GLuint CurrentDrawFramebuffer; GLuint CurrentReadFramebuffer; GLuint CurrentProgram; /** The last added call of the given function. */ struct marshal_cmd_CallList *LastCallList; struct marshal_cmd_BindBuffer *LastBindBuffer1; struct marshal_cmd_BindBuffer *LastBindBuffer2; /** Global mutex update info. */ unsigned GlobalLockUpdateBatchCounter; bool LockGlobalMutexes; struct gl_pixelstore_attrib Unpack; }; void _mesa_glthread_init(struct gl_context *ctx); void _mesa_glthread_destroy(struct gl_context *ctx); void _mesa_glthread_init_dispatch0(struct gl_context *ctx, struct _glapi_table *table); void _mesa_glthread_init_dispatch1(struct gl_context *ctx, struct _glapi_table *table); void _mesa_glthread_init_dispatch2(struct gl_context *ctx, struct _glapi_table *table); void _mesa_glthread_init_dispatch3(struct gl_context *ctx, struct _glapi_table *table); void _mesa_glthread_init_dispatch4(struct gl_context *ctx, struct _glapi_table *table); void _mesa_glthread_init_dispatch5(struct gl_context *ctx, struct _glapi_table *table); void _mesa_glthread_init_dispatch6(struct gl_context *ctx, struct _glapi_table *table); void _mesa_glthread_init_dispatch7(struct gl_context *ctx, struct _glapi_table *table); void _mesa_glthread_enable(struct gl_context *ctx); void _mesa_glthread_disable(struct gl_context *ctx); void _mesa_glthread_flush_batch(struct gl_context *ctx); void _mesa_glthread_finish(struct gl_context *ctx); void _mesa_glthread_finish_before(struct gl_context *ctx, const char *func); bool _mesa_glthread_invalidate_zsbuf(struct gl_context *ctx); void _mesa_glthread_release_upload_buffer(struct gl_context *ctx); void _mesa_glthread_upload(struct gl_context *ctx, const void *data, GLsizeiptr size, unsigned *out_offset, struct gl_buffer_object **out_buffer, uint8_t **out_ptr, unsigned start_offset); void _mesa_glthread_reset_vao(struct glthread_vao *vao); void _mesa_error_glthread_safe(struct gl_context *ctx, GLenum error, bool glthread, const char *format, ...); void _mesa_glthread_execute_list(struct gl_context *ctx, GLuint list); void _mesa_glthread_DeleteBuffers(struct gl_context *ctx, GLsizei n, const GLuint *buffers); void _mesa_glthread_BindVertexArray(struct gl_context *ctx, GLuint id); void _mesa_glthread_DeleteVertexArrays(struct gl_context *ctx, GLsizei n, const GLuint *ids); void _mesa_glthread_GenVertexArrays(struct gl_context *ctx, GLsizei n, GLuint *arrays); void _mesa_glthread_set_prim_restart(struct gl_context *ctx, GLenum cap, bool value); void _mesa_glthread_PrimitiveRestartIndex(struct gl_context *ctx, GLuint index); void _mesa_glthread_ClientState(struct gl_context *ctx, GLuint *vaobj, gl_vert_attrib attrib, bool enable); void _mesa_glthread_AttribDivisor(struct gl_context *ctx, const GLuint *vaobj, gl_vert_attrib attrib, GLuint divisor); void _mesa_glthread_AttribPointer(struct gl_context *ctx, gl_vert_attrib attrib, union gl_vertex_format_user format, GLsizei stride, const void *pointer); void _mesa_glthread_DSAAttribPointer(struct gl_context *ctx, GLuint vao, GLuint buffer, gl_vert_attrib attrib, union gl_vertex_format_user format, GLsizei stride, GLintptr offset); void _mesa_glthread_AttribFormat(struct gl_context *ctx, GLuint attribindex, union gl_vertex_format_user format, GLuint relativeoffset); void _mesa_glthread_DSAAttribFormat(struct gl_context *ctx, GLuint vaobj, GLuint attribindex, union gl_vertex_format_user format, GLuint relativeoffset); void _mesa_glthread_VertexBuffer(struct gl_context *ctx, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); void _mesa_glthread_DSAVertexBuffer(struct gl_context *ctx, GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); void _mesa_glthread_DSAVertexBuffers(struct gl_context *ctx, GLuint vaobj, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides); void _mesa_glthread_BindingDivisor(struct gl_context *ctx, GLuint bindingindex, GLuint divisor); void _mesa_glthread_DSABindingDivisor(struct gl_context *ctx, GLuint vaobj, GLuint bindingindex, GLuint divisor); void _mesa_glthread_AttribBinding(struct gl_context *ctx, GLuint attribindex, GLuint bindingindex); void _mesa_glthread_DSAAttribBinding(struct gl_context *ctx, GLuint vaobj, GLuint attribindex, GLuint bindingindex); void _mesa_glthread_DSAElementBuffer(struct gl_context *ctx, GLuint vaobj, GLuint buffer); void _mesa_glthread_PushClientAttrib(struct gl_context *ctx, GLbitfield mask, bool set_default); void _mesa_glthread_PopClientAttrib(struct gl_context *ctx); void _mesa_glthread_ClientAttribDefault(struct gl_context *ctx, GLbitfield mask); void _mesa_glthread_InterleavedArrays(struct gl_context *ctx, GLenum format, GLsizei stride, const GLvoid *pointer); void _mesa_glthread_ProgramChanged(struct gl_context *ctx); void _mesa_glthread_UnrollDrawElements(struct gl_context *ctx, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); void _mesa_glthread_unbind_uploaded_vbos(struct gl_context *ctx); void _mesa_glthread_PixelStorei(struct gl_context *ctx, GLenum pname, GLint param); #ifdef __cplusplus } #endif #endif /* _GLTHREAD_H*/