diff options
-rw-r--r-- | src/gallium/drivers/nv50/nv50_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_state.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_state_validate.c | 93 |
3 files changed, 99 insertions, 0 deletions
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index d839cf701e..f532fa6bfb 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -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 * diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index 088df9e675..aa65fd482e 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -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 diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index 8921bfaf88..68d419f9fc 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -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); |