nv50: start on fb state
authorBen Skeggs <skeggsb@gmail.com>
Tue, 11 Mar 2008 17:50:53 +0000 (04:50 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Tue, 11 Mar 2008 17:50:53 +0000 (04:50 +1100)
src/gallium/drivers/nv50/nv50_context.h
src/gallium/drivers/nv50/nv50_state.c
src/gallium/drivers/nv50/nv50_state_validate.c

index d839cf701ebf33f388cb1bd99924b43d8c3cffe5..f532fa6bfb39cbba9098313fb6f26858188af111 100644 (file)
@@ -29,6 +29,7 @@
 #define NV50_NEW_SCISSOR       (1 << 4)
 #define NV50_NEW_VIEWPORT      (1 << 5)
 #define NV50_NEW_RASTERIZER    (1 << 6)
+#define NV50_NEW_FRAMEBUFFER   (1 << 7)
 
 struct nv50_blend_stateobj {
        struct pipe_blend_state pipe;
@@ -61,6 +62,7 @@ struct nv50_context {
        struct pipe_poly_stipple stipple;
        struct pipe_scissor_state scissor;
        struct pipe_viewport_state viewport;
+       struct pipe_framebuffer_state framebuffer;
 };
 
 static INLINE struct nv50_context *
index 088df9e675692903999da54a32440cd5b7a9b169..aa65fd482e48760d036073177913f8bec4ec6823 100644 (file)
@@ -386,6 +386,10 @@ static void
 nv50_set_framebuffer_state(struct pipe_context *pipe,
                           const struct pipe_framebuffer_state *fb)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->framebuffer = *fb;
+       nv50->dirty |= NV50_NEW_FRAMEBUFFER;
 }
 
 static void
index 8921bfaf887d587d8c75ee6f760b24c2fceb44dd..68d419f9fc85b8aff28d6ad17cab94dec4ec6309 100644 (file)
@@ -1,6 +1,96 @@
 #include "nv50_context.h"
 #include "nouveau/nouveau_stateobj.h"
 
+static void
+nv50_state_validate_fb(struct nv50_context *nv50)
+{
+       struct nouveau_grobj *tesla = nv50->screen->tesla;
+       struct nouveau_stateobj *so = so_new(128, 18);
+       struct pipe_framebuffer_state *fb = &nv50->framebuffer;
+       unsigned i, w, h, gw = 0;
+
+       for (i = 0; i < fb->num_cbufs; i++) {
+               if (!gw) {
+                       w = fb->cbufs[i]->width;
+                       h = fb->cbufs[i]->height;
+                       gw = 1;
+               } else {
+                       assert(w != fb->cbufs[i]->width);
+                       assert(h != fb->cbufs[i]->height);
+               }
+
+               so_method(so, tesla, NV50TCL_RT_HORIZ(i), 2);
+               so_data  (so, fb->cbufs[i]->width);
+               so_data  (so, fb->cbufs[i]->height);
+
+               so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5);
+               so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset,
+                         NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0);
+               so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset,
+                         NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0);
+               switch (fb->cbufs[i]->format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+                       so_data(so, 0xcf);
+                       break;
+               case PIPE_FORMAT_R5G6B5_UNORM:
+                       so_data(so, 0xe8);
+                       break;
+               default:
+                       {
+                               char fmt[128];
+                               pf_sprint_name(fmt, fb->cbufs[i]->format);
+                               NOUVEAU_ERR("AIIII unknown format %s\n", fmt);
+                       }                   
+                       so_data(so, 0xe6);
+                       break;
+               }
+               so_data(so, 0x00000040);
+               so_data(so, 0x00000000);
+       }
+
+       if (fb->zsbuf) {
+               if (!gw) {
+                       w = fb->zsbuf->width;
+                       h = fb->zsbuf->height;
+                       gw = 1;
+               } else {
+                       assert(w != fb->zsbuf->width);
+                       assert(h != fb->zsbuf->height);
+               }
+
+               so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5);
+               so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset,
+                         NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0);
+               so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset,
+                         NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0);
+               switch (fb->zsbuf->format) {
+               case PIPE_FORMAT_Z24S8_UNORM:
+                       so_data(so, 0x16);
+                       break;
+               default:
+                       {
+                               char fmt[128];
+                               pf_sprint_name(fmt, fb->zsbuf->format);
+                               NOUVEAU_ERR("AIIII unknown format %s\n", fmt);
+                       }                   
+                       so_data(so, 0x16);
+                       break;
+               }
+               so_data(so, 0x00000040);
+               so_data(so, 0x00000000);
+       }
+
+       so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ, 2);
+       so_data  (so, w << 16);
+       so_data  (so, h << 16);
+       so_method(so, tesla, 0xff0, 2);
+       so_data  (so, w << 16);
+       so_data  (so, h << 16);
+
+       so_emit(nv50->screen->nvws, so);
+       so_ref(NULL, &so);
+}
+
 boolean
 nv50_state_validate(struct nv50_context *nv50)
 {
@@ -9,6 +99,9 @@ nv50_state_validate(struct nv50_context *nv50)
        struct nouveau_stateobj *so;
        unsigned i;
 
+       if (nv50->dirty & NV50_NEW_FRAMEBUFFER)
+               nv50_state_validate_fb(nv50);
+
        if (nv50->dirty & NV50_NEW_BLEND)
                so_emit(nvws, nv50->blend->so);