mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-04 21:20:37 +02:00
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 <zackr@vmware.com> Reviewed-by: José Fonseca<jfonseca@vmware.com> Reviewed-by: Brian Paul <brianp@vmware.com> Reviewed-by: Roland Scheidegger <sroland@vmware.com>
This commit is contained in:
parent
7756aae815
commit
97b8ae429e
11 changed files with 79 additions and 36 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue