Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 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 
37
 * \author Keith Whitwell 
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_unmap(iws, i915_render->vbo);
185
      iws->buffer_destroy(iws, i915_render->vbo);
186
      /*
187
       * XXX If buffers where referenced then this should be done in
188
       * update_vbo_state but since they arn't and malloc likes to reuse
189
       * memory we need to set it to null
190
       */
191
      i915->vbo = NULL;
192
      i915_render->vbo = NULL;
193
   }
194
 
195
   i915->vbo_flushed = 0;
196
 
197
   i915_render->vbo_size = MAX2(size, i915_render->vbo_alloc_size);
198
   i915_render->vbo_hw_offset = 0;
199
   i915_render->vbo_sw_offset = 0;
200
   i915_render->vbo_index = 0;
201
 
202
#ifndef VBUF_MAP_BUFFER
203
   if (i915_render->vbo_size > i915_render->map_size) {
204
      i915_render->map_size = i915_render->vbo_size;
205
      FREE(i915_render->vbo_ptr);
206
      i915_render->vbo_ptr = MALLOC(i915_render->map_size);
207
   }
208
#endif
209
 
210
   i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size,
211
                                         I915_NEW_VERTEX);
212
   i915_render->vbo_ptr = iws->buffer_map(iws, i915_render->vbo, TRUE);
213
}
214
 
215
/**
216
 * Callback exported to the draw module.
217
 *
218
 * Side effects:
219
 *    Updates hw_offset, sw_offset, index and may allocate
220
 *    a new buffer. Also updates may update the vbo state
221
 *    on the i915 context.
222
 */
223
static boolean
224
i915_vbuf_render_allocate_vertices(struct vbuf_render *render,
225
                                   ushort vertex_size,
226
                                   ushort nr_vertices)
227
{
228
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
229
   size_t size = (size_t)vertex_size * (size_t)nr_vertices;
230
   size_t offset;
231
 
232
   /*
233
    * Align sw_offset with first multiple of vertex size from hw_offset.
234
    * Set index to be the multiples from from hw_offset to sw_offset.
235
    * i915_vbuf_render_new_buf will reset index, sw_offset, hw_offset
236
    * when it allocates a new buffer this is correct.
237
    */
238
   {
239
      offset = i915_render->vbo_sw_offset - i915_render->vbo_hw_offset;
240
      offset = util_align_npot(offset, vertex_size);
241
      i915_render->vbo_sw_offset = i915_render->vbo_hw_offset + offset;
242
      i915_render->vbo_index = offset / vertex_size;
243
   }
244
 
245
   if (!i915_vbuf_render_reserve(i915_render, size))
246
      i915_vbuf_render_new_buf(i915_render, size);
247
 
248
   /*
249
    * If a new buffer has been alocated sw_offset,
250
    * hw_offset & index will be reset by new_buf
251
    */
252
 
253
   i915_render->vertex_size = vertex_size;
254
 
255
   i915_vbuf_update_vbo_state(render);
256
 
257
   if (!i915_render->vbo)
258
      return FALSE;
259
   return TRUE;
260
}
261
 
262
static void *
263
i915_vbuf_render_map_vertices(struct vbuf_render *render)
264
{
265
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
266
   struct i915_context *i915 = i915_render->i915;
267
 
268
   if (i915->vbo_flushed)
269
      debug_printf("%s bad vbo flush occured stalling on hw\n", __FUNCTION__);
270
 
271
#ifdef VBUF_MAP_BUFFER
272
   return (unsigned char *)i915_render->vbo_ptr + i915_render->vbo_sw_offset;
273
#else
274
   return (unsigned char *)i915_render->vbo_ptr;
275
#endif
276
}
277
 
278
static void
279
i915_vbuf_render_unmap_vertices(struct vbuf_render *render,
280
                                ushort min_index,
281
                                ushort max_index)
282
{
283
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
284
   struct i915_context *i915 = i915_render->i915;
285
   struct i915_winsys *iws = i915->iws;
286
 
287
   i915_render->vbo_max_index = max_index;
288
   i915_render->vbo_max_used = MAX2(i915_render->vbo_max_used, i915_render->vertex_size * (max_index + 1));
289
#ifdef VBUF_MAP_BUFFER
290
   (void)iws;
291
#else
292
   i915_render->map_used_start = i915_render->vertex_size * min_index;
293
   i915_render->map_used_end = i915_render->vertex_size * (max_index + 1);
294
   iws->buffer_write(iws, i915_render->vbo,
295
                     i915_render->map_used_start + i915_render->vbo_sw_offset,
296
                     i915_render->map_used_end - i915_render->map_used_start,
297
                     (unsigned char *)i915_render->vbo_ptr + i915_render->map_used_start);
298
 
299
#endif
300
}
301
 
