17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2020 Advanced Micro Devices, Inc. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg/* This implements vertex array state tracking for glthread. It's separate 257ec681f3Smrg * from the rest of Mesa. Only minimum functionality is implemented here 267ec681f3Smrg * to serve glthread. 277ec681f3Smrg */ 287ec681f3Smrg 297ec681f3Smrg#include "main/glthread.h" 307ec681f3Smrg#include "main/glformats.h" 317ec681f3Smrg#include "main/mtypes.h" 327ec681f3Smrg#include "main/hash.h" 337ec681f3Smrg#include "main/dispatch.h" 347ec681f3Smrg#include "main/varray.h" 357ec681f3Smrg 367ec681f3Smrg 377ec681f3Smrgvoid 387ec681f3Smrg_mesa_glthread_reset_vao(struct glthread_vao *vao) 397ec681f3Smrg{ 407ec681f3Smrg static unsigned default_elem_size[VERT_ATTRIB_MAX] = { 417ec681f3Smrg [VERT_ATTRIB_NORMAL] = 12, 427ec681f3Smrg [VERT_ATTRIB_COLOR1] = 12, 437ec681f3Smrg [VERT_ATTRIB_FOG] = 4, 447ec681f3Smrg [VERT_ATTRIB_COLOR_INDEX] = 4, 457ec681f3Smrg [VERT_ATTRIB_EDGEFLAG] = 1, 467ec681f3Smrg [VERT_ATTRIB_POINT_SIZE] = 4, 477ec681f3Smrg }; 487ec681f3Smrg 497ec681f3Smrg vao->CurrentElementBufferName = 0; 507ec681f3Smrg vao->UserEnabled = 0; 517ec681f3Smrg vao->Enabled = 0; 527ec681f3Smrg vao->BufferEnabled = 0; 537ec681f3Smrg vao->UserPointerMask = 0; 547ec681f3Smrg vao->NonZeroDivisorMask = 0; 557ec681f3Smrg 567ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(vao->Attrib); i++) { 577ec681f3Smrg unsigned elem_size = default_elem_size[i]; 587ec681f3Smrg if (!elem_size) 597ec681f3Smrg elem_size = 16; 607ec681f3Smrg 617ec681f3Smrg vao->Attrib[i].ElementSize = elem_size; 627ec681f3Smrg vao->Attrib[i].RelativeOffset = 0; 637ec681f3Smrg vao->Attrib[i].BufferIndex = i; 647ec681f3Smrg vao->Attrib[i].Stride = elem_size; 657ec681f3Smrg vao->Attrib[i].Divisor = 0; 667ec681f3Smrg vao->Attrib[i].EnabledAttribCount = 0; 677ec681f3Smrg vao->Attrib[i].Pointer = NULL; 687ec681f3Smrg } 697ec681f3Smrg} 707ec681f3Smrg 717ec681f3Smrgstatic struct glthread_vao * 727ec681f3Smrglookup_vao(struct gl_context *ctx, GLuint id) 737ec681f3Smrg{ 747ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 757ec681f3Smrg struct glthread_vao *vao; 767ec681f3Smrg 777ec681f3Smrg assert(id != 0); 787ec681f3Smrg 797ec681f3Smrg if (glthread->LastLookedUpVAO && 807ec681f3Smrg glthread->LastLookedUpVAO->Name == id) { 817ec681f3Smrg vao = glthread->LastLookedUpVAO; 827ec681f3Smrg } else { 837ec681f3Smrg vao = _mesa_HashLookupLocked(glthread->VAOs, id); 847ec681f3Smrg if (!vao) 857ec681f3Smrg return NULL; 867ec681f3Smrg 877ec681f3Smrg glthread->LastLookedUpVAO = vao; 887ec681f3Smrg } 897ec681f3Smrg 907ec681f3Smrg return vao; 917ec681f3Smrg} 927ec681f3Smrg 937ec681f3Smrgvoid 947ec681f3Smrg_mesa_glthread_BindVertexArray(struct gl_context *ctx, GLuint id) 957ec681f3Smrg{ 967ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 977ec681f3Smrg 987ec681f3Smrg if (id == 0) { 997ec681f3Smrg glthread->CurrentVAO = &glthread->DefaultVAO; 1007ec681f3Smrg } else { 1017ec681f3Smrg struct glthread_vao *vao = lookup_vao(ctx, id); 1027ec681f3Smrg 1037ec681f3Smrg if (vao) 1047ec681f3Smrg glthread->CurrentVAO = vao; 1057ec681f3Smrg } 1067ec681f3Smrg} 1077ec681f3Smrg 1087ec681f3Smrgvoid 1097ec681f3Smrg_mesa_glthread_DeleteVertexArrays(struct gl_context *ctx, 1107ec681f3Smrg GLsizei n, const GLuint *ids) 1117ec681f3Smrg{ 1127ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 1137ec681f3Smrg 1147ec681f3Smrg if (!ids) 1157ec681f3Smrg return; 1167ec681f3Smrg 1177ec681f3Smrg for (int i = 0; i < n; i++) { 1187ec681f3Smrg /* IDs equal to 0 should be silently ignored. */ 1197ec681f3Smrg if (!ids[i]) 1207ec681f3Smrg continue; 1217ec681f3Smrg 1227ec681f3Smrg struct glthread_vao *vao = lookup_vao(ctx, ids[i]); 1237ec681f3Smrg if (!vao) 1247ec681f3Smrg continue; 1257ec681f3Smrg 1267ec681f3Smrg /* If the array object is currently bound, the spec says "the binding 1277ec681f3Smrg * for that object reverts to zero and the default vertex array 1287ec681f3Smrg * becomes current." 1297ec681f3Smrg */ 1307ec681f3Smrg if (glthread->CurrentVAO == vao) 1317ec681f3Smrg glthread->CurrentVAO = &glthread->DefaultVAO; 1327ec681f3Smrg 1337ec681f3Smrg if (glthread->LastLookedUpVAO == vao) 1347ec681f3Smrg glthread->LastLookedUpVAO = NULL; 1357ec681f3Smrg 1367ec681f3Smrg /* The ID is immediately freed for re-use */ 1377ec681f3Smrg _mesa_HashRemoveLocked(glthread->VAOs, vao->Name); 1387ec681f3Smrg free(vao); 1397ec681f3Smrg } 1407ec681f3Smrg} 1417ec681f3Smrg 1427ec681f3Smrgvoid 1437ec681f3Smrg_mesa_glthread_GenVertexArrays(struct gl_context *ctx, 1447ec681f3Smrg GLsizei n, GLuint *arrays) 1457ec681f3Smrg{ 1467ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 1477ec681f3Smrg 1487ec681f3Smrg if (!arrays) 1497ec681f3Smrg return; 1507ec681f3Smrg 1517ec681f3Smrg /* The IDs have been generated at this point. Create VAOs for glthread. */ 1527ec681f3Smrg for (int i = 0; i < n; i++) { 1537ec681f3Smrg GLuint id = arrays[i]; 1547ec681f3Smrg struct glthread_vao *vao; 1557ec681f3Smrg 1567ec681f3Smrg vao = calloc(1, sizeof(*vao)); 1577ec681f3Smrg if (!vao) 1587ec681f3Smrg continue; /* Is that all we can do? */ 1597ec681f3Smrg 1607ec681f3Smrg vao->Name = id; 1617ec681f3Smrg _mesa_glthread_reset_vao(vao); 1627ec681f3Smrg _mesa_HashInsertLocked(glthread->VAOs, id, vao, true); 1637ec681f3Smrg } 1647ec681f3Smrg} 1657ec681f3Smrg 1667ec681f3Smrg/* If vaobj is NULL, use the currently-bound VAO. */ 1677ec681f3Smrgstatic inline struct glthread_vao * 1687ec681f3Smrgget_vao(struct gl_context *ctx, const GLuint *vaobj) 1697ec681f3Smrg{ 1707ec681f3Smrg if (vaobj) 1717ec681f3Smrg return lookup_vao(ctx, *vaobj); 1727ec681f3Smrg 1737ec681f3Smrg return ctx->GLThread.CurrentVAO; 1747ec681f3Smrg} 1757ec681f3Smrg 1767ec681f3Smrgstatic void 1777ec681f3Smrgupdate_primitive_restart(struct gl_context *ctx) 1787ec681f3Smrg{ 1797ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 1807ec681f3Smrg 1817ec681f3Smrg glthread->_PrimitiveRestart = glthread->PrimitiveRestart || 1827ec681f3Smrg glthread->PrimitiveRestartFixedIndex; 1837ec681f3Smrg glthread->_RestartIndex[0] = 1847ec681f3Smrg _mesa_get_prim_restart_index(glthread->PrimitiveRestartFixedIndex, 1857ec681f3Smrg glthread->RestartIndex, 1); 1867ec681f3Smrg glthread->_RestartIndex[1] = 1877ec681f3Smrg _mesa_get_prim_restart_index(glthread->PrimitiveRestartFixedIndex, 1887ec681f3Smrg glthread->RestartIndex, 2); 1897ec681f3Smrg glthread->_RestartIndex[3] = 1907ec681f3Smrg _mesa_get_prim_restart_index(glthread->PrimitiveRestartFixedIndex, 1917ec681f3Smrg glthread->RestartIndex, 4); 1927ec681f3Smrg} 1937ec681f3Smrg 1947ec681f3Smrgvoid 1957ec681f3Smrg_mesa_glthread_set_prim_restart(struct gl_context *ctx, GLenum cap, bool value) 1967ec681f3Smrg{ 1977ec681f3Smrg switch (cap) { 1987ec681f3Smrg case GL_PRIMITIVE_RESTART: 1997ec681f3Smrg ctx->GLThread.PrimitiveRestart = value; 2007ec681f3Smrg break; 2017ec681f3Smrg case GL_PRIMITIVE_RESTART_FIXED_INDEX: 2027ec681f3Smrg ctx->GLThread.PrimitiveRestartFixedIndex = value; 2037ec681f3Smrg break; 2047ec681f3Smrg } 2057ec681f3Smrg 2067ec681f3Smrg update_primitive_restart(ctx); 2077ec681f3Smrg} 2087ec681f3Smrg 2097ec681f3Smrgvoid 2107ec681f3Smrg_mesa_glthread_PrimitiveRestartIndex(struct gl_context *ctx, GLuint index) 2117ec681f3Smrg{ 2127ec681f3Smrg ctx->GLThread.RestartIndex = index; 2137ec681f3Smrg update_primitive_restart(ctx); 2147ec681f3Smrg} 2157ec681f3Smrg 2167ec681f3Smrgstatic inline void 2177ec681f3Smrgenable_buffer(struct glthread_vao *vao, unsigned binding_index) 2187ec681f3Smrg{ 2197ec681f3Smrg int attrib_count = ++vao->Attrib[binding_index].EnabledAttribCount; 2207ec681f3Smrg 2217ec681f3Smrg if (attrib_count == 1) 2227ec681f3Smrg vao->BufferEnabled |= 1 << binding_index; 2237ec681f3Smrg else if (attrib_count == 2) 2247ec681f3Smrg vao->BufferInterleaved |= 1 << binding_index; 2257ec681f3Smrg} 2267ec681f3Smrg 2277ec681f3Smrgstatic inline void 2287ec681f3Smrgdisable_buffer(struct glthread_vao *vao, unsigned binding_index) 2297ec681f3Smrg{ 2307ec681f3Smrg int attrib_count = --vao->Attrib[binding_index].EnabledAttribCount; 2317ec681f3Smrg 2327ec681f3Smrg if (attrib_count == 0) 2337ec681f3Smrg vao->BufferEnabled &= ~(1 << binding_index); 2347ec681f3Smrg else if (attrib_count == 1) 2357ec681f3Smrg vao->BufferInterleaved &= ~(1 << binding_index); 2367ec681f3Smrg else 2377ec681f3Smrg assert(attrib_count >= 0); 2387ec681f3Smrg} 2397ec681f3Smrg 2407ec681f3Smrgvoid 2417ec681f3Smrg_mesa_glthread_ClientState(struct gl_context *ctx, GLuint *vaobj, 2427ec681f3Smrg gl_vert_attrib attrib, bool enable) 2437ec681f3Smrg{ 2447ec681f3Smrg /* The primitive restart client state uses a special value. */ 2457ec681f3Smrg if (attrib == VERT_ATTRIB_PRIMITIVE_RESTART_NV) { 2467ec681f3Smrg ctx->GLThread.PrimitiveRestart = enable; 2477ec681f3Smrg update_primitive_restart(ctx); 2487ec681f3Smrg return; 2497ec681f3Smrg } 2507ec681f3Smrg 2517ec681f3Smrg if (attrib >= VERT_ATTRIB_MAX) 2527ec681f3Smrg return; 2537ec681f3Smrg 2547ec681f3Smrg struct glthread_vao *vao = get_vao(ctx, vaobj); 2557ec681f3Smrg if (!vao) 2567ec681f3Smrg return; 2577ec681f3Smrg 2587ec681f3Smrg const unsigned attrib_bit = 1u << attrib; 2597ec681f3Smrg 2607ec681f3Smrg if (enable && !(vao->UserEnabled & attrib_bit)) { 2617ec681f3Smrg vao->UserEnabled |= attrib_bit; 2627ec681f3Smrg 2637ec681f3Smrg /* The generic0 attribute supersedes the position attribute. We need to 2647ec681f3Smrg * update BufferBindingEnabled accordingly. 2657ec681f3Smrg */ 2667ec681f3Smrg if (attrib == VERT_ATTRIB_POS) { 2677ec681f3Smrg if (!(vao->UserEnabled & VERT_BIT_GENERIC0)) 2687ec681f3Smrg enable_buffer(vao, vao->Attrib[VERT_ATTRIB_POS].BufferIndex); 2697ec681f3Smrg } else { 2707ec681f3Smrg enable_buffer(vao, vao->Attrib[attrib].BufferIndex); 2717ec681f3Smrg 2727ec681f3Smrg if (attrib == VERT_ATTRIB_GENERIC0 && vao->UserEnabled & VERT_BIT_POS) 2737ec681f3Smrg disable_buffer(vao, vao->Attrib[VERT_ATTRIB_POS].BufferIndex); 2747ec681f3Smrg } 2757ec681f3Smrg } else if (!enable && (vao->UserEnabled & attrib_bit)) { 2767ec681f3Smrg vao->UserEnabled &= ~attrib_bit; 2777ec681f3Smrg 2787ec681f3Smrg /* The generic0 attribute supersedes the position attribute. We need to 2797ec681f3Smrg * update BufferBindingEnabled accordingly. 2807ec681f3Smrg */ 2817ec681f3Smrg if (attrib == VERT_ATTRIB_POS) { 2827ec681f3Smrg if (!(vao->UserEnabled & VERT_BIT_GENERIC0)) 2837ec681f3Smrg disable_buffer(vao, vao->Attrib[VERT_ATTRIB_POS].BufferIndex); 2847ec681f3Smrg } else { 2857ec681f3Smrg disable_buffer(vao, vao->Attrib[attrib].BufferIndex); 2867ec681f3Smrg 2877ec681f3Smrg if (attrib == VERT_ATTRIB_GENERIC0 && vao->UserEnabled & VERT_BIT_POS) 2887ec681f3Smrg enable_buffer(vao, vao->Attrib[VERT_ATTRIB_POS].BufferIndex); 2897ec681f3Smrg } 2907ec681f3Smrg } 2917ec681f3Smrg 2927ec681f3Smrg /* The generic0 attribute supersedes the position attribute. */ 2937ec681f3Smrg vao->Enabled = vao->UserEnabled; 2947ec681f3Smrg if (vao->Enabled & VERT_BIT_GENERIC0) 2957ec681f3Smrg vao->Enabled &= ~VERT_BIT_POS; 2967ec681f3Smrg} 2977ec681f3Smrg 2987ec681f3Smrgstatic void 2997ec681f3Smrgset_attrib_binding(struct glthread_state *glthread, struct glthread_vao *vao, 3007ec681f3Smrg gl_vert_attrib attrib, unsigned new_binding_index) 3017ec681f3Smrg{ 3027ec681f3Smrg unsigned old_binding_index = vao->Attrib[attrib].BufferIndex; 3037ec681f3Smrg 3047ec681f3Smrg if (old_binding_index != new_binding_index) { 3057ec681f3Smrg vao->Attrib[attrib].BufferIndex = new_binding_index; 3067ec681f3Smrg 3077ec681f3Smrg if (vao->Enabled & (1u << attrib)) { 3087ec681f3Smrg /* Update BufferBindingEnabled. */ 3097ec681f3Smrg enable_buffer(vao, new_binding_index); 3107ec681f3Smrg disable_buffer(vao, old_binding_index); 3117ec681f3Smrg } 3127ec681f3Smrg } 3137ec681f3Smrg} 3147ec681f3Smrg 3157ec681f3Smrgvoid _mesa_glthread_AttribDivisor(struct gl_context *ctx, const GLuint *vaobj, 3167ec681f3Smrg gl_vert_attrib attrib, GLuint divisor) 3177ec681f3Smrg{ 3187ec681f3Smrg if (attrib >= VERT_ATTRIB_MAX) 3197ec681f3Smrg return; 3207ec681f3Smrg 3217ec681f3Smrg struct glthread_vao *vao = get_vao(ctx, vaobj); 3227ec681f3Smrg if (!vao) 3237ec681f3Smrg return; 3247ec681f3Smrg 3257ec681f3Smrg vao->Attrib[attrib].Divisor = divisor; 3267ec681f3Smrg 3277ec681f3Smrg set_attrib_binding(&ctx->GLThread, vao, attrib, attrib); 3287ec681f3Smrg 3297ec681f3Smrg if (divisor) 3307ec681f3Smrg vao->NonZeroDivisorMask |= 1u << attrib; 3317ec681f3Smrg else 3327ec681f3Smrg vao->NonZeroDivisorMask &= ~(1u << attrib); 3337ec681f3Smrg} 3347ec681f3Smrg 3357ec681f3Smrgstatic unsigned 3367ec681f3Smrgelement_size(GLint size, GLenum type) 3377ec681f3Smrg{ 3387ec681f3Smrg if (size == GL_BGRA) 3397ec681f3Smrg size = 4; 3407ec681f3Smrg 3417ec681f3Smrg return _mesa_bytes_per_vertex_attrib(size, type); 3427ec681f3Smrg} 3437ec681f3Smrg 3447ec681f3Smrgstatic void 3457ec681f3Smrgattrib_pointer(struct glthread_state *glthread, struct glthread_vao *vao, 3467ec681f3Smrg GLuint buffer, gl_vert_attrib attrib, 3477ec681f3Smrg GLint size, GLenum type, GLsizei stride, 3487ec681f3Smrg const void *pointer) 3497ec681f3Smrg{ 3507ec681f3Smrg if (attrib >= VERT_ATTRIB_MAX) 3517ec681f3Smrg return; 3527ec681f3Smrg 3537ec681f3Smrg unsigned elem_size = element_size(size, type); 3547ec681f3Smrg 3557ec681f3Smrg vao->Attrib[attrib].ElementSize = elem_size; 3567ec681f3Smrg vao->Attrib[attrib].Stride = stride ? stride : elem_size; 3577ec681f3Smrg vao->Attrib[attrib].Pointer = pointer; 3587ec681f3Smrg vao->Attrib[attrib].RelativeOffset = 0; 3597ec681f3Smrg 3607ec681f3Smrg set_attrib_binding(glthread, vao, attrib, attrib); 3617ec681f3Smrg 3627ec681f3Smrg if (buffer != 0) 3637ec681f3Smrg vao->UserPointerMask &= ~(1u << attrib); 3647ec681f3Smrg else 3657ec681f3Smrg vao->UserPointerMask |= 1u << attrib; 3667ec681f3Smrg} 3677ec681f3Smrg 3687ec681f3Smrgvoid 3697ec681f3Smrg_mesa_glthread_AttribPointer(struct gl_context *ctx, gl_vert_attrib attrib, 3707ec681f3Smrg GLint size, GLenum type, GLsizei stride, 3717ec681f3Smrg const void *pointer) 3727ec681f3Smrg{ 3737ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 3747ec681f3Smrg 3757ec681f3Smrg attrib_pointer(glthread, glthread->CurrentVAO, 3767ec681f3Smrg glthread->CurrentArrayBufferName, 3777ec681f3Smrg attrib, size, type, stride, pointer); 3787ec681f3Smrg} 3797ec681f3Smrg 3807ec681f3Smrgvoid 3817ec681f3Smrg_mesa_glthread_DSAAttribPointer(struct gl_context *ctx, GLuint vaobj, 3827ec681f3Smrg GLuint buffer, gl_vert_attrib attrib, 3837ec681f3Smrg GLint size, GLenum type, GLsizei stride, 3847ec681f3Smrg GLintptr offset) 3857ec681f3Smrg{ 3867ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 3877ec681f3Smrg struct glthread_vao *vao; 3887ec681f3Smrg 3897ec681f3Smrg vao = lookup_vao(ctx, vaobj); 3907ec681f3Smrg if (!vao) 3917ec681f3Smrg return; 3927ec681f3Smrg 3937ec681f3Smrg attrib_pointer(glthread, vao, buffer, attrib, size, type, stride, 3947ec681f3Smrg (const void*)offset); 3957ec681f3Smrg} 3967ec681f3Smrg 3977ec681f3Smrgstatic void 3987ec681f3Smrgattrib_format(struct glthread_state *glthread, struct glthread_vao *vao, 3997ec681f3Smrg GLuint attribindex, GLint size, GLenum type, 4007ec681f3Smrg GLuint relativeoffset) 4017ec681f3Smrg{ 4027ec681f3Smrg if (attribindex >= VERT_ATTRIB_GENERIC_MAX) 4037ec681f3Smrg return; 4047ec681f3Smrg 4057ec681f3Smrg unsigned elem_size = element_size(size, type); 4067ec681f3Smrg 4077ec681f3Smrg unsigned i = VERT_ATTRIB_GENERIC(attribindex); 4087ec681f3Smrg vao->Attrib[i].ElementSize = elem_size; 4097ec681f3Smrg vao->Attrib[i].RelativeOffset = relativeoffset; 4107ec681f3Smrg} 4117ec681f3Smrg 4127ec681f3Smrgvoid 4137ec681f3Smrg_mesa_glthread_AttribFormat(struct gl_context *ctx, GLuint attribindex, 4147ec681f3Smrg GLint size, GLenum type, GLuint relativeoffset) 4157ec681f3Smrg{ 4167ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 4177ec681f3Smrg 4187ec681f3Smrg attrib_format(glthread, glthread->CurrentVAO, attribindex, size, type, 4197ec681f3Smrg relativeoffset); 4207ec681f3Smrg} 4217ec681f3Smrg 4227ec681f3Smrgvoid 4237ec681f3Smrg_mesa_glthread_DSAAttribFormat(struct gl_context *ctx, GLuint vaobj, 4247ec681f3Smrg GLuint attribindex, GLint size, GLenum type, 4257ec681f3Smrg GLuint relativeoffset) 4267ec681f3Smrg{ 4277ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 4287ec681f3Smrg struct glthread_vao *vao = lookup_vao(ctx, vaobj); 4297ec681f3Smrg 4307ec681f3Smrg if (vao) 4317ec681f3Smrg attrib_format(glthread, vao, attribindex, size, type, relativeoffset); 4327ec681f3Smrg} 4337ec681f3Smrg 4347ec681f3Smrgstatic void 4357ec681f3Smrgbind_vertex_buffer(struct glthread_state *glthread, struct glthread_vao *vao, 4367ec681f3Smrg GLuint bindingindex, GLuint buffer, GLintptr offset, 4377ec681f3Smrg GLsizei stride) 4387ec681f3Smrg{ 4397ec681f3Smrg if (bindingindex >= VERT_ATTRIB_GENERIC_MAX) 4407ec681f3Smrg return; 4417ec681f3Smrg 4427ec681f3Smrg unsigned i = VERT_ATTRIB_GENERIC(bindingindex); 4437ec681f3Smrg vao->Attrib[i].Pointer = (const void*)offset; 4447ec681f3Smrg vao->Attrib[i].Stride = stride; 4457ec681f3Smrg 4467ec681f3Smrg if (buffer != 0) 4477ec681f3Smrg vao->UserPointerMask &= ~(1u << i); 4487ec681f3Smrg else 4497ec681f3Smrg vao->UserPointerMask |= 1u << i; 4507ec681f3Smrg} 4517ec681f3Smrg 4527ec681f3Smrgvoid 4537ec681f3Smrg_mesa_glthread_VertexBuffer(struct gl_context *ctx, GLuint bindingindex, 4547ec681f3Smrg GLuint buffer, GLintptr offset, GLsizei stride) 4557ec681f3Smrg{ 4567ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 4577ec681f3Smrg 4587ec681f3Smrg bind_vertex_buffer(glthread, glthread->CurrentVAO, bindingindex, buffer, 4597ec681f3Smrg offset, stride); 4607ec681f3Smrg} 4617ec681f3Smrg 4627ec681f3Smrgvoid 4637ec681f3Smrg_mesa_glthread_DSAVertexBuffer(struct gl_context *ctx, GLuint vaobj, 4647ec681f3Smrg GLuint bindingindex, GLuint buffer, 4657ec681f3Smrg GLintptr offset, GLsizei stride) 4667ec681f3Smrg{ 4677ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 4687ec681f3Smrg struct glthread_vao *vao = lookup_vao(ctx, vaobj); 4697ec681f3Smrg 4707ec681f3Smrg if (vao) 4717ec681f3Smrg bind_vertex_buffer(glthread, vao, bindingindex, buffer, offset, stride); 4727ec681f3Smrg} 4737ec681f3Smrg 4747ec681f3Smrgvoid 4757ec681f3Smrg_mesa_glthread_DSAVertexBuffers(struct gl_context *ctx, GLuint vaobj, 4767ec681f3Smrg GLuint first, GLsizei count, 4777ec681f3Smrg const GLuint *buffers, 4787ec681f3Smrg const GLintptr *offsets, 4797ec681f3Smrg const GLsizei *strides) 4807ec681f3Smrg{ 4817ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 4827ec681f3Smrg struct glthread_vao *vao; 4837ec681f3Smrg 4847ec681f3Smrg vao = lookup_vao(ctx, vaobj); 4857ec681f3Smrg if (!vao) 4867ec681f3Smrg return; 4877ec681f3Smrg 4887ec681f3Smrg for (unsigned i = 0; i < count; i++) { 4897ec681f3Smrg bind_vertex_buffer(glthread, vao, first + i, buffers[i], offsets[i], 4907ec681f3Smrg strides[i]); 4917ec681f3Smrg } 4927ec681f3Smrg} 4937ec681f3Smrg 4947ec681f3Smrgstatic void 4957ec681f3Smrgbinding_divisor(struct glthread_state *glthread, struct glthread_vao *vao, 4967ec681f3Smrg GLuint bindingindex, GLuint divisor) 4977ec681f3Smrg{ 4987ec681f3Smrg if (bindingindex >= VERT_ATTRIB_GENERIC_MAX) 4997ec681f3Smrg return; 5007ec681f3Smrg 5017ec681f3Smrg unsigned i = VERT_ATTRIB_GENERIC(bindingindex); 5027ec681f3Smrg vao->Attrib[i].Divisor = divisor; 5037ec681f3Smrg 5047ec681f3Smrg if (divisor) 5057ec681f3Smrg vao->NonZeroDivisorMask |= 1u << i; 5067ec681f3Smrg else 5077ec681f3Smrg vao->NonZeroDivisorMask &= ~(1u << i); 5087ec681f3Smrg} 5097ec681f3Smrg 5107ec681f3Smrgvoid 5117ec681f3Smrg_mesa_glthread_BindingDivisor(struct gl_context *ctx, GLuint bindingindex, 5127ec681f3Smrg GLuint divisor) 5137ec681f3Smrg{ 5147ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 5157ec681f3Smrg 5167ec681f3Smrg binding_divisor(glthread, glthread->CurrentVAO, bindingindex, divisor); 5177ec681f3Smrg} 5187ec681f3Smrg 5197ec681f3Smrgvoid 5207ec681f3Smrg_mesa_glthread_DSABindingDivisor(struct gl_context *ctx, GLuint vaobj, 5217ec681f3Smrg GLuint bindingindex, GLuint divisor) 5227ec681f3Smrg{ 5237ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 5247ec681f3Smrg struct glthread_vao *vao = lookup_vao(ctx, vaobj); 5257ec681f3Smrg 5267ec681f3Smrg if (vao) 5277ec681f3Smrg binding_divisor(glthread, vao, bindingindex, divisor); 5287ec681f3Smrg} 5297ec681f3Smrg 5307ec681f3Smrgvoid 5317ec681f3Smrg_mesa_glthread_AttribBinding(struct gl_context *ctx, GLuint attribindex, 5327ec681f3Smrg GLuint bindingindex) 5337ec681f3Smrg{ 5347ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 5357ec681f3Smrg 5367ec681f3Smrg if (attribindex >= VERT_ATTRIB_GENERIC_MAX || 5377ec681f3Smrg bindingindex >= VERT_ATTRIB_GENERIC_MAX) 5387ec681f3Smrg return; 5397ec681f3Smrg 5407ec681f3Smrg set_attrib_binding(glthread, glthread->CurrentVAO, 5417ec681f3Smrg VERT_ATTRIB_GENERIC(attribindex), 5427ec681f3Smrg VERT_ATTRIB_GENERIC(bindingindex)); 5437ec681f3Smrg} 5447ec681f3Smrg 5457ec681f3Smrgvoid 5467ec681f3Smrg_mesa_glthread_DSAAttribBinding(struct gl_context *ctx, GLuint vaobj, 5477ec681f3Smrg GLuint attribindex, GLuint bindingindex) 5487ec681f3Smrg{ 5497ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 5507ec681f3Smrg 5517ec681f3Smrg if (attribindex >= VERT_ATTRIB_GENERIC_MAX || 5527ec681f3Smrg bindingindex >= VERT_ATTRIB_GENERIC_MAX) 5537ec681f3Smrg return; 5547ec681f3Smrg 5557ec681f3Smrg struct glthread_vao *vao = lookup_vao(ctx, vaobj); 5567ec681f3Smrg if (vao) { 5577ec681f3Smrg set_attrib_binding(glthread, vao, 5587ec681f3Smrg VERT_ATTRIB_GENERIC(attribindex), 5597ec681f3Smrg VERT_ATTRIB_GENERIC(bindingindex)); 5607ec681f3Smrg } 5617ec681f3Smrg} 5627ec681f3Smrg 5637ec681f3Smrgvoid 5647ec681f3Smrg_mesa_glthread_DSAElementBuffer(struct gl_context *ctx, GLuint vaobj, 5657ec681f3Smrg GLuint buffer) 5667ec681f3Smrg{ 5677ec681f3Smrg struct glthread_vao *vao = lookup_vao(ctx, vaobj); 5687ec681f3Smrg 5697ec681f3Smrg if (vao) 5707ec681f3Smrg vao->CurrentElementBufferName = buffer; 5717ec681f3Smrg} 5727ec681f3Smrg 5737ec681f3Smrgvoid 5747ec681f3Smrg_mesa_glthread_PushClientAttrib(struct gl_context *ctx, GLbitfield mask, 5757ec681f3Smrg bool set_default) 5767ec681f3Smrg{ 5777ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 5787ec681f3Smrg 5797ec681f3Smrg if (glthread->ClientAttribStackTop >= MAX_CLIENT_ATTRIB_STACK_DEPTH) 5807ec681f3Smrg return; 5817ec681f3Smrg 5827ec681f3Smrg struct glthread_client_attrib *top = 5837ec681f3Smrg &glthread->ClientAttribStack[glthread->ClientAttribStackTop]; 5847ec681f3Smrg 5857ec681f3Smrg if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { 5867ec681f3Smrg top->VAO = *glthread->CurrentVAO; 5877ec681f3Smrg top->CurrentArrayBufferName = glthread->CurrentArrayBufferName; 5887ec681f3Smrg top->ClientActiveTexture = glthread->ClientActiveTexture; 5897ec681f3Smrg top->RestartIndex = glthread->RestartIndex; 5907ec681f3Smrg top->PrimitiveRestart = glthread->PrimitiveRestart; 5917ec681f3Smrg top->PrimitiveRestartFixedIndex = glthread->PrimitiveRestartFixedIndex; 5927ec681f3Smrg top->Valid = true; 5937ec681f3Smrg } else { 5947ec681f3Smrg top->Valid = false; 5957ec681f3Smrg } 5967ec681f3Smrg 5977ec681f3Smrg glthread->ClientAttribStackTop++; 5987ec681f3Smrg 5997ec681f3Smrg if (set_default) 6007ec681f3Smrg _mesa_glthread_ClientAttribDefault(ctx, mask); 6017ec681f3Smrg} 6027ec681f3Smrg 6037ec681f3Smrgvoid 6047ec681f3Smrg_mesa_glthread_PopClientAttrib(struct gl_context *ctx) 6057ec681f3Smrg{ 6067ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 6077ec681f3Smrg 6087ec681f3Smrg if (glthread->ClientAttribStackTop == 0) 6097ec681f3Smrg return; 6107ec681f3Smrg 6117ec681f3Smrg glthread->ClientAttribStackTop--; 6127ec681f3Smrg 6137ec681f3Smrg struct glthread_client_attrib *top = 6147ec681f3Smrg &glthread->ClientAttribStack[glthread->ClientAttribStackTop]; 6157ec681f3Smrg 6167ec681f3Smrg if (!top->Valid) 6177ec681f3Smrg return; 6187ec681f3Smrg 6197ec681f3Smrg /* Popping a delete VAO is an error. */ 6207ec681f3Smrg struct glthread_vao *vao = NULL; 6217ec681f3Smrg if (top->VAO.Name) { 6227ec681f3Smrg vao = lookup_vao(ctx, top->VAO.Name); 6237ec681f3Smrg if (!vao) 6247ec681f3Smrg return; 6257ec681f3Smrg } 6267ec681f3Smrg 6277ec681f3Smrg /* Restore states. */ 6287ec681f3Smrg glthread->CurrentArrayBufferName = top->CurrentArrayBufferName; 6297ec681f3Smrg glthread->ClientActiveTexture = top->ClientActiveTexture; 6307ec681f3Smrg glthread->RestartIndex = top->RestartIndex; 6317ec681f3Smrg glthread->PrimitiveRestart = top->PrimitiveRestart; 6327ec681f3Smrg glthread->PrimitiveRestartFixedIndex = top->PrimitiveRestartFixedIndex; 6337ec681f3Smrg 6347ec681f3Smrg if (!vao) 6357ec681f3Smrg vao = &glthread->DefaultVAO; 6367ec681f3Smrg 6377ec681f3Smrg assert(top->VAO.Name == vao->Name); 6387ec681f3Smrg *vao = top->VAO; /* Copy all fields. */ 6397ec681f3Smrg glthread->CurrentVAO = vao; 6407ec681f3Smrg} 6417ec681f3Smrg 6427ec681f3Smrgvoid 6437ec681f3Smrg_mesa_glthread_ClientAttribDefault(struct gl_context *ctx, GLbitfield mask) 6447ec681f3Smrg{ 6457ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 6467ec681f3Smrg 6477ec681f3Smrg if (!(mask & GL_CLIENT_VERTEX_ARRAY_BIT)) 6487ec681f3Smrg return; 6497ec681f3Smrg 6507ec681f3Smrg glthread->CurrentArrayBufferName = 0; 6517ec681f3Smrg glthread->ClientActiveTexture = 0; 6527ec681f3Smrg glthread->RestartIndex = 0; 6537ec681f3Smrg glthread->PrimitiveRestart = false; 6547ec681f3Smrg glthread->PrimitiveRestartFixedIndex = false; 6557ec681f3Smrg glthread->CurrentVAO = &glthread->DefaultVAO; 6567ec681f3Smrg _mesa_glthread_reset_vao(glthread->CurrentVAO); 6577ec681f3Smrg} 6587ec681f3Smrg 6597ec681f3Smrgvoid 6607ec681f3Smrg_mesa_glthread_InterleavedArrays(struct gl_context *ctx, GLenum format, 6617ec681f3Smrg GLsizei stride, const GLvoid *pointer) 6627ec681f3Smrg{ 6637ec681f3Smrg struct gl_interleaved_layout layout; 6647ec681f3Smrg unsigned tex = VERT_ATTRIB_TEX(ctx->GLThread.ClientActiveTexture); 6657ec681f3Smrg 6667ec681f3Smrg if (stride < 0 || !_mesa_get_interleaved_layout(format, &layout)) 6677ec681f3Smrg return; 6687ec681f3Smrg 6697ec681f3Smrg if (!stride) 6707ec681f3Smrg stride = layout.defstride; 6717ec681f3Smrg 6727ec681f3Smrg _mesa_glthread_ClientState(ctx, NULL, VERT_ATTRIB_EDGEFLAG, false); 6737ec681f3Smrg _mesa_glthread_ClientState(ctx, NULL, VERT_ATTRIB_COLOR_INDEX, false); 6747ec681f3Smrg /* XXX also disable secondary color and generic arrays? */ 6757ec681f3Smrg 6767ec681f3Smrg /* Texcoords */ 6777ec681f3Smrg if (layout.tflag) { 6787ec681f3Smrg _mesa_glthread_ClientState(ctx, NULL, tex, true); 6797ec681f3Smrg _mesa_glthread_AttribPointer(ctx, tex, layout.tcomps, GL_FLOAT, stride, 6807ec681f3Smrg (GLubyte *) pointer + layout.toffset); 6817ec681f3Smrg } else { 6827ec681f3Smrg _mesa_glthread_ClientState(ctx, NULL, tex, false); 6837ec681f3Smrg } 6847ec681f3Smrg 6857ec681f3Smrg /* Color */ 6867ec681f3Smrg if (layout.cflag) { 6877ec681f3Smrg _mesa_glthread_ClientState(ctx, NULL, VERT_ATTRIB_COLOR0, true); 6887ec681f3Smrg _mesa_glthread_AttribPointer(ctx, VERT_ATTRIB_COLOR0, layout.ccomps, 6897ec681f3Smrg layout.ctype, stride, 6907ec681f3Smrg (GLubyte *) pointer + layout.coffset); 6917ec681f3Smrg } else { 6927ec681f3Smrg _mesa_glthread_ClientState(ctx, NULL, VERT_ATTRIB_COLOR0, false); 6937ec681f3Smrg } 6947ec681f3Smrg 6957ec681f3Smrg /* Normals */ 6967ec681f3Smrg if (layout.nflag) { 6977ec681f3Smrg _mesa_glthread_ClientState(ctx, NULL, VERT_ATTRIB_NORMAL, true); 6987ec681f3Smrg _mesa_glthread_AttribPointer(ctx, VERT_ATTRIB_NORMAL, 3, GL_FLOAT, 6997ec681f3Smrg stride, (GLubyte *) pointer + layout.noffset); 7007ec681f3Smrg } else { 7017ec681f3Smrg _mesa_glthread_ClientState(ctx, NULL, VERT_ATTRIB_NORMAL, false); 7027ec681f3Smrg } 7037ec681f3Smrg 7047ec681f3Smrg /* Vertices */ 7057ec681f3Smrg _mesa_glthread_ClientState(ctx, NULL, VERT_ATTRIB_POS, true); 7067ec681f3Smrg _mesa_glthread_AttribPointer(ctx, VERT_ATTRIB_POS, layout.vcomps, GL_FLOAT, 7077ec681f3Smrg stride, (GLubyte *) pointer + layout.voffset); 7087ec681f3Smrg} 709