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

t_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 doxygen 1.7.6.1

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