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"
36 * - Handle ARB_vertex_attrib_binding (incl. EXT_dsa and ARB_dsa)
39 static struct glthread_vao
*
40 lookup_vao(struct gl_context
*ctx
, GLuint id
)
42 struct glthread_state
*glthread
= &ctx
->GLThread
;
43 struct glthread_vao
*vao
;
47 if (glthread
->LastLookedUpVAO
&&
48 glthread
->LastLookedUpVAO
->Name
== id
) {
49 vao
= glthread
->LastLookedUpVAO
;
51 vao
= _mesa_HashLookupLocked(glthread
->VAOs
, id
);
55 glthread
->LastLookedUpVAO
= vao
;
62 _mesa_glthread_BindVertexArray(struct gl_context
*ctx
, GLuint id
)
64 struct glthread_state
*glthread
= &ctx
->GLThread
;
67 glthread
->CurrentVAO
= &glthread
->DefaultVAO
;
69 struct glthread_vao
*vao
= lookup_vao(ctx
, id
);
72 glthread
->CurrentVAO
= vao
;
77 _mesa_glthread_DeleteVertexArrays(struct gl_context
*ctx
,
78 GLsizei n
, const GLuint
*ids
)
80 struct glthread_state
*glthread
= &ctx
->GLThread
;
85 for (int i
= 0; i
< n
; i
++) {
86 /* IDs equal to 0 should be silently ignored. */
90 struct glthread_vao
*vao
= lookup_vao(ctx
, ids
[i
]);
94 /* If the array object is currently bound, the spec says "the binding
95 * for that object reverts to zero and the default vertex array
98 if (glthread
->CurrentVAO
== vao
)
99 glthread
->CurrentVAO
= &glthread
->DefaultVAO
;
101 if (glthread
->LastLookedUpVAO
== vao
)
102 glthread
->LastLookedUpVAO
= NULL
;
104 /* The ID is immediately freed for re-use */
105 _mesa_HashRemoveLocked(glthread
->VAOs
, vao
->Name
);
111 _mesa_glthread_GenVertexArrays(struct gl_context
*ctx
,
112 GLsizei n
, GLuint
*arrays
)
114 struct glthread_state
*glthread
= &ctx
->GLThread
;
119 /* The IDs have been generated at this point. Create VAOs for glthread. */
120 for (int i
= 0; i
< n
; i
++) {
121 GLuint id
= arrays
[i
];
122 struct glthread_vao
*vao
;
124 vao
= calloc(1, sizeof(*vao
));
126 continue; /* Is that all we can do? */
129 _mesa_HashInsertLocked(glthread
->VAOs
, id
, vao
);
133 /* If vaobj is NULL, use the currently-bound VAO. */
134 static inline struct glthread_vao
*
135 get_vao(struct gl_context
*ctx
, const GLuint
*vaobj
)
138 return lookup_vao(ctx
, *vaobj
);
140 return ctx
->GLThread
.CurrentVAO
;
144 _mesa_glthread_ClientState(struct gl_context
*ctx
, GLuint
*vaobj
,
145 gl_vert_attrib attrib
, bool enable
)
147 if (attrib
>= VERT_ATTRIB_MAX
)
150 struct glthread_vao
*vao
= get_vao(ctx
, vaobj
);
155 vao
->Enabled
|= 1u << attrib
;
157 vao
->Enabled
&= ~(1u << attrib
);
160 void _mesa_glthread_AttribDivisor(struct gl_context
*ctx
, const GLuint
*vaobj
,
161 gl_vert_attrib attrib
, GLuint divisor
)
163 if (attrib
>= VERT_ATTRIB_MAX
)
166 struct glthread_vao
*vao
= get_vao(ctx
, vaobj
);
170 vao
->Attrib
[attrib
].Divisor
= divisor
;
173 vao
->NonZeroDivisorMask
|= 1u << attrib
;
175 vao
->NonZeroDivisorMask
&= ~(1u << attrib
);
179 attrib_pointer(struct glthread_state
*glthread
, struct glthread_vao
*vao
,
180 GLuint buffer
, gl_vert_attrib attrib
,
181 GLint size
, GLenum type
, GLsizei stride
,
184 if (attrib
>= VERT_ATTRIB_MAX
)
187 unsigned elem_size
= _mesa_bytes_per_vertex_attrib(size
, type
);
189 vao
->Attrib
[attrib
].ElementSize
= elem_size
;
190 vao
->Attrib
[attrib
].Stride
= stride
? stride
: elem_size
;
191 vao
->Attrib
[attrib
].Pointer
= pointer
;
194 vao
->UserPointerMask
&= ~(1u << attrib
);
196 vao
->UserPointerMask
|= 1u << attrib
;
200 _mesa_glthread_AttribPointer(struct gl_context
*ctx
, gl_vert_attrib attrib
,
201 GLint size
, GLenum type
, GLsizei stride
,
204 struct glthread_state
*glthread
= &ctx
->GLThread
;
206 attrib_pointer(glthread
, glthread
->CurrentVAO
,
207 glthread
->CurrentArrayBufferName
,
208 attrib
, size
, type
, stride
, pointer
);
212 _mesa_glthread_DSAAttribPointer(struct gl_context
*ctx
, GLuint vaobj
,
213 GLuint buffer
, gl_vert_attrib attrib
,
214 GLint size
, GLenum type
, GLsizei stride
,
217 struct glthread_state
*glthread
= &ctx
->GLThread
;
218 struct glthread_vao
*vao
;
220 vao
= lookup_vao(ctx
, vaobj
);
224 attrib_pointer(glthread
, vao
, buffer
, attrib
, size
, type
, stride
,
225 (const void*)offset
);