From 00f97ad5def91d485de0e5dd79fd39fae9ed3ce1 Mon Sep 17 00:00:00 2001 From: Edward O'Callaghan Date: Fri, 11 Dec 2015 22:43:30 +1100 Subject: [PATCH] softpipe: implement some support for multiple viewports 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 Reviewed-by: Roland Scheidegger --- src/gallium/drivers/softpipe/sp_context.h | 9 ++- src/gallium/drivers/softpipe/sp_quad.h | 1 + .../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 ++-- .../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 073b71a913e..8e5e24217a5 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 b29dad2ea95..2c2b018a24f 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 bac40c013b3..4cce9e9bc12 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 973803e909d..ac2d97825ce 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 885be739033..191494acbb8 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 59c22c6a67c..4de6296fce5 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 2a6a6f47f55..7e998af1325 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 768e8989b20..e2ecbdf2b01 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); -- 2.30.2