diff options
| author | Hui Qi Tay <hqtay@vmware.com> | 2010-08-27 10:37:09 +0100 | 
|---|---|---|
| committer | Keith Whitwell <keithw@vmware.com> | 2010-08-27 13:08:54 +0100 | 
| commit | 57d84d9ca4a645ca326b66ff3b82bee0db18ac97 (patch) | |
| tree | c1a027ff24b90e28f5d0ec7a4135c2af46df83e4 | |
| parent | 3783053fa59fceef59fe0356af5c8dbc095e9adf (diff) | |
llvmpipe: native point rasterization
Conflicts:
	src/gallium/drivers/llvmpipe/lp_setup_context.h
	src/gallium/drivers/llvmpipe/lp_setup_line.c
	src/gallium/drivers/llvmpipe/lp_setup_tri.c
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_context.c | 6 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_context.h | 3 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.c | 15 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.h | 4 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_context.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_point.c | 225 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_derived.c | 10 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_rasterizer.c | 2 | 
8 files changed, 262 insertions, 5 deletions
| diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c index a6873abbee..c52b17b298 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.c +++ b/src/gallium/drivers/llvmpipe/lp_context.c @@ -155,8 +155,10 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )     draw_install_aapoint_stage(llvmpipe->draw, &llvmpipe->pipe);     draw_install_pstipple_stage(llvmpipe->draw, &llvmpipe->pipe); -   /* convert points and lines into triangles: */ -   draw_wide_point_threshold(llvmpipe->draw, 0.0); +   /* convert points and lines into triangles:  +    * (otherwise, draw points and lines natively) +    */ +   draw_wide_point_threshold(llvmpipe->draw, 10000.0);     draw_wide_line_threshold(llvmpipe->draw, 10000.0);  #if USE_DRAW_STAGE_PSTIPPLE diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 50f9091c3c..34fa20e204 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -101,6 +101,9 @@ struct llvmpipe_context {     /** Vertex format */     struct vertex_info vertex_info; +    +   /** Which vertex shader output slot contains point size */ +   int psize_slot;     /** Fragment shader input interpolation info */     unsigned num_inputs; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 4c8275665e..778bfb4f6e 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -494,6 +494,15 @@ lp_setup_set_line_state( struct lp_setup_context *setup,     setup->line_width = line_width;  } +void  +lp_setup_set_point_state( struct lp_setup_context *setup, +                          float point_size) +{ +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + +   setup->point_size = point_size; +} +  void  lp_setup_set_fs_inputs( struct lp_setup_context *setup,                          const struct lp_shader_input *input, @@ -733,6 +742,12 @@ lp_setup_update_state( struct lp_setup_context *setup )      */     {        struct llvmpipe_context *lp = llvmpipe_context(scene->pipe); + +      /* Will probably need to move this somewhere else, just need   +       * to know about vertex shader point size attribute. +       */ +      setup->psize = lp->psize_slot; +        if (lp->dirty) {           llvmpipe_update_derived(lp);        } diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index 693550b8c8..6b041e7071 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -104,6 +104,10 @@ void  lp_setup_set_line_state( struct lp_setup_context *setup,                           float line_width); +void  +lp_setup_set_point_state( struct lp_setup_context *setup, +                          float point_size); +  void  lp_setup_set_fs_inputs( struct lp_setup_context *setup,                          const struct lp_shader_input *interp, diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index 97919c09d4..7d486afbbf 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -92,6 +92,8 @@ struct lp_setup_context     unsigned cullmode;     float pixel_offset;     float line_width; +   float point_size; +   float psize;     struct pipe_framebuffer_state fb;     struct u_rect framebuffer; diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c index 709c3e2fd2..07a28fc6e3 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_point.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c @@ -1,6 +1,6 @@  /**************************************************************************   * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2010, VMware Inc.   * All Rights Reserved.   *   * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS   * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR   * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE   * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -30,10 +30,229 @@   */  #include "lp_setup_context.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "lp_perf.h" +#include "lp_setup_context.h" +#include "lp_rast.h" +#include "lp_state_fs.h" + +#define NUM_CHANNELS 4 + +struct point_info { +   /* x,y deltas */ +   int dy01, dy12; +   int dx01, dx12; + +   const float (*v0)[4]; +};    + + +/** + * Compute a0 for a constant-valued coefficient (GL_FLAT shading). + */ +static void constant_coef( struct lp_setup_context *setup, +                           struct lp_rast_triangle *point, +                           unsigned slot, +                           const float value, +                           unsigned i ) +{ +   point->inputs.a0[slot][i] = value; +   point->inputs.dadx[slot][i] = 0.0f; +   point->inputs.dady[slot][i] = 0.0f; +} + +/** + * Special coefficient setup for gl_FragCoord. + * X and Y are trivial + * Z and W are copied from position_coef which should have already been computed. + * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask. + */ +static void +setup_point_fragcoord_coef(struct lp_setup_context *setup, +                           struct lp_rast_triangle *point, +                           const struct point_info *info, +                           unsigned slot, +                           unsigned usage_mask) +{ +   /*X*/ +   if (usage_mask & TGSI_WRITEMASK_X) { +      point->inputs.a0[slot][0] = 0.0; +      point->inputs.dadx[slot][0] = 1.0; +      point->inputs.dady[slot][0] = 0.0; +   } + +   /*Y*/ +   if (usage_mask & TGSI_WRITEMASK_Y) { +      point->inputs.a0[slot][1] = 0.0; +      point->inputs.dadx[slot][1] = 0.0; +      point->inputs.dady[slot][1] = 1.0; +   } + +   /*Z*/ +   if (usage_mask & TGSI_WRITEMASK_Z) { +      constant_coef(setup, point, slot, info->v0[0][2], 2); +   } + +   /*W*/ +   if (usage_mask & TGSI_WRITEMASK_W) { +      constant_coef(setup, point, slot, info->v0[0][3], 3); +   } +} + +/** + * Compute the point->coef[] array dadx, dady, a0 values. + */ +static void    +setup_point_coefficients( struct lp_setup_context *setup, +                          struct lp_rast_triangle *point, +                          const struct point_info *info) +{ +   unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ; +   unsigned slot; + +   /* setup interpolation for all the remaining attributes: +    */ +   for (slot = 0; slot < setup->fs.nr_inputs; slot++) { +      unsigned vert_attr = setup->fs.input[slot].src_index; +      unsigned usage_mask = setup->fs.input[slot].usage_mask; +      unsigned i; +       +      switch (setup->fs.input[slot].interp) { +      case LP_INTERP_POSITION: +         /* +          * The generated pixel interpolators will pick up the coeffs from +          * slot 0, so all need to ensure that the usage mask is covers all +          * usages. +          */ +         fragcoord_usage_mask |= usage_mask; +         break; + +      default: +         for (i = 0; i < NUM_CHANNELS; i++) { +            if (usage_mask & (1 << i)) +               constant_coef(setup, point, slot+1, info->v0[vert_attr][i], i); +         } +      } +   } + +   /* The internal position input is in slot zero: +    */ +   setup_point_fragcoord_coef(setup, point, info, 0, +                              fragcoord_usage_mask); +} + +static INLINE int +subpixel_snap(float a) +{ +   return util_iround(FIXED_ONE * a); +} +  static void lp_setup_point( struct lp_setup_context *setup, -                       const float (*v0)[4] ) +                            const float (*v0)[4] )  { +   /* x/y positions in fixed point */ +   const int sizeAttr = setup->psize; +   const float size +      = sizeAttr > 0 ? v0[sizeAttr][0] +      : setup->point_size; +   const float half_width = 0.5F * size; +  +   const int x0 = subpixel_snap(v0[0][0] - half_width - setup->pixel_offset); +   const int x1 = subpixel_snap(v0[0][0] - half_width - setup->pixel_offset); +   const int x2 = subpixel_snap(v0[0][0] + half_width - setup->pixel_offset); +   const int y0 = subpixel_snap(v0[0][1] - half_width - setup->pixel_offset); +   const int y1 = subpixel_snap(v0[0][1] + half_width - setup->pixel_offset); +   const int y2 = subpixel_snap(v0[0][1] + half_width - setup->pixel_offset); +   struct lp_scene *scene = lp_setup_get_current_scene(setup); +   struct lp_rast_triangle *point; +   unsigned bytes; +   struct u_rect bbox; +   unsigned nr_planes = 4; +   struct point_info info; + + +   /* Bounding rectangle (in pixels) */ +   { +      /* Yes this is necessary to accurately calculate bounding boxes +       * with the two fill-conventions we support.  GL (normally) ends +       * up needing a bottom-left fill convention, which requires +       * slightly different rounding. +       */ +      int adj = (setup->pixel_offset != 0) ? 1 : 0; + +      bbox.x0 = (MIN3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER; +      bbox.x1 = (MAX3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER; +      bbox.y0 = (MIN3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; +      bbox.y1 = (MAX3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; + +      /* Inclusive coordinates: +       */ +      bbox.x1--; +      bbox.y1--; +   } +    +   if (!u_rect_test_intersection(&setup->draw_region, &bbox)) { +      if (0) debug_printf("offscreen\n"); +      LP_COUNT(nr_culled_tris); +      return; +   } + +   u_rect_find_intersection(&setup->draw_region, &bbox); + +   point = lp_setup_alloc_triangle(scene, +                                   setup->fs.nr_inputs, +                                   nr_planes, +                                   &bytes); +   if (!point) +      return; + +#ifdef DEBUG +   point->v[0][0] = v0[0][0]; +   point->v[0][1] = v0[0][1]; +#endif + +   info.v0 = v0; +   info.dx01 = x1 - x0; +   info.dx12 = x2 - x1; +   info.dy01 = y1 - y0; +   info.dy12 = y2 - y1; +    +   /* Setup parameter interpolants: +    */ +   setup_point_coefficients(setup, point, &info); + +   point->inputs.facing = 1.0F; +   point->inputs.state = setup->fs.stored; + +   { +      point->plane[0].dcdx = -1; +      point->plane[0].dcdy = 0; +      point->plane[0].c = 1-bbox.x0; +      point->plane[0].ei = 0; +      point->plane[0].eo = 1; + +      point->plane[1].dcdx = 1; +      point->plane[1].dcdy = 0; +      point->plane[1].c = bbox.x1+1; +      point->plane[1].ei = -1; +      point->plane[1].eo = 0; + +      point->plane[2].dcdx = 0; +      point->plane[2].dcdy = 1; +      point->plane[2].c = 1-bbox.y0; +      point->plane[2].ei = 0; +      point->plane[2].eo = 1; + +      point->plane[3].dcdx = 0; +      point->plane[3].dcdy = -1; +      point->plane[3].c = bbox.y1+1; +      point->plane[3].ei = -1; +      point->plane[3].eo = 0; +   } + +   lp_setup_bin_triangle(setup, point, &bbox, nr_planes);  } diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 77bec4640b..9ef9983307 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -125,6 +125,16 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)        inputs[i].src_index = vinfo->num_attribs;        draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);     } + +   /* Figure out if we need pointsize as well. +    */ +   llvmpipe->psize_slot = draw_find_shader_output(llvmpipe->draw, +                                                  TGSI_SEMANTIC_PSIZE, 0); +   if (llvmpipe->psize_slot > 0) { +      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, +                            llvmpipe->psize_slot); +   } +     llvmpipe->num_inputs = lpfs->info.num_inputs;     draw_compute_vertex_size(vinfo); diff --git a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c index 67b985aa24..f845a0c6e5 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c +++ b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c @@ -75,6 +75,8 @@ llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, void *handle)                     llvmpipe->rasterizer->flatshade_first);        lp_setup_set_line_state( llvmpipe->setup,                     llvmpipe->rasterizer->line_width); +      lp_setup_set_point_state( llvmpipe->setup, +                   llvmpipe->rasterizer->point_size);     }     llvmpipe->dirty |= LP_NEW_RASTERIZER; | 