302
/**
303
 * Ensure that the given max_index given is not larger ushort max.
304
 * If it is larger then ushort max it advanced the hw_offset to the
305
 * same position in the vbo as sw_offset and set index to zero.
306
 *
307
 * Side effects:
308
 *    On failure update hw_offset and index.
309
 */
310
static void
311
i915_vbuf_ensure_index_bounds(struct vbuf_render *render,
312
                              unsigned max_index)
313
{
314
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
315
 
316
   if (max_index + i915_render->vbo_index < ((1 << 17) - 1))
317
      return;
318
 
319
   i915_render->vbo_hw_offset = i915_render->vbo_sw_offset;
320
   i915_render->vbo_index = 0;
321
 
322
   i915_vbuf_update_vbo_state(render);
323
}
324
 
325
static void
326
i915_vbuf_render_set_primitive(struct vbuf_render *render,
327
                               unsigned prim)
328
{
329
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
330
   i915_render->prim = prim;
331
 
332
   switch(prim) {
333
   case PIPE_PRIM_POINTS:
334
      i915_render->hwprim = PRIM3D_POINTLIST;
335
      i915_render->fallback = 0;
336
      break;
337
   case PIPE_PRIM_LINES:
338
      i915_render->hwprim = PRIM3D_LINELIST;
339
      i915_render->fallback = 0;
340
      break;
341
   case PIPE_PRIM_LINE_LOOP:
342
      i915_render->hwprim = PRIM3D_LINELIST;
343
      i915_render->fallback = PIPE_PRIM_LINE_LOOP;
344
      break;
345
   case PIPE_PRIM_LINE_STRIP:
346
      i915_render->hwprim = PRIM3D_LINESTRIP;
347
      i915_render->fallback = 0;
348
      break;
349
   case PIPE_PRIM_TRIANGLES:
350
      i915_render->hwprim = PRIM3D_TRILIST;
351
      i915_render->fallback = 0;
352
      break;
353
   case PIPE_PRIM_TRIANGLE_STRIP:
354
      i915_render->hwprim = PRIM3D_TRISTRIP;
355
      i915_render->fallback = 0;
356
      break;
357
   case PIPE_PRIM_TRIANGLE_FAN:
358
      i915_render->hwprim = PRIM3D_TRIFAN;
359
      i915_render->fallback = 0;
360
      break;
361
   case PIPE_PRIM_QUADS:
362
      i915_render->hwprim = PRIM3D_TRILIST;
363
      i915_render->fallback = PIPE_PRIM_QUADS;
364
      break;
365
   case PIPE_PRIM_QUAD_STRIP:
366
      i915_render->hwprim = PRIM3D_TRILIST;
367
      i915_render->fallback = PIPE_PRIM_QUAD_STRIP;
368
      break;
369
   case PIPE_PRIM_POLYGON:
370
      i915_render->hwprim = PRIM3D_POLY;
371
      i915_render->fallback = 0;
372
      break;
373
   default:
374
      /* FIXME: Actually, can handle a lot more just fine... */
375
      assert(0 && "unexpected prim in i915_vbuf_render_set_primitive()");
376
   }
377
}
378
 
379
/**
380
 * Used for fallbacks in draw_arrays
381
 */
382
static void
383
draw_arrays_generate_indices(struct vbuf_render *render,
384
                             unsigned start, uint nr,
385
                             unsigned type)
