draw_context.c revision 3c9aa3a7b12cfe178c14fea93cfb64a32db0b8ad
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 "util/u_cpu_detect.h"
38#include "util/u_inlines.h"
39#include "draw_context.h"
40#include "draw_vs.h"
41#include "draw_gs.h"
42
43#if HAVE_LLVM
44#include "gallivm/lp_bld_init.h"
45#include "draw_llvm.h"
46
47static boolean
48draw_get_option_use_llvm(void)
49{
50   static boolean first = TRUE;
51   static boolean value;
52   if (first) {
53      first = FALSE;
54      value = debug_get_bool_option("DRAW_USE_LLVM", TRUE);
55
56#ifdef PIPE_ARCH_X86
57      util_cpu_detect();
58      /* require SSE2 due to LLVM PR6960. */
59      if (!util_cpu_caps.has_sse2)
60         value = FALSE;
61#endif
62   }
63   return value;
64}
65#endif
66
67
68
69/**
70 * Create new draw module context.
71 */
72struct draw_context *
73draw_create(struct pipe_context *pipe)
74{
75   return draw_create_gallivm(pipe, NULL);
76}
77
78
79
80/**
81 * Create new draw module context with gallivm state for LLVM JIT.
82 */
83struct draw_context *
84draw_create_gallivm(struct pipe_context *pipe, struct gallivm_state *gallivm)
85{
86   struct draw_context *draw = CALLOC_STRUCT( draw_context );
87   if (draw == NULL)
88      goto fail;
89
90#if HAVE_LLVM
91   if (draw_get_option_use_llvm() && gallivm) {
92      draw->llvm = draw_llvm_create(draw, gallivm);
93   }
94#endif
95
96   if (!draw_init(draw))
97      goto fail;
98
99   draw->pipe = pipe;
100
101   return draw;
102
103fail:
104   draw_destroy( draw );
105   return NULL;
106}
107
108
109
110boolean draw_init(struct draw_context *draw)
111{
112   /*
113    * Note that several functions compute the clipmask of the predefined
114    * formats with hardcoded formulas instead of using these. So modifications
115    * here must be reflected there too.
116    */
117
118   ASSIGN_4V( draw->plane[0], -1,  0,  0, 1 );
119   ASSIGN_4V( draw->plane[1],  1,  0,  0, 1 );
120   ASSIGN_4V( draw->plane[2],  0, -1,  0, 1 );
121   ASSIGN_4V( draw->plane[3],  0,  1,  0, 1 );
122   ASSIGN_4V( draw->plane[4],  0,  0,  1, 1 ); /* yes these are correct */
123   ASSIGN_4V( draw->plane[5],  0,  0, -1, 1 ); /* mesa's a bit wonky */
124   draw->nr_planes = 6;
125   draw->clip_xy = 1;
126   draw->clip_z = 1;
127
128
129   draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */
130
131
132   if (!draw_pipeline_init( draw ))
133      return FALSE;
134
135   if (!draw_pt_init( draw ))
136      return FALSE;
137
138   if (!draw_vs_init( draw ))
139      return FALSE;
140
141   if (!draw_gs_init( draw ))
142      return FALSE;
143
144   return TRUE;
145}
146
147
148void draw_destroy( struct draw_context *draw )
149{
150   struct pipe_context *pipe;
151   int i, j;
152
153   if (!draw)
154      return;
155
156   pipe = draw->pipe;
157
158   /* free any rasterizer CSOs that we may have created.
159    */
160   for (i = 0; i < 2; i++) {
161      for (j = 0; j < 2; j++) {
162         if (draw->rasterizer_no_cull[i][j]) {
163            pipe->delete_rasterizer_state(pipe, draw->rasterizer_no_cull[i][j]);
164         }
165      }
166   }
167
168   for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
169      pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL);
170   }
171
172   /* Not so fast -- we're just borrowing this at the moment.
173    *
174   if (draw->render)
175      draw->render->destroy( draw->render );
176   */
177
178   draw_pipeline_destroy( draw );
179   draw_pt_destroy( draw );
180   draw_vs_destroy( draw );
181   draw_gs_destroy( draw );
182#ifdef HAVE_LLVM
183   if(draw->llvm)
184      draw_llvm_destroy( draw->llvm );
185#endif
186
187   FREE( draw );
188}
189
190
191
192void draw_flush( struct draw_context *draw )
193{
194   draw_do_flush( draw, DRAW_FLUSH_BACKEND );
195}
196
197
198/**
199 * Specify the Minimum Resolvable Depth factor for polygon offset.
200 * This factor potentially depends on the number of Z buffer bits,
201 * the rasterization algorithm and the arithmetic performed on Z
202 * values between vertex shading and rasterization.  It will vary
203 * from one driver to another.
204 */
205void draw_set_mrd(struct draw_context *draw, double mrd)
206{
207   draw->mrd = mrd;
208}
209
210
211static void update_clip_flags( struct draw_context *draw )
212{
213   draw->clip_xy = !draw->driver.bypass_clip_xy;
214   draw->clip_z = (!draw->driver.bypass_clip_z &&
215                   !draw->depth_clamp);
216   draw->clip_user = (draw->nr_planes > 6);
217}
218
219/**
220 * Register new primitive rasterization/rendering state.
221 * This causes the drawing pipeline to be rebuilt.
222 */
223void draw_set_rasterizer_state( struct draw_context *draw,
224                                const struct pipe_rasterizer_state *raster,
225                                void *rast_handle )
226{
227   if (!draw->suspend_flushing) {
228      draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
229
230      draw->rasterizer = raster;
231      draw->rast_handle = rast_handle;
232
233  }
234}
235
236/* With a little more work, llvmpipe will be able to turn this off and
237 * do its own x/y clipping.
238 *
239 * Some hardware can turn off clipping altogether - in particular any
240 * hardware with a TNL unit can do its own clipping, even if it is
241 * relying on the draw module for some other reason.
242 */
243void draw_set_driver_clipping( struct draw_context *draw,
244                               boolean bypass_clip_xy,
245                               boolean bypass_clip_z )
246{
247   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
248
249   draw->driver.bypass_clip_xy = bypass_clip_xy;
250   draw->driver.bypass_clip_z = bypass_clip_z;
251   update_clip_flags(draw);
252}
253
254
255/**
256 * Plug in the primitive rendering/rasterization stage (which is the last
257 * stage in the drawing pipeline).
258 * This is provided by the device driver.
259 */
260void draw_set_rasterize_stage( struct draw_context *draw,
261                               struct draw_stage *stage )
262{
263   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
264
265   draw->pipeline.rasterize = stage;
266}
267
268
269/**
270 * Set the draw module's clipping state.
271 */
272void draw_set_clip_state( struct draw_context *draw,
273                          const struct pipe_clip_state *clip )
274{
275   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
276
277   assert(clip->nr <= PIPE_MAX_CLIP_PLANES);
278   memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0]));
279   draw->nr_planes = 6 + clip->nr;
280   draw->depth_clamp = clip->depth_clamp;
281
282   update_clip_flags(draw);
283}
284
285
286/**
287 * Set the draw module's viewport state.
288 */
289void draw_set_viewport_state( struct draw_context *draw,
290                              const struct pipe_viewport_state *viewport )
291{
292   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
293   draw->viewport = *viewport; /* struct copy */
294   draw->identity_viewport = (viewport->scale[0] == 1.0f &&
295                              viewport->scale[1] == 1.0f &&
296                              viewport->scale[2] == 1.0f &&
297                              viewport->scale[3] == 1.0f &&
298                              viewport->translate[0] == 0.0f &&
299                              viewport->translate[1] == 0.0f &&
300                              viewport->translate[2] == 0.0f &&
301                              viewport->translate[3] == 0.0f);
302
303   draw_vs_set_viewport( draw, viewport );
304}
305
306
307
308void
309draw_set_vertex_buffers(struct draw_context *draw,
310                        unsigned count,
311                        const struct pipe_vertex_buffer *buffers)
312{
313   assert(count <= PIPE_MAX_ATTRIBS);
314
315   util_copy_vertex_buffers(draw->pt.vertex_buffer,
316                            &draw->pt.nr_vertex_buffers,
317                            buffers, count);
318}
319
320
321void
322draw_set_vertex_elements(struct draw_context *draw,
323                         unsigned count,
324                         const struct pipe_vertex_element *elements)
325{
326   assert(count <= PIPE_MAX_ATTRIBS);
327
328   memcpy(draw->pt.vertex_element, elements, count * sizeof(elements[0]));
329   draw->pt.nr_vertex_elements = count;
330}
331
332
333/**
334 * Tell drawing context where to find mapped vertex buffers.
335 */
336void
337draw_set_mapped_vertex_buffer(struct draw_context *draw,
338                              unsigned attr, const void *buffer)
339{
340   draw->pt.user.vbuffer[attr] = buffer;
341}
342
343
344void
345draw_set_mapped_constant_buffer(struct draw_context *draw,
346                                unsigned shader_type,
347                                unsigned slot,
348                                const void *buffer,
349                                unsigned size )
350{
351   debug_assert(shader_type == PIPE_SHADER_VERTEX ||
352                shader_type == PIPE_SHADER_GEOMETRY);
353   debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS);
354
355   switch (shader_type) {
356   case PIPE_SHADER_VERTEX:
357      draw->pt.user.vs_constants[slot] = buffer;
358      draw->pt.user.vs_constants_size[slot] = size;
359      draw->pt.user.planes = (float (*) [12][4]) &(draw->plane[0]);
360      draw_vs_set_constants(draw, slot, buffer, size);
361      break;
362   case PIPE_SHADER_GEOMETRY:
363      draw->pt.user.gs_constants[slot] = buffer;
364      draw->pt.user.gs_constants_size[slot] = size;
365      draw_gs_set_constants(draw, slot, buffer, size);
366      break;
367   default:
368      assert(0 && "invalid shader type in draw_set_mapped_constant_buffer");
369   }
370}
371
372
373/**
374 * Tells the draw module to draw points with triangles if their size
375 * is greater than this threshold.
376 */
377void
378draw_wide_point_threshold(struct draw_context *draw, float threshold)
379{
380   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
381   draw->pipeline.wide_point_threshold = threshold;
382}
383
384
385/**
386 * Should the draw module handle point->quad conversion for drawing sprites?
387 */
388void
389draw_wide_point_sprites(struct draw_context *draw, boolean draw_sprite)
390{
391   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
392   draw->pipeline.wide_point_sprites = draw_sprite;
393}
394
395
396/**
397 * Tells the draw module to draw lines with triangles if their width
398 * is greater than this threshold.
399 */
400void
401draw_wide_line_threshold(struct draw_context *draw, float threshold)
402{
403   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
404   draw->pipeline.wide_line_threshold = threshold;
405}
406
407
408/**
409 * Tells the draw module whether or not to implement line stipple.
410 */
411void
412draw_enable_line_stipple(struct draw_context *draw, boolean enable)
413{
414   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
415   draw->pipeline.line_stipple = enable;
416}
417
418
419/**
420 * Tells draw module whether to convert points to quads for sprite mode.
421 */
422void
423draw_enable_point_sprites(struct draw_context *draw, boolean enable)
424{
425   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
426   draw->pipeline.point_sprite = enable;
427}
428
429
430void
431draw_set_force_passthrough( struct draw_context *draw, boolean enable )
432{
433   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
434   draw->force_passthrough = enable;
435}
436
437
438
439/**
440 * Allocate an extra vertex/geometry shader vertex attribute.
441 * This is used by some of the optional draw module stages such
442 * as wide_point which may need to allocate additional generic/texcoord
443 * attributes.
444 */
445int
446draw_alloc_extra_vertex_attrib(struct draw_context *draw,
447                               uint semantic_name, uint semantic_index)
448{
449   const int num_outputs = draw_current_shader_outputs(draw);
450   const int n = draw->extra_shader_outputs.num;
451
452   assert(n < Elements(draw->extra_shader_outputs.semantic_name));
453
454   draw->extra_shader_outputs.semantic_name[n] = semantic_name;
455   draw->extra_shader_outputs.semantic_index[n] = semantic_index;
456   draw->extra_shader_outputs.slot[n] = num_outputs + n;
457   draw->extra_shader_outputs.num++;
458
459   return draw->extra_shader_outputs.slot[n];
460}
461
462
463/**
464 * Remove all extra vertex attributes that were allocated with
465 * draw_alloc_extra_vertex_attrib().
466 */
467void
468draw_remove_extra_vertex_attribs(struct draw_context *draw)
469{
470   draw->extra_shader_outputs.num = 0;
471}
472
473
474/**
475 * Ask the draw module for the location/slot of the given vertex attribute in
476 * a post-transformed vertex.
477 *
478 * With this function, drivers that use the draw module should have no reason
479 * to track the current vertex/geometry shader.
480 *
481 * Note that the draw module may sometimes generate vertices with extra
482 * attributes (such as texcoords for AA lines).  The driver can call this
483 * function to find those attributes.
484 *
485 * Zero is returned if the attribute is not found since this is
486 * a don't care / undefined situtation.  Returning -1 would be a bit more
487 * work for the drivers.
488 */
489int
490draw_find_shader_output(const struct draw_context *draw,
491                        uint semantic_name, uint semantic_index)
492{
493   const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
494   const struct draw_geometry_shader *gs = draw->gs.geometry_shader;
495   uint i;
496   const struct tgsi_shader_info *info = &vs->info;
497
498   if (gs)
499      info = &gs->info;
500
501   for (i = 0; i < info->num_outputs; i++) {
502      if (info->output_semantic_name[i] == semantic_name &&
503          info->output_semantic_index[i] == semantic_index)
504         return i;
505   }
506
507   /* Search the extra vertex attributes */
508   for (i = 0; i < draw->extra_shader_outputs.num; i++) {
509      if (draw->extra_shader_outputs.semantic_name[i] == semantic_name &&
510          draw->extra_shader_outputs.semantic_index[i] == semantic_index) {
511         return draw->extra_shader_outputs.slot[i];
512      }
513   }
514
515   return 0;
516}
517
518
519/**
520 * Return total number of the shader outputs.  This function is similar to
521 * draw_current_shader_outputs() but this function also counts any extra
522 * vertex/geometry output attributes that may be filled in by some draw
523 * stages (such as AA point, AA line).
524 *
525 * If geometry shader is present, its output will be returned,
526 * if not vertex shader is used.
527 */
528uint
529draw_num_shader_outputs(const struct draw_context *draw)
530{
531   uint count;
532
533   /* If a geometry shader is present, its outputs go to the
534    * driver, else the vertex shader's outputs.
535    */
536   if (draw->gs.geometry_shader)
537      count = draw->gs.geometry_shader->info.num_outputs;
538   else
539      count = draw->vs.vertex_shader->info.num_outputs;
540
541   count += draw->extra_shader_outputs.num;
542
543   return count;
544}
545
546
547/**
548 * Provide TGSI sampler objects for vertex/geometry shaders that use
549 * texture fetches.
550 * This might only be used by software drivers for the time being.
551 */
552void
553draw_texture_samplers(struct draw_context *draw,
554                      uint shader,
555                      uint num_samplers,
556                      struct tgsi_sampler **samplers)
557{
558   if (shader == PIPE_SHADER_VERTEX) {
559      draw->vs.num_samplers = num_samplers;
560      draw->vs.samplers = samplers;
561   } else {
562      debug_assert(shader == PIPE_SHADER_GEOMETRY);
563      draw->gs.num_samplers = num_samplers;
564      draw->gs.samplers = samplers;
565   }
566}
567
568
569
570
571void draw_set_render( struct draw_context *draw,
572		      struct vbuf_render *render )
573{
574   draw->render = render;
575}
576
577
578void
579draw_set_index_buffer(struct draw_context *draw,
580                      const struct pipe_index_buffer *ib)
581{
582   if (ib)
583      memcpy(&draw->pt.index_buffer, ib, sizeof(draw->pt.index_buffer));
584   else
585      memset(&draw->pt.index_buffer, 0, sizeof(draw->pt.index_buffer));
586}
587
588
589/**
590 * Tell drawing context where to find mapped index/element buffer.
591 */
592void
593draw_set_mapped_index_buffer(struct draw_context *draw,
594                             const void *elements)
595{
596    draw->pt.user.elts = elements;
597}
598
599
600/* Revamp me please:
601 */
602void draw_do_flush( struct draw_context *draw, unsigned flags )
603{
604   if (!draw->suspend_flushing)
605   {
606      assert(!draw->flushing); /* catch inadvertant recursion */
607
608      draw->flushing = TRUE;
609
610      draw_pipeline_flush( draw, flags );
611
612      draw->reduced_prim = ~0; /* is reduced_prim needed any more? */
613
614      draw->flushing = FALSE;
615   }
616}
617
618
619/**
620 * Return the number of output attributes produced by the geometry
621 * shader, if present.  If no geometry shader, return the number of
622 * outputs from the vertex shader.
623 * \sa draw_num_shader_outputs
624 */
625uint
626draw_current_shader_outputs(const struct draw_context *draw)
627{
628   if (draw->gs.geometry_shader)
629      return draw->gs.num_gs_outputs;
630   return draw->vs.num_vs_outputs;
631}
632
633
634/**
635 * Return the index of the shader output which will contain the
636 * vertex position.
637 */
638uint
639draw_current_shader_position_output(const struct draw_context *draw)
640{
641   if (draw->gs.geometry_shader)
642      return draw->gs.position_output;
643   return draw->vs.position_output;
644}
645
646
647/**
648 * Return a pointer/handle for a driver/CSO rasterizer object which
649 * disabled culling, stippling, unfilled tris, etc.
650 * This is used by some pipeline stages (such as wide_point, aa_line
651 * and aa_point) which convert points/lines into triangles.  In those
652 * cases we don't want to accidentally cull the triangles.
653 *
654 * \param scissor  should the rasterizer state enable scissoring?
655 * \param flatshade  should the rasterizer state use flat shading?
656 * \return  rasterizer CSO handle
657 */
658void *
659draw_get_rasterizer_no_cull( struct draw_context *draw,
660                             boolean scissor,
661                             boolean flatshade )
662{
663   if (!draw->rasterizer_no_cull[scissor][flatshade]) {
664      /* create now */
665      struct pipe_context *pipe = draw->pipe;
666      struct pipe_rasterizer_state rast;
667
668      memset(&rast, 0, sizeof(rast));
669      rast.scissor = scissor;
670      rast.flatshade = flatshade;
671      rast.front_ccw = 1;
672      rast.gl_rasterization_rules = draw->rasterizer->gl_rasterization_rules;
673
674      draw->rasterizer_no_cull[scissor][flatshade] =
675         pipe->create_rasterizer_state(pipe, &rast);
676   }
677   return draw->rasterizer_no_cull[scissor][flatshade];
678}
679
680void
681draw_set_mapped_so_buffers(struct draw_context *draw,
682                           void *buffers[PIPE_MAX_SO_BUFFERS],
683                           unsigned num_buffers)
684{
685   int i;
686
687   for (i = 0; i < num_buffers; ++i) {
688      draw->so.buffers[i] = buffers[i];
689   }
690   draw->so.num_buffers = num_buffers;
691}
692
693void
694draw_set_so_state(struct draw_context *draw,
695                  struct pipe_stream_output_state *state)
696{
697   memcpy(&draw->so.state,
698          state,
699          sizeof(struct pipe_stream_output_state));
700}
701
702void
703draw_set_sampler_views(struct draw_context *draw,
704                       struct pipe_sampler_view **views,
705                       unsigned num)
706{
707   unsigned i;
708
709   debug_assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
710
711   for (i = 0; i < num; ++i)
712      draw->sampler_views[i] = views[i];
713   for (i = num; i < PIPE_MAX_VERTEX_SAMPLERS; ++i)
714      draw->sampler_views[i] = NULL;
715
716   draw->num_sampler_views = num;
717}
718
719void
720draw_set_samplers(struct draw_context *draw,
721                  struct pipe_sampler_state **samplers,
722                  unsigned num)
723{
724   unsigned i;
725
726   debug_assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
727
728   for (i = 0; i < num; ++i)
729      draw->samplers[i] = samplers[i];
730   for (i = num; i < PIPE_MAX_VERTEX_SAMPLERS; ++i)
731      draw->samplers[i] = NULL;
732
733   draw->num_samplers = num;
734
735#ifdef HAVE_LLVM
736   if (draw->llvm)
737      draw_llvm_set_sampler_state(draw);
738#endif
739}
740
741void
742draw_set_mapped_texture(struct draw_context *draw,
743                        unsigned sampler_idx,
744                        uint32_t width, uint32_t height, uint32_t depth,
745                        uint32_t last_level,
746                        uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS],
747                        uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS],
748                        const void *data[PIPE_MAX_TEXTURE_LEVELS])
749{
750#ifdef HAVE_LLVM
751   if(draw->llvm)
752      draw_llvm_set_mapped_texture(draw,
753                                sampler_idx,
754                                width, height, depth, last_level,
755                                row_stride, img_stride, data);
756#endif
757}
758