Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygent_vertex.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2003 Tungsten Graphics, inc. 00003 * All Rights Reserved. 00004 * 00005 * Permission is hereby granted, free of charge, to any person obtaining a 00006 * copy of this software and associated documentation files (the "Software"), 00007 * to deal in the Software without restriction, including without limitation 00008 * on the rights to use, copy, modify, merge, publish, distribute, sub 00009 * license, and/or sell copies of the Software, and to permit persons to whom 00010 * the Software is furnished to do so, subject to the following conditions: 00011 * 00012 * The above copyright notice and this permission notice (including the next 00013 * paragraph) shall be included in all copies or substantial portions of the 00014 * Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 00019 * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 00020 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 00021 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 00022 * USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 * 00024 * Authors: 00025 * Keith Whitwell <keithw@tungstengraphics.com> 00026 */ 00027 00028 #include "main/glheader.h" 00029 #include "main/context.h" 00030 #include "main/colormac.h" 00031 00032 #include "t_context.h" 00033 #include "t_vertex.h" 00034 00035 #define DBG 0 00036 00037 /* Build and manage clipspace/ndc/window vertices. 00038 */ 00039 00040 static GLboolean match_fastpath( struct tnl_clipspace *vtx, 00041 const struct tnl_clipspace_fastpath *fp) 00042 { 00043 GLuint j; 00044 00045 if (vtx->attr_count != fp->attr_count) 00046 return GL_FALSE; 00047 00048 for (j = 0; j < vtx->attr_count; j++) 00049 if (vtx->attr[j].format != fp->attr[j].format || 00050 vtx->attr[j].inputsize != fp->attr[j].size || 00051 vtx->attr[j].vertoffset != fp->attr[j].offset) 00052 return GL_FALSE; 00053 00054 if (fp->match_strides) { 00055 if (vtx->vertex_size != fp->vertex_size) 00056 return GL_FALSE; 00057 00058 for (j = 0; j < vtx->attr_count; j++) 00059 if (vtx->attr[j].inputstride != fp->attr[j].stride) 00060 return GL_FALSE; 00061 } 00062 00063 return GL_TRUE; 00064 } 00065 00066 static GLboolean search_fastpath_emit( struct tnl_clipspace *vtx ) 00067 { 00068 struct tnl_clipspace_fastpath *fp = vtx->fastpath; 00069 00070 for ( ; fp ; fp = fp->next) { 00071 if (match_fastpath(vtx, fp)) { 00072 vtx->emit = fp->func; 00073 return GL_TRUE; 00074 } 00075 } 00076 00077 return GL_FALSE; 00078 } 00079 00080 void _tnl_register_fastpath( struct tnl_clipspace *vtx, 00081 GLboolean match_strides ) 00082 { 00083 struct tnl_clipspace_fastpath *fastpath = CALLOC_STRUCT(tnl_clipspace_fastpath); 00084 GLuint i; 00085 00086 fastpath->vertex_size = vtx->vertex_size; 00087 fastpath->attr_count = vtx->attr_count; 00088 fastpath->match_strides = match_strides; 00089 fastpath->func = vtx->emit; 00090 fastpath->attr = (struct tnl_attr_type *) 00091 _mesa_malloc(vtx->attr_count * sizeof(fastpath->attr[0])); 00092 00093 for (i = 0; i < vtx->attr_count; i++) { 00094 fastpath->attr[i].format = vtx->attr[i].format; 00095 fastpath->attr[i].stride = vtx->attr[i].inputstride; 00096 fastpath->attr[i].size = vtx->attr[i].inputsize; 00097 fastpath->attr[i].offset = vtx->attr[i].vertoffset; 00098 } 00099 00100 fastpath->next = vtx->fastpath; 00101 vtx->fastpath = fastpath; 00102 } 00103 00104 00105 00106 /*********************************************************************** 00107 * Build codegen functions or return generic ones: 00108 */ 00109 static void choose_emit_func( GLcontext *ctx, GLuint count, GLubyte *dest) 00110 { 00111 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 00112 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00113 struct tnl_clipspace_attr *a = vtx->attr; 00114 const GLuint attr_count = vtx->attr_count; 00115 GLuint j; 00116 00117 for (j = 0; j < attr_count; j++) { 00118 GLvector4f *vptr = VB->AttribPtr[a[j].attrib]; 00119 a[j].inputstride = vptr->stride; 00120 a[j].inputsize = vptr->size; 00121 a[j].emit = a[j].insert[vptr->size - 1]; /* not always used */ 00122 } 00123 00124 vtx->emit = NULL; 00125 00126 /* Does this match an existing (hardwired, codegen or known-bad) 00127 * fastpath? 00128 */ 00129 if (search_fastpath_emit(vtx)) { 00130 /* Use this result. If it is null, then it is already known 00131 * that the current state will fail for codegen and there is no 00132 * point trying again. 00133 */ 00134 } 00135 else if (vtx->codegen_emit) { 00136 vtx->codegen_emit(ctx); 00137 } 00138 00139 if (!vtx->emit) { 00140 _tnl_generate_hardwired_emit(ctx); 00141 } 00142 00143 /* Otherwise use the generic version: 00144 */ 00145 if (!vtx->emit) 00146 vtx->emit = _tnl_generic_emit; 00147 00148 vtx->emit( ctx, count, dest ); 00149 } 00150 00151 00152 00153 static void choose_interp_func( GLcontext *ctx, 00154 GLfloat t, 00155 GLuint edst, GLuint eout, GLuint ein, 00156 GLboolean force_boundary ) 00157 { 00158 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00159 00160 if (vtx->need_extras && 00161 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { 00162 vtx->interp = _tnl_generic_interp_extras; 00163 } else { 00164 vtx->interp = _tnl_generic_interp; 00165 } 00166 00167 vtx->interp( ctx, t, edst, eout, ein, force_boundary ); 00168 } 00169 00170 00171 static void choose_copy_pv_func( GLcontext *ctx, GLuint edst, GLuint esrc ) 00172 { 00173 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00174 00175 if (vtx->need_extras && 00176 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { 00177 vtx->copy_pv = _tnl_generic_copy_pv_extras; 00178 } else { 00179 vtx->copy_pv = _tnl_generic_copy_pv; 00180 } 00181 00182 vtx->copy_pv( ctx, edst, esrc ); 00183 } 00184 00185 00186 /*********************************************************************** 00187 * Public entrypoints, mostly dispatch to the above: 00188 */ 00189 00190 00191 /* Interpolate between two vertices to produce a third: 00192 */ 00193 void _tnl_interp( GLcontext *ctx, 00194 GLfloat t, 00195 GLuint edst, GLuint eout, GLuint ein, 00196 GLboolean force_boundary ) 00197 { 00198 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00199 vtx->interp( ctx, t, edst, eout, ein, force_boundary ); 00200 } 00201 00202 /* Copy colors from one vertex to another: 00203 */ 00204 void _tnl_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc ) 00205 { 00206 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00207 vtx->copy_pv( ctx, edst, esrc ); 00208 } 00209 00210 00211 /* Extract a named attribute from a hardware vertex. Will have to 00212 * reverse any viewport transformation, swizzling or other conversions 00213 * which may have been applied: 00214 */ 00215 void _tnl_get_attr( GLcontext *ctx, const void *vin, 00216 GLenum attr, GLfloat *dest ) 00217 { 00218 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00219 const struct tnl_clipspace_attr *a = vtx->attr; 00220 const GLuint attr_count = vtx->attr_count; 00221 GLuint j; 00222 00223 for (j = 0; j < attr_count; j++) { 00224 if (a[j].attrib == attr) { 00225 a[j].extract( &a[j], dest, (GLubyte *)vin + a[j].vertoffset ); 00226 return; 00227 } 00228 } 00229 00230 /* Else return the value from ctx->Current. 00231 */ 00232 if (attr == _TNL_ATTRIB_POINTSIZE) { 00233 /* If the hardware vertex doesn't have point size then use size from 00234 * GLcontext. XXX this will be wrong if drawing attenuated points! 00235 */ 00236 dest[0] = ctx->Point.Size; 00237 } 00238 else { 00239 _mesa_memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat)); 00240 } 00241 } 00242 00243 00244 /* Complementary operation to the above. 00245 */ 00246 void _tnl_set_attr( GLcontext *ctx, void *vout, 00247 GLenum attr, const GLfloat *src ) 00248 { 00249 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00250 const struct tnl_clipspace_attr *a = vtx->attr; 00251 const GLuint attr_count = vtx->attr_count; 00252 GLuint j; 00253 00254 for (j = 0; j < attr_count; j++) { 00255 if (a[j].attrib == attr) { 00256 a[j].insert[4-1]( &a[j], (GLubyte *)vout + a[j].vertoffset, src ); 00257 return; 00258 } 00259 } 00260 } 00261 00262 00263 void *_tnl_get_vertex( GLcontext *ctx, GLuint nr ) 00264 { 00265 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00266 00267 return vtx->vertex_buf + nr * vtx->vertex_size; 00268 } 00269 00270 void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state ) 00271 { 00272 if (new_state & (_DD_NEW_TRI_LIGHT_TWOSIDE|_DD_NEW_TRI_UNFILLED) ) { 00273 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00274 vtx->new_inputs = ~0; 00275 vtx->interp = choose_interp_func; 00276 vtx->copy_pv = choose_copy_pv_func; 00277 } 00278 } 00279 00280 static void invalidate_funcs( struct tnl_clipspace *vtx ) 00281 { 00282 vtx->emit = choose_emit_func; 00283 vtx->interp = choose_interp_func; 00284 vtx->copy_pv = choose_copy_pv_func; 00285 vtx->new_inputs = ~0; 00286 } 00287 00288 GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map, 00289 GLuint nr, const GLfloat *vp, 00290 GLuint unpacked_size ) 00291 { 00292 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00293 GLuint offset = 0; 00294 GLuint i, j; 00295 00296 assert(nr < _TNL_ATTRIB_MAX); 00297 assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS); 00298 00299 vtx->new_inputs = ~0; 00300 vtx->need_viewport = GL_FALSE; 00301 00302 if (vp) { 00303 vtx->need_viewport = GL_TRUE; 00304 } 00305 00306 for (j = 0, i = 0; i < nr; i++) { 00307 const GLuint format = map[i].format; 00308 if (format == EMIT_PAD) { 00309 if (DBG) 00310 _mesa_printf("%d: pad %d, offset %d\n", i, 00311 map[i].offset, offset); 00312 00313 offset += map[i].offset; 00314 00315 } 00316 else { 00317 GLuint tmpoffset; 00318 00319 if (unpacked_size) 00320 tmpoffset = map[i].offset; 00321 else 00322 tmpoffset = offset; 00323 00324 if (vtx->attr_count != j || 00325 vtx->attr[j].attrib != map[i].attrib || 00326 vtx->attr[j].format != format || 00327 vtx->attr[j].vertoffset != tmpoffset) { 00328 invalidate_funcs(vtx); 00329 00330 vtx->attr[j].attrib = map[i].attrib; 00331 vtx->attr[j].format = format; 00332 vtx->attr[j].vp = vp; 00333 vtx->attr[j].insert = _tnl_format_info[format].insert; 00334 vtx->attr[j].extract = _tnl_format_info[format].extract; 00335 vtx->attr[j].vertattrsize = _tnl_format_info[format].attrsize; 00336 vtx->attr[j].vertoffset = tmpoffset; 00337 } 00338 00339 00340 if (DBG) 00341 _mesa_printf("%d: %s, vp %p, offset %d\n", i, 00342 _tnl_format_info[format].name, (void *)vp, 00343 vtx->attr[j].vertoffset); 00344 00345 offset += _tnl_format_info[format].attrsize; 00346 j++; 00347 } 00348 } 00349 00350 vtx->attr_count = j; 00351 00352 if (unpacked_size) 00353 vtx->vertex_size = unpacked_size; 00354 else 00355 vtx->vertex_size = offset; 00356 00357 assert(vtx->vertex_size <= vtx->max_vertex_size); 00358 return vtx->vertex_size; 00359 } 00360 00361 00362 00363 void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs ) 00364 { 00365 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00366 vtx->new_inputs |= newinputs; 00367 } 00368 00369 00370 /* This event has broader use beyond this file - will move elsewhere 00371 * and probably invoke a driver callback. 00372 */ 00373 void _tnl_notify_pipeline_output_change( GLcontext *ctx ) 00374 { 00375 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00376 invalidate_funcs(vtx); 00377 } 00378 00379 00380 static void adjust_input_ptrs( GLcontext *ctx, GLint diff) 00381 { 00382 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 00383 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00384 struct tnl_clipspace_attr *a = vtx->attr; 00385 const GLuint count = vtx->attr_count; 00386 int j; 00387 00388 diff -= 1; 00389 for (j=0; j<count; ++j) { 00390 register GLvector4f *vptr = VB->AttribPtr[a->attrib]; 00391 (a++)->inputptr += diff*vptr->stride; 00392 } 00393 } 00394 00395 static void update_input_ptrs( GLcontext *ctx, GLuint start ) 00396 { 00397 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 00398 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00399 struct tnl_clipspace_attr *a = vtx->attr; 00400 const GLuint count = vtx->attr_count; 00401 GLuint j; 00402 00403 for (j = 0; j < count; j++) { 00404 GLvector4f *vptr = VB->AttribPtr[a[j].attrib]; 00405 00406 if (vtx->emit != choose_emit_func) { 00407 assert(a[j].inputstride == vptr->stride); 00408 assert(a[j].inputsize == vptr->size); 00409 } 00410 00411 a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride; 00412 } 00413 00414 if (a->vp) { 00415 vtx->vp_scale[0] = a->vp[MAT_SX]; 00416 vtx->vp_scale[1] = a->vp[MAT_SY]; 00417 vtx->vp_scale[2] = a->vp[MAT_SZ]; 00418 vtx->vp_scale[3] = 1.0; 00419 vtx->vp_xlate[0] = a->vp[MAT_TX]; 00420 vtx->vp_xlate[1] = a->vp[MAT_TY]; 00421 vtx->vp_xlate[2] = a->vp[MAT_TZ]; 00422 vtx->vp_xlate[3] = 0.0; 00423 } 00424 } 00425 00426 00427 void _tnl_build_vertices( GLcontext *ctx, 00428 GLuint start, 00429 GLuint end, 00430 GLuint newinputs ) 00431 { 00432 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00433 update_input_ptrs( ctx, start ); 00434 vtx->emit( ctx, end - start, 00435 (GLubyte *)(vtx->vertex_buf + 00436 start * vtx->vertex_size)); 00437 } 00438 00439 /* Emit VB vertices start..end to dest. Note that VB vertex at 00440 * postion start will be emitted to dest at position zero. 00441 */ 00442 void *_tnl_emit_vertices_to_buffer( GLcontext *ctx, 00443 GLuint start, 00444 GLuint end, 00445 void *dest ) 00446 { 00447 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00448 00449 update_input_ptrs(ctx, start); 00450 /* Note: dest should not be adjusted for non-zero 'start' values: 00451 */ 00452 vtx->emit( ctx, end - start, (GLubyte*) dest ); 00453 return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start)); 00454 } 00455 00456 /* Emit indexed VB vertices start..end to dest. Note that VB vertex at 00457 * postion start will be emitted to dest at position zero. 00458 */ 00459 00460 void *_tnl_emit_indexed_vertices_to_buffer( GLcontext *ctx, 00461 const GLuint *elts, 00462 GLuint start, 00463 GLuint end, 00464 void *dest ) 00465 { 00466 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00467 GLuint oldIndex; 00468 GLubyte *cdest = dest; 00469 00470 update_input_ptrs(ctx, oldIndex = elts[start++]); 00471 vtx->emit( ctx, 1, cdest ); 00472 cdest += vtx->vertex_size; 00473 00474 for (; start < end; ++start) { 00475 adjust_input_ptrs(ctx, elts[start] - oldIndex); 00476 oldIndex = elts[start]; 00477 vtx->emit( ctx, 1, cdest); 00478 cdest += vtx->vertex_size; 00479 } 00480 00481 return (void *) cdest; 00482 } 00483 00484 00485 void _tnl_init_vertices( GLcontext *ctx, 00486 GLuint vb_size, 00487 GLuint max_vertex_size ) 00488 { 00489 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00490 00491 _tnl_install_attrs( ctx, NULL, 0, NULL, 0 ); 00492 00493 vtx->need_extras = GL_TRUE; 00494 if (max_vertex_size > vtx->max_vertex_size) { 00495 _tnl_free_vertices( ctx ); 00496 vtx->max_vertex_size = max_vertex_size; 00497 vtx->vertex_buf = (GLubyte *)ALIGN_CALLOC(vb_size * max_vertex_size, 32 ); 00498 invalidate_funcs(vtx); 00499 } 00500 00501 switch(CHAN_TYPE) { 00502 case GL_UNSIGNED_BYTE: 00503 vtx->chan_scale[0] = 255.0; 00504 vtx->chan_scale[1] = 255.0; 00505 vtx->chan_scale[2] = 255.0; 00506 vtx->chan_scale[3] = 255.0; 00507 break; 00508 case GL_UNSIGNED_SHORT: 00509 vtx->chan_scale[0] = 65535.0; 00510 vtx->chan_scale[1] = 65535.0; 00511 vtx->chan_scale[2] = 65535.0; 00512 vtx->chan_scale[3] = 65535.0; 00513 break; 00514 default: 00515 vtx->chan_scale[0] = 1.0; 00516 vtx->chan_scale[1] = 1.0; 00517 vtx->chan_scale[2] = 1.0; 00518 vtx->chan_scale[3] = 1.0; 00519 break; 00520 } 00521 00522 vtx->identity[0] = 0.0; 00523 vtx->identity[1] = 0.0; 00524 vtx->identity[2] = 0.0; 00525 vtx->identity[3] = 1.0; 00526 00527 vtx->codegen_emit = NULL; 00528 00529 #ifdef USE_SSE_ASM 00530 if (!_mesa_getenv("MESA_NO_CODEGEN")) 00531 vtx->codegen_emit = _tnl_generate_sse_emit; 00532 #endif 00533 } 00534 00535 00536 void _tnl_free_vertices( GLcontext *ctx ) 00537 { 00538 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); 00539 struct tnl_clipspace_fastpath *fp, *tmp; 00540 00541 if (vtx->vertex_buf) { 00542 ALIGN_FREE(vtx->vertex_buf); 00543 vtx->vertex_buf = NULL; 00544 } 00545 00546 for (fp = vtx->fastpath ; fp ; fp = tmp) { 00547 tmp = fp->next; 00548 FREE(fp->attr); 00549 00550 /* KW: At the moment, fp->func is constrained to be allocated by 00551 * _mesa_exec_alloc(), as the hardwired fastpaths in 00552 * t_vertex_generic.c are handled specially. It would be nice 00553 * to unify them, but this probably won't change until this 00554 * module gets another overhaul. 00555 */ 00556 _mesa_exec_free((void *) fp->func); 00557 FREE(fp); 00558 } 00559 00560 vtx->fastpath = NULL; 00561 } Generated on Sat May 26 2012 04:19:36 for ReactOS by
1.7.6.1
|