Subversion Repositories Kolibri OS

Rev

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

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