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