baebbc7bae3a471594507761fdbf1d2af4ff975a
[mesa.git] / src / gallium / drivers / i915 / i915_prim_vbuf.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 /**
29 * \file
30 * Build post-transformation, post-clipping vertex buffers and element
31 * lists by hooking into the end of the primitive pipeline and
32 * manipulating the vertex_id field in the vertex headers.
33 *
34 * XXX: work in progress
35 *
36 * \author José Fonseca <jrfonseca@tungstengraphics.com>
37 * \author Keith Whitwell <keith@tungstengraphics.com>
38 */
39
40
41 #include "draw/draw_context.h"
42 #include "draw/draw_vbuf.h"
43 #include "util/u_debug.h"
44 #include "util/u_inlines.h"
45 #include "util/u_math.h"
46 #include "util/u_memory.h"
47 #include "util/u_fifo.h"
48
49 #include "i915_context.h"
50 #include "i915_reg.h"
51 #include "i915_batch.h"
52 #include "i915_state.h"
53
54
55 #define VBUF_MAP_BUFFER
56
57 /**
58 * Primitive renderer for i915.
59 */
60 struct i915_vbuf_render {
61 struct vbuf_render base;
62
63 struct i915_context *i915;
64
65 /** Vertex size in bytes */
66 size_t vertex_size;
67
68 /** Software primitive */
69 unsigned prim;
70
71 /** Hardware primitive */
72 unsigned hwprim;
73
74 /** Genereate a vertex list */
75 unsigned fallback;
76
77 /* Stuff for the vbo */
78 struct i915_winsys_buffer *vbo;
79 size_t vbo_size; /**< current size of allocated buffer */
80 size_t vbo_alloc_size; /**< minimum buffer size to allocate */
81 size_t vbo_hw_offset; /**< offset that we program the hardware with */
82 size_t vbo_sw_offset; /**< offset that we work with */
83 size_t vbo_index; /**< index offset to be added to all indices */
84 void *vbo_ptr;
85 size_t vbo_max_used;
86 size_t vbo_max_index; /**< index offset to be added to all indices */
87
88 #ifndef VBUF_MAP_BUFFER
89 size_t map_used_start;
90 size_t map_used_end;
91 size_t map_size;
92 #endif
93 };
94
95
96 /**
97 * Basically a cast wrapper.
98 */
99 static INLINE struct i915_vbuf_render *
100 i915_vbuf_render(struct vbuf_render *render)
101 {
102 assert(render);
103 return (struct i915_vbuf_render *)render;
104 }
105
106 /**
107 * If vbo state differs between renderer and context
108 * push state to the context. This function pushes
109 * hw_offset to i915->vbo_offset and vbo to i915->vbo.
110 *
111 * Side effects:
112 * May updates context vbo_offset and vbo fields.
113 */
114 static void
115 i915_vbuf_update_vbo_state(struct vbuf_render *render)
116 {
117 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
118 struct i915_context *i915 = i915_render->i915;
119
120 if (i915->vbo != i915_render->vbo ||
121 i915->vbo_offset != i915_render->vbo_hw_offset) {
122 i915->vbo = i915_render->vbo;
123 i915->vbo_offset = i915_render->vbo_hw_offset;
124 i915->dirty |= I915_NEW_VBO;
125 }
126 }
127
128 /**
129 * Callback exported to the draw module.
130 * Returns the current vertex_info.
131 *
132 * Side effects:
133 * If state is dirty update derived state.
134 */
135 static const struct vertex_info *
136 i915_vbuf_render_get_vertex_info(struct vbuf_render *render)
137 {
138 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
139 struct i915_context *i915 = i915_render->i915;
140
141 if (i915->dirty) {
142 /* make sure we have up to date vertex layout */
143 i915_update_derived(i915);
144 }
145
146 return &i915->current.vertex_info;
147 }
148
149 /**
150 * Reserve space in the vbo for vertices.
151 *
152 * Side effects:
153 * None.
154 */
155 static boolean
156 i915_vbuf_render_reserve(struct i915_vbuf_render *i915_render, size_t size)
157 {
158 struct i915_context *i915 = i915_render->i915;
159
160 if (i915_render->vbo_size < size + i915_render->vbo_sw_offset)
161 return FALSE;
162
163 if (i915->vbo_flushed)
164 return FALSE;
165
166 return TRUE;
167 }
168
169 /**
170 * Allocate a new vbo buffer should there not be enough space for
171 * the requested number of vertices by the draw module.
172 *
173 * Side effects:
174 * Updates hw_offset, sw_offset, index and allocates a new buffer.
175 * Will set i915->vbo to null on buffer allocation.
176 */
177 static void
178 i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size)
179 {
180 struct i915_context *i915 = i915_render->i915;
181 struct i915_winsys *iws = i915->iws;
182
183 if (i915_render->vbo) {
184 iws->buffer_destroy(iws, i915_render->vbo);
185 /*
186 * XXX If buffers where referenced then this should be done in
187 * update_vbo_state but since they arn't and malloc likes to reuse
188 * memory we need to set it to null
189 */
190 i915->vbo = NULL;
191 i915_render->vbo = NULL;
192 }
193
194 i915->vbo_flushed = 0;
195
196 i915_render->vbo_size = MAX2(size, i915_render->vbo_alloc_size);
197 i915_render->vbo_hw_offset = 0;
198 i915_render->vbo_sw_offset = 0;
199 i915_render->vbo_index = 0;
200
201 #ifndef VBUF_MAP_BUFFER
202 if (i915_render->vbo_size > i915_render->map_size) {
203 i915_render->map_size = i915_render->vbo_size;
204 FREE(i915_render->vbo_ptr);
205 i915_render->vbo_ptr = MALLOC(i915_render->map_size);
206 }
207 #endif
208
209 i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size,
210 I915_NEW_VERTEX);
211 }
212
213 /**
214 * Callback exported to the draw module.
215 *
216 * Side effects:
217 * Updates hw_offset, sw_offset, index and may allocate
218 * a new buffer. Also updates may update the vbo state
219 * on the i915 context.
220 */
221 static boolean
222 i915_vbuf_render_allocate_vertices(struct vbuf_render *render,
223 ushort vertex_size,
224 ushort nr_vertices)
225 {
226 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
227 size_t size = (size_t)vertex_size * (size_t)nr_vertices;
228 size_t offset;
229
230 /*
231 * Align sw_offset with first multiple of vertex size from hw_offset.
232 * Set index to be the multiples from from hw_offset to sw_offset.
233 * i915_vbuf_render_new_buf will reset index, sw_offset, hw_offset
234 * when it allocates a new buffer this is correct.
235 */
236 {
237 offset = i915_render->vbo_sw_offset - i915_render->vbo_hw_offset;
238 offset = util_align_npot(offset, vertex_size);
239 i915_render->vbo_sw_offset = i915_render->vbo_hw_offset + offset;
240 i915_render->vbo_index = offset / vertex_size;
241 }
242
243 if (!i915_vbuf_render_reserve(i915_render, size))
244 i915_vbuf_render_new_buf(i915_render, size);
245
246 /*
247 * If a new buffer has been alocated sw_offset,
248 * hw_offset & index will be reset by new_buf
249 */
250
251 i915_render->vertex_size = vertex_size;
252
253 i915_vbuf_update_vbo_state(render);
254
255 if (!i915_render->vbo)
256 return FALSE;
257 return TRUE;
258 }
259
260 static void *
261 i915_vbuf_render_map_vertices(struct vbuf_render *render)
262 {
263 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
264 struct i915_context *i915 = i915_render->i915;
265 struct i915_winsys *iws = i915->iws;
266
267 if (i915->vbo_flushed)
268 debug_printf("%s bad vbo flush occured stalling on hw\n", __FUNCTION__);
269
270 #ifdef VBUF_MAP_BUFFER
271 i915_render->vbo_ptr = iws->buffer_map(iws, i915_render->vbo, TRUE);
272 return (unsigned char *)i915_render->vbo_ptr + i915_render->vbo_sw_offset;
273 #else
274 (void)iws;
275 return (unsigned char *)i915_render->vbo_ptr;
276 #endif
277 }
278
279 static void
280 i915_vbuf_render_unmap_vertices(struct vbuf_render *render,
281 ushort min_index,
282 ushort max_index)
283 {
284 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
285 struct i915_context *i915 = i915_render->i915;
286 struct i915_winsys *iws = i915->iws;
287
288 i915_render->vbo_max_index = max_index;
289 i915_render->vbo_max_used = MAX2(i915_render->vbo_max_used, i915_render->vertex_size * (max_index + 1));
290 #ifdef VBUF_MAP_BUFFER
291 iws->buffer_unmap(iws, i915_render->vbo);
292 #else
293 i915_render->map_used_start = i915_render->vertex_size * min_index;
294 i915_render->map_used_end = i915_render->vertex_size * (max_index + 1);
295 iws->buffer_write(iws, i915_render->vbo,
296 i915_render->map_used_start + i915_render->vbo_sw_offset,
297 i915_render->map_used_end - i915_render->map_used_start,
298 (unsigned char *)i915_render->vbo_ptr + i915_render->map_used_start);
299
300 #endif
301 }
302
303 /**
304 * Ensure that the given max_index given is not larger ushort max.
305 * If it is larger then ushort max it advanced the hw_offset to the
306 * same position in the vbo as sw_offset and set index to zero.
307 *
308 * Side effects:
309 * On failure update hw_offset and index.
310 */
311 static void
312 i915_vbuf_ensure_index_bounds(struct vbuf_render *render,
313 unsigned max_index)
314 {
315 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
316
317 if (max_index + i915_render->vbo_index < ((1 << 17) - 1))
318 return;
319
320 i915_render->vbo_hw_offset = i915_render->vbo_sw_offset;
321 i915_render->vbo_index = 0;
322
323 i915_vbuf_update_vbo_state(render);
324 }
325
326 static boolean
327 i915_vbuf_render_set_primitive(struct vbuf_render *render,
328 unsigned prim)
329 {
330 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
331 i915_render->prim = prim;
332
333 switch(prim) {
334 case PIPE_PRIM_POINTS:
335 i915_render->hwprim = PRIM3D_POINTLIST;
336 i915_render->fallback = 0;
337 return TRUE;
338 case PIPE_PRIM_LINES:
339 i915_render->hwprim = PRIM3D_LINELIST;
340 i915_render->fallback = 0;
341 return TRUE;
342 case PIPE_PRIM_LINE_LOOP:
343 i915_render->hwprim = PRIM3D_LINELIST;
344 i915_render->fallback = PIPE_PRIM_LINE_LOOP;
345 return TRUE;
346 case PIPE_PRIM_LINE_STRIP:
347 i915_render->hwprim = PRIM3D_LINESTRIP;
348 i915_render->fallback = 0;
349 return TRUE;
350 case PIPE_PRIM_TRIANGLES:
351 i915_render->hwprim = PRIM3D_TRILIST;
352 i915_render->fallback = 0;
353 return TRUE;
354 case PIPE_PRIM_TRIANGLE_STRIP:
355 i915_render->hwprim = PRIM3D_TRISTRIP;
356 i915_render->fallback = 0;
357 return TRUE;
358 case PIPE_PRIM_TRIANGLE_FAN:
359 i915_render->hwprim = PRIM3D_TRIFAN;
360 i915_render->fallback = 0;
361 return TRUE;
362 case PIPE_PRIM_QUADS:
363 i915_render->hwprim = PRIM3D_TRILIST;
364 i915_render->fallback = PIPE_PRIM_QUADS;
365 return TRUE;
366 case PIPE_PRIM_QUAD_STRIP:
367 i915_render->hwprim = PRIM3D_TRILIST;
368 i915_render->fallback = PIPE_PRIM_QUAD_STRIP;
369 return TRUE;
370 case PIPE_PRIM_POLYGON:
371 i915_render->hwprim = PRIM3D_POLY;
372 i915_render->fallback = 0;
373 return TRUE;
374 default:
375 /* FIXME: Actually, can handle a lot more just fine... */
376 return FALSE;
377 }
378 }
379
380 /**
381 * Used for fallbacks in draw_arrays
382 */
383 static void
384 draw_arrays_generate_indices(struct vbuf_render *render,
385 unsigned start, uint nr,
386 unsigned type)
387 {
388 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
389 struct i915_context *i915 = i915_render->i915;
390 unsigned i;
391 unsigned end = start + nr + i915_render->vbo_index;
392 start += i915_render->vbo_index;
393
394 switch(type) {
395 case 0:
396 for (i = start; i+1 < end; i += 2)
397 OUT_BATCH((i+0) | (i+1) << 16);
398 if (i < end)
399 OUT_BATCH(i);
400 break;
401 case PIPE_PRIM_LINE_LOOP:
402 if (nr >= 2) {
403 for (i = start + 1; i < end; i++)
404 OUT_BATCH((i-0) | (i+0) << 16);
405 OUT_BATCH((i-0) | ( start) << 16);
406 }
407 break;
408 case PIPE_PRIM_QUADS:
409 for (i = start; i + 3 < end; i += 4) {
410 OUT_BATCH((i+0) | (i+1) << 16);
411 OUT_BATCH((i+3) | (i+1) << 16);
412 OUT_BATCH((i+2) | (i+3) << 16);
413 }
414 break;
415 case PIPE_PRIM_QUAD_STRIP:
416 for (i = start; i + 3 < end; i += 2) {
417 OUT_BATCH((i+0) | (i+1) << 16);
418 OUT_BATCH((i+3) | (i+2) << 16);
419 OUT_BATCH((i+0) | (i+3) << 16);
420 }
421 break;
422 default:
423 assert(0);
424 }
425 }
426
427 static unsigned
428 draw_arrays_calc_nr_indices(uint nr, unsigned type)
429 {
430 switch (type) {
431 case 0:
432 return nr;
433 case PIPE_PRIM_LINE_LOOP:
434 if (nr >= 2)
435 return nr * 2;
436 else
437 return 0;
438 case PIPE_PRIM_QUADS:
439 return (nr / 4) * 6;
440 case PIPE_PRIM_QUAD_STRIP:
441 return ((nr - 2) / 2) * 6;
442 default:
443 assert(0);
444 return 0;
445 }
446 }
447
448 static void
449 draw_arrays_fallback(struct vbuf_render *render,
450 unsigned start,
451 uint nr)
452 {
453 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
454 struct i915_context *i915 = i915_render->i915;
455 unsigned nr_indices;
456
457 nr_indices = draw_arrays_calc_nr_indices(nr, i915_render->fallback);
458 if (!nr_indices)
459 return;
460
461 i915_vbuf_ensure_index_bounds(render, start + nr_indices);
462
463 if (i915->dirty)
464 i915_update_derived(i915);
465
466 if (i915->hardware_dirty)
467 i915_emit_hardware_state(i915);
468
469 if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) {
470 FLUSH_BATCH(NULL);
471
472 /* Make sure state is re-emitted after a flush:
473 */
474 i915_update_derived(i915);
475 i915_emit_hardware_state(i915);
476 i915->vbo_flushed = 1;
477
478 if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) {
479 assert(0);
480 goto out;
481 }
482 }
483
484 OUT_BATCH(_3DPRIMITIVE |
485 PRIM_INDIRECT |
486 i915_render->hwprim |
487 PRIM_INDIRECT_ELTS |
488 nr_indices);
489
490 draw_arrays_generate_indices(render, start, nr, i915_render->fallback);
491
492 out:
493 return;
494 }
495
496 static void
497 i915_vbuf_render_draw_arrays(struct vbuf_render *render,
498 unsigned start,
499 uint nr)
500 {
501 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
502 struct i915_context *i915 = i915_render->i915;
503
504 if (i915_render->fallback) {
505 draw_arrays_fallback(render, start, nr);
506 return;
507 }
508
509 i915_vbuf_ensure_index_bounds(render, start + nr);
510 start += i915_render->vbo_index;
511
512 if (i915->dirty)
513 i915_update_derived(i915);
514
515 if (i915->hardware_dirty)
516 i915_emit_hardware_state(i915);
517
518 if (!BEGIN_BATCH(2, 0)) {
519 FLUSH_BATCH(NULL);
520
521 /* Make sure state is re-emitted after a flush:
522 */
523 i915_update_derived(i915);
524 i915_emit_hardware_state(i915);
525 i915->vbo_flushed = 1;
526
527 if (!BEGIN_BATCH(2, 0)) {
528 assert(0);
529 goto out;
530 }
531 }
532
533 OUT_BATCH(_3DPRIMITIVE |
534 PRIM_INDIRECT |
535 PRIM_INDIRECT_SEQUENTIAL |
536 i915_render->hwprim |
537 nr);
538 OUT_BATCH(start); /* Beginning vertex index */
539
540 out:
541 return;
542 }
543
544 /**
545 * Used for normal and fallback emitting of indices
546 * If type is zero normal operation assumed.
547 */
548 static void
549 draw_generate_indices(struct vbuf_render *render,
550 const ushort *indices,
551 uint nr_indices,
552 unsigned type)
553 {
554 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
555 struct i915_context *i915 = i915_render->i915;
556 unsigned i;
557 unsigned o = i915_render->vbo_index;
558
559 switch(type) {
560 case 0:
561 for (i = 0; i + 1 < nr_indices; i += 2) {
562 OUT_BATCH((o+indices[i]) | (o+indices[i+1]) << 16);
563 }
564 if (i < nr_indices) {
565 OUT_BATCH((o+indices[i]));
566 }
567 break;
568 case PIPE_PRIM_LINE_LOOP:
569 if (nr_indices >= 2) {
570 for (i = 1; i < nr_indices; i++)
571 OUT_BATCH((o+indices[i-1]) | (o+indices[i]) << 16);
572 OUT_BATCH((o+indices[i-1]) | (o+indices[0]) << 16);
573 }
574 break;
575 case PIPE_PRIM_QUADS:
576 for (i = 0; i + 3 < nr_indices; i += 4) {
577 OUT_BATCH((o+indices[i+0]) | (o+indices[i+1]) << 16);
578 OUT_BATCH((o+indices[i+3]) | (o+indices[i+1]) << 16);
579 OUT_BATCH((o+indices[i+2]) | (o+indices[i+3]) << 16);
580 }
581 break;
582 case PIPE_PRIM_QUAD_STRIP:
583 for (i = 0; i + 3 < nr_indices; i += 2) {
584 OUT_BATCH((o+indices[i+0]) | (o+indices[i+1]) << 16);
585 OUT_BATCH((o+indices[i+3]) | (o+indices[i+2]) << 16);
586 OUT_BATCH((o+indices[i+0]) | (o+indices[i+3]) << 16);
587 }
588 break;
589 default:
590 assert(0);
591 break;
592 }
593 }
594
595 static unsigned
596 draw_calc_nr_indices(uint nr_indices, unsigned type)
597 {
598 switch (type) {
599 case 0:
600 return nr_indices;
601 case PIPE_PRIM_LINE_LOOP:
602 if (nr_indices >= 2)
603 return nr_indices * 2;
604 else
605 return 0;
606 case PIPE_PRIM_QUADS:
607 return (nr_indices / 4) * 6;
608 case PIPE_PRIM_QUAD_STRIP:
609 return ((nr_indices - 2) / 2) * 6;
610 default:
611 assert(0);
612 return 0;
613 }
614 }
615
616 static void
617 i915_vbuf_render_draw_elements(struct vbuf_render *render,
618 const ushort *indices,
619 uint nr_indices)
620 {
621 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
622 struct i915_context *i915 = i915_render->i915;
623 unsigned save_nr_indices;
624
625 save_nr_indices = nr_indices;
626
627 nr_indices = draw_calc_nr_indices(nr_indices, i915_render->fallback);
628 if (!nr_indices)
629 return;
630
631 i915_vbuf_ensure_index_bounds(render, i915_render->vbo_max_index);
632
633 if (i915->dirty)
634 i915_update_derived(i915);
635
636 if (i915->hardware_dirty)
637 i915_emit_hardware_state(i915);
638
639 if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) {
640 FLUSH_BATCH(NULL);
641
642 /* Make sure state is re-emitted after a flush:
643 */
644 i915_update_derived(i915);
645 i915_emit_hardware_state(i915);
646 i915->vbo_flushed = 1;
647
648 if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) {
649 assert(0);
650 goto out;
651 }
652 }
653
654 OUT_BATCH(_3DPRIMITIVE |
655 PRIM_INDIRECT |
656 i915_render->hwprim |
657 PRIM_INDIRECT_ELTS |
658 nr_indices);
659 draw_generate_indices(render,
660 indices,
661 save_nr_indices,
662 i915_render->fallback);
663
664 out:
665 return;
666 }
667
668 static void
669 i915_vbuf_render_release_vertices(struct vbuf_render *render)
670 {
671 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
672
673 i915_render->vbo_sw_offset += i915_render->vbo_max_used;
674 i915_render->vbo_max_used = 0;
675
676 /*
677 * Micro optimization, by calling update here we the offset change
678 * will be picked up on the next pipe_context::draw_*.
679 */
680 i915_vbuf_update_vbo_state(render);
681 }
682
683 static void
684 i915_vbuf_render_destroy(struct vbuf_render *render)
685 {
686 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
687 FREE(i915_render);
688 }
689
690 /**
691 * Create a new primitive render.
692 */
693 static struct vbuf_render *
694 i915_vbuf_render_create(struct i915_context *i915)
695 {
696 struct i915_vbuf_render *i915_render = CALLOC_STRUCT(i915_vbuf_render);
697 struct i915_winsys *iws = i915->iws;
698 int i;
699
700 i915_render->i915 = i915;
701
702 i915_render->base.max_vertex_buffer_bytes = 16*4096;
703
704 /* NOTE: it must be such that state and vertices indices fit in a single
705 * batch buffer.
706 */
707 i915_render->base.max_indices = 16*1024;
708
709 i915_render->base.get_vertex_info = i915_vbuf_render_get_vertex_info;
710 i915_render->base.allocate_vertices = i915_vbuf_render_allocate_vertices;
711 i915_render->base.map_vertices = i915_vbuf_render_map_vertices;
712 i915_render->base.unmap_vertices = i915_vbuf_render_unmap_vertices;
713 i915_render->base.set_primitive = i915_vbuf_render_set_primitive;
714 i915_render->base.draw_elements = i915_vbuf_render_draw_elements;
715 i915_render->base.draw_arrays = i915_vbuf_render_draw_arrays;
716 i915_render->base.release_vertices = i915_vbuf_render_release_vertices;
717 i915_render->base.destroy = i915_vbuf_render_destroy;
718
719 #ifndef VBUF_MAP_BUFFER
720 i915_render->map_size = 0;
721 i915_render->map_used_start = 0;
722 i915_render->map_used_end = 0;
723 #endif
724
725 i915_render->vbo = NULL;
726 i915_render->vbo_ptr = NULL;
727 i915_render->vbo_size = 0;
728 i915_render->vbo_hw_offset = 0;
729 i915_render->vbo_sw_offset = 0;
730 i915_render->vbo_alloc_size = i915_render->base.max_vertex_buffer_bytes * 4;
731
732 #ifdef VBUF_USE_POOL
733 i915_render->pool_used = FALSE;
734 i915_render->pool_buffer_size = i915_render->vbo_alloc_size;
735 i915_render->pool_fifo = u_fifo_create(6);
736 for (i = 0; i < 6; i++)
737 u_fifo_add(i915_render->pool_fifo,
738 iws->buffer_create(iws, i915_render->pool_buffer_size,
739 I915_NEW_VERTEX));
740 #else
741 (void)i;
742 (void)iws;
743 #endif
744
745 return &i915_render->base;
746 }
747
748 /**
749 * Create a new primitive vbuf/render stage.
750 */
751 struct draw_stage *i915_draw_vbuf_stage(struct i915_context *i915)
752 {
753 struct vbuf_render *render;
754 struct draw_stage *stage;
755
756 render = i915_vbuf_render_create(i915);
757 if(!render)
758 return NULL;
759
760 stage = draw_vbuf_stage(i915->draw, render);
761 if(!stage) {
762 render->destroy(render);
763 return NULL;
764 }
765 /** TODO JB: this shouldn't be here */
766 draw_set_render(i915->draw, render);
767
768 return stage;
769 }