[Mesa-dev] [PATCH 1/2] softpipe: implement some support for multiple viewports

Roland Scheidegger sroland at vmware.com
Fri Dec 11 11:10:20 PST 2015


Pushed, thanks!

Roland

Am 11.12.2015 um 12:43 schrieb Edward O'Callaghan:
> Mostly related to making sure the rasterizer can correctly
> pick out the correct scissor box for the current viewport.
> 
> Signed-off-by: Edward O'Callaghan <eocallaghan at alterapraxis.com>
> ---
>  src/gallium/drivers/softpipe/sp_context.h         |  9 ++-
>  src/gallium/drivers/softpipe/sp_quad.h            |  1 +
>  src/gallium/drivers/softpipe/sp_quad_depth_test.c |  5 +-
>  src/gallium/drivers/softpipe/sp_setup.c           | 49 +++++++++++----
>  src/gallium/drivers/softpipe/sp_setup.h           |  5 ++
>  src/gallium/drivers/softpipe/sp_state_clip.c      | 15 +++--
>  src/gallium/drivers/softpipe/sp_state_derived.c   | 76 +++++++++++++++--------
>  src/gallium/drivers/softpipe/sp_surface.c         |  4 +-
>  8 files changed, 112 insertions(+), 52 deletions(-)
> 
> diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
> index 073b71a..8e5e242 100644
> --- a/src/gallium/drivers/softpipe/sp_context.h
> +++ b/src/gallium/drivers/softpipe/sp_context.h
> @@ -79,10 +79,10 @@ struct softpipe_context {
>     struct pipe_resource *constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
>     struct pipe_framebuffer_state framebuffer;
>     struct pipe_poly_stipple poly_stipple;
> -   struct pipe_scissor_state scissor;
> +   struct pipe_scissor_state scissors[PIPE_MAX_VIEWPORTS];
>     struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
>  
> -   struct pipe_viewport_state viewport;
> +   struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
>     struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
>     struct pipe_index_buffer index_buffer;
>     struct pipe_resource *mapped_vs_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS];
> @@ -123,6 +123,9 @@ struct softpipe_context {
>     /** Which vertex shader output slot contains point size */
>     int psize_slot;
>  
> +   /** Which vertex shader output slot contains viewport index */
> +   int viewport_index_slot;
> +
>     /** Which vertex shader output slot contains layer */
>     int layer_slot;
>  
> @@ -140,7 +143,7 @@ struct softpipe_context {
>     unsigned reduced_prim;
>  
>     /** Derived from scissor and surface bounds: */
> -   struct pipe_scissor_state cliprect;
> +   struct pipe_scissor_state cliprect[PIPE_MAX_VIEWPORTS];
>  
>     unsigned line_stipple_counter;
>  
> diff --git a/src/gallium/drivers/softpipe/sp_quad.h b/src/gallium/drivers/softpipe/sp_quad.h
> index b29dad2..2c2b018 100644
> --- a/src/gallium/drivers/softpipe/sp_quad.h
> +++ b/src/gallium/drivers/softpipe/sp_quad.h
> @@ -63,6 +63,7 @@ struct quad_header_input
>  {
>     int x0, y0;                /**< quad window pos, always even */
>     unsigned layer;
> +   unsigned viewport_index;
>     float coverage[TGSI_QUAD_SIZE]; /**< fragment coverage for antialiasing */
>     unsigned facing:1;         /**< Front (0) or back (1) facing? */
>     unsigned prim:2;           /**< QUAD_PRIM_POINT, LINE, TRI */
> diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c
> index bac40c0..4cce9e9 100644
> --- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c
> +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c
> @@ -785,6 +785,7 @@ depth_test_quads_fallback(struct quad_stage *qs,
>     boolean interp_depth = !fsInfo->writes_z;
>     boolean shader_stencil_ref = fsInfo->writes_stencil;
>     struct depth_data data;
> +   unsigned vp_idx = quads[0]->input.viewport_index;
>  
>     data.use_shader_stencil_refs = FALSE;
>  
> @@ -804,8 +805,8 @@ depth_test_quads_fallback(struct quad_stage *qs,
>                                       quads[0]->input.y0, quads[0]->input.layer);
>        data.clamp = !qs->softpipe->rasterizer->depth_clip;
>  
> -      near_val = qs->softpipe->viewport.translate[2] - qs->softpipe->viewport.scale[2];
> -      far_val = near_val + (qs->softpipe->viewport.scale[2] * 2.0);
> +      near_val = qs->softpipe->viewports[vp_idx].translate[2] - qs->softpipe->viewports[vp_idx].scale[2];
> +      far_val = near_val + (qs->softpipe->viewports[vp_idx].scale[2] * 2.0);
>        data.minval = MIN2(near_val, far_val);
>        data.maxval = MAX2(near_val, far_val);
>  
> diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c
> index 973803e..ac2d978 100644
> --- a/src/gallium/drivers/softpipe/sp_setup.c
> +++ b/src/gallium/drivers/softpipe/sp_setup.c
> @@ -128,7 +128,8 @@ struct setup_context {
>  static inline void
>  quad_clip(struct setup_context *setup, struct quad_header *quad)
>  {
> -   const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
> +   unsigned viewport_index = quad[0].input.viewport_index;
> +   const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect[viewport_index];
>     const int minx = (int) cliprect->minx;
>     const int maxx = (int) cliprect->maxx;
>     const int miny = (int) cliprect->miny;
> @@ -159,7 +160,7 @@ quad_clip(struct setup_context *setup, struct quad_header *quad)
>  static inline void
>  clip_emit_quad(struct setup_context *setup, struct quad_header *quad)
>  {
> -   quad_clip( setup, quad );
> +   quad_clip(setup, quad);
>  
>     if (quad->inout.mask) {
>        struct softpipe_context *sp = setup->softpipe;
> @@ -707,9 +708,10 @@ static void
>  subtriangle(struct setup_context *setup,
>              struct edge *eleft,
>              struct edge *eright,
> -            int lines)
> +            int lines,
> +            unsigned viewport_index)
>  {
> -   const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
> +   const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect[viewport_index];
>     const int minx = (int) cliprect->minx;
>     const int maxx = (int) cliprect->maxx;
>     const int miny = (int) cliprect->miny;
> @@ -807,6 +809,7 @@ sp_setup_tri(struct setup_context *setup,
>  {
>     float det;
>     uint layer = 0;
> +   unsigned viewport_index = 0;
>  #if DEBUG_VERTS
>     debug_printf("Setup triangle:\n");
>     print_vertex(setup, v0);
> @@ -845,19 +848,25 @@ sp_setup_tri(struct setup_context *setup,
>     }
>     setup->quad[0].input.layer = layer;
>  
> +   if (setup->softpipe->viewport_index_slot > 0) {
> +      unsigned *udata = (unsigned*)v0[setup->softpipe->viewport_index_slot];
> +      viewport_index = sp_clamp_viewport_idx(*udata);
> +   }
> +   setup->quad[0].input.viewport_index = viewport_index;
> +
>     /*   init_constant_attribs( setup ); */
>  
>     if (setup->oneoverarea < 0.0) {
>        /* emaj on left:
>         */
> -      subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
> -      subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
> +      subtriangle(setup, &setup->emaj, &setup->ebot, setup->ebot.lines, viewport_index);
> +      subtriangle(setup, &setup->emaj, &setup->etop, setup->etop.lines, viewport_index);
>     }
>     else {
>        /* emaj on right:
>         */
> -      subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
> -      subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
> +      subtriangle(setup, &setup->ebot, &setup->emaj, setup->ebot.lines, viewport_index);
> +      subtriangle(setup, &setup->etop, &setup->emaj, setup->etop.lines, viewport_index);
>     }
>  
>     flush_spans( setup );
> @@ -1054,7 +1063,7 @@ plot(struct setup_context *setup, int x, int y)
>        /* flush prev quad, start new quad */
>  
>        if (setup->quad[0].input.x0 != -1)
> -         clip_emit_quad( setup, &setup->quad[0] );
> +         clip_emit_quad(setup, &setup->quad[0]);
>  
>        setup->quad[0].input.x0 = quadX;
>        setup->quad[0].input.y0 = quadY;
> @@ -1083,6 +1092,7 @@ sp_setup_line(struct setup_context *setup,
>     int dy = y1 - y0;
>     int xstep, ystep;
>     uint layer = 0;
> +   unsigned viewport_index = 0;
>  
>  #if DEBUG_VERTS
>     debug_printf("Setup line:\n");
> @@ -1132,6 +1142,12 @@ sp_setup_line(struct setup_context *setup,
>     }
>     setup->quad[0].input.layer = layer;
>  
> +   if (setup->softpipe->viewport_index_slot > 0) {
> +      unsigned *udata = (unsigned*)setup->vprovoke[setup->softpipe->viewport_index_slot];
> +      viewport_index = sp_clamp_viewport_idx(*udata);
> +   }
> +   setup->quad[0].input.viewport_index = viewport_index;
> +
>     /* XXX temporary: set coverage to 1.0 so the line appears
>      * if AA mode happens to be enabled.
>      */
> @@ -1183,7 +1199,7 @@ sp_setup_line(struct setup_context *setup,
>  
>     /* draw final quad */
>     if (setup->quad[0].inout.mask) {
> -      clip_emit_quad( setup, &setup->quad[0] );
> +      clip_emit_quad(setup, &setup->quad[0]);
>     }
>  }
>  
> @@ -1223,6 +1239,7 @@ sp_setup_point(struct setup_context *setup,
>     const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
>     uint fragSlot;
>     uint layer = 0;
> +   unsigned viewport_index = 0;
>  #if DEBUG_VERTS
>     debug_printf("Setup point:\n");
>     print_vertex(setup, v0);
> @@ -1239,6 +1256,12 @@ sp_setup_point(struct setup_context *setup,
>     }
>     setup->quad[0].input.layer = layer;
>  
> +   if (setup->softpipe->viewport_index_slot > 0) {
> +      unsigned *udata = (unsigned*)v0[setup->softpipe->viewport_index_slot];
> +      viewport_index = sp_clamp_viewport_idx(*udata);
> +   }
> +   setup->quad[0].input.viewport_index = viewport_index;
> +
>     /* For points, all interpolants are constant-valued.
>      * However, for point sprites, we'll need to setup texcoords appropriately.
>      * XXX: which coefficients are the texcoords???
> @@ -1300,7 +1323,7 @@ sp_setup_point(struct setup_context *setup,
>        setup->quad[0].input.x0 = (int) x - ix;
>        setup->quad[0].input.y0 = (int) y - iy;
>        setup->quad[0].inout.mask = (1 << ix) << (2 * iy);
> -      clip_emit_quad( setup, &setup->quad[0] );
> +      clip_emit_quad(setup, &setup->quad[0]);
>     }
>     else {
>        if (round) {
> @@ -1361,7 +1384,7 @@ sp_setup_point(struct setup_context *setup,
>                 if (setup->quad[0].inout.mask) {
>                    setup->quad[0].input.x0 = ix;
>                    setup->quad[0].input.y0 = iy;
> -                  clip_emit_quad( setup, &setup->quad[0] );
> +                  clip_emit_quad(setup, &setup->quad[0]);
>                 }
>              }
>           }
> @@ -1408,7 +1431,7 @@ sp_setup_point(struct setup_context *setup,
>                 setup->quad[0].inout.mask = mask;
>                 setup->quad[0].input.x0 = ix;
>                 setup->quad[0].input.y0 = iy;
> -               clip_emit_quad( setup, &setup->quad[0] );
> +               clip_emit_quad(setup, &setup->quad[0]);
>              }
>           }
>        }
> diff --git a/src/gallium/drivers/softpipe/sp_setup.h b/src/gallium/drivers/softpipe/sp_setup.h
> index 885be73..191494a 100644
> --- a/src/gallium/drivers/softpipe/sp_setup.h
> +++ b/src/gallium/drivers/softpipe/sp_setup.h
> @@ -45,6 +45,11 @@ void
>  sp_setup_point( struct setup_context *setup,
>               const float (*v0)[4] );
>  
> +static inline unsigned
> +sp_clamp_viewport_idx(int idx)
> +{
> +   return (PIPE_MAX_VIEWPORTS > idx && idx >= 0) ? idx : 0;
> +}
>  
>  struct setup_context *sp_setup_create_context( struct softpipe_context *softpipe );
>  void sp_setup_prepare( struct setup_context *setup );
> diff --git a/src/gallium/drivers/softpipe/sp_state_clip.c b/src/gallium/drivers/softpipe/sp_state_clip.c
> index 59c22c6..4de6296 100644
> --- a/src/gallium/drivers/softpipe/sp_state_clip.c
> +++ b/src/gallium/drivers/softpipe/sp_state_clip.c
> @@ -47,15 +47,16 @@ static void
>  softpipe_set_viewport_states(struct pipe_context *pipe,
>                               unsigned start_slot,
>                               unsigned num_viewports,
> -                             const struct pipe_viewport_state *viewport)
> +                             const struct pipe_viewport_state *viewports)
>  {
>     struct softpipe_context *softpipe = softpipe_context(pipe);
>  
>     /* pass the viewport info to the draw module */
>     draw_set_viewport_states(softpipe->draw, start_slot, num_viewports,
> -                            viewport);
> +                            viewports);
>  
> -   softpipe->viewport = *viewport; /* struct copy */
> +   memcpy(softpipe->viewports + start_slot, viewports,
> +          sizeof(struct pipe_viewport_state) * num_viewports);
>     softpipe->dirty |= SP_NEW_VIEWPORT;
>  }
>  
> @@ -64,13 +65,17 @@ static void
>  softpipe_set_scissor_states(struct pipe_context *pipe,
>                              unsigned start_slot,
>                              unsigned num_scissors,
> -                            const struct pipe_scissor_state *scissor)
> +                            const struct pipe_scissor_state *scissors)
>  {
>     struct softpipe_context *softpipe = softpipe_context(pipe);
>  
>     draw_flush(softpipe->draw);
>  
> -   softpipe->scissor = *scissor; /* struct copy */
> +   debug_assert(start_slot < PIPE_MAX_VIEWPORTS);
> +   debug_assert((start_slot + num_scissors) <= PIPE_MAX_VIEWPORTS);
> +
> +   memcpy(softpipe->scissors + start_slot, scissors,
> +          sizeof(struct pipe_scissor_state) * num_scissors);
>     softpipe->dirty |= SP_NEW_SCISSOR;
>  }
>  
> diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c
> index 2a6a6f4..7e998af 100644
> --- a/src/gallium/drivers/softpipe/sp_state_derived.c
> +++ b/src/gallium/drivers/softpipe/sp_state_derived.c
> @@ -64,6 +64,7 @@ struct vertex_info *
>  softpipe_get_vertex_info(struct softpipe_context *softpipe)
>  {
>     struct vertex_info *vinfo = &softpipe->vertex_info;
> +   int vs_index;
>  
>     if (vinfo->num_attribs == 0) {
>        /* compute vertex layout now */
> @@ -135,17 +136,35 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
>           draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
>        }
>  
> -      softpipe->psize_slot = draw_find_shader_output(softpipe->draw,
> -                                                 TGSI_SEMANTIC_PSIZE, 0);
> -      if (softpipe->psize_slot >= 0) {
> -         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
> -                               softpipe->psize_slot);
> +      /* Figure out if we need pointsize as well. */
> +      vs_index = draw_find_shader_output(softpipe->draw,
> +                                         TGSI_SEMANTIC_PSIZE, 0);
> +
> +      if (vs_index >= 0) {
> +         softpipe->psize_slot = vinfo->num_attribs;
> +         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
> +      }
> +
> +      /* Figure out if we need viewport index */
> +      vs_index = draw_find_shader_output(softpipe->draw,
> +                                         TGSI_SEMANTIC_VIEWPORT_INDEX,
> +                                         0);
> +      if (vs_index >= 0) {
> +         softpipe->viewport_index_slot = vinfo->num_attribs;
> +         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
> +      } else {
> +         softpipe->viewport_index_slot = 0;
>        }
>  
> -      softpipe->layer_slot = draw_find_shader_output(softpipe->draw,
> -                                         TGSI_SEMANTIC_LAYER, 0);
> -      if (softpipe->layer_slot >= 0) {
> -         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, softpipe->layer_slot);
> +      /* Figure out if we need layer */
> +      vs_index = draw_find_shader_output(softpipe->draw,
> +                                         TGSI_SEMANTIC_LAYER,
> +                                         0);
> +      if (vs_index >= 0) {
> +         softpipe->layer_slot = vinfo->num_attribs;
> +         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
> +      } else {
> +         softpipe->layer_slot = 0;
>        }
>  
>        draw_compute_vertex_size(vinfo);
> @@ -183,30 +202,33 @@ softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
>  static void
>  compute_cliprect(struct softpipe_context *sp)
>  {
> +   unsigned i;
>     /* SP_NEW_FRAMEBUFFER
>      */
>     uint surfWidth = sp->framebuffer.width;
>     uint surfHeight = sp->framebuffer.height;
>  
> -   /* SP_NEW_RASTERIZER
> -    */
> -   if (sp->rasterizer->scissor) {
> -
> -      /* SP_NEW_SCISSOR
> -       *
> -       * clip to scissor rect:
> +   for (i = 0; i < PIPE_MAX_VIEWPORTS; i++) {
> +      /* SP_NEW_RASTERIZER
>         */
> -      sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
> -      sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
> -      sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
> -      sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
> -   }
> -   else {
> -      /* clip to surface bounds */
> -      sp->cliprect.minx = 0;
> -      sp->cliprect.miny = 0;
> -      sp->cliprect.maxx = surfWidth;
> -      sp->cliprect.maxy = surfHeight;
> +      if (sp->rasterizer->scissor) {
> +
> +         /* SP_NEW_SCISSOR
> +          *
> +          * clip to scissor rect:
> +          */
> +         sp->cliprect[i].minx = MAX2(sp->scissors[i].minx, 0);
> +         sp->cliprect[i].miny = MAX2(sp->scissors[i].miny, 0);
> +         sp->cliprect[i].maxx = MIN2(sp->scissors[i].maxx, surfWidth);
> +         sp->cliprect[i].maxy = MIN2(sp->scissors[i].maxy, surfHeight);
> +      }
> +      else {
> +         /* clip to surface bounds */
> +         sp->cliprect[i].minx = 0;
> +         sp->cliprect[i].miny = 0;
> +         sp->cliprect[i].maxx = surfWidth;
> +         sp->cliprect[i].maxy = surfHeight;
> +      }
>     }
>  }
>  
> diff --git a/src/gallium/drivers/softpipe/sp_surface.c b/src/gallium/drivers/softpipe/sp_surface.c
> index 768e898..e2ecbdf 100644
> --- a/src/gallium/drivers/softpipe/sp_surface.c
> +++ b/src/gallium/drivers/softpipe/sp_surface.c
> @@ -67,8 +67,8 @@ static void sp_blit(struct pipe_context *pipe,
>     util_blitter_save_so_targets(sp->blitter, sp->num_so_targets,
>                       (struct pipe_stream_output_target**)sp->so_targets);
>     util_blitter_save_rasterizer(sp->blitter, sp->rasterizer);
> -   util_blitter_save_viewport(sp->blitter, &sp->viewport);
> -   util_blitter_save_scissor(sp->blitter, &sp->scissor);
> +   util_blitter_save_viewport(sp->blitter, &sp->viewports[0]);
> +   util_blitter_save_scissor(sp->blitter, &sp->scissors[0]);
>     util_blitter_save_fragment_shader(sp->blitter, sp->fs);
>     util_blitter_save_blend(sp->blitter, sp->blend);
>     util_blitter_save_depth_stencil_alpha(sp->blitter, sp->depth_stencil);
> 



More information about the mesa-dev mailing list