blob: b8d6dc560f053efffac6f10a390c135ee9df38d3 [file] [log] [blame]
#include "nv04_context.h"
#include "nv04_state.h"
static void nv04_vertex_layout(struct pipe_context* pipe)
{
struct nv04_context *nv04 = nv04_context(pipe);
struct nv04_fragment_program *fp = nv04->fragprog.current;
uint32_t src = 0;
int i;
struct vertex_info vinfo;
memset(&vinfo, 0, sizeof(vinfo));
for (i = 0; i < fp->info.num_inputs; i++) {
int isn = fp->info.input_semantic_name[i];
int isi = fp->info.input_semantic_index[i];
switch (isn) {
case TGSI_SEMANTIC_POSITION:
draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
break;
case TGSI_SEMANTIC_COLOR:
draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
break;
default:
case TGSI_SEMANTIC_GENERIC:
draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
break;
case TGSI_SEMANTIC_FOG:
draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
break;
}
}
printf("%d vertex input\n",fp->info.num_inputs);
draw_compute_vertex_size(&vinfo);
}
static uint32_t nv04_blend_func(uint32_t f)
{
switch ( f ) {
case PIPE_BLENDFACTOR_ZERO: return 0x1;
case PIPE_BLENDFACTOR_ONE: return 0x2;
case PIPE_BLENDFACTOR_SRC_COLOR: return 0x3;
case PIPE_BLENDFACTOR_INV_SRC_COLOR: return 0x4;
case PIPE_BLENDFACTOR_SRC_ALPHA: return 0x5;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return 0x6;
case PIPE_BLENDFACTOR_DST_ALPHA: return 0x7;
case PIPE_BLENDFACTOR_INV_DST_ALPHA: return 0x8;
case PIPE_BLENDFACTOR_DST_COLOR: return 0x9;
case PIPE_BLENDFACTOR_INV_DST_COLOR: return 0xA;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return 0xB;
}
NOUVEAU_MSG("Unable to find the blend function 0x%x\n",f);
return 0;
}
static void nv04_emit_control(struct nv04_context* nv04)
{
uint32_t control = nv04->dsa->control;
struct nv04_screen *screen = nv04->screen;
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *fahrenheit = screen->fahrenheit;
BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_CONTROL, 1);
OUT_RING(chan, control);
}
static void nv04_emit_blend(struct nv04_context* nv04)
{
struct nv04_screen *screen = nv04->screen;
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *fahrenheit = screen->fahrenheit;
uint32_t blend;
blend=0x4; // texture MODULATE_ALPHA
blend|=0x20; // alpha is MSB
blend|=(2<<6); // flat shading
blend|=(1<<8); // persp correct
blend|=(0<<16); // no fog
blend|=(nv04->blend->b_enable<<20);
blend|=(nv04_blend_func(nv04->blend->b_src)<<24);
blend|=(nv04_blend_func(nv04->blend->b_dst)<<28);
BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_BLEND, 1);
OUT_RING(chan, blend);
}
static void nv04_emit_sampler(struct nv04_context *nv04, int unit)
{
struct nv04_miptree *nv04mt = nv04->tex_miptree[unit];
struct pipe_texture *pt = &nv04mt->base;
struct nv04_screen *screen = nv04->screen;
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *fahrenheit = screen->fahrenheit;
struct nouveau_bo *bo = nouveau_bo(nv04mt->buffer);
BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_OFFSET, 3);
OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
OUT_RELOCd(chan, bo, (nv04->fragtex.format | nv04->sampler[unit]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
OUT_RING(chan, nv04->sampler[unit]->filter);
}
static void nv04_state_emit_framebuffer(struct nv04_context* nv04)
{
struct pipe_framebuffer_state* fb = nv04->framebuffer;
struct nv04_surface *rt, *zeta;
uint32_t rt_format, w, h;
int colour_format = 0, zeta_format = 0;
struct nv04_miptree *nv04mt = 0;
struct nv04_screen *screen = nv04->screen;
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *context_surfaces_3d = screen->context_surfaces_3d;
struct nouveau_bo *bo;
w = fb->cbufs[0]->width;
h = fb->cbufs[0]->height;
colour_format = fb->cbufs[0]->format;
rt = (struct nv04_surface *)fb->cbufs[0];
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 = (struct nv04_surface *)fb->zsbuf;
}
switch (colour_format) {
case PIPE_FORMAT_A8R8G8B8_UNORM:
case 0:
rt_format = 0x108;
break;
case PIPE_FORMAT_R5G6B5_UNORM:
rt_format = 0x103;
break;
default:
assert(0);
}
BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_FORMAT, 1);
OUT_RING(chan, rt_format);
nv04mt = (struct nv04_miptree *)rt->base.texture;
bo = nouveau_bo(nv04mt->buffer);
/* FIXME pitches have to be aligned ! */
BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2);
OUT_RING(chan, rt->pitch|(zeta->pitch<<16));
OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
if (fb->zsbuf) {
nv04mt = (struct nv04_miptree *)zeta->base.texture;
BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1);
OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
}
}
void
nv04_emit_hw_state(struct nv04_context *nv04)
{
struct nv04_screen *screen = nv04->screen;
struct nouveau_channel *chan = screen->base.channel;
struct nouveau_grobj *fahrenheit = screen->fahrenheit;
struct nouveau_grobj *context_surfaces_3d = screen->context_surfaces_3d;
int i;
if (nv04->dirty & NV04_NEW_VERTPROG) {
//nv04_vertprog_bind(nv04, nv04->vertprog.current);
nv04->dirty &= ~NV04_NEW_VERTPROG;
}
if (nv04->dirty & NV04_NEW_FRAGPROG) {
nv04_fragprog_bind(nv04, nv04->fragprog.current);
nv04->dirty &= ~NV04_NEW_FRAGPROG;
nv04->dirty_samplers |= (1<<10);
nv04->dirty_samplers = 0;
}
if (nv04->dirty & NV04_NEW_CONTROL) {
nv04->dirty &= ~NV04_NEW_CONTROL;
BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_CONTROL, 1);
OUT_RING(chan, nv04->dsa->control);
}
if (nv04->dirty & NV04_NEW_BLEND) {
nv04->dirty &= ~NV04_NEW_BLEND;
nv04_emit_blend(nv04);
}
if (nv04->dirty & NV04_NEW_VTXARRAYS) {
nv04->dirty &= ~NV04_NEW_VTXARRAYS;
nv04_vertex_layout(nv04);
}
if (nv04->dirty & NV04_NEW_SAMPLER) {
nv04->dirty &= ~NV04_NEW_SAMPLER;
nv04_emit_sampler(nv04, 0);
}
if (nv04->dirty & NV04_NEW_VIEWPORT) {
nv04->dirty &= ~NV04_NEW_VIEWPORT;
// nv04_state_emit_viewport(nv04);
}
if (nv04->dirty & NV04_NEW_FRAMEBUFFER) {
nv04->dirty &= ~NV04_NEW_FRAMEBUFFER;
nv04_state_emit_framebuffer(nv04);
}
/* Emit relocs for every referenced buffer.
* This is to ensure the bufmgr has an accurate idea of how
* the buffer is used. This isn't very efficient, but we don't
* seem to take a significant performance hit. Will be improved
* at some point. Vertex arrays are emitted by nv04_vbo.c
*/
/* Render target */
unsigned rt_pitch = ((struct nv04_surface *)nv04->rt)->pitch;
unsigned zeta_pitch = ((struct nv04_surface *)nv04->zeta)->pitch;
BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2);
OUT_RING(chan, rt_pitch|(zeta_pitch<<16));
OUT_RELOCl(chan, nouveau_bo(nv04->rt), 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
if (nv04->zeta) {
BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1);
OUT_RELOCl(chan, nouveau_bo(nv04->zeta), 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
}
/* Texture images */
for (i = 0; i < 1; i++) {
if (!(nv04->fp_samplers & (1 << i)))
continue;
struct nv04_miptree *nv04mt = nv04->tex_miptree[i];
struct nouveau_bo *bo = nouveau_bo(nv04mt->buffer);
BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_OFFSET, 2);
OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
OUT_RELOCd(chan, bo, (nv04->fragtex.format | nv04->sampler[i]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
}
}