draw_context.c revision 66891826421d5b774e081f7a2a85580cd0523fab
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 34#include "pipe/p_util.h" 35#include "draw_context.h" 36#include "draw_vbuf.h" 37#include "draw_vs.h" 38 39 40struct draw_context *draw_create( void ) 41{ 42 struct draw_context *draw = CALLOC_STRUCT( draw_context ); 43 if (draw == NULL) 44 goto fail; 45 46#if defined(__i386__) || defined(__386__) 47 draw->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL; 48#else 49 draw->use_sse = FALSE; 50#endif 51 52 /* create pipeline stages */ 53 draw->pipeline.wide_line = draw_wide_line_stage( draw ); 54 draw->pipeline.wide_point = draw_wide_point_stage( draw ); 55 draw->pipeline.stipple = draw_stipple_stage( draw ); 56 draw->pipeline.unfilled = draw_unfilled_stage( draw ); 57 draw->pipeline.twoside = draw_twoside_stage( draw ); 58 draw->pipeline.offset = draw_offset_stage( draw ); 59 draw->pipeline.clip = draw_clip_stage( draw ); 60 draw->pipeline.flatshade = draw_flatshade_stage( draw ); 61 draw->pipeline.cull = draw_cull_stage( draw ); 62 draw->pipeline.validate = draw_validate_stage( draw ); 63 draw->pipeline.first = draw->pipeline.validate; 64 65 if (!draw->pipeline.wide_line || 66 !draw->pipeline.wide_point || 67 !draw->pipeline.stipple || 68 !draw->pipeline.unfilled || 69 !draw->pipeline.twoside || 70 !draw->pipeline.offset || 71 !draw->pipeline.clip || 72 !draw->pipeline.flatshade || 73 !draw->pipeline.cull || 74 !draw->pipeline.validate) 75 goto fail; 76 77 78 ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 ); 79 ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 ); 80 ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 ); 81 ASSIGN_4V( draw->plane[3], 0, 1, 0, 1 ); 82 ASSIGN_4V( draw->plane[4], 0, 0, 1, 1 ); /* yes these are correct */ 83 ASSIGN_4V( draw->plane[5], 0, 0, -1, 1 ); /* mesa's a bit wonky */ 84 draw->nr_planes = 6; 85 86 /* Statically allocate maximum sized vertices for the cache - could be cleverer... 87 */ 88 { 89 char *tmp = align_malloc(VS_QUEUE_LENGTH * MAX_VERTEX_ALLOCATION, 16); 90 if (!tmp) 91 goto fail; 92 93 draw->vs.vertex_cache = tmp; 94 } 95 96 draw->shader_queue_flush = draw_vertex_shader_queue_flush; 97 98 /* these defaults are oriented toward the needs of softpipe */ 99 draw->wide_point_threshold = 1000000.0; /* infinity */ 100 draw->wide_line_threshold = 1.0; 101 draw->line_stipple = TRUE; 102 draw->point_sprite = TRUE; 103 104 draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */ 105 106 draw_set_mapped_element_buffer( draw, 0, NULL ); 107 108 tgsi_exec_machine_init(&draw->machine); 109 110 /* FIXME: give this machine thing a proper constructor: 111 */ 112 draw->machine.Inputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); 113 draw->machine.Outputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); 114 115 116 if (!draw_pt_init( draw )) 117 goto fail; 118 119 return draw; 120 121fail: 122 draw_destroy( draw ); 123 return NULL; 124} 125 126 127void draw_destroy( struct draw_context *draw ) 128{ 129 if (!draw) 130 return; 131 132 if (draw->pipeline.wide_line) 133 draw->pipeline.wide_line->destroy( draw->pipeline.wide_line ); 134 if (draw->pipeline.wide_point) 135 draw->pipeline.wide_point->destroy( draw->pipeline.wide_point ); 136 if (draw->pipeline.stipple) 137 draw->pipeline.stipple->destroy( draw->pipeline.stipple ); 138 if (draw->pipeline.unfilled) 139 draw->pipeline.unfilled->destroy( draw->pipeline.unfilled ); 140 if (draw->pipeline.twoside) 141 draw->pipeline.twoside->destroy( draw->pipeline.twoside ); 142 if (draw->pipeline.offset) 143 draw->pipeline.offset->destroy( draw->pipeline.offset ); 144 if (draw->pipeline.clip) 145 draw->pipeline.clip->destroy( draw->pipeline.clip ); 146 if (draw->pipeline.flatshade) 147 draw->pipeline.flatshade->destroy( draw->pipeline.flatshade ); 148 if (draw->pipeline.cull) 149 draw->pipeline.cull->destroy( draw->pipeline.cull ); 150 if (draw->pipeline.validate) 151 draw->pipeline.validate->destroy( draw->pipeline.validate ); 152 if (draw->pipeline.aaline) 153 draw->pipeline.aaline->destroy( draw->pipeline.aaline ); 154 if (draw->pipeline.aapoint) 155 draw->pipeline.aapoint->destroy( draw->pipeline.aapoint ); 156 if (draw->pipeline.pstipple) 157 draw->pipeline.pstipple->destroy( draw->pipeline.pstipple ); 158 if (draw->pipeline.rasterize) 159 draw->pipeline.rasterize->destroy( draw->pipeline.rasterize ); 160 161 if (draw->machine.Inputs) 162 align_free(draw->machine.Inputs); 163 if (draw->machine.Outputs) 164 align_free(draw->machine.Outputs); 165 tgsi_exec_machine_free_data(&draw->machine); 166 167 168 if (draw->vs.vertex_cache) 169 align_free( draw->vs.vertex_cache ); /* Frees all the vertices. */ 170 171 /* Not so fast -- we're just borrowing this at the moment. 172 * 173 if (draw->render) 174 draw->render->destroy( draw->render ); 175 */ 176 177 draw_pt_destroy( draw ); 178 179 FREE( draw ); 180} 181 182 183 184void draw_flush( struct draw_context *draw ) 185{ 186 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 187} 188 189 190 191/** 192 * Register new primitive rasterization/rendering state. 193 * This causes the drawing pipeline to be rebuilt. 194 */ 195void draw_set_rasterizer_state( struct draw_context *draw, 196 const struct pipe_rasterizer_state *raster ) 197{ 198 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 199 200 draw->rasterizer = raster; 201} 202 203 204/** 205 * Plug in the primitive rendering/rasterization stage (which is the last 206 * stage in the drawing pipeline). 207 * This is provided by the device driver. 208 */ 209void draw_set_rasterize_stage( struct draw_context *draw, 210 struct draw_stage *stage ) 211{ 212 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 213 214 draw->pipeline.rasterize = stage; 215} 216 217 218/** 219 * Set the draw module's clipping state. 220 */ 221void draw_set_clip_state( struct draw_context *draw, 222 const struct pipe_clip_state *clip ) 223{ 224 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 225 226 assert(clip->nr <= PIPE_MAX_CLIP_PLANES); 227 memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0])); 228 draw->nr_planes = 6 + clip->nr; 229} 230 231 232/** 233 * Set the draw module's viewport state. 234 */ 235void draw_set_viewport_state( struct draw_context *draw, 236 const struct pipe_viewport_state *viewport ) 237{ 238 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 239 draw->viewport = *viewport; /* struct copy */ 240 draw->identity_viewport = (viewport->scale[0] == 1.0f && 241 viewport->scale[1] == 1.0f && 242 viewport->scale[2] == 1.0f && 243 viewport->scale[3] == 1.0f && 244 viewport->translate[0] == 0.0f && 245 viewport->translate[1] == 0.0f && 246 viewport->translate[2] == 0.0f && 247 viewport->translate[3] == 0.0f); 248} 249 250 251 252void 253draw_set_vertex_buffers(struct draw_context *draw, 254 unsigned count, 255 const struct pipe_vertex_buffer *buffers) 256{ 257 assert(count <= PIPE_MAX_ATTRIBS); 258 259 draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ ); 260 261 memcpy(draw->vertex_buffer, buffers, count * sizeof(buffers[0])); 262 draw->nr_vertex_buffers = count; 263} 264 265 266void 267draw_set_vertex_elements(struct draw_context *draw, 268 unsigned count, 269 const struct pipe_vertex_element *elements) 270{ 271 assert(count <= PIPE_MAX_ATTRIBS); 272 273 draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ ); 274 275 memcpy(draw->vertex_element, elements, count * sizeof(elements[0])); 276 draw->nr_vertex_elements = count; 277} 278 279 280/** 281 * Tell drawing context where to find mapped vertex buffers. 282 */ 283void 284draw_set_mapped_vertex_buffer(struct draw_context *draw, 285 unsigned attr, const void *buffer) 286{ 287 draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ ); 288 draw->user.vbuffer[attr] = buffer; 289} 290 291 292void 293draw_set_mapped_constant_buffer(struct draw_context *draw, 294 const void *buffer) 295{ 296 draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ ); 297 draw->user.constants = buffer; 298} 299 300 301/** 302 * Tells the draw module to draw points with triangles if their size 303 * is greater than this threshold. 304 */ 305void 306draw_wide_point_threshold(struct draw_context *draw, float threshold) 307{ 308 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 309 draw->wide_point_threshold = threshold; 310} 311 312 313/** 314 * Tells the draw module to draw lines with triangles if their width 315 * is greater than this threshold. 316 */ 317void 318draw_wide_line_threshold(struct draw_context *draw, float threshold) 319{ 320 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 321 draw->wide_line_threshold = threshold; 322} 323 324 325/** 326 * Tells the draw module whether or not to implement line stipple. 327 */ 328void 329draw_enable_line_stipple(struct draw_context *draw, boolean enable) 330{ 331 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 332 draw->line_stipple = enable; 333} 334 335 336/** 337 * Tells draw module whether to convert points to quads for sprite mode. 338 */ 339void 340draw_enable_point_sprites(struct draw_context *draw, boolean enable) 341{ 342 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 343 draw->point_sprite = enable; 344} 345 346 347/** 348 * Ask the draw module for the location/slot of the given vertex attribute in 349 * a post-transformed vertex. 350 * 351 * With this function, drivers that use the draw module should have no reason 352 * to track the current vertex shader. 353 * 354 * Note that the draw module may sometimes generate vertices with extra 355 * attributes (such as texcoords for AA lines). The driver can call this 356 * function to find those attributes. 357 * 358 * Zero is returned if the attribute is not found since this is 359 * a don't care / undefined situtation. Returning -1 would be a bit more 360 * work for the drivers. 361 */ 362int 363draw_find_vs_output(struct draw_context *draw, 364 uint semantic_name, uint semantic_index) 365{ 366 const struct draw_vertex_shader *vs = draw->vertex_shader; 367 uint i; 368 for (i = 0; i < vs->info.num_outputs; i++) { 369 if (vs->info.output_semantic_name[i] == semantic_name && 370 vs->info.output_semantic_index[i] == semantic_index) 371 return i; 372 } 373 374 /* XXX there may be more than one extra vertex attrib. 375 * For example, simulated gl_FragCoord and gl_PointCoord. 376 */ 377 if (draw->extra_vp_outputs.semantic_name == semantic_name && 378 draw->extra_vp_outputs.semantic_index == semantic_index) { 379 return draw->extra_vp_outputs.slot; 380 } 381 return 0; 382} 383 384 385/** 386 * Return number of vertex shader outputs. 387 */ 388uint 389draw_num_vs_outputs(struct draw_context *draw) 390{ 391 uint count = draw->vertex_shader->info.num_outputs; 392 if (draw->extra_vp_outputs.slot > 0) 393 count++; 394 return count; 395} 396 397 398/** 399 * Allocate space for temporary post-transform vertices, such as for clipping. 400 */ 401void draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr ) 402{ 403 assert(!stage->tmp); 404 405 stage->nr_tmps = nr; 406 407 if (nr) { 408 ubyte *store = (ubyte *) MALLOC( MAX_VERTEX_SIZE * nr ); 409 unsigned i; 410 411 stage->tmp = (struct vertex_header **) MALLOC( sizeof(struct vertex_header *) * nr ); 412 413 for (i = 0; i < nr; i++) 414 stage->tmp[i] = (struct vertex_header *)(store + i * MAX_VERTEX_SIZE); 415 } 416} 417 418 419void draw_free_temp_verts( struct draw_stage *stage ) 420{ 421 if (stage->tmp) { 422 FREE( stage->tmp[0] ); 423 FREE( stage->tmp ); 424 stage->tmp = NULL; 425 } 426} 427 428 429boolean draw_use_sse(struct draw_context *draw) 430{ 431 return (boolean) draw->use_sse; 432} 433 434 435void draw_reset_vertex_ids(struct draw_context *draw) 436{ 437 struct draw_stage *stage = draw->pipeline.first; 438 439 while (stage) { 440 unsigned i; 441 442 for (i = 0; i < stage->nr_tmps; i++) 443 stage->tmp[i]->vertex_id = UNDEFINED_VERTEX_ID; 444 445 stage = stage->next; 446 } 447 448 draw_pt_reset_vertex_ids(draw); 449} 450 451 452void draw_set_render( struct draw_context *draw, 453 struct vbuf_render *render ) 454{ 455 draw->render = render; 456} 457 458void draw_set_edgeflags( struct draw_context *draw, 459 const unsigned *edgeflag ) 460{ 461 draw->user.edgeflag = edgeflag; 462} 463 464 465boolean draw_get_edgeflag( struct draw_context *draw, 466 unsigned idx ) 467{ 468 if (draw->user.edgeflag) 469 return (draw->user.edgeflag[idx/32] & (1 << (idx%32))) != 0; 470 else 471 return 1; 472} 473 474 475/** 476 * Tell the drawing context about the index/element buffer to use 477 * (ala glDrawElements) 478 * If no element buffer is to be used (i.e. glDrawArrays) then this 479 * should be called with eltSize=0 and elements=NULL. 480 * 481 * \param draw the drawing context 482 * \param eltSize size of each element (1, 2 or 4 bytes) 483 * \param elements the element buffer ptr 484 */ 485void 486draw_set_mapped_element_buffer( struct draw_context *draw, 487 unsigned eltSize, void *elements ) 488{ 489 draw->user.elts = elements; 490 draw->user.eltSize = eltSize; 491} 492