From: Zack Rusin Date: Fri, 24 May 2013 20:28:19 +0000 (-0400) Subject: llvmpipe: implement support for multiple viewports X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=97b8ae429ec64003e258764db12ea69d4e978f6d;p=mesa.git llvmpipe: implement support for multiple viewports Largely related to making sure the rasterizer can correctly pick out the correct scissor box for the current viewport. Signed-off-by: Zack Rusin Reviewed-by: José Fonseca Reviewed-by: Brian Paul Reviewed-by: Roland Scheidegger --- diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index d605dba2260..54f38303ae5 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -75,10 +75,10 @@ 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]; 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]; @@ -116,6 +116,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 35630b95249..562fb518b28 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_MAX_VIEWPORTS: - return 1; + return PIPE_MAX_VIEWPORTS; } /* 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 a6dce24bec2..0134b700096 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -616,17 +616,20 @@ 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, + const struct pipe_scissor_state *scissors ) { + unsigned i; LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - assert(scissor); + assert(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 < PIPE_MAX_VIEWPORTS; ++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; } @@ -1010,10 +1013,13 @@ 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; + for (i = 0; i < PIPE_MAX_VIEWPORTS; ++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 @@ -1059,6 +1065,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 802ab0105e8..1f55aa41c7f 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -117,8 +117,8 @@ 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, + 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 6b35a0209ca..62d5a3c5796 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -103,11 +103,12 @@ 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]; + struct u_rect draw_regions[PIPE_MAX_VIEWPORTS]; /* intersection of fb & scissor */ struct { unsigned flags; @@ -195,6 +196,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 54f19cb9f3c..c2a069fe066 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 146f1bd07ca..30ce7490de9 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 b2c8cb52500..c1ba52e8ca6 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 a26c79f72f6..0e027fa9128 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_clip.c +++ b/src/gallium/drivers/llvmpipe/lp_state_clip.c @@ -55,7 +55,8 @@ llvmpipe_set_viewport_states(struct pipe_context *pipe, draw_set_viewport_states(llvmpipe->draw, start_slot, num_viewports, viewports); - llvmpipe->viewport = *viewports; /* struct copy */ + memcpy(llvmpipe->viewports + start_slot, viewports, + sizeof(struct pipe_viewport_state) * num_viewports); llvmpipe->dirty |= LP_NEW_VIEWPORT; } @@ -70,7 +71,8 @@ llvmpipe_set_scissor_states(struct pipe_context *pipe, draw_flush(llvmpipe->draw); - llvmpipe->scissor = *scissors; /* struct copy */ + memcpy(llvmpipe->scissors + start_slot, 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 aef222d20f6..9c5e84722f1 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) { + 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,7 @@ 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->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 961d0bcc734..2019d52f09c 100644 --- a/src/gallium/drivers/llvmpipe/lp_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_surface.c @@ -212,8 +212,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_viewport(lp->blitter, &lp->viewport); - util_blitter_save_scissor(lp->blitter, &lp->scissor); + util_blitter_save_viewport(lp->blitter, &lp->viewports[0]); + util_blitter_save_scissor(lp->blitter, &lp->scissors[0]); 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);