These patches should fix viewport and scissoring
being y-inverted.
The effect should be visible in the gearbox demo.

Christoph
>From 2bd1767340698ff6efb38c1869febdde52c4369d Mon Sep 17 00:00:00 2001
From: Christoph Bumiller <[email protected]>
Date: Sun, 12 Jul 2009 15:39:41 +0200
Subject: [PATCH 1/3] nv50: use correct scissor reg

---
 src/gallium/drivers/nv50/nv50_screen.c         |    4 ++++
 src/gallium/drivers/nv50/nv50_state_validate.c |   21 +++++++++++++++------
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_screen.c 
b/src/gallium/drivers/nv50/nv50_screen.c
index b4d6530..fd41d88 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -416,6 +416,10 @@ nv50_screen_create(struct pipe_winsys *ws, struct 
nouveau_device *dev)
        so_method(so, screen->tesla, 0x1234, 1);
        so_data  (so, 1);
 
+       /* activate first scissor rectangle */
+       so_method(so, screen->tesla, 0x0e00, 1);
+       so_data  (so, 1);
+
        so_emit(chan, so);
        so_ref (so, &screen->static_init);
        so_ref (NULL, &so);
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c 
b/src/gallium/drivers/nv50/nv50_state_validate.c
index 1edf741..4981b1b 100644
--- a/src/gallium/drivers/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -124,12 +124,18 @@ nv50_state_validate_fb(struct nv50_context *nv50)
        so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ, 2);
        so_data  (so, w << 16);
        so_data  (so, h << 16);
+       /* set window scissor rectangle to window extents */
        so_method(so, tesla, 0x0e04, 2);
        so_data  (so, w << 16);
        so_data  (so, h << 16);
-       so_method(so, tesla, 0xdf8, 2);
+       /* set window lower left corner */
+       so_method(so, tesla, 0x0df8, 2);
        so_data  (so, 0);
        so_data  (so, h);
+       /* set screen scissor rectangle */
+       so_method(so, tesla, 0x0ff4, 2);
+       so_data  (so, w << 16);
+       so_data  (so, h << 16);
 
        so_ref(so, &nv50->state.fb);
        so_ref(NULL, &so);
@@ -238,13 +244,16 @@ nv50_state_validate(struct nv50_context *nv50)
                nv50->state.scissor_enabled = rast->scissor;
 
                so = so_new(3, 0);
-               so_method(so, tesla, 0x0ff4, 2);
+               so_method(so, tesla, 0x0e04, 2);
                if (nv50->state.scissor_enabled) {
-                       so_data(so, ((s->maxx - s->minx) << 16) | s->minx);
-                       so_data(so, ((s->maxy - s->miny) << 16) | s->miny);
+                       /* pipe always uses Y_0_TOP for scissor state */
+                       unsigned scs_top = nv50->framebuffer.height - s->miny;
+                       unsigned scs_btm = nv50->framebuffer.height - s->maxy;
+                       so_data(so, (s->maxx << 16) | s->minx);
+                       so_data(so, (scs_top << 16) | scs_btm);
                } else {
-                       so_data(so, (8192 << 16));
-                       so_data(so, (8192 << 16));
+                       so_data(so, (nv50->framebuffer.width << 16));
+                       so_data(so, (nv50->framebuffer.height << 16));
                }
                so_ref(so, &nv50->state.scissor);
                so_ref(NULL, &so);
-- 
1.6.3.3

>From b5e44bc72717c9774e943cb7073b662a4bf74967 Mon Sep 17 00:00:00 2001
From: Christoph Bumiller <[email protected]>
Date: Sun, 12 Jul 2009 15:45:57 +0200
Subject: [PATCH 2/3] nv50: fix viewport transform

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

>From 345fe5b25c1fbc0bfbff1c93ca3f2d43f7752801 Mon Sep 17 00:00:00 2001
From: Christoph Bumiller <[email protected]>
Date: Sun, 12 Jul 2009 15:51:16 +0200
Subject: [PATCH 3/3] nv50: invert y coordinates in transfers if needed

When the state tracker assumes Y_0_BOTTOM (i.e. when rendering
to an OpenGL FBO), we need to invert the y coordinates as well,
since for M2MF, y = 0 is the beginning of the memory area.
---
 src/gallium/drivers/nv50/nv50_transfer.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_transfer.c 
b/src/gallium/drivers/nv50/nv50_transfer.c
index d0b7f0b..f6a8a47 100644
--- a/src/gallium/drivers/nv50/nv50_transfer.c
+++ b/src/gallium/drivers/nv50/nv50_transfer.c
@@ -76,13 +76,13 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct 
nouveau_bo *src_bo,
                OUT_RELOCl(chan, dst_bo, dst_offset, dst_reloc);
                if (src_bo->tile_flags) {
                        BEGIN_RING(chan, m2mf, 0x0218, 1);
-                       OUT_RING  (chan, (dy << 16) | sx);
+                       OUT_RING  (chan, (sy << 16) | sx);
                } else {
                        src_offset += (line_count * src_pitch);
                }
                if (dst_bo->tile_flags) {
                        BEGIN_RING(chan, m2mf, 0x0234, 1);
-                       OUT_RING  (chan, (sy << 16) | dx);
+                       OUT_RING  (chan, (dy << 16) | dx);
                } else {
                        dst_offset += (line_count * dst_pitch);
                }
@@ -112,6 +112,9 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct 
pipe_texture *pt,
        unsigned image = 0;
        int ret;
 
+       if (!(pt->tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET))
+               y = pt->height[level] - y - h;
+
        if (pt->target == PIPE_TEXTURE_CUBE)
                image = face;
        else
-- 
1.6.3.3

_______________________________________________
Nouveau mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to