Merge remote branch 'upstream/gallium-0.2' into nouveau-gallium-0.2
[mesa.git] / src / gallium / auxiliary / draw / draw_context.c
index 3d09d9585189fe979f8cc9b62d2398f692b5ef1d..78249054f2a5e932c6eaa97c17d9f8d93bbf5422 100644 (file)
   */
 
 
-#include "pipe/p_util.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
 #include "draw_context.h"
-#include "draw_private.h"
 #include "draw_vbuf.h"
-
+#include "draw_vs.h"
+#include "draw_pt.h"
+#include "draw_pipe.h"
 
 
 struct draw_context *draw_create( void )
 {
    struct draw_context *draw = CALLOC_STRUCT( draw_context );
-
-#if defined(__i386__) || defined(__386__)
-   draw->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL;
-#else
-   draw->use_sse = FALSE;
-#endif
-
-   /* create pipeline stages */
-   draw->pipeline.wide_line  = draw_wide_line_stage( draw );
-   draw->pipeline.wide_point = draw_wide_point_stage( draw );
-   draw->pipeline.stipple   = draw_stipple_stage( draw );
-   draw->pipeline.unfilled  = draw_unfilled_stage( draw );
-   draw->pipeline.twoside   = draw_twoside_stage( draw );
-   draw->pipeline.offset    = draw_offset_stage( draw );
-   draw->pipeline.clip      = draw_clip_stage( draw );
-   draw->pipeline.flatshade = draw_flatshade_stage( draw );
-   draw->pipeline.cull      = draw_cull_stage( draw );
-   draw->pipeline.validate  = draw_validate_stage( draw );
-   draw->pipeline.first     = draw->pipeline.validate;
+   if (draw == NULL)
+      goto fail;
 
    ASSIGN_4V( draw->plane[0], -1,  0,  0, 1 );
    ASSIGN_4V( draw->plane[1],  1,  0,  0, 1 );
@@ -69,53 +54,35 @@ struct draw_context *draw_create( void )
    ASSIGN_4V( draw->plane[5],  0,  0, -1, 1 ); /* mesa's a bit wonky */
    draw->nr_planes = 6;
 
-   /* Statically allocate maximum sized vertices for the cache - could be cleverer...
-    */
-   {
-      uint i;
-      const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f;
-      char *tmp = align_malloc(Elements(draw->vs.queue) * size, 16);
 
-      for (i = 0; i < Elements(draw->vs.queue); i++)
-        draw->vs.queue[i].vertex = (struct vertex_header *)(tmp + i * size);
-   }
+   draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */
 
-   draw->shader_queue_flush = draw_vertex_shader_queue_flush;
 
-   /* these defaults are oriented toward the needs of softpipe */
-   draw->wide_point_threshold = 1000000.0; /* infinity */
-   draw->wide_line_threshold = 1.0;
-   draw->line_stipple = TRUE;
+   if (!draw_pipeline_init( draw ))
+      goto fail;
 
-   draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */
+   if (!draw_pt_init( draw ))
+      goto fail;
 
-   draw_vertex_cache_invalidate( draw );
-   draw_set_mapped_element_buffer( draw, 0, NULL );
+#ifdef PIPE_ARCH_X86
+   if (!draw_vs_init( draw ))
+      goto fail;
+#endif
 
    return draw;
+
+fail:
+   draw_destroy( draw );   
+   return NULL;
 }
 
 
 void draw_destroy( struct draw_context *draw )
 {
-   draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
-   draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
-   draw->pipeline.stipple->destroy( draw->pipeline.stipple );
-   draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
-   draw->pipeline.twoside->destroy( draw->pipeline.twoside );
-   draw->pipeline.offset->destroy( draw->pipeline.offset );
-   draw->pipeline.clip->destroy( draw->pipeline.clip );
-   draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
-   draw->pipeline.cull->destroy( draw->pipeline.cull );
-   draw->pipeline.validate->destroy( draw->pipeline.validate );
-   if (draw->pipeline.aaline)
-      draw->pipeline.aaline->destroy( draw->pipeline.aaline );
-   if (draw->pipeline.aapoint)
-      draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );
-   if (draw->pipeline.rasterize)
-      draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
-   tgsi_exec_machine_free_data(&draw->machine);
-   align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
+   if (!draw)
+      return;
+
+
 
    /* Not so fast -- we're just borrowing this at the moment.
     * 
@@ -123,6 +90,10 @@ void draw_destroy( struct draw_context *draw )
       draw->render->destroy( draw->render );
    */
 
