OSDN Git Service

virgl: add openarena readpixels workaround.
[android-x86/external-mesa.git] / src / mesa / vbo / vbo_split_copy.c
1
2 /*
3  * Mesa 3-D graphics library
4  *
5  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Keith Whitwell <keithw@vmware.com>
27  */
28
29 /* Split indexed primitives with per-vertex copying.
30  */
31
32 #include <stdio.h>
33
34 #include "main/glheader.h"
35 #include "main/bufferobj.h"
36 #include "main/imports.h"
37 #include "main/glformats.h"
38 #include "main/macros.h"
39 #include "main/mtypes.h"
40
41 #include "vbo_split.h"
42 #include "vbo.h"
43
44
45 #define ELT_TABLE_SIZE 16
46
47 /**
48  * Used for vertex-level splitting of indexed buffers.  Note that
49  * non-indexed primitives may be converted to indexed in some cases
50  * (eg loops, fans) in order to use this splitting path.
51  */
52 struct copy_context {
53
54    struct gl_context *ctx;
55    const struct gl_client_array **array;
56    const struct _mesa_prim *prim;
57    GLuint nr_prims;
58    const struct _mesa_index_buffer *ib;
59    vbo_draw_func draw;
60
61    const struct split_limits *limits;
62
63    struct {
64       GLuint attr;
65       GLuint size;
66       const struct gl_client_array *array;
67       const GLubyte *src_ptr;
68
69       struct gl_client_array dstarray;
70
71    } varying[VERT_ATTRIB_MAX];
72    GLuint nr_varying;
73
74    const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX];
75    struct _mesa_index_buffer dstib;
76
77    GLuint *translated_elt_buf;
78    const GLuint *srcelt;
79
80    /** A baby hash table to avoid re-emitting (some) duplicate
81     * vertices when splitting indexed primitives.
82     */
83    struct { 
84       GLuint in;
85       GLuint out;
86    } vert_cache[ELT_TABLE_SIZE];
87
88    GLuint vertex_size;
89    GLubyte *dstbuf;
90    GLubyte *dstptr;     /**< dstptr == dstbuf + dstelt_max * vertsize */
91    GLuint dstbuf_size;  /**< in vertices */
92    GLuint dstbuf_nr;    /**< count of emitted vertices, also the largest value
93                          * in dstelt.  Our MaxIndex.
94                          */
95
96    GLuint *dstelt;
97    GLuint dstelt_nr;
98    GLuint dstelt_size;
99
100 #define MAX_PRIM 32
101    struct _mesa_prim dstprim[MAX_PRIM];
102    GLuint dstprim_nr;
103
104 };
105
106
107 static GLuint attr_size( const struct gl_client_array *array )
108 {
109    return array->Size * _mesa_sizeof_type(array->Type);
110 }
111
112
113 /**
114  * Starts returning true slightly before the buffer fills, to ensure
115  * that there is sufficient room for any remaining vertices to finish
116  * off the prim:
117  */
118 static GLboolean
119 check_flush( struct copy_context *copy )
120 {
121    GLenum mode = copy->dstprim[copy->dstprim_nr].mode; 
122
123    if (GL_TRIANGLE_STRIP == mode &&
124        copy->dstelt_nr & 1) { /* see bug9962 */
125        return GL_FALSE;
126    }
127
128    if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
129       return GL_TRUE;
130
131    if (copy->dstelt_nr + 4 > copy->dstelt_size)
132       return GL_TRUE;
133
134    return GL_FALSE;
135 }
136
137
138 /**
139  * Dump the parameters/info for a vbo->draw() call.
140  */
141 static void
142 dump_draw_info(struct gl_context *ctx,
143                const struct gl_client_array **arrays,
144                const struct _mesa_prim *prims,
145                GLuint nr_prims,
146                const struct _mesa_index_buffer *ib,
147                GLuint min_index,
148                GLuint max_index)
149 {
150    GLuint i, j;
151
152    printf("VBO Draw:\n");
153    for (i = 0; i < nr_prims; i++) {
154       printf("Prim %u of %u\n", i, nr_prims);
155       printf("  Prim mode 0x%x\n", prims[i].mode);
156       printf("  IB: %p\n", (void*) ib);
157       for (j = 0; j < VERT_ATTRIB_MAX; j++) {
158          printf("    array %d at %p:\n", j, (void*) arrays[j]);
159          printf("      enabled %d, ptr %p, size %d, type 0x%x, stride %d\n",
160                 arrays[j]->Enabled, arrays[j]->Ptr,
161                 arrays[j]->Size, arrays[j]->Type, arrays[j]->StrideB);
162          if (0) {
163             GLint k = prims[i].start + prims[i].count - 1;
164             GLfloat *last = (GLfloat *) (arrays[j]->Ptr + arrays[j]->Stride * k);
165             printf("        last: %f %f %f\n",
166                    last[0], last[1], last[2]);
167          }
168       }
169    }
170 }
171
172
173 static void
174 flush( struct copy_context *copy )
175 {
176    struct gl_context *ctx = copy->ctx;
177    const struct gl_client_array **saved_arrays = ctx->Array._DrawArrays;
178    GLuint i;
179
180    /* Set some counters: 
181     */
182    copy->dstib.count = copy->dstelt_nr;
183
184 #if 0
185    dump_draw_info(copy->ctx,
186                   copy->dstarray_ptr,
187                   copy->dstprim,
188                   copy->dstprim_nr,
189                   &copy->dstib,
190                   0,
191                   copy->dstbuf_nr);
192 #else
193    (void) dump_draw_info;
194 #endif
195
196    ctx->Array._DrawArrays = copy->dstarray_ptr;
197    ctx->NewDriverState |= ctx->DriverFlags.NewArray;
198
199    copy->draw( ctx,
200                copy->dstprim,
201                copy->dstprim_nr,
202                &copy->dstib,
203                GL_TRUE,
204                0,
205                copy->dstbuf_nr - 1,
206                NULL, 0, NULL );
207
208    ctx->Array._DrawArrays = saved_arrays;
209    ctx->NewDriverState |= ctx->DriverFlags.NewArray;
210
211    /* Reset all pointers: 
212     */
213    copy->dstprim_nr = 0;
214    copy->dstelt_nr = 0;
215    copy->dstbuf_nr = 0;
216    copy->dstptr = copy->dstbuf;
217
218    /* Clear the vertex cache:
219     */
220    for (i = 0; i < ELT_TABLE_SIZE; i++)
221       copy->vert_cache[i].in = ~0;
222 }
223
224
225 /**
226  * Called at begin of each primitive during replay.
227  */
228 static void
229 begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
230 {
231    struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
232
233    prim->mode = mode;
234    prim->begin = begin_flag;
235    prim->num_instances = 1;
236 }
237
238
239 /**
240  * Use a hashtable to attempt to identify recently-emitted vertices
241  * and avoid re-emitting them.
242  */
243 static GLuint
244 elt(struct copy_context *copy, GLuint elt_idx)
245 {
246    GLuint elt = copy->srcelt[elt_idx];
247    GLuint slot = elt & (ELT_TABLE_SIZE-1);
248
249 /*    printf("elt %d\n", elt); */
250
251    /* Look up the incoming element in the vertex cache.  Re-emit if
252     * necessary.   
253     */
254    if (copy->vert_cache[slot].in != elt) {
255       GLubyte *csr = copy->dstptr;
256       GLuint i;
257
258 /*       printf("  --> emit to dstelt %d\n", copy->dstbuf_nr); */
259
260       for (i = 0; i < copy->nr_varying; i++) {
261          const struct gl_client_array *srcarray = copy->varying[i].array;
262          const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB;
263
264          memcpy(csr, srcptr, copy->varying[i].size);
265          csr += copy->varying[i].size;
266
267 #ifdef NAN_CHECK
268          if (srcarray->Type == GL_FLOAT) {
269             GLuint k;
270             GLfloat *f = (GLfloat *) srcptr;
271             for (k = 0; k < srcarray->Size; k++) {
272                assert(!IS_INF_OR_NAN(f[k]));
273                assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
274             }
275          }
276 #endif
277
278          if (0) 
279          {
280             const GLuint *f = (const GLuint *)srcptr;
281             GLuint j;
282             printf("  varying %d: ", i);
283             for(j = 0; j < copy->varying[i].size / 4; j++)
284                printf("%x ", f[j]);
285             printf("\n");
286          }
287       }
288
289       copy->vert_cache[slot].in = elt;
290       copy->vert_cache[slot].out = copy->dstbuf_nr++;
291       copy->dstptr += copy->vertex_size;
292
293       assert(csr == copy->dstptr);
294       assert(copy->dstptr == (copy->dstbuf +
295                               copy->dstbuf_nr * copy->vertex_size));
296    }
297 /*    else */
298 /*       printf("  --> reuse vertex\n"); */
299    
300 /*    printf("  --> emit %d\n", copy->vert_cache[slot].out); */
301    copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
302    return check_flush(copy);
303 }
304
305
306 /**
307  * Called at end of each primitive during replay.
308  */
309 static void
310 end( struct copy_context *copy, GLboolean end_flag )
311 {
312    struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
313
314 /*    printf("end (%d)\n", end_flag); */
315
316    prim->end = end_flag;
317    prim->count = copy->dstelt_nr - prim->start;
318
319    if (++copy->dstprim_nr == MAX_PRIM ||
320        check_flush(copy)) 
321       flush(copy);
322 }
323
324
325 static void
326 replay_elts( struct copy_context *copy )
327 {
328    GLuint i, j, k;
329    GLboolean split;
330
331    for (i = 0; i < copy->nr_prims; i++) {
332       const struct _mesa_prim *prim = &copy->prim[i];
333       const GLuint start = prim->start;
334       GLuint first, incr;
335
336       switch (prim->mode) {
337          
338       case GL_LINE_LOOP:
339          /* Convert to linestrip and emit the final vertex explicitly,
340           * but only in the resultant strip that requires it.
341           */
342          j = 0;
343          while (j != prim->count) {
344             begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
345
346             for (split = GL_FALSE; j != prim->count && !split; j++)
347                split = elt(copy, start + j);
348
349             if (j == prim->count) {
350                /* Done, emit final line.  Split doesn't matter as
351                 * it is always raised a bit early so we can emit
352                 * the last verts if necessary!
353                 */
354                if (prim->end) 
355                   (void)elt(copy, start + 0);
356
357                end(copy, prim->end);
358             }
359             else {
360                /* Wrap
361                 */
362                assert(split);
363                end(copy, 0);
364                j--;
365             }
366          }
367          break;
368
369       case GL_TRIANGLE_FAN:
370       case GL_POLYGON:
371          j = 2;
372          while (j != prim->count) {
373             begin(copy, prim->mode, prim->begin && j == 0);
374
375             split = elt(copy, start+0); 
376             assert(!split);
377
378             split = elt(copy, start+j-1); 
379             assert(!split);
380
381             for (; j != prim->count && !split; j++)
382                split = elt(copy, start+j);
383
384             end(copy, prim->end && j == prim->count);
385
386             if (j != prim->count) {
387                /* Wrapped the primitive, need to repeat some vertices:
388                 */
389                j -= 1;
390             }
391          }
392          break;
393
394       default:
395          (void)split_prim_inplace(prim->mode, &first, &incr);
396          
397          j = 0;
398          while (j != prim->count) {
399
400             begin(copy, prim->mode, prim->begin && j == 0);
401
402             split = 0;
403             for (k = 0; k < first; k++, j++)
404                split |= elt(copy, start+j);
405
406             assert(!split);
407
408             for (; j != prim->count && !split; )
409                for (k = 0; k < incr; k++, j++)
410                   split |= elt(copy, start+j);
411
412             end(copy, prim->end && j == prim->count);
413
414             if (j != prim->count) {
415                /* Wrapped the primitive, need to repeat some vertices:
416                 */
417                assert(j > first - incr);
418                j -= (first - incr);
419             }
420          }
421          break;
422       }
423    }
424
425    if (copy->dstprim_nr)
426       flush(copy);
427 }
428
429
430 static void
431 replay_init( struct copy_context *copy )
432 {
433    struct gl_context *ctx = copy->ctx;
434    GLuint i;
435    GLuint offset;
436    const GLvoid *srcptr;
437
438    /* Make a list of varying attributes and their vbo's.  Also
439     * calculate vertex size.
440     */
441    copy->vertex_size = 0;
442    for (i = 0; i < VERT_ATTRIB_MAX; i++) {
443       struct gl_buffer_object *vbo = copy->array[i]->BufferObj;
444
445       if (copy->array[i]->StrideB == 0) {
446          copy->dstarray_ptr[i] = copy->array[i];
447       }
448       else {
449          GLuint j = copy->nr_varying++;
450          
451          copy->varying[j].attr = i;
452          copy->varying[j].array = copy->array[i];
453          copy->varying[j].size = attr_size(copy->array[i]);
454          copy->vertex_size += attr_size(copy->array[i]);
455       
456          if (_mesa_is_bufferobj(vbo) &&
457              !_mesa_bufferobj_mapped(vbo, MAP_INTERNAL))
458             ctx->Driver.MapBufferRange(ctx, 0, vbo->Size, GL_MAP_READ_BIT, vbo,
459                                        MAP_INTERNAL);
460
461          copy->varying[j].src_ptr =
462                ADD_POINTERS(vbo->Mappings[MAP_INTERNAL].Pointer,
463                             copy->array[i]->Ptr);
464
465          copy->dstarray_ptr[i] = &copy->varying[j].dstarray;
466       }
467    }
468
469    /* There must always be an index buffer.  Currently require the
470     * caller convert non-indexed prims to indexed.  Could alternately
471     * do it internally.
472     */
473    if (_mesa_is_bufferobj(copy->ib->obj) &&
474        !_mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL))
475       ctx->Driver.MapBufferRange(ctx, 0, copy->ib->obj->Size, GL_MAP_READ_BIT,
476                                  copy->ib->obj, MAP_INTERNAL);
477
478    srcptr = (const GLubyte *)
479             ADD_POINTERS(copy->ib->obj->Mappings[MAP_INTERNAL].Pointer,
480                          copy->ib->ptr);
481
482    switch (copy->ib->type) {
483    case GL_UNSIGNED_BYTE:
484       copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
485       copy->srcelt = copy->translated_elt_buf;
486
487       for (i = 0; i < copy->ib->count; i++)
488          copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
489       break;
490
491    case GL_UNSIGNED_SHORT:
492       copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
493       copy->srcelt = copy->translated_elt_buf;
494
495       for (i = 0; i < copy->ib->count; i++)
496          copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
497       break;
498
499    case GL_UNSIGNED_INT:
500       copy->translated_elt_buf = NULL;
501       copy->srcelt = (const GLuint *)srcptr;
502       break;
503    }
504
505    /* Figure out the maximum allowed vertex buffer size:
506     */
507    if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
508       copy->dstbuf_size = copy->limits->max_verts;
509    }
510    else {
511       copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
512    }
513
514    /* Allocate an output vertex buffer:
515     *
516     * XXX:  This should be a VBO!
517     */
518    copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size);   
519    copy->dstptr = copy->dstbuf;
520
521    /* Setup new vertex arrays to point into the output buffer: 
522     */
523    for (offset = 0, i = 0; i < copy->nr_varying; i++) {
524       const struct gl_client_array *src = copy->varying[i].array;
525       struct gl_client_array *dst = &copy->varying[i].dstarray;
526
527       dst->Size = src->Size;
528       dst->Type = src->Type;
529       dst->Format = GL_RGBA;
530       dst->Stride = copy->vertex_size;
531       dst->StrideB = copy->vertex_size;
532       dst->Ptr = copy->dstbuf + offset;
533       dst->Enabled = GL_TRUE;
534       dst->Normalized = src->Normalized; 
535       dst->Integer = src->Integer;
536       dst->Doubles = src->Doubles;
537       dst->BufferObj = ctx->Shared->NullBufferObj;
538       dst->_ElementSize = src->_ElementSize;
539
540       offset += copy->varying[i].size;
541    }
542
543    /* Allocate an output element list:
544     */
545    copy->dstelt_size = MIN2(65536,
546                             copy->ib->count * 2 + 3);
547    copy->dstelt_size = MIN2(copy->dstelt_size,
548                             copy->limits->max_indices);
549    copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size);
550    copy->dstelt_nr = 0;
551
552    /* Setup the new index buffer to point to the allocated element
553     * list:
554     */
555    copy->dstib.count = 0;       /* duplicates dstelt_nr */
556    copy->dstib.type = GL_UNSIGNED_INT;
557    copy->dstib.obj = ctx->Shared->NullBufferObj;
558    copy->dstib.ptr = copy->dstelt;
559 }
560
561
562 /**
563  * Free up everything allocated during split/replay.
564  */
565 static void
566 replay_finish( struct copy_context *copy )
567 {
568    struct gl_context *ctx = copy->ctx;
569    GLuint i;
570
571    /* Free our vertex and index buffers: 
572     */
573    free(copy->translated_elt_buf);
574    free(copy->dstbuf);
575    free(copy->dstelt);
576
577    /* Unmap VBO's 
578     */
579    for (i = 0; i < copy->nr_varying; i++) {
580       struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj;
581       if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo, MAP_INTERNAL))
582          ctx->Driver.UnmapBuffer(ctx, vbo, MAP_INTERNAL);
583    }
584
585    /* Unmap index buffer:
586     */
587    if (_mesa_is_bufferobj(copy->ib->obj) &&
588        _mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL)) {
589       ctx->Driver.UnmapBuffer(ctx, copy->ib->obj, MAP_INTERNAL);
590    }
591 }
592
593
594 /**
595  * Split VBO into smaller pieces, draw the pieces.
596  */
597 void vbo_split_copy( struct gl_context *ctx,
598                      const struct gl_client_array *arrays[],
599                      const struct _mesa_prim *prim,
600                      GLuint nr_prims,
601                      const struct _mesa_index_buffer *ib,
602                      vbo_draw_func draw,
603                      const struct split_limits *limits )
604 {
605    struct copy_context copy;
606    GLuint i, this_nr_prims;
607
608    for (i = 0; i < nr_prims;) {
609       /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
610        * will rebase the elements to the basevertex, and we'll only
611        * emit strings of prims with the same basevertex in one draw call.
612        */
613       for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
614            this_nr_prims++) {
615          if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
616             break;
617       }
618
619       memset(&copy, 0, sizeof(copy));
620
621       /* Require indexed primitives:
622        */
623       assert(ib);
624
625       copy.ctx = ctx;
626       copy.array = arrays;
627       copy.prim = &prim[i];
628       copy.nr_prims = this_nr_prims;
629       copy.ib = ib;
630       copy.draw = draw;
631       copy.limits = limits;
632
633       /* Clear the vertex cache:
634        */
635       for (i = 0; i < ELT_TABLE_SIZE; i++)
636          copy.vert_cache[i].in = ~0;
637
638       replay_init(&copy);
639       replay_elts(&copy);
640       replay_finish(&copy);
641    }
642 }