Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygent_draw.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.1 00004 * 00005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 * 00024 * Authors: 00025 * Keith Whitwell <keith@tungstengraphics.com> 00026 */ 00027 00028 #include "main/glheader.h" 00029 #include "main/context.h" 00030 #include "main/imports.h" 00031 #include "main/state.h" 00032 #include "main/mtypes.h" 00033 #include "main/macros.h" 00034 #include "main/enums.h" 00035 00036 #include "t_context.h" 00037 #include "t_pipeline.h" 00038 #include "t_vp_build.h" 00039 #include "t_vertex.h" 00040 #include "tnl.h" 00041 00042 00043 00044 static GLubyte *get_space(GLcontext *ctx, GLuint bytes) 00045 { 00046 TNLcontext *tnl = TNL_CONTEXT(ctx); 00047 GLubyte *space = _mesa_malloc(bytes); 00048 00049 tnl->block[tnl->nr_blocks++] = space; 00050 return space; 00051 } 00052 00053 00054 static void free_space(GLcontext *ctx) 00055 { 00056 TNLcontext *tnl = TNL_CONTEXT(ctx); 00057 GLuint i; 00058 for (i = 0; i < tnl->nr_blocks; i++) 00059 _mesa_free(tnl->block[i]); 00060 tnl->nr_blocks = 0; 00061 } 00062 00063 00064 /* Convert the incoming array to GLfloats. Understands the 00065 * array->Normalized flag and selects the correct conversion method. 00066 */ 00067 #define CONVERT( TYPE, MACRO ) do { \ 00068 GLuint i, j; \ 00069 if (input->Normalized) { \ 00070 for (i = 0; i < count; i++) { \ 00071 const TYPE *in = (TYPE *)ptr; \ 00072 for (j = 0; j < sz; j++) { \ 00073 *fptr++ = MACRO(*in); \ 00074 in++; \ 00075 } \ 00076 ptr += input->StrideB; \ 00077 } \ 00078 } else { \ 00079 for (i = 0; i < count; i++) { \ 00080 const TYPE *in = (TYPE *)ptr; \ 00081 for (j = 0; j < sz; j++) { \ 00082 *fptr++ = (GLfloat)(*in); \ 00083 in++; \ 00084 } \ 00085 ptr += input->StrideB; \ 00086 } \ 00087 } \ 00088 } while (0) 00089 00090 00091 00092 /* Adjust pointer to point at first requested element, convert to 00093 * floating point, populate VB->AttribPtr[]. 00094 */ 00095 static void _tnl_import_array( GLcontext *ctx, 00096 GLuint attrib, 00097 GLuint count, 00098 const struct gl_client_array *input, 00099 const GLubyte *ptr ) 00100 { 00101 TNLcontext *tnl = TNL_CONTEXT(ctx); 00102 struct vertex_buffer *VB = &tnl->vb; 00103 GLuint stride = input->StrideB; 00104 00105 if (input->Type != GL_FLOAT) { 00106 const GLuint sz = input->Size; 00107 GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat)); 00108 GLfloat *fptr = (GLfloat *)buf; 00109 00110 switch (input->Type) { 00111 case GL_BYTE: 00112 CONVERT(GLbyte, BYTE_TO_FLOAT); 00113 break; 00114 case GL_UNSIGNED_BYTE: 00115 CONVERT(GLubyte, UBYTE_TO_FLOAT); 00116 break; 00117 case GL_SHORT: 00118 CONVERT(GLshort, SHORT_TO_FLOAT); 00119 break; 00120 case GL_UNSIGNED_SHORT: 00121 CONVERT(GLushort, USHORT_TO_FLOAT); 00122 break; 00123 case GL_INT: 00124 CONVERT(GLint, INT_TO_FLOAT); 00125 break; 00126 case GL_UNSIGNED_INT: 00127 CONVERT(GLuint, UINT_TO_FLOAT); 00128 break; 00129 case GL_DOUBLE: 00130 CONVERT(GLdouble, (GLfloat)); 00131 break; 00132 default: 00133 assert(0); 00134 break; 00135 } 00136 00137 ptr = buf; 00138 stride = sz * sizeof(GLfloat); 00139 } 00140 00141 VB->AttribPtr[attrib] = &tnl->tmp_inputs[attrib]; 00142 VB->AttribPtr[attrib]->data = (GLfloat (*)[4])ptr; 00143 VB->AttribPtr[attrib]->start = (GLfloat *)ptr; 00144 VB->AttribPtr[attrib]->count = count; 00145 VB->AttribPtr[attrib]->stride = stride; 00146 VB->AttribPtr[attrib]->size = input->Size; 00147 00148 /* This should die, but so should the whole GLvector4f concept: 00149 */ 00150 VB->AttribPtr[attrib]->flags = (((1<<input->Size)-1) | 00151 VEC_NOT_WRITEABLE | 00152 (stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE)); 00153 00154 VB->AttribPtr[attrib]->storage = NULL; 00155 } 00156 00157 #define CLIPVERTS ((6 + MAX_CLIP_PLANES) * 2) 00158 00159 00160 static GLboolean *_tnl_import_edgeflag( GLcontext *ctx, 00161 const GLvector4f *input, 00162 GLuint count) 00163 { 00164 const GLubyte *ptr = (const GLubyte *)input->data; 00165 const GLuint stride = input->stride; 00166 GLboolean *space = (GLboolean *)get_space(ctx, count + CLIPVERTS); 00167 GLboolean *bptr = space; 00168 GLuint i; 00169 00170 for (i = 0; i < count; i++) { 00171 *bptr++ = ((GLfloat *)ptr)[0] == 1.0; 00172 ptr += stride; 00173 } 00174 00175 return space; 00176 } 00177 00178 00179 static void bind_inputs( GLcontext *ctx, 00180 const struct gl_client_array *inputs[], 00181 GLint count, 00182 struct gl_buffer_object **bo, 00183 GLuint *nr_bo ) 00184 { 00185 TNLcontext *tnl = TNL_CONTEXT(ctx); 00186 struct vertex_buffer *VB = &tnl->vb; 00187 GLuint i; 00188 00189 /* Map all the VBOs 00190 */ 00191 for (i = 0; i < VERT_ATTRIB_MAX; i++) { 00192 const void *ptr; 00193 00194 if (inputs[i]->BufferObj->Name) { 00195 if (!inputs[i]->BufferObj->Pointer) { 00196 bo[*nr_bo] = inputs[i]->BufferObj; 00197 (*nr_bo)++; 00198 ctx->Driver.MapBuffer(ctx, 00199 GL_ARRAY_BUFFER, 00200 GL_READ_ONLY_ARB, 00201 inputs[i]->BufferObj); 00202 00203 assert(inputs[i]->BufferObj->Pointer); 00204 } 00205 00206 ptr = ADD_POINTERS(inputs[i]->BufferObj->Pointer, 00207 inputs[i]->Ptr); 00208 } 00209 else 00210 ptr = inputs[i]->Ptr; 00211 00212 /* Just make sure the array is floating point, otherwise convert to 00213 * temporary storage. 00214 * 00215 * XXX: remove the GLvector4f type at some stage and just use 00216 * client arrays. 00217 */ 00218 _tnl_import_array(ctx, i, count, inputs[i], ptr); 00219 } 00220 00221 /* We process only the vertices between min & max index: 00222 */ 00223 VB->Count = count; 00224 00225 00226 /* Legacy pointers -- remove one day. 00227 */ 00228 VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS]; 00229 VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; 00230 VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0]; 00231 VB->ColorPtr[1] = NULL; 00232 VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR_INDEX]; 00233 VB->IndexPtr[1] = NULL; 00234 VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1]; 00235 VB->SecondaryColorPtr[1] = NULL; 00236 VB->FogCoordPtr = VB->AttribPtr[_TNL_ATTRIB_FOG]; 00237 00238 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { 00239 VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]; 00240 } 00241 00242 /* Clipping and drawing code still requires this to be a packed 00243 * array of ubytes which can be written into. TODO: Fix and 00244 * remove. 00245 */ 00246 if (ctx->Polygon.FrontMode != GL_FILL || 00247 ctx->Polygon.BackMode != GL_FILL) 00248 { 00249 VB->EdgeFlag = _tnl_import_edgeflag( ctx, 00250 VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG], 00251 VB->Count ); 00252 } 00253 else { 00254 /* the data previously pointed to by EdgeFlag may have been freed */ 00255 VB->EdgeFlag = NULL; 00256 } 00257 } 00258 00259 00260 /* Translate indices to GLuints and store in VB->Elts. 00261 */ 00262 static void bind_indices( GLcontext *ctx, 00263 const struct _mesa_index_buffer *ib, 00264 struct gl_buffer_object **bo, 00265 GLuint *nr_bo) 00266 { 00267 TNLcontext *tnl = TNL_CONTEXT(ctx); 00268 struct vertex_buffer *VB = &tnl->vb; 00269 GLuint i; 00270 void *ptr; 00271 00272 if (!ib) { 00273 VB->Elts = NULL; 00274 return; 00275 } 00276 00277 if (ib->obj->Name && !ib->obj->Pointer) { 00278 bo[*nr_bo] = ib->obj; 00279 (*nr_bo)++; 00280 ctx->Driver.MapBuffer(ctx, 00281 GL_ELEMENT_ARRAY_BUFFER, 00282 GL_READ_ONLY_ARB, 00283 ib->obj); 00284 00285 assert(ib->obj->Pointer); 00286 } 00287 00288 ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); 00289 00290 if (ib->type == GL_UNSIGNED_INT) { 00291 VB->Elts = (GLuint *) ptr; 00292 } 00293 else { 00294 GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint)); 00295 VB->Elts = elts; 00296 00297 if (ib->type == GL_UNSIGNED_SHORT) { 00298 const GLushort *in = (GLushort *)ptr; 00299 for (i = 0; i < ib->count; i++) 00300 *elts++ = (GLuint)(*in++); 00301 } 00302 else { 00303 const GLubyte *in = (GLubyte *)ptr; 00304 for (i = 0; i < ib->count; i++) 00305 *elts++ = (GLuint)(*in++); 00306 } 00307 } 00308 } 00309 00310 static void bind_prims( GLcontext *ctx, 00311 const struct _mesa_prim *prim, 00312 GLuint nr_prims ) 00313 { 00314 TNLcontext *tnl = TNL_CONTEXT(ctx); 00315 struct vertex_buffer *VB = &tnl->vb; 00316 00317 VB->Primitive = prim; 00318 VB->PrimitiveCount = nr_prims; 00319 } 00320 00321 static void unmap_vbos( GLcontext *ctx, 00322 struct gl_buffer_object **bo, 00323 GLuint nr_bo ) 00324 { 00325 GLuint i; 00326 for (i = 0; i < nr_bo; i++) { 00327 ctx->Driver.UnmapBuffer(ctx, 00328 0, /* target -- I don't see why this would be needed */ 00329 bo[i]); 00330 } 00331 } 00332 00333 00334 00335 /* This is the main entrypoint into the slimmed-down software tnl 00336 * module. In a regular swtnl driver, this can be plugged straight 00337 * into the vbo->Driver.DrawPrims() callback. 00338 */ 00339 void _tnl_draw_prims( GLcontext *ctx, 00340 const struct gl_client_array *arrays[], 00341 const struct _mesa_prim *prim, 00342 GLuint nr_prims, 00343 const struct _mesa_index_buffer *ib, 00344 GLuint min_index, 00345 GLuint max_index) 00346 { 00347 TNLcontext *tnl = TNL_CONTEXT(ctx); 00348 const GLuint TEST_SPLIT = 0; 00349 const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES; 00350 00351 if (0) 00352 { 00353 GLuint i; 00354 _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); 00355 for (i = 0; i < nr_prims; i++) 00356 _mesa_printf("prim %d: %s start %d count %d\n", i, 00357 _mesa_lookup_enum_by_nr(prim[i].mode), 00358 prim[i].start, 00359 prim[i].count); 00360 } 00361 00362 if (min_index) { 00363 /* We always translate away calls with min_index != 0. 00364 */ 00365 vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, 00366 min_index, max_index, 00367 _tnl_draw_prims ); 00368 return; 00369 } 00370 else if (max_index > max) { 00371 /* The software TNL pipeline has a fixed amount of storage for 00372 * vertices and it is necessary to split incoming drawing commands 00373 * if they exceed that limit. 00374 */ 00375 struct split_limits limits; 00376 limits.max_verts = max; 00377 limits.max_vb_size = ~0; 00378 limits.max_indices = ~0; 00379 00380 /* This will split the buffers one way or another and 00381 * recursively call back into this function. 00382 */ 00383 vbo_split_prims( ctx, arrays, prim, nr_prims, ib, 00384 0, max_index, 00385 _tnl_draw_prims, 00386 &limits ); 00387 } 00388 else { 00389 /* May need to map a vertex buffer object for every attribute plus 00390 * one for the index buffer. 00391 */ 00392 struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1]; 00393 GLuint nr_bo = 0; 00394 00395 /* Binding inputs may imply mapping some vertex buffer objects. 00396 * They will need to be unmapped below. 00397 */ 00398 bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo); 00399 bind_indices(ctx, ib, bo, &nr_bo); 00400 bind_prims(ctx, prim, nr_prims ); 00401 00402 TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); 00403 00404 unmap_vbos(ctx, bo, nr_bo); 00405 free_space(ctx); 00406 } 00407 } 00408 Generated on Sat May 26 2012 04:19:35 for ReactOS by
1.7.6.1
|