Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Keith Whitwell <keithw@vmware.com>
  26.  */
  27.  
  28.  
  29. /*
  30.  * Render whole vertex buffers, including projection of vertices from
  31.  * clip space and clipping of primitives.
  32.  *
  33.  * This file makes calls to project vertices and to the point, line
  34.  * and triangle rasterizers via the function pointers:
  35.  *
  36.  *    context->Driver.Render.*
  37.  *
  38.  */
  39.  
  40.  
  41. #include <stdio.h>
  42. #include "main/glheader.h"
  43. #include "main/context.h"
  44. #include "main/enums.h"
  45. #include "main/macros.h"
  46. #include "main/imports.h"
  47. #include "main/mtypes.h"
  48. #include "math/m_xform.h"
  49.  
  50. #include "t_pipeline.h"
  51.  
  52.  
  53.  
  54. /**********************************************************************/
  55. /*                        Clip single primitives                      */
  56. /**********************************************************************/
  57.  
  58.  
  59. #define W(i) coord[i][3]
  60. #define Z(i) coord[i][2]
  61. #define Y(i) coord[i][1]
  62. #define X(i) coord[i][0]
  63. #define SIZE 4
  64. #define TAG(x) x##_4
  65. #include "t_vb_cliptmp.h"
  66.  
  67.  
  68.  
  69. /**********************************************************************/
  70. /*              Clip and render whole begin/end objects               */
  71. /**********************************************************************/
  72.  
  73. #define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
  74. #define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
  75. #define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
  76.  
  77.  
  78. /* This does NOT include the CLIP_USER_BIT! */
  79. #define CLIPMASK (CLIP_FRUSTUM_BITS | CLIP_CULL_BIT)
  80.  
  81.  
  82. /* Vertices, with the possibility of clipping.
  83.  */
  84. #define RENDER_POINTS( start, count ) \
  85.    tnl->Driver.Render.Points( ctx, start, count )
  86.  
  87. #define RENDER_LINE( v1, v2 )                   \
  88. do {                                            \
  89.    GLubyte c1 = mask[v1], c2 = mask[v2];        \
  90.    GLubyte ormask = c1|c2;                      \
  91.    if (!ormask)                                 \
  92.       LineFunc( ctx, v1, v2 );                  \
  93.    else if (!(c1 & c2 & CLIPMASK))                      \
  94.       clip_line_4( ctx, v1, v2, ormask );       \
  95. } while (0)
  96.  
  97. #define RENDER_TRI( v1, v2, v3 )                        \
  98. do {                                                    \
  99.    GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
  100.    GLubyte ormask = c1|c2|c3;                           \
  101.    if (!ormask)                                         \
  102.       TriangleFunc( ctx, v1, v2, v3 );                  \
  103.    else if (!(c1 & c2 & c3 & CLIPMASK))                         \
  104.       clip_tri_4( ctx, v1, v2, v3, ormask );            \
  105. } while (0)
  106.  
  107. #define RENDER_QUAD( v1, v2, v3, v4 )                   \
  108. do {                                                    \
  109.    GLubyte c1 = mask[v1], c2 = mask[v2];                \
  110.    GLubyte c3 = mask[v3], c4 = mask[v4];                \
  111.    GLubyte ormask = c1|c2|c3|c4;                        \
  112.    if (!ormask)                                         \
  113.       QuadFunc( ctx, v1, v2, v3, v4 );                  \
  114.    else if (!(c1 & c2 & c3 & c4 & CLIPMASK))            \
  115.       clip_quad_4( ctx, v1, v2, v3, v4, ormask );       \
  116. } while (0)
  117.  
  118.  
  119. #define LOCAL_VARS                                              \
  120.    TNLcontext *tnl = TNL_CONTEXT(ctx);                          \
  121.    struct vertex_buffer *VB = &tnl->vb;                         \
  122.    const GLuint * const elt = VB->Elts;                         \
  123.    const GLubyte *mask = VB->ClipMask;                          \
  124.    const GLuint sz = VB->ClipPtr->size;                         \
  125.    const tnl_line_func LineFunc = tnl->Driver.Render.Line;              \
  126.    const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle;  \
  127.    const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad;              \
  128.    const GLboolean stipple = ctx->Line.StippleFlag;             \
  129.    (void) (LineFunc && TriangleFunc && QuadFunc);               \
  130.    (void) elt; (void) mask; (void) sz; (void) stipple;
  131.  
  132. #define TAG(x) clip_##x##_verts
  133. #define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
  134. #define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
  135. #define PRESERVE_VB_DEFS
  136. #include "t_vb_rendertmp.h"
  137.  
  138.  
  139.  
  140. /* Elts, with the possibility of clipping.
  141.  */
  142. #undef ELT
  143. #undef TAG
  144. #define ELT(x) elt[x]
  145. #define TAG(x) clip_##x##_elts
  146. #include "t_vb_rendertmp.h"
  147.  
  148. /* TODO: do this for all primitives, verts and elts:
  149.  */
  150. static void clip_elt_triangles( struct gl_context *ctx,
  151.                                 GLuint start,
  152.                                 GLuint count,
  153.                                 GLuint flags )
  154. {
  155.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  156.    tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
  157.    struct vertex_buffer *VB = &tnl->vb;
  158.    const GLuint * const elt = VB->Elts;
  159.    GLubyte *mask = VB->ClipMask;
  160.    GLuint last = count-2;
  161.    GLuint j;
  162.    (void) flags;
  163.  
  164.    tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
  165.  
  166.    for (j=start; j < last; j+=3 ) {
  167.       GLubyte c1 = mask[elt[j]];
  168.       GLubyte c2 = mask[elt[j+1]];
  169.       GLubyte c3 = mask[elt[j+2]];
  170.       GLubyte ormask = c1|c2|c3;
  171.       if (ormask) {
  172.          if (start < j)
  173.             render_tris( ctx, start, j, 0 );
  174.          if (!(c1&c2&c3&CLIPMASK))
  175.             clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
  176.          start = j+3;
  177.       }
  178.    }
  179.  
  180.    if (start < j)
  181.       render_tris( ctx, start, j, 0 );
  182. }
  183.  
  184. /**********************************************************************/
  185. /*                  Render whole begin/end objects                    */
  186. /**********************************************************************/
  187.  
  188. #define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
  189. #define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
  190. #define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
  191.  
  192.  
  193. /* Vertices, no clipping.
  194.  */
  195. #define RENDER_POINTS( start, count ) \
  196.    tnl->Driver.Render.Points( ctx, start, count )
  197.  
  198. #define RENDER_LINE( v1, v2 ) \
  199.    LineFunc( ctx, v1, v2 )
  200.  
  201. #define RENDER_TRI( v1, v2, v3 ) \
  202.    TriangleFunc( ctx, v1, v2, v3 )
  203.  
  204. #define RENDER_QUAD( v1, v2, v3, v4 ) \
  205.    QuadFunc( ctx, v1, v2, v3, v4 )
  206.  
  207. #define TAG(x) _tnl_##x##_verts
  208.  
  209. #define LOCAL_VARS                                              \
  210.    TNLcontext *tnl = TNL_CONTEXT(ctx);                          \
  211.    struct vertex_buffer *VB = &tnl->vb;                         \
  212.    const GLuint * const elt = VB->Elts;                         \
  213.    const tnl_line_func LineFunc = tnl->Driver.Render.Line;              \
  214.    const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle;  \
  215.    const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad;              \
  216.    const GLboolean stipple = ctx->Line.StippleFlag;             \
  217.    (void) (LineFunc && TriangleFunc && QuadFunc);               \
  218.    (void) elt; (void) stipple
  219.  
  220. #define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
  221. #define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
  222. #define RENDER_TAB_QUALIFIER
  223. #define PRESERVE_VB_DEFS
  224. #include "t_vb_rendertmp.h"
  225.  
  226.  
  227. /* Elts, no clipping.
  228.  */
  229. #undef ELT
  230. #define TAG(x) _tnl_##x##_elts
  231. #define ELT(x) elt[x]
  232. #include "t_vb_rendertmp.h"
  233.  
  234.  
  235. /**********************************************************************/
  236. /*              Helper functions for drivers                  */
  237. /**********************************************************************/
  238.  
  239. void _tnl_RenderClippedPolygon( struct gl_context *ctx, const GLuint *elts, GLuint n )
  240. {
  241.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  242.    struct vertex_buffer *VB = &tnl->vb;
  243.    GLuint *tmp = VB->Elts;
  244.  
  245.    VB->Elts = (GLuint *)elts;
  246.    tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
  247.    VB->Elts = tmp;
  248. }
  249.  
  250. void _tnl_RenderClippedLine( struct gl_context *ctx, GLuint ii, GLuint jj )
  251. {
  252.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  253.    tnl->Driver.Render.Line( ctx, ii, jj );
  254. }
  255.  
  256.  
  257.  
  258. /**********************************************************************/
  259. /*              Clip and render whole vertex buffers                  */
  260. /**********************************************************************/
  261.  
  262.  
  263. static GLboolean run_render( struct gl_context *ctx,
  264.                              struct tnl_pipeline_stage *stage )
  265. {
  266.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  267.    struct vertex_buffer *VB = &tnl->vb;
  268.    tnl_render_func *tab;
  269.    GLint pass = 0;
  270.  
  271.    /* Allow the drivers to lock before projected verts are built so
  272.     * that window coordinates are guarenteed not to change before
  273.     * rendering.
  274.     */
  275.    assert(tnl->Driver.Render.Start);
  276.  
  277.    tnl->Driver.Render.Start( ctx );
  278.  
  279.    assert(tnl->Driver.Render.BuildVertices);
  280.    assert(tnl->Driver.Render.PrimitiveNotify);
  281.    assert(tnl->Driver.Render.Points);
  282.    assert(tnl->Driver.Render.Line);
  283.    assert(tnl->Driver.Render.Triangle);
  284.    assert(tnl->Driver.Render.Quad);
  285.    assert(tnl->Driver.Render.ResetLineStipple);
  286.    assert(tnl->Driver.Render.Interp);
  287.    assert(tnl->Driver.Render.CopyPV);
  288.    assert(tnl->Driver.Render.ClippedLine);
  289.    assert(tnl->Driver.Render.ClippedPolygon);
  290.    assert(tnl->Driver.Render.Finish);
  291.  
  292.    tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
  293.  
  294.    if (VB->ClipOrMask) {
  295.       tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
  296.       clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
  297.    }
  298.    else {
  299.       tab = (VB->Elts ?
  300.              tnl->Driver.Render.PrimTabElts :
  301.              tnl->Driver.Render.PrimTabVerts);
  302.    }
  303.  
  304.    do
  305.    {
  306.       GLuint i;
  307.  
  308.       for (i = 0 ; i < VB->PrimitiveCount ; i++)
  309.       {
  310.          GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
  311.          GLuint start = VB->Primitive[i].start;
  312.          GLuint length = VB->Primitive[i].count;
  313.  
  314.          assert((prim & PRIM_MODE_MASK) <= GL_POLYGON);
  315.  
  316.          if (MESA_VERBOSE & VERBOSE_PRIMS)
  317.             _mesa_debug(NULL, "MESA prim %s %d..%d\n",
  318.                         _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK),
  319.                         start, start+length);
  320.  
  321.          if (length)
  322.             tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim );
  323.       }
  324.    } while (tnl->Driver.Render.Multipass &&
  325.             tnl->Driver.Render.Multipass( ctx, ++pass ));
  326.  
  327.    tnl->Driver.Render.Finish( ctx );
  328.  
  329.    return GL_FALSE;             /* finished the pipe */
  330. }
  331.  
  332.  
  333. /**********************************************************************/
  334. /*                          Render pipeline stage                     */
  335. /**********************************************************************/
  336.  
  337.  
  338.  
  339.  
  340.  
  341. const struct tnl_pipeline_stage _tnl_render_stage =
  342. {
  343.    "render",                    /* name */
  344.    NULL,                        /* private data */
  345.    NULL,                        /* creator */
  346.    NULL,                        /* destructor */
  347.    NULL,                        /* validate */
  348.    run_render                   /* run */
  349. };
  350.