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