ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

vbo_split_inplace.c
Go to the documentation of this file.
00001 
00002 /*
00003  * Mesa 3-D graphics library
00004  * Version:  6.5
00005  *
00006  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
00007  *
00008  * Permission is hereby granted, free of charge, to any person obtaining a
00009  * copy of this software and associated documentation files (the "Software"),
00010  * to deal in the Software without restriction, including without limitation
00011  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00012  * and/or sell copies of the Software, and to permit persons to whom the
00013  * Software is furnished to do so, subject to the following conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be included
00016  * in all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00021  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00022  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00023  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00024  *
00025  * Authors:
00026  *    Keith Whitwell <keith@tungstengraphics.com>
00027  */
00028 
00029 
00030 #include "main/mtypes.h"
00031 #include "main/macros.h"
00032 #include "main/enums.h"
00033 #include "vbo_split.h"
00034 
00035 
00036 #define MAX_PRIM 32
00037 
00038 /* Used for splitting without copying.
00039  */
00040 struct split_context {
00041    GLcontext *ctx;
00042    const struct gl_client_array **array;
00043    const struct _mesa_prim *prim;
00044    GLuint nr_prims;
00045    const struct _mesa_index_buffer *ib;
00046    GLuint min_index;
00047    GLuint max_index;
00048    vbo_draw_func draw;
00049 
00050    const struct split_limits *limits;
00051 
00052    struct _mesa_prim dstprim[MAX_PRIM];
00053    GLuint dstprim_nr;
00054 };
00055 
00056 
00057 
00058 
00059 static void flush_vertex( struct split_context *split )
00060 {
00061    GLuint min_index, max_index;
00062 
00063    if (!split->dstprim_nr) 
00064       return;
00065 
00066    if (split->ib) {
00067       /* This should basically be multipass rendering over the same
00068        * unchanging set of VBO's.  Would like the driver not to
00069        * re-upload the data, or swtnl not to re-transform the
00070        * vertices.
00071        */
00072       assert(split->max_index - split->min_index < split->limits->max_verts);
00073       min_index = split->min_index;
00074       max_index = split->max_index;
00075    }
00076    else {
00077       /* Non-indexed rendering.  Cannot assume that the primitives are
00078        * ordered by increasing vertex, because of entrypoints like
00079        * MultiDrawArrays.
00080        */
00081       GLuint i;
00082       min_index = split->dstprim[0].start;
00083       max_index = min_index + split->dstprim[0].count - 1;
00084 
00085       for (i = 1; i < split->dstprim_nr; i++) {
00086      GLuint tmp_min = split->dstprim[i].start;
00087      GLuint tmp_max = tmp_min + split->dstprim[i].count - 1;
00088 
00089      if (tmp_min < min_index) 
00090         min_index = tmp_min;
00091 
00092      if (tmp_max > max_index) 
00093         max_index = tmp_max;
00094       }
00095    }
00096 
00097    assert(max_index >= min_index);
00098 
00099    split->draw( split->ctx, 
00100         split->array, 
00101         split->dstprim,
00102         split->dstprim_nr,
00103         NULL,
00104         min_index,
00105         max_index);
00106 
00107    split->dstprim_nr = 0;
00108 }
00109 
00110 
00111 static struct _mesa_prim *next_outprim( struct split_context *split )
00112 {
00113    if (split->dstprim_nr == MAX_PRIM-1) {
00114       flush_vertex(split);
00115    }
00116 
00117    {
00118       struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
00119       memset(prim, 0, sizeof(*prim));
00120       return prim;
00121    }
00122 }
00123 
00124 static int align(int value, int alignment)
00125 {
00126    return (value + alignment - 1) & ~(alignment - 1);
00127 }
00128 
00129 
00130 
00131 /* Break large primitives into smaller ones.  If not possible, convert
00132  * the primitive to indexed and pass to split_elts().
00133  */
00134 static void split_prims( struct split_context *split) 
00135 {
00136    GLuint csr = 0;
00137    GLuint i;
00138 
00139    for (i = 0; i < split->nr_prims; i++) {
00140       const struct _mesa_prim *prim = &split->prim[i];
00141       GLuint first, incr;
00142       GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
00143       GLuint count;
00144 
00145       /* Always wrap on an even numbered vertex to avoid problems with
00146        * triangle strips.  
00147        */
00148       GLuint available = align(split->limits->max_verts - csr - 1, 2); 
00149       assert(split->limits->max_verts >= csr);
00150 
00151       if (prim->count < first)
00152      continue;
00153       
00154       count = prim->count - (prim->count - first) % incr; 
00155 
00156 
00157       if ((available < count && !split_inplace) || 
00158       (available < first && split_inplace)) {
00159      flush_vertex(split);
00160      csr = 0;
00161      available = align(split->limits->max_verts - csr - 1, 2);
00162       }
00163       
00164       if (available >= count) {
00165      struct _mesa_prim *outprim = next_outprim(split);
00166      *outprim = *prim;
00167      csr += prim->count;
00168      available = align(split->limits->max_verts - csr - 1, 2); 
00169       } 
00170       else if (split_inplace) {
00171      GLuint j, nr;
00172 
00173 
00174      for (j = 0 ; j < count ; ) {
00175         GLuint remaining = count - j;
00176         struct _mesa_prim *outprim = next_outprim(split);
00177 
00178         nr = MIN2( available, remaining );
00179         
00180         nr -= (nr - first) % incr;
00181         
00182         outprim->mode = prim->mode;
00183         outprim->begin = (j == 0 && prim->begin);
00184         outprim->end = (nr == remaining && prim->end);
00185         outprim->start = prim->start + j;
00186         outprim->count = nr;
00187         
00188         if (nr == remaining) {
00189            /* Finished. 
00190         */
00191            j += nr;     
00192            csr += nr;
00193            available = align(split->limits->max_verts - csr - 1, 2); 
00194         }
00195         else {
00196            /* Wrapped the primitive: 
00197         */
00198            j += nr - (first - incr);
00199            flush_vertex(split);
00200            csr = 0;
00201            available = align(split->limits->max_verts - csr - 1, 2); 
00202         }
00203      }
00204       }
00205       else if (split->ib == NULL) {
00206      /* XXX: could at least send the first max_verts off from the
00207       * inplace buffers.
00208       */
00209 
00210      /* else convert to indexed primitive and pass to split_elts,
00211       * which will do the necessary copying and turn it back into a
00212       * vertex primitive for rendering...
00213       */
00214      struct _mesa_index_buffer ib;
00215      struct _mesa_prim tmpprim;
00216      GLuint *elts = malloc(count * sizeof(GLuint));
00217      GLuint j;
00218      
00219      for (j = 0; j < count; j++)
00220         elts[j] = prim->start + j;
00221 
00222      ib.count = count;
00223      ib.type = GL_UNSIGNED_INT;
00224      ib.obj = split->ctx->Array.NullBufferObj;
00225      ib.ptr = elts;
00226         
00227      tmpprim = *prim;
00228      tmpprim.indexed = 1;
00229      tmpprim.start = 0;
00230      tmpprim.count = count;
00231 
00232      flush_vertex(split);
00233 
00234      vbo_split_copy(split->ctx,
00235             split->array,
00236             &tmpprim, 1, 
00237             &ib,
00238             split->draw,
00239             split->limits);
00240         
00241      free(elts);
00242       }
00243       else {
00244      flush_vertex(split);
00245 
00246      vbo_split_copy(split->ctx,
00247             split->array,
00248             prim, 1, 
00249             split->ib,
00250             split->draw,
00251             split->limits);
00252       }
00253    }
00254 
00255    flush_vertex(split);
00256 }
00257 
00258 
00259 void vbo_split_inplace( GLcontext *ctx,
00260             const struct gl_client_array *arrays[],
00261             const struct _mesa_prim *prim,
00262             GLuint nr_prims,
00263             const struct _mesa_index_buffer *ib,
00264             GLuint min_index,
00265             GLuint max_index,
00266             vbo_draw_func draw,
00267             const struct split_limits *limits )
00268 {
00269    struct split_context split;
00270 
00271    memset(&split, 0, sizeof(split));
00272 
00273    split.ctx = ctx;
00274    split.array = arrays;
00275    split.prim = prim;
00276    split.nr_prims = nr_prims;
00277    split.ib = ib;
00278    split.min_index = min_index;
00279    split.max_index = max_index;
00280    split.draw = draw;
00281    split.limits = limits;
00282 
00283    split_prims( &split );
00284 }
00285 
00286 

Generated on Sat May 26 2012 04:19:38 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.