386
{
387
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
388
   struct i915_context *i915 = i915_render->i915;
389
   unsigned i;
390
   unsigned end = start + nr + i915_render->vbo_index;
391
   start += i915_render->vbo_index;
392
 
393
   switch(type) {
394
   case 0:
395
      for (i = start; i+1 < end; i += 2)
396
         OUT_BATCH((i+0) | (i+1) << 16);
397
      if (i < end)
398
         OUT_BATCH(i);
399
      break;
400
   case PIPE_PRIM_LINE_LOOP:
401
      if (nr >= 2) {
402
         for (i = start + 1; i < end; i++)
403
            OUT_BATCH((i-1) | (i+0) << 16);
404
         OUT_BATCH((i-1) | ( start) << 16);
405
      }
406
      break;
407
   case PIPE_PRIM_QUADS:
408
      for (i = start; i + 3 < end; i += 4) {
409
         OUT_BATCH((i+0) | (i+1) << 16);
410
         OUT_BATCH((i+3) | (i+1) << 16);
411
         OUT_BATCH((i+2) | (i+3) << 16);
412
      }
413
      break;
414
   case PIPE_PRIM_QUAD_STRIP:
415
      for (i = start; i + 3 < end; i += 2) {
416
         OUT_BATCH((i+0) | (i+1) << 16);
417
         OUT_BATCH((i+3) | (i+2) << 16);
418
         OUT_BATCH((i+0) | (i+3) << 16);
419
      }
420
      break;
421
   default:
422
      assert(0);
423
   }
424
}
425
 
426
static unsigned
427
draw_arrays_calc_nr_indices(uint nr, unsigned type)
428
{
429
   switch (type) {
430
   case 0:
431
      return nr;
432
   case PIPE_PRIM_LINE_LOOP:
433
      if (nr >= 2)
434
         return nr * 2;
435
      else
436
         return 0;
437
   case PIPE_PRIM_QUADS:
438
      return (nr / 4) * 6;
439
   case PIPE_PRIM_QUAD_STRIP:
440
      return ((nr - 2) / 2) * 6;
441
   default:
442
      assert(0);
443
      return 0;
444
   }
445
}
446
 
447
static void
448
draw_arrays_fallback(struct vbuf_render *render,
449
                     unsigned start,
450
                     uint nr)
451
{
452
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
453
   struct i915_context *i915 = i915_render->i915;
454
   unsigned nr_indices;
455
 
456
   nr_indices = draw_arrays_calc_nr_indices(nr, i915_render->fallback);
457
   if (!nr_indices)
458
      return;
459
 
460
   i915_vbuf_ensure_index_bounds(render, start + nr_indices);
461
 
462
   if (i915->dirty)
463
      i915_update_derived(i915);
464
 
465
   if (i915->hardware_dirty)
466
      i915_emit_hardware_state(i915);
467
 
468
   if (!BEGIN_BATCH(1 + (nr_indices + 1)/2)) {
469
      FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
470
 
471
      /* Make sure state is re-emitted after a flush:
472
       */
473
      i915_emit_hardware_state(i915);
474
      i915->vbo_flushed = 1;
475
 
476
      if (!BEGIN_BATCH(1 + (nr_indices + 1)/2)) {
477
         assert(0);
478
         goto out;
479
      }
480
   }
481
 
482
   OUT_BATCH(_3DPRIMITIVE |
483
             PRIM_INDIRECT |
484
             i915_render->hwprim |
485
             PRIM_INDIRECT_ELTS |
486
             nr_indices);
487
 
488
   draw_arrays_generate_indices(render, start, nr, i915_render->fallback);
489
 
490
out:
491
   return;
492
}
493
 
494
static void
495
i915_vbuf_render_draw_arrays(struct vbuf_render *render,
496
                             unsigned start,
497
                             uint nr)
498
{
499
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
500
   struct i915_context *i915 = i915_render->i915;
501
 
502
   if (i915_render->fallback) {
503
      draw_arrays_fallback(render, start, nr);
504
      return;
505
   }
506
 
507
   i915_vbuf_ensure_index_bounds(render, start + nr);
508
   start += i915_render->vbo_index;
509
 
510
   if (i915->dirty)
511
      i915_update_derived(i915);
512
 
513
   if (i915->hardware_dirty)
514
      i915_emit_hardware_state(i915);
515
 
516
   if (!BEGIN_BATCH(2)) {
517
      FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
518
 
519
      /* Make sure state is re-emitted after a flush:
520
       */
521
      i915_emit_hardware_state(i915);
522
      i915->vbo_flushed = 1;
523
 
524
      if (!BEGIN_BATCH(2)) {
525
         assert(0);
526
         goto out;
527
      }
528
   }
529
 
530
   OUT_BATCH(_3DPRIMITIVE |
531
             PRIM_INDIRECT |
532
             PRIM_INDIRECT_SEQUENTIAL |
533
             i915_render->hwprim |
534
             nr);
535
   OUT_BATCH(start); /* Beginning vertex index */
536
 
537
out:
538
   return;
539
}
540
 
541
/**
542
 * Used for normal and fallback emitting of indices
543
 * If type is zero normal operation assumed.
544
 */
