draw_context.c revision 1774b177b858f9f87d00e54b0bf00e9634e375e9
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_private.h" 37 38 39 40struct draw_context *draw_create( void ) 41{ 42 struct draw_context *draw = CALLOC_STRUCT( draw_context ); 43 44#if defined(__i386__) || defined(__386__) 45 draw->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL; 46#else 47 draw->use_sse = FALSE; 48#endif 49 50 /* create pipeline stages */ 51 draw->pipeline.wide = draw_wide_stage( draw ); 52 draw->pipeline.stipple = draw_stipple_stage( draw ); 53 draw->pipeline.unfilled = draw_unfilled_stage( draw ); 54 draw->pipeline.twoside = draw_twoside_stage( draw ); 55 draw->pipeline.offset = draw_offset_stage( draw ); 56 draw->pipeline.clip = draw_clip_stage( draw ); 57 draw->pipeline.flatshade = draw_flatshade_stage( draw ); 58 draw->pipeline.cull = draw_cull_stage( draw ); 59 draw->pipeline.validate = draw_validate_stage( draw ); 60 draw->pipeline.first = draw->pipeline.validate; 61 62 ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 ); 63 ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 ); 64 ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 ); 65 ASSIGN_4V( draw->plane[3], 0, 1, 0, 1 ); 66 ASSIGN_4V( draw->plane[4], 0, 0, 1, 1 ); /* yes these are correct */ 67 ASSIGN_4V( draw->plane[5], 0, 0, -1, 1 ); /* mesa's a bit wonky */ 68 draw->nr_planes = 6; 69 70 /* Statically allocate maximum sized vertices for the cache - could be cleverer... 71 */ 72 { 73 uint i; 74 const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f; 75 char *tmp = align_malloc(Elements(draw->vs.queue) * size, 16); 76 77 for (i = 0; i < Elements(draw->vs.queue); i++) 78 draw->vs.queue[i].vertex = (struct vertex_header *)(tmp + i * size); 79 } 80 81 draw->shader_queue_flush = draw_vertex_shader_queue_flush; 82 83 draw->wide_point_threshold = 1000000.0; /* infinity */ 84 draw->convert_wide_lines = TRUE; 85 86 draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */ 87 88 draw_vertex_cache_invalidate( draw ); 89 draw_set_mapped_element_buffer( draw, 0, NULL ); 90 91 return draw; 92} 93 94 95void draw_destroy( struct draw_context *draw ) 96{ 97 draw->pipeline.wide->destroy( draw->pipeline.wide ); 98 draw->pipeline.stipple->destroy( draw->pipeline.stipple ); 99 draw->pipeline.unfilled->destroy( draw->pipeline.unfilled ); 100 draw->pipeline.twoside->destroy( draw->pipeline.twoside ); 101 draw->pipeline.offset->destroy( draw->pipeline.offset ); 102 draw->pipeline.clip->destroy( draw->pipeline.clip ); 103 draw->pipeline.flatshade->destroy( draw->pipeline.flatshade ); 104 draw->pipeline.cull->destroy( draw->pipeline.cull ); 105 draw->pipeline.validate->destroy( draw->pipeline.validate ); 106 if (draw->pipeline.aaline) 107 draw->pipeline.aaline->destroy( draw->pipeline.aaline ); 108 if (draw->pipeline.aapoint) 109 draw->pipeline.aapoint->destroy( draw->pipeline.aapoint ); 110 if (draw->pipeline.rasterize) 111 draw->pipeline.rasterize->destroy( draw->pipeline.rasterize ); 112 tgsi_exec_machine_free_data(&draw->machine); 113 align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */ 114 FREE( draw ); 115} 116 117 118 119void draw_flush( struct draw_context *draw ) 120{ 121 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 122} 123 124 125 126/** 127 * Register new primitive rasterization/rendering state. 128 * This causes the drawing pipeline to be rebuilt. 129 */ 130void draw_set_rasterizer_state( struct draw_context *draw, 131 const struct pipe_rasterizer_state *raster ) 132{ 133 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 134 135 draw->rasterizer = raster; 136} 137 138 139/** 140 * Plug in the primitive rendering/rasterization stage (which is the last 141 * stage in the drawing pipeline). 142 * This is provided by the device driver. 143 */ 144void draw_set_rasterize_stage( struct draw_context *draw, 145 struct draw_stage *stage ) 146{ 147 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 148 149 draw->pipeline.rasterize = stage; 150} 151 152 153/** 154 * Set the draw module's clipping state. 155 */ 156void draw_set_clip_state( struct draw_context *draw, 157 const struct pipe_clip_state *clip ) 158{ 159 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 160 161 assert(clip->nr <= PIPE_MAX_CLIP_PLANES); 162 memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0])); 163 draw->nr_planes = 6 + clip->nr; 164} 165 166 167/** 168 * Set the draw module's viewport state. 169 */ 170void draw_set_viewport_state( struct draw_context *draw, 171 const struct pipe_viewport_state *viewport ) 172{ 173 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 174 draw->viewport = *viewport; /* struct copy */ 175} 176 177 178 179void 180draw_set_vertex_buffer(struct draw_context *draw, 181 unsigned attr, 182 const struct pipe_vertex_buffer *buffer) 183{ 184 draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ ); 185 assert(attr < PIPE_ATTRIB_MAX); 186 draw->vertex_buffer[attr] = *buffer; 187} 188 189 190void 191draw_set_vertex_element(struct draw_context *draw, 192 unsigned attr, 193 const struct pipe_vertex_element *element) 194{ 195 draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ ); 196 assert(attr < PIPE_ATTRIB_MAX); 197 draw->vertex_element[attr] = *element; 198} 199 200 201/** 202 * Tell drawing context where to find mapped vertex buffers. 203 */ 204void 205draw_set_mapped_vertex_buffer(struct draw_context *draw, 206 unsigned attr, const void *buffer) 207{ 208 draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ ); 209 draw->user.vbuffer[attr] = buffer; 210} 211 212 213void 214draw_set_mapped_constant_buffer(struct draw_context *draw, 215 const void *buffer) 216{ 217 draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ ); 218 draw->user.constants = buffer; 219} 220 221 222/** 223 * Tells the draw module to draw points with triangles if their size 224 * is greater than this threshold. 225 */ 226void 227draw_wide_point_threshold(struct draw_context *draw, float threshold) 228{ 229 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 230 draw->wide_point_threshold = threshold; 231} 232 233 234/** 235 * Tells the draw module whether to convert wide lines (width != 1) 236 * into triangles. 237 */ 238void 239draw_convert_wide_lines(struct draw_context *draw, boolean enable) 240{ 241 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 242 draw->convert_wide_lines = enable; 243} 244 245 246/** 247 * Ask the draw module for the location/slot of the given vertex attribute in 248 * a post-transformed vertex. 249 * 250 * With this function, drivers that use the draw module should have no reason 251 * to track the current vertex shader. 252 * 253 * Note that the draw module may sometimes generate vertices with extra 254 * attributes (such as texcoords for AA lines). The driver can call this 255 * function to find those attributes. 256 * 257 * Zero is returned if the attribute is not found since this is 258 * a don't care / undefined situtation. Returning -1 would be a bit more 259 * work for the drivers. 260 */ 261int 262draw_find_vs_output(struct draw_context *draw, 263 uint semantic_name, uint semantic_index) 264{ 265 const struct draw_vertex_shader *vs = draw->vertex_shader; 266 uint i; 267 for (i = 0; i < vs->info.num_outputs; i++) { 268 if (vs->info.output_semantic_name[i] == semantic_name && 269 vs->info.output_semantic_index[i] == semantic_index) 270 return i; 271 } 272 273 /* XXX there may be more than one extra vertex attrib. 274 * For example, simulated gl_FragCoord and gl_PointCoord. 275 */ 276 if (draw->extra_vp_outputs.semantic_name == semantic_name && 277 draw->extra_vp_outputs.semantic_index == semantic_index) { 278 return draw->extra_vp_outputs.slot; 279 } 280 return 0; 281} 282 283 284/** 285 * Return number of vertex shader outputs. 286 */ 287uint 288draw_num_vs_outputs(struct draw_context *draw) 289{ 290 uint count = draw->vertex_shader->info.num_outputs; 291 if (draw->extra_vp_outputs.slot >= 0) 292 count++; 293 return count; 294} 295 296 297/** 298 * Allocate space for temporary post-transform vertices, such as for clipping. 299 */ 300void draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr ) 301{ 302 assert(!stage->tmp); 303 304 stage->nr_tmps = nr; 305 306 if (nr) { 307 ubyte *store = (ubyte *) MALLOC( MAX_VERTEX_SIZE * nr ); 308 unsigned i; 309 310 stage->tmp = (struct vertex_header **) MALLOC( sizeof(struct vertex_header *) * nr ); 311 312 for (i = 0; i < nr; i++) 313 stage->tmp[i] = (struct vertex_header *)(store + i * MAX_VERTEX_SIZE); 314 } 315} 316 317 318void draw_free_temp_verts( struct draw_stage *stage ) 319{ 320 if (stage->tmp) { 321 FREE( stage->tmp[0] ); 322 FREE( stage->tmp ); 323 stage->tmp = NULL; 324 } 325} 326 327 328boolean draw_use_sse(struct draw_context *draw) 329{ 330 return (boolean) draw->use_sse; 331} 332 333 334void draw_reset_vertex_ids(struct draw_context *draw) 335{ 336 struct draw_stage *stage = draw->pipeline.first; 337 338 while (stage) { 339 unsigned i; 340 341 for (i = 0; i < stage->nr_tmps; i++) 342 stage->tmp[i]->vertex_id = UNDEFINED_VERTEX_ID; 343 344 stage = stage->next; 345 } 346 347 draw_vertex_cache_reset_vertex_ids(draw); 348} 349