+   draw_pipeline_destroy( draw );
+   draw_pt_destroy( draw );
+   draw_vs_destroy( draw );
+
    FREE( draw );
 }
 
@@ -145,6 +116,20 @@ void draw_set_rasterizer_state( struct draw_context *draw,
    draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
 
    draw->rasterizer = raster;
+   draw->bypass_clipping =
+      ((draw->rasterizer && draw->rasterizer->bypass_clipping) ||
+       draw->driver.bypass_clipping);
+}
+
+
+void draw_set_driver_clipping( struct draw_context *draw,
+                               boolean bypass_clipping )
+{
+   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
+   draw->driver.bypass_clipping = bypass_clipping;
+   draw->bypass_clipping = (draw->rasterizer->bypass_clipping || 
+                            draw->driver.bypass_clipping);
 }
 
 
@@ -184,29 +169,41 @@ void draw_set_viewport_state( struct draw_context *draw,
 {
    draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
    draw->viewport = *viewport; /* struct copy */
+   draw->identity_viewport = (viewport->scale[0] == 1.0f &&
+                              viewport->scale[1] == 1.0f &&
+                              viewport->scale[2] == 1.0f &&
+                              viewport->scale[3] == 1.0f &&
+                              viewport->translate[0] == 0.0f &&
+                              viewport->translate[1] == 0.0f &&
+                              viewport->translate[2] == 0.0f &&
+                              viewport->translate[3] == 0.0f);
+
+   draw_vs_set_viewport( draw, viewport );
 }
 
 
 
 void
-draw_set_vertex_buffer(struct draw_context *draw,
-                       unsigned attr,
-                       const struct pipe_vertex_buffer *buffer)
+draw_set_vertex_buffers(struct draw_context *draw,
+                        unsigned count,
+                        const struct pipe_vertex_buffer *buffers)
 {
-   draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ );
-   assert(attr < PIPE_ATTRIB_MAX);
-   draw->vertex_buffer[attr] = *buffer;
+   assert(count <= PIPE_MAX_ATTRIBS);
+
+   memcpy(draw->pt.vertex_buffer, buffers, count * sizeof(buffers[0]));
+   draw->pt.nr_vertex_buffers = count;
 }
 
 
 void
-draw_set_vertex_element(struct draw_context *draw,
-                        unsigned attr,
-                        const struct pipe_vertex_element *element)
+draw_set_vertex_elements(struct draw_context *draw,
+                         unsigned count,
+                         const struct pipe_vertex_element *elements)
 {
-   draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ );
-   assert(attr < PIPE_ATTRIB_MAX);
-   draw->vertex_element[attr] = *element;
+   assert(count <= PIPE_MAX_ATTRIBS);
+
+   memcpy(draw->pt.vertex_element, elements, count * sizeof(elements[0]));
+   draw->pt.nr_vertex_elements = count;
 }
 
 
@@ -217,17 +214,17 @@ void
 draw_set_mapped_vertex_buffer(struct draw_context *draw,
                               unsigned attr, const void *buffer)
 {
-   draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ );
-   draw->user.vbuffer[attr] = buffer;
+   draw->pt.user.vbuffer[attr] = buffer;
 }
 
 
 void
 draw_set_mapped_constant_buffer(struct draw_context *draw,
-                                const void *buffer)
+                                const void *buffer, 
+                                unsigned size )
 {
-   draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ );
-   draw->user.constants = buffer;
+   draw->pt.user.constants = buffer;
+   draw_vs_set_constants( draw, (const float (*)[4])buffer, size );
 }
 
 
@@ -239,7 +236,7 @@ void
 draw_wide_point_threshold(struct draw_context *draw, float threshold)
 {
    draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
-   draw->wide_point_threshold = threshold;
+   draw->pipeline.wide_point_threshold = threshold;
 }
 
 
@@ -251,7 +248,7 @@ void
 draw_wide_line_threshold(struct draw_context *draw, float threshold)
 {
    draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
-   draw->wide_line_threshold = threshold;
+   draw->pipeline.wide_line_threshold = threshold;
 }
 
 
@@ -262,7 +259,18 @@ void
 draw_enable_line_stipple(struct draw_context *draw, boolean enable)
 {
    draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
-   draw->line_stipple = enable;
+   draw->pipeline.line_stipple = enable;
+}
+
+
+/**
+ * Tells draw module whether to convert points to quads for sprite mode.
+ */
+void
+draw_enable_point_sprites(struct draw_context *draw, boolean enable)
+{
+   draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+   draw->pipeline.point_sprite = enable;
 }
 
 
