summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nv40
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nv40')
-rw-r--r--src/gallium/drivers/nv40/Makefile9
-rw-r--r--src/gallium/drivers/nv40/nv40_context.c251
-rw-r--r--src/gallium/drivers/nv40/nv40_context.h162
-rw-r--r--src/gallium/drivers/nv40/nv40_fragprog.c132
-rw-r--r--src/gallium/drivers/nv40/nv40_fragtex.c48
-rw-r--r--src/gallium/drivers/nv40/nv40_miptree.c57
-rw-r--r--src/gallium/drivers/nv40/nv40_query.c10
-rw-r--r--src/gallium/drivers/nv40/nv40_screen.c279
-rw-r--r--src/gallium/drivers/nv40/nv40_screen.h36
-rw-r--r--src/gallium/drivers/nv40/nv40_state.c297
-rw-r--r--src/gallium/drivers/nv40/nv40_state.h2
-rw-r--r--src/gallium/drivers/nv40/nv40_state_blend.c40
-rw-r--r--src/gallium/drivers/nv40/nv40_state_clip.c18
-rw-r--r--src/gallium/drivers/nv40/nv40_state_emit.c137
-rw-r--r--src/gallium/drivers/nv40/nv40_state_fb.c155
-rw-r--r--src/gallium/drivers/nv40/nv40_state_rasterizer.c17
-rw-r--r--src/gallium/drivers/nv40/nv40_state_scissor.c34
-rw-r--r--src/gallium/drivers/nv40/nv40_state_stipple.c39
-rw-r--r--src/gallium/drivers/nv40/nv40_state_viewport.c29
-rw-r--r--src/gallium/drivers/nv40/nv40_state_zsa.c17
-rw-r--r--src/gallium/drivers/nv40/nv40_surface.c72
-rw-r--r--src/gallium/drivers/nv40/nv40_vbo.c253
-rw-r--r--src/gallium/drivers/nv40/nv40_vertprog.c60
23 files changed, 1292 insertions, 862 deletions
diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile
index 2a9de4a2dc..3369a21574 100644
--- a/src/gallium/drivers/nv40/Makefile
+++ b/src/gallium/drivers/nv40/Makefile
@@ -11,8 +11,17 @@ DRIVER_SOURCES = \
nv40_fragtex.c \
nv40_miptree.c \
nv40_query.c \
+ nv40_screen.c \
nv40_state.c \
+ nv40_state_blend.c \
+ nv40_state_clip.c \
nv40_state_emit.c \
+ nv40_state_fb.c \
+ nv40_state_rasterizer.c \
+ nv40_state_scissor.c \
+ nv40_state_stipple.c \
+ nv40_state_viewport.c \
+ nv40_state_zsa.c \
nv40_surface.c \
nv40_vbo.c \
nv40_vertprog.c
diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c
index 8b5cc693de..203c843a01 100644
--- a/src/gallium/drivers/nv40/nv40_context.c
+++ b/src/gallium/drivers/nv40/nv40_context.c
@@ -4,84 +4,7 @@
#include "pipe/p_util.h"
#include "nv40_context.h"
-
-#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf
-#define NV4X_GRCLASS4497_CHIPSETS 0x00005450
-#define NV6X_GRCLASS4497_CHIPSETS 0x00000088
-
-static const char *
-nv40_get_name(struct pipe_context *pipe)
-{
- struct nv40_context *nv40 = nv40_context(pipe);
- static char buffer[128];
-
- snprintf(buffer, sizeof(buffer), "NV%02X", nv40->chipset);
- return buffer;
-}
-
-static const char *
-nv40_get_vendor(struct pipe_context *pipe)
-{
- return "nouveau";
-}
-
-static int
-nv40_get_param(struct pipe_context *pipe, int param)
-{
- switch (param) {
- case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
- return 16;
- case PIPE_CAP_NPOT_TEXTURES:
- return 1;
- case PIPE_CAP_TWO_SIDED_STENCIL:
- return 1;
- case PIPE_CAP_GLSL:
- return 0;
- case PIPE_CAP_S3TC:
- return 0;
- case PIPE_CAP_ANISOTROPIC_FILTER:
- return 1;
- case PIPE_CAP_POINT_SPRITE:
- return 1;
- case PIPE_CAP_MAX_RENDER_TARGETS:
- return 4;
- case PIPE_CAP_OCCLUSION_QUERY:
- return 1;
- case PIPE_CAP_TEXTURE_SHADOW_MAP:
- return 1;
- case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
- return 13;
- case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
- return 10;
- case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
- return 13;
- default:
- NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
- return 0;
- }
-}
-
-static float
-nv40_get_paramf(struct pipe_context *pipe, int param)
-{
- switch (param) {
- case PIPE_CAP_MAX_LINE_WIDTH:
- case PIPE_CAP_MAX_LINE_WIDTH_AA:
- return 10.0;
- case PIPE_CAP_MAX_POINT_WIDTH:
- case PIPE_CAP_MAX_POINT_WIDTH_AA:
- return 64.0;
- case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
- return 16.0;
- case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
- return 16.0;
- case PIPE_CAP_BITMAP_TEXCOORD_BIAS:
- return 0.0;
- default:
- NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
- return 0.0;
- }
-}
+#include "nv40_screen.h"
static void
nv40_flush(struct pipe_context *pipe, unsigned flags)
@@ -97,7 +20,7 @@ nv40_flush(struct pipe_context *pipe, unsigned flags)
}
if (flags & PIPE_FLUSH_WAIT) {
- nvws->notifier_reset(nv40->hw->sync, 0);
+ nvws->notifier_reset(nv40->screen->sync, 0);
BEGIN_RING(curie, 0x104, 1);
OUT_RING (0);
BEGIN_RING(curie, 0x100, 1);
@@ -107,149 +30,7 @@ nv40_flush(struct pipe_context *pipe, unsigned flags)
FIRE_RING();
if (flags & PIPE_FLUSH_WAIT)
- nvws->notifier_wait(nv40->hw->sync, 0, 0, 2000);
-}
-
-static void
-nv40_channel_takedown(struct nv40_channel_context *cnv40)
-{
- struct nouveau_winsys *nvws = cnv40->nvws;
-
- nvws->res_free(&cnv40->vp_exec_heap);
- nvws->res_free(&cnv40->vp_data_heap);
- nvws->res_free(&cnv40->query_heap);
- nvws->notifier_free(&cnv40->query);
- nvws->notifier_free(&cnv40->sync);
- nvws->grobj_free(&cnv40->curie);
- free(cnv40);
-}
-
-static struct nv40_channel_context *
-nv40_channel_init(struct pipe_winsys *ws, struct nouveau_winsys *nvws,
- unsigned chipset)
-{
- struct nv40_channel_context *cnv40 = NULL;
- struct nouveau_stateobj *so;
- unsigned curie_class = 0;
- int ret;
-
- switch (chipset & 0xf0) {
- case 0x40:
- if (NV4X_GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f)))
- curie_class = NV40TCL;
- else
- if (NV4X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
- curie_class = NV44TCL;
- break;
- case 0x60:
- if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
- curie_class = NV44TCL;
- break;
- default:
- break;
- }
-
- if (!curie_class) {
- NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", chipset);
- return NULL;
- }
-
- cnv40 = CALLOC(1, sizeof(struct nv40_channel_context));
- if (!cnv40)
- return NULL;
- cnv40->chipset = chipset;
- cnv40->nvws = nvws;
-
- /* Notifier for sync purposes */
- ret = nvws->notifier_alloc(nvws, 1, &cnv40->sync);
- if (ret) {
- NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
- nv40_channel_takedown(cnv40);
- return NULL;
- }
-
- /* Query objects */
- ret = nvws->notifier_alloc(nvws, 32, &cnv40->query);
- if (ret) {
- NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
- nv40_channel_takedown(cnv40);
- return NULL;
- }
-
- ret = nvws->res_init(&cnv40->query_heap, 0, 32);
- if (ret) {
- NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
- nv40_channel_takedown(cnv40);
- return NULL;
- }
-
- /* Vtxprog resources */
- if (nvws->res_init(&cnv40->vp_exec_heap, 0, 512) ||
- nvws->res_init(&cnv40->vp_data_heap, 0, 256)) {
- nv40_channel_takedown(cnv40);
- return NULL;
- }
-
- /* 3D object */
- ret = nvws->grobj_alloc(nvws, curie_class, &cnv40->curie);
- if (ret) {
- NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
- return FALSE;
- }
-
- /* Static curie initialisation */
- so = so_new(128, 0);
- so_method(so, cnv40->curie, NV40TCL_DMA_NOTIFY, 1);
- so_data (so, cnv40->sync->handle);
- so_method(so, cnv40->curie, NV40TCL_DMA_TEXTURE0, 2);
- so_data (so, nvws->channel->vram->handle);
- so_data (so, nvws->channel->gart->handle);
- so_method(so, cnv40->curie, NV40TCL_DMA_COLOR1, 1);
- so_data (so, nvws->channel->vram->handle);
- so_method(so, cnv40->curie, NV40TCL_DMA_COLOR0, 2);
- so_data (so, nvws->channel->vram->handle);
- so_data (so, nvws->channel->vram->handle);
- so_method(so, cnv40->curie, NV40TCL_DMA_VTXBUF0, 2);
- so_data (so, nvws->channel->vram->handle);
- so_data (so, nvws->channel->gart->handle);
- so_method(so, cnv40->curie, NV40TCL_DMA_FENCE, 2);
- so_data (so, 0);
- so_data (so, cnv40->query->handle);
- so_method(so, cnv40->curie, NV40TCL_DMA_UNK01AC, 2);
- so_data (so, nvws->channel->vram->handle);
- so_data (so, nvws->channel->vram->handle);
- so_method(so, cnv40->curie, NV40TCL_DMA_COLOR2, 2);
- so_data (so, nvws->channel->vram->handle);
- so_data (so, nvws->channel->vram->handle);
-
- so_method(so, cnv40->curie, 0x1ea4, 3);
- so_data (so, 0x00000010);
- so_data (so, 0x01000100);
- so_data (so, 0xff800006);
-
- /* vtxprog output routing */
- so_method(so, cnv40->curie, 0x1fc4, 1);
- so_data (so, 0x06144321);
- so_method(so, cnv40->curie, 0x1fc8, 2);
- so_data (so, 0xedcba987);
- so_data (so, 0x00000021);
- so_method(so, cnv40->curie, 0x1fd0, 1);
- so_data (so, 0x00171615);
- so_method(so, cnv40->curie, 0x1fd4, 1);
- so_data (so, 0x001b1a19);
-
- so_method(so, cnv40->curie, 0x1ef8, 1);
- so_data (so, 0x0020ffff);
- so_method(so, cnv40->curie, 0x1d64, 1);
- so_data (so, 0x00d30000);
- so_method(so, cnv40->curie, 0x1e94, 1);
- so_data (so, 0x00000001);
-
- so_emit(nvws, so);
- so_ref(NULL, &so);
- nvws->push_flush(nvws->channel, 0);
-
- return cnv40;
+ nvws->notifier_wait(nv40->screen->sync, 0, 0, 2000);
}
static void
@@ -259,40 +40,30 @@ nv40_destroy(struct pipe_context *pipe)
if (nv40->draw)
draw_destroy(nv40->draw);
-
- if (nv40->hw) {
- if (--nv40->hw->refcount == 0)
- nv40_channel_takedown(nv40->hw);
- }
-
free(nv40);
}
struct pipe_context *
-nv40_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws,
- unsigned chipset)
+nv40_create(struct pipe_screen *pscreen, unsigned pctx_id)
{
+ struct nv40_screen *screen = nv40_screen(pscreen);
+ struct pipe_winsys *ws = pscreen->winsys;
struct nv40_context *nv40;
+ unsigned chipset = screen->chipset;
+ struct nouveau_winsys *nvws = screen->nvws;
nv40 = CALLOC(1, sizeof(struct nv40_context));
if (!nv40)
return NULL;
-
- nv40->hw = nv40_channel_init(ws, nvws, chipset);
- if (!nv40->hw) {
- nv40_destroy(&nv40->pipe);
- return NULL;
- }
+ nv40->screen = screen;
+ nv40->pctx_id = pctx_id;
nv40->chipset = chipset;
nv40->nvws = nvws;
nv40->pipe.winsys = ws;
+ nv40->pipe.screen = pscreen;
nv40->pipe.destroy = nv40_destroy;
- nv40->pipe.get_name = nv40_get_name;
- nv40->pipe.get_vendor = nv40_get_vendor;
- nv40->pipe.get_param = nv40_get_param;
- nv40->pipe.get_paramf = nv40_get_paramf;
nv40->pipe.draw_arrays = nv40_draw_arrays;
nv40->pipe.draw_elements = nv40_draw_elements;
nv40->pipe.clear = nv40_clear;
diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h
index f511759e3b..e118776306 100644
--- a/src/gallium/drivers/nv40/nv40_context.h
+++ b/src/gallium/drivers/nv40/nv40_context.h
@@ -11,7 +11,7 @@
#include "nouveau/nouveau_gldefs.h"
#define NOUVEAU_PUSH_CONTEXT(ctx) \
- struct nv40_channel_context *ctx = nv40->hw
+ struct nv40_screen *ctx = nv40->screen
#include "nouveau/nouveau_push.h"
#include "nouveau/nouveau_stateobj.h"
@@ -22,6 +22,45 @@
#define NOUVEAU_MSG(fmt, args...) \
fprintf(stderr, "nouveau: "fmt, ##args);
+enum nv40_state_index {
+ NV40_STATE_FB = 0,
+ NV40_STATE_VIEWPORT = 1,
+ NV40_STATE_BLEND = 2,
+ NV40_STATE_RAST = 3,
+ NV40_STATE_ZSA = 4,
+ NV40_STATE_BCOL = 5,
+ NV40_STATE_CLIP = 6,
+ NV40_STATE_SCISSOR = 7,
+ NV40_STATE_STIPPLE = 8,
+ NV40_STATE_FRAGPROG = 9,
+ NV40_STATE_VERTPROG = 10,
+ NV40_STATE_FRAGTEX0 = 11,
+ NV40_STATE_FRAGTEX1 = 12,
+ NV40_STATE_FRAGTEX2 = 13,
+ NV40_STATE_FRAGTEX3 = 14,
+ NV40_STATE_FRAGTEX4 = 15,
+ NV40_STATE_FRAGTEX5 = 16,
+ NV40_STATE_FRAGTEX6 = 17,
+ NV40_STATE_FRAGTEX7 = 18,
+ NV40_STATE_FRAGTEX8 = 19,
+ NV40_STATE_FRAGTEX9 = 20,
+ NV40_STATE_FRAGTEX10 = 21,
+ NV40_STATE_FRAGTEX11 = 22,
+ NV40_STATE_FRAGTEX12 = 23,
+ NV40_STATE_FRAGTEX13 = 24,
+ NV40_STATE_FRAGTEX14 = 25,
+ NV40_STATE_FRAGTEX15 = 26,
+ NV40_STATE_VERTTEX0 = 27,
+ NV40_STATE_VERTTEX1 = 28,
+ NV40_STATE_VERTTEX2 = 29,
+ NV40_STATE_VERTTEX3 = 30,
+ NV40_STATE_VTXBUF = 31,
+ NV40_STATE_VTXFMT = 32,
+ NV40_STATE_MAX = 33
+};
+
+#include "nv40_screen.h"
+
#define NV40_NEW_BLEND (1 << 0)
#define NV40_NEW_RAST (1 << 1)
#define NV40_NEW_ZSA (1 << 2)
@@ -34,68 +73,70 @@
#define NV40_NEW_VERTPROG (1 << 9)
#define NV40_NEW_FRAGPROG (1 << 10)
#define NV40_NEW_ARRAYS (1 << 11)
+#define NV40_NEW_UCP (1 << 12)
-struct nv40_channel_context {
- struct nouveau_winsys *nvws;
- unsigned refcount;
+#define NV40_FALLBACK_TNL (1 << 0)
+#define NV40_FALLBACK_RAST (1 << 1)
+
+struct nv40_rasterizer_state {
+ struct pipe_rasterizer_state pipe;
+ struct nouveau_stateobj *so;
+};
- unsigned chipset;
+struct nv40_zsa_state {
+ struct pipe_depth_stencil_alpha_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+struct nv40_blend_state {
+ struct pipe_blend_state pipe;
+ struct nouveau_stateobj *so;
+};
- /* HW graphics objects */
- struct nouveau_grobj *curie;
- struct nouveau_notifier *sync;
- /* Query object resources */
- struct nouveau_notifier *query;
- struct nouveau_resource *query_heap;
+struct nv40_state {
+ unsigned scissor_enabled;
+ unsigned stipple_enabled;
+ unsigned fp_samplers;
- /* Vtxprog resources */
- struct nouveau_resource *vp_exec_heap;
- struct nouveau_resource *vp_data_heap;
+ uint64_t dirty;
+ struct nouveau_stateobj *hw[NV40_STATE_MAX];
};
struct nv40_context {
struct pipe_context pipe;
+
struct nouveau_winsys *nvws;
+ struct nv40_screen *screen;
+ unsigned pctx_id;
- struct nv40_channel_context *hw;
struct draw_context *draw;
int chipset;
- uint32_t dirty;
-
+ /* HW state derived from pipe states */
+ struct nv40_state state;
+ unsigned fallback;
+
+ /* Context state */
+ unsigned dirty;
+ struct pipe_scissor_state scissor;
+ unsigned stipple[32];
+ struct pipe_clip_state clip;
+ struct nv40_vertex_program *vertprog;
+ struct nv40_fragment_program *fragprog;
+ struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+ struct nv40_rasterizer_state *rasterizer;
+ struct nv40_zsa_state *zsa;
+ struct nv40_blend_state *blend;
+ struct pipe_blend_color blend_colour;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_buffer *idxbuf;
+ unsigned idxbuf_format;
struct nv40_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
struct nv40_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
unsigned dirty_samplers;
- unsigned fp_samplers;
- unsigned vp_samplers;
-
- struct nouveau_stateobj *so_framebuffer;
- struct nouveau_stateobj *so_fragtex[16];
- struct nouveau_stateobj *so_vtxbuf;
- struct nouveau_stateobj *so_blend;
- struct nouveau_stateobj *so_rast;
- struct nouveau_stateobj *so_zsa;
- struct nouveau_stateobj *so_bcol;
- struct nouveau_stateobj *so_scissor;
- struct nouveau_stateobj *so_viewport;
- struct nouveau_stateobj *so_stipple;
-
- struct {
- struct nv40_vertex_program *active;
-
- struct nv40_vertex_program *current;
- struct pipe_buffer *constant_buf;
- } vertprog;
-
- struct {
- struct nv40_fragment_program *active;
-
- struct nv40_fragment_program *current;
- struct pipe_buffer *constant_buf;
- } fragprog;
-
struct pipe_vertex_buffer vtxbuf[PIPE_ATTRIB_MAX];
struct pipe_vertex_element vtxelt[PIPE_ATTRIB_MAX];
};
@@ -106,27 +147,29 @@ nv40_context(struct pipe_context *pipe)
return (struct nv40_context *)pipe;
}
+struct nv40_state_entry {
+ boolean (*validate)(struct nv40_context *nv40);
+ struct {
+ unsigned pipe;
+ unsigned hw;
+ } dirty;
+};
+
extern void nv40_init_state_functions(struct nv40_context *nv40);
extern void nv40_init_surface_functions(struct nv40_context *nv40);
extern void nv40_init_miptree_functions(struct nv40_context *nv40);
extern void nv40_init_query_functions(struct nv40_context *nv40);
+extern void nv40_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
/* nv40_draw.c */
extern struct draw_stage *nv40_draw_render_stage(struct nv40_context *nv40);
/* nv40_vertprog.c */
-extern void nv40_vertprog_translate(struct nv40_context *,
- struct nv40_vertex_program *);
-extern void nv40_vertprog_bind(struct nv40_context *,
- struct nv40_vertex_program *);
extern void nv40_vertprog_destroy(struct nv40_context *,
struct nv40_vertex_program *);
/* nv40_fragprog.c */
-extern void nv40_fragprog_translate(struct nv40_context *,
- struct nv40_fragment_program *);
-extern void nv40_fragprog_bind(struct nv40_context *,
- struct nv40_fragment_program *);
extern void nv40_fragprog_destroy(struct nv40_context *,
struct nv40_fragment_program *);
@@ -136,6 +179,19 @@ extern void nv40_fragtex_bind(struct nv40_context *);
/* nv40_state.c and friends */
extern void nv40_emit_hw_state(struct nv40_context *nv40);
extern void nv40_state_tex_update(struct nv40_context *nv40);
+extern struct nv40_state_entry nv40_state_clip;
+extern struct nv40_state_entry nv40_state_rasterizer;
+extern struct nv40_state_entry nv40_state_scissor;
+extern struct nv40_state_entry nv40_state_stipple;
+extern struct nv40_state_entry nv40_state_fragprog;
+extern struct nv40_state_entry nv40_state_vertprog;
+extern struct nv40_state_entry nv40_state_blend;
+extern struct nv40_state_entry nv40_state_blend_colour;
+extern struct nv40_state_entry nv40_state_zsa;
+extern struct nv40_state_entry nv40_state_viewport;
+extern struct nv40_state_entry nv40_state_framebuffer;
+extern struct nv40_state_entry nv40_state_fragtex;
+extern struct nv40_state_entry nv40_state_vbo;
/* nv40_vbo.c */
extern boolean nv40_draw_arrays(struct pipe_context *, unsigned mode,
diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nv40/nv40_fragprog.c
index 07a418c1e9..3c4ea7e99e 100644
--- a/src/gallium/drivers/nv40/nv40_fragprog.c
+++ b/src/gallium/drivers/nv40/nv40_fragprog.c
@@ -668,7 +668,7 @@ nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc,
return TRUE;
}
-void
+static void
nv40_fragprog_translate(struct nv40_context *nv40,
struct nv40_fragment_program *fp)
{
@@ -750,28 +750,80 @@ nv40_fragprog_translate(struct nv40_context *nv40,
fp->insn[fpc->inst_offset + 3] = 0x00000000;
fp->translated = TRUE;
- fp->on_hw = FALSE;
out_err:
tgsi_parse_free(&parse);
free(fpc);
}
-void
-nv40_fragprog_bind(struct nv40_context *nv40, struct nv40_fragment_program *fp)
+static void
+nv40_fragprog_upload(struct nv40_context *nv40,
+ struct nv40_fragment_program *fp)
+{
+ struct pipe_winsys *ws = nv40->pipe.winsys;
+ const uint32_t le = 1;
+ uint32_t *map;
+ int i;
+
+ map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+#if 0
+ for (i = 0; i < fp->insn_len; i++) {
+ NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
+ }
+#endif
+
+ if ((*(const uint8_t *)&le)) {
+ for (i = 0; i < fp->insn_len; i++) {
+ map[i] = fp->insn[i];
+ }
+ } else {
+ /* Weird swapping for big-endian chips */
+ for (i = 0; i < fp->insn_len; i++) {
+ map[i] = ((fp->insn[i] & 0xffff) << 16) |
+ ((fp->insn[i] >> 16) & 0xffff);
+ }
+ }
+
+ ws->buffer_unmap(ws, fp->buffer);
+}
+
+static boolean
+nv40_fragprog_validate(struct nv40_context *nv40)
{
+ struct nv40_fragment_program *fp = nv40->fragprog;
+ struct pipe_buffer *constbuf =
+ nv40->constbuf[PIPE_SHADER_FRAGMENT];
struct pipe_winsys *ws = nv40->pipe.winsys;
struct nouveau_stateobj *so;
int i;
+ if (fp->translated)
+ goto update_constants;
+
+ nv40_fragprog_translate(nv40, fp);
if (!fp->translated) {
- nv40_fragprog_translate(nv40, fp);
- if (!fp->translated)
- assert(0);
+ nv40->fallback |= NV40_FALLBACK_RAST;
+ return FALSE;
}
+ fp->buffer = ws->buffer_create(ws, 0x100, 0, fp->insn_len * 4);
+ nv40_fragprog_upload(nv40, fp);
+
+ so = so_new(4, 1);
+ so_method(so, nv40->screen->curie, NV40TCL_FP_ADDRESS, 1);
+ so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
+ NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+ NV40TCL_FP_ADDRESS_DMA0, NV40TCL_FP_ADDRESS_DMA1);
+ so_method(so, nv40->screen->curie, NV40TCL_FP_CONTROL, 1);
+ so_data (so, fp->fp_control);
+ so_ref(so, &fp->so);
+
+update_constants:
if (fp->nr_consts) {
- float *map = ws->buffer_map(ws, nv40->fragprog.constant_buf,
- PIPE_BUFFER_USAGE_CPU_READ);
+ boolean new_consts = FALSE;
+ float *map;
+
+ map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ);
for (i = 0; i < fp->nr_consts; i++) {
struct nv40_fragment_program_data *fpd = &fp->consts[i];
uint32_t *p = &fp->insn[fpd->offset];
@@ -780,56 +832,20 @@ nv40_fragprog_bind(struct nv40_context *nv40, struct nv40_fragment_program *fp)
if (!memcmp(p, cb, 4 * sizeof(float)))
continue;
memcpy(p, cb, 4 * sizeof(float));
- fp->on_hw = 0;
+ new_consts = TRUE;
}
- ws->buffer_unmap(ws, nv40->fragprog.constant_buf);
- }
+ ws->buffer_unmap(ws, constbuf);
- if (!fp->on_hw) {
- const uint32_t le = 1;
- uint32_t *map;
-
- if (!fp->buffer)
- fp->buffer = ws->buffer_create(ws, 0x100, 0,
- fp->insn_len * 4);
- map = ws->buffer_map(ws, fp->buffer,
- PIPE_BUFFER_USAGE_CPU_WRITE);
-
-#if 0
- for (i = 0; i < fp->insn_len; i++) {
- NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
- }
-#endif
-
- if ((*(const uint8_t *)&le)) {
- for (i = 0; i < fp->insn_len; i++) {
- map[i] = fp->insn[i];
- }
- } else {
- /* Weird swapping for big-endian chips */
- for (i = 0; i < fp->insn_len; i++) {
- map[i] = ((fp->insn[i] & 0xffff) << 16) |
- ((fp->insn[i] >> 16) & 0xffff);
- }
- }
-
- ws->buffer_unmap(ws, fp->buffer);
- fp->on_hw = TRUE;
+ if (new_consts)
+ nv40_fragprog_upload(nv40, fp);
}
- so = so_new(4, 1);
- so_method(so, nv40->hw->curie, NV40TCL_FP_ADDRESS, 1);
- so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
- NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
- NV40TCL_FP_ADDRESS_DMA0, NV40TCL_FP_ADDRESS_DMA1);
- so_method(so, nv40->hw->curie, NV40TCL_FP_CONTROL, 1);
- so_data (so, fp->fp_control);
-
- so_emit(nv40->nvws, so);
- so_ref(so, &fp->so);
- so_ref(NULL, &so);
+ if (fp->so != nv40->state.hw[NV40_STATE_FRAGPROG]) {
+ so_ref(fp->so, &nv40->state.hw[NV40_STATE_FRAGPROG]);
+ return TRUE;
+ }
- nv40->fragprog.active = fp;
+ return FALSE;
}
void
@@ -840,3 +856,11 @@ nv40_fragprog_destroy(struct nv40_context *nv40,
free(fp->insn);
}
+struct nv40_state_entry nv40_state_fragprog = {
+ .validate = nv40_fragprog_validate,
+ .dirty = {
+ .pipe = NV40_NEW_FRAGPROG,
+ .hw = NV40_STATE_FRAGPROG
+ }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_fragtex.c b/src/gallium/drivers/nv40/nv40_fragtex.c
index 5af5fbe746..436f954cec 100644
--- a/src/gallium/drivers/nv40/nv40_fragtex.c
+++ b/src/gallium/drivers/nv40/nv40_fragtex.c
@@ -41,6 +41,7 @@ static struct nv40_texture_format *
nv40_fragtex_format(uint pipe_format)
{
struct nv40_texture_format *tf = nv40_texture_formats;
+ char fs[128];
while (tf->defined) {
if (tf->pipe == pipe_format)
@@ -48,11 +49,13 @@ nv40_fragtex_format(uint pipe_format)
tf++;
}
+ pf_sprint_name(fs, pipe_format);
+ NOUVEAU_ERR("unknown texture format %s\n", fs);
return NULL;
}
-static void
+static struct nouveau_stateobj *
nv40_fragtex_build(struct nv40_context *nv40, int unit)
{
struct nv40_sampler_state *ps = nv40->tex_sampler[unit];
@@ -90,7 +93,7 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit)
break;
default:
NOUVEAU_ERR("Unknown target %d\n", pt->target);
- return;
+ return NULL;
}
if (swizzled) {
@@ -103,7 +106,7 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit)
txs = tf->swizzle;
so = so_new(16, 2);
- so_method(so, nv40->hw->curie, NV40TCL_TEX_OFFSET(unit), 8);
+ so_method(so, nv40->screen->curie, NV40TCL_TEX_OFFSET(unit), 8);
so_reloc (so, nv40mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
so_reloc (so, nv40mt->buffer, txf, tex_flags | NOUVEAU_BO_OR,
NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1);
@@ -114,28 +117,30 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit)
so_data (so, (pt->width[0] << NV40TCL_TEX_SIZE0_W_SHIFT) |
pt->height[0]);
so_data (so, ps->bcol);
- so_method(so, nv40->hw->curie, NV40TCL_TEX_SIZE1(unit), 1);
+ so_method(so, nv40->screen->curie, NV40TCL_TEX_SIZE1(unit), 1);
so_data (so, (pt->depth[0] << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp);
- so_emit(nv40->nvws, so);
- so_ref (so, &nv40->so_fragtex[unit]);
- so_ref (NULL, &so);
+ return so;
}
-void
-nv40_fragtex_bind(struct nv40_context *nv40)
+static boolean
+nv40_fragtex_validate(struct nv40_context *nv40)
{
- struct nv40_fragment_program *fp = nv40->fragprog.active;
+ struct nv40_fragment_program *fp = nv40->fragprog;
+ struct nv40_state *state = &nv40->state;
+ struct nouveau_stateobj *so;
unsigned samplers, unit;
- samplers = nv40->fp_samplers & ~fp->samplers;
+ samplers = state->fp_samplers & ~fp->samplers;
while (samplers) {
unit = ffs(samplers) - 1;
samplers &= ~(1 << unit);
- so_ref(NULL, &nv40->so_fragtex[unit]);
- BEGIN_RING(curie, NV40TCL_TEX_ENABLE(unit), 1);
- OUT_RING (0);
+ so = so_new(2, 0);
+ so_method(so, nv40->screen->curie, NV40TCL_TEX_ENABLE(unit), 1);
+ so_data (so, 0);
+ so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
+ state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
}
samplers = nv40->dirty_samplers & fp->samplers;
@@ -143,9 +148,20 @@ nv40_fragtex_bind(struct nv40_context *nv40)
unit = ffs(samplers) - 1;
samplers &= ~(1 << unit);
- nv40_fragtex_build(nv40, unit);
+ so = nv40_fragtex_build(nv40, unit);
+ so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
+ state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
}
- nv40->fp_samplers = fp->samplers;
+ nv40->state.fp_samplers = fp->samplers;
+ return FALSE;
}
+struct nv40_state_entry nv40_state_fragtex = {
+ .validate = nv40_fragtex_validate,
+ .dirty = {
+ .pipe = NV40_NEW_SAMPLER | NV40_NEW_FRAGPROG,
+ .hw = 0
+ }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nv40/nv40_miptree.c
index 92e6b3a43d..94ba05b710 100644
--- a/src/gallium/drivers/nv40/nv40_miptree.c
+++ b/src/gallium/drivers/nv40/nv40_miptree.c
@@ -54,15 +54,18 @@ nv40_miptree_layout(struct nv40_miptree *nv40mt)
}
static struct pipe_texture *
-nv40_miptree_create(struct pipe_context *pipe, const struct pipe_texture *pt)
+nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
{
- struct pipe_winsys *ws = pipe->winsys;
+ struct pipe_winsys *ws = pscreen->winsys;
struct nv40_miptree *mt;
mt = MALLOC(sizeof(struct nv40_miptree));
if (!mt)
return NULL;
mt->base = *pt;
+ mt->base.refcount = 1;
+ mt->base.screen = pscreen;
+
nv40_miptree_layout(mt);
mt->buffer = ws->buffer_create(ws, 256, PIPE_BUFFER_USAGE_PIXEL,
@@ -76,9 +79,9 @@ nv40_miptree_create(struct pipe_context *pipe, const struct pipe_texture *pt)
}
static void
-nv40_miptree_release(struct pipe_context *pipe, struct pipe_texture **pt)
+nv40_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **pt)
{
- struct pipe_winsys *ws = pipe->winsys;
+ struct pipe_winsys *ws = pscreen->winsys;
struct pipe_texture *mt = *pt;
*pt = NULL;
@@ -95,10 +98,52 @@ nv40_miptree_release(struct pipe_context *pipe, struct pipe_texture **pt)
}
}
+static void
+nv40_miptree_update(struct pipe_context *pipe, struct pipe_texture *mt)
+{
+}
+
+static struct pipe_surface *
+nv40_miptree_surface(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice)
+{
+ struct pipe_winsys *ws = pscreen->winsys;
+ struct nv40_miptree *nv40mt = (struct nv40_miptree *)pt;
+ struct pipe_surface *ps;
+
+ ps = ws->surface_alloc(ws);
+ if (!ps)
+ return NULL;
+ pipe_buffer_reference(ws, &ps->buffer, nv40mt->buffer);
+ ps->format = pt->format;
+ ps->cpp = pt->cpp;
+ ps->width = pt->width[level];
+ ps->height = pt->height[level];
+ ps->pitch = nv40mt->level[level].pitch / ps->cpp;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ps->offset = nv40mt->level[level].image_offset[face];
+ } else
+ if (pt->target == PIPE_TEXTURE_3D) {
+ ps->offset = nv40mt->level[level].image_offset[zslice];
+ } else {
+ ps->offset = nv40mt->level[level].image_offset[0];
+ }
+
+ return ps;
+}
+
void
nv40_init_miptree_functions(struct nv40_context *nv40)
{
- nv40->pipe.texture_create = nv40_miptree_create;
- nv40->pipe.texture_release = nv40_miptree_release;
+ nv40->pipe.texture_update = nv40_miptree_update;
+}
+
+void
+nv40_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+ pscreen->texture_create = nv40_miptree_create;
+ pscreen->texture_release = nv40_miptree_release;
+ pscreen->get_tex_surface = nv40_miptree_surface;
}
diff --git a/src/gallium/drivers/nv40/nv40_query.c b/src/gallium/drivers/nv40/nv40_query.c
index 8bca2788b9..0317845624 100644
--- a/src/gallium/drivers/nv40/nv40_query.c
+++ b/src/gallium/drivers/nv40/nv40_query.c
@@ -45,9 +45,9 @@ nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
- if (nv40->nvws->res_alloc(nv40->hw->query_heap, 1, NULL, &q->object))
+ if (nv40->nvws->res_alloc(nv40->screen->query_heap, 1, NULL, &q->object))
assert(0);
- nv40->nvws->notifier_reset(nv40->hw->query, q->object->start);
+ nv40->nvws->notifier_reset(nv40->screen->query, q->object->start);
BEGIN_RING(curie, NV40TCL_QUERY_RESET, 1);
OUT_RING (1);
@@ -82,17 +82,17 @@ nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq,
if (!q->ready) {
unsigned status;
- status = nvws->notifier_status(nv40->hw->query,
+ status = nvws->notifier_status(nv40->screen->query,
q->object->start);
if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) {
if (wait == FALSE)
return FALSE;
- nvws->notifier_wait(nv40->hw->query, q->object->start,
+ nvws->notifier_wait(nv40->screen->query, q->object->start,
NV_NOTIFY_STATE_STATUS_COMPLETED,
0);
}
- q->result = nvws->notifier_retval(nv40->hw->query,
+ q->result = nvws->notifier_retval(nv40->screen->query,
q->object->start);
q->ready = TRUE;
nvws->res_free(&q->object);
diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c
new file mode 100644
index 0000000000..268ca83ce0
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_screen.c
@@ -0,0 +1,279 @@
+#include "pipe/p_screen.h"
+#include "pipe/p_util.h"
+
+#include "nv40_context.h"
+#include "nv40_screen.h"
+
+#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf
+#define NV4X_GRCLASS4497_CHIPSETS 0x00005450
+#define NV6X_GRCLASS4497_CHIPSETS 0x00000088
+
+static const char *
+nv40_screen_get_name(struct pipe_screen *pscreen)
+{
+ struct nv40_screen *screen = nv40_screen(pscreen);
+ static char buffer[128];
+
+ snprintf(buffer, sizeof(buffer), "NV%02X", screen->chipset);
+ return buffer;
+}
+
+static const char *
+nv40_screen_get_vendor(struct pipe_screen *pscreen)
+{
+ return "nouveau";
+}
+
+static int
+nv40_screen_get_param(struct pipe_screen *pscreen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return 16;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 1;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 1;
+ case PIPE_CAP_GLSL:
+ return 0;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 1;
+ case PIPE_CAP_POINT_SPRITE:
+ return 1;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 4;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 1;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 1;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 13;
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 10;
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 13;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0;
+ }
+}
+
+static float
+nv40_screen_get_paramf(struct pipe_screen *pscreen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 10.0;
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 64.0;
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 16.0;
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 16.0;
+ case PIPE_CAP_BITMAP_TEXCOORD_BIAS:
+ return 0.0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0.0;
+ }
+}
+
+static boolean
+nv40_screen_surface_format_supported(struct pipe_screen *pscreen,
+ enum pipe_format format, uint type)
+{
+ switch (type) {
+ case PIPE_SURFACE:
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ break;
+ case PIPE_TEXTURE:
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_U_L8:
+ case PIPE_FORMAT_U_A8:
+ case PIPE_FORMAT_U_I8:
+ case PIPE_FORMAT_U_A8_L8:
+ case PIPE_FORMAT_Z16_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ break;
+ default:
+ assert(0);
+ };
+
+ return FALSE;
+}
+
+static void
+nv40_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct nv40_screen *screen = nv40_screen(pscreen);
+ struct nouveau_winsys *nvws = screen->nvws;
+
+ nvws->res_free(&screen->vp_exec_heap);
+ nvws->res_free(&screen->vp_data_heap);
+ nvws->res_free(&screen->query_heap);
+ nvws->notifier_free(&screen->query);
+ nvws->notifier_free(&screen->sync);
+ nvws->grobj_free(&screen->curie);
+
+ FREE(pscreen);
+}
+
+struct pipe_screen *
+nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws,
+ unsigned chipset)
+{
+ struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen);
+ struct nouveau_stateobj *so;
+ unsigned curie_class;
+ int ret;
+
+ if (!screen)
+ return NULL;
+ screen->chipset = chipset;
+ screen->nvws = nvws;
+
+ /* 3D object */
+ switch (chipset & 0xf0) {
+ case 0x40:
+ if (NV4X_GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f)))
+ curie_class = NV40TCL;
+ else
+ if (NV4X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
+ curie_class = NV44TCL;
+ break;
+ case 0x60:
+ if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
+ curie_class = NV44TCL;
+ break;
+ default:
+ break;
+ }
+
+ if (!curie_class) {
+ NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", chipset);
+ return NULL;
+ }
+
+ ret = nvws->grobj_alloc(nvws, curie_class, &screen->curie);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+ return FALSE;
+ }
+
+ /* Notifier for sync purposes */
+ ret = nvws->notifier_alloc(nvws, 1, &screen->sync);
+ if (ret) {
+ NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+ nv40_screen_destroy(&screen->pipe);
+ return NULL;
+ }
+
+ /* Query objects */
+ ret = nvws->notifier_alloc(nvws, 32, &screen->query);
+ if (ret) {
+ NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
+ nv40_screen_destroy(&screen->pipe);
+ return NULL;
+ }
+
+ ret = nvws->res_init(&screen->query_heap, 0, 32);
+ if (ret) {
+ NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
+ nv40_screen_destroy(&screen->pipe);
+ return NULL;
+ }
+
+ /* Vtxprog resources */
+ if (nvws->res_init(&screen->vp_exec_heap, 0, 512) ||
+ nvws->res_init(&screen->vp_data_heap, 0, 256)) {
+ nv40_screen_destroy(&screen->pipe);
+ return NULL;
+ }
+
+ /* Static curie initialisation */
+ so = so_new(128, 0);
+ so_method(so, screen->curie, NV40TCL_DMA_NOTIFY, 1);
+ so_data (so, screen->sync->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_TEXTURE0, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->gart->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_COLOR1, 1);
+ so_data (so, nvws->channel->vram->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_COLOR0, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->vram->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_VTXBUF0, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->gart->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_FENCE, 2);
+ so_data (so, 0);
+ so_data (so, screen->query->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_UNK01AC, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->vram->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_COLOR2, 2);
+ so_data (so, nvws->channel->vram->handle);
+ so_data (so, nvws->channel->vram->handle);
+
+ so_method(so, screen->curie, 0x1ea4, 3);
+ so_data (so, 0x00000010);
+ so_data (so, 0x01000100);
+ so_data (so, 0xff800006);
+
+ /* vtxprog output routing */
+ so_method(so, screen->curie, 0x1fc4, 1);
+ so_data (so, 0x06144321);
+ so_method(so, screen->curie, 0x1fc8, 2);
+ so_data (so, 0xedcba987);
+ so_data (so, 0x00000021);
+ so_method(so, screen->curie, 0x1fd0, 1);
+ so_data (so, 0x00171615);
+ so_method(so, screen->curie, 0x1fd4, 1);
+ so_data (so, 0x001b1a19);
+
+ so_method(so, screen->curie, 0x1ef8, 1);
+ so_data (so, 0x0020ffff);
+ so_method(so, screen->curie, 0x1d64, 1);
+ so_data (so, 0x00d30000);
+ so_method(so, screen->curie, 0x1e94, 1);
+ so_data (so, 0x00000001);
+
+ so_emit(nvws, so);
+ so_ref(NULL, &so);
+ nvws->push_flush(nvws->channel, 0);
+
+ screen->pipe.winsys = ws;
+ screen->pipe.destroy = nv40_screen_destroy;
+
+ screen->pipe.get_name = nv40_screen_get_name;
+ screen->pipe.get_vendor = nv40_screen_get_vendor;
+ screen->pipe.get_param = nv40_screen_get_param;
+ screen->pipe.get_paramf = nv40_screen_get_paramf;
+
+ screen->pipe.is_format_supported = nv40_screen_surface_format_supported;
+
+ nv40_screen_init_miptree_functions(&screen->pipe);
+
+ return &screen->pipe;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h
new file mode 100644
index 0000000000..3ea78aadfd
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_screen.h
@@ -0,0 +1,36 @@
+#ifndef __NV40_SCREEN_H__
+#define __NV40_SCREEN_H__
+
+#include "pipe/p_screen.h"
+
+struct nv40_screen {
+ struct pipe_screen pipe;
+
+ struct nouveau_winsys *nvws;
+ unsigned chipset;
+
+ unsigned cur_pctx;
+
+ /* HW graphics objects */
+ struct nouveau_grobj *curie;
+ struct nouveau_notifier *sync;
+
+ /* Query object resources */
+ struct nouveau_notifier *query;
+ struct nouveau_resource *query_heap;
+
+ /* Vtxprog resources */
+ struct nouveau_resource *vp_exec_heap;
+ struct nouveau_resource *vp_data_heap;
+
+ /* Current 3D state of channel */
+ struct nouveau_stateobj *state[NV40_STATE_MAX];
+};
+
+static INLINE struct nv40_screen *
+nv40_screen(struct pipe_screen *screen)
+{
+ return (struct nv40_screen *)screen;
+}
+
+#endif
diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c
index 713f31dbb1..caa2f9df0c 100644
--- a/src/gallium/drivers/nv40/nv40_state.c
+++ b/src/gallium/drivers/nv40/nv40_state.c
@@ -10,7 +10,8 @@ nv40_blend_state_create(struct pipe_context *pipe,
const struct pipe_blend_state *cso)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nouveau_grobj *curie = nv40->hw->curie;
+ struct nouveau_grobj *curie = nv40->screen->curie;
+ struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso));
struct nouveau_stateobj *so = so_new(16, 0);
if (cso->blend_enable) {
@@ -46,7 +47,9 @@ nv40_blend_state_create(struct pipe_context *pipe,
so_method(so, curie, NV40TCL_DITHER_ENABLE, 1);
so_data (so, cso->dither ? 1 : 0);
- return (void *)so;
+ so_ref(so, &bso->so);
+ bso->pipe = *cso;
+ return (void *)bso;
}
static void
@@ -54,16 +57,17 @@ nv40_blend_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv40_context *nv40 = nv40_context(pipe);
- so_ref(hwcso, &nv40->so_blend);
+ nv40->blend = hwcso;
nv40->dirty |= NV40_NEW_BLEND;
}
static void
nv40_blend_state_delete(struct pipe_context *pipe, void *hwcso)
{
- struct nouveau_stateobj *so = hwcso;
+ struct nv40_blend_state *bso = hwcso;
- so_ref(NULL, &so);
+ so_ref(NULL, &bso->so);
+ FREE(bso);
}
@@ -255,12 +259,13 @@ nv40_sampler_state_bind(struct pipe_context *pipe, unsigned unit,
nv40->tex_sampler[unit] = ps;
nv40->dirty_samplers |= (1 << unit);
+ nv40->dirty |= NV40_NEW_SAMPLER;
}
static void
nv40_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
{
- free(hwcso);
+ FREE(hwcso);
}
static void
@@ -271,6 +276,7 @@ nv40_set_sampler_texture(struct pipe_context *pipe, unsigned unit,
nv40->tex_miptree[unit] = (struct nv40_miptree *)miptree;
nv40->dirty_samplers |= (1 << unit);
+ nv40->dirty |= NV40_NEW_SAMPLER;
}
static void *
@@ -278,33 +284,32 @@ nv40_rasterizer_state_create(struct pipe_context *pipe,
const struct pipe_rasterizer_state *cso)
{
struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso));
struct nouveau_stateobj *so = so_new(32, 0);
+ struct nouveau_grobj *curie = nv40->screen->curie;
/*XXX: ignored:
* light_twoside
- * offset_cw/ccw -nohw
- * scissor
* point_smooth -nohw
* multisample
- * offset_units / offset_scale
*/
- so_method(so, nv40->hw->curie, NV40TCL_SHADE_MODEL, 1);
+ so_method(so, curie, NV40TCL_SHADE_MODEL, 1);
so_data (so, cso->flatshade ? NV40TCL_SHADE_MODEL_FLAT :
NV40TCL_SHADE_MODEL_SMOOTH);
- so_method(so, nv40->hw->curie, NV40TCL_LINE_WIDTH, 2);
+ so_method(so, curie, NV40TCL_LINE_WIDTH, 2);
so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff);
so_data (so, cso->line_smooth ? 1 : 0);
- so_method(so, nv40->hw->curie, NV40TCL_LINE_STIPPLE_ENABLE, 2);
+ so_method(so, curie, NV40TCL_LINE_STIPPLE_ENABLE, 2);
so_data (so, cso->line_stipple_enable ? 1 : 0);
so_data (so, (cso->line_stipple_pattern << 16) |
cso->line_stipple_factor);
- so_method(so, nv40->hw->curie, NV40TCL_POINT_SIZE, 1);
+ so_method(so, curie, NV40TCL_POINT_SIZE, 1);
so_data (so, fui(cso->point_size));
- so_method(so, nv40->hw->curie, NV40TCL_POLYGON_MODE_FRONT, 6);
+ so_method(so, curie, NV40TCL_POLYGON_MODE_FRONT, 6);
if (cso->front_winding == PIPE_WINDING_CCW) {
so_data(so, nvgl_polygon_mode(cso->fill_ccw));
so_data(so, nvgl_polygon_mode(cso->fill_cw));
@@ -345,10 +350,32 @@ nv40_rasterizer_state_create(struct pipe_context *pipe,
so_data(so, cso->poly_smooth ? 1 : 0);
so_data(so, cso->cull_mode != PIPE_WINDING_NONE ? 1 : 0);
- so_method(so, nv40->hw->curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
so_data (so, cso->poly_stipple_enable ? 1 : 0);
- so_method(so, nv40->hw->curie, NV40TCL_POINT_SPRITE, 1);
+ so_method(so, curie, NV40TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if (cso->offset_cw || cso->offset_ccw) {
+ so_method(so, curie, NV40TCL_POLYGON_OFFSET_FACTOR, 2);
+ so_data (so, fui(cso->offset_scale));
+ so_data (so, fui(cso->offset_units * 2));
+ }
+
+ so_method(so, curie, NV40TCL_POINT_SPRITE, 1);
if (cso->point_sprite) {
unsigned psctl = (1 << 0), i;
@@ -362,7 +389,9 @@ nv40_rasterizer_state_create(struct pipe_context *pipe,
so_data(so, 0);
}
- return (void *)so;
+ so_ref(so, &rsso->so);
+ rsso->pipe = *cso;
+ return (void *)rsso;
}
static void
@@ -370,16 +399,17 @@ nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv40_context *nv40 = nv40_context(pipe);
- so_ref(hwcso, &nv40->so_rast);
+ nv40->rasterizer = hwcso;
nv40->dirty |= NV40_NEW_RAST;
}
static void
nv40_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
{
- struct nouveau_stateobj *so = hwcso;
+ struct nv40_rasterizer_state *rsso = hwcso;
- so_ref(NULL, &so);
+ so_ref(NULL, &rsso->so);
+ FREE(rsso);
}
static void *
@@ -387,20 +417,21 @@ nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *cso)
{
struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
struct nouveau_stateobj *so = so_new(32, 0);
- so_method(so, nv40->hw->curie, NV40TCL_DEPTH_FUNC, 3);
+ so_method(so, nv40->screen->curie, NV40TCL_DEPTH_FUNC, 3);
so_data (so, nvgl_comparison_op(cso->depth.func));
so_data (so, cso->depth.writemask ? 1 : 0);
so_data (so, cso->depth.enabled ? 1 : 0);
- so_method(so, nv40->hw->curie, NV40TCL_ALPHA_TEST_ENABLE, 3);
+ so_method(so, nv40->screen->curie, NV40TCL_ALPHA_TEST_ENABLE, 3);
so_data (so, cso->alpha.enabled ? 1 : 0);
so_data (so, nvgl_comparison_op(cso->alpha.func));
so_data (so, float_to_ubyte(cso->alpha.ref));
if (cso->stencil[0].enabled) {
- so_method(so, nv40->hw->curie, NV40TCL_STENCIL_FRONT_ENABLE, 8);
+ so_method(so, nv40->screen->curie, NV40TCL_STENCIL_FRONT_ENABLE, 8);
so_data (so, cso->stencil[0].enabled ? 1 : 0);
so_data (so, cso->stencil[0].write_mask);
so_data (so, nvgl_comparison_op(cso->stencil[0].func));
@@ -410,12 +441,12 @@ nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe,
so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
} else {
- so_method(so, nv40->hw->curie, NV40TCL_STENCIL_FRONT_ENABLE, 1);
+ so_method(so, nv40->screen->curie, NV40TCL_STENCIL_FRONT_ENABLE, 1);
so_data (so, 0);
}
if (cso->stencil[1].enabled) {
- so_method(so, nv40->hw->curie, NV40TCL_STENCIL_BACK_ENABLE, 8);
+ so_method(so, nv40->screen->curie, NV40TCL_STENCIL_BACK_ENABLE, 8);
so_data (so, cso->stencil[1].enabled ? 1 : 0);
so_data (so, cso->stencil[1].write_mask);
so_data (so, nvgl_comparison_op(cso->stencil[1].func));
@@ -425,11 +456,13 @@ nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe,
so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
} else {
- so_method(so, nv40->hw->curie, NV40TCL_STENCIL_BACK_ENABLE, 1);
+ so_method(so, nv40->screen->curie, NV40TCL_STENCIL_BACK_ENABLE, 1);
so_data (so, 0);
}
- return (void *)so;
+ so_ref(so, &zsaso->so);
+ zsaso->pipe = *cso;
+ return (void *)zsaso;
}
static void
@@ -437,16 +470,17 @@ nv40_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv40_context *nv40 = nv40_context(pipe);
- so_ref(hwcso, &nv40->so_zsa);
+ nv40->zsa = hwcso;
nv40->dirty |= NV40_NEW_ZSA;
}
static void
nv40_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
{
- struct nouveau_stateobj *so = hwcso;
+ struct nv40_zsa_state *zsaso = hwcso;
- so_ref(NULL, &so);
+ so_ref(NULL, &zsaso->so);
+ FREE(zsaso);
}
static void *
@@ -465,9 +499,8 @@ static void
nv40_vp_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nv40_vertex_program *vp = hwcso;
- nv40->vertprog.current = vp;
+ nv40->vertprog = hwcso;
nv40->dirty |= NV40_NEW_VERTPROG;
}
@@ -478,7 +511,7 @@ nv40_vp_state_delete(struct pipe_context *pipe, void *hwcso)
struct nv40_vertex_program *vp = hwcso;
nv40_vertprog_destroy(nv40, vp);
- free(vp);
+ FREE(vp);
}
static void *
@@ -497,9 +530,8 @@ static void
nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nv40_fragment_program *fp = hwcso;
- nv40->fragprog.current = fp;
+ nv40->fragprog = hwcso;
nv40->dirty |= NV40_NEW_FRAGPROG;
}
@@ -510,7 +542,7 @@ nv40_fp_state_delete(struct pipe_context *pipe, void *hwcso)
struct nv40_fragment_program *fp = hwcso;
nv40_fragprog_destroy(nv40, fp);
- free(fp);
+ FREE(fp);
}
static void
@@ -518,16 +550,8 @@ nv40_set_blend_color(struct pipe_context *pipe,
const struct pipe_blend_color *bcol)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nouveau_stateobj *so = so_new(2, 0);
-
- so_method(so, nv40->hw->curie, NV40TCL_BLEND_COLOR, 1);
- so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) |
- (float_to_ubyte(bcol->color[0]) << 16) |
- (float_to_ubyte(bcol->color[1]) << 8) |
- (float_to_ubyte(bcol->color[2]) << 0)));
- so_ref(so, &nv40->so_bcol);
- so_ref(NULL, &so);
+ nv40->blend_colour = *bcol;
nv40->dirty |= NV40_NEW_BCOL;
}
@@ -535,6 +559,10 @@ static void
nv40_set_clip_state(struct pipe_context *pipe,
const struct pipe_clip_state *clip)
{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->clip = *clip;
+ nv40->dirty |= NV40_NEW_UCP;
}
static void
@@ -544,11 +572,11 @@ nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
struct nv40_context *nv40 = nv40_context(pipe);
if (shader == PIPE_SHADER_VERTEX) {
- nv40->vertprog.constant_buf = buf->buffer;
+ nv40->constbuf[PIPE_SHADER_VERTEX] = buf->buffer;
nv40->dirty |= NV40_NEW_VERTPROG;
} else
if (shader == PIPE_SHADER_FRAGMENT) {
- nv40->fragprog.constant_buf = buf->buffer;
+ nv40->constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
nv40->dirty |= NV40_NEW_FRAGPROG;
}
}
@@ -558,146 +586,8 @@ nv40_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct pipe_surface *rt[4], *zeta;
- uint32_t rt_enable, rt_format, w, h;
- int i, colour_format = 0, zeta_format = 0;
- struct nouveau_stateobj *so = so_new(64, 10);
- unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
-
- rt_enable = 0;
- for (i = 0; i < 4; i++) {
- if (!fb->cbufs[i])
- continue;
-
- if (colour_format) {
- assert(w == fb->cbufs[i]->width);
- assert(h == fb->cbufs[i]->height);
- assert(colour_format == fb->cbufs[i]->format);
- } else {
- w = fb->cbufs[i]->width;
- h = fb->cbufs[i]->height;
- colour_format = fb->cbufs[i]->format;
- rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i);
- rt[i] = fb->cbufs[i];
- }
- }
-
- if (rt_enable & (NV40TCL_RT_ENABLE_COLOR1 | NV40TCL_RT_ENABLE_COLOR2 |
- NV40TCL_RT_ENABLE_COLOR3))
- rt_enable |= NV40TCL_RT_ENABLE_MRT;
-
- if (fb->zsbuf) {
- if (colour_format) {
- assert(w == fb->zsbuf->width);
- assert(h == fb->zsbuf->height);
- } else {
- w = fb->zsbuf->width;
- h = fb->zsbuf->height;
- }
- zeta_format = fb->zsbuf->format;
- zeta = fb->zsbuf;
- }
-
- rt_format = NV40TCL_RT_FORMAT_TYPE_LINEAR;
-
- switch (colour_format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case 0:
- rt_format |= NV40TCL_RT_FORMAT_COLOR_A8R8G8B8;
- break;
- case PIPE_FORMAT_R5G6B5_UNORM:
- rt_format |= NV40TCL_RT_FORMAT_COLOR_R5G6B5;
- break;
- default:
- assert(0);
- }
-
- switch (zeta_format) {
- case PIPE_FORMAT_Z16_UNORM:
- rt_format |= NV40TCL_RT_FORMAT_ZETA_Z16;
- break;
- case PIPE_FORMAT_Z24S8_UNORM:
- case 0:
- rt_format |= NV40TCL_RT_FORMAT_ZETA_Z24S8;
- break;
- default:
- assert(0);
- }
-
- if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) {
- so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR0, 1);
- so_reloc (so, rt[0]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
- nv40->nvws->channel->vram->handle,
- nv40->nvws->channel->gart->handle);
- so_method(so, nv40->hw->curie, NV40TCL_COLOR0_PITCH, 2);
- so_data (so, rt[0]->pitch * rt[0]->cpp);
- so_reloc (so, rt[0]->buffer, rt[0]->offset, rt_flags |
- NOUVEAU_BO_LOW, 0, 0);
- }
-
- if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) {
- so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR1, 1);
- so_reloc (so, rt[1]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
- nv40->nvws->channel->vram->handle,
- nv40->nvws->channel->gart->handle);
- so_method(so, nv40->hw->curie, NV40TCL_COLOR1_OFFSET, 2);
- so_reloc (so, rt[1]->buffer, rt[1]->offset, rt_flags |
- NOUVEAU_BO_LOW, 0, 0);
- so_data (so, rt[1]->pitch * rt[1]->cpp);
- }
-
- if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) {
- so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR2, 1);
- so_reloc (so, rt[2]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
- nv40->nvws->channel->vram->handle,
- nv40->nvws->channel->gart->handle);
- so_method(so, nv40->hw->curie, NV40TCL_COLOR2_OFFSET, 1);
- so_reloc (so, rt[2]->buffer, rt[2]->offset, rt_flags |
- NOUVEAU_BO_LOW, 0, 0);
- so_method(so, nv40->hw->curie, NV40TCL_COLOR2_PITCH, 1);
- so_data (so, rt[2]->pitch * rt[2]->cpp);
- }
-
- if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) {
- so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR3, 1);
- so_reloc (so, rt[3]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
- nv40->nvws->channel->vram->handle,
- nv40->nvws->channel->gart->handle);
- so_method(so, nv40->hw->curie, NV40TCL_COLOR3_OFFSET, 1);
- so_reloc (so, rt[3]->buffer, rt[3]->offset, rt_flags |
- NOUVEAU_BO_LOW, 0, 0);
- so_method(so, nv40->hw->curie, NV40TCL_COLOR3_PITCH, 1);
- so_data (so, rt[3]->pitch * rt[3]->cpp);
- }
-
- if (zeta_format) {
- so_method(so, nv40->hw->curie, NV40TCL_DMA_ZETA, 1);
- so_reloc (so, zeta->buffer, 0, rt_flags | NOUVEAU_BO_OR,
- nv40->nvws->channel->vram->handle,
- nv40->nvws->channel->gart->handle);
- so_method(so, nv40->hw->curie, NV40TCL_ZETA_OFFSET, 1);
- so_reloc (so, zeta->buffer, zeta->offset, rt_flags |
- NOUVEAU_BO_LOW, 0, 0);
- so_method(so, nv40->hw->curie, NV40TCL_ZETA_PITCH, 1);
- so_data (so, zeta->pitch * zeta->cpp);
- }
-
- so_method(so, nv40->hw->curie, NV40TCL_RT_ENABLE, 1);
- so_data (so, rt_enable);
- so_method(so, nv40->hw->curie, NV40TCL_RT_HORIZ, 3);
- so_data (so, (w << 16) | 0);
- so_data (so, (h << 16) | 0);
- so_data (so, rt_format);
- so_method(so, nv40->hw->curie, NV40TCL_VIEWPORT_HORIZ, 2);
- so_data (so, (w << 16) | 0);
- so_data (so, (h << 16) | 0);
- so_method(so, nv40->hw->curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2);
- so_data (so, ((w - 1) << 16) | 0);
- so_data (so, ((h - 1) << 16) | 0);
-
- so_ref(so, &nv40->so_framebuffer);
- so_ref(NULL, &so);
+ nv40->framebuffer = *fb;
nv40->dirty |= NV40_NEW_FB;
}
@@ -706,15 +596,8 @@ nv40_set_polygon_stipple(struct pipe_context *pipe,
const struct pipe_poly_stipple *stipple)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nouveau_stateobj *so = so_new(33, 0);
- unsigned i;
- so_method(so, nv40->hw->curie, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 32);
- for (i = 0; i < 32; i++)
- so_data(so, stipple->stipple[i]);
-
- so_ref(so, &nv40->so_stipple);
- so_ref(NULL, &so);
+ memcpy(nv40->stipple, stipple->stipple, 4 * 32);
nv40->dirty |= NV40_NEW_STIPPLE;
}
@@ -723,14 +606,8 @@ nv40_set_scissor_state(struct pipe_context *pipe,
const struct pipe_scissor_state *s)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nouveau_stateobj *so = so_new(3, 0);
-
- so_method(so, nv40->hw->curie, NV40TCL_SCISSOR_HORIZ, 2);
- so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
- so_data (so, ((s->maxy - s->miny) << 16) | s->miny);
- so_ref(so, &nv40->so_scissor);
- so_ref(NULL, &so);
+ nv40->scissor = *s;
nv40->dirty |= NV40_NEW_SCISSOR;
}
@@ -739,20 +616,8 @@ nv40_set_viewport_state(struct pipe_context *pipe,
const struct pipe_viewport_state *vpt)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nouveau_stateobj *so = so_new(9, 0);
-
- so_method(so, nv40->hw->curie, NV40TCL_VIEWPORT_TRANSLATE_X, 8);
- so_data (so, fui(vpt->translate[0]));
- so_data (so, fui(vpt->translate[1]));
- so_data (so, fui(vpt->translate[2]));
- so_data (so, fui(vpt->translate[3]));
- so_data (so, fui(vpt->scale[0]));
- so_data (so, fui(vpt->scale[1]));
- so_data (so, fui(vpt->scale[2]));
- so_data (so, fui(vpt->scale[3]));
-
- so_ref(so, &nv40->so_viewport);
- so_ref(NULL, &so);
+
+ nv40->viewport = *vpt;
nv40->dirty |= NV40_NEW_VIEWPORT;
}
@@ -763,7 +628,6 @@ nv40_set_vertex_buffer(struct pipe_context *pipe, unsigned index,
struct nv40_context *nv40 = nv40_context(pipe);
nv40->vtxbuf[index] = *vb;
-
nv40->dirty |= NV40_NEW_ARRAYS;
}
@@ -774,7 +638,6 @@ nv40_set_vertex_element(struct pipe_context *pipe, unsigned index,
struct nv40_context *nv40 = nv40_context(pipe);
nv40->vtxelt[index] = *ve;
-
nv40->dirty |= NV40_NEW_ARRAYS;
}
diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nv40/nv40_state.h
index e82ab9de98..e5217fe91c 100644
--- a/src/gallium/drivers/nv40/nv40_state.h
+++ b/src/gallium/drivers/nv40/nv40_state.h
@@ -39,6 +39,7 @@ struct nv40_vertex_program {
uint32_t ir;
uint32_t or;
+ struct nouveau_stateobj *so;
};
struct nv40_fragment_program_data {
@@ -50,7 +51,6 @@ struct nv40_fragment_program {
const struct pipe_shader_state *pipe;
boolean translated;
- boolean on_hw;
unsigned samplers;
uint32_t *insn;
diff --git a/src/gallium/drivers/nv40/nv40_state_blend.c b/src/gallium/drivers/nv40/nv40_state_blend.c
new file mode 100644
index 0000000000..95e6d7394f
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_blend.c
@@ -0,0 +1,40 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_blend_validate(struct nv40_context *nv40)
+{
+ so_ref(nv40->blend->so, &nv40->state.hw[NV40_STATE_BLEND]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_blend = {
+ .validate = nv40_state_blend_validate,
+ .dirty = {
+ .pipe = NV40_NEW_BLEND,
+ .hw = NV40_STATE_BLEND
+ }
+};
+
+static boolean
+nv40_state_blend_colour_validate(struct nv40_context *nv40)
+{
+ struct nouveau_stateobj *so = so_new(2, 0);
+ struct pipe_blend_color *bcol = &nv40->blend_colour;
+
+ so_method(so, nv40->screen->curie, NV40TCL_BLEND_COLOR, 1);
+ so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) |
+ (float_to_ubyte(bcol->color[0]) << 16) |
+ (float_to_ubyte(bcol->color[1]) << 8) |
+ (float_to_ubyte(bcol->color[2]) << 0)));
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_BCOL]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_blend_colour = {
+ .validate = nv40_state_blend_colour_validate,
+ .dirty = {
+ .pipe = NV40_NEW_BCOL,
+ .hw = NV40_STATE_BCOL
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_clip.c b/src/gallium/drivers/nv40/nv40_state_clip.c
new file mode 100644
index 0000000000..93e690161f
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_clip.c
@@ -0,0 +1,18 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_clip_validate(struct nv40_context *nv40)
+{
+ if (nv40->clip.nr)
+ nv40->fallback |= NV40_FALLBACK_TNL;
+
+ return FALSE;
+}
+
+struct nv40_state_entry nv40_state_clip = {
+ .validate = nv40_state_clip_validate,
+ .dirty = {
+ .pipe = NV40_NEW_UCP,
+ .hw = 0
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
index a10c995548..9f268640e0 100644
--- a/src/gallium/drivers/nv40/nv40_state_emit.c
+++ b/src/gallium/drivers/nv40/nv40_state_emit.c
@@ -1,77 +1,108 @@
#include "nv40_context.h"
#include "nv40_state.h"
-/* Emit relocs for every referenced buffer.
- *
- * This is to ensure the bufmgr has an accurate idea of how
- * the buffer is used. These relocs appear in the push buffer as
- * NOPs, and will only be turned into state changes if a buffer
- * actually moves.
- */
+static struct nv40_state_entry *render_states[] = {
+ &nv40_state_framebuffer,
+ &nv40_state_rasterizer,
+ &nv40_state_clip,
+ &nv40_state_scissor,
+ &nv40_state_stipple,
+ &nv40_state_fragprog,
+ &nv40_state_fragtex,
+ &nv40_state_vertprog,
+ &nv40_state_blend,
+ &nv40_state_blend_colour,
+ &nv40_state_zsa,
+ &nv40_state_viewport,
+ &nv40_state_vbo,
+ NULL
+};
+
static void
-nv40_state_emit_dummy_relocs(struct nv40_context *nv40)
+nv40_state_validate(struct nv40_context *nv40)
{
- unsigned i;
-
- so_emit_reloc_markers(nv40->nvws, nv40->so_framebuffer);
- for (i = 0; i < 16; i++) {
- if (!(nv40->fp_samplers & (1 << i)))
- continue;
- so_emit_reloc_markers(nv40->nvws, nv40->so_fragtex[i]);
- }
- so_emit_reloc_markers(nv40->nvws, nv40->fragprog.active->so);
-}
+ struct nv40_state_entry **states = render_states;
+ unsigned last_fallback;
-void
-nv40_emit_hw_state(struct nv40_context *nv40)
-{
- if (nv40->dirty & NV40_NEW_FB)
- so_emit(nv40->nvws, nv40->so_framebuffer);
+ last_fallback = nv40->fallback;
+ nv40->fallback = 0;
- if (nv40->dirty & NV40_NEW_BLEND)
- so_emit(nv40->nvws, nv40->so_blend);
+ while (*states) {
+ struct nv40_state_entry *e = *states;
- if (nv40->dirty & NV40_NEW_RAST)
- so_emit(nv40->nvws, nv40->so_rast);
+ if (nv40->dirty & e->dirty.pipe) {
+ if (e->validate(nv40))
+ nv40->state.dirty |= (1ULL << e->dirty.hw);
+ }
- if (nv40->dirty & NV40_NEW_ZSA)
- so_emit(nv40->nvws, nv40->so_zsa);
+ states++;
+ }
+ nv40->dirty = 0;
- if (nv40->dirty & NV40_NEW_BCOL)
- so_emit(nv40->nvws, nv40->so_bcol);
+ if (nv40->fallback & NV40_FALLBACK_TNL &&
+ !(last_fallback & NV40_FALLBACK_TNL)) {
+ NOUVEAU_ERR("XXX: hwtnl->swtnl\n");
+ } else
+ if (last_fallback & NV40_FALLBACK_TNL &&
+ !(nv40->fallback & NV40_FALLBACK_TNL)) {
+ NOUVEAU_ERR("XXX: swtnl->hwtnl\n");
+ }
- if (nv40->dirty & NV40_NEW_SCISSOR)
- so_emit(nv40->nvws, nv40->so_scissor);
+ if (nv40->fallback & NV40_FALLBACK_RAST &&
+ !(last_fallback & NV40_FALLBACK_RAST)) {
+ NOUVEAU_ERR("XXX: hwrast->swrast\n");
+ } else
+ if (last_fallback & NV40_FALLBACK_RAST &&
+ !(nv40->fallback & NV40_FALLBACK_RAST)) {
+ NOUVEAU_ERR("XXX: swrast->hwrast\n");
+ }
+}
- if (nv40->dirty & NV40_NEW_VIEWPORT)
- so_emit(nv40->nvws, nv40->so_viewport);
+static void
+nv40_state_emit(struct nv40_context *nv40)
+{
+ struct nv40_state *state = &nv40->state;
+ struct nv40_screen *screen = nv40->screen;
+ unsigned i, samplers;
- if (nv40->dirty & NV40_NEW_STIPPLE)
- so_emit(nv40->nvws, nv40->so_stipple);
+ if (nv40->pctx_id != screen->cur_pctx) {
+ for (i = 0; i < NV40_STATE_MAX; i++) {
+ if (state->hw[i] && screen->state[i] != state->hw[i])
+ state->dirty |= (1ULL << i);
+ }
- if (nv40->dirty & NV40_NEW_FRAGPROG) {
- nv40_fragprog_bind(nv40, nv40->fragprog.current);
- /*XXX: clear NV40_NEW_FRAGPROG if no new program uploaded */
+ screen->cur_pctx = nv40->pctx_id;
}
- if (nv40->dirty_samplers || (nv40->dirty & NV40_NEW_FRAGPROG)) {
- nv40_fragtex_bind(nv40);
+ while (state->dirty) {
+ unsigned idx = ffsll(state->dirty) - 1;
- BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
- OUT_RING (2);
- BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
- OUT_RING (1);
- nv40->dirty &= ~NV40_NEW_FRAGPROG;
+ so_ref (state->hw[idx], &nv40->screen->state[idx]);
+ so_emit(nv40->nvws, nv40->screen->state[idx]);
+ state->dirty &= ~(1ULL << idx);
}
- if (nv40->dirty & NV40_NEW_VERTPROG) {
- nv40_vertprog_bind(nv40, nv40->vertprog.current);
- nv40->dirty &= ~NV40_NEW_VERTPROG;
+ so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FB]);
+ for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
+ if (!(samplers & (1 << i)))
+ continue;
+ so_emit_reloc_markers(nv40->nvws,
+ state->hw[NV40_STATE_FRAGTEX0+i]);
+ samplers &= ~(1ULL << i);
}
+ so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FRAGPROG]);
+ so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_VTXBUF]);
+}
- nv40->dirty_samplers = 0;
- nv40->dirty = 0;
+void
+nv40_emit_hw_state(struct nv40_context *nv40)
+{
+ nv40_state_validate(nv40);
+ nv40_state_emit(nv40);
- nv40_state_emit_dummy_relocs(nv40);
+ BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
+ OUT_RING (2);
+ BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
+ OUT_RING (1);
}
diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c
new file mode 100644
index 0000000000..71795ab182
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_fb.c
@@ -0,0 +1,155 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_framebuffer_validate(struct nv40_context *nv40)
+{
+ struct pipe_framebuffer_state *fb = &nv40->framebuffer;
+ struct pipe_surface *rt[4], *zeta;
+ uint32_t rt_enable, rt_format, w, h;
+ int i, colour_format = 0, zeta_format = 0;
+ struct nouveau_stateobj *so = so_new(64, 10);
+ unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
+
+ rt_enable = 0;
+ for (i = 0; i < 4; i++) {
+ if (!fb->cbufs[i])
+ continue;
+
+ if (colour_format) {
+ assert(w == fb->cbufs[i]->width);
+ assert(h == fb->cbufs[i]->height);
+ assert(colour_format == fb->cbufs[i]->format);
+ } else {
+ w = fb->cbufs[i]->width;
+ h = fb->cbufs[i]->height;
+ colour_format = fb->cbufs[i]->format;
+ rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i);
+ rt[i] = fb->cbufs[i];
+ }
+ }
+
+ if (rt_enable & (NV40TCL_RT_ENABLE_COLOR1 | NV40TCL_RT_ENABLE_COLOR2 |
+ NV40TCL_RT_ENABLE_COLOR3))
+ rt_enable |= NV40TCL_RT_ENABLE_MRT;
+
+ if (fb->zsbuf) {
+ if (colour_format) {
+ assert(w == fb->zsbuf->width);
+ assert(h == fb->zsbuf->height);
+ } else {
+ w = fb->zsbuf->width;
+ h = fb->zsbuf->height;
+ }
+
+ zeta_format = fb->zsbuf->format;
+ zeta = fb->zsbuf;
+ }
+
+ rt_format = NV40TCL_RT_FORMAT_TYPE_LINEAR;
+
+ switch (colour_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case 0:
+ rt_format |= NV40TCL_RT_FORMAT_COLOR_A8R8G8B8;
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ rt_format |= NV40TCL_RT_FORMAT_COLOR_R5G6B5;
+ break;
+ default:
+ assert(0);
+ }
+
+ switch (zeta_format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ rt_format |= NV40TCL_RT_FORMAT_ZETA_Z16;
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case 0:
+ rt_format |= NV40TCL_RT_FORMAT_ZETA_Z24S8;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) {
+ so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR0, 1);
+ so_reloc (so, rt[0]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+ nv40->nvws->channel->vram->handle,
+ nv40->nvws->channel->gart->handle);
+ so_method(so, nv40->screen->curie, NV40TCL_COLOR0_PITCH, 2);
+ so_data (so, rt[0]->pitch * rt[0]->cpp);
+ so_reloc (so, rt[0]->buffer, rt[0]->offset, rt_flags |
+ NOUVEAU_BO_LOW, 0, 0);
+ }
+
+ if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) {
+ so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR1, 1);
+ so_reloc (so, rt[1]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+ nv40->nvws->channel->vram->handle,
+ nv40->nvws->channel->gart->handle);
+ so_method(so, nv40->screen->curie, NV40TCL_COLOR1_OFFSET, 2);
+ so_reloc (so, rt[1]->buffer, rt[1]->offset, rt_flags |
+ NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, rt[1]->pitch * rt[1]->cpp);
+ }
+
+ if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) {
+ so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR2, 1);
+ so_reloc (so, rt[2]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+ nv40->nvws->channel->vram->handle,
+ nv40->nvws->channel->gart->handle);
+ so_method(so, nv40->screen->curie, NV40TCL_COLOR2_OFFSET, 1);
+ so_reloc (so, rt[2]->buffer, rt[2]->offset, rt_flags |
+ NOUVEAU_BO_LOW, 0, 0);
+ so_method(so, nv40->screen->curie, NV40TCL_COLOR2_PITCH, 1);
+ so_data (so, rt[2]->pitch * rt[2]->cpp);
+ }
+
+ if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) {
+ so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR3, 1);
+ so_reloc (so, rt[3]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+ nv40->nvws->channel->vram->handle,
+ nv40->nvws->channel->gart->handle);
+ so_method(so, nv40->screen->curie, NV40TCL_COLOR3_OFFSET, 1);
+ so_reloc (so, rt[3]->buffer, rt[3]->offset, rt_flags |
+ NOUVEAU_BO_LOW, 0, 0);
+ so_method(so, nv40->screen->curie, NV40TCL_COLOR3_PITCH, 1);
+ so_data (so, rt[3]->pitch * rt[3]->cpp);
+ }
+
+ if (zeta_format) {
+ so_method(so, nv40->screen->curie, NV40TCL_DMA_ZETA, 1);
+ so_reloc (so, zeta->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+ nv40->nvws->channel->vram->handle,
+ nv40->nvws->channel->gart->handle);
+ so_method(so, nv40->screen->curie, NV40TCL_ZETA_OFFSET, 1);
+ so_reloc (so, zeta->buffer, zeta->offset, rt_flags |
+ NOUVEAU_BO_LOW, 0, 0);
+ so_method(so, nv40->screen->curie, NV40TCL_ZETA_PITCH, 1);
+ so_data (so, zeta->pitch * zeta->cpp);
+ }
+
+ so_method(so, nv40->screen->curie, NV40TCL_RT_ENABLE, 1);
+ so_data (so, rt_enable);
+ so_method(so, nv40->screen->curie, NV40TCL_RT_HORIZ, 3);
+ so_data (so, (w << 16) | 0);
+ so_data (so, (h << 16) | 0);
+ so_data (so, rt_format);
+ so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_HORIZ, 2);
+ so_data (so, (w << 16) | 0);
+ so_data (so, (h << 16) | 0);
+ so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+ so_data (so, ((w - 1) << 16) | 0);
+ so_data (so, ((h - 1) << 16) | 0);
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_FB]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_framebuffer = {
+ .validate = nv40_state_framebuffer_validate,
+ .dirty = {
+ .pipe = NV40_NEW_FB,
+ .hw = NV40_STATE_FB
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_rasterizer.c b/src/gallium/drivers/nv40/nv40_state_rasterizer.c
new file mode 100644
index 0000000000..9ecda5990f
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_rasterizer.c
@@ -0,0 +1,17 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_rasterizer_validate(struct nv40_context *nv40)
+{
+ so_ref(nv40->rasterizer->so,
+ &nv40->state.hw[NV40_STATE_RAST]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_rasterizer = {
+ .validate = nv40_state_rasterizer_validate,
+ .dirty = {
+ .pipe = NV40_NEW_RAST,
+ .hw = NV40_STATE_RAST
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_scissor.c b/src/gallium/drivers/nv40/nv40_state_scissor.c
new file mode 100644
index 0000000000..9e9eadc511
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_scissor.c
@@ -0,0 +1,34 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_scissor_validate(struct nv40_context *nv40)
+{
+ struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
+ struct pipe_scissor_state *s = &nv40->scissor;
+ struct nouveau_stateobj *so;
+
+ if (nv40->state.hw[NV40_STATE_SCISSOR] &&
+ (rast->scissor == 0 && nv40->state.scissor_enabled == 0))
+ return FALSE;
+
+ so = so_new(3, 0);
+ so_method(so, nv40->screen->curie, NV40TCL_SCISSOR_HORIZ, 2);
+ if (rast->scissor) {
+ so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
+ so_data (so, ((s->maxy - s->miny) << 16) | s->miny);
+ } else {
+ so_data (so, 4096 << 16);
+ so_data (so, 4096 << 16);
+ }
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_SCISSOR]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_scissor = {
+ .validate = nv40_state_scissor_validate,
+ .dirty = {
+ .pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST,
+ .hw = NV40_STATE_SCISSOR
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_stipple.c b/src/gallium/drivers/nv40/nv40_state_stipple.c
new file mode 100644
index 0000000000..b51024ad9b
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_stipple.c
@@ -0,0 +1,39 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_stipple_validate(struct nv40_context *nv40)
+{
+ struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
+ struct nouveau_grobj *curie = nv40->screen->curie;
+ struct nouveau_stateobj *so;
+
+ if (nv40->state.hw[NV40_STATE_STIPPLE] &&
+ (rast->poly_stipple_enable == 0 && nv40->state.stipple_enabled == 0))
+ return FALSE;
+
+ if (rast->poly_stipple_enable) {
+ unsigned i;
+
+ so = so_new(35, 0);
+ so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_data (so, 1);
+ so_method(so, curie, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 32);
+ for (i = 0; i < 32; i++)
+ so_data(so, nv40->stipple[i]);
+ } else {
+ so = so_new(2, 0);
+ so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_STIPPLE]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_stipple = {
+ .validate = nv40_state_stipple_validate,
+ .dirty = {
+ .pipe = NV40_NEW_STIPPLE | NV40_NEW_RAST,
+ .hw = NV40_STATE_STIPPLE,
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_viewport.c b/src/gallium/drivers/nv40/nv40_state_viewport.c
new file mode 100644
index 0000000000..3a32533907
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_viewport.c
@@ -0,0 +1,29 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_viewport_validate(struct nv40_context *nv40)
+{
+ struct nouveau_stateobj *so = so_new(9, 0);
+ struct pipe_viewport_state *vpt = &nv40->viewport;
+
+ so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_TRANSLATE_X, 8);
+ so_data (so, fui(vpt->translate[0]));
+ so_data (so, fui(vpt->translate[1]));
+ so_data (so, fui(vpt->translate[2]));
+ so_data (so, fui(vpt->translate[3]));
+ so_data (so, fui(vpt->scale[0]));
+ so_data (so, fui(vpt->scale[1]));
+ so_data (so, fui(vpt->scale[2]));
+ so_data (so, fui(vpt->scale[3]));
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_VIEWPORT]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_viewport = {
+ .validate = nv40_state_viewport_validate,
+ .dirty = {
+ .pipe = NV40_NEW_VIEWPORT,
+ .hw = NV40_STATE_VIEWPORT
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_zsa.c b/src/gallium/drivers/nv40/nv40_state_zsa.c
new file mode 100644
index 0000000000..fb760677c8
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_zsa.c
@@ -0,0 +1,17 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_zsa_validate(struct nv40_context *nv40)
+{
+ so_ref(nv40->zsa->so,
+ &nv40->state.hw[NV40_STATE_ZSA]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_zsa = {
+ .validate = nv40_state_zsa_validate,
+ .dirty = {
+ .pipe = NV40_NEW_ZSA,
+ .hw = NV40_STATE_ZSA
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_surface.c b/src/gallium/drivers/nv40/nv40_surface.c
index 9726ab4e4d..e8a6011696 100644
--- a/src/gallium/drivers/nv40/nv40_surface.c
+++ b/src/gallium/drivers/nv40/nv40_surface.c
@@ -33,76 +33,6 @@
#include "pipe/p_inlines.h"
#include "util/p_tile.h"
-static boolean
-nv40_surface_format_supported(struct pipe_context *pipe,
- enum pipe_format format, uint type)
-{
- switch (type) {
- case PIPE_SURFACE:
- switch (format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_R5G6B5_UNORM:
- case PIPE_FORMAT_Z24S8_UNORM:
- case PIPE_FORMAT_Z16_UNORM:
- return TRUE;
- default:
- break;
- }
- break;
- case PIPE_TEXTURE:
- switch (format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_A1R5G5B5_UNORM:
- case PIPE_FORMAT_A4R4G4B4_UNORM:
- case PIPE_FORMAT_R5G6B5_UNORM:
- case PIPE_FORMAT_U_L8:
- case PIPE_FORMAT_U_A8:
- case PIPE_FORMAT_U_I8:
- case PIPE_FORMAT_U_A8_L8:
- case PIPE_FORMAT_Z16_UNORM:
- case PIPE_FORMAT_Z24S8_UNORM:
- return TRUE;
- default:
- break;
- }
- break;
- default:
- assert(0);
- };
-
- return FALSE;
-}
-
-static struct pipe_surface *
-nv40_get_tex_surface(struct pipe_context *pipe, struct pipe_texture *pt,
- unsigned face, unsigned level, unsigned zslice)
-{
- struct pipe_winsys *ws = pipe->winsys;
- struct nv40_miptree *nv40mt = (struct nv40_miptree *)pt;
- struct pipe_surface *ps;
-
- ps = ws->surface_alloc(ws);
- if (!ps)
- return NULL;
- pipe_buffer_reference(ws, &ps->buffer, nv40mt->buffer);
- ps->format = pt->format;
- ps->cpp = pt->cpp;
- ps->width = pt->width[level];
- ps->height = pt->height[level];
- ps->pitch = nv40mt->level[level].pitch / ps->cpp;
-
- if (pt->target == PIPE_TEXTURE_CUBE) {
- ps->offset = nv40mt->level[level].image_offset[face];
- } else
- if (pt->target == PIPE_TEXTURE_3D) {
- ps->offset = nv40mt->level[level].image_offset[zslice];
- } else {
- ps->offset = nv40mt->level[level].image_offset[0];
- }
-
- return ps;
-}
-
static void
nv40_surface_copy(struct pipe_context *pipe, unsigned do_flip,
struct pipe_surface *dest, unsigned destx, unsigned desty,
@@ -130,8 +60,6 @@ nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
void
nv40_init_surface_functions(struct nv40_context *nv40)
{
- nv40->pipe.is_format_supported = nv40_surface_format_supported;
- nv40->pipe.get_tex_surface = nv40_get_tex_surface;
nv40->pipe.surface_copy = nv40_surface_copy;
nv40->pipe.surface_fill = nv40_surface_fill;
}
diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c
index fa827ef0c5..bedc8c6d4e 100644
--- a/src/gallium/drivers/nv40/nv40_vbo.c
+++ b/src/gallium/drivers/nv40/nv40_vbo.c
@@ -30,9 +30,50 @@ nv40_vbo_type(uint format)
case PIPE_FORMAT_TYPE_UNORM:
return NV40TCL_VTXFMT_TYPE_UBYTE;
default:
- NOUVEAU_ERR("Unknown format 0x%08x\n", format);
+ {
+ char fs[128];
+ pf_sprint_name(fs, format);
+ NOUVEAU_ERR("Unknown format %s\n", fs);
return NV40TCL_VTXFMT_TYPE_FLOAT;
}
+ }
+}
+
+static boolean
+nv40_vbo_set_idxbuf(struct nv40_context *nv40, struct pipe_buffer *ib,
+ unsigned ib_size)
+{
+ unsigned type;
+
+ if (!ib) {
+ nv40->idxbuf = NULL;
+ nv40->idxbuf_format = 0xdeadbeef;
+ return FALSE;
+ }
+
+ /* No support for 8bit indices, no support at all on 0x4497 chips */
+ if (nv40->screen->curie->grclass == NV44TCL || ib_size == 1)
+ return FALSE;
+
+ switch (ib_size) {
+ case 2:
+ type = NV40TCL_IDXBUF_FORMAT_TYPE_U16;
+ break;
+ case 4:
+ type = NV40TCL_IDXBUF_FORMAT_TYPE_U32;
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (ib != nv40->idxbuf ||
+ type != nv40->idxbuf_format) {
+ nv40->dirty |= NV40_NEW_ARRAYS;
+ nv40->idxbuf = ib;
+ nv40->idxbuf_format = type;
+ }
+
+ return TRUE;
}
static boolean
@@ -97,105 +138,15 @@ nv40_vbo_static_attrib(struct nv40_context *nv40, int attrib,
return TRUE;
}
-static void
-nv40_vbo_arrays_update(struct nv40_context *nv40, struct pipe_buffer *ib,
- unsigned ib_format)
-{
- struct nv40_vertex_program *vp = nv40->vertprog.active;
- struct nouveau_stateobj *vtxbuf, *vtxfmt;
- unsigned inputs, hw, num_hw;
- unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
-
- inputs = vp->ir;
- for (hw = 0; hw < 16 && inputs; hw++) {
- if (inputs & (1 << hw)) {
- num_hw = hw;
- inputs &= ~(1 << hw);
- }
- }
- num_hw++;
-
- vtxbuf = so_new(20, 18);
- so_method(vtxbuf, nv40->hw->curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw);
- vtxfmt = so_new(17, 0);
- so_method(vtxfmt, nv40->hw->curie, NV40TCL_VTXFMT(0), num_hw);
-
- inputs = vp->ir;
- for (hw = 0; hw < num_hw; hw++) {
- struct pipe_vertex_element *ve;
- struct pipe_vertex_buffer *vb;
-
- if (!(inputs & (1 << hw))) {
- so_data(vtxbuf, 0);
- so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
- continue;
- }
-
- ve = &nv40->vtxelt[hw];
- vb = &nv40->vtxbuf[ve->vertex_buffer_index];
-
- if (!vb->pitch && nv40_vbo_static_attrib(nv40, hw, ve, vb)) {
- so_data(vtxbuf, 0);
- so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
- continue;
- }
-
- so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset,
- vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
- 0, NV40TCL_VTXBUF_ADDRESS_DMA1);
- so_data (vtxfmt, ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) |
- (nv40_vbo_ncomp(ve->src_format) <<
- NV40TCL_VTXFMT_SIZE_SHIFT) |
- nv40_vbo_type(ve->src_format)));
- }
-
- if (ib) {
- so_method(vtxbuf, nv40->hw->curie, NV40TCL_IDXBUF_ADDRESS, 2);
- so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
- so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR,
- 0, NV40TCL_IDXBUF_FORMAT_DMA1);
- }
-
- so_emit(nv40->nvws, vtxfmt);
- so_emit(nv40->nvws, vtxbuf);
- so_ref (vtxbuf, &nv40->so_vtxbuf);
- so_ref (NULL, &vtxbuf);
- so_ref (NULL, &vtxfmt);
-}
-
-static boolean
-nv40_vbo_validate_state(struct nv40_context *nv40,
- struct pipe_buffer *ib, unsigned ib_format)
-{
- unsigned vdn = nv40->dirty & NV40_NEW_ARRAYS;
-
- nv40_emit_hw_state(nv40);
- if (vdn || ib) {
- nv40_vbo_arrays_update(nv40, ib, ib_format);
- nv40->dirty &= ~NV40_NEW_ARRAYS;
- }
-
- so_emit_reloc_markers(nv40->nvws, nv40->so_vtxbuf);
-
- BEGIN_RING(curie, 0x1710, 1);
- OUT_RING (0); /* vtx cache flush */
-
- return TRUE;
-}
-
boolean
nv40_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
unsigned count)
{
struct nv40_context *nv40 = nv40_context(pipe);
unsigned nr;
- boolean ret;
- ret = nv40_vbo_validate_state(nv40, NULL, 0);
- if (!ret) {
- NOUVEAU_ERR("state validate failed\n");
- return FALSE;
- }
+ nv40_vbo_set_idxbuf(nv40, NULL, 0);
+ nv40_emit_hw_state(nv40);
BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
OUT_RING (nvgl_primitive(mode));
@@ -302,14 +253,9 @@ nv40_draw_elements_inline(struct pipe_context *pipe,
{
struct nv40_context *nv40 = nv40_context(pipe);
struct pipe_winsys *ws = pipe->winsys;
- boolean ret;
void *map;
- ret = nv40_vbo_validate_state(nv40, NULL, 0);
- if (!ret) {
- NOUVEAU_ERR("state validate failed\n");
- return FALSE;
- }
+ nv40_emit_hw_state(nv40);
map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ);
if (!ib) {
@@ -345,30 +291,12 @@ nv40_draw_elements_inline(struct pipe_context *pipe,
static boolean
nv40_draw_elements_vbo(struct pipe_context *pipe,
- struct pipe_buffer *ib, unsigned ib_size,
unsigned mode, unsigned start, unsigned count)
{
struct nv40_context *nv40 = nv40_context(pipe);
- unsigned nr, type;
- boolean ret;
-
- switch (ib_size) {
- case 2:
- type = NV40TCL_IDXBUF_FORMAT_TYPE_U16;
- break;
- case 4:
- type = NV40TCL_IDXBUF_FORMAT_TYPE_U32;
- break;
- default:
- NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
- return FALSE;
- }
+ unsigned nr;
- ret = nv40_vbo_validate_state(nv40, ib, type);
- if (!ret) {
- NOUVEAU_ERR("failed state validation\n");
- return FALSE;
- }
+ nv40_emit_hw_state(nv40);
BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
OUT_RING (nvgl_primitive(mode));
@@ -406,19 +334,92 @@ nv40_draw_elements(struct pipe_context *pipe,
{
struct nv40_context *nv40 = nv40_context(pipe);
- /* 0x4497 doesn't support real index buffers, and there doesn't appear
- * to be support on any chipset for 8-bit indices.
- */
- if (nv40->hw->curie->grclass == NV44TCL || indexSize == 1) {
+ if (nv40_vbo_set_idxbuf(nv40, indexBuffer, indexSize)) {
+ nv40_draw_elements_vbo(pipe, mode, start, count);
+ } else {
nv40_draw_elements_inline(pipe, indexBuffer, indexSize,
mode, start, count);
- } else {
- nv40_draw_elements_vbo(pipe, indexBuffer, indexSize,
- mode, start, count);
}
pipe->flush(pipe, 0);
return TRUE;
}
+static boolean
+nv40_vbo_validate(struct nv40_context *nv40)
+{
+ struct nv40_vertex_program *vp = nv40->vertprog;
+ struct nouveau_stateobj *vtxbuf, *vtxfmt;
+ struct pipe_buffer *ib = nv40->idxbuf;
+ unsigned ib_format = nv40->idxbuf_format;
+ unsigned inputs, hw, num_hw;
+ unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+
+ inputs = vp->ir;
+ for (hw = 0; hw < 16 && inputs; hw++) {
+ if (inputs & (1 << hw)) {
+ num_hw = hw;
+ inputs &= ~(1 << hw);
+ }
+ }
+ num_hw++;
+
+ vtxbuf = so_new(20, 18);
+ so_method(vtxbuf, nv40->screen->curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw);
+ vtxfmt = so_new(17, 0);
+ so_method(vtxfmt, nv40->screen->curie, NV40TCL_VTXFMT(0), num_hw);
+
+ inputs = vp->ir;
+ for (hw = 0; hw < num_hw; hw++) {
+ struct pipe_vertex_element *ve;
+ struct pipe_vertex_buffer *vb;
+
+ if (!(inputs & (1 << hw))) {
+ so_data(vtxbuf, 0);
+ so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
+ continue;
+ }
+
+ ve = &nv40->vtxelt[hw];
+ vb = &nv40->vtxbuf[ve->vertex_buffer_index];
+
+ if (!vb->pitch && nv40_vbo_static_attrib(nv40, hw, ve, vb)) {
+ so_data(vtxbuf, 0);
+ so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
+ continue;
+ }
+
+ so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset,
+ vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+ 0, NV40TCL_VTXBUF_ADDRESS_DMA1);
+ so_data (vtxfmt, ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) |
+ (nv40_vbo_ncomp(ve->src_format) <<
+ NV40TCL_VTXFMT_SIZE_SHIFT) |
+ nv40_vbo_type(ve->src_format)));
+ }
+
+ if (ib) {
+ so_method(vtxbuf, nv40->screen->curie, NV40TCL_IDXBUF_ADDRESS, 2);
+ so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
+ so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR,
+ 0, NV40TCL_IDXBUF_FORMAT_DMA1);
+ }
+
+ so_method(vtxbuf, nv40->screen->curie, 0x1710, 1);
+ so_data (vtxbuf, 0);
+
+ so_ref(vtxbuf, &nv40->state.hw[NV40_STATE_VTXBUF]);
+ nv40->state.dirty |= (1ULL << NV40_STATE_VTXBUF);
+ so_ref(vtxfmt, &nv40->state.hw[NV40_STATE_VTXFMT]);
+ nv40->state.dirty |= (1ULL << NV40_STATE_VTXFMT);
+ return FALSE;
+}
+
+struct nv40_state_entry nv40_state_vbo = {
+ .validate = nv40_vbo_validate,
+ .dirty = {
+ .pipe = NV40_NEW_ARRAYS,
+ .hw = 0,
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nv40/nv40_vertprog.c
index 9f4738b830..5b7a343e55 100644
--- a/src/gallium/drivers/nv40/nv40_vertprog.c
+++ b/src/gallium/drivers/nv40/nv40_vertprog.c
@@ -558,7 +558,7 @@ nv40_vertprog_prepare(struct nv40_vpc *vpc)
return TRUE;
}
-void
+static void
nv40_vertprog_translate(struct nv40_context *nv40,
struct nv40_vertex_program *vp)
{
@@ -631,24 +631,32 @@ out_err:
free(vpc);
}
-void
-nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
+static boolean
+nv40_vertprog_validate(struct nv40_context *nv40)
{
+ struct nv40_vertex_program *vp = nv40->vertprog;
+ struct pipe_buffer *constbuf =
+ nv40->constbuf[PIPE_SHADER_VERTEX];
struct nouveau_winsys *nvws = nv40->nvws;
struct pipe_winsys *ws = nv40->pipe.winsys;
boolean upload_code = FALSE, upload_data = FALSE;
int i;
/* Translate TGSI shader into hw bytecode */
+ if (vp->translated)
+ goto check_gpu_resources;
+
+ nv40_vertprog_translate(nv40, vp);
if (!vp->translated) {
- nv40_vertprog_translate(nv40, vp);
- if (!vp->translated)
- assert(0);
+ nv40->fallback |= NV40_FALLBACK_TNL;
+ return FALSE;
}
+check_gpu_resources:
/* Allocate hw vtxprog exec slots */
if (!vp->exec) {
- struct nouveau_resource *heap = nv40->hw->vp_exec_heap;
+ struct nouveau_resource *heap = nv40->screen->vp_exec_heap;
+ struct nouveau_stateobj *so;
uint vplen = vp->nr_insns;
if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) {
@@ -663,12 +671,20 @@ nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
assert(0);
}
+ so = so_new(5, 0);
+ so_method(so, nv40->screen->curie, NV40TCL_VP_START_FROM_ID, 1);
+ so_data (so, vp->exec->start);
+ so_method(so, nv40->screen->curie, NV40TCL_VP_ATTRIB_EN, 2);
+ so_data (so, vp->ir);
+ so_data (so, vp->or);
+ so_ref(so, &vp->so);
+
upload_code = TRUE;
}
/* Allocate hw vtxprog const slots */
if (vp->nr_consts && !vp->data) {
- struct nouveau_resource *heap = nv40->hw->vp_data_heap;
+ struct nouveau_resource *heap = nv40->screen->vp_data_heap;
if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) {
while (heap->next && heap->size < vp->nr_consts) {
@@ -725,8 +741,8 @@ nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
if (vp->nr_consts) {
float *map = NULL;
- if (nv40->vertprog.constant_buf) {
- map = ws->buffer_map(ws, nv40->vertprog.constant_buf,
+ if (constbuf) {
+ map = ws->buffer_map(ws, constbuf,
PIPE_BUFFER_USAGE_CPU_READ);
}
@@ -747,9 +763,8 @@ nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
OUT_RINGp ((uint32_t *)vpd->value, 4);
}
- if (map) {
- ws->buffer_unmap(ws, nv40->vertprog.constant_buf);
- }
+ if (constbuf)
+ ws->buffer_unmap(ws, constbuf);
}
/* Upload vtxprog */
@@ -770,13 +785,12 @@ nv40_vertprog_bind(struct nv40_context *nv40, struct nv40_vertex_program *vp)
}
}
- BEGIN_RING(curie, NV40TCL_VP_START_FROM_ID, 1);
- OUT_RING (vp->exec->start);
- BEGIN_RING(curie, NV40TCL_VP_ATTRIB_EN, 2);
- OUT_RING (vp->ir);
- OUT_RING (vp->or);
+ if (vp->so != nv40->state.hw[NV40_STATE_VERTPROG]) {
+ so_ref(vp->so, &nv40->state.hw[NV40_STATE_VERTPROG]);
+ return TRUE;
+ }
- nv40->vertprog.active = vp;
+ return FALSE;
}
void
@@ -788,3 +802,11 @@ nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp)
free(vp->insns);
}
+struct nv40_state_entry nv40_state_vertprog = {
+ .validate = nv40_vertprog_validate,
+ .dirty = {
+ .pipe = NV40_NEW_VERTPROG,
+ .hw = NV40_STATE_VERTPROG,
+ }
+};
+