[Mesa-dev] [PATCH 4/4] llvmpipe: implement support for multiple viewports
Roland Scheidegger
sroland at vmware.com
Thu May 23 14:32:33 PDT 2013
Am 23.05.2013 22:33, schrieb Zack Rusin:
> Largely related to making sure the rasterizer can correctly
> pick out the correct scissor box for the current viewport.
>
> Signed-off-by: Zack Rusin <zackr at vmware.com>
> ---
> src/gallium/drivers/llvmpipe/lp_context.h | 9 ++++--
> src/gallium/drivers/llvmpipe/lp_screen.c | 2 +-
> src/gallium/drivers/llvmpipe/lp_setup.c | 34 +++++++++++++++--------
> src/gallium/drivers/llvmpipe/lp_setup.h | 5 ++--
> src/gallium/drivers/llvmpipe/lp_setup_context.h | 9 ++++--
> src/gallium/drivers/llvmpipe/lp_setup_line.c | 12 ++++++--
> src/gallium/drivers/llvmpipe/lp_setup_point.c | 12 +++++---
> src/gallium/drivers/llvmpipe/lp_setup_tri.c | 17 ++++++++----
> src/gallium/drivers/llvmpipe/lp_state_clip.c | 8 ++++--
> src/gallium/drivers/llvmpipe/lp_state_derived.c | 15 +++++++++-
> src/gallium/drivers/llvmpipe/lp_surface.c | 4 +--
> 11 files changed, 91 insertions(+), 36 deletions(-)
>
> diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
> index d605dba..444c768 100644
> --- a/src/gallium/drivers/llvmpipe/lp_context.h
> +++ b/src/gallium/drivers/llvmpipe/lp_context.h
> @@ -75,10 +75,12 @@ struct llvmpipe_context {
> struct pipe_constant_buffer constants[PIPE_SHADER_TYPES][LP_MAX_TGSI_CONST_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];
> + unsigned num_scissors;
> 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];
> + unsigned num_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];
> @@ -116,6 +118,9 @@ struct llvmpipe_context {
> /** Which vertex shader output slot contains point size */
> int psize_slot;
>
> + /** Which vertex shader output slot contains viewport index */
> + int viewport_index_slot;
> +
> /**< minimum resolvable depth value, for polygon offset */
> double mrd;
>
> diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
> index 712b7c6..9c4de72 100644
> --- a/src/gallium/drivers/llvmpipe/lp_screen.c
> +++ b/src/gallium/drivers/llvmpipe/lp_screen.c
> @@ -231,7 +231,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
> case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
> return 0;
> case PIPE_CAP_MULTIPLE_VIEWPORTS:
> - return 0;
> + return 1;
> }
> /* should only get here on unhandled cases */
> debug_printf("Unexpected PIPE_CAP %d query\n", param);
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
> index 9fef34e..caa168d 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup.c
> +++ b/src/gallium/drivers/llvmpipe/lp_setup.c
> @@ -616,17 +616,23 @@ lp_setup_set_blend_color( struct lp_setup_context *setup,
>
>
> void
> -lp_setup_set_scissor( struct lp_setup_context *setup,
> - const struct pipe_scissor_state *scissor )
> +lp_setup_set_scissors( struct lp_setup_context *setup,
> + unsigned num_scissors,
> + const struct pipe_scissor_state *scissors )
> {
> + unsigned i;
> LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
>
> - assert(scissor);
> + assert(scissors);
> +
> + setup->num_scissors = num_scissors;
>
> - setup->scissor.x0 = scissor->minx;
> - setup->scissor.x1 = scissor->maxx-1;
> - setup->scissor.y0 = scissor->miny;
> - setup->scissor.y1 = scissor->maxy-1;
> + for (i = 0; i < num_scissors; ++i) {
> + setup->scissors[i].x0 = scissors[i].minx;
> + setup->scissors[i].x1 = scissors[i].maxx-1;
> + setup->scissors[i].y0 = scissors[i].miny;
> + setup->scissors[i].y1 = scissors[i].maxy-1;
> + }
> setup->dirty |= LP_SETUP_NEW_SCISSOR;
> }
>
> @@ -1012,10 +1018,15 @@ try_update_scene_state( struct lp_setup_context *setup )
> }
>
> if (setup->dirty & LP_SETUP_NEW_SCISSOR) {
> - setup->draw_region = setup->framebuffer;
> - if (setup->scissor_test) {
> - u_rect_possible_intersection(&setup->scissor,
> - &setup->draw_region);
> + unsigned i;
> + /* we always need at least one draw region */
> + setup->draw_regions[0] = setup->framebuffer;
> + for (i = 0; i < setup->num_scissors; ++i) {
> + setup->draw_regions[i] = setup->framebuffer;
> + if (setup->scissor_test) {
> + u_rect_possible_intersection(&setup->scissors[i],
> + &setup->draw_regions[i]);
> + }
> }
> /* If the framebuffer is large we have to think about fixed-point
> * integer overflow. For 2K by 2K images, coordinates need 15 bits
> @@ -1061,6 +1072,7 @@ lp_setup_update_state( struct lp_setup_context *setup,
> * to know about vertex shader point size attribute.
> */
> setup->psize = lp->psize_slot;
> + setup->viewport_index_slot = lp->viewport_index_slot;
>
> assert(lp->dirty == 0);
>
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h
> index 802ab01..68c710b 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup.h
> +++ b/src/gallium/drivers/llvmpipe/lp_setup.h
> @@ -117,8 +117,9 @@ lp_setup_set_blend_color( struct lp_setup_context *setup,
> const struct pipe_blend_color *blend_color );
>
> void
> -lp_setup_set_scissor( struct lp_setup_context *setup,
> - const struct pipe_scissor_state *scissor );
> +lp_setup_set_scissors( struct lp_setup_context *setup,
> + unsigned num_scissors,
> + const struct pipe_scissor_state *scissors );
>
> void
> lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup,
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h
> index 6b35a02..da85f78 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
> +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
> @@ -103,11 +103,13 @@ struct lp_setup_context
> float line_width;
> float point_size;
> float psize;
> + unsigned viewport_index_slot;
>
> struct pipe_framebuffer_state fb;
> struct u_rect framebuffer;
> - struct u_rect scissor;
> - struct u_rect draw_region; /* intersection of fb & scissor */
> + struct u_rect scissors[PIPE_MAX_VIEWPORTS];
> + unsigned num_scissors;
> + struct u_rect draw_regions[PIPE_MAX_VIEWPORTS]; /* intersection of fb & scissor */
>
> struct {
> unsigned flags;
> @@ -195,6 +197,7 @@ boolean
> lp_setup_bin_triangle( struct lp_setup_context *setup,
> struct lp_rast_triangle *tri,
> const struct u_rect *bbox,
> - int nr_planes );
> + int nr_planes,
> + unsigned scissor_index );
>
> #endif
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c
> index 54f19cb..c2a069f 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup_line.c
> +++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c
> @@ -289,6 +289,7 @@ try_setup_line( struct lp_setup_context *setup,
> int y[4];
> int i;
> int nr_planes = 4;
> + unsigned scissor_index = 0;
>
> /* linewidth should be interpreted as integer */
> int fixed_width = util_iround(width) * FIXED_ONE;
> @@ -315,6 +316,10 @@ try_setup_line( struct lp_setup_context *setup,
>
> if (setup->scissor_test) {
> nr_planes = 8;
> + if (setup->viewport_index_slot > 0) {
> + unsigned *udata = (unsigned*)v1[setup->viewport_index_slot];
> + scissor_index = *udata;
> + }
> }
> else {
> nr_planes = 4;
> @@ -563,7 +568,7 @@ try_setup_line( struct lp_setup_context *setup,
> return TRUE;
> }
>
> - if (!u_rect_test_intersection(&setup->draw_region, &bbox)) {
> + if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
> if (0) debug_printf("offscreen\n");
> LP_COUNT(nr_culled_tris);
> return TRUE;
> @@ -672,7 +677,8 @@ try_setup_line( struct lp_setup_context *setup,
> * these planes elsewhere.
> */
> if (nr_planes == 8) {
> - const struct u_rect *scissor = &setup->scissor;
> + const struct u_rect *scissor =
> + &setup->scissors[scissor_index];
>
> plane[4].dcdx = -1;
> plane[4].dcdy = 0;
> @@ -695,7 +701,7 @@ try_setup_line( struct lp_setup_context *setup,
> plane[7].eo = 0;
> }
>
> - return lp_setup_bin_triangle(setup, line, &bbox, nr_planes);
> + return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, scissor_index);
> }
>
>
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c
> index 146f1bd..30ce7490 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup_point.c
> +++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c
> @@ -324,8 +324,12 @@ try_setup_point( struct lp_setup_context *setup,
> struct u_rect bbox;
> unsigned nr_planes = 4;
> struct point_info info;
> + unsigned scissor_index = 0;
>
> -
> + if (setup->viewport_index_slot > 0) {
> + unsigned *udata = (unsigned*)v0[setup->viewport_index_slot];
> + scissor_index = *udata;
> + }
> /* Bounding rectangle (in pixels) */
> {
> /* Yes this is necessary to accurately calculate bounding boxes
> @@ -346,13 +350,13 @@ try_setup_point( struct lp_setup_context *setup,
> bbox.y1--;
> }
>
> - if (!u_rect_test_intersection(&setup->draw_region, &bbox)) {
> + if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
> if (0) debug_printf("offscreen\n");
> LP_COUNT(nr_culled_tris);
> return TRUE;
> }
>
> - u_rect_find_intersection(&setup->draw_region, &bbox);
> + u_rect_find_intersection(&setup->draw_regions[scissor_index], &bbox);
>
> point = lp_setup_alloc_triangle(scene,
> key->num_inputs,
> @@ -407,7 +411,7 @@ try_setup_point( struct lp_setup_context *setup,
> plane[3].eo = 0;
> }
>
> - return lp_setup_bin_triangle(setup, point, &bbox, nr_planes);
> + return lp_setup_bin_triangle(setup, point, &bbox, nr_planes, scissor_index);
> }
>
>
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
> index b2c8cb5..c1ba52e 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
> +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
> @@ -246,6 +246,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
> struct u_rect bbox;
> unsigned tri_bytes;
> int nr_planes = 3;
> + unsigned scissor_index = 0;
>
> /* Area should always be positive here */
> assert(position->area > 0);
> @@ -255,6 +256,10 @@ do_triangle_ccw(struct lp_setup_context *setup,
>
> if (setup->scissor_test) {
> nr_planes = 7;
> + if (setup->viewport_index_slot > 0) {
> + unsigned *udata = (unsigned*)v0[setup->viewport_index_slot];
> + scissor_index = *udata;
> + }
> }
> else {
> nr_planes = 3;
> @@ -285,7 +290,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
> return TRUE;
> }
>
> - if (!u_rect_test_intersection(&setup->draw_region, &bbox)) {
> + if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
> if (0) debug_printf("offscreen\n");
> LP_COUNT(nr_culled_tris);
> return TRUE;
> @@ -491,7 +496,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
> * these planes elsewhere.
> */
> if (nr_planes == 7) {
> - const struct u_rect *scissor = &setup->scissor;
> + const struct u_rect *scissor = &setup->scissors[scissor_index];
>
> plane[3].dcdx = -1;
> plane[3].dcdy = 0;
> @@ -514,7 +519,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
> plane[6].eo = 0;
> }
>
> - return lp_setup_bin_triangle( setup, tri, &bbox, nr_planes );
> + return lp_setup_bin_triangle( setup, tri, &bbox, nr_planes, scissor_index );
> }
>
> /*
> @@ -548,7 +553,8 @@ boolean
> lp_setup_bin_triangle( struct lp_setup_context *setup,
> struct lp_rast_triangle *tri,
> const struct u_rect *bbox,
> - int nr_planes )
> + int nr_planes,
> + unsigned scissor_index )
> {
> struct lp_scene *scene = setup->scene;
> struct u_rect trimmed_box = *bbox;
> @@ -570,7 +576,8 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
> * the rasterizer to also respect scissor, etc, just for the rare
> * cases where a small triangle extends beyond the scissor.
> */
> - u_rect_find_intersection(&setup->draw_region, &trimmed_box);
> + u_rect_find_intersection(&setup->draw_regions[scissor_index],
> + &trimmed_box);
>
> /* Determine which tile(s) intersect the triangle's bounding box
> */
> diff --git a/src/gallium/drivers/llvmpipe/lp_state_clip.c b/src/gallium/drivers/llvmpipe/lp_state_clip.c
> index ed47e5e..e33d82a 100644
> --- a/src/gallium/drivers/llvmpipe/lp_state_clip.c
> +++ b/src/gallium/drivers/llvmpipe/lp_state_clip.c
> @@ -53,7 +53,9 @@ llvmpipe_set_viewport_states(struct pipe_context *pipe,
> /* pass the viewport info to the draw module */
> draw_set_viewport_states(llvmpipe->draw, num_viewports, viewports);
>
> - llvmpipe->viewport = *viewports; /* struct copy */
> + memcpy(llvmpipe->viewports, viewports,
> + sizeof(struct pipe_viewport_state) * num_viewports);
> + llvmpipe->num_viewports = num_viewports;
> llvmpipe->dirty |= LP_NEW_VIEWPORT;
> }
>
> @@ -67,7 +69,9 @@ llvmpipe_set_scissor_states(struct pipe_context *pipe,
>
> draw_flush(llvmpipe->draw);
>
> - llvmpipe->scissor = *scissors; /* struct copy */
> + llvmpipe->num_scissors = num_scissors;
> + memcpy(llvmpipe->scissors, scissors,
> + sizeof(struct pipe_scissor_state) * num_scissors);
> llvmpipe->dirty |= LP_NEW_SCISSOR;
> }
>
> diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
> index aef222d..9002139 100644
> --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
> +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
> @@ -116,6 +116,18 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
> draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
> }
>
> + /* Figure out if we need viewport index */
> + vs_index = draw_find_shader_output(llvmpipe->draw,
> + TGSI_SEMANTIC_VIEWPORT_INDEX,
> + 0);
> + if (vs_index > 0) {
Couldn't vs_index legitimately be output zero?
Though I guess that would be more a problem with draw_find_shader_output
(as it returns 0 for not found indices) than viewport index here
specifically.
> + llvmpipe->viewport_index_slot = vinfo->num_attribs;
> + draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
> + } else {
> + llvmpipe->viewport_index_slot = 0;
> + }
> +
> +
> draw_compute_vertex_size(vinfo);
> lp_setup_set_vertex_info(llvmpipe->setup, vinfo);
> }
> @@ -164,7 +176,8 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
> &llvmpipe->blend_color);
>
> if (llvmpipe->dirty & LP_NEW_SCISSOR)
> - lp_setup_set_scissor(llvmpipe->setup, &llvmpipe->scissor);
> + lp_setup_set_scissors(llvmpipe->setup, llvmpipe->num_scissors,
> + llvmpipe->scissors);
>
> if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA) {
> lp_setup_set_alpha_ref_value(llvmpipe->setup,
> diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c
> index 036b129..5a174f6 100644
> --- a/src/gallium/drivers/llvmpipe/lp_surface.c
> +++ b/src/gallium/drivers/llvmpipe/lp_surface.c
> @@ -214,8 +214,8 @@ static void lp_blit(struct pipe_context *pipe,
> util_blitter_save_so_targets(lp->blitter, lp->num_so_targets,
> (struct pipe_stream_output_target**)lp->so_targets);
> util_blitter_save_rasterizer(lp->blitter, (void*)lp->rasterizer);
> - util_blitter_save_viewports(lp->blitter, 1, &lp->viewport);
> - util_blitter_save_scissors(lp->blitter, 1, &lp->scissor);
> + util_blitter_save_viewports(lp->blitter, lp->num_viewports, lp->viewports);
> + util_blitter_save_scissors(lp->blitter, lp->num_scissors, lp->scissors);
> util_blitter_save_fragment_shader(lp->blitter, lp->fs);
> util_blitter_save_blend(lp->blitter, (void*)lp->blend);
> util_blitter_save_depth_stencil_alpha(lp->blitter, (void*)lp->depth_stencil);
>
Otherwise looks good.
Roland
More information about the mesa-dev
mailing list