@@ -282,10 +290,10 @@ draw_enable_line_stipple(struct draw_context *draw, boolean enable)
  * work for the drivers.
  */
 int
-draw_find_vs_output(struct draw_context *draw,
+draw_find_vs_output(const struct draw_context *draw,
                     uint semantic_name, uint semantic_index)
 {
-   const struct draw_vertex_shader *vs = draw->vertex_shader;
+   const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
    uint i;
    for (i = 0; i < vs->info.num_outputs; i++) {
       if (vs->info.output_semantic_name[i] == semantic_name &&
@@ -308,71 +316,81 @@ draw_find_vs_output(struct draw_context *draw,
  * Return number of vertex shader outputs.
  */
 uint
-draw_num_vs_outputs(struct draw_context *draw)
+draw_num_vs_outputs(const struct draw_context *draw)
 {
-   uint count = draw->vertex_shader->info.num_outputs;
-   if (draw->extra_vp_outputs.slot >= 0)
+   uint count = draw->vs.vertex_shader->info.num_outputs;
+   if (draw->extra_vp_outputs.slot > 0)
       count++;
    return count;
 }
 
 
-/**
- * Allocate space for temporary post-transform vertices, such as for clipping.
- */
-void draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr )
+
+void draw_set_render( struct draw_context *draw, 
+                     struct vbuf_render *render )
 {
-   assert(!stage->tmp);
+   draw->render = render;
+}
 
-   stage->nr_tmps = nr;
+void draw_set_edgeflags( struct draw_context *draw,
+                         const unsigned *edgeflag )
+{
+   draw->pt.user.edgeflag = edgeflag;
+}
 
-   if (nr) {
-      ubyte *store = (ubyte *) MALLOC( MAX_VERTEX_SIZE * nr );
-      unsigned i;
 
-      stage->tmp = (struct vertex_header **) MALLOC( sizeof(struct vertex_header *) * nr );
-      
-      for (i = 0; i < nr; i++)
-        stage->tmp[i] = (struct vertex_header *)(store + i * MAX_VERTEX_SIZE);
-   }
-}
 
 
-void draw_free_temp_verts( struct draw_stage *stage )
+/**
+ * Tell the drawing context about the index/element buffer to use
+ * (ala glDrawElements)
+ * If no element buffer is to be used (i.e. glDrawArrays) then this
+ * should be called with eltSize=0 and elements=NULL.
+ *
+ * \param draw  the drawing context
+ * \param eltSize  size of each element (1, 2 or 4 bytes)
+ * \param elements  the element buffer ptr
+ */
+void
+draw_set_mapped_element_buffer_range( struct draw_context *draw,
+                                      unsigned eltSize,
+                                      unsigned min_index,
+                                      unsigned max_index,
+                                      void *elements )
 {
-   if (stage->tmp) {
-      FREE( stage->tmp[0] );
-      FREE( stage->tmp );
-      stage->tmp = NULL;
-   }
+   draw->pt.user.elts = elements;
+   draw->pt.user.eltSize = eltSize;
+   draw->pt.user.min_index = min_index;
+   draw->pt.user.max_index = max_index;
 }
 
 
-boolean draw_use_sse(struct draw_context *draw)
+void
+draw_set_mapped_element_buffer( struct draw_context *draw,
+                                unsigned eltSize,
+                                void *elements )
 {
-   return (boolean) draw->use_sse;
+   draw->pt.user.elts = elements;
+   draw->pt.user.eltSize = eltSize;
+   draw->pt.user.min_index = 0;
+   draw->pt.user.max_index = 0xffffffff;
 }
 
-
-void draw_reset_vertex_ids(struct draw_context *draw)
+/* Revamp me please:
+ */
+void draw_do_flush( struct draw_context *draw, unsigned flags )
 {
-   struct draw_stage *stage = draw->pipeline.first;
-   
-   while (stage) {
-      unsigned i;
-
-      for (i = 0; i < stage->nr_tmps; i++)
-        stage->tmp[i]->vertex_id = UNDEFINED_VERTEX_ID;
+   if (!draw->suspend_flushing)
+   {
+      assert(!draw->flushing); /* catch inadvertant recursion */
 
-      stage = stage->next;
-   }
+      draw->flushing = TRUE;
 
-   draw_vertex_cache_reset_vertex_ids(draw);
-}
+      draw_pipeline_flush( draw, flags );
 
-
-void draw_set_render( struct draw_context *draw, 
-                     struct vbuf_render *render )
-{
-   draw->render = render;
+      draw->reduced_prim = ~0; /* is reduced_prim needed any more? */
+      
+      draw->flushing = FALSE;
+   }
 }