Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / tnl / t_draw.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.1
4  *
5  * Copyright (C) 1999-2007  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  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Keith Whitwell <keith@tungstengraphics.com>
26  */
27
28 #include "main/glheader.h"
29 #include "main/condrender.h"
30 #include "main/context.h"
31 #include "main/imports.h"
32 #include "main/mtypes.h"
33 #include "main/macros.h"
34 #include "main/enums.h"
35
36 #include "t_context.h"
37 #include "tnl.h"
38
39
40
41 static GLubyte *get_space(struct gl_context *ctx, GLuint bytes)
42 {
43    TNLcontext *tnl = TNL_CONTEXT(ctx);
44    GLubyte *space = malloc(bytes);
45    
46    tnl->block[tnl->nr_blocks++] = space;
47    return space;
48 }
49
50
51 static void free_space(struct gl_context *ctx)
52 {
53    TNLcontext *tnl = TNL_CONTEXT(ctx);
54    GLuint i;
55    for (i = 0; i < tnl->nr_blocks; i++)
56       free(tnl->block[i]);
57    tnl->nr_blocks = 0;
58 }
59
60
61 /* Convert the incoming array to GLfloats.  Understands the
62  * array->Normalized flag and selects the correct conversion method.
63  */
64 #define CONVERT( TYPE, MACRO ) do {             \
65    GLuint i, j;                                 \
66    if (input->Normalized) {                     \
67       for (i = 0; i < count; i++) {             \
68          const TYPE *in = (TYPE *)ptr;          \
69          for (j = 0; j < sz; j++) {             \
70             *fptr++ = MACRO(*in);               \
71             in++;                               \
72          }                                      \
73          ptr += input->StrideB;                 \
74       }                                         \
75    } else {                                     \
76       for (i = 0; i < count; i++) {             \
77          const TYPE *in = (TYPE *)ptr;          \
78          for (j = 0; j < sz; j++) {             \
79             *fptr++ = (GLfloat)(*in);           \
80             in++;                               \
81          }                                      \
82          ptr += input->StrideB;                 \
83       }                                         \
84    }                                            \
85 } while (0)
86
87
88 /**
89  * Convert array of BGRA/GLubyte[4] values to RGBA/float[4]
90  * \param ptr  input/ubyte array
91  * \param fptr  output/float array
92  */
93 static void
94 convert_bgra_to_float(const struct gl_client_array *input,
95                       const GLubyte *ptr, GLfloat *fptr,
96                       GLuint count )
97 {
98    GLuint i;
99    assert(input->Normalized);
100    assert(input->Size == 4);
101    for (i = 0; i < count; i++) {
102       const GLubyte *in = (GLubyte *) ptr;  /* in is in BGRA order */
103       *fptr++ = UBYTE_TO_FLOAT(in[2]);  /* red */
104       *fptr++ = UBYTE_TO_FLOAT(in[1]);  /* green */
105       *fptr++ = UBYTE_TO_FLOAT(in[0]);  /* blue */
106       *fptr++ = UBYTE_TO_FLOAT(in[3]);  /* alpha */
107       ptr += input->StrideB;
108    }
109 }
110
111 static void
112 convert_half_to_float(const struct gl_client_array *input,
113                       const GLubyte *ptr, GLfloat *fptr,
114                       GLuint count, GLuint sz)
115 {
116    GLuint i, j;
117
118    for (i = 0; i < count; i++) {
119       GLhalfARB *in = (GLhalfARB *)ptr;
120
121       for (j = 0; j < sz; j++) {
122          *fptr++ = _mesa_half_to_float(in[j]);
123       }
124       ptr += input->StrideB;
125    }
126 }
127
128 /**
129  * \brief Convert fixed-point to floating-point.
130  *
131  * In OpenGL, a fixed-point number is a "signed 2's complement 16.16 scaled
132  * integer" (Table 2.2 of the OpenGL ES 2.0 spec).
133  *
134  * If the buffer has the \c normalized flag set, the formula
135  *     \code normalize(x) := (2*x + 1) / (2^16 - 1) \endcode
136  * is used to map the fixed-point numbers into the range [-1, 1].
137  */
138 static void
139 convert_fixed_to_float(const struct gl_client_array *input,
140                        const GLubyte *ptr, GLfloat *fptr,
141                        GLuint count)
142 {
143    GLuint i, j;
144    const GLint size = input->Size;
145
146    if (input->Normalized) {
147       for (i = 0; i < count; ++i) {
148          const GLfixed *in = (GLfixed *) ptr;
149          for (j = 0; j < size; ++j) {
150             *fptr++ = (GLfloat) (2 * in[j] + 1) / (GLfloat) ((1 << 16) - 1);
151          }
152          ptr += input->StrideB;
153       }
154    } else {
155       for (i = 0; i < count; ++i) {
156          const GLfixed *in = (GLfixed *) ptr;
157          for (j = 0; j < size; ++j) {
158             *fptr++ = in[j] / (GLfloat) (1 << 16);
159          }
160          ptr += input->StrideB;
161       }
162    }
163 }
164
165 /* Adjust pointer to point at first requested element, convert to
166  * floating point, populate VB->AttribPtr[].
167  */
168 static void _tnl_import_array( struct gl_context *ctx,
169                                GLuint attrib,
170                                GLuint count,
171                                const struct gl_client_array *input,
172                                const GLubyte *ptr )
173 {
174    TNLcontext *tnl = TNL_CONTEXT(ctx);
175    struct vertex_buffer *VB = &tnl->vb;
176    GLuint stride = input->StrideB;
177
178    if (input->Type != GL_FLOAT) {
179       const GLuint sz = input->Size;
180       GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
181       GLfloat *fptr = (GLfloat *)buf;
182
183       switch (input->Type) {
184       case GL_BYTE: 
185          CONVERT(GLbyte, BYTE_TO_FLOAT); 
186          break;
187       case GL_UNSIGNED_BYTE: 
188          if (input->Format == GL_BGRA) {
189             /* See GL_EXT_vertex_array_bgra */
190             convert_bgra_to_float(input, ptr, fptr, count);
191          }
192          else {
193             CONVERT(GLubyte, UBYTE_TO_FLOAT); 
194          }
195          break;
196       case GL_SHORT: 
197          CONVERT(GLshort, SHORT_TO_FLOAT); 
198          break;
199       case GL_UNSIGNED_SHORT: 
200          CONVERT(GLushort, USHORT_TO_FLOAT); 
201          break;
202       case GL_INT: 
203          CONVERT(GLint, INT_TO_FLOAT); 
204          break;
205       case GL_UNSIGNED_INT: 
206          CONVERT(GLuint, UINT_TO_FLOAT); 
207          break;
208       case GL_DOUBLE: 
209          CONVERT(GLdouble, (GLfloat)); 
210          break;
211       case GL_HALF_FLOAT:
212          convert_half_to_float(input, ptr, fptr, count, sz);
213          break;
214       case GL_FIXED:
215          convert_fixed_to_float(input, ptr, fptr, count);
216          break;
217       default:
218          assert(0);
219          break;
220       }
221
222       ptr = buf;
223       stride = sz * sizeof(GLfloat);
224    }
225
226    VB->AttribPtr[attrib] = &tnl->tmp_inputs[attrib];
227    VB->AttribPtr[attrib]->data = (GLfloat (*)[4])ptr;
228    VB->AttribPtr[attrib]->start = (GLfloat *)ptr;
229    VB->AttribPtr[attrib]->count = count;
230    VB->AttribPtr[attrib]->stride = stride;
231    VB->AttribPtr[attrib]->size = input->Size;
232
233    /* This should die, but so should the whole GLvector4f concept: 
234     */
235    VB->AttribPtr[attrib]->flags = (((1<<input->Size)-1) | 
236                                    VEC_NOT_WRITEABLE |
237                                    (stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE));
238    
239    VB->AttribPtr[attrib]->storage = NULL;
240 }
241
242 #define CLIPVERTS  ((6 + MAX_CLIP_PLANES) * 2)
243
244
245 static GLboolean *_tnl_import_edgeflag( struct gl_context *ctx,
246                                         const GLvector4f *input,
247                                         GLuint count)
248 {
249    const GLubyte *ptr = (const GLubyte *)input->data;
250    const GLuint stride = input->stride;
251    GLboolean *space = (GLboolean *)get_space(ctx, count + CLIPVERTS);
252    GLboolean *bptr = space;
253    GLuint i;
254
255    for (i = 0; i < count; i++) {
256       *bptr++ = ((GLfloat *)ptr)[0] == 1.0;
257       ptr += stride;
258    }
259
260    return space;
261 }
262
263
264 static void bind_inputs( struct gl_context *ctx, 
265                          const struct gl_client_array *inputs[],
266                          GLint count,
267                          struct gl_buffer_object **bo,
268                          GLuint *nr_bo )
269 {
270    TNLcontext *tnl = TNL_CONTEXT(ctx);
271    struct vertex_buffer *VB = &tnl->vb;
272    GLuint i;
273
274    /* Map all the VBOs
275     */
276    for (i = 0; i < VERT_ATTRIB_MAX; i++) {
277       const void *ptr;
278
279       if (inputs[i]->BufferObj->Name) { 
280          if (!inputs[i]->BufferObj->Pointer) {
281             bo[*nr_bo] = inputs[i]->BufferObj;
282             (*nr_bo)++;
283             ctx->Driver.MapBuffer(ctx, 
284                                   GL_ARRAY_BUFFER,
285                                   GL_READ_ONLY_ARB,
286                                   inputs[i]->BufferObj);
287             
288             assert(inputs[i]->BufferObj->Pointer);
289          }
290          
291          ptr = ADD_POINTERS(inputs[i]->BufferObj->Pointer,
292                             inputs[i]->Ptr);
293       }
294       else
295          ptr = inputs[i]->Ptr;
296
297       /* Just make sure the array is floating point, otherwise convert to
298        * temporary storage.  
299        *
300        * XXX: remove the GLvector4f type at some stage and just use
301        * client arrays.
302        */
303       _tnl_import_array(ctx, i, count, inputs[i], ptr);
304    }
305
306    /* We process only the vertices between min & max index:
307     */
308    VB->Count = count;
309
310    /* These should perhaps be part of _TNL_ATTRIB_* */
311    VB->BackfaceColorPtr = NULL;
312    VB->BackfaceIndexPtr = NULL;
313    VB->BackfaceSecondaryColorPtr = NULL;
314
315    /* Clipping and drawing code still requires this to be a packed
316     * array of ubytes which can be written into.  TODO: Fix and
317     * remove.
318     */
319    if (ctx->Polygon.FrontMode != GL_FILL ||
320        ctx->Polygon.BackMode != GL_FILL)
321    {
322       VB->EdgeFlag = _tnl_import_edgeflag( ctx, 
323                                            VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG],
324                                            VB->Count );
325    }
326    else {
327       /* the data previously pointed to by EdgeFlag may have been freed */
328       VB->EdgeFlag = NULL;
329    }
330 }
331
332
333 /* Translate indices to GLuints and store in VB->Elts.
334  */
335 static void bind_indices( struct gl_context *ctx,
336                           const struct _mesa_index_buffer *ib,
337                           struct gl_buffer_object **bo,
338                           GLuint *nr_bo)
339 {
340    TNLcontext *tnl = TNL_CONTEXT(ctx);
341    struct vertex_buffer *VB = &tnl->vb;
342    GLuint i;
343    void *ptr;
344
345    if (!ib) {
346       VB->Elts = NULL;
347       return;
348    }
349
350    if (ib->obj->Name && !ib->obj->Pointer) {
351       bo[*nr_bo] = ib->obj;
352       (*nr_bo)++;
353       ctx->Driver.MapBuffer(ctx, 
354                             GL_ELEMENT_ARRAY_BUFFER,
355                             GL_READ_ONLY_ARB,
356                             ib->obj);
357
358       assert(ib->obj->Pointer);
359    }
360
361    ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
362
363    if (ib->type == GL_UNSIGNED_INT && VB->Primitive[0].basevertex == 0) {
364       VB->Elts = (GLuint *) ptr;
365    }
366    else {
367       GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
368       VB->Elts = elts;
369
370       if (ib->type == GL_UNSIGNED_INT) {
371          const GLuint *in = (GLuint *)ptr;
372          for (i = 0; i < ib->count; i++)
373             *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
374       }
375       else if (ib->type == GL_UNSIGNED_SHORT) {
376          const GLushort *in = (GLushort *)ptr;
377          for (i = 0; i < ib->count; i++) 
378             *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
379       }
380       else {
381          const GLubyte *in = (GLubyte *)ptr;
382          for (i = 0; i < ib->count; i++) 
383             *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
384       }
385    }
386 }
387
388 static void bind_prims( struct gl_context *ctx,
389                         const struct _mesa_prim *prim,
390                         GLuint nr_prims )
391 {
392    TNLcontext *tnl = TNL_CONTEXT(ctx);
393    struct vertex_buffer *VB = &tnl->vb;
394
395    VB->Primitive = prim;
396    VB->PrimitiveCount = nr_prims;
397 }
398
399 static void unmap_vbos( struct gl_context *ctx,
400                         struct gl_buffer_object **bo,
401                         GLuint nr_bo )
402 {
403    GLuint i;
404    for (i = 0; i < nr_bo; i++) { 
405       ctx->Driver.UnmapBuffer(ctx, 
406                               0, /* target -- I don't see why this would be needed */
407                               bo[i]);
408    }
409 }
410
411
412 void _tnl_vbo_draw_prims(struct gl_context *ctx,
413                          const struct gl_client_array *arrays[],
414                          const struct _mesa_prim *prim,
415                          GLuint nr_prims,
416                          const struct _mesa_index_buffer *ib,
417                          GLboolean index_bounds_valid,
418                          GLuint min_index,
419                          GLuint max_index)
420 {
421    if (!index_bounds_valid)
422       vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
423
424    _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
425 }
426
427 /* This is the main entrypoint into the slimmed-down software tnl
428  * module.  In a regular swtnl driver, this can be plugged straight
429  * into the vbo->Driver.DrawPrims() callback.
430  */
431 void _tnl_draw_prims( struct gl_context *ctx,
432                       const struct gl_client_array *arrays[],
433                       const struct _mesa_prim *prim,
434                       GLuint nr_prims,
435                       const struct _mesa_index_buffer *ib,
436                       GLuint min_index,
437                       GLuint max_index)
438 {
439    TNLcontext *tnl = TNL_CONTEXT(ctx);
440    const GLuint TEST_SPLIT = 0;
441    const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
442    GLint max_basevertex = prim->basevertex;
443    GLuint i;
444
445    /* Mesa core state should have been validated already */
446    assert(ctx->NewState == 0x0);
447
448    if (!_mesa_check_conditional_render(ctx))
449       return; /* don't draw */
450
451    for (i = 1; i < nr_prims; i++)
452       max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
453
454    if (0)
455    {
456       printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
457       for (i = 0; i < nr_prims; i++)
458          printf("prim %d: %s start %d count %d\n", i, 
459                 _mesa_lookup_enum_by_nr(prim[i].mode),
460                 prim[i].start,
461                 prim[i].count);
462    }
463
464    if (min_index) {
465       /* We always translate away calls with min_index != 0. 
466        */
467       vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, 
468                         min_index, max_index,
469                         _tnl_vbo_draw_prims );
470       return;
471    }
472    else if ((GLint)max_index + max_basevertex > max) {
473       /* The software TNL pipeline has a fixed amount of storage for
474        * vertices and it is necessary to split incoming drawing commands
475        * if they exceed that limit.
476        */
477       struct split_limits limits;
478       limits.max_verts = max;
479       limits.max_vb_size = ~0;
480       limits.max_indices = ~0;
481
482       /* This will split the buffers one way or another and
483        * recursively call back into this function.
484        */
485       vbo_split_prims( ctx, arrays, prim, nr_prims, ib, 
486                        0, max_index + prim->basevertex,
487                        _tnl_vbo_draw_prims,
488                        &limits );
489    }
490    else {
491       /* May need to map a vertex buffer object for every attribute plus
492        * one for the index buffer.
493        */
494       struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
495       GLuint nr_bo = 0;
496       GLuint inst;
497
498       for (i = 0; i < nr_prims;) {
499          GLuint this_nr_prims;
500
501          /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
502           * will rebase the elements to the basevertex, and we'll only
503           * emit strings of prims with the same basevertex in one draw call.
504           */
505          for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
506               this_nr_prims++) {
507             if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
508                break;
509          }
510
511          assert(prim[i].num_instances > 0);
512
513          /* Binding inputs may imply mapping some vertex buffer objects.
514           * They will need to be unmapped below.
515           */
516          for (inst = 0; inst < prim[i].num_instances; inst++) {
517
518             bind_prims(ctx, &prim[i], this_nr_prims);
519             bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1,
520                         bo, &nr_bo);
521             bind_indices(ctx, ib, bo, &nr_bo);
522
523             tnl->CurInstance = inst;
524             TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
525
526             unmap_vbos(ctx, bo, nr_bo);
527             free_space(ctx);
528          }
529
530          i += this_nr_prims;
531       }
532    }
533 }
534