nvfx_destroy(struct pipe_context *pipe)
{
struct nvfx_context *nvfx = nvfx_context(pipe);
- unsigned i;
-
- for (i = 0; i < NVFX_STATE_MAX; i++) {
- if (nvfx->state.hw[i])
- so_ref(NULL, &nvfx->state.hw[i]);
- }
if (nvfx->draw)
draw_destroy(nvfx->draw);
#define NOUVEAU_MSG(fmt, args...) \
fprintf(stderr, "nouveau: "fmt, ##args);
-enum nvfx_state_index {
- NVFX_STATE_FB = 0,
- NVFX_STATE_VIEWPORT = 1,
- NVFX_STATE_BLEND = 2,
- NVFX_STATE_RAST = 3,
- NVFX_STATE_ZSA = 4,
- NVFX_STATE_BCOL = 5,
- NVFX_STATE_CLIP = 6,
- NVFX_STATE_SCISSOR = 7,
- NVFX_STATE_STIPPLE = 8,
- NVFX_STATE_FRAGPROG = 9,
- NVFX_STATE_VERTPROG = 10,
- NVFX_STATE_FRAGTEX0 = 11,
- NVFX_STATE_FRAGTEX1 = 12,
- NVFX_STATE_FRAGTEX2 = 13,
- NVFX_STATE_FRAGTEX3 = 14,
- NVFX_STATE_FRAGTEX4 = 15,
- NVFX_STATE_FRAGTEX5 = 16,
- NVFX_STATE_FRAGTEX6 = 17,
- NVFX_STATE_FRAGTEX7 = 18,
- NVFX_STATE_FRAGTEX8 = 19,
- NVFX_STATE_FRAGTEX9 = 20,
- NVFX_STATE_FRAGTEX10 = 21,
- NVFX_STATE_FRAGTEX11 = 22,
- NVFX_STATE_FRAGTEX12 = 23,
- NVFX_STATE_FRAGTEX13 = 24,
- NVFX_STATE_FRAGTEX14 = 25,
- NVFX_STATE_FRAGTEX15 = 26,
- NVFX_STATE_VERTTEX0 = 27,
- NVFX_STATE_VERTTEX1 = 28,
- NVFX_STATE_VERTTEX2 = 29,
- NVFX_STATE_VERTTEX3 = 30,
- NVFX_STATE_VTXBUF = 31,
- NVFX_STATE_VTXFMT = 32,
- NVFX_STATE_VTXATTR = 33,
- NVFX_STATE_SR = 34,
- NVFX_STATE_MAX = 35
-};
-
#include "nvfx_screen.h"
#define NVFX_NEW_BLEND (1 << 0)
unsigned scissor_enabled;
unsigned stipple_enabled;
unsigned fp_samplers;
-
- uint64_t dirty;
- struct nouveau_stateobj *hw[NVFX_STATE_MAX];
};
struct nvfx_vtxelt_state {
HW, SWTNL, SWRAST
} render_mode;
unsigned fallback_swtnl;
- unsigned fallback_swrast;
/* Context state */
unsigned dirty, draw_dirty;
return (struct nvfx_context *)pipe;
}
-struct nvfx_state_entry {
- boolean (*validate)(struct nvfx_context *nvfx);
- struct {
- unsigned pipe;
- unsigned hw;
- } dirty;
-};
-
extern struct nvfx_state_entry nvfx_state_blend;
extern struct nvfx_state_entry nvfx_state_blend_colour;
extern struct nvfx_state_entry nvfx_state_fragprog;
struct pipe_resource *idxbuf,
unsigned ib_size, unsigned mode,
unsigned start, unsigned count);
+extern void nvfx_vtxfmt_validate(struct nvfx_context *nvfx);
/* nvfx_fb.c */
+extern void nvfx_state_framebuffer_validate(struct nvfx_context *nvfx);
void
nvfx_framebuffer_relocate(struct nvfx_context *nvfx);
/* nvfx_fragprog.c */
extern void nvfx_fragprog_destroy(struct nvfx_context *,
struct nvfx_fragment_program *);
+extern void nvfx_fragprog_validate(struct nvfx_context *nvfx);
extern void
nvfx_fragprog_relocate(struct nvfx_context *nvfx);
/* nvfx_fragtex.c */
+extern void nvfx_fragtex_validate(struct nvfx_context *nvfx);
extern void
nvfx_fragtex_relocate(struct nvfx_context *nvfx);
/* nvfx_state.c */
extern void nvfx_init_state_functions(struct nvfx_context *nvfx);
+extern void nvfx_state_scissor_validate(struct nvfx_context *nvfx);
+extern void nvfx_state_stipple_validate(struct nvfx_context *nvfx);
+extern void nvfx_state_blend_validate(struct nvfx_context *nvfx);
+extern void nvfx_state_blend_colour_validate(struct nvfx_context *nvfx);
+extern void nvfx_state_viewport_validate(struct nvfx_context *nvfx);
+extern void nvfx_state_rasterizer_validate(struct nvfx_context *nvfx);
+extern void nvfx_state_sr_validate(struct nvfx_context *nvfx);
+extern void nvfx_state_zsa_validate(struct nvfx_context *nvfx);
/* nvfx_state_emit.c */
extern void nvfx_state_relocate(struct nvfx_context *nvfx);
unsigned count);
/* nvfx_vertprog.c */
+extern boolean nvfx_vertprog_validate(struct nvfx_context *nvfx);
extern void nvfx_vertprog_destroy(struct nvfx_context *,
struct nvfx_vertex_program *);
nvfx->swtnl.draw[a] = draw_out;
}
-static boolean
-nvfx_state_vtxfmt_validate(struct nvfx_context *nvfx)
+void
+nvfx_vtxfmt_validate(struct nvfx_context *nvfx)
{
struct nvfx_fragment_program *fp = nvfx->fragprog;
unsigned colour = 0, texcoords = 0, fog = 0, i;
}
emit_attrib(nvfx, 0, 0xff, TGSI_SEMANTIC_POSITION, 0);
-
- return FALSE;
}
-
-struct nvfx_state_entry nvfx_state_vtxfmt = {
- .validate = nvfx_state_vtxfmt_validate,
- .dirty = {
- .pipe = NVFX_NEW_ARRAYS | NVFX_NEW_FRAGPROG,
- .hw = 0
- }
-};
}
}
-boolean
+void
nvfx_fragprog_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
if (fp->translated)
goto update_constants;
- nvfx->fallback_swrast &= ~NVFX_NEW_FRAGPROG;
nvfx_fragprog_translate(nvfx, fp);
if (!fp->translated) {
static unsigned dummy[8] = {1, 0, 0, 0, 1, 0, 0, 0};
fp->insn = malloc(sizeof(dummy));
memcpy(fp->insn, dummy, sizeof(dummy));
fp->insn_len = sizeof(dummy) / sizeof(dummy[0]);
- return FALSE;
+ return;
}
fp->buffer = pipe_buffer_create(pscreen,
OUT_RING(chan, RING_3D(NV34TCL_TX_UNITS_ENABLE, 1));
OUT_RING(chan, fp->samplers);
}
- return TRUE;
}
void
FREE(fp->insn);
}
-struct nvfx_state_entry nvfx_state_fragprog = {
- .validate = nvfx_fragprog_validate,
- .dirty = {
- .pipe = NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST,
- .hw = 0
- }
-};
#include "nvfx_context.h"
#include "nvfx_resource.h"
-static boolean
+void
nvfx_fragtex_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
samplers = nvfx->dirty_samplers;
if(!samplers)
- return FALSE;
+ return;
while (samplers) {
unit = ffs(samplers) - 1;
}
}
nvfx->dirty_samplers = 0;
- return FALSE;
}
void
NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
}
}
-
-struct nvfx_state_entry nvfx_state_fragtex = {
- .validate = nvfx_fragtex_validate,
- .dirty = {
- .pipe = NVFX_NEW_SAMPLER | NVFX_NEW_FRAGPROG,
- .hw = 0
- }
-};
nvfx_screen_destroy(struct pipe_screen *pscreen)
{
struct nvfx_screen *screen = nvfx_screen(pscreen);
- unsigned i;
-
- for (i = 0; i < NVFX_STATE_MAX; i++) {
- if (screen->state[i])
- so_ref(NULL, &screen->state[i]);
- }
nouveau_resource_destroy(&screen->vp_exec_heap);
nouveau_resource_destroy(&screen->vp_data_heap);
/* Vtxprog resources */
struct nouveau_resource *vp_exec_heap;
struct nouveau_resource *vp_data_heap;
-
- /* Current 3D state of channel */
- struct nouveau_stateobj *state[NVFX_STATE_MAX];
};
static INLINE struct nvfx_screen *
{
struct nvfx_context *nvfx = nvfx_context(pipe);
+ if(nvfx->rasterizer && hwcso)
+ {
+ if(!nvfx->rasterizer || ((struct nvfx_rasterizer_state*)hwcso)->pipe.scissor
+ != nvfx->rasterizer->pipe.scissor)
+ {
+ nvfx->dirty |= NVFX_NEW_SCISSOR;
+ nvfx->draw_dirty |= NVFX_NEW_SCISSOR;
+ }
+
+ if(((struct nvfx_rasterizer_state*)hwcso)->pipe.poly_stipple_enable
+ != nvfx->rasterizer->pipe.poly_stipple_enable)
+ {
+ nvfx->dirty |= NVFX_NEW_STIPPLE;
+ nvfx->draw_dirty |= NVFX_NEW_STIPPLE;
+ }
+ }
+
nvfx->rasterizer = hwcso;
nvfx->dirty |= NVFX_NEW_RAST;
nvfx->draw_dirty |= NVFX_NEW_RAST;
#include "nvfx_context.h"
-static boolean
+void
nvfx_state_blend_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
sb_emit(chan, nvfx->blend->sb, nvfx->blend->sb_len);
- return TRUE;
}
-struct nvfx_state_entry nvfx_state_blend = {
- .validate = nvfx_state_blend_validate,
- .dirty = {
- .pipe = NVFX_NEW_BLEND,
- }
-};
-
-static boolean
+void
nvfx_state_blend_colour_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
(float_to_ubyte(bcol->color[0]) << 16) |
(float_to_ubyte(bcol->color[1]) << 8) |
(float_to_ubyte(bcol->color[2]) << 0)));
- return TRUE;
}
-
-struct nvfx_state_entry nvfx_state_blend_colour = {
- .validate = nvfx_state_blend_colour_validate,
- .dirty = {
- .pipe = NVFX_NEW_BCOL,
- }
-};
#include "nvfx_state.h"
#include "draw/draw_context.h"
-#define RENDER_STATES(name, vbo) \
-static struct nvfx_state_entry *name##render_states[] = { \
- &nvfx_state_framebuffer, \
- &nvfx_state_rasterizer, \
- &nvfx_state_scissor, \
- &nvfx_state_stipple, \
- &nvfx_state_fragprog, \
- &nvfx_state_fragtex, \
- &nvfx_state_vertprog, \
- &nvfx_state_blend, \
- &nvfx_state_blend_colour, \
- &nvfx_state_zsa, \
- &nvfx_state_sr, \
- &nvfx_state_viewport, \
- &nvfx_state_##vbo, \
- NULL \
-}
-
-RENDER_STATES(, vbo);
-RENDER_STATES(swtnl_, vtxfmt);
-
-static void
-nvfx_state_do_validate(struct nvfx_context *nvfx,
- struct nvfx_state_entry **states)
+static boolean
+nvfx_state_validate_common(struct nvfx_context *nvfx)
{
- while (*states) {
- struct nvfx_state_entry *e = *states;
-
- if (nvfx->dirty & e->dirty.pipe) {
- if (e->validate(nvfx))
- nvfx->state.dirty |= (1ULL << e->dirty.hw);
+ struct nouveau_channel* chan = nvfx->screen->base.channel;
+ unsigned dirty = nvfx->dirty;
+
+ if(nvfx != nvfx->screen->cur_ctx)
+ dirty = ~0;
+
+ if(nvfx->render_mode == HW)
+ {
+ if(dirty & (NVFX_NEW_VERTPROG | NVFX_NEW_VERTCONST | NVFX_NEW_UCP))
+ {
+ if(!nvfx_vertprog_validate(nvfx))
+ return FALSE;
}
- states++;
+ if(dirty & (NVFX_NEW_ARRAYS))
+ {
+ if(!nvfx_vbo_validate(nvfx))
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* TODO: this looks a bit misdesigned */
+ if(dirty & (NVFX_NEW_VERTPROG | NVFX_NEW_UCP))
+ nvfx_vertprog_validate(nvfx);
+
+ if(dirty & (NVFX_NEW_ARRAYS | NVFX_NEW_FRAGPROG))
+ nvfx_vtxfmt_validate(nvfx);
}
- nvfx->dirty = 0;
-}
-void
-nvfx_state_emit(struct nvfx_context *nvfx)
-{
- struct nvfx_state *state = &nvfx->state;
- struct nvfx_screen *screen = nvfx->screen;
- struct nouveau_channel *chan = screen->base.channel;
- struct nouveau_grobj *eng3d = screen->eng3d;
- unsigned i;
- uint64_t states;
-
- /* XXX: race conditions
- */
- if (nvfx != screen->cur_ctx) {
- for (i = 0; i < NVFX_STATE_MAX; i++) {
- if (state->hw[i] && screen->state[i] != state->hw[i])
- state->dirty |= (1ULL << i);
- }
+ if(dirty & NVFX_NEW_FB)
+ nvfx_state_framebuffer_validate(nvfx);
- screen->cur_ctx = nvfx;
- }
+ if(dirty & NVFX_NEW_RAST)
+ sb_emit(chan, nvfx->rasterizer->sb, nvfx->rasterizer->sb_len);
- for (i = 0, states = state->dirty; states; i++) {
- if (!(states & (1ULL << i)))
- continue;
- so_ref (state->hw[i], &nvfx->screen->state[i]);
- if (state->hw[i])
- so_emit(chan, nvfx->screen->state[i]);
- states &= ~(1ULL << i);
- }
+ if(dirty & NVFX_NEW_SCISSOR)
+ nvfx_state_scissor_validate(nvfx);
+
+ if(dirty & NVFX_NEW_STIPPLE)
+ nvfx_state_stipple_validate(nvfx);
+
+ if(dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST))
+ nvfx_fragprog_validate(nvfx);
+
+ if(dirty & NVFX_NEW_SAMPLER)
+ nvfx_fragtex_validate(nvfx);
+
+ if(dirty & NVFX_NEW_BLEND)
+ sb_emit(chan, nvfx->blend->sb, nvfx->blend->sb_len);
+
+ if(dirty & NVFX_NEW_BCOL)
+ nvfx_state_blend_colour_validate(nvfx);
+
+ if(dirty & NVFX_NEW_ZSA)
+ sb_emit(chan, nvfx->zsa->sb, nvfx->zsa->sb_len);
+
+ if(dirty & NVFX_NEW_SR)
+ nvfx_state_sr_validate(nvfx);
+
+/* Having this depend on FB looks wrong, but it seems
+ necessary to make this work on nv3x
+ TODO: find the right fix
+*/
+ if(dirty & (NVFX_NEW_VIEWPORT | NVFX_NEW_FB))
+ nvfx_state_viewport_validate(nvfx);
/* TODO: could nv30 need this or something similar too? */
- if(nvfx->is_nv4x) {
- if (state->dirty & ((1ULL << NVFX_STATE_FRAGPROG) |
- (1ULL << NVFX_STATE_FRAGTEX0))) {
- BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
- OUT_RING (chan, 2);
- BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
- OUT_RING (chan, 1);
- }
+ if((dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_SAMPLER)) && nvfx->is_nv4x) {
+ WAIT_RING(chan, 4);
+ OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
+ OUT_RING(chan, 2);
+ OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
+ OUT_RING(chan, 1);
}
- state->dirty = 0;
+ nvfx->dirty = 0;
+ return TRUE;
+}
+void
+nvfx_state_emit(struct nvfx_context *nvfx)
+{
+ struct nouveau_channel* chan = nvfx->screen->base.channel;
/* we need to ensure there is enough space to output relocations in one go */
unsigned max_relocs = 0
+ 16 /* vertex buffers, incl. dma flag */
return FALSE;
/* Attempt to go to hwtnl again */
- nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
nvfx->dirty |= (NVFX_NEW_VIEWPORT |
NVFX_NEW_VERTPROG |
NVFX_NEW_ARRAYS);
nvfx->render_mode = HW;
}
- nvfx_state_do_validate(nvfx, render_states);
-
- if (nvfx->fallback_swtnl || nvfx->fallback_swrast)
+ if(!nvfx_state_validate_common(nvfx))
return FALSE;
if (was_sw)
draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe);
}
- nvfx_state_do_validate(nvfx, swtnl_render_states);
-
- if (nvfx->fallback_swrast) {
- NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx->fallback_swrast);
- return FALSE;
- }
+ nvfx_state_validate_common(nvfx);
nvfx->draw_dirty = 0;
return TRUE;
-static void
+void
nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
{
struct pipe_framebuffer_state *fb = &nvfx->framebuffer;
DO_(nvfx->hw_zeta, NV34, ZETA);
}
-
-struct nvfx_state_entry nvfx_state_framebuffer = {
- .validate = nvfx_state_framebuffer_validate,
- .dirty = {
- .pipe = NVFX_NEW_FB,
- .hw = NVFX_STATE_FB
- }
-};
#include "nvfx_context.h"
-static boolean
+void
nvfx_state_rasterizer_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
sb_emit(chan, nvfx->rasterizer->sb, nvfx->rasterizer->sb_len);
- return TRUE;
}
-struct nvfx_state_entry nvfx_state_rasterizer = {
- .validate = nvfx_state_rasterizer_validate,
- .dirty = {
- .pipe = NVFX_NEW_RAST,
- }
-};
#include "nvfx_context.h"
-static boolean
+void
nvfx_state_scissor_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct pipe_scissor_state *s = &nvfx->scissor;
if ((rast->scissor == 0 && nvfx->state.scissor_enabled == 0))
- return FALSE;
+ return;
nvfx->state.scissor_enabled = rast->scissor;
WAIT_RING(chan, 3);
OUT_RING(chan, 4096 << 16);
OUT_RING(chan, 4096 << 16);
}
- return TRUE;
}
-
-struct nvfx_state_entry nvfx_state_scissor = {
- .validate = nvfx_state_scissor_validate,
- .dirty = {
- .pipe = NVFX_NEW_SCISSOR | NVFX_NEW_RAST,
- }
-};
#include "nvfx_context.h"
-static boolean
+void
nvfx_state_stipple_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct pipe_rasterizer_state *rast = &nvfx->rasterizer->pipe;
if ((rast->poly_stipple_enable == 0 && nvfx->state.stipple_enabled == 0))
- return FALSE;
+ return;
if (rast->poly_stipple_enable) {
unsigned i;
OUT_RING(chan, RING_3D(NV34TCL_POLYGON_STIPPLE_ENABLE, 1));
OUT_RING(chan, 0);
}
-
- return TRUE;
}
-
-struct nvfx_state_entry nvfx_state_stipple = {
- .validate = nvfx_state_stipple_validate,
- .dirty = {
- .pipe = NVFX_NEW_STIPPLE | NVFX_NEW_RAST,
- }
-};
#include "nvfx_context.h"
-/* Having this depend on FB and RAST looks wrong, but it seems
- necessary to make this work on nv3x
- TODO: find the right fix
-*/
-
-static boolean
+void
nvfx_state_viewport_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel *chan = nvfx->screen->base.channel;
OUT_RING(chan, RING_3D(0x1d78, 1));
OUT_RING(chan, nvfx->is_nv4x ? 0x110 : 1);
}
- return FALSE;
}
-
-struct nvfx_state_entry nvfx_state_viewport = {
- .validate = nvfx_state_viewport_validate,
- .dirty = {
- .pipe = NVFX_NEW_VIEWPORT | NVFX_NEW_FB | NVFX_NEW_RAST,
- }
-};
#include "nvfx_context.h"
-static boolean
+void
nvfx_state_zsa_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
sb_emit(chan, nvfx->zsa->sb, nvfx->zsa->sb_len);
- return TRUE;
}
-struct nvfx_state_entry nvfx_state_zsa = {
- .validate = nvfx_state_zsa_validate,
- .dirty = {
- .pipe = NVFX_NEW_ZSA,
- }
-};
-
-static boolean
+void
nvfx_state_sr_validate(struct nvfx_context *nvfx)
{
struct nouveau_channel* chan = nvfx->screen->base.channel;
OUT_RING(chan, sr->ref_value[0]);
OUT_RING(chan, RING_3D(NV34TCL_STENCIL_BACK_FUNC_REF, 1));
OUT_RING(chan, sr->ref_value[1]);
- return TRUE;
}
-
-struct nvfx_state_entry nvfx_state_sr = {
- .validate = nvfx_state_sr_validate,
- .dirty = {
- .pipe = NVFX_NEW_SR,
- }
-};
}
nvfx->hw_vtxelt_nr = nvfx->vtxelt->num_elements;
- return FALSE;
+ return TRUE;
}
-struct nvfx_state_entry nvfx_state_vbo = {
- .validate = nvfx_vbo_validate,
- .dirty = {
- .pipe = NVFX_NEW_ARRAYS,
- .hw = 0,
- }
-};
-
void
nvfx_vbo_relocate(struct nvfx_context *nvfx)
{
FREE(vpc);
}
-static boolean
+boolean
nvfx_vertprog_validate(struct nvfx_context *nvfx)
{
struct pipe_context *pipe = &nvfx->pipe;
OUT_RING(chan, vp->clip_ctrl);
}
- return FALSE;
+ return TRUE;
}
void
vp->ir = vp->or = vp->clip_ctrl = 0;
}
-
-struct nvfx_state_entry nvfx_state_vertprog = {
- .validate = nvfx_vertprog_validate,
- .dirty = {
- .pipe = NVFX_NEW_VERTPROG | NVFX_NEW_VERTCONST | NVFX_NEW_UCP,
- }
-};