Subversion Repositories Kolibri OS

Rev

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

  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.  
  497.       for (i = 0; i < nr_prims;) {
  498.          GLuint this_nr_prims;
  499.  
  500.          /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
  501.           * will rebase the elements to the basevertex, and we'll only
  502.           * emit strings of prims with the same basevertex in one draw call.
  503.           */
  504.          for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
  505.               this_nr_prims++) {
  506.             if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
  507.                break;
  508.          }
  509.  
  510.          /* Binding inputs may imply mapping some vertex buffer objects.
  511.           * They will need to be unmapped below.
  512.           */
  513.          bind_prims(ctx, &prim[i], this_nr_prims);
  514.          bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1,
  515.                      bo, &nr_bo);
  516.          bind_indices(ctx, ib, bo, &nr_bo);
  517.  
  518.          TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
  519.  
  520.          unmap_vbos(ctx, bo, nr_bo);
  521.          free_space(ctx);
  522.  
  523.          i += this_nr_prims;
  524.       }
  525.    }
  526. }
  527.  
  528.