mesa/st: accept NULL and empty buffer objects
[mesa.git] / src / mesa / state_tracker / st_atom_array.c
1
2 /**************************************************************************
3 *
4 * Copyright 2007 VMware, Inc.
5 * Copyright 2012 Marek Olšák <maraeo@gmail.com>
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 * IN NO EVENT SHALL AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30 /*
31 * This converts the VBO's vertex attribute/array information into
32 * Gallium vertex state and binds it.
33 *
34 * Authors:
35 * Keith Whitwell <keithw@vmware.com>
36 * Marek Olšák <maraeo@gmail.com>
37 */
38
39 #include "st_context.h"
40 #include "st_atom.h"
41 #include "st_cb_bufferobjects.h"
42 #include "st_draw.h"
43 #include "st_program.h"
44
45 #include "cso_cache/cso_context.h"
46 #include "util/u_math.h"
47 #include "util/u_upload_mgr.h"
48 #include "main/bufferobj.h"
49 #include "main/glformats.h"
50 #include "main/varray.h"
51 #include "main/arrayobj.h"
52
53 /* vertex_formats[gltype - GL_BYTE][integer*2 + normalized][size - 1] */
54 static const uint16_t vertex_formats[][4][4] = {
55 { /* GL_BYTE */
56 {
57 PIPE_FORMAT_R8_SSCALED,
58 PIPE_FORMAT_R8G8_SSCALED,
59 PIPE_FORMAT_R8G8B8_SSCALED,
60 PIPE_FORMAT_R8G8B8A8_SSCALED
61 },
62 {
63 PIPE_FORMAT_R8_SNORM,
64 PIPE_FORMAT_R8G8_SNORM,
65 PIPE_FORMAT_R8G8B8_SNORM,
66 PIPE_FORMAT_R8G8B8A8_SNORM
67 },
68 {
69 PIPE_FORMAT_R8_SINT,
70 PIPE_FORMAT_R8G8_SINT,
71 PIPE_FORMAT_R8G8B8_SINT,
72 PIPE_FORMAT_R8G8B8A8_SINT
73 },
74 },
75 { /* GL_UNSIGNED_BYTE */
76 {
77 PIPE_FORMAT_R8_USCALED,
78 PIPE_FORMAT_R8G8_USCALED,
79 PIPE_FORMAT_R8G8B8_USCALED,
80 PIPE_FORMAT_R8G8B8A8_USCALED
81 },
82 {
83 PIPE_FORMAT_R8_UNORM,
84 PIPE_FORMAT_R8G8_UNORM,
85 PIPE_FORMAT_R8G8B8_UNORM,
86 PIPE_FORMAT_R8G8B8A8_UNORM
87 },
88 {
89 PIPE_FORMAT_R8_UINT,
90 PIPE_FORMAT_R8G8_UINT,
91 PIPE_FORMAT_R8G8B8_UINT,
92 PIPE_FORMAT_R8G8B8A8_UINT
93 },
94 },
95 { /* GL_SHORT */
96 {
97 PIPE_FORMAT_R16_SSCALED,
98 PIPE_FORMAT_R16G16_SSCALED,
99 PIPE_FORMAT_R16G16B16_SSCALED,
100 PIPE_FORMAT_R16G16B16A16_SSCALED
101 },
102 {
103 PIPE_FORMAT_R16_SNORM,
104 PIPE_FORMAT_R16G16_SNORM,
105 PIPE_FORMAT_R16G16B16_SNORM,
106 PIPE_FORMAT_R16G16B16A16_SNORM
107 },
108 {
109 PIPE_FORMAT_R16_SINT,
110 PIPE_FORMAT_R16G16_SINT,
111 PIPE_FORMAT_R16G16B16_SINT,
112 PIPE_FORMAT_R16G16B16A16_SINT
113 },
114 },
115 { /* GL_UNSIGNED_SHORT */
116 {
117 PIPE_FORMAT_R16_USCALED,
118 PIPE_FORMAT_R16G16_USCALED,
119 PIPE_FORMAT_R16G16B16_USCALED,
120 PIPE_FORMAT_R16G16B16A16_USCALED
121 },
122 {
123 PIPE_FORMAT_R16_UNORM,
124 PIPE_FORMAT_R16G16_UNORM,
125 PIPE_FORMAT_R16G16B16_UNORM,
126 PIPE_FORMAT_R16G16B16A16_UNORM
127 },
128 {
129 PIPE_FORMAT_R16_UINT,
130 PIPE_FORMAT_R16G16_UINT,
131 PIPE_FORMAT_R16G16B16_UINT,
132 PIPE_FORMAT_R16G16B16A16_UINT
133 },
134 },
135 { /* GL_INT */
136 {
137 PIPE_FORMAT_R32_SSCALED,
138 PIPE_FORMAT_R32G32_SSCALED,
139 PIPE_FORMAT_R32G32B32_SSCALED,
140 PIPE_FORMAT_R32G32B32A32_SSCALED
141 },
142 {
143 PIPE_FORMAT_R32_SNORM,
144 PIPE_FORMAT_R32G32_SNORM,
145 PIPE_FORMAT_R32G32B32_SNORM,
146 PIPE_FORMAT_R32G32B32A32_SNORM
147 },
148 {
149 PIPE_FORMAT_R32_SINT,
150 PIPE_FORMAT_R32G32_SINT,
151 PIPE_FORMAT_R32G32B32_SINT,
152 PIPE_FORMAT_R32G32B32A32_SINT
153 },
154 },
155 { /* GL_UNSIGNED_INT */
156 {
157 PIPE_FORMAT_R32_USCALED,
158 PIPE_FORMAT_R32G32_USCALED,
159 PIPE_FORMAT_R32G32B32_USCALED,
160 PIPE_FORMAT_R32G32B32A32_USCALED
161 },
162 {
163 PIPE_FORMAT_R32_UNORM,
164 PIPE_FORMAT_R32G32_UNORM,
165 PIPE_FORMAT_R32G32B32_UNORM,
166 PIPE_FORMAT_R32G32B32A32_UNORM
167 },
168 {
169 PIPE_FORMAT_R32_UINT,
170 PIPE_FORMAT_R32G32_UINT,
171 PIPE_FORMAT_R32G32B32_UINT,
172 PIPE_FORMAT_R32G32B32A32_UINT
173 },
174 },
175 { /* GL_FLOAT */
176 {
177 PIPE_FORMAT_R32_FLOAT,
178 PIPE_FORMAT_R32G32_FLOAT,
179 PIPE_FORMAT_R32G32B32_FLOAT,
180 PIPE_FORMAT_R32G32B32A32_FLOAT
181 },
182 {
183 PIPE_FORMAT_R32_FLOAT,
184 PIPE_FORMAT_R32G32_FLOAT,
185 PIPE_FORMAT_R32G32B32_FLOAT,
186 PIPE_FORMAT_R32G32B32A32_FLOAT
187 },
188 },
189 {{0}}, /* GL_2_BYTES */
190 {{0}}, /* GL_3_BYTES */
191 {{0}}, /* GL_4_BYTES */
192 { /* GL_DOUBLE */
193 {
194 PIPE_FORMAT_R64_FLOAT,
195 PIPE_FORMAT_R64G64_FLOAT,
196 PIPE_FORMAT_R64G64B64_FLOAT,
197 PIPE_FORMAT_R64G64B64A64_FLOAT
198 },
199 {
200 PIPE_FORMAT_R64_FLOAT,
201 PIPE_FORMAT_R64G64_FLOAT,
202 PIPE_FORMAT_R64G64B64_FLOAT,
203 PIPE_FORMAT_R64G64B64A64_FLOAT
204 },
205 },
206 { /* GL_HALF_FLOAT */
207 {
208 PIPE_FORMAT_R16_FLOAT,
209 PIPE_FORMAT_R16G16_FLOAT,
210 PIPE_FORMAT_R16G16B16_FLOAT,
211 PIPE_FORMAT_R16G16B16A16_FLOAT
212 },
213 {
214 PIPE_FORMAT_R16_FLOAT,
215 PIPE_FORMAT_R16G16_FLOAT,
216 PIPE_FORMAT_R16G16B16_FLOAT,
217 PIPE_FORMAT_R16G16B16A16_FLOAT
218 },
219 },
220 { /* GL_FIXED */
221 {
222 PIPE_FORMAT_R32_FIXED,
223 PIPE_FORMAT_R32G32_FIXED,
224 PIPE_FORMAT_R32G32B32_FIXED,
225 PIPE_FORMAT_R32G32B32A32_FIXED
226 },
227 {
228 PIPE_FORMAT_R32_FIXED,
229 PIPE_FORMAT_R32G32_FIXED,
230 PIPE_FORMAT_R32G32B32_FIXED,
231 PIPE_FORMAT_R32G32B32A32_FIXED
232 },
233 },
234 };
235
236
237 /**
238 * Return a PIPE_FORMAT_x for the given GL datatype and size.
239 */
240 static enum pipe_format
241 st_pipe_vertex_format(const struct gl_vertex_format *vformat)
242 {
243 const GLubyte size = vformat->Size;
244 const GLenum16 format = vformat->Format;
245 const bool normalized = vformat->Normalized;
246 const bool integer = vformat->Integer;
247 GLenum16 type = vformat->Type;
248 unsigned index;
249
250 assert(size >= 1 && size <= 4);
251 assert(format == GL_RGBA || format == GL_BGRA);
252 assert(vformat->_ElementSize == _mesa_bytes_per_vertex_attrib(size, type));
253
254 switch (type) {
255 case GL_HALF_FLOAT_OES:
256 type = GL_HALF_FLOAT;
257 break;
258
259 case GL_INT_2_10_10_10_REV:
260 assert(size == 4 && !integer);
261
262 if (format == GL_BGRA) {
263 if (normalized)
264 return PIPE_FORMAT_B10G10R10A2_SNORM;
265 else
266 return PIPE_FORMAT_B10G10R10A2_SSCALED;
267 } else {
268 if (normalized)
269 return PIPE_FORMAT_R10G10B10A2_SNORM;
270 else
271 return PIPE_FORMAT_R10G10B10A2_SSCALED;
272 }
273 break;
274
275 case GL_UNSIGNED_INT_2_10_10_10_REV:
276 assert(size == 4 && !integer);
277
278 if (format == GL_BGRA) {
279 if (normalized)
280 return PIPE_FORMAT_B10G10R10A2_UNORM;
281 else
282 return PIPE_FORMAT_B10G10R10A2_USCALED;
283 } else {
284 if (normalized)
285 return PIPE_FORMAT_R10G10B10A2_UNORM;
286 else
287 return PIPE_FORMAT_R10G10B10A2_USCALED;
288 }
289 break;
290
291 case GL_UNSIGNED_INT_10F_11F_11F_REV:
292 assert(size == 3 && !integer && format == GL_RGBA);
293 return PIPE_FORMAT_R11G11B10_FLOAT;
294
295 case GL_UNSIGNED_BYTE:
296 if (format == GL_BGRA) {
297 /* this is an odd-ball case */
298 assert(normalized);
299 return PIPE_FORMAT_B8G8R8A8_UNORM;
300 }
301 break;
302 }
303
304 index = integer*2 + normalized;
305 assert(index <= 2);
306 assert(type >= GL_BYTE && type <= GL_FIXED);
307 return vertex_formats[type - GL_BYTE][index][size-1];
308 }
309
310 static void init_velement(struct pipe_vertex_element *velement,
311 int src_offset, int format,
312 int instance_divisor, int vbo_index)
313 {
314 velement->src_offset = src_offset;
315 velement->src_format = format;
316 velement->instance_divisor = instance_divisor;
317 velement->vertex_buffer_index = vbo_index;
318 assert(velement->src_format);
319 }
320
321 static void init_velement_lowered(const struct st_vertex_program *vp,
322 struct pipe_vertex_element *velements,
323 const struct gl_vertex_format *vformat,
324 int src_offset, int instance_divisor,
325 int vbo_index, int idx)
326 {
327 const GLubyte nr_components = vformat->Size;
328
329 if (vformat->Doubles) {
330 int lower_format;
331
332 if (nr_components < 2)
333 lower_format = PIPE_FORMAT_R32G32_UINT;
334 else
335 lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
336
337 init_velement(&velements[idx], src_offset,
338 lower_format, instance_divisor, vbo_index);
339 idx++;
340
341 if (idx < vp->num_inputs &&
342 vp->index_to_input[idx] == ST_DOUBLE_ATTRIB_PLACEHOLDER) {
343 if (nr_components >= 3) {
344 if (nr_components == 3)
345 lower_format = PIPE_FORMAT_R32G32_UINT;
346 else
347 lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
348
349 init_velement(&velements[idx], src_offset + 4 * sizeof(float),
350 lower_format, instance_divisor, vbo_index);
351 } else {
352 /* The values here are undefined. Fill in some conservative
353 * dummy values.
354 */
355 init_velement(&velements[idx], src_offset, PIPE_FORMAT_R32G32_UINT,
356 instance_divisor, vbo_index);
357 }
358 }
359 } else {
360 const unsigned format = st_pipe_vertex_format(vformat);
361
362 init_velement(&velements[idx], src_offset,
363 format, instance_divisor, vbo_index);
364 }
365 }
366
367 static void
368 set_vertex_attribs(struct st_context *st,
369 struct pipe_vertex_buffer *vbuffers,
370 unsigned num_vbuffers,
371 struct pipe_vertex_element *velements,
372 unsigned num_velements)
373 {
374 struct cso_context *cso = st->cso_context;
375
376 cso_set_vertex_buffers(cso, 0, num_vbuffers, vbuffers);
377 if (st->last_num_vbuffers > num_vbuffers) {
378 /* Unbind remaining buffers, if any. */
379 cso_set_vertex_buffers(cso, num_vbuffers,
380 st->last_num_vbuffers - num_vbuffers, NULL);
381 }
382 st->last_num_vbuffers = num_vbuffers;
383 cso_set_vertex_elements(cso, num_velements, velements);
384 }
385
386 void
387 st_setup_arrays(struct st_context *st,
388 const struct st_vertex_program *vp,
389 const struct st_vp_variant *vp_variant,
390 struct pipe_vertex_element *velements,
391 struct pipe_vertex_buffer *vbuffer, unsigned *num_vbuffers)
392 {
393 struct gl_context *ctx = st->ctx;
394 const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;
395 const GLbitfield inputs_read = vp_variant->vert_attrib_mask;
396 const ubyte *input_to_index = vp->input_to_index;
397
398 /* Process attribute array data. */
399 GLbitfield mask = inputs_read & _mesa_draw_array_bits(ctx);
400 while (mask) {
401 /* The attribute index to start pulling a binding */
402 const gl_vert_attrib i = ffs(mask) - 1;
403 const struct gl_vertex_buffer_binding *const binding
404 = _mesa_draw_buffer_binding(vao, i);
405 const unsigned bufidx = (*num_vbuffers)++;
406
407 if (_mesa_is_bufferobj(binding->BufferObj)) {
408 /* Set the binding */
409 struct st_buffer_object *stobj = st_buffer_object(binding->BufferObj);
410 vbuffer[bufidx].buffer.resource = stobj ? stobj->buffer : NULL;
411 vbuffer[bufidx].is_user_buffer = false;
412 vbuffer[bufidx].buffer_offset = _mesa_draw_binding_offset(binding);
413 } else {
414 /* Set the binding */
415 const void *ptr = (const void *)_mesa_draw_binding_offset(binding);
416 vbuffer[bufidx].buffer.user = ptr;
417 vbuffer[bufidx].is_user_buffer = true;
418 vbuffer[bufidx].buffer_offset = 0;
419
420 if (!binding->InstanceDivisor)
421 st->draw_needs_minmax_index = true;
422 }
423 vbuffer[bufidx].stride = binding->Stride; /* in bytes */
424
425 const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding);
426 GLbitfield attrmask = mask & boundmask;
427 /* Mark the those attributes as processed */
428 mask &= ~boundmask;
429 /* We can assume that we have array for the binding */
430 assert(attrmask);
431 /* Walk attributes belonging to the binding */
432 while (attrmask) {
433 const gl_vert_attrib attr = u_bit_scan(&attrmask);
434 const struct gl_array_attributes *const attrib
435 = _mesa_draw_array_attrib(vao, attr);
436 const GLuint off = _mesa_draw_attributes_relative_offset(attrib);
437 init_velement_lowered(vp, velements, &attrib->Format, off,
438 binding->InstanceDivisor, bufidx,
439 input_to_index[attr]);
440 }
441 }
442 }
443
444 void
445 st_setup_current(struct st_context *st,
446 const struct st_vertex_program *vp,
447 const struct st_vp_variant *vp_variant,
448 struct pipe_vertex_element *velements,
449 struct pipe_vertex_buffer *vbuffer, unsigned *num_vbuffers)
450 {
451 struct gl_context *ctx = st->ctx;
452 const GLbitfield inputs_read = vp_variant->vert_attrib_mask;
453
454 /* Process values that should have better been uniforms in the application */
455 GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx);
456 if (curmask) {
457 /* vertex program validation must be done before this */
458 const struct st_vertex_program *vp = st->vp;
459 const ubyte *input_to_index = vp->input_to_index;
460 /* For each attribute, upload the maximum possible size. */
461 GLubyte data[VERT_ATTRIB_MAX * sizeof(GLdouble) * 4];
462 GLubyte *cursor = data;
463 const unsigned bufidx = (*num_vbuffers)++;
464 unsigned max_alignment = 1;
465
466 while (curmask) {
467 const gl_vert_attrib attr = u_bit_scan(&curmask);
468 const struct gl_array_attributes *const attrib
469 = _mesa_draw_current_attrib(ctx, attr);
470 const unsigned size = attrib->Format._ElementSize;
471 const unsigned alignment = util_next_power_of_two(size);
472 max_alignment = MAX2(max_alignment, alignment);
473 memcpy(cursor, attrib->Ptr, size);
474 if (alignment != size)
475 memset(cursor + size, 0, alignment - size);
476
477 init_velement_lowered(vp, velements, &attrib->Format, cursor - data, 0,
478 bufidx, input_to_index[attr]);
479
480 cursor += alignment;
481 }
482
483 vbuffer[bufidx].is_user_buffer = false;
484 vbuffer[bufidx].buffer.resource = NULL;
485 /* vbuffer[bufidx].buffer_offset is set below */
486 vbuffer[bufidx].stride = 0;
487
488 /* Use const_uploader for zero-stride vertex attributes, because
489 * it may use a better memory placement than stream_uploader.
490 * The reason is that zero-stride attributes can be fetched many
491 * times (thousands of times), so a better placement is going to
492 * perform better.
493 */
494 struct u_upload_mgr *uploader = st->can_bind_const_buffer_as_vertex ?
495 st->pipe->const_uploader :
496 st->pipe->stream_uploader;
497 u_upload_data(uploader,
498 0, cursor - data, max_alignment, data,
499 &vbuffer[bufidx].buffer_offset,
500 &vbuffer[bufidx].buffer.resource);
501 /* Always unmap. The uploader might use explicit flushes. */
502 u_upload_unmap(uploader);
503 }
504 }
505
506 void
507 st_setup_current_user(struct st_context *st,
508 const struct st_vertex_program *vp,
509 const struct st_vp_variant *vp_variant,
510 struct pipe_vertex_element *velements,
511 struct pipe_vertex_buffer *vbuffer, unsigned *num_vbuffers)
512 {
513 struct gl_context *ctx = st->ctx;
514 const GLbitfield inputs_read = vp_variant->vert_attrib_mask;
515 const ubyte *input_to_index = vp->input_to_index;
516
517 /* Process values that should have better been uniforms in the application */
518 GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx);
519 /* For each attribute, make an own user buffer binding. */
520 while (curmask) {
521 const gl_vert_attrib attr = u_bit_scan(&curmask);
522 const struct gl_array_attributes *const attrib
523 = _mesa_draw_current_attrib(ctx, attr);
524 const unsigned bufidx = (*num_vbuffers)++;
525
526 init_velement_lowered(vp, velements, &attrib->Format, 0, 0,
527 bufidx, input_to_index[attr]);
528
529 vbuffer[bufidx].is_user_buffer = true;
530 vbuffer[bufidx].buffer.user = attrib->Ptr;
531 vbuffer[bufidx].buffer_offset = 0;
532 vbuffer[bufidx].stride = 0;
533 }
534 }
535
536 void
537 st_update_array(struct st_context *st)
538 {
539 /* vertex program validation must be done before this */
540 /* _NEW_PROGRAM, ST_NEW_VS_STATE */
541 const struct st_vertex_program *vp = st->vp;
542 const struct st_vp_variant *vp_variant = st->vp_variant;
543
544 struct pipe_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];
545 unsigned num_vbuffers = 0, first_upload_vbuffer;
546 struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
547 unsigned num_velements;
548
549 st->vertex_array_out_of_memory = FALSE;
550 st->draw_needs_minmax_index = false;
551
552 /* ST_NEW_VERTEX_ARRAYS alias ctx->DriverFlags.NewArray */
553 /* Setup arrays */
554 st_setup_arrays(st, vp, vp_variant, velements, vbuffer, &num_vbuffers);
555 if (st->vertex_array_out_of_memory)
556 return;
557
558 /* _NEW_CURRENT_ATTRIB */
559 /* Setup current uploads */
560 first_upload_vbuffer = num_vbuffers;
561 st_setup_current(st, vp, vp_variant, velements, vbuffer, &num_vbuffers);
562
563 /* Set the array into cso */
564 num_velements = vp_variant->num_inputs;
565 set_vertex_attribs(st, vbuffer, num_vbuffers, velements, num_velements);
566
567 /* Unreference uploaded buffer resources. */
568 for (unsigned i = first_upload_vbuffer; i < num_vbuffers; ++i) {
569 pipe_resource_reference(&vbuffer[i].buffer.resource, NULL);
570 }
571 }