Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2003 Tungsten Graphics, inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  9.  * license, and/or sell copies of the Software, and to permit persons to whom
  10.  * the Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
  19.  * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  20.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  21.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  22.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Keith Whitwell <keithw@tungstengraphics.com>
  26.  */
  27.  
  28. #include "main/glheader.h"
  29. #include "main/context.h"
  30. #include "main/colormac.h"
  31. #include "swrast/s_chan.h"
  32. #include "t_context.h"
  33. #include "t_vertex.h"
  34.  
  35. #define DBG 0
  36.  
  37. /* Build and manage clipspace/ndc/window vertices.
  38.  */
  39.  
  40. static GLboolean match_fastpath( struct tnl_clipspace *vtx,
  41.                                  const struct tnl_clipspace_fastpath *fp)
  42. {
  43.    GLuint j;
  44.  
  45.    if (vtx->attr_count != fp->attr_count)
  46.       return GL_FALSE;
  47.  
  48.    for (j = 0; j < vtx->attr_count; j++)
  49.       if (vtx->attr[j].format != fp->attr[j].format ||
  50.           vtx->attr[j].inputsize != fp->attr[j].size ||
  51.           vtx->attr[j].vertoffset != fp->attr[j].offset)
  52.          return GL_FALSE;
  53.      
  54.    if (fp->match_strides) {
  55.       if (vtx->vertex_size != fp->vertex_size)
  56.          return GL_FALSE;
  57.  
  58.       for (j = 0; j < vtx->attr_count; j++)
  59.          if (vtx->attr[j].inputstride != fp->attr[j].stride)
  60.             return GL_FALSE;
  61.    }
  62.    
  63.    return GL_TRUE;
  64. }
  65.  
  66. static GLboolean search_fastpath_emit( struct tnl_clipspace *vtx )
  67. {
  68.    struct tnl_clipspace_fastpath *fp = vtx->fastpath;
  69.  
  70.    for ( ; fp ; fp = fp->next) {
  71.       if (match_fastpath(vtx, fp)) {
  72.          vtx->emit = fp->func;
  73.          return GL_TRUE;
  74.       }
  75.    }
  76.  
  77.    return GL_FALSE;
  78. }
  79.  
  80. void _tnl_register_fastpath( struct tnl_clipspace *vtx,
  81.                              GLboolean match_strides )
  82. {
  83.    struct tnl_clipspace_fastpath *fastpath = CALLOC_STRUCT(tnl_clipspace_fastpath);
  84.    GLuint i;
  85.  
  86.    fastpath->vertex_size = vtx->vertex_size;
  87.    fastpath->attr_count = vtx->attr_count;
  88.    fastpath->match_strides = match_strides;
  89.    fastpath->func = vtx->emit;
  90.    fastpath->attr =
  91.       malloc(vtx->attr_count * sizeof(fastpath->attr[0]));
  92.  
  93.    for (i = 0; i < vtx->attr_count; i++) {
  94.       fastpath->attr[i].format = vtx->attr[i].format;
  95.       fastpath->attr[i].stride = vtx->attr[i].inputstride;
  96.       fastpath->attr[i].size = vtx->attr[i].inputsize;
  97.       fastpath->attr[i].offset = vtx->attr[i].vertoffset;
  98.    }
  99.  
  100.    fastpath->next = vtx->fastpath;
  101.    vtx->fastpath = fastpath;
  102. }
  103.  
  104.  
  105.  
  106. /***********************************************************************
  107.  * Build codegen functions or return generic ones:
  108.  */
  109. static void choose_emit_func( struct gl_context *ctx, GLuint count, GLubyte *dest)
  110. {
  111.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  112.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  113.    struct tnl_clipspace_attr *a = vtx->attr;
  114.    const GLuint attr_count = vtx->attr_count;
  115.    GLuint j;
  116.  
  117.    for (j = 0; j < attr_count; j++) {
  118.       GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
  119.       a[j].inputstride = vptr->stride;
  120.       a[j].inputsize = vptr->size;
  121.       a[j].emit = a[j].insert[vptr->size - 1]; /* not always used */
  122.    }
  123.  
  124.    vtx->emit = NULL;
  125.    
  126.    /* Does this match an existing (hardwired, codegen or known-bad)
  127.     * fastpath?
  128.     */
  129.    if (search_fastpath_emit(vtx)) {
  130.       /* Use this result.  If it is null, then it is already known
  131.        * that the current state will fail for codegen and there is no
  132.        * point trying again.
  133.        */
  134.    }
  135.    else if (vtx->codegen_emit) {
  136.       vtx->codegen_emit(ctx);
  137.    }
  138.  
  139.    if (!vtx->emit) {
  140.       _tnl_generate_hardwired_emit(ctx);
  141.    }
  142.  
  143.    /* Otherwise use the generic version:
  144.     */
  145.    if (!vtx->emit)
  146.       vtx->emit = _tnl_generic_emit;
  147.  
  148.    vtx->emit( ctx, count, dest );
  149. }
  150.  
  151.  
  152.  
  153. static void choose_interp_func( struct gl_context *ctx,
  154.                                 GLfloat t,
  155.                                 GLuint edst, GLuint eout, GLuint ein,
  156.                                 GLboolean force_boundary )
  157. {
  158.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  159.    GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
  160.                          ctx->Polygon.BackMode != GL_FILL);
  161.    GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
  162.  
  163.    if (vtx->need_extras && (twosided || unfilled)) {
  164.       vtx->interp = _tnl_generic_interp_extras;
  165.    } else {
  166.       vtx->interp = _tnl_generic_interp;
  167.    }
  168.  
  169.    vtx->interp( ctx, t, edst, eout, ein, force_boundary );
  170. }
  171.  
  172.  
  173. static void choose_copy_pv_func(  struct gl_context *ctx, GLuint edst, GLuint esrc )
  174. {
  175.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  176.    GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
  177.                          ctx->Polygon.BackMode != GL_FILL);
  178.  
  179.    GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
  180.  
  181.    if (vtx->need_extras && (twosided || unfilled)) {
  182.       vtx->copy_pv = _tnl_generic_copy_pv_extras;
  183.    } else {
  184.       vtx->copy_pv = _tnl_generic_copy_pv;
  185.    }
  186.  
  187.    vtx->copy_pv( ctx, edst, esrc );
  188. }
  189.  
  190.  
  191. /***********************************************************************
  192.  * Public entrypoints, mostly dispatch to the above:
  193.  */
  194.  
  195.  
  196. /* Interpolate between two vertices to produce a third:
  197.  */
  198. void _tnl_interp( struct gl_context *ctx,
  199.                   GLfloat t,
  200.                   GLuint edst, GLuint eout, GLuint ein,
  201.                   GLboolean force_boundary )
  202. {
  203.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  204.    vtx->interp( ctx, t, edst, eout, ein, force_boundary );
  205. }
  206.  
  207. /* Copy colors from one vertex to another:
  208.  */
  209. void _tnl_copy_pv(  struct gl_context *ctx, GLuint edst, GLuint esrc )
  210. {
  211.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  212.    vtx->copy_pv( ctx, edst, esrc );
  213. }
  214.  
  215.  
  216. /* Extract a named attribute from a hardware vertex.  Will have to
  217.  * reverse any viewport transformation, swizzling or other conversions
  218.  * which may have been applied:
  219.  */
  220. void _tnl_get_attr( struct gl_context *ctx, const void *vin,
  221.                               GLenum attr, GLfloat *dest )
  222. {
  223.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  224.    const struct tnl_clipspace_attr *a = vtx->attr;
  225.    const GLuint attr_count = vtx->attr_count;
  226.    GLuint j;
  227.  
  228.    for (j = 0; j < attr_count; j++) {
  229.       if (a[j].attrib == attr) {
  230.          a[j].extract( &a[j], dest, (GLubyte *)vin + a[j].vertoffset );
  231.          return;
  232.       }
  233.    }
  234.  
  235.    /* Else return the value from ctx->Current.
  236.     */
  237.    if (attr == _TNL_ATTRIB_POINTSIZE) {
  238.       /* If the hardware vertex doesn't have point size then use size from
  239.        * struct gl_context.  XXX this will be wrong if drawing attenuated points!
  240.        */
  241.       dest[0] = ctx->Point.Size;
  242.    }
  243.    else {
  244.       memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
  245.    }
  246. }
  247.  
  248.  
  249. /* Complementary operation to the above.
  250.  */
  251. void _tnl_set_attr( struct gl_context *ctx, void *vout,
  252.                     GLenum attr, const GLfloat *src )
  253. {
  254.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  255.    const struct tnl_clipspace_attr *a = vtx->attr;
  256.    const GLuint attr_count = vtx->attr_count;
  257.    GLuint j;
  258.  
  259.    for (j = 0; j < attr_count; j++) {
  260.       if (a[j].attrib == attr) {
  261.          a[j].insert[4-1]( &a[j], (GLubyte *)vout + a[j].vertoffset, src );
  262.          return;
  263.       }
  264.    }
  265. }
  266.  
  267.  
  268. void *_tnl_get_vertex( struct gl_context *ctx, GLuint nr )
  269. {
  270.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  271.  
  272.    return vtx->vertex_buf + nr * vtx->vertex_size;
  273. }
  274.  
  275. void _tnl_invalidate_vertex_state( struct gl_context *ctx, GLuint new_state )
  276. {
  277.    /* if two-sided lighting changes or filled/unfilled polygon state changes */
  278.    if (new_state & (_NEW_LIGHT | _NEW_POLYGON) ) {
  279.       struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  280.       vtx->new_inputs = ~0;
  281.       vtx->interp = choose_interp_func;
  282.       vtx->copy_pv = choose_copy_pv_func;
  283.    }
  284. }
  285.  
  286. static void invalidate_funcs( struct tnl_clipspace *vtx )
  287. {
  288.    vtx->emit = choose_emit_func;
  289.    vtx->interp = choose_interp_func;
  290.    vtx->copy_pv = choose_copy_pv_func;
  291.    vtx->new_inputs = ~0;
  292. }
  293.  
  294. GLuint _tnl_install_attrs( struct gl_context *ctx, const struct tnl_attr_map *map,
  295.                            GLuint nr, const GLfloat *vp,
  296.                            GLuint unpacked_size )
  297. {
  298.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  299.    GLuint offset = 0;
  300.    GLuint i, j;
  301.  
  302.    assert(nr < _TNL_ATTRIB_MAX);
  303.    assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS);
  304.  
  305.    vtx->new_inputs = ~0;
  306.    vtx->need_viewport = GL_FALSE;
  307.  
  308.    if (vp) {
  309.       vtx->need_viewport = GL_TRUE;
  310.    }
  311.  
  312.    for (j = 0, i = 0; i < nr; i++) {
  313.       const GLuint format = map[i].format;
  314.       if (format == EMIT_PAD) {
  315.          if (DBG)
  316.             printf("%d: pad %d, offset %d\n", i,  
  317.                    map[i].offset, offset);  
  318.  
  319.          offset += map[i].offset;
  320.  
  321.       }
  322.       else {
  323.          GLuint tmpoffset;
  324.  
  325.          if (unpacked_size)
  326.             tmpoffset = map[i].offset;
  327.          else
  328.             tmpoffset = offset;
  329.  
  330.          if (vtx->attr_count != j ||
  331.              vtx->attr[j].attrib != map[i].attrib ||
  332.              vtx->attr[j].format != format ||
  333.              vtx->attr[j].vertoffset != tmpoffset) {
  334.             invalidate_funcs(vtx);
  335.  
  336.             vtx->attr[j].attrib = map[i].attrib;
  337.             vtx->attr[j].format = format;
  338.             vtx->attr[j].vp = vp;
  339.             vtx->attr[j].insert = _tnl_format_info[format].insert;
  340.             vtx->attr[j].extract = _tnl_format_info[format].extract;
  341.             vtx->attr[j].vertattrsize = _tnl_format_info[format].attrsize;
  342.             vtx->attr[j].vertoffset = tmpoffset;
  343.          }
  344.  
  345.          
  346.          if (DBG)
  347.             printf("%d: %s, vp %p, offset %d\n", i,  
  348.                    _tnl_format_info[format].name, (void *)vp,
  349.                    vtx->attr[j].vertoffset);  
  350.  
  351.          offset += _tnl_format_info[format].attrsize;
  352.          j++;
  353.       }
  354.    }
  355.  
  356.    vtx->attr_count = j;
  357.  
  358.    if (unpacked_size)
  359.       vtx->vertex_size = unpacked_size;
  360.    else
  361.       vtx->vertex_size = offset;
  362.  
  363.    assert(vtx->vertex_size <= vtx->max_vertex_size);
  364.    return vtx->vertex_size;
  365. }
  366.  
  367.  
  368.  
  369. void _tnl_invalidate_vertices( struct gl_context *ctx, GLuint newinputs )
  370. {
  371.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  372.    vtx->new_inputs |= newinputs;
  373. }
  374.  
  375.  
  376. /* This event has broader use beyond this file - will move elsewhere
  377.  * and probably invoke a driver callback.
  378.  */
  379. void _tnl_notify_pipeline_output_change( struct gl_context *ctx )
  380. {
  381.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  382.    invalidate_funcs(vtx);
  383. }
  384.  
  385.  
  386. static void adjust_input_ptrs( struct gl_context *ctx, GLint diff)
  387. {
  388.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  389.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  390.    struct tnl_clipspace_attr *a = vtx->attr;
  391.    const GLuint count = vtx->attr_count;
  392.    GLuint j;
  393.  
  394.    diff -= 1;
  395.    for (j=0; j<count; ++j) {
  396.            register GLvector4f *vptr = VB->AttribPtr[a->attrib];
  397.            (a++)->inputptr += diff*vptr->stride;
  398.    }
  399. }
  400.  
  401. static void update_input_ptrs( struct gl_context *ctx, GLuint start )
  402. {
  403.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  404.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  405.    struct tnl_clipspace_attr *a = vtx->attr;
  406.    const GLuint count = vtx->attr_count;
  407.    GLuint j;
  408.    
  409.    for (j = 0; j < count; j++) {
  410.       GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
  411.  
  412.       if (vtx->emit != choose_emit_func) {
  413.          assert(a[j].inputstride == vptr->stride);
  414.          assert(a[j].inputsize == vptr->size);
  415.       }
  416.  
  417.       a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
  418.    }
  419.    
  420.    if (a->vp) {
  421.       vtx->vp_scale[0] = a->vp[MAT_SX];
  422.       vtx->vp_scale[1] = a->vp[MAT_SY];
  423.       vtx->vp_scale[2] = a->vp[MAT_SZ];
  424.       vtx->vp_scale[3] = 1.0;
  425.       vtx->vp_xlate[0] = a->vp[MAT_TX];
  426.       vtx->vp_xlate[1] = a->vp[MAT_TY];
  427.       vtx->vp_xlate[2] = a->vp[MAT_TZ];
  428.       vtx->vp_xlate[3] = 0.0;
  429.    }
  430. }
  431.  
  432.  
  433. void _tnl_build_vertices( struct gl_context *ctx,
  434.                           GLuint start,
  435.                           GLuint end,
  436.                           GLuint newinputs )
  437. {
  438.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);  
  439.    update_input_ptrs( ctx, start );      
  440.    vtx->emit( ctx, end - start,
  441.               (GLubyte *)(vtx->vertex_buf +
  442.                           start * vtx->vertex_size));
  443. }
  444.  
  445. /* Emit VB vertices start..end to dest.  Note that VB vertex at
  446.  * postion start will be emitted to dest at position zero.
  447.  */
  448. void *_tnl_emit_vertices_to_buffer( struct gl_context *ctx,
  449.                                     GLuint start,
  450.                                     GLuint end,
  451.                                     void *dest )
  452. {
  453.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  454.  
  455.    update_input_ptrs(ctx, start);
  456.    /* Note: dest should not be adjusted for non-zero 'start' values:
  457.     */
  458.    vtx->emit( ctx, end - start, (GLubyte*) dest );     
  459.    return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start));
  460. }
  461.  
  462. /* Emit indexed VB vertices start..end to dest.  Note that VB vertex at
  463.  * postion start will be emitted to dest at position zero.
  464.  */
  465.  
  466. void *_tnl_emit_indexed_vertices_to_buffer( struct gl_context *ctx,
  467.                                             const GLuint *elts,
  468.                                             GLuint start,
  469.                                             GLuint end,
  470.                                             void *dest )
  471. {
  472.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  473.    GLuint oldIndex;
  474.    GLubyte *cdest = dest;
  475.  
  476.    update_input_ptrs(ctx, oldIndex = elts[start++]);
  477.    vtx->emit( ctx, 1, cdest );
  478.    cdest += vtx->vertex_size;
  479.  
  480.    for (; start < end; ++start) {
  481.       adjust_input_ptrs(ctx, elts[start] - oldIndex);
  482.       oldIndex = elts[start];
  483.       vtx->emit( ctx, 1, cdest);
  484.       cdest += vtx->vertex_size;
  485.    }
  486.  
  487.    return (void *) cdest;
  488. }
  489.  
  490.  
  491. void _tnl_init_vertices( struct gl_context *ctx,
  492.                         GLuint vb_size,
  493.                         GLuint max_vertex_size )
  494. {
  495.    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);  
  496.  
  497.    _tnl_install_attrs( ctx, NULL, 0, NULL, 0 );
  498.  
  499.    vtx->need_extras = GL_TRUE;
  500.    if (max_vertex_size > vtx->max_vertex_size) {
  501.       _tnl_free_vertices( ctx );
  502.       vtx->max_vertex_size = max_vertex_size;
  503.       vtx->vertex_buf = _mesa_align_calloc(vb_size * max_vertex_size, 32 );
  504.       invalidate_funcs(vtx);
  505.    }
  506.  
  507.    switch(CHAN_TYPE) {
  508.    case GL_UNSIGNED_BYTE:
  509.       vtx->chan_scale[0] = 255.0;
  510.       vtx->chan_scale[1] = 255.0;
  511.       vtx->chan_scale[2] = 255.0;
  512.       vtx->chan_scale[3] = 255.0;
  513.       break;
  514.    case GL_UNSIGNED_SHORT:
  515.       vtx->chan_scale[0] = 65535.0;
  516.       vtx->chan_scale[1] = 65535.0;
  517.       vtx->chan_scale[2] = 65535.0;
  518.       vtx->chan_scale[3] = 65535.0;
  519.       break;
  520.    default:
  521.       vtx->chan_scale[0] = 1.0;
  522.       vtx->chan_scale[1] = 1.0;
  523.       vtx->chan_scale[2] = 1.0;
  524.       vtx->chan_scale[3] = 1.0;
  525.       break;
  526.    }
  527.  
  528.    vtx->identity[0] = 0.0;
  529.    vtx->identity[1] = 0.0;
  530.    vtx->identity[2] = 0.0;
  531.    vtx->identity[3] = 1.0;
  532.  
  533.    vtx->codegen_emit = NULL;
  534.  
  535. #ifdef USE_SSE_ASM
  536.    if (!_mesa_getenv("MESA_NO_CODEGEN"))
  537.       vtx->codegen_emit = _tnl_generate_sse_emit;
  538. #endif
  539. }
  540.  
  541.  
  542. void _tnl_free_vertices( struct gl_context *ctx )
  543. {
  544.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  545.    if (tnl) {
  546.       struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
  547.       struct tnl_clipspace_fastpath *fp, *tmp;
  548.  
  549.       if (vtx->vertex_buf) {
  550.          _mesa_align_free(vtx->vertex_buf);
  551.          vtx->vertex_buf = NULL;
  552.       }
  553.  
  554.       for (fp = vtx->fastpath ; fp ; fp = tmp) {
  555.          tmp = fp->next;
  556.          free(fp->attr);
  557.  
  558.          /* KW: At the moment, fp->func is constrained to be allocated by
  559.           * _mesa_exec_alloc(), as the hardwired fastpaths in
  560.           * t_vertex_generic.c are handled specially.  It would be nice
  561.           * to unify them, but this probably won't change until this
  562.           * module gets another overhaul.
  563.           */
  564.          _mesa_exec_free((void *) fp->func);
  565.          free(fp);
  566.       }
  567.  
  568.       vtx->fastpath = NULL;
  569.    }
  570. }
  571.