diff options
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_state_validate.c')
-rw-r--r-- | src/gallium/drivers/nv50/nv50_state_validate.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c new file mode 100644 index 0000000000..68d419f9fc --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -0,0 +1,162 @@ +#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) +{ + struct nouveau_winsys *nvws = nv50->screen->nvws; + struct nouveau_grobj *tesla = nv50->screen->tesla; + 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); + + if (nv50->dirty & NV50_NEW_ZSA) + so_emit(nvws, nv50->zsa->so); + + if (nv50->dirty & NV50_NEW_RASTERIZER) + so_emit(nvws, nv50->rasterizer->so); + + if (nv50->dirty & NV50_NEW_BLEND_COLOUR) { + so = so_new(5, 0); + so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 8); + so_data (so, fui(nv50->blend_colour.color[3])); + so_data (so, fui(nv50->blend_colour.color[0])); + so_data (so, fui(nv50->blend_colour.color[1])); + so_data (so, fui(nv50->blend_colour.color[2])); + so_emit(nvws, so); + so_ref(NULL, &so); + } + + if (nv50->dirty & NV50_NEW_STIPPLE) { + so = so_new(33, 0); + so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32); + for (i = 0; i < 32; i++) + so_data(so, nv50->stipple.stipple[i]); + so_emit(nvws, so); + so_ref(NULL, &so); + } + + if (nv50->dirty & NV50_NEW_SCISSOR) { + so = so_new(3, 0); + so_method(so, tesla, NV50TCL_SCISSOR_HORIZ, 2); + so_data (so, (nv50->scissor.maxx << 16) | + nv50->scissor.minx); + so_data (so, (nv50->scissor.maxy << 16) | + nv50->scissor.miny); + so_emit(nvws, so); + so_ref(NULL, &so); + } + + if (nv50->dirty & NV50_NEW_VIEWPORT) { + so = so_new(8, 0); + so_method(so, tesla, NV50TCL_VIEWPORT_UNK0(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_UNK1(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_emit(nvws, so); + so_ref(NULL, &so); + } + + nv50->dirty = 0; + return TRUE; +} + |