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