d246d2d4253b936f2765a21024803e5421e285f3
[mesa.git] / src / mesa / main / glthread_varray.c
1 /*
2 * Copyright © 2020 Advanced Micro Devices, Inc.
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 /* This implements vertex array state tracking for glthread. It's separate
25 * from the rest of Mesa. Only minimum functionality is implemented here
26 * to serve glthread.
27 */
28
29 #include "main/glthread.h"
30 #include "main/mtypes.h"
31 #include "main/hash.h"
32 #include "main/dispatch.h"
33
34 /* TODO:
35 * - Implement better tracking of user pointers
36 * - These can unbind user pointers:
37 * ARB_vertex_attrib_binding
38 * ARB_direct_state_access
39 * EXT_direct_state_access
40 */
41
42 static struct glthread_vao *
43 lookup_vao(struct gl_context *ctx, GLuint id)
44 {
45 struct glthread_state *glthread = &ctx->GLThread;
46 struct glthread_vao *vao;
47
48 assert(id != 0);
49
50 if (glthread->LastLookedUpVAO &&
51 glthread->LastLookedUpVAO->Name == id) {
52 vao = glthread->LastLookedUpVAO;
53 } else {
54 vao = _mesa_HashLookupLocked(glthread->VAOs, id);
55 if (!vao)
56 return NULL;
57
58 glthread->LastLookedUpVAO = vao;
59 }
60
61 return vao;
62 }
63
64 void
65 _mesa_glthread_BindVertexArray(struct gl_context *ctx, GLuint id)
66 {
67 struct glthread_state *glthread = &ctx->GLThread;
68
69 if (id == 0) {
70 glthread->CurrentVAO = &glthread->DefaultVAO;
71 } else {
72 struct glthread_vao *vao = lookup_vao(ctx, id);
73
74 if (vao)
75 glthread->CurrentVAO = vao;
76 }
77 }
78
79 void
80 _mesa_glthread_DeleteVertexArrays(struct gl_context *ctx,
81 GLsizei n, const GLuint *ids)
82 {
83 struct glthread_state *glthread = &ctx->GLThread;
84
85 if (!ids)
86 return;
87
88 for (int i = 0; i < n; i++) {
89 /* IDs equal to 0 should be silently ignored. */
90 if (!ids[i])
91 continue;
92
93 struct glthread_vao *vao = lookup_vao(ctx, ids[i]);
94 if (!vao)
95 continue;
96
97 /* If the array object is currently bound, the spec says "the binding
98 * for that object reverts to zero and the default vertex array
99 * becomes current."
100 */
101 if (glthread->CurrentVAO == vao)
102 glthread->CurrentVAO = &glthread->DefaultVAO;
103
104 if (glthread->LastLookedUpVAO == vao)
105 glthread->LastLookedUpVAO = NULL;
106
107 /* The ID is immediately freed for re-use */
108 _mesa_HashRemoveLocked(glthread->VAOs, vao->Name);
109 free(vao);
110 }
111 }
112
113 void
114 _mesa_glthread_GenVertexArrays(struct gl_context *ctx,
115 GLsizei n, GLuint *arrays)
116 {
117 struct glthread_state *glthread = &ctx->GLThread;
118
119 if (!arrays)
120 return;
121
122 /* The IDs have been generated at this point. Create VAOs for glthread. */
123 for (int i = 0; i < n; i++) {
124 GLuint id = arrays[i];
125 struct glthread_vao *vao;
126
127 vao = malloc(sizeof(*vao));
128 if (!vao)
129 continue; /* Is that all we can do? */
130
131 vao->Name = id;
132 vao->HasUserPointer = false;
133 _mesa_HashInsertLocked(glthread->VAOs, id, vao);
134 }
135 }
136
137 void
138 _mesa_glthread_AttribPointer(struct gl_context *ctx)
139 {
140 struct glthread_state *glthread = &ctx->GLThread;
141
142 if (!glthread->vertex_array_is_vbo)
143 glthread->CurrentVAO->HasUserPointer = true;
144 }