545
static void
546
draw_generate_indices(struct vbuf_render *render,
547
                      const ushort *indices,
548
                      uint nr_indices,
549
                      unsigned type)
550
{
551
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
552
   struct i915_context *i915 = i915_render->i915;
553
   unsigned i;
554
   unsigned o = i915_render->vbo_index;
555
 
556
   switch(type) {
557
   case 0:
558
      for (i = 0; i + 1 < nr_indices; i += 2) {
559
         OUT_BATCH((o+indices[i]) | (o+indices[i+1]) << 16);
560
      }
561
      if (i < nr_indices) {
562
         OUT_BATCH((o+indices[i]));
563
      }
564
      break;
565
   case PIPE_PRIM_LINE_LOOP:
566
      if (nr_indices >= 2) {
567
         for (i = 1; i < nr_indices; i++)
568
            OUT_BATCH((o+indices[i-1]) | (o+indices[i]) << 16);
569
         OUT_BATCH((o+indices[i-1]) | (o+indices[0]) << 16);
570
      }
571
      break;
572
   case PIPE_PRIM_QUADS:
573
      for (i = 0; i + 3 < nr_indices; i += 4) {
574
         OUT_BATCH((o+indices[i+0]) | (o+indices[i+1]) << 16);
575
         OUT_BATCH((o+indices[i+3]) | (o+indices[i+1]) << 16);
576
         OUT_BATCH((o+indices[i+2]) | (o+indices[i+3]) << 16);
577
      }
578
      break;
579
   case PIPE_PRIM_QUAD_STRIP:
580
      for (i = 0; i + 3 < nr_indices; i += 2) {
581
         OUT_BATCH((o+indices[i+0]) | (o+indices[i+1]) << 16);
582
         OUT_BATCH((o+indices[i+3]) | (o+indices[i+2]) << 16);
583
         OUT_BATCH((o+indices[i+0]) | (o+indices[i+3]) << 16);
584
      }
585
      break;
586
   default:
587
      assert(0);
588
      break;
589
   }
590
}
591
 
592
static unsigned
593
draw_calc_nr_indices(uint nr_indices, unsigned type)
594
{
595
   switch (type) {
596
   case 0:
597
      return nr_indices;
598
   case PIPE_PRIM_LINE_LOOP:
599
      if (nr_indices >= 2)
600
         return nr_indices * 2;
601
      else
602
         return 0;
603
   case PIPE_PRIM_QUADS:
604
      return (nr_indices / 4) * 6;
605
   case PIPE_PRIM_QUAD_STRIP:
606
      return ((nr_indices - 2) / 2) * 6;
607
   default:
608
      assert(0);
609
      return 0;
610
   }
611
}
612
 
613
static void
614
i915_vbuf_render_draw_elements(struct vbuf_render *render,
615
                               const ushort *indices,
616
                               uint nr_indices)
617
{
618
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
619
   struct i915_context *i915 = i915_render->i915;
620
   unsigned save_nr_indices;
621
 
622
   save_nr_indices = nr_indices;
623
 
624
   nr_indices = draw_calc_nr_indices(nr_indices, i915_render->fallback);
625
   if (!nr_indices)
626
      return;
627
 
628
   i915_vbuf_ensure_index_bounds(render, i915_render->vbo_max_index);
629
 
630
   if (i915->dirty)
631
      i915_update_derived(i915);
632
 
633
   if (i915->hardware_dirty)
634
      i915_emit_hardware_state(i915);
635
 
636
   if (!BEGIN_BATCH(1 + (nr_indices + 1)/2)) {
637
      FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
638
 
639
      /* Make sure state is re-emitted after a flush:
640
       */
641
      i915_emit_hardware_state(i915);
642
      i915->vbo_flushed = 1;
643
 
644
      if (!BEGIN_BATCH(1 + (nr_indices + 1)/2)) {
645
         assert(0);
646
         goto out;
647
      }
648
   }
649
 
650
   OUT_BATCH(_3DPRIMITIVE |
651
             PRIM_INDIRECT |
652
             i915_render->hwprim |
653
             PRIM_INDIRECT_ELTS |
654
             nr_indices);
655
   draw_generate_indices(render,
656
                         indices,
657
                         save_nr_indices,
658
                         i915_render->fallback);
659
 
660
out:
661
   return;
662
}
663
 
