summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h2
-rw-r--r--src/gallium/drivers/nv50/nv50_state.c4
-rw-r--r--src/gallium/drivers/nv50/nv50_state_validate.c93
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 d839cf701eb..f532fa6bfb3 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 088df9e6756..aa65fd482e4 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 8921bfaf887..68d419f9fc8 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);