Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvbo_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
1.7.6.1
|