2 * Copyright © 2012 Intel Corporation
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
27 /** Tracks the current bindings for the vertex array and index array buffers.
29 * This is part of what we need to enable glthread on compat-GL contexts that
30 * happen to use VBOs, without also supporting the full tracking of VBO vs
31 * user vertex array bindings per attribute on each vertex array for
32 * determining what to upload at draw call time.
34 * Note that GL core makes it so that a buffer binding with an invalid handle
35 * in the "buffer" parameter will throw an error, and then a
36 * glVertexAttribPointer() that followsmight not end up pointing at a VBO.
37 * However, in GL core the draw call would throw an error as well, so we don't
38 * really care if our tracking is wrong for this case -- we never need to
39 * marshal user data for draw calls, and the unmarshal will just generate an
40 * error or not as appropriate.
42 * For compatibility GL, we do need to accurately know whether the draw call
43 * on the unmarshal side will dereference a user pointer or load data from a
44 * VBO per vertex. That would make it seem like we need to track whether a
45 * "buffer" is valid, so that we can know when an error will be generated
46 * instead of updating the binding. However, compat GL has the ridiculous
47 * feature that if you pass a bad name, it just gens a buffer object for you,
48 * so we escape without having to know if things are valid or not.
51 _mesa_glthread_BindBuffer(struct gl_context
*ctx
, GLenum target
, GLuint buffer
)
53 struct glthread_state
*glthread
= ctx
->GLThread
;
57 glthread
->vertex_array_is_vbo
= (buffer
!= 0);
59 case GL_ELEMENT_ARRAY_BUFFER
:
60 /* The current element array buffer binding is actually tracked in the
61 * vertex array object instead of the context, so this would need to
62 * change on vertex array object updates.
64 glthread
->CurrentVAO
->IndexBufferIsUserPointer
= buffer
!= 0;
66 case GL_DRAW_INDIRECT_BUFFER
:
67 glthread
->draw_indirect_buffer_is_vbo
= buffer
!= 0;
73 /* BufferData: marshalled asynchronously */
74 struct marshal_cmd_BufferData
76 struct marshal_cmd_base cmd_base
;
77 GLuint target_or_name
;
80 const GLvoid
*data_external_mem
;
81 bool data_null
; /* If set, no data follows for "data" */
84 /* Next size bytes are GLubyte data[size] */
88 _mesa_unmarshal_BufferData(struct gl_context
*ctx
,
89 const struct marshal_cmd_BufferData
*cmd
)
91 const GLuint target_or_name
= cmd
->target_or_name
;
92 const GLsizei size
= cmd
->size
;
93 const GLenum usage
= cmd
->usage
;
98 else if (!cmd
->named
&& target_or_name
== GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD
)
99 data
= cmd
->data_external_mem
;
101 data
= (const void *) (cmd
+ 1);
104 CALL_NamedBufferDataEXT(ctx
->CurrentServerDispatch
,
105 (target_or_name
, size
, data
, usage
));
106 } else if (cmd
->named
) {
107 CALL_NamedBufferData(ctx
->CurrentServerDispatch
,
108 (target_or_name
, size
, data
, usage
));
110 CALL_BufferData(ctx
->CurrentServerDispatch
,
111 (target_or_name
, size
, data
, usage
));
116 _mesa_unmarshal_NamedBufferData(struct gl_context
*ctx
,
117 const struct marshal_cmd_NamedBufferData
*cmd
)
119 unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData");
123 _mesa_unmarshal_NamedBufferDataEXT(struct gl_context
*ctx
,
124 const struct marshal_cmd_NamedBufferDataEXT
*cmd
)
126 unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData");
130 _mesa_marshal_BufferData_merged(GLuint target_or_name
, GLsizeiptr size
,
131 const GLvoid
*data
, GLenum usage
, bool named
,
132 bool ext_dsa
, const char *func
)
134 GET_CURRENT_CONTEXT(ctx
);
135 bool external_mem
= !named
&&
136 target_or_name
== GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD
;
137 bool copy_data
= data
&& !external_mem
;
138 int cmd_size
= sizeof(struct marshal_cmd_BufferData
) + (copy_data
? size
: 0);
140 if (unlikely(size
< 0 || size
> INT_MAX
|| cmd_size
< 0 ||
141 cmd_size
> MARSHAL_MAX_CMD_SIZE
||
142 (named
&& target_or_name
== 0))) {
143 _mesa_glthread_finish_before(ctx
, func
);
145 CALL_NamedBufferData(ctx
->CurrentServerDispatch
,
146 (target_or_name
, size
, data
, usage
));
148 CALL_BufferData(ctx
->CurrentServerDispatch
,
149 (target_or_name
, size
, data
, usage
));
154 struct marshal_cmd_BufferData
*cmd
=
155 _mesa_glthread_allocate_command(ctx
, DISPATCH_CMD_BufferData
,
158 cmd
->target_or_name
= target_or_name
;
161 cmd
->data_null
= !data
;
163 cmd
->ext_dsa
= ext_dsa
;
164 cmd
->data_external_mem
= data
;
167 char *variable_data
= (char *) (cmd
+ 1);
168 memcpy(variable_data
, data
, size
);
173 _mesa_marshal_BufferData(GLenum target
, GLsizeiptr size
, const GLvoid
* data
,
176 _mesa_marshal_BufferData_merged(target
, size
, data
, usage
, false, false,
181 _mesa_marshal_NamedBufferData(GLuint buffer
, GLsizeiptr size
,
182 const GLvoid
* data
, GLenum usage
)
184 _mesa_marshal_BufferData_merged(buffer
, size
, data
, usage
, true, false,
189 _mesa_marshal_NamedBufferDataEXT(GLuint buffer
, GLsizeiptr size
,
190 const GLvoid
*data
, GLenum usage
)
192 _mesa_marshal_BufferData_merged(buffer
, size
, data
, usage
, true, true,
193 "NamedBufferDataEXT");
197 /* BufferSubData: marshalled asynchronously */
198 struct marshal_cmd_BufferSubData
200 struct marshal_cmd_base cmd_base
;
201 GLenum target_or_name
;
206 /* Next size bytes are GLubyte data[size] */
210 _mesa_unmarshal_BufferSubData(struct gl_context
*ctx
,
211 const struct marshal_cmd_BufferSubData
*cmd
)
213 const GLenum target_or_name
= cmd
->target_or_name
;
214 const GLintptr offset
= cmd
->offset
;
215 const GLsizeiptr size
= cmd
->size
;
216 const void *data
= (const void *) (cmd
+ 1);
219 CALL_NamedBufferSubDataEXT(ctx
->CurrentServerDispatch
,
220 (target_or_name
, offset
, size
, data
));
221 } else if (cmd
->named
) {
222 CALL_NamedBufferSubData(ctx
->CurrentServerDispatch
,
223 (target_or_name
, offset
, size
, data
));
225 CALL_BufferSubData(ctx
->CurrentServerDispatch
,
226 (target_or_name
, offset
, size
, data
));
231 _mesa_unmarshal_NamedBufferSubData(struct gl_context
*ctx
,
232 const struct marshal_cmd_NamedBufferSubData
*cmd
)
234 unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData");
238 _mesa_unmarshal_NamedBufferSubDataEXT(struct gl_context
*ctx
,
239 const struct marshal_cmd_NamedBufferSubDataEXT
*cmd
)
241 unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData");
245 _mesa_marshal_BufferSubData_merged(GLuint target_or_name
, GLintptr offset
,
246 GLsizeiptr size
, const GLvoid
*data
,
247 bool named
, bool ext_dsa
, const char *func
)
249 GET_CURRENT_CONTEXT(ctx
);
250 size_t cmd_size
= sizeof(struct marshal_cmd_BufferSubData
) + size
;
252 if (unlikely(size
< 0 || size
> INT_MAX
|| cmd_size
< 0 ||
253 cmd_size
> MARSHAL_MAX_CMD_SIZE
|| !data
||
254 (named
&& target_or_name
== 0))) {
255 _mesa_glthread_finish_before(ctx
, func
);
257 CALL_NamedBufferSubData(ctx
->CurrentServerDispatch
,
258 (target_or_name
, offset
, size
, data
));
260 CALL_BufferSubData(ctx
->CurrentServerDispatch
,
261 (target_or_name
, offset
, size
, data
));
266 struct marshal_cmd_BufferSubData
*cmd
=
267 _mesa_glthread_allocate_command(ctx
, DISPATCH_CMD_BufferSubData
,
269 cmd
->target_or_name
= target_or_name
;
270 cmd
->offset
= offset
;
273 cmd
->ext_dsa
= ext_dsa
;
275 char *variable_data
= (char *) (cmd
+ 1);
276 memcpy(variable_data
, data
, size
);
280 _mesa_marshal_BufferSubData(GLenum target
, GLintptr offset
, GLsizeiptr size
,
283 _mesa_marshal_BufferSubData_merged(target
, offset
, size
, data
, false,
284 false, "BufferSubData");
288 _mesa_marshal_NamedBufferSubData(GLuint buffer
, GLintptr offset
,
289 GLsizeiptr size
, const GLvoid
* data
)
291 _mesa_marshal_BufferSubData_merged(buffer
, offset
, size
, data
, true,
292 false, "NamedBufferSubData");
296 _mesa_marshal_NamedBufferSubDataEXT(GLuint buffer
, GLintptr offset
,
297 GLsizeiptr size
, const GLvoid
* data
)
299 _mesa_marshal_BufferSubData_merged(buffer
, offset
, size
, data
, true,
300 true, "NamedBufferSubDataEXT");