664
static void
665
i915_vbuf_render_release_vertices(struct vbuf_render *render)
666
{
667
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
668
 
669
   i915_render->vbo_sw_offset += i915_render->vbo_max_used;
670
   i915_render->vbo_max_used = 0;
671
 
672
   /*
673
    * Micro optimization, by calling update here we the offset change
674
    * will be picked up on the next pipe_context::draw_*.
675
    */
676
   i915_vbuf_update_vbo_state(render);
677
}
678
 
679
static void
680
i915_vbuf_render_destroy(struct vbuf_render *render)
681
{
682
   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
683
   struct i915_context *i915 = i915_render->i915;
684
   struct i915_winsys *iws = i915->iws;
685
 
686
   if (i915_render->vbo) {
687
      i915->vbo = NULL;
688
      iws->buffer_unmap(iws, i915_render->vbo);
689
      iws->buffer_destroy(iws, i915_render->vbo);
690
   }
691
 
692
   FREE(i915_render);
693
}
694
 
695
/**
696
 * Create a new primitive render.
697
 */
698
static struct vbuf_render *
699
i915_vbuf_render_create(struct i915_context *i915)
700
{
701
   struct i915_vbuf_render *i915_render = CALLOC_STRUCT(i915_vbuf_render);
702
   struct i915_winsys *iws = i915->iws;
703
   int i;
704
 
705
   i915_render->i915 = i915;
706
 
707
   i915_render->base.max_vertex_buffer_bytes = 4*4096;
708
 
709
   /* NOTE: it must be such that state and vertices indices fit in a single
710
    * batch buffer. 4096 is one batch buffer and 430 is the max amount of
711
    * state in dwords. The result is the number of 16-bit indices which can
712
    * fit in a single batch buffer.
713
    */
714
   i915_render->base.max_indices = (4096 - 430 * 4) / 2;
715
 
716
   i915_render->base.get_vertex_info = i915_vbuf_render_get_vertex_info;
717
   i915_render->base.allocate_vertices = i915_vbuf_render_allocate_vertices;
718
   i915_render->base.map_vertices = i915_vbuf_render_map_vertices;
719
   i915_render->base.unmap_vertices = i915_vbuf_render_unmap_vertices;
720
   i915_render->base.set_primitive = i915_vbuf_render_set_primitive;
721
   i915_render->base.draw_elements = i915_vbuf_render_draw_elements;
722
   i915_render->base.draw_arrays = i915_vbuf_render_draw_arrays;
723
   i915_render->base.release_vertices = i915_vbuf_render_release_vertices;
724
   i915_render->base.destroy = i915_vbuf_render_destroy;
725
 
726
#ifndef VBUF_MAP_BUFFER
727
   i915_render->map_size = 0;
728
   i915_render->map_used_start = 0;
729
   i915_render->map_used_end = 0;
730
#endif
731
 
732
   i915_render->vbo = NULL;
733
   i915_render->vbo_ptr = NULL;
734
   i915_render->vbo_size = 0;
735
   i915_render->vbo_hw_offset = 0;
736
   i915_render->vbo_sw_offset = 0;
737
   i915_render->vbo_alloc_size = i915_render->base.max_vertex_buffer_bytes * 4;
738
 
739
#ifdef VBUF_USE_POOL
740
   i915_render->pool_used = FALSE;
741
   i915_render->pool_buffer_size = i915_render->vbo_alloc_size;
742
   i915_render->pool_fifo = u_fifo_create(6);
743
   for (i = 0; i < 6; i++)
744
      u_fifo_add(i915_render->pool_fifo,
745
                 iws->buffer_create(iws, i915_render->pool_buffer_size,
746
                                    I915_NEW_VERTEX));
747
#else
748
   (void)i;
749
   (void)iws;
750
#endif
751
 
752
   return &i915_render->base;
753
}
754
 
755
/**
756
 * Create a new primitive vbuf/render stage.
757
 */
758
struct draw_stage *i915_draw_vbuf_stage(struct i915_context *i915)
759
{
760
   struct vbuf_render *render;
761
   struct draw_stage *stage;
762
 
763
   render = i915_vbuf_render_create(i915);
764
   if(!render)
765
      return NULL;
766
 
767
   stage = draw_vbuf_stage(i915->draw, render);
768
   if(!stage) {
769
      render->destroy(render);
770
      return NULL;
771
   }
772
   /** TODO JB: this shouldn't be here */
773
   draw_set_render(i915->draw, render);
774
 
775
   return stage;
776
}