[Mesa-dev] [PATCH 4/4] llvmpipe: implement support for multiple viewports
Zack Rusin
zackr at vmware.com
Thu May 23 13:33:43 PDT 2013
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) {
+ 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);
--
1.7.10.4
More information about the mesa-dev
mailing list