Subversion Repositories Kolibri OS

Rev

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