2 * Copyright © 2020 Advanced Micro Devices, Inc.
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:
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
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
24 /* This implements vertex array state tracking for glthread. It's separate
25 * from the rest of Mesa. Only minimum functionality is implemented here
29 #include "main/glthread.h"
30 #include "main/glformats.h"
31 #include "main/mtypes.h"
32 #include "main/hash.h"
33 #include "main/dispatch.h"
34 #include "main/varray.h"
37 * - Handle ARB_vertex_attrib_binding (incl. EXT_dsa and ARB_dsa)
40 static struct glthread_vao
*
41 lookup_vao(struct gl_context
*ctx
, GLuint id
)
43 struct glthread_state
*glthread
= &ctx
->GLThread
;
44 struct glthread_vao
*vao
;
48 if (glthread
->LastLookedUpVAO
&&
49 glthread
->LastLookedUpVAO
->Name
== id
) {
50 vao
= glthread
->LastLookedUpVAO
;
52 vao
= _mesa_HashLookupLocked(glthread
->VAOs
, id
);
56 glthread
->LastLookedUpVAO
= vao
;
63 _mesa_glthread_BindVertexArray(struct gl_context
*ctx
, GLuint id
)
65 struct glthread_state
*glthread
= &ctx
->GLThread
;
68 glthread
->CurrentVAO
= &glthread
->DefaultVAO
;
70 struct glthread_vao
*vao
= lookup_vao(ctx
, id
);
73 glthread
->CurrentVAO
= vao
;
78 _mesa_glthread_DeleteVertexArrays(struct gl_context
*ctx
,
79 GLsizei n
, const GLuint
*ids
)
81 struct glthread_state
*glthread
= &ctx
->GLThread
;
86 for (int i
= 0; i
< n
; i
++) {
87 /* IDs equal to 0 should be silently ignored. */
91 struct glthread_vao
*vao
= lookup_vao(ctx
, ids
[i
]);
95 /* If the array object is currently bound, the spec says "the binding
96 * for that object reverts to zero and the default vertex array
99 if (glthread
->CurrentVAO
== vao
)
100 glthread
->CurrentVAO
= &glthread
->DefaultVAO
;
102 if (glthread
->LastLookedUpVAO
== vao
)
103 glthread
->LastLookedUpVAO
= NULL
;
105 /* The ID is immediately freed for re-use */
106 _mesa_HashRemoveLocked(glthread
->VAOs
, vao
->Name
);
112 _mesa_glthread_GenVertexArrays(struct gl_context
*ctx
,
113 GLsizei n
, GLuint
*arrays
)
115 struct glthread_state
*glthread
= &ctx
->GLThread
;
120 /* The IDs have been generated at this point. Create VAOs for glthread. */
121 for (int i
= 0; i
< n
; i
++) {
122 GLuint id
= arrays
[i
];
123 struct glthread_vao
*vao
;
125 vao
= calloc(1, sizeof(*vao
));
127 continue; /* Is that all we can do? */
130 _mesa_HashInsertLocked(glthread
->VAOs
, id
, vao
);
134 /* If vaobj is NULL, use the currently-bound VAO. */
135 static inline struct glthread_vao
*
136 get_vao(struct gl_context
*ctx
, const GLuint
*vaobj
)
139 return lookup_vao(ctx
, *vaobj
);
141 return ctx
->GLThread
.CurrentVAO
;
145 update_primitive_restart(struct gl_context
*ctx
)
147 struct glthread_state
*glthread
= &ctx
->GLThread
;
149 glthread
->_PrimitiveRestart
= glthread
->PrimitiveRestart
||
150 glthread
->PrimitiveRestartFixedIndex
;
151 glthread
->_RestartIndex
[0] =
152 _mesa_get_prim_restart_index(glthread
->PrimitiveRestartFixedIndex
,
153 glthread
->RestartIndex
, 1);
154 glthread
->_RestartIndex
[1] =
155 _mesa_get_prim_restart_index(glthread
->PrimitiveRestartFixedIndex
,
156 glthread
->RestartIndex
, 2);
157 glthread
->_RestartIndex
[3] =
158 _mesa_get_prim_restart_index(glthread
->PrimitiveRestartFixedIndex
,
159 glthread
->RestartIndex
, 4);
163 _mesa_glthread_set_prim_restart(struct gl_context
*ctx
, GLenum cap
, bool value
)
166 case GL_PRIMITIVE_RESTART
:
167 ctx
->GLThread
.PrimitiveRestart
= value
;
169 case GL_PRIMITIVE_RESTART_FIXED_INDEX
:
170 ctx
->GLThread
.PrimitiveRestartFixedIndex
= value
;
174 update_primitive_restart(ctx
);
178 _mesa_glthread_PrimitiveRestartIndex(struct gl_context
*ctx
, GLuint index
)
180 ctx
->GLThread
.RestartIndex
= index
;
181 update_primitive_restart(ctx
);
185 _mesa_glthread_ClientState(struct gl_context
*ctx
, GLuint
*vaobj
,
186 gl_vert_attrib attrib
, bool enable
)
188 /* The primitive restart client state uses a special value. */
189 if (attrib
== VERT_ATTRIB_PRIMITIVE_RESTART_NV
) {
190 ctx
->GLThread
.PrimitiveRestart
= enable
;
191 update_primitive_restart(ctx
);
195 if (attrib
>= VERT_ATTRIB_MAX
)
198 struct glthread_vao
*vao
= get_vao(ctx
, vaobj
);
203 vao
->Enabled
|= 1u << attrib
;
205 vao
->Enabled
&= ~(1u << attrib
);
208 void _mesa_glthread_AttribDivisor(struct gl_context
*ctx
, const GLuint
*vaobj
,
209 gl_vert_attrib attrib
, GLuint divisor
)
211 if (attrib
>= VERT_ATTRIB_MAX
)
214 struct glthread_vao
*vao
= get_vao(ctx
, vaobj
);
218 vao
->Attrib
[attrib
].Divisor
= divisor
;
221 vao
->NonZeroDivisorMask
|= 1u << attrib
;
223 vao
->NonZeroDivisorMask
&= ~(1u << attrib
);
227 attrib_pointer(struct glthread_state
*glthread
, struct glthread_vao
*vao
,
228 GLuint buffer
, gl_vert_attrib attrib
,
229 GLint size
, GLenum type
, GLsizei stride
,
232 if (attrib
>= VERT_ATTRIB_MAX
)
235 unsigned elem_size
= _mesa_bytes_per_vertex_attrib(size
, type
);
237 vao
->Attrib
[attrib
].ElementSize
= elem_size
;
238 vao
->Attrib
[attrib
].Stride
= stride
? stride
: elem_size
;
239 vao
->Attrib
[attrib
].Pointer
= pointer
;
242 vao
->UserPointerMask
&= ~(1u << attrib
);
244 vao
->UserPointerMask
|= 1u << attrib
;
248 _mesa_glthread_AttribPointer(struct gl_context
*ctx
, gl_vert_attrib attrib
,
249 GLint size
, GLenum type
, GLsizei stride
,
252 struct glthread_state
*glthread
= &ctx
->GLThread
;
254 attrib_pointer(glthread
, glthread
->CurrentVAO
,
255 glthread
->CurrentArrayBufferName
,
256 attrib
, size
, type
, stride
, pointer
);
260 _mesa_glthread_DSAAttribPointer(struct gl_context
*ctx
, GLuint vaobj
,
261 GLuint buffer
, gl_vert_attrib attrib
,
262 GLint size
, GLenum type
, GLsizei stride
,
265 struct glthread_state
*glthread
= &ctx
->GLThread
;
266 struct glthread_vao
*vao
;
268 vao
= lookup_vao(ctx
, vaobj
);
272 attrib_pointer(glthread
, vao
, buffer
, attrib
, size
, type
, stride
,
273 (const void*)offset
);