draw_context.c revision 0bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72c
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_context.h" 35#include "util/u_memory.h" 36#include "util/u_math.h" 37#include "draw_context.h" 38#include "draw_vs.h" 39#include "draw_gs.h" 40 41#if HAVE_LLVM 42#include "gallivm/lp_bld_init.h" 43#endif 44 45struct draw_context *draw_create( struct pipe_context *pipe ) 46{ 47 struct draw_context *draw = CALLOC_STRUCT( draw_context ); 48 if (draw == NULL) 49 goto fail; 50 51#if HAVE_LLVM 52 lp_build_init(); 53 assert(lp_build_engine); 54 draw->engine = lp_build_engine; 55#endif 56 57 if (!draw_init(draw)) 58 goto fail; 59 60 draw->pipe = pipe; 61 62 return draw; 63 64fail: 65 draw_destroy( draw ); 66 return NULL; 67} 68 69boolean draw_init(struct draw_context *draw) 70{ 71 /* 72 * Note that several functions compute the clipmask of the predefined 73 * formats with hardcoded formulas instead of using these. So modifications 74 * here must be reflected there too. 75 */ 76 77 ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 ); 78 ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 ); 79 ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 ); 80 ASSIGN_4V( draw->plane[3], 0, 1, 0, 1 ); 81 ASSIGN_4V( draw->plane[4], 0, 0, 1, 1 ); /* yes these are correct */ 82 ASSIGN_4V( draw->plane[5], 0, 0, -1, 1 ); /* mesa's a bit wonky */ 83 draw->nr_planes = 6; 84 85 86 draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */ 87 88 89 if (!draw_pipeline_init( draw )) 90 return FALSE; 91 92 if (!draw_pt_init( draw )) 93 return FALSE; 94 95 if (!draw_vs_init( draw )) 96 return FALSE; 97 98 if (!draw_gs_init( draw )) 99 return FALSE; 100 101 return TRUE; 102} 103 104 105void draw_destroy( struct draw_context *draw ) 106{ 107 struct pipe_context *pipe; 108 int i, j; 109 110 if (!draw) 111 return; 112 113 pipe = draw->pipe; 114 115 /* free any rasterizer CSOs that we may have created. 116 */ 117 for (i = 0; i < 2; i++) { 118 for (j = 0; j < 2; j++) { 119 if (draw->rasterizer_no_cull[i][j]) { 120 pipe->delete_rasterizer_state(pipe, draw->rasterizer_no_cull[i][j]); 121 } 122 } 123 } 124 125 /* Not so fast -- we're just borrowing this at the moment. 126 * 127 if (draw->render) 128 draw->render->destroy( draw->render ); 129 */ 130 131 draw_pipeline_destroy( draw ); 132 draw_pt_destroy( draw ); 133 draw_vs_destroy( draw ); 134 draw_gs_destroy( draw ); 135 136 FREE( draw ); 137} 138 139 140 141void draw_flush( struct draw_context *draw ) 142{ 143 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 144} 145 146 147/** 148 * Specify the Minimum Resolvable Depth factor for polygon offset. 149 * This factor potentially depends on the number of Z buffer bits, 150 * the rasterization algorithm and the arithmetic performed on Z 151 * values between vertex shading and rasterization. It will vary 152 * from one driver to another. 153 */ 154void draw_set_mrd(struct draw_context *draw, double mrd) 155{ 156 draw->mrd = mrd; 157} 158 159 160/** 161 * Register new primitive rasterization/rendering state. 162 * This causes the drawing pipeline to be rebuilt. 163 */ 164void draw_set_rasterizer_state( struct draw_context *draw, 165 const struct pipe_rasterizer_state *raster, 166 void *rast_handle ) 167{ 168 if (!draw->suspend_flushing) { 169 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 170 171 draw->rasterizer = raster; 172 draw->rast_handle = rast_handle; 173 174 draw->bypass_clipping = draw->driver.bypass_clipping; 175 } 176} 177 178 179void draw_set_driver_clipping( struct draw_context *draw, 180 boolean bypass_clipping ) 181{ 182 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 183 184 draw->driver.bypass_clipping = bypass_clipping; 185 draw->bypass_clipping = draw->driver.bypass_clipping; 186} 187 188 189/** 190 * Plug in the primitive rendering/rasterization stage (which is the last 191 * stage in the drawing pipeline). 192 * This is provided by the device driver. 193 */ 194void draw_set_rasterize_stage( struct draw_context *draw, 195 struct draw_stage *stage ) 196{ 197 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 198 199 draw->pipeline.rasterize = stage; 200} 201 202 203/** 204 * Set the draw module's clipping state. 205 */ 206void draw_set_clip_state( struct draw_context *draw, 207 const struct pipe_clip_state *clip ) 208{ 209 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 210 211 assert(clip->nr <= PIPE_MAX_CLIP_PLANES); 212 memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0])); 213 draw->nr_planes = 6 + clip->nr; 214} 215 216 217/** 218 * Set the draw module's viewport state. 219 */ 220void draw_set_viewport_state( struct draw_context *draw, 221 const struct pipe_viewport_state *viewport ) 222{ 223 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 224 draw->viewport = *viewport; /* struct copy */ 225 draw->identity_viewport = (viewport->scale[0] == 1.0f && 226 viewport->scale[1] == 1.0f && 227 viewport->scale[2] == 1.0f && 228 viewport->scale[3] == 1.0f && 229 viewport->translate[0] == 0.0f && 230 viewport->translate[1] == 0.0f && 231 viewport->translate[2] == 0.0f && 232 viewport->translate[3] == 0.0f); 233 234 draw_vs_set_viewport( draw, viewport ); 235} 236 237 238 239void 240draw_set_vertex_buffers(struct draw_context *draw, 241 unsigned count, 242 const struct pipe_vertex_buffer *buffers) 243{ 244 assert(count <= PIPE_MAX_ATTRIBS); 245 246 memcpy(draw->pt.vertex_buffer, buffers, count * sizeof(buffers[0])); 247 draw->pt.nr_vertex_buffers = count; 248} 249 250 251void 252draw_set_vertex_elements(struct draw_context *draw, 253 unsigned count, 254 const struct pipe_vertex_element *elements) 255{ 256 assert(count <= PIPE_MAX_ATTRIBS); 257 258 memcpy(draw->pt.vertex_element, elements, count * sizeof(elements[0])); 259 draw->pt.nr_vertex_elements = count; 260} 261 262 263/** 264 * Tell drawing context where to find mapped vertex buffers. 265 */ 266void 267draw_set_mapped_vertex_buffer(struct draw_context *draw, 268 unsigned attr, const void *buffer) 269{ 270 draw->pt.user.vbuffer[attr] = buffer; 271} 272 273 274void 275draw_set_mapped_constant_buffer(struct draw_context *draw, 276 unsigned shader_type, 277 unsigned slot, 278 const void *buffer, 279 unsigned size ) 280{ 281 debug_assert(shader_type == PIPE_SHADER_VERTEX || 282 shader_type == PIPE_SHADER_GEOMETRY); 283 debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS); 284 285 if (shader_type == PIPE_SHADER_VERTEX) { 286 draw->pt.user.vs_constants[slot] = buffer; 287 draw_vs_set_constants(draw, slot, buffer, size); 288 } else if (shader_type == PIPE_SHADER_GEOMETRY) { 289 draw->pt.user.gs_constants[slot] = buffer; 290 draw_gs_set_constants(draw, slot, buffer, size); 291 } 292} 293 294 295/** 296 * Tells the draw module to draw points with triangles if their size 297 * is greater than this threshold. 298 */ 299void 300draw_wide_point_threshold(struct draw_context *draw, float threshold) 301{ 302 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 303 draw->pipeline.wide_point_threshold = threshold; 304} 305 306 307/** 308 * Should the draw module handle point->quad conversion for drawing sprites? 309 */ 310void 311draw_wide_point_sprites(struct draw_context *draw, boolean draw_sprite) 312{ 313 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 314 draw->pipeline.wide_point_sprites = draw_sprite; 315} 316 317 318/** 319 * Tells the draw module to draw lines with triangles if their width 320 * is greater than this threshold. 321 */ 322void 323draw_wide_line_threshold(struct draw_context *draw, float threshold) 324{ 325 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 326 draw->pipeline.wide_line_threshold = threshold; 327} 328 329 330/** 331 * Tells the draw module whether or not to implement line stipple. 332 */ 333void 334draw_enable_line_stipple(struct draw_context *draw, boolean enable) 335{ 336 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 337 draw->pipeline.line_stipple = enable; 338} 339 340 341/** 342 * Tells draw module whether to convert points to quads for sprite mode. 343 */ 344void 345draw_enable_point_sprites(struct draw_context *draw, boolean enable) 346{ 347 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 348 draw->pipeline.point_sprite = enable; 349} 350 351 352void 353draw_set_force_passthrough( struct draw_context *draw, boolean enable ) 354{ 355 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 356 draw->force_passthrough = enable; 357} 358 359 360/** 361 * Ask the draw module for the location/slot of the given vertex attribute in 362 * a post-transformed vertex. 363 * 364 * With this function, drivers that use the draw module should have no reason 365 * to track the current vertex/geometry shader. 366 * 367 * Note that the draw module may sometimes generate vertices with extra 368 * attributes (such as texcoords for AA lines). The driver can call this 369 * function to find those attributes. 370 * 371 * Zero is returned if the attribute is not found since this is 372 * a don't care / undefined situtation. Returning -1 would be a bit more 373 * work for the drivers. 374 */ 375int 376draw_find_shader_output(const struct draw_context *draw, 377 uint semantic_name, uint semantic_index) 378{ 379 const struct draw_vertex_shader *vs = draw->vs.vertex_shader; 380 const struct draw_geometry_shader *gs = draw->gs.geometry_shader; 381 uint i; 382 const struct tgsi_shader_info *info = &vs->info; 383 384 if (gs) 385 info = &gs->info; 386 387 for (i = 0; i < info->num_outputs; i++) { 388 if (info->output_semantic_name[i] == semantic_name && 389 info->output_semantic_index[i] == semantic_index) 390 return i; 391 } 392 393 /* XXX there may be more than one extra vertex attrib. 394 * For example, simulated gl_FragCoord and gl_PointCoord. 395 */ 396 if (draw->extra_shader_outputs.semantic_name == semantic_name && 397 draw->extra_shader_outputs.semantic_index == semantic_index) { 398 return draw->extra_shader_outputs.slot; 399 } 400 401 return 0; 402} 403 404 405/** 406 * Return total number of the shader outputs. This function is similar to 407 * draw_current_shader_outputs() but this function also counts any extra 408 * vertex/geometry output attributes that may be filled in by some draw 409 * stages (such as AA point, AA line). 410 * 411 * If geometry shader is present, its output will be returned, 412 * if not vertex shader is used. 413 */ 414uint 415draw_num_shader_outputs(const struct draw_context *draw) 416{ 417 uint count = draw->vs.vertex_shader->info.num_outputs; 418 419 /* If a geometry shader is present, its outputs go to the 420 * driver, else the vertex shader's outputs. 421 */ 422 if (draw->gs.geometry_shader) 423 count = draw->gs.geometry_shader->info.num_outputs; 424 425 if (draw->extra_shader_outputs.slot > 0) 426 count++; 427 return count; 428} 429 430 431/** 432 * Provide TGSI sampler objects for vertex/geometry shaders that use 433 * texture fetches. 434 * This might only be used by software drivers for the time being. 435 */ 436void 437draw_texture_samplers(struct draw_context *draw, 438 uint num_samplers, 439 struct tgsi_sampler **samplers) 440{ 441 draw->vs.num_samplers = num_samplers; 442 draw->vs.samplers = samplers; 443 draw->gs.num_samplers = num_samplers; 444 draw->gs.samplers = samplers; 445} 446 447 448 449 450void draw_set_render( struct draw_context *draw, 451 struct vbuf_render *render ) 452{ 453 draw->render = render; 454} 455 456 457 458/** 459 * Tell the drawing context about the index/element buffer to use 460 * (ala glDrawElements) 461 * If no element buffer is to be used (i.e. glDrawArrays) then this 462 * should be called with eltSize=0 and elements=NULL. 463 * 464 * \param draw the drawing context 465 * \param eltSize size of each element (1, 2 or 4 bytes) 466 * \param elements the element buffer ptr 467 */ 468void 469draw_set_mapped_element_buffer_range( struct draw_context *draw, 470 unsigned eltSize, 471 int eltBias, 472 unsigned min_index, 473 unsigned max_index, 474 const void *elements ) 475{ 476 draw->pt.user.elts = elements; 477 draw->pt.user.eltSize = eltSize; 478 draw->pt.user.eltBias = eltBias; 479 draw->pt.user.min_index = min_index; 480 draw->pt.user.max_index = max_index; 481} 482 483 484void 485draw_set_mapped_element_buffer( struct draw_context *draw, 486 unsigned eltSize, 487 int eltBias, 488 const void *elements ) 489{ 490 draw->pt.user.elts = elements; 491 draw->pt.user.eltSize = eltSize; 492 draw->pt.user.eltBias = eltBias; 493 draw->pt.user.min_index = 0; 494 draw->pt.user.max_index = 0xffffffff; 495} 496 497 498/* Revamp me please: 499 */ 500void draw_do_flush( struct draw_context *draw, unsigned flags ) 501{ 502 if (!draw->suspend_flushing) 503 { 504 assert(!draw->flushing); /* catch inadvertant recursion */ 505 506 draw->flushing = TRUE; 507 508 draw_pipeline_flush( draw, flags ); 509 510 draw->reduced_prim = ~0; /* is reduced_prim needed any more? */ 511 512 draw->flushing = FALSE; 513 } 514} 515 516 517/** 518 * Return the number of output attributes produced by the geometry 519 * shader, if present. If no geometry shader, return the number of 520 * outputs from the vertex shader. 521 * \sa draw_num_shader_outputs 522 */ 523uint 524draw_current_shader_outputs(const struct draw_context *draw) 525{ 526 if (draw->gs.geometry_shader) 527 return draw->gs.num_gs_outputs; 528 return draw->vs.num_vs_outputs; 529} 530 531 532/** 533 * Return the index of the shader output which will contain the 534 * vertex position. 535 */ 536uint 537draw_current_shader_position_output(const struct draw_context *draw) 538{ 539 if (draw->gs.geometry_shader) 540 return draw->gs.position_output; 541 return draw->vs.position_output; 542} 543 544 545/** 546 * Return a pointer/handle for a driver/CSO rasterizer object which 547 * disabled culling, stippling, unfilled tris, etc. 548 * This is used by some pipeline stages (such as wide_point, aa_line 549 * and aa_point) which convert points/lines into triangles. In those 550 * cases we don't want to accidentally cull the triangles. 551 * 552 * \param scissor should the rasterizer state enable scissoring? 553 * \param flatshade should the rasterizer state use flat shading? 554 * \return rasterizer CSO handle 555 */ 556void * 557draw_get_rasterizer_no_cull( struct draw_context *draw, 558 boolean scissor, 559 boolean flatshade ) 560{ 561 if (!draw->rasterizer_no_cull[scissor][flatshade]) { 562 /* create now */ 563 struct pipe_context *pipe = draw->pipe; 564 struct pipe_rasterizer_state rast; 565 566 memset(&rast, 0, sizeof(rast)); 567 rast.scissor = scissor; 568 rast.flatshade = flatshade; 569 rast.front_ccw = 1; 570 rast.gl_rasterization_rules = draw->rasterizer->gl_rasterization_rules; 571 572 draw->rasterizer_no_cull[scissor][flatshade] = 573 pipe->create_rasterizer_state(pipe, &rast); 574 } 575 return draw->rasterizer_no_cull[scissor][flatshade]; 576} 577