14a49301eSmrg/**************************************************************************
24a49301eSmrg *
3af69d88dSmrg * Copyright 2007 VMware, Inc.
44a49301eSmrg * All Rights Reserved.
54a49301eSmrg *
64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a
74a49301eSmrg * copy of this software and associated documentation files (the
84a49301eSmrg * "Software"), to deal in the Software without restriction, including
94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish,
104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to
114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to
124a49301eSmrg * the following conditions:
134a49301eSmrg *
144a49301eSmrg * The above copyright notice and this permission notice (including the
154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions
164a49301eSmrg * of the Software.
174a49301eSmrg *
184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
254a49301eSmrg *
264a49301eSmrg **************************************************************************/
274a49301eSmrg
284a49301eSmrg /*
294a49301eSmrg  * Authors:
30af69d88dSmrg  *   Keith Whitwell <keithw@vmware.com>
314a49301eSmrg  */
324a49301eSmrg
334a49301eSmrg#include "draw/draw_private.h"
344a49301eSmrg#include "draw/draw_pipe.h"
35cdc920a0Smrg#include "util/u_debug.h"
36af69d88dSmrg#include "util/u_math.h"
374a49301eSmrg
384a49301eSmrg
394a49301eSmrg
404a49301eSmrgboolean draw_pipeline_init( struct draw_context *draw )
414a49301eSmrg{
424a49301eSmrg   /* create pipeline stages */
434a49301eSmrg   draw->pipeline.wide_line  = draw_wide_line_stage( draw );
444a49301eSmrg   draw->pipeline.wide_point = draw_wide_point_stage( draw );
454a49301eSmrg   draw->pipeline.stipple   = draw_stipple_stage( draw );
464a49301eSmrg   draw->pipeline.unfilled  = draw_unfilled_stage( draw );
474a49301eSmrg   draw->pipeline.twoside   = draw_twoside_stage( draw );
484a49301eSmrg   draw->pipeline.offset    = draw_offset_stage( draw );
494a49301eSmrg   draw->pipeline.clip      = draw_clip_stage( draw );
504a49301eSmrg   draw->pipeline.flatshade = draw_flatshade_stage( draw );
514a49301eSmrg   draw->pipeline.cull      = draw_cull_stage( draw );
527ec681f3Smrg   draw->pipeline.user_cull = draw_user_cull_stage( draw );
534a49301eSmrg   draw->pipeline.validate  = draw_validate_stage( draw );
544a49301eSmrg   draw->pipeline.first     = draw->pipeline.validate;
554a49301eSmrg
564a49301eSmrg   if (!draw->pipeline.wide_line ||
574a49301eSmrg       !draw->pipeline.wide_point ||
584a49301eSmrg       !draw->pipeline.stipple ||
594a49301eSmrg       !draw->pipeline.unfilled ||
604a49301eSmrg       !draw->pipeline.twoside ||
614a49301eSmrg       !draw->pipeline.offset ||
624a49301eSmrg       !draw->pipeline.clip ||
634a49301eSmrg       !draw->pipeline.flatshade ||
644a49301eSmrg       !draw->pipeline.cull ||
657ec681f3Smrg       !draw->pipeline.user_cull ||
664a49301eSmrg       !draw->pipeline.validate)
674a49301eSmrg      return FALSE;
684a49301eSmrg
694a49301eSmrg   /* these defaults are oriented toward the needs of softpipe */
703464ebd5Sriastradh   draw->pipeline.wide_point_threshold = 1000000.0f; /* infinity */
713464ebd5Sriastradh   draw->pipeline.wide_line_threshold = 1.0f;
723464ebd5Sriastradh   draw->pipeline.wide_point_sprites = FALSE;
734a49301eSmrg   draw->pipeline.line_stipple = TRUE;
744a49301eSmrg   draw->pipeline.point_sprite = TRUE;
754a49301eSmrg
764a49301eSmrg   return TRUE;
774a49301eSmrg}
784a49301eSmrg
794a49301eSmrg
804a49301eSmrgvoid draw_pipeline_destroy( struct draw_context *draw )
814a49301eSmrg{
824a49301eSmrg   if (draw->pipeline.wide_line)
834a49301eSmrg      draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
844a49301eSmrg   if (draw->pipeline.wide_point)
854a49301eSmrg      draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
864a49301eSmrg   if (draw->pipeline.stipple)
874a49301eSmrg      draw->pipeline.stipple->destroy( draw->pipeline.stipple );
884a49301eSmrg   if (draw->pipeline.unfilled)
894a49301eSmrg      draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
904a49301eSmrg   if (draw->pipeline.twoside)
914a49301eSmrg      draw->pipeline.twoside->destroy( draw->pipeline.twoside );
924a49301eSmrg   if (draw->pipeline.offset)
934a49301eSmrg      draw->pipeline.offset->destroy( draw->pipeline.offset );
944a49301eSmrg   if (draw->pipeline.clip)
954a49301eSmrg      draw->pipeline.clip->destroy( draw->pipeline.clip );
964a49301eSmrg   if (draw->pipeline.flatshade)
974a49301eSmrg      draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
984a49301eSmrg   if (draw->pipeline.cull)
994a49301eSmrg      draw->pipeline.cull->destroy( draw->pipeline.cull );
1007ec681f3Smrg   if (draw->pipeline.user_cull)
1017ec681f3Smrg      draw->pipeline.user_cull->destroy( draw->pipeline.user_cull );
1024a49301eSmrg   if (draw->pipeline.validate)
1034a49301eSmrg      draw->pipeline.validate->destroy( draw->pipeline.validate );
1044a49301eSmrg   if (draw->pipeline.aaline)
1054a49301eSmrg      draw->pipeline.aaline->destroy( draw->pipeline.aaline );
1064a49301eSmrg   if (draw->pipeline.aapoint)
1074a49301eSmrg      draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );
1084a49301eSmrg   if (draw->pipeline.pstipple)
1094a49301eSmrg      draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );
1104a49301eSmrg   if (draw->pipeline.rasterize)
1114a49301eSmrg      draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
1124a49301eSmrg}
1134a49301eSmrg
1144a49301eSmrg
1154a49301eSmrg
1164a49301eSmrg/**
1174a49301eSmrg * Build primitive to render a point with vertex at v0.
1184a49301eSmrg */
1194a49301eSmrgstatic void do_point( struct draw_context *draw,
1204a49301eSmrg		      const char *v0 )
1214a49301eSmrg{
1224a49301eSmrg   struct prim_header prim;
1234a49301eSmrg
1244a49301eSmrg   prim.flags = 0;
1254a49301eSmrg   prim.pad = 0;
1264a49301eSmrg   prim.v[0] = (struct vertex_header *)v0;
1274a49301eSmrg
1284a49301eSmrg   draw->pipeline.first->point( draw->pipeline.first, &prim );
1294a49301eSmrg}
1304a49301eSmrg
1314a49301eSmrg
1324a49301eSmrg/**
1334a49301eSmrg * Build primitive to render a line with vertices at v0, v1.
1344a49301eSmrg * \param flags  bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
1354a49301eSmrg */
1364a49301eSmrgstatic void do_line( struct draw_context *draw,
1374a49301eSmrg                     ushort flags,
1384a49301eSmrg		     const char *v0,
1394a49301eSmrg		     const char *v1 )
1404a49301eSmrg{
1414a49301eSmrg   struct prim_header prim;
1424a49301eSmrg
1434a49301eSmrg   prim.flags = flags;
1444a49301eSmrg   prim.pad = 0;
1454a49301eSmrg   prim.v[0] = (struct vertex_header *)v0;
1464a49301eSmrg   prim.v[1] = (struct vertex_header *)v1;
1474a49301eSmrg
1484a49301eSmrg   draw->pipeline.first->line( draw->pipeline.first, &prim );
1494a49301eSmrg}
1504a49301eSmrg
1514a49301eSmrg
1524a49301eSmrg/**
1534a49301eSmrg * Build primitive to render a triangle with vertices at v0, v1, v2.
1544a49301eSmrg * \param flags  bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
1554a49301eSmrg */
1564a49301eSmrgstatic void do_triangle( struct draw_context *draw,
1574a49301eSmrg                         ushort flags,
1584a49301eSmrg			 char *v0,
1594a49301eSmrg			 char *v1,
1604a49301eSmrg			 char *v2 )
1614a49301eSmrg{
1624a49301eSmrg   struct prim_header prim;
1634a49301eSmrg
1644a49301eSmrg   prim.v[0] = (struct vertex_header *)v0;
1654a49301eSmrg   prim.v[1] = (struct vertex_header *)v1;
1664a49301eSmrg   prim.v[2] = (struct vertex_header *)v2;
1674a49301eSmrg   prim.flags = flags;
1684a49301eSmrg   prim.pad = 0;
1694a49301eSmrg
1704a49301eSmrg   draw->pipeline.first->tri( draw->pipeline.first, &prim );
1714a49301eSmrg}
1724a49301eSmrg
1734a49301eSmrg
1744a49301eSmrg/*
1754a49301eSmrg * Set up macros for draw_pt_decompose.h template code.
1764a49301eSmrg * This code uses vertex indexes / elements.
1774a49301eSmrg */
1783464ebd5Sriastradh
1793464ebd5Sriastradh#define TRIANGLE(flags,i0,i1,i2)                                  \
1803464ebd5Sriastradh   do {                                                           \
1813464ebd5Sriastradh      do_triangle( draw,                                          \
1823464ebd5Sriastradh                   flags,                                         \
1833464ebd5Sriastradh                   verts + stride * (i0),                         \
1843464ebd5Sriastradh                   verts + stride * (i1),                         \
1853464ebd5Sriastradh                   verts + stride * (i2) );                       \
1863464ebd5Sriastradh   } while (0)
1873464ebd5Sriastradh
1883464ebd5Sriastradh#define LINE(flags,i0,i1)                                         \
1893464ebd5Sriastradh   do {                                                           \
1903464ebd5Sriastradh      do_line( draw,                                              \
1913464ebd5Sriastradh               flags,                                             \
1923464ebd5Sriastradh               verts + stride * (i0),                             \
1933464ebd5Sriastradh               verts + stride * (i1) );                           \
1943464ebd5Sriastradh   } while (0)
1954a49301eSmrg
1964a49301eSmrg#define POINT(i0)                               \
1973464ebd5Sriastradh   do {                                         \
1983464ebd5Sriastradh      do_point( draw, verts + stride * (i0) );  \
1993464ebd5Sriastradh   } while (0)
2003464ebd5Sriastradh
201af69d88dSmrg#define GET_ELT(idx) (MIN2(elts[idx], max_index))
2024a49301eSmrg
2033464ebd5Sriastradh#define FUNC pipe_run_elts
2043464ebd5Sriastradh#define FUNC_VARS                               \
2054a49301eSmrg    struct draw_context *draw,                  \
2064a49301eSmrg    unsigned prim,                              \
2073464ebd5Sriastradh    unsigned prim_flags,                        \
2084a49301eSmrg    struct vertex_header *vertices,             \
2094a49301eSmrg    unsigned stride,                            \
2103464ebd5Sriastradh    const ushort *elts,                         \
211af69d88dSmrg    unsigned count,                             \
212af69d88dSmrg    unsigned max_index
2134a49301eSmrg
2144a49301eSmrg#include "draw_pt_decompose.h"
2154a49301eSmrg
2164a49301eSmrg
2174a49301eSmrg
2184a49301eSmrg/**
2193464ebd5Sriastradh * Code to run the pipeline on a fairly arbitrary collection of vertices.
2204a49301eSmrg * For drawing indexed primitives.
2214a49301eSmrg *
2224a49301eSmrg * Vertex headers must be pre-initialized with the
2234a49301eSmrg * UNDEFINED_VERTEX_ID, this code will cause that id to become
2244a49301eSmrg * overwritten, so it may have to be reset if there is the intention
2254a49301eSmrg * to reuse the vertices.
2264a49301eSmrg *
2274a49301eSmrg * This code provides a callback to reset the vertex id's which the
2284a49301eSmrg * draw_vbuf.c code uses when it has to perform a flush.
2294a49301eSmrg */
2304a49301eSmrgvoid draw_pipeline_run( struct draw_context *draw,
2313464ebd5Sriastradh                        const struct draw_vertex_info *vert_info,
2323464ebd5Sriastradh                        const struct draw_prim_info *prim_info)
2334a49301eSmrg{
2343464ebd5Sriastradh   unsigned i, start;
2353464ebd5Sriastradh
2363464ebd5Sriastradh   draw->pipeline.verts = (char *)vert_info->verts;
2373464ebd5Sriastradh   draw->pipeline.vertex_stride = vert_info->stride;
2383464ebd5Sriastradh   draw->pipeline.vertex_count = vert_info->count;
2393464ebd5Sriastradh
2403464ebd5Sriastradh   for (start = i = 0;
2413464ebd5Sriastradh        i < prim_info->primitive_count;
2423464ebd5Sriastradh        start += prim_info->primitive_lengths[i], i++)
2433464ebd5Sriastradh   {
2443464ebd5Sriastradh      const unsigned count = prim_info->primitive_lengths[i];
2453464ebd5Sriastradh
2463464ebd5Sriastradh#if DEBUG
2473464ebd5Sriastradh      /* Warn if one of the element indexes go outside the vertex buffer */
2483464ebd5Sriastradh      {
2493464ebd5Sriastradh         unsigned max_index = 0x0, i;
2503464ebd5Sriastradh         /* find the largest element index */
2513464ebd5Sriastradh         for (i = 0; i < count; i++) {
2523464ebd5Sriastradh            unsigned int index = prim_info->elts[start + i];
2533464ebd5Sriastradh            if (index > max_index)
2543464ebd5Sriastradh               max_index = index;
2553464ebd5Sriastradh         }
2563464ebd5Sriastradh         if (max_index >= vert_info->count) {
2573464ebd5Sriastradh            debug_printf("%s: max_index (%u) outside vertex buffer (%u)\n",
2583464ebd5Sriastradh                         __FUNCTION__,
2593464ebd5Sriastradh                         max_index,
2603464ebd5Sriastradh                         vert_info->count);
2613464ebd5Sriastradh         }
2623464ebd5Sriastradh      }
2633464ebd5Sriastradh#endif
2643464ebd5Sriastradh
2653464ebd5Sriastradh      pipe_run_elts(draw,
2663464ebd5Sriastradh                    prim_info->prim,
2673464ebd5Sriastradh                    prim_info->flags,
2683464ebd5Sriastradh                    vert_info->verts,
2693464ebd5Sriastradh                    vert_info->stride,
2703464ebd5Sriastradh                    prim_info->elts + start,
271af69d88dSmrg                    count,
272af69d88dSmrg                    vert_info->count - 1);
2733464ebd5Sriastradh   }
2744a49301eSmrg
2754a49301eSmrg   draw->pipeline.verts = NULL;
2764a49301eSmrg   draw->pipeline.vertex_count = 0;
2774a49301eSmrg}
2784a49301eSmrg
2794a49301eSmrg
2804a49301eSmrg/*
2814a49301eSmrg * Set up macros for draw_pt_decompose.h template code.
2823464ebd5Sriastradh * This code is for non-indexed (aka linear) rendering (no elts).
2834a49301eSmrg */
2844a49301eSmrg
2853464ebd5Sriastradh#define TRIANGLE(flags,i0,i1,i2)       \
2863464ebd5Sriastradh   do_triangle( draw, flags,           \
2873464ebd5Sriastradh                verts + stride * (i0), \
2883464ebd5Sriastradh                verts + stride * (i1), \
2893464ebd5Sriastradh                verts + stride * (i2) )
2904a49301eSmrg
2913464ebd5Sriastradh#define LINE(flags,i0,i1)              \
2923464ebd5Sriastradh   do_line( draw, flags,               \
2933464ebd5Sriastradh            verts + stride * (i0),     \
2943464ebd5Sriastradh            verts + stride * (i1) )
2954a49301eSmrg
2963464ebd5Sriastradh#define POINT(i0)                      \
2973464ebd5Sriastradh   do_point( draw, verts + stride * (i0) )
2984a49301eSmrg
2993464ebd5Sriastradh
3003464ebd5Sriastradh#define GET_ELT(idx) (idx)
3013464ebd5Sriastradh
3023464ebd5Sriastradh#define FUNC pipe_run_linear
3033464ebd5Sriastradh#define FUNC_VARS                      \
3043464ebd5Sriastradh    struct draw_context *draw,         \
3053464ebd5Sriastradh    unsigned prim,                     \
3063464ebd5Sriastradh    unsigned prim_flags,               \
3073464ebd5Sriastradh    struct vertex_header *vertices,    \
3083464ebd5Sriastradh    unsigned stride,                   \
3093464ebd5Sriastradh    unsigned count
3104a49301eSmrg
3114a49301eSmrg#include "draw_pt_decompose.h"
3124a49301eSmrg
3134a49301eSmrg
3144a49301eSmrg/*
3154a49301eSmrg * For drawing non-indexed primitives.
3164a49301eSmrg */
3174a49301eSmrgvoid draw_pipeline_run_linear( struct draw_context *draw,
3183464ebd5Sriastradh                               const struct draw_vertex_info *vert_info,
3193464ebd5Sriastradh                               const struct draw_prim_info *prim_info)
3204a49301eSmrg{
3213464ebd5Sriastradh   unsigned i, start;
3223464ebd5Sriastradh
3233464ebd5Sriastradh   for (start = i = 0;
3243464ebd5Sriastradh        i < prim_info->primitive_count;
3253464ebd5Sriastradh        start += prim_info->primitive_lengths[i], i++)
3263464ebd5Sriastradh   {
3273464ebd5Sriastradh      unsigned count = prim_info->primitive_lengths[i];
3283464ebd5Sriastradh      char *verts = ((char*)vert_info->verts) +
3293464ebd5Sriastradh                    (start * vert_info->stride);
3303464ebd5Sriastradh
3313464ebd5Sriastradh      draw->pipeline.verts = verts;
3323464ebd5Sriastradh      draw->pipeline.vertex_stride = vert_info->stride;
3333464ebd5Sriastradh      draw->pipeline.vertex_count = count;
3343464ebd5Sriastradh
3353464ebd5Sriastradh      assert(count <= vert_info->count);
3363464ebd5Sriastradh
3373464ebd5Sriastradh      pipe_run_linear(draw,
3383464ebd5Sriastradh                      prim_info->prim,
3393464ebd5Sriastradh                      prim_info->flags,
3403464ebd5Sriastradh                      (struct vertex_header*)verts,
3413464ebd5Sriastradh                      vert_info->stride,
3423464ebd5Sriastradh                      count);
3433464ebd5Sriastradh   }
3444a49301eSmrg
3454a49301eSmrg   draw->pipeline.verts = NULL;
3464a49301eSmrg   draw->pipeline.vertex_count = 0;
3474a49301eSmrg}
3484a49301eSmrg
3494a49301eSmrg
3504a49301eSmrgvoid draw_pipeline_flush( struct draw_context *draw,
3514a49301eSmrg                          unsigned flags )
3524a49301eSmrg{
3534a49301eSmrg   draw->pipeline.first->flush( draw->pipeline.first, flags );
354af69d88dSmrg   if (flags & DRAW_FLUSH_STATE_CHANGE)
355af69d88dSmrg      draw->pipeline.first = draw->pipeline.validate;
3564a49301eSmrg}
357