Subversion Repositories Kolibri OS

Rev

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

  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 <keith@tungstengraphics.com>
  27.  */
  28.  
  29. /* Helper for drivers which find themselves rendering a range of
  30.  * indices starting somewhere above zero.  Typically the application
  31.  * is issuing multiple DrawArrays() or DrawElements() to draw
  32.  * successive primitives layed out linearly in the vertex arrays.
  33.  * Unless the vertex arrays are all in a VBO, the OpenGL semantics
  34.  * imply that we need to re-upload the vertex data on each draw call.
  35.  * In that case, we want to avoid starting the upload at zero, as it
  36.  * will mean every draw call uploads an increasing amount of not-used
  37.  * vertex data.  Worse - in the software tnl module, all those
  38.  * vertices will be transformed and lit.
  39.  *
  40.  * If we just upload the new data, however, the indices will be
  41.  * incorrect as we tend to upload each set of vertex data to a new
  42.  * region.  
  43.  *
  44.  * This file provides a helper to adjust the arrays, primitives and
  45.  * indices of a draw call so that it can be re-issued with a min_index
  46.  * of zero.
  47.  */
  48.  
  49. #include "main/glheader.h"
  50. #include "main/imports.h"
  51. #include "main/mtypes.h"
  52.  
  53. #include "vbo.h"
  54.  
  55.  
  56. #define REBASE(TYPE)                                            \
  57. static void *rebase_##TYPE( const void *ptr,                    \
  58.                           GLuint count,                         \
  59.                           TYPE min_index )                      \
  60. {                                                               \
  61.    const TYPE *in = (TYPE *)ptr;                                \
  62.    TYPE *tmp_indices = malloc(count * sizeof(TYPE));    \
  63.    GLuint i;                                                    \
  64.                                                                 \
  65.    for (i = 0; i < count; i++)                                  \
  66.       tmp_indices[i] = in[i] - min_index;                       \
  67.                                                                 \
  68.    return (void *)tmp_indices;                                  \
  69. }
  70.  
  71.  
  72. REBASE(GLuint)
  73. REBASE(GLushort)
  74. REBASE(GLubyte)
  75.  
  76. GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] )
  77. {
  78.    GLuint i;
  79.    
  80.    for (i = 0; i < VERT_ATTRIB_MAX; i++)
  81.       if (arrays[i]->StrideB &&
  82.           arrays[i]->BufferObj->Name == 0)
  83.          return GL_FALSE;
  84.  
  85.    return GL_TRUE;
  86. }
  87.  
  88. GLboolean vbo_any_varyings_in_vbos( const struct gl_client_array *arrays[] )
  89. {
  90.    GLuint i;
  91.  
  92.    for (i = 0; i < VERT_ATTRIB_MAX; i++)
  93.       if (arrays[i]->BufferObj->Name != 0)
  94.          return GL_TRUE;
  95.  
  96.    return GL_FALSE;
  97. }
  98.  
  99. /* Adjust primitives, indices and vertex definitions so that min_index
  100.  * becomes zero. There are lots of reasons for wanting to do this, eg:
  101.  *
  102.  * Software tnl:
  103.  *    - any time min_index != 0, otherwise unused vertices lower than
  104.  *      min_index will be transformed.
  105.  *
  106.  * Hardware tnl:
  107.  *    - if ib != NULL and min_index != 0, otherwise vertices lower than
  108.  *      min_index will be uploaded.  Requires adjusting index values.
  109.  *
  110.  *    - if ib == NULL and min_index != 0, just for convenience so this doesn't
  111.  *      have to be handled within the driver.
  112.  *
  113.  * Hardware tnl with VBO support:
  114.  *    - as above, but only when vertices are not (all?) in VBO's.
  115.  *    - can't save time by trying to upload half a vbo - typically it is
  116.  *      all or nothing.
  117.  */
  118. void vbo_rebase_prims( struct gl_context *ctx,
  119.                        const struct gl_client_array *arrays[],
  120.                        const struct _mesa_prim *prim,
  121.                        GLuint nr_prims,
  122.                        const struct _mesa_index_buffer *ib,
  123.                        GLuint min_index,
  124.                        GLuint max_index,
  125.                        vbo_draw_func draw )
  126. {
  127.    struct gl_client_array tmp_arrays[VERT_ATTRIB_MAX];
  128.    const struct gl_client_array *tmp_array_pointers[VERT_ATTRIB_MAX];
  129.  
  130.    struct _mesa_index_buffer tmp_ib;
  131.    struct _mesa_prim *tmp_prims = NULL;
  132.    const struct gl_client_array **saved_arrays = ctx->Array._DrawArrays;
  133.    void *tmp_indices = NULL;
  134.    GLuint i;
  135.  
  136.    assert(min_index != 0);
  137.  
  138.    if (0)
  139.       printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
  140.  
  141.  
  142.    /* XXX this path is disabled for now.
  143.     * There's rendering corruption in some apps when it's enabled.
  144.     */
  145.    if (0 && ib && ctx->Extensions.ARB_draw_elements_base_vertex) {
  146.       /* If we can just tell the hardware or the TNL to interpret our
  147.        * indices with a different base, do so.
  148.        */
  149.       tmp_prims = malloc(sizeof(*prim) * nr_prims);
  150.  
  151.       for (i = 0; i < nr_prims; i++) {
  152.          tmp_prims[i] = prim[i];
  153.          tmp_prims[i].basevertex -= min_index;
  154.       }
  155.  
  156.       prim = tmp_prims;
  157.    } else if (ib) {
  158.       /* Unfortunately need to adjust each index individually.
  159.        */
  160.       GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer;
  161.       void *ptr;
  162.  
  163.       if (map_ib)
  164.          ctx->Driver.MapBufferRange(ctx, 0, ib->obj->Size, GL_MAP_READ_BIT,
  165.                                     ib->obj);
  166.  
  167.  
  168.       ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
  169.  
  170.       /* Some users might prefer it if we translated elements to
  171.        * GLuints here.  Others wouldn't...
  172.        */
  173.       switch (ib->type) {
  174.       case GL_UNSIGNED_INT:
  175.          tmp_indices = rebase_GLuint( ptr, ib->count, min_index );
  176.          break;
  177.       case GL_UNSIGNED_SHORT:
  178.          tmp_indices = rebase_GLushort( ptr, ib->count, min_index );
  179.          break;
  180.       case GL_UNSIGNED_BYTE:
  181.          tmp_indices = rebase_GLubyte( ptr, ib->count, min_index );
  182.          break;
  183.       }      
  184.  
  185.       if (map_ib)
  186.          ctx->Driver.UnmapBuffer(ctx, ib->obj);
  187.  
  188.       tmp_ib.obj = ctx->Shared->NullBufferObj;
  189.       tmp_ib.ptr = tmp_indices;
  190.       tmp_ib.count = ib->count;
  191.       tmp_ib.type = ib->type;
  192.  
  193.       ib = &tmp_ib;
  194.    }
  195.    else {
  196.       /* Otherwise the primitives need adjustment.
  197.        */
  198.       tmp_prims = malloc(sizeof(*prim) * nr_prims);
  199.  
  200.       for (i = 0; i < nr_prims; i++) {
  201.          /* If this fails, it could indicate an application error:
  202.           */
  203.          assert(prim[i].start >= min_index);
  204.  
  205.          tmp_prims[i] = prim[i];
  206.          tmp_prims[i].start -= min_index;
  207.       }
  208.  
  209.       prim = tmp_prims;
  210.    }
  211.  
  212.    /* Just need to adjust the pointer values on each incoming array.
  213.     * This works for VBO and non-vbo rendering and shouldn't pesimize
  214.     * VBO-based upload schemes.  However this may still not be a fast
  215.     * path for hardware tnl for VBO based rendering as most machines
  216.     * will be happier if you just specify a starting vertex value in
  217.     * each primitive.
  218.     *
  219.     * For drivers with hardware tnl, you only want to do this if you
  220.     * are forced to, eg non-VBO indexed rendering with start != 0.
  221.     */
  222.    for (i = 0; i < VERT_ATTRIB_MAX; i++) {
  223.       tmp_arrays[i] = *arrays[i];
  224.       tmp_arrays[i].Ptr += min_index * tmp_arrays[i].StrideB;
  225.       tmp_array_pointers[i] = &tmp_arrays[i];
  226.    }
  227.    
  228.    /* Re-issue the draw call.
  229.     */
  230.    ctx->Array._DrawArrays = tmp_array_pointers;
  231.    ctx->NewDriverState |= ctx->DriverFlags.NewArray;
  232.  
  233.    draw( ctx,
  234.          prim,
  235.          nr_prims,
  236.          ib,
  237.          GL_TRUE,
  238.          0,
  239.          max_index - min_index,
  240.          NULL );
  241.  
  242.    ctx->Array._DrawArrays = saved_arrays;
  243.    ctx->NewDriverState |= ctx->DriverFlags.NewArray;
  244.    
  245.    free(tmp_indices);
  246.    
  247.    free(tmp_prims);
  248. }
  249.  
  250.  
  251.  
  252.