We need to invert the viewport translate/scale parameters when the state tracker thinks we have Y_0_TOP. If these cases, we have do to bypass mode by setting an identity viewport transform for x, z and inversion for y, or p.e. clear_with_quad won't work correctly. Clipping for xy in NDC space needs to be disabled then. --- src/gallium/drivers/nv50/nv50_context.h | 1 + src/gallium/drivers/nv50/nv50_state_validate.c | 55 +++++++++++++++++------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index 9b8cc4d..f66e0f2 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -140,6 +140,7 @@ struct nv50_context { struct pipe_scissor_state scissor; struct pipe_viewport_state viewport; struct pipe_framebuffer_state framebuffer; + int fb_invert_y; struct nv50_program *vertprog; struct nv50_program *fragprog; struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index 4981b1b..b65301b 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -31,6 +31,11 @@ nv50_state_validate_fb(struct nv50_context *nv50) struct pipe_framebuffer_state *fb = &nv50->framebuffer; unsigned i, w, h, gw = 0; + nv50->fb_invert_y = 0; + if (fb->nr_cbufs && (fb->cbufs[0]->texture->tex_usage & + PIPE_TEXTURE_USAGE_DISPLAY_TARGET)) + nv50->fb_invert_y = fb->cbufs[0]->height; + for (i = 0; i < fb->nr_cbufs; i++) { struct pipe_texture *pt = fb->cbufs[i]->texture; struct nouveau_bo *bo = nv50_miptree(pt)->bo; @@ -263,6 +268,7 @@ scissor_uptodate: if (nv50->dirty & (NV50_NEW_VIEWPORT | NV50_NEW_RASTERIZER)) { unsigned bypass; + struct pipe_viewport_state viewp; if (!nv50->rasterizer->pipe.bypass_vs_clip_and_viewport) bypass = 0; @@ -277,25 +283,42 @@ scissor_uptodate: so = so_new(12, 0); if (!bypass) { - so_method(so, tesla, NV50TCL_VIEWPORT_UNK1(0), 3); - so_data (so, fui(nv50->viewport.translate[0])); - so_data (so, fui(nv50->viewport.translate[1])); - so_data (so, fui(nv50->viewport.translate[2])); - so_method(so, tesla, NV50TCL_VIEWPORT_UNK0(0), 3); - so_data (so, fui(nv50->viewport.scale[0])); - so_data (so, fui(-nv50->viewport.scale[1])); - so_data (so, fui(nv50->viewport.scale[2])); - so_method(so, tesla, 0x192c, 1); - so_data (so, 1); - so_method(so, tesla, 0x0f90, 1); - so_data (so, 0); + memcpy(&viewp, &nv50->viewport, sizeof(viewp)); + + if (nv50->fb_invert_y) { + viewp.scale[1] = -nv50->viewport.scale[1]; + viewp.translate[1] = (float)nv50->fb_invert_y - + nv50->viewport.translate[1]; + } + so_method(so, tesla, 0x193c, 1); + so_data (so, 0x0000); } else { - so_method(so, tesla, 0x192c, 1); - so_data (so, 0); - so_method(so, tesla, 0x0f90, 1); - so_data (so, 1); + viewp.scale[0] = viewp.scale[2] = 1.0f; + viewp.translate[0] = viewp.translate[2] = 0.0f; + + if (nv50->fb_invert_y) { + viewp.scale[1] = -1.0f; + viewp.translate[1] = (float)nv50->fb_invert_y; + } else { + viewp.scale[1] = 1.0f; + viewp.translate[1] = 0.0f; + } + /* don't do xy-clipping in NDC space */ + so_method(so, tesla, 0x193c, 1); + so_data (so, 0x0800); } + so_method(so, tesla, 0x192c, 1); + so_data (so, 1); + so_method(so, tesla, NV50TCL_VIEWPORT_UNK1(0), 3); + so_data (so, fui(viewp.translate[0])); + so_data (so, fui(viewp.translate[1])); + so_data (so, fui(viewp.translate[2])); + so_method(so, tesla, NV50TCL_VIEWPORT_UNK0(0), 3); + so_data (so, fui(viewp.scale[0])); + so_data (so, fui(viewp.scale[1])); + so_data (so, fui(viewp.scale[2])); + so_ref(so, &nv50->state.viewport); so_ref(NULL, &so); nv50->state.dirty |= NV50_NEW_VIEWPORT; -- 1.6.3.3 --------------050205000506050205030809 Content-Type: text/plain; name="0003-nv50-invert-y-coordinates-in-transfers-if-needed.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename*0="0003-nv50-invert-y-coordinates-in-transfers-if-needed.patch"