summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2011-01-29 20:53:57 +0100
committerMarek Olšák <maraeo@gmail.com>2011-02-07 02:23:46 +0100
commit975320ab76f5c247f6ed4dab80627173845200d0 (patch)
tree888695efaf5d0056df04e85a61ebfe5beaa9c431
parent1c2a4f0820ff2272f993e6da28dcf8bcbbc3252a (diff)
util: import a new vertex buffer manager
This code has originally matured in r300g and was ported to r600g several times. It was obvious it's a code duplication. See also comments in the header file.
-rw-r--r--src/gallium/auxiliary/Makefile3
-rw-r--r--src/gallium/auxiliary/SConscript1
-rw-r--r--src/gallium/auxiliary/util/u_vbuf_mgr.c606
-rw-r--r--src/gallium/auxiliary/util/u_vbuf_mgr.h113
4 files changed, 722 insertions, 1 deletions
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index ff355c47832..7d7d700eacd 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -142,7 +142,8 @@ C_SOURCES = \
142 util/u_tile.c \ 142 util/u_tile.c \
143 util/u_transfer.c \ 143 util/u_transfer.c \
144 util/u_resource.c \ 144 util/u_resource.c \
145 util/u_upload_mgr.c 145 util/u_upload_mgr.c \
146 util/u_vbuf_mgr.c
146 147
147 # Disabling until pipe-video branch gets merged in 148 # Disabling until pipe-video branch gets merged in
148 #vl/vl_bitstream_parser.c \ 149 #vl/vl_bitstream_parser.c \
diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript
index fca7e5fd117..0ec63071615 100644
--- a/src/gallium/auxiliary/SConscript
+++ b/src/gallium/auxiliary/SConscript
@@ -190,6 +190,7 @@ source = [
190 'util/u_tile.c', 190 'util/u_tile.c',
191 'util/u_transfer.c', 191 'util/u_transfer.c',
192 'util/u_upload_mgr.c', 192 'util/u_upload_mgr.c',
193 'util/u_vbuf_mgr.c',
193 # Disabling until pipe-video branch gets merged in 194 # Disabling until pipe-video branch gets merged in
194 #'vl/vl_bitstream_parser.c', 195 #'vl/vl_bitstream_parser.c',
195 #'vl/vl_mpeg12_mc_renderer.c', 196 #'vl/vl_mpeg12_mc_renderer.c',
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.c b/src/gallium/auxiliary/util/u_vbuf_mgr.c
new file mode 100644
index 00000000000..28c7f727ef8
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_vbuf_mgr.c
@@ -0,0 +1,606 @@
1/**************************************************************************
2 *
3 * Copyright 2011 Marek Olšák <maraeo@gmail.com>
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "util/u_vbuf_mgr.h"
29
30#include "util/u_format.h"
31#include "util/u_inlines.h"
32#include "util/u_memory.h"
33#include "util/u_upload_mgr.h"
34#include "translate/translate.h"
35#include "translate/translate_cache.h"
36
37/* Hardware vertex fetcher limitations can be described by this structure. */
38struct u_vbuf_caps {
39 /* Vertex format CAPs. */
40 /* TRUE if hardware supports it. */
41 unsigned format_fixed32:1; /* PIPE_FORMAT_*32*_FIXED */
42 unsigned format_float16:1; /* PIPE_FORMAT_*16*_FLOAT */
43 unsigned format_float64:1; /* PIPE_FORMAT_*64*_FLOAT */
44 unsigned format_norm32:1; /* PIPE_FORMAT_*32*NORM */
45 unsigned format_scaled32:1; /* PIPE_FORMAT_*32*SCALED */
46
47 /* Whether vertex fetches don't have to be dword-aligned. */
48 /* TRUE if hardware supports it. */
49 unsigned fetch_dword_unaligned:1;
50};
51
52struct u_vbuf_mgr_elements {
53 unsigned count;
54 struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
55
56 /* If (velem[i].src_format != real_format[i]), the vertex buffer
57 * referenced by the vertex element cannot be used for rendering and
58 * its vertex data must be translated to real_format[i]. */
59 enum pipe_format native_format[PIPE_MAX_ATTRIBS];
60 unsigned native_format_size[PIPE_MAX_ATTRIBS];
61
62 /* This might mean two things:
63 * - src_format != native_format, as discussed above.
64 * - src_offset % 4 != 0 (if the caps don't allow such an offset). */
65 boolean incompatible_layout;
66};
67
68struct u_vbuf_mgr_priv {
69 struct u_vbuf_mgr b;
70 struct u_vbuf_caps caps;
71 struct pipe_context *pipe;
72
73 struct translate_cache *translate_cache;
74 unsigned translate_vb_slot;
75
76 struct u_upload_mgr *uploader;
77
78 struct u_vbuf_mgr_elements *ve;
79 void *saved_ve, *fallback_ve;
80 boolean ve_binding_lock;
81
82 boolean any_user_vbs;
83 boolean incompatible_vb_layout;
84};
85
86static void u_vbuf_mgr_init_format_caps(struct u_vbuf_mgr_priv *mgr)
87{
88 struct pipe_screen *screen = mgr->pipe->screen;
89
90 mgr->caps.format_fixed32 =
91 screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER,
92 0, PIPE_BIND_VERTEX_BUFFER, 0);
93
94 mgr->caps.format_float16 =
95 screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER,
96 0, PIPE_BIND_VERTEX_BUFFER, 0);
97
98 mgr->caps.format_float64 =
99 screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER,
100 0, PIPE_BIND_VERTEX_BUFFER, 0);
101
102 mgr->caps.format_norm32 =
103 screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER,
104 0, PIPE_BIND_VERTEX_BUFFER, 0) &&
105 screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER,
106 0, PIPE_BIND_VERTEX_BUFFER, 0);
107
108 mgr->caps.format_scaled32 =
109 screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER,
110 0, PIPE_BIND_VERTEX_BUFFER, 0) &&
111 screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER,
112 0, PIPE_BIND_VERTEX_BUFFER, 0);
113}
114
115struct u_vbuf_mgr *
116u_vbuf_mgr_create(struct pipe_context *pipe,
117 unsigned upload_buffer_size,
118 unsigned upload_buffer_alignment,
119 enum u_fetch_alignment fetch_alignment)
120{
121 struct u_vbuf_mgr_priv *mgr = CALLOC_STRUCT(u_vbuf_mgr_priv);
122
123 mgr->pipe = pipe;
124 mgr->translate_cache = translate_cache_create();
125
126 mgr->uploader = u_upload_create(pipe, upload_buffer_size,
127 upload_buffer_alignment,
128 PIPE_BIND_VERTEX_BUFFER);
129
130 mgr->caps.fetch_dword_unaligned =
131 fetch_alignment == U_VERTEX_FETCH_BYTE_ALIGNED;
132
133 u_vbuf_mgr_init_format_caps(mgr);
134
135 return &mgr->b;
136}
137
138void u_vbuf_mgr_destroy(struct u_vbuf_mgr *mgrb)
139{
140 struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
141 unsigned i;
142
143 for (i = 0; i < mgr->b.nr_real_vertex_buffers; i++) {
144 pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL);
145 pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL);
146 }
147
148 translate_cache_destroy(mgr->translate_cache);
149 u_upload_destroy(mgr->uploader);
150 FREE(mgr);
151}
152
153
154static void u_vbuf_translate_begin(struct u_vbuf_mgr_priv *mgr,
155 int min_index, int max_index,
156 boolean *upload_flushed)
157{
158 struct translate_key key = {0};
159 struct translate_element *te;
160 unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0};
161 struct translate *tr;
162 boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
163 uint8_t *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
164 struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0};
165 struct pipe_resource *out_buffer = NULL;
166 unsigned i, num_verts, out_offset;
167 struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
168
169 /* Initialize the translate key, i.e. the recipe how vertices should be
170 * translated. */
171 for (i = 0; i < mgr->ve->count; i++) {
172 struct pipe_vertex_buffer *vb =
173 &mgr->b.vertex_buffer[mgr->ve->ve[i].vertex_buffer_index];
174 enum pipe_format output_format = mgr->ve->native_format[i];
175 unsigned output_format_size = mgr->ve->native_format_size[i];
176
177 /* Check for support. */
178 if (mgr->ve->ve[i].src_format == mgr->ve->native_format[i] &&
179 (mgr->caps.fetch_dword_unaligned ||
180 (vb->buffer_offset % 4 == 0 &&
181 vb->stride % 4 == 0 &&
182 mgr->ve->ve[i].src_offset % 4 == 0))) {
183 continue;
184 }
185
186 /* Workaround for translate: output floats instead of halfs. */
187 switch (output_format) {
188 case PIPE_FORMAT_R16_FLOAT:
189 output_format = PIPE_FORMAT_R32_FLOAT;
190 output_format_size = 4;
191 break;
192 case PIPE_FORMAT_R16G16_FLOAT:
193 output_format = PIPE_FORMAT_R32G32_FLOAT;
194 output_format_size = 8;
195 break;
196 case PIPE_FORMAT_R16G16B16_FLOAT:
197 output_format = PIPE_FORMAT_R32G32B32_FLOAT;
198 output_format_size = 12;
199 break;
200 case PIPE_FORMAT_R16G16B16A16_FLOAT:
201 output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
202 output_format_size = 16;
203 break;
204 default:;
205 }
206
207 /* Add this vertex element. */
208 te = &key.element[key.nr_elements];
209 /*te->type;
210 te->instance_divisor;*/
211 te->input_buffer = mgr->ve->ve[i].vertex_buffer_index;
212 te->input_format = mgr->ve->ve[i].src_format;
213 te->input_offset = mgr->ve->ve[i].src_offset;
214 te->output_format = output_format;
215 te->output_offset = key.output_stride;
216
217 key.output_stride += output_format_size;
218 vb_translated[mgr->ve->ve[i].vertex_buffer_index] = TRUE;
219 tr_elem_index[i] = key.nr_elements;
220 key.nr_elements++;
221 }
222
223 /* Get a translate object. */
224 tr = translate_cache_find(mgr->translate_cache, &key);
225
226 /* Map buffers we want to translate. */
227 for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
228 if (vb_translated[i]) {
229 struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[i];
230
231 vb_map[i] = pipe_buffer_map(mgr->pipe, vb->buffer,
232 PIPE_TRANSFER_READ, &vb_transfer[i]);
233
234 tr->set_buffer(tr, i,
235 vb_map[i] + vb->buffer_offset + vb->stride * min_index,
236 vb->stride, ~0);
237 }
238 }
239
240 /* Create and map the output buffer. */
241 num_verts = max_index + 1 - min_index;
242
243 u_upload_alloc(mgr->uploader,
244 key.output_stride * min_index,
245 key.output_stride * num_verts,
246 &out_offset, &out_buffer, upload_flushed,
247 (void**)&out_map);
248
249 out_offset -= key.output_stride * min_index;
250
251 /* Translate. */
252 tr->run(tr, 0, num_verts, 0, out_map);
253
254 /* Unmap all buffers. */
255 for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
256 if (vb_translated[i]) {
257 pipe_buffer_unmap(mgr->pipe, vb_transfer[i]);
258 }
259 }
260
261 /* Setup the new vertex buffer in the first free slot. */
262 mgr->translate_vb_slot = ~0;
263 for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
264 if (!mgr->b.vertex_buffer[i].buffer) {
265 mgr->translate_vb_slot = i;
266
267 if (i >= mgr->b.nr_vertex_buffers) {
268 mgr->b.nr_real_vertex_buffers = i+1;
269 }
270 break;
271 }
272 }
273
274 if (mgr->translate_vb_slot != ~0) {
275 /* Setup the new vertex buffer. */
276 pipe_resource_reference(
277 &mgr->b.real_vertex_buffer[mgr->translate_vb_slot], out_buffer);
278 mgr->b.vertex_buffer[mgr->translate_vb_slot].buffer_offset = out_offset;
279 mgr->b.vertex_buffer[mgr->translate_vb_slot].stride = key.output_stride;
280
281 /* Setup new vertex elements. */
282 for (i = 0; i < mgr->ve->count; i++) {
283 if (vb_translated[mgr->ve->ve[i].vertex_buffer_index]) {
284 te = &key.element[tr_elem_index[i]];
285 new_velems[i].instance_divisor = mgr->ve->ve[i].instance_divisor;
286 new_velems[i].src_format = te->output_format;
287 new_velems[i].src_offset = te->output_offset;
288 new_velems[i].vertex_buffer_index = mgr->translate_vb_slot;
289 } else {
290 memcpy(&new_velems[i], &mgr->ve->ve[i],
291 sizeof(struct pipe_vertex_element));
292 }
293 }
294
295 mgr->fallback_ve =
296 mgr->pipe->create_vertex_elements_state(mgr->pipe, mgr->ve->count,
297 new_velems);
298
299 /* Preserve saved_ve. */
300 mgr->ve_binding_lock = TRUE;
301 mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->fallback_ve);
302 mgr->ve_binding_lock = FALSE;
303 }
304
305 pipe_resource_reference(&out_buffer, NULL);
306}
307
308static void u_vbuf_translate_end(struct u_vbuf_mgr_priv *mgr)
309{
310 if (mgr->fallback_ve == NULL) {
311 return;
312 }
313
314 /* Restore vertex elements. */
315 /* Note that saved_ve will be overwritten in bind_vertex_elements_state. */
316 mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->saved_ve);
317 mgr->pipe->delete_vertex_elements_state(mgr->pipe, mgr->fallback_ve);
318 mgr->fallback_ve = NULL;
319
320 /* Delete the now-unused VBO. */
321 pipe_resource_reference(&mgr->b.real_vertex_buffer[mgr->translate_vb_slot],
322 NULL);
323 mgr->b.nr_real_vertex_buffers = mgr->b.nr_vertex_buffers;
324}
325
326#define FORMAT_REPLACE(what, withwhat) \
327 case PIPE_FORMAT_##what: format = PIPE_FORMAT_##withwhat; break
328
329struct u_vbuf_mgr_elements *
330u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb,
331 unsigned count,
332 const struct pipe_vertex_element *attribs,
333 struct pipe_vertex_element *native_attribs)
334{
335 struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
336 unsigned i;
337 struct u_vbuf_mgr_elements *ve = CALLOC_STRUCT(u_vbuf_mgr_elements);
338
339 ve->count = count;
340
341 if (!count) {
342 return ve;
343 }
344
345 memcpy(ve->ve, attribs, sizeof(struct pipe_vertex_element) * count);
346 memcpy(native_attribs, attribs, sizeof(struct pipe_vertex_element) * count);
347
348 /* Set the best native format in case the original format is not
349 * supported. */
350 for (i = 0; i < count; i++) {
351 enum pipe_format format = ve->ve[i].src_format;
352
353 /* Choose a native format.
354 * For now we don't care about the alignment, that's going to
355 * be sorted out later. */
356 if (!mgr->caps.format_fixed32) {
357 switch (format) {
358 FORMAT_REPLACE(R32_FIXED, R32_FLOAT);
359 FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT);
360 FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT);
361 FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT);
362 default:;
363 }
364 }
365 if (!mgr->caps.format_float16) {
366 switch (format) {
367 FORMAT_REPLACE(R16_FLOAT, R32_FLOAT);
368 FORMAT_REPLACE(R16G16_FLOAT, R32G32_FLOAT);
369 FORMAT_REPLACE(R16G16B16_FLOAT, R32G32B32_FLOAT);
370 FORMAT_REPLACE(R16G16B16A16_FLOAT, R32G32B32A32_FLOAT);
371 default:;
372 }
373 }
374 if (!mgr->caps.format_float64) {
375 switch (format) {
376 FORMAT_REPLACE(R64_FLOAT, R32_FLOAT);
377 FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT);
378 FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT);
379 FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT);
380 default:;
381 }
382 }
383 if (!mgr->caps.format_norm32) {
384 switch (format) {
385 FORMAT_REPLACE(R32_UNORM, R32_FLOAT);
386 FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT);
387 FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT);
388 FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT);
389 FORMAT_REPLACE(R32_SNORM, R32_FLOAT);
390 FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT);
391 FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT);
392 FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT);
393 default:;
394 }
395 }
396 if (!mgr->caps.format_scaled32) {
397 switch (format) {
398 FORMAT_REPLACE(R32_USCALED, R32_FLOAT);
399 FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT);
400 FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT);
401 FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT);
402 FORMAT_REPLACE(R32_SSCALED, R32_FLOAT);
403 FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT);
404 FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT);
405 FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT);
406 default:;
407 }
408 }
409
410 native_attribs[i].src_format = format;
411 ve->native_format[i] = format;
412 ve->native_format_size[i] =
413 util_format_get_blocksize(ve->native_format[i]);
414
415 ve->incompatible_layout =
416 ve->incompatible_layout ||
417 ve->ve[i].src_format != ve->native_format[i] ||
418 (!mgr->caps.fetch_dword_unaligned && ve->ve[i].src_offset % 4 != 0);
419 }
420
421 /* Align the formats to the size of DWORD if needed. */
422 if (!mgr->caps.fetch_dword_unaligned) {
423 for (i = 0; i < count; i++) {
424 ve->native_format_size[i] = align(ve->native_format_size[i], 4);
425 }
426 }
427
428 return ve;
429}
430
431void u_vbuf_mgr_bind_vertex_elements(struct u_vbuf_mgr *mgrb,
432 void *cso,
433 struct u_vbuf_mgr_elements *ve)
434{
435 struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
436
437 if (!cso) {
438 return;
439 }
440
441 if (!mgr->ve_binding_lock) {
442 mgr->saved_ve = cso;
443 mgr->ve = ve;
444 }
445}
446
447void u_vbuf_mgr_destroy_vertex_elements(struct u_vbuf_mgr *mgr,
448 struct u_vbuf_mgr_elements *ve)
449{
450 FREE(ve);
451}
452
453void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb,
454 unsigned count,
455 const struct pipe_vertex_buffer *bufs)
456{
457 struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
458 unsigned i;
459
460 mgr->b.max_index = ~0;
461 mgr->any_user_vbs = FALSE;
462 mgr->incompatible_vb_layout = FALSE;
463
464 if (!mgr->caps.fetch_dword_unaligned) {
465 /* Check if the strides and offsets are aligned to the size of DWORD. */
466 for (i = 0; i < count; i++) {
467 if (bufs[i].buffer) {
468 if (bufs[i].stride % 4 != 0 ||
469 bufs[i].buffer_offset % 4 != 0) {
470 mgr->incompatible_vb_layout = TRUE;
471 break;
472 }
473 }
474 }
475 }
476
477 for (i = 0; i < count; i++) {
478 const struct pipe_vertex_buffer *vb = &bufs[i];
479
480 pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer);
481 pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL);
482
483 if (u_vbuf_resource(vb->buffer)->user_ptr) {
484 mgr->any_user_vbs = TRUE;
485 continue;
486 }
487
488 pipe_resource_reference(&mgr->b.real_vertex_buffer[i], vb->buffer);
489
490 /* The stride of zero means we will be fetching only the first
491 * vertex, so don't care about max_index. */
492 if (!vb->stride) {
493 continue;
494 }
495
496 /* Update the maximum index. */
497 mgr->b.max_index =
498 MIN2(mgr->b.max_index,
499 (vb->buffer->width0 - vb->buffer_offset) / vb->stride);
500 }
501
502 for (; i < mgr->b.nr_real_vertex_buffers; i++) {
503 pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL);
504 pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL);
505 }
506
507 memcpy(mgr->b.vertex_buffer, bufs,
508 sizeof(struct pipe_vertex_buffer) * count);
509
510 mgr->b.nr_vertex_buffers = count;
511 mgr->b.nr_real_vertex_buffers = count;
512}
513
514static void u_vbuf_upload_buffers(struct u_vbuf_mgr_priv *mgr,
515 int min_index, int max_index,
516 boolean *upload_flushed)
517{
518 int i, nr = mgr->ve->count;
519 unsigned count = max_index + 1 - min_index;
520 boolean uploaded[PIPE_MAX_ATTRIBS] = {0};
521
522 for (i = 0; i < nr; i++) {
523 unsigned index = mgr->ve->ve[i].vertex_buffer_index;
524 struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[index];
525
526 if (vb->buffer &&
527 u_vbuf_resource(vb->buffer)->user_ptr &&
528 !uploaded[index]) {
529 unsigned first, size;
530 boolean flushed;
531
532 if (vb->stride) {
533 first = vb->stride * min_index;
534 size = vb->stride * count;
535 } else {
536 first = 0;
537 size = mgr->ve->native_format_size[i];
538 }
539
540 u_upload_data(mgr->uploader, first, size,
541 u_vbuf_resource(vb->buffer)->user_ptr + first,
542 &vb->buffer_offset,
543 &mgr->b.real_vertex_buffer[index],
544 &flushed);
545
546 vb->buffer_offset -= first;
547
548 uploaded[index] = TRUE;
549 *upload_flushed = *upload_flushed || flushed;
550 } else {
551 assert(mgr->b.real_vertex_buffer[index]);
552 }
553 }
554}
555
556void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb,
557 const struct pipe_draw_info *info,
558 boolean *buffers_updated,
559 boolean *uploader_flushed)
560{
561 struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
562 boolean bufs_updated, upload_flushed = FALSE;
563 int min_index, max_index;
564
565 min_index = info->min_index - info->index_bias;
566 max_index = MIN2(info->max_index, mgr->b.max_index) - info->index_bias;
567
568 /* Translate vertices with non-native layouts or formats. */
569 if (mgr->incompatible_vb_layout || mgr->ve->incompatible_layout) {
570 u_vbuf_translate_begin(mgr, min_index, max_index, &upload_flushed);
571
572 if (mgr->fallback_ve) {
573 bufs_updated = TRUE;
574 }
575 }
576
577 /* Upload user buffers. */
578 if (mgr->any_user_vbs) {
579 u_vbuf_upload_buffers(mgr, min_index, max_index, &upload_flushed);
580 bufs_updated = TRUE;
581 }
582
583 /* Set the return values. */
584 if (buffers_updated) {
585 *buffers_updated = bufs_updated;
586 }
587 if (uploader_flushed) {
588 *uploader_flushed = upload_flushed;
589 }
590}
591
592void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgrb)
593{
594 struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
595
596 if (mgr->fallback_ve) {
597 u_vbuf_translate_end(mgr);
598 }
599}
600
601void u_vbuf_mgr_flush_uploader(struct u_vbuf_mgr *mgrb)
602{
603 struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
604
605 u_upload_flush(mgr->uploader);
606}
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.h b/src/gallium/auxiliary/util/u_vbuf_mgr.h
new file mode 100644
index 00000000000..5eb59385f9b
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_vbuf_mgr.h
@@ -0,0 +1,113 @@
1/**************************************************************************
2 *
3 * Copyright 2011 Marek Olšák <maraeo@gmail.com>
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#ifndef U_VBUF_MGR_H
29#define U_VBUF_MGR_H
30
31/* This module builds upon u_upload_mgr and translate_cache and takes care of
32 * user buffer uploads and vertex format fallbacks. It's designed
33 * for the drivers which don't always use the Draw module. (e.g. for HWTCL)
34 */
35
36#include "pipe/p_context.h"
37#include "pipe/p_state.h"
38#include "util/u_transfer.h"
39
40/* The manager.
41 * This structure should also be used to access vertex buffers
42 * from a driver. */
43struct u_vbuf_mgr {
44 /* This is what was set in set_vertex_buffers.
45 * May contain user buffers. */
46 struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
47 unsigned nr_vertex_buffers;
48
49 /* Contains only real vertex buffers.
50 * Hardware drivers should use real_vertex_buffers[i]
51 * instead of vertex_buffers[i].buffer. */
52 struct pipe_resource *real_vertex_buffer[PIPE_MAX_ATTRIBS];
53 int nr_real_vertex_buffers;
54
55 /* Precomputed max_index for hardware vertex buffers. */
56 int max_index;
57};
58
59struct u_vbuf_resource {
60 struct u_resource b;
61 uint8_t *user_ptr;
62};
63
64/* Opaque type containing information about vertex elements for the manager. */
65struct u_vbuf_mgr_elements;
66
67enum u_fetch_alignment {
68 U_VERTEX_FETCH_BYTE_ALIGNED,
69 U_VERTEX_FETCH_DWORD_ALIGNED
70};
71
72
73struct u_vbuf_mgr *
74u_vbuf_mgr_create(struct pipe_context *pipe,
75 unsigned upload_buffer_size,
76 unsigned upload_buffer_alignment,
77 enum u_fetch_alignment fetch_alignment);
78
79void u_vbuf_mgr_destroy(struct u_vbuf_mgr *mgr);
80
81struct u_vbuf_mgr_elements *
82u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgr,
83 unsigned count,
84 const struct pipe_vertex_element *attrs,
85 struct pipe_vertex_element *native_attrs);
86
87void u_vbuf_mgr_bind_vertex_elements(struct u_vbuf_mgr *mgr,
88 void *cso,
89 struct u_vbuf_mgr_elements *ve);
90
91void u_vbuf_mgr_destroy_vertex_elements(struct u_vbuf_mgr *mgr,
92 struct u_vbuf_mgr_elements *ve);
93
94void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgr,
95 unsigned count,
96 const struct pipe_vertex_buffer *bufs);
97
98void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgr,
99 const struct pipe_draw_info *info,
100 boolean *buffers_updated,
101 boolean *uploader_flushed);
102
103void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgr);
104
105void u_vbuf_mgr_flush_uploader(struct u_vbuf_mgr *mgr);
106
107
108static INLINE struct u_vbuf_resource *u_vbuf_resource(struct pipe_resource *r)
109{
110 return (struct u_vbuf_resource*)r;
111}
112
113#endif