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 <eocallaghan@alterapraxis.com> Reviewed-by: Roland Scheidegger <sroland@vmware.com>
This commit is contained in:

committed by
Roland Scheidegger

parent
6c2c1e0ffe
commit
00f97ad5de
@@ -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;
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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 );
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user