nvfx: so->RING_3D: fb

This commit is contained in:
Luca Barbieri 2010-03-14 20:52:18 +01:00
parent b3cc1adc14
commit f320176b71
3 changed files with 117 additions and 77 deletions

View file

@ -111,6 +111,12 @@ struct nvfx_vtxelt_state {
unsigned num_elements;
};
struct nvfx_render_target {
struct nouveau_bo* bo;
unsigned offset;
unsigned pitch;
};
struct nvfx_context {
struct pipe_context pipe;
@ -169,6 +175,8 @@ struct nvfx_context {
unsigned hw_vtxelt_nr;
uint8_t hw_samplers;
uint32_t hw_txf[8];
struct nvfx_render_target hw_rt[4];
struct nvfx_render_target hw_zeta;
};
static INLINE struct nvfx_context *
@ -218,6 +226,10 @@ extern void nvfx_draw_elements_swtnl(struct pipe_context *pipe,
unsigned ib_size, unsigned mode,
unsigned start, unsigned count);
/* nvfx_fb.c */
void
nvfx_framebuffer_relocate(struct nvfx_context *nvfx);
/* nvfx_fragprog.c */
extern void nvfx_fragprog_destroy(struct nvfx_context *,
struct nvfx_fragment_program *);

View file

@ -98,9 +98,7 @@ nvfx_state_emit(struct nvfx_context *nvfx)
void
nvfx_state_relocate(struct nvfx_context *nvfx)
{
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct nvfx_state *state = &nvfx->state;
so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FB]);
nvfx_framebuffer_relocate(nvfx);
nvfx_fragtex_relocate(nvfx);
nvfx_fragprog_relocate(nvfx);
if (nvfx->render_mode == HW)

View file

@ -4,17 +4,14 @@
static boolean
static void
nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
{
struct pipe_framebuffer_state *fb = &nvfx->framebuffer;
struct nouveau_channel *chan = nvfx->screen->base.channel;
struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
struct nv04_surface *rt[4], *zeta = NULL;
uint32_t rt_enable = 0, rt_format = 0;
int i, colour_format = 0, zeta_format = 0;
int depth_only = 0;
struct nouveau_stateobj *so = so_new(18, 24, 10);
unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
unsigned w = fb->width;
unsigned h = fb->height;
@ -26,14 +23,18 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
assert(fb->nr_cbufs <= 4);
for (i = 0; i < fb->nr_cbufs; i++) {
if (colour_format) {
if (colour_format)
assert(colour_format == fb->cbufs[i]->format);
} else {
else
colour_format = fb->cbufs[i]->format;
rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i);
rt[i] = (struct nv04_surface *)fb->cbufs[i];
}
rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i);
nvfx->hw_rt[i].bo = nvfx_surface_buffer(fb->cbufs[i]);
nvfx->hw_rt[i].offset = fb->cbufs[i]->offset;
nvfx->hw_rt[i].pitch = ((struct nv04_surface *)fb->cbufs[i])->pitch;
}
for(; i < 4; ++i)
nvfx->hw_rt[i].bo = 0;
if (rt_enable & (NV34TCL_RT_ENABLE_COLOR1 |
NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3))
@ -41,20 +42,24 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
if (fb->zsbuf) {
zeta_format = fb->zsbuf->format;
zeta = (struct nv04_surface *)fb->zsbuf;
nvfx->hw_zeta.bo = nvfx_surface_buffer(fb->zsbuf);
nvfx->hw_zeta.offset = fb->zsbuf->offset;
nvfx->hw_zeta.pitch = ((struct nv04_surface *)fb->zsbuf)->pitch;
}
else
nvfx->hw_zeta.bo = 0;
if (rt_enable & (NV34TCL_RT_ENABLE_COLOR0 | NV34TCL_RT_ENABLE_COLOR1 |
NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3)) {
/* Render to at least a colour buffer */
if (!(rt[0]->base.texture->flags & NVFX_RESOURCE_FLAG_LINEAR)) {
if (!(fb->cbufs[0]->texture->flags & NVFX_RESOURCE_FLAG_LINEAR)) {
assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1)));
for (i = 1; i < fb->nr_cbufs; i++)
assert(!(rt[i]->base.texture->flags & NVFX_RESOURCE_FLAG_LINEAR));
assert(!(fb->cbufs[i]->texture->flags & NVFX_RESOURCE_FLAG_LINEAR));
rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED |
(log2i(rt[0]->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) |
(log2i(rt[0]->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT);
(log2i(fb->cbufs[0]->width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) |
(log2i(fb->cbufs[0]->height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT);
}
else
rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;
@ -62,17 +67,17 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
depth_only = 1;
/* Render to depth buffer only */
if (!(zeta->base.texture->flags & NVFX_RESOURCE_FLAG_LINEAR)) {
if (!(fb->zsbuf->texture->_usage & NVFX_RESOURCE_FLAG_LINEAR)) {
assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1)));
rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED |
(log2i(zeta->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) |
(log2i(zeta->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT);
(log2i(fb->zsbuf->width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) |
(log2i(fb->zsbuf->height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT);
}
else
rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;
} else {
return FALSE;
return;
}
switch (colour_format) {
@ -108,115 +113,140 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
if ((!nvfx->is_nv4x) && colour_bits > zeta_bits) {
/* TODO: does this limitation really exist?
TODO: can it be worked around somehow? */
return FALSE;
assert(0);
}
if ((rt_enable & NV34TCL_RT_ENABLE_COLOR0)
|| ((!nvfx->is_nv4x) && depth_only)) {
struct nv04_surface *rt0 = (depth_only ? zeta : rt[0]);
struct nvfx_render_target *rt0 = (depth_only ? &nvfx->hw_zeta : &nvfx->hw_rt[0]);
uint32_t pitch = rt0->pitch;
if(!nvfx->is_nv4x)
{
if (zeta) {
pitch |= (zeta->pitch << 16);
if (nvfx->hw_zeta.bo) {
pitch |= (nvfx->hw_zeta.pitch << 16);
} else {
pitch |= (pitch << 16);
}
}
so_method(so, eng3d, NV34TCL_DMA_COLOR0, 1);
so_reloc (so, nvfx_surface_buffer(&rt0->base), 0,
OUT_RING(chan, RING_3D(NV34TCL_DMA_COLOR0, 1));
OUT_RELOC(chan, rt0->bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
so_method(so, eng3d, NV34TCL_COLOR0_PITCH, 2);
so_data (so, pitch);
so_reloc (so, nvfx_surface_buffer(&rt[0]->base),
rt0->base.offset, rt_flags | NOUVEAU_BO_LOW,
OUT_RING(chan, RING_3D(NV34TCL_COLOR0_PITCH, 2));
OUT_RING(chan, pitch);
OUT_RELOC(chan, rt0->bo,
rt0->offset, rt_flags | NOUVEAU_BO_LOW,
0, 0);
}
if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) {
so_method(so, eng3d, NV34TCL_DMA_COLOR1, 1);
so_reloc (so, nvfx_surface_buffer(&rt[1]->base), 0,
OUT_RING(chan, RING_3D(NV34TCL_DMA_COLOR1, 1));
OUT_RELOC(chan, nvfx->hw_rt[1].bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
so_method(so, eng3d, NV34TCL_COLOR1_OFFSET, 2);
so_reloc (so, nvfx_surface_buffer(&rt[1]->base),
rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW,
OUT_RING(chan, RING_3D(NV34TCL_COLOR1_OFFSET, 2));
OUT_RELOC(chan, nvfx->hw_rt[1].bo,
nvfx->hw_rt[1].offset, rt_flags | NOUVEAU_BO_LOW,
0, 0);
so_data (so, rt[1]->pitch);
OUT_RING(chan, nvfx->hw_rt[1].pitch);
}
if(nvfx->is_nv4x)
{
if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) {
so_method(so, eng3d, NV40TCL_DMA_COLOR2, 1);
so_reloc (so, nvfx_surface_buffer(&rt[2]->base), 0,
OUT_RING(chan, RING_3D(NV40TCL_DMA_COLOR2, 1));
OUT_RELOC(chan, nvfx->hw_rt[2].bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
so_method(so, eng3d, NV40TCL_COLOR2_OFFSET, 1);
so_reloc (so, nvfx_surface_buffer(&rt[2]->base),
rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW,
OUT_RING(chan, RING_3D(NV40TCL_COLOR2_OFFSET, 1));
OUT_RELOC(chan, nvfx->hw_rt[2].bo,
nvfx->hw_rt[2].offset, rt_flags | NOUVEAU_BO_LOW,
0, 0);
so_method(so, eng3d, NV40TCL_COLOR2_PITCH, 1);
so_data (so, rt[2]->pitch);
OUT_RING(chan, RING_3D(NV40TCL_COLOR2_PITCH, 1));
OUT_RING(chan, nvfx->hw_rt[2].pitch);
}
if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) {
so_method(so, eng3d, NV40TCL_DMA_COLOR3, 1);
so_reloc (so, nvfx_surface_buffer(&rt[3]->base), 0,
OUT_RING(chan, RING_3D(NV40TCL_DMA_COLOR3, 1));
OUT_RELOC(chan, nvfx->hw_rt[3].bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
so_method(so, eng3d, NV40TCL_COLOR3_OFFSET, 1);
so_reloc (so, nvfx_surface_buffer(&rt[3]->base),
rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW,
OUT_RING(chan, RING_3D(NV40TCL_COLOR3_OFFSET, 1));
OUT_RELOC(chan, nvfx->hw_rt[3].bo,
nvfx->hw_rt[3].offset, rt_flags | NOUVEAU_BO_LOW,
0, 0);
so_method(so, eng3d, NV40TCL_COLOR3_PITCH, 1);
so_data (so, rt[3]->pitch);
OUT_RING(chan, RING_3D(NV40TCL_COLOR3_PITCH, 1));
OUT_RING(chan, nvfx->hw_rt[3].pitch);
}
}
if (zeta_format) {
so_method(so, eng3d, NV34TCL_DMA_ZETA, 1);
so_reloc (so, nvfx_surface_buffer(&zeta->base), 0,
OUT_RING(chan, RING_3D(NV34TCL_DMA_ZETA, 1));
OUT_RELOC(chan, nvfx->hw_zeta.bo, 0,
rt_flags | NOUVEAU_BO_OR,
chan->vram->handle, chan->gart->handle);
so_method(so, eng3d, NV34TCL_ZETA_OFFSET, 1);
OUT_RING(chan, RING_3D(NV34TCL_ZETA_OFFSET, 1));
/* TODO: reverse engineer LMA */
so_reloc (so, nvfx_surface_buffer(&zeta->base),
zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0);
OUT_RELOC(chan, nvfx->hw_zeta.bo,
nvfx->hw_zeta.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0);
if(nvfx->is_nv4x) {
so_method(so, eng3d, NV40TCL_ZETA_PITCH, 1);
so_data (so, zeta->pitch);
OUT_RING(chan, RING_3D(NV40TCL_ZETA_PITCH, 1));
OUT_RING(chan, nvfx->hw_zeta.pitch);
}
}
so_method(so, eng3d, NV34TCL_RT_ENABLE, 1);
so_data (so, rt_enable);
so_method(so, eng3d, NV34TCL_RT_HORIZ, 3);
so_data (so, (w << 16) | 0);
so_data (so, (h << 16) | 0);
so_data (so, rt_format);
so_method(so, eng3d, NV34TCL_VIEWPORT_HORIZ, 2);
so_data (so, (w << 16) | 0);
so_data (so, (h << 16) | 0);
so_method(so, eng3d, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2);
so_data (so, ((w - 1) << 16) | 0);
so_data (so, ((h - 1) << 16) | 0);
so_method(so, eng3d, 0x1d88, 1);
so_data (so, (1 << 12) | h);
OUT_RING(chan, RING_3D(NV34TCL_RT_ENABLE, 1));
OUT_RING(chan, rt_enable);
OUT_RING(chan, RING_3D(NV34TCL_RT_HORIZ, 3));
OUT_RING(chan, (w << 16) | 0);
OUT_RING(chan, (h << 16) | 0);
OUT_RING(chan, rt_format);
OUT_RING(chan, RING_3D(NV34TCL_VIEWPORT_HORIZ, 2));
OUT_RING(chan, (w << 16) | 0);
OUT_RING(chan, (h << 16) | 0);
OUT_RING(chan, RING_3D(NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2));
OUT_RING(chan, ((w - 1) << 16) | 0);
OUT_RING(chan, ((h - 1) << 16) | 0);
OUT_RING(chan, RING_3D(0x1d88, 1));
OUT_RING(chan, (1 << 12) | h);
if(!nvfx->is_nv4x) {
/* Wonder why this is needed, context should all be set to zero on init */
/* TODO: we can most likely remove this, after putting it in context init */
so_method(so, eng3d, NV34TCL_VIEWPORT_TX_ORIGIN, 1);
so_data (so, 0);
OUT_RING(chan, RING_3D(NV34TCL_VIEWPORT_TX_ORIGIN, 1));
OUT_RING(chan, 0);
}
}
void
nvfx_framebuffer_relocate(struct nvfx_context *nvfx)
{
struct nouveau_channel *chan = nvfx->screen->base.channel;
unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
rt_flags |= NOUVEAU_BO_DUMMY;
MARK_RING(chan, 20, 20);
#define DO_(var, pfx, name) \
if(var.bo) { \
OUT_RELOC(chan, var.bo, RING_3D(pfx##TCL_DMA_##name, 1), rt_flags, 0, 0); \
OUT_RELOC(chan, var.bo, 0, \
rt_flags | NOUVEAU_BO_OR, \
chan->vram->handle, chan->gart->handle); \
OUT_RELOC(chan, var.bo, RING_3D(pfx##TCL_##name##_OFFSET, 1), rt_flags, 0, 0); \
OUT_RELOC(chan, var.bo, \
var.offset, rt_flags | NOUVEAU_BO_LOW, \
0, 0); \
}
so_ref(so, &nvfx->state.hw[NVFX_STATE_FB]);
so_ref(NULL, &so);
return TRUE;
#define DO(pfx, num) DO_(nvfx->hw_rt[num], pfx, COLOR##num)
DO(NV34, 0);
DO(NV34, 1);
DO(NV40, 2);
DO(NV40, 3);
DO_(nvfx->hw_zeta, NV34, ZETA);
}
struct nvfx_state_entry nvfx_state_framebuffer = {