Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * 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
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28.  /*
  29.   * Authors:
  30.   *   Keith Whitwell <keith@tungstengraphics.com>
  31.   */
  32.  
  33. #include "draw/draw_private.h"
  34. #include "draw/draw_pipe.h"
  35. #include "util/u_debug.h"
  36. #include "util/u_math.h"
  37.  
  38.  
  39.  
  40. boolean draw_pipeline_init( struct draw_context *draw )
  41. {
  42.    /* create pipeline stages */
  43.    draw->pipeline.wide_line  = draw_wide_line_stage( draw );
  44.    draw->pipeline.wide_point = draw_wide_point_stage( draw );
  45.    draw->pipeline.stipple   = draw_stipple_stage( draw );
  46.    draw->pipeline.unfilled  = draw_unfilled_stage( draw );
  47.    draw->pipeline.twoside   = draw_twoside_stage( draw );
  48.    draw->pipeline.offset    = draw_offset_stage( draw );
  49.    draw->pipeline.clip      = draw_clip_stage( draw );
  50.    draw->pipeline.flatshade = draw_flatshade_stage( draw );
  51.    draw->pipeline.cull      = draw_cull_stage( draw );
  52.    draw->pipeline.validate  = draw_validate_stage( draw );
  53.    draw->pipeline.first     = draw->pipeline.validate;
  54.  
  55.    if (!draw->pipeline.wide_line ||
  56.        !draw->pipeline.wide_point ||
  57.        !draw->pipeline.stipple ||
  58.        !draw->pipeline.unfilled ||
  59.        !draw->pipeline.twoside ||
  60.        !draw->pipeline.offset ||
  61.        !draw->pipeline.clip ||
  62.        !draw->pipeline.flatshade ||
  63.        !draw->pipeline.cull ||
  64.        !draw->pipeline.validate)
  65.       return FALSE;
  66.  
  67.    /* these defaults are oriented toward the needs of softpipe */
  68.    draw->pipeline.wide_point_threshold = 1000000.0f; /* infinity */
  69.    draw->pipeline.wide_line_threshold = 1.0f;
  70.    draw->pipeline.wide_point_sprites = FALSE;
  71.    draw->pipeline.line_stipple = TRUE;
  72.    draw->pipeline.point_sprite = TRUE;
  73.  
  74.    return TRUE;
  75. }
  76.  
  77.  
  78. void draw_pipeline_destroy( struct draw_context *draw )
  79. {
  80.    if (draw->pipeline.wide_line)
  81.       draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
  82.    if (draw->pipeline.wide_point)
  83.       draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
  84.    if (draw->pipeline.stipple)
  85.       draw->pipeline.stipple->destroy( draw->pipeline.stipple );
  86.    if (draw->pipeline.unfilled)
  87.       draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
  88.    if (draw->pipeline.twoside)
  89.       draw->pipeline.twoside->destroy( draw->pipeline.twoside );
  90.    if (draw->pipeline.offset)
  91.       draw->pipeline.offset->destroy( draw->pipeline.offset );
  92.    if (draw->pipeline.clip)
  93.       draw->pipeline.clip->destroy( draw->pipeline.clip );
  94.    if (draw->pipeline.flatshade)
  95.       draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
  96.    if (draw->pipeline.cull)
  97.       draw->pipeline.cull->destroy( draw->pipeline.cull );
  98.    if (draw->pipeline.validate)
  99.       draw->pipeline.validate->destroy( draw->pipeline.validate );
  100.    if (draw->pipeline.aaline)
  101.       draw->pipeline.aaline->destroy( draw->pipeline.aaline );
  102.    if (draw->pipeline.aapoint)
  103.       draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );
  104.    if (draw->pipeline.pstipple)
  105.       draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );
  106.    if (draw->pipeline.rasterize)
  107.       draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
  108. }
  109.  
  110.  
  111.  
  112. /**
  113.  * Build primitive to render a point with vertex at v0.
  114.  */
  115. static void do_point( struct draw_context *draw,
  116.                       const char *v0 )
  117. {
  118.    struct prim_header prim;
  119.    
  120.    prim.flags = 0;
  121.    prim.pad = 0;
  122.    prim.v[0] = (struct vertex_header *)v0;
  123.  
  124.    draw->pipeline.first->point( draw->pipeline.first, &prim );
  125. }
  126.  
  127.  
  128. /**
  129.  * Build primitive to render a line with vertices at v0, v1.
  130.  * \param flags  bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
  131.  */
  132. static void do_line( struct draw_context *draw,
  133.                      ushort flags,
  134.                      const char *v0,
  135.                      const char *v1 )
  136. {
  137.    struct prim_header prim;
  138.    
  139.    prim.flags = flags;
  140.    prim.pad = 0;
  141.    prim.v[0] = (struct vertex_header *)v0;
  142.    prim.v[1] = (struct vertex_header *)v1;
  143.  
  144.    draw->pipeline.first->line( draw->pipeline.first, &prim );
  145. }
  146.  
  147.  
  148. /**
  149.  * Build primitive to render a triangle with vertices at v0, v1, v2.
  150.  * \param flags  bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
  151.  */
  152. static void do_triangle( struct draw_context *draw,
  153.                          ushort flags,
  154.                          char *v0,
  155.                          char *v1,
  156.                          char *v2 )
  157. {
  158.    struct prim_header prim;
  159.    
  160.    prim.v[0] = (struct vertex_header *)v0;
  161.    prim.v[1] = (struct vertex_header *)v1;
  162.    prim.v[2] = (struct vertex_header *)v2;
  163.    prim.flags = flags;
  164.    prim.pad = 0;
  165.  
  166.    draw->pipeline.first->tri( draw->pipeline.first, &prim );
  167. }
  168.  
  169.  
  170. /*
  171.  * Set up macros for draw_pt_decompose.h template code.
  172.  * This code uses vertex indexes / elements.
  173.  */
  174.  
  175. #define TRIANGLE(flags,i0,i1,i2)                                  \
  176.    do {                                                           \
  177.       do_triangle( draw,                                          \
  178.                    flags,                                         \
  179.                    verts + stride * (i0),                         \
  180.                    verts + stride * (i1),                         \
  181.                    verts + stride * (i2) );                       \
  182.    } while (0)
  183.  
  184. #define LINE(flags,i0,i1)                                         \
  185.    do {                                                           \
  186.       do_line( draw,                                              \
  187.                flags,                                             \
  188.                verts + stride * (i0),                             \
  189.                verts + stride * (i1) );                           \
  190.    } while (0)
  191.  
  192. #define POINT(i0)                               \
  193.    do {                                         \
  194.       do_point( draw, verts + stride * (i0) );  \
  195.    } while (0)
  196.  
  197. #define GET_ELT(idx) (MIN2(elts[idx], max_index))
  198.  
  199. #define FUNC pipe_run_elts
  200. #define FUNC_VARS                               \
  201.     struct draw_context *draw,                  \
  202.     unsigned prim,                              \
  203.     unsigned prim_flags,                        \
  204.     struct vertex_header *vertices,             \
  205.     unsigned stride,                            \
  206.     const ushort *elts,                         \
  207.     unsigned count,                             \
  208.     unsigned max_index
  209.  
  210. #include "draw_pt_decompose.h"
  211.  
  212.  
  213.  
  214. /**
  215.  * Code to run the pipeline on a fairly arbitrary collection of vertices.
  216.  * For drawing indexed primitives.
  217.  *
  218.  * Vertex headers must be pre-initialized with the
  219.  * UNDEFINED_VERTEX_ID, this code will cause that id to become
  220.  * overwritten, so it may have to be reset if there is the intention
  221.  * to reuse the vertices.
  222.  *
  223.  * This code provides a callback to reset the vertex id's which the
  224.  * draw_vbuf.c code uses when it has to perform a flush.
  225.  */
  226. void draw_pipeline_run( struct draw_context *draw,
  227.                         const struct draw_vertex_info *vert_info,
  228.                         const struct draw_prim_info *prim_info)
  229. {
  230.    unsigned i, start;
  231.  
  232.    draw->pipeline.verts = (char *)vert_info->verts;
  233.    draw->pipeline.vertex_stride = vert_info->stride;
  234.    draw->pipeline.vertex_count = vert_info->count;
  235.  
  236.    for (start = i = 0;
  237.         i < prim_info->primitive_count;
  238.         start += prim_info->primitive_lengths[i], i++)
  239.    {
  240.       const unsigned count = prim_info->primitive_lengths[i];
  241.  
  242. #if DEBUG
  243.       /* Warn if one of the element indexes go outside the vertex buffer */
  244.       {
  245.          unsigned max_index = 0x0, i;
  246.          /* find the largest element index */
  247.          for (i = 0; i < count; i++) {
  248.             unsigned int index = prim_info->elts[start + i];
  249.             if (index > max_index)
  250.                max_index = index;
  251.          }
  252.          if (max_index >= vert_info->count) {
  253.             debug_printf("%s: max_index (%u) outside vertex buffer (%u)\n",
  254.                          __FUNCTION__,
  255.                          max_index,
  256.                          vert_info->count);
  257.          }
  258.       }
  259. #endif
  260.  
  261.       pipe_run_elts(draw,
  262.                     prim_info->prim,
  263.                     prim_info->flags,
  264.                     vert_info->verts,
  265.                     vert_info->stride,
  266.                     prim_info->elts + start,
  267.                     count,
  268.                     vert_info->count - 1);
  269.    }
  270.  
  271.    draw->pipeline.verts = NULL;
  272.    draw->pipeline.vertex_count = 0;
  273. }
  274.  
  275.  
  276. /*
  277.  * Set up macros for draw_pt_decompose.h template code.
  278.  * This code is for non-indexed (aka linear) rendering (no elts).
  279.  */
  280.  
  281. #define TRIANGLE(flags,i0,i1,i2)       \
  282.    do_triangle( draw, flags,           \
  283.                 verts + stride * (i0), \
  284.                 verts + stride * (i1), \
  285.                 verts + stride * (i2) )
  286.  
  287. #define LINE(flags,i0,i1)              \
  288.    do_line( draw, flags,               \
  289.             verts + stride * (i0),     \
  290.             verts + stride * (i1) )
  291.  
  292. #define POINT(i0)                      \
  293.    do_point( draw, verts + stride * (i0) )
  294.  
  295.  
  296. #define GET_ELT(idx) (idx)
  297.  
  298. #define FUNC pipe_run_linear
  299. #define FUNC_VARS                      \
  300.     struct draw_context *draw,         \
  301.     unsigned prim,                     \
  302.     unsigned prim_flags,               \
  303.     struct vertex_header *vertices,    \
  304.     unsigned stride,                   \
  305.     unsigned count
  306.  
  307. #include "draw_pt_decompose.h"
  308.  
  309.  
  310. /*
  311.  * For drawing non-indexed primitives.
  312.  */
  313. void draw_pipeline_run_linear( struct draw_context *draw,
  314.                                const struct draw_vertex_info *vert_info,
  315.                                const struct draw_prim_info *prim_info)
  316. {
  317.    unsigned i, start;
  318.  
  319.    for (start = i = 0;
  320.         i < prim_info->primitive_count;
  321.         start += prim_info->primitive_lengths[i], i++)
  322.    {
  323.       unsigned count = prim_info->primitive_lengths[i];
  324.       char *verts = ((char*)vert_info->verts) +
  325.                     (start * vert_info->stride);
  326.  
  327.       draw->pipeline.verts = verts;
  328.       draw->pipeline.vertex_stride = vert_info->stride;
  329.       draw->pipeline.vertex_count = count;
  330.  
  331.       assert(count <= vert_info->count);
  332.  
  333.       pipe_run_linear(draw,
  334.                       prim_info->prim,
  335.                       prim_info->flags,
  336.                       (struct vertex_header*)verts,
  337.                       vert_info->stride,
  338.                       count);
  339.    }
  340.  
  341.    draw->pipeline.verts = NULL;
  342.    draw->pipeline.vertex_count = 0;
  343. }
  344.  
  345.  
  346. void draw_pipeline_flush( struct draw_context *draw,
  347.                           unsigned flags )
  348. {
  349.    draw->pipeline.first->flush( draw->pipeline.first, flags );
  350.    if (flags & DRAW_FLUSH_STATE_CHANGE)
  351.       draw->pipeline.first = draw->pipeline.validate;
  352. }
  353.