diff options
Diffstat (limited to 'src/gallium/drivers/nv10')
-rw-r--r-- | src/gallium/drivers/nv10/Makefile | 20 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_clear.c | 14 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_context.c | 322 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_context.h | 154 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_fragprog.c | 21 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_fragtex.c | 124 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_miptree.c | 167 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_prim_vbuf.c | 261 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_screen.c | 198 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_screen.h | 28 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_state.c | 590 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_state.h | 139 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_state_emit.c | 306 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_surface.c | 63 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_transfer.c | 195 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_vbo.c | 78 |
16 files changed, 2680 insertions, 0 deletions
diff --git a/src/gallium/drivers/nv10/Makefile b/src/gallium/drivers/nv10/Makefile new file mode 100644 index 0000000000..62677f5194 --- /dev/null +++ b/src/gallium/drivers/nv10/Makefile @@ -0,0 +1,20 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nv10 + +C_SOURCES = \ + nv10_clear.c \ + nv10_context.c \ + nv10_fragprog.c \ + nv10_fragtex.c \ + nv10_miptree.c \ + nv10_prim_vbuf.c \ + nv10_screen.c \ + nv10_state.c \ + nv10_state_emit.c \ + nv10_surface.c \ + nv10_transfer.c \ + nv10_vbo.c + +include ../../Makefile.template diff --git a/src/gallium/drivers/nv10/nv10_clear.c b/src/gallium/drivers/nv10/nv10_clear.c new file mode 100644 index 0000000000..a39a2b5f52 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_clear.c @@ -0,0 +1,14 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "util/u_clear.h" + +#include "nv10_context.h" + +void +nv10_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil) +{ + util_clear(pipe, nv10_context(pipe)->framebuffer, buffers, rgba, depth, + stencil); +} diff --git a/src/gallium/drivers/nv10/nv10_context.c b/src/gallium/drivers/nv10/nv10_context.c new file mode 100644 index 0000000000..a127b134ec --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_context.c @@ -0,0 +1,322 @@ +#include "draw/draw_context.h" +#include "pipe/p_defines.h" +#include "pipe/internal/p_winsys_screen.h" + +#include "nv10_context.h" +#include "nv10_screen.h" + +static void +nv10_flush(struct pipe_context *pipe, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + draw_flush(nv10->draw); + + FIRE_RING(fence); +} + +static void +nv10_destroy(struct pipe_context *pipe) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + if (nv10->draw) + draw_destroy(nv10->draw); + + FREE(nv10); +} + +static void nv10_init_hwctx(struct nv10_context *nv10) +{ + struct nv10_screen *screen = nv10->screen; + struct nouveau_channel *chan = screen->base.channel; + int i; + float projectionmatrix[16]; + + BEGIN_RING(celsius, NV10TCL_DMA_NOTIFY, 1); + OUT_RING (screen->sync->handle); + BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY0, 2); + OUT_RING (chan->vram->handle); + OUT_RING (chan->gart->handle); + BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY2, 2); + OUT_RING (chan->vram->handle); + OUT_RING (chan->vram->handle); + + BEGIN_RING(celsius, NV10TCL_NOP, 1); + OUT_RING (0); + + BEGIN_RING(celsius, NV10TCL_RT_HORIZ, 2); + OUT_RING (0); + OUT_RING (0); + + BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1); + OUT_RING ((0x7ff<<16)|0x800); + BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1); + OUT_RING ((0x7ff<<16)|0x800); + + for (i=1;i<8;i++) { + BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_VERT(i), 1); + OUT_RING (0); + } + + BEGIN_RING(celsius, 0x290, 1); + OUT_RING ((0x10<<16)|1); + BEGIN_RING(celsius, 0x3f4, 1); + OUT_RING (0); + + BEGIN_RING(celsius, NV10TCL_NOP, 1); + OUT_RING (0); + + if (nv10->screen->celsius->grclass != NV10TCL) { + /* For nv11, nv17 */ + BEGIN_RING(celsius, 0x120, 3); + OUT_RING (0); + OUT_RING (1); + OUT_RING (2); + + BEGIN_RING(celsius, NV10TCL_NOP, 1); + OUT_RING (0); + } + + BEGIN_RING(celsius, NV10TCL_NOP, 1); + OUT_RING (0); + + /* Set state */ + BEGIN_RING(celsius, NV10TCL_FOG_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_FUNC, 2); + OUT_RING (0x207); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_TX_ENABLE(0), 2); + OUT_RING (0); + OUT_RING (0); + + BEGIN_RING(celsius, NV10TCL_RC_IN_ALPHA(0), 12); + OUT_RING (0x30141010); + OUT_RING (0); + OUT_RING (0x20040000); + OUT_RING (0); + OUT_RING (0); + OUT_RING (0); + OUT_RING (0x00000c00); + OUT_RING (0); + OUT_RING (0x00000c00); + OUT_RING (0x18000000); + OUT_RING (0x300e0300); + OUT_RING (0x0c091c80); + + BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_DITHER_ENABLE, 2); + OUT_RING (1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_VERTEX_WEIGHT_ENABLE, 2); + OUT_RING (0); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_SRC, 4); + OUT_RING (1); + OUT_RING (0); + OUT_RING (0); + OUT_RING (0x8006); + BEGIN_RING(celsius, NV10TCL_STENCIL_MASK, 8); + OUT_RING (0xff); + OUT_RING (0x207); + OUT_RING (0); + OUT_RING (0xff); + OUT_RING (0x1e00); + OUT_RING (0x1e00); + OUT_RING (0x1e00); + OUT_RING (0x1d01); + BEGIN_RING(celsius, NV10TCL_NORMALIZE_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_FOG_ENABLE, 2); + OUT_RING (0); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_LIGHT_MODEL, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_COLOR_CONTROL, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_ENABLED_LIGHTS, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3); + OUT_RING (0); + OUT_RING (0); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_DEPTH_FUNC, 1); + OUT_RING (0x201); + BEGIN_RING(celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_DEPTH_TEST_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_POLYGON_OFFSET_FACTOR, 2); + OUT_RING (0); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_POINT_SIZE, 1); + OUT_RING (8); + BEGIN_RING(celsius, NV10TCL_POINT_PARAMETERS_ENABLE, 2); + OUT_RING (0); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_LINE_WIDTH, 1); + OUT_RING (8); + BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_POLYGON_MODE_FRONT, 2); + OUT_RING (0x1b02); + OUT_RING (0x1b02); + BEGIN_RING(celsius, NV10TCL_CULL_FACE, 2); + OUT_RING (0x405); + OUT_RING (0x901); + BEGIN_RING(celsius, NV10TCL_POLYGON_SMOOTH_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_CULL_FACE_ENABLE, 1); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_TX_GEN_S(0), 8); + for (i=0;i<8;i++) { + OUT_RING (0); + } + BEGIN_RING(celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3); + OUT_RING (0x3fc00000); /* -1.50 */ + OUT_RING (0xbdb8aa0a); /* -0.09 */ + OUT_RING (0); /* 0.00 */ + + BEGIN_RING(celsius, NV10TCL_NOP, 1); + OUT_RING (0); + + BEGIN_RING(celsius, NV10TCL_FOG_MODE, 2); + OUT_RING (0x802); + OUT_RING (2); + /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when + * using texturing, except when using the texture matrix + */ + BEGIN_RING(celsius, NV10TCL_VIEW_MATRIX_ENABLE, 1); + OUT_RING (6); + BEGIN_RING(celsius, NV10TCL_COLOR_MASK, 1); + OUT_RING (0x01010101); + + /* Set vertex component */ + BEGIN_RING(celsius, NV10TCL_VERTEX_COL_4F_R, 4); + OUT_RINGf (1.0); + OUT_RINGf (1.0); + OUT_RINGf (1.0); + OUT_RINGf (1.0); + BEGIN_RING(celsius, NV10TCL_VERTEX_COL2_3F_R, 3); + OUT_RING (0); + OUT_RING (0); + OUT_RING (0); + BEGIN_RING(celsius, NV10TCL_VERTEX_NOR_3F_X, 3); + OUT_RING (0); + OUT_RING (0); + OUT_RINGf (1.0); + BEGIN_RING(celsius, NV10TCL_VERTEX_TX0_4F_S, 4); + OUT_RINGf (0.0); + OUT_RINGf (0.0); + OUT_RINGf (0.0); + OUT_RINGf (1.0); + BEGIN_RING(celsius, NV10TCL_VERTEX_TX1_4F_S, 4); + OUT_RINGf (0.0); + OUT_RINGf (0.0); + OUT_RINGf (0.0); + OUT_RINGf (1.0); + BEGIN_RING(celsius, NV10TCL_VERTEX_FOG_1F, 1); + OUT_RINGf (0.0); + BEGIN_RING(celsius, NV10TCL_EDGEFLAG_ENABLE, 1); + OUT_RING (1); + + memset(projectionmatrix, 0, sizeof(projectionmatrix)); + BEGIN_RING(celsius, NV10TCL_PROJECTION_MATRIX(0), 16); + projectionmatrix[0*4+0] = 1.0; + projectionmatrix[1*4+1] = 1.0; + projectionmatrix[2*4+2] = 1.0; + projectionmatrix[3*4+3] = 1.0; + for (i=0;i<16;i++) { + OUT_RINGf (projectionmatrix[i]); + } + + BEGIN_RING(celsius, NV10TCL_DEPTH_RANGE_NEAR, 2); + OUT_RING (0.0); + OUT_RINGf (16777216.0); + + BEGIN_RING(celsius, NV10TCL_VIEWPORT_SCALE_X, 4); + OUT_RINGf (-2048.0); + OUT_RINGf (-2048.0); + OUT_RINGf (16777215.0 * 0.5); + OUT_RING (0); + + FIRE_RING (NULL); +} + +static void +nv10_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield) +{ +} + +static unsigned int +nv10_is_texture_referenced( struct pipe_context *pipe, + struct pipe_texture *texture, + unsigned face, unsigned level) +{ + /** + * FIXME: Optimize. + */ + + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; +} + +static unsigned int +nv10_is_buffer_referenced( struct pipe_context *pipe, + struct pipe_buffer *buf) +{ + /** + * FIXME: Optimize. + */ + + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; +} + +struct pipe_context * +nv10_create(struct pipe_screen *pscreen, unsigned pctx_id) +{ + struct nv10_screen *screen = nv10_screen(pscreen); + struct pipe_winsys *ws = pscreen->winsys; + struct nv10_context *nv10; + struct nouveau_winsys *nvws = screen->nvws; + + nv10 = CALLOC(1, sizeof(struct nv10_context)); + if (!nv10) + return NULL; + nv10->screen = screen; + nv10->pctx_id = pctx_id; + + nv10->nvws = nvws; + + nv10->pipe.winsys = ws; + nv10->pipe.screen = pscreen; + nv10->pipe.destroy = nv10_destroy; + nv10->pipe.set_edgeflags = nv10_set_edgeflags; + nv10->pipe.draw_arrays = nv10_draw_arrays; + nv10->pipe.draw_elements = nv10_draw_elements; + nv10->pipe.clear = nv10_clear; + nv10->pipe.flush = nv10_flush; + + nv10->pipe.is_texture_referenced = nv10_is_texture_referenced; + nv10->pipe.is_buffer_referenced = nv10_is_buffer_referenced; + + nv10_init_surface_functions(nv10); + nv10_init_state_functions(nv10); + + nv10->draw = draw_create(); + assert(nv10->draw); + draw_set_rasterize_stage(nv10->draw, nv10_draw_vbuf_stage(nv10)); + + nv10_init_hwctx(nv10); + + return &nv10->pipe; +} + diff --git a/src/gallium/drivers/nv10/nv10_context.h b/src/gallium/drivers/nv10/nv10_context.h new file mode 100644 index 0000000000..f1e003c953 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_context.h @@ -0,0 +1,154 @@ +#ifndef __NV10_CONTEXT_H__ +#define __NV10_CONTEXT_H__ + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_compiler.h" + +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "draw/draw_vertex.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_gldefs.h" + +#define NOUVEAU_PUSH_CONTEXT(ctx) \ + struct nv10_screen *ctx = nv10->screen +#include "nouveau/nouveau_push.h" + +#include "nv10_state.h" + +#define NOUVEAU_ERR(fmt, args...) \ + fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); +#define NOUVEAU_MSG(fmt, args...) \ + fprintf(stderr, "nouveau: "fmt, ##args); + +#define NV10_NEW_VERTPROG (1 << 0) +#define NV10_NEW_FRAGPROG (1 << 1) +#define NV10_NEW_VTXARRAYS (1 << 2) +#define NV10_NEW_BLEND (1 << 3) +#define NV10_NEW_BLENDCOL (1 << 4) +#define NV10_NEW_RAST (1 << 5) +#define NV10_NEW_DSA (1 << 6) +#define NV10_NEW_VIEWPORT (1 << 7) +#define NV10_NEW_SCISSOR (1 << 8) +#define NV10_NEW_FRAMEBUFFER (1 << 9) + +#include "nv10_screen.h" + +struct nv10_context { + struct pipe_context pipe; + + struct nouveau_winsys *nvws; + struct nv10_screen *screen; + unsigned pctx_id; + + struct draw_context *draw; + + uint32_t dirty; + + struct nv10_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; + struct nv10_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; + unsigned dirty_samplers; + unsigned fp_samplers; + unsigned vp_samplers; + + uint32_t rt_enable; + struct pipe_buffer *rt[4]; + struct pipe_buffer *zeta; + uint32_t lma_offset; + + struct nv10_blend_state *blend; + struct pipe_blend_color *blend_color; + struct nv10_rasterizer_state *rast; + struct nv10_depth_stencil_alpha_state *dsa; + struct pipe_viewport_state *viewport; + struct pipe_scissor_state *scissor; + struct pipe_framebuffer_state *framebuffer; + + //struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; + float *constbuf[PIPE_SHADER_TYPES][32][4]; + unsigned constbuf_nr[PIPE_SHADER_TYPES]; + + struct vertex_info vertex_info; + + struct { + struct pipe_buffer *buffer; + uint32_t format; + } tex[2]; + + unsigned vb_enable; + struct { + struct pipe_buffer *buffer; + unsigned delta; + } vb[16]; + +/* struct { + + struct nouveau_resource *exec_heap; + struct nouveau_resource *data_heap; + + struct nv10_vertex_program *active; + + struct nv10_vertex_program *current; + } vertprog; +*/ + struct { + struct nv10_fragment_program *active; + + struct nv10_fragment_program *current; + struct pipe_buffer *constant_buf; + } fragprog; + + struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; + struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; +}; + +static INLINE struct nv10_context * +nv10_context(struct pipe_context *pipe) +{ + return (struct nv10_context *)pipe; +} + +extern void nv10_init_state_functions(struct nv10_context *nv10); +extern void nv10_init_surface_functions(struct nv10_context *nv10); + +extern void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen); + +/* nv10_clear.c */ +extern void nv10_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil); + + +/* nv10_draw.c */ +extern struct draw_stage *nv10_draw_render_stage(struct nv10_context *nv10); + +/* nv10_fragprog.c */ +extern void nv10_fragprog_bind(struct nv10_context *, + struct nv10_fragment_program *); +extern void nv10_fragprog_destroy(struct nv10_context *, + struct nv10_fragment_program *); + +/* nv10_fragtex.c */ +extern void nv10_fragtex_bind(struct nv10_context *); + +/* nv10_prim_vbuf.c */ +struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 ); +extern void nv10_vtxbuf_bind(struct nv10_context* nv10); + +/* nv10_state.c and friends */ +extern void nv10_emit_hw_state(struct nv10_context *nv10); +extern void nv10_state_tex_update(struct nv10_context *nv10); + +/* nv10_vbo.c */ +extern boolean nv10_draw_arrays(struct pipe_context *, unsigned mode, + unsigned start, unsigned count); +extern boolean nv10_draw_elements( struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned prim, unsigned start, unsigned count); + + +#endif diff --git a/src/gallium/drivers/nv10/nv10_fragprog.c b/src/gallium/drivers/nv10/nv10_fragprog.c new file mode 100644 index 0000000000..698db5a16a --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_fragprog.c @@ -0,0 +1,21 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_util.h" + +#include "nv10_context.h" + +void +nv10_fragprog_bind(struct nv10_context *nv10, struct nv10_fragment_program *fp) +{ +} + +void +nv10_fragprog_destroy(struct nv10_context *nv10, + struct nv10_fragment_program *fp) +{ +} + diff --git a/src/gallium/drivers/nv10/nv10_fragtex.c b/src/gallium/drivers/nv10/nv10_fragtex.c new file mode 100644 index 0000000000..27f2f87584 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_fragtex.c @@ -0,0 +1,124 @@ +#include "nv10_context.h" +#include "nouveau/nouveau_util.h" + +#define _(m,tf) \ +{ \ + TRUE, \ + PIPE_FORMAT_##m, \ + NV10TCL_TX_FORMAT_FORMAT_##tf, \ +} + +struct nv10_texture_format { + boolean defined; + uint pipe; + int format; +}; + +static struct nv10_texture_format +nv10_texture_formats[] = { + _(A8R8G8B8_UNORM, A8R8G8B8), + _(A1R5G5B5_UNORM, A1R5G5B5), + _(A4R4G4B4_UNORM, A4R4G4B4), + _(L8_UNORM , L8 ), + _(A8_UNORM , A8 ), + _(A8L8_UNORM , A8L8 ), +// _(RGB_DXT1 , DXT1, ), +// _(RGBA_DXT1 , DXT1, ), +// _(RGBA_DXT3 , DXT3, ), +// _(RGBA_DXT5 , DXT5, ), + {}, +}; + +static struct nv10_texture_format * +nv10_fragtex_format(uint pipe_format) +{ + struct nv10_texture_format *tf = nv10_texture_formats; + + while (tf->defined) { + if (tf->pipe == pipe_format) + return tf; + tf++; + } + + return NULL; +} + + +static void +nv10_fragtex_build(struct nv10_context *nv10, int unit) +{ +#if 0 + struct nv10_sampler_state *ps = nv10->tex_sampler[unit]; + struct nv10_miptree *nv10mt = nv10->tex_miptree[unit]; + struct pipe_texture *pt = &nv10mt->base; + struct nv10_texture_format *tf; + uint32_t txf, txs, txp; + + tf = nv10_fragtex_format(pt->format); + if (!tf || !tf->defined) { + NOUVEAU_ERR("Unsupported texture format: 0x%x\n", pt->format); + return; + } + + txf = tf->format << 8; + txf |= (pt->last_level + 1) << 16; + txf |= log2i(pt->width[0]) << 20; + txf |= log2i(pt->height[0]) << 24; + txf |= log2i(pt->depth[0]) << 28; + txf |= 8; + + switch (pt->target) { + case PIPE_TEXTURE_CUBE: + txf |= NV10TCL_TX_FORMAT_CUBE_MAP; + /* fall-through */ + case PIPE_TEXTURE_2D: + txf |= (2<<4); + break; + case PIPE_TEXTURE_1D: + txf |= (1<<4); + break; + default: + NOUVEAU_ERR("Unknown target %d\n", pt->target); + return; + } + + BEGIN_RING(celsius, NV10TCL_TX_OFFSET(unit), 8); + OUT_RELOCl(nv10mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); + OUT_RELOCd(nv10mt->buffer,txf,NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/); + OUT_RING (ps->wrap); + OUT_RING (0x40000000); /* enable */ + OUT_RING (txs); + OUT_RING (ps->filt | 0x2000 /* magic */); + OUT_RING ((pt->width[0] << 16) | pt->height[0]); + OUT_RING (ps->bcol); +#endif +} + +void +nv10_fragtex_bind(struct nv10_context *nv10) +{ +#if 0 + struct nv10_fragment_program *fp = nv10->fragprog.active; + unsigned samplers, unit; + + samplers = nv10->fp_samplers & ~fp->samplers; + while (samplers) { + unit = ffs(samplers) - 1; + samplers &= ~(1 << unit); + + BEGIN_RING(celsius, NV10TCL_TX_ENABLE(unit), 1); + OUT_RING (0); + } + + samplers = nv10->dirty_samplers & fp->samplers; + while (samplers) { + unit = ffs(samplers) - 1; + samplers &= ~(1 << unit); + + nv10_fragtex_build(nv10, unit); + } + + nv10->fp_samplers = fp->samplers; +#endif +} + diff --git a/src/gallium/drivers/nv10/nv10_miptree.c b/src/gallium/drivers/nv10/nv10_miptree.c new file mode 100644 index 0000000000..34e3c2ebd7 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_miptree.c @@ -0,0 +1,167 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_inlines.h" + +#include "nv10_context.h" +#include "nv10_screen.h" + +static void +nv10_miptree_layout(struct nv10_miptree *nv10mt) +{ + struct pipe_texture *pt = &nv10mt->base; + boolean swizzled = FALSE; + uint width = pt->width[0], height = pt->height[0]; + uint offset = 0; + int nr_faces, l, f; + + if (pt->target == PIPE_TEXTURE_CUBE) { + nr_faces = 6; + } else { + nr_faces = 1; + } + + for (l = 0; l <= pt->last_level; l++) { + pt->width[l] = width; + pt->height[l] = height; + pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width); + pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height); + + if (swizzled) + nv10mt->level[l].pitch = pt->nblocksx[l] * pt->block.size; + else + nv10mt->level[l].pitch = pt->nblocksx[0] * pt->block.size; + nv10mt->level[l].pitch = (nv10mt->level[l].pitch + 63) & ~63; + + nv10mt->level[l].image_offset = + CALLOC(nr_faces, sizeof(unsigned)); + + width = MAX2(1, width >> 1); + height = MAX2(1, height >> 1); + + } + + for (f = 0; f < nr_faces; f++) { + for (l = 0; l <= pt->last_level; l++) { + nv10mt->level[l].image_offset[f] = offset; + offset += nv10mt->level[l].pitch * pt->height[l]; + } + } + + nv10mt->total_size = offset; +} + +static struct pipe_texture * +nv10_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, + const unsigned *stride, struct pipe_buffer *pb) +{ + struct nv10_miptree *mt; + + /* Only supports 2D, non-mipmapped textures for the moment */ + if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || + pt->depth[0] != 1) + return NULL; + + mt = CALLOC_STRUCT(nv10_miptree); + if (!mt) + return NULL; + + mt->base = *pt; + pipe_reference_init(&mt->base.reference, 1); + mt->base.screen = pscreen; + mt->level[0].pitch = stride[0]; + mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); + + pipe_buffer_reference(&mt->buffer, pb); + return &mt->base; +} + +static struct pipe_texture * +nv10_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) +{ + struct nv10_miptree *mt; + + mt = MALLOC(sizeof(struct nv10_miptree)); + if (!mt) + return NULL; + mt->base = *pt; + pipe_reference_init(&mt->base.reference, 1); + mt->base.screen = screen; + + nv10_miptree_layout(mt); + + mt->buffer = screen->buffer_create(screen, 256, PIPE_BUFFER_USAGE_PIXEL, + mt->total_size); + if (!mt->buffer) { + FREE(mt); + return NULL; + } + + return &mt->base; +} + +static void +nv10_miptree_destroy(struct pipe_texture *pt) +{ + struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt; + int l; + + pipe_buffer_reference(&nv10mt->buffer, NULL); + for (l = 0; l <= pt->last_level; l++) { + if (nv10mt->level[l].image_offset) + FREE(nv10mt->level[l].image_offset); + } + FREE(nv10mt); +} + +static void +nv10_miptree_update(struct pipe_context *pipe, struct pipe_texture *mt, + uint face, uint levels) +{ +} + + +static struct pipe_surface * +nv10_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt, + unsigned face, unsigned level, unsigned zslice, + unsigned flags) +{ + struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt; + struct nv04_surface *ns; + + ns = CALLOC_STRUCT(nv04_surface); + if (!ns) + return NULL; + pipe_texture_reference(&ns->base.texture, pt); + ns->base.format = pt->format; + ns->base.width = pt->width[level]; + ns->base.height = pt->height[level]; + ns->base.usage = flags; + pipe_reference_init(&ns->base.reference, 1); + ns->base.face = face; + ns->base.level = level; + ns->base.zslice = zslice; + ns->pitch = nv10mt->level[level].pitch; + + if (pt->target == PIPE_TEXTURE_CUBE) { + ns->base.offset = nv10mt->level[level].image_offset[face]; + } else { + ns->base.offset = nv10mt->level[level].image_offset[0]; + } + + return &ns->base; +} + +static void +nv10_miptree_surface_destroy(struct pipe_surface *surface) +{ +} + +void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen) +{ + pscreen->texture_create = nv10_miptree_create; + pscreen->texture_blanket = nv10_miptree_blanket; + pscreen->texture_destroy = nv10_miptree_destroy; + pscreen->get_tex_surface = nv10_miptree_surface_get; + pscreen->tex_surface_destroy = nv10_miptree_surface_destroy; +} + diff --git a/src/gallium/drivers/nv10/nv10_prim_vbuf.c b/src/gallium/drivers/nv10/nv10_prim_vbuf.c new file mode 100644 index 0000000000..1806d5f8cc --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_prim_vbuf.c @@ -0,0 +1,261 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * \file + * Build post-transformation, post-clipping vertex buffers and element + * lists by hooking into the end of the primitive pipeline and + * manipulating the vertex_id field in the vertex headers. + * + * XXX: work in progress + * + * \author José Fonseca <jrfonseca@tungstengraphics.com> + * \author Keith Whitwell <keith@tungstengraphics.com> + */ + + +#include "util/u_debug.h" +#include "pipe/p_inlines.h" + +#include "nv10_context.h" +#include "nv10_state.h" + +#include "draw/draw_vbuf.h" + +/** + * Primitive renderer for nv10. + */ +struct nv10_vbuf_render { + struct vbuf_render base; + + struct nv10_context *nv10; + + /** Vertex buffer */ + struct pipe_buffer* buffer; + + /** Vertex size in bytes */ + unsigned vertex_size; + + /** Hardware primitive */ + unsigned hwprim; +}; + + +void nv10_vtxbuf_bind( struct nv10_context* nv10 ) +{ + int i; + for(i = 0; i < 8; i++) { + BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET(i), 1); + OUT_RING(0/*nv10->vtxbuf*/); + BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT(i) ,1); + OUT_RING(0/*XXX*/); + } +} + +/** + * Basically a cast wrapper. + */ +static INLINE struct nv10_vbuf_render * +nv10_vbuf_render( struct vbuf_render *render ) +{ + assert(render); + return (struct nv10_vbuf_render *)render; +} + + +static const struct vertex_info * +nv10_vbuf_render_get_vertex_info( struct vbuf_render *render ) +{ + struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); + struct nv10_context *nv10 = nv10_render->nv10; + + nv10_emit_hw_state(nv10); + + return &nv10->vertex_info; +} + +static boolean +nv10_vbuf_render_allocate_vertices( struct vbuf_render *render, + ushort vertex_size, + ushort nr_vertices ) +{ + struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); + struct nv10_context *nv10 = nv10_render->nv10; + struct pipe_screen *screen = nv10->pipe.screen; + size_t size = (size_t)vertex_size * (size_t)nr_vertices; + + assert(!nv10_render->buffer); + nv10_render->buffer = screen->buffer_create(screen, 64, PIPE_BUFFER_USAGE_VERTEX, size); + + nv10->dirty |= NV10_NEW_VTXARRAYS; + + if (nv10_render->buffer) + return FALSE; + return TRUE; +} + +static void * +nv10_vbuf_render_map_vertices( struct vbuf_render *render ) +{ + struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); + struct nv10_context *nv10 = nv10_render->nv10; + struct pipe_screen *pscreen = nv10->pipe.screen; + + return pipe_buffer_map(pscreen, nv10_render->buffer, + PIPE_BUFFER_USAGE_CPU_WRITE); +} + +static void +nv10_vbuf_render_unmap_vertices( struct vbuf_render *render, + ushort min_index, + ushort max_index ) +{ + struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); + struct nv10_context *nv10 = nv10_render->nv10; + struct pipe_screen *pscreen = nv10->pipe.screen; + + assert(!nv10_render->buffer); + pipe_buffer_unmap(pscreen, nv10_render->buffer); +} + +static boolean +nv10_vbuf_render_set_primitive( struct vbuf_render *render, + unsigned prim ) +{ + struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); + unsigned hwp = nvgl_primitive(prim); + if (hwp == 0) + return FALSE; + + nv10_render->hwprim = hwp; + return TRUE; +} + + +static void +nv10_vbuf_render_draw( struct vbuf_render *render, + const ushort *indices, + uint nr_indices) +{ + struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); + struct nv10_context *nv10 = nv10_render->nv10; + int push, i; + + nv10_emit_hw_state(nv10); + + BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_OFFSET_POS, 1); + OUT_RELOCl(nv10_render->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); + + BEGIN_RING(celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); + OUT_RING(nv10_render->hwprim); + + if (nr_indices & 1) { + BEGIN_RING(celsius, NV10TCL_VB_ELEMENT_U32, 1); + OUT_RING (indices[0]); + indices++; nr_indices--; + } + + while (nr_indices) { + // XXX too big/small ? check the size + push = MIN2(nr_indices, 1200 * 2); + + BEGIN_RING_NI(celsius, NV10TCL_VB_ELEMENT_U16, push >> 1); + for (i = 0; i < push; i+=2) + OUT_RING((indices[i+1] << 16) | indices[i]); + + nr_indices -= push; + indices += push; + } + + BEGIN_RING(celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); + OUT_RING (0); +} + + +static void +nv10_vbuf_render_release_vertices( struct vbuf_render *render ) +{ + struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); + + assert(nv10_render->buffer); + pipe_buffer_reference(&nv10_render->buffer, NULL); +} + + +static void +nv10_vbuf_render_destroy( struct vbuf_render *render ) +{ + struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); + FREE(nv10_render); +} + + +/** + * Create a new primitive render. + */ +static struct vbuf_render * +nv10_vbuf_render_create( struct nv10_context *nv10 ) +{ + struct nv10_vbuf_render *nv10_render = CALLOC_STRUCT(nv10_vbuf_render); + + nv10_render->nv10 = nv10; + + nv10_render->base.max_vertex_buffer_bytes = 16*1024; + nv10_render->base.max_indices = 1024; + nv10_render->base.get_vertex_info = nv10_vbuf_render_get_vertex_info; + nv10_render->base.allocate_vertices = nv10_vbuf_render_allocate_vertices; + nv10_render->base.map_vertices = nv10_vbuf_render_map_vertices; + nv10_render->base.unmap_vertices = nv10_vbuf_render_unmap_vertices; + nv10_render->base.set_primitive = nv10_vbuf_render_set_primitive; + nv10_render->base.draw = nv10_vbuf_render_draw; + nv10_render->base.release_vertices = nv10_vbuf_render_release_vertices; + nv10_render->base.destroy = nv10_vbuf_render_destroy; + + return &nv10_render->base; +} + + +/** + * Create a new primitive vbuf/render stage. + */ +struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 ) +{ + struct vbuf_render *render; + struct draw_stage *stage; + + render = nv10_vbuf_render_create(nv10); + if(!render) + return NULL; + + stage = draw_vbuf_stage( nv10->draw, render ); + if(!stage) { + render->destroy(render); + return NULL; + } + + return stage; +} diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c new file mode 100644 index 0000000000..4469b22d91 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_screen.c @@ -0,0 +1,198 @@ +#include "pipe/p_screen.h" + +#include "nv10_context.h" +#include "nv10_screen.h" + +static int +nv10_screen_get_param(struct pipe_screen *screen, int param) +{ + switch (param) { + case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: + return 2; + case PIPE_CAP_NPOT_TEXTURES: + return 0; + case PIPE_CAP_TWO_SIDED_STENCIL: + return 0; + 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 0; + case PIPE_CAP_MAX_RENDER_TARGETS: + return 1; + case PIPE_CAP_OCCLUSION_QUERY: + return 0; + case PIPE_CAP_TEXTURE_SHADOW_MAP: + return 0; + case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: + return 12; + case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: + return 0; + case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: + return 12; + case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: + return 0; + case PIPE_CAP_TGSI_CONT_SUPPORTED: + return 0; + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 0; + case NOUVEAU_CAP_HW_VTXBUF: + case NOUVEAU_CAP_HW_IDXBUF: + return 0; + default: + NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); + return 0; + } +} + +static float +nv10_screen_get_paramf(struct pipe_screen *screen, 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 2.0; + case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: + return 4.0; + default: + NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); + return 0.0; + } +} + +static boolean +nv10_screen_is_format_supported(struct pipe_screen *screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned tex_usage, unsigned geom_flags) +{ + if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { + switch (format) { + case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_R5G6B5_UNORM: + return TRUE; + default: + break; + } + } else + if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { + switch (format) { + case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z16_UNORM: + return TRUE; + default: + break; + } + } else { + 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_L8_UNORM: + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_I8_UNORM: + return TRUE; + default: + break; + } + } + + return FALSE; +} + +static void +nv10_screen_destroy(struct pipe_screen *pscreen) +{ + struct nv10_screen *screen = nv10_screen(pscreen); + + nouveau_notifier_free(&screen->sync); + nouveau_grobj_free(&screen->celsius); + + FREE(pscreen); +} + +static struct pipe_buffer * +nv10_surface_buffer(struct pipe_surface *surf) +{ + struct nv10_miptree *mt = (struct nv10_miptree *)surf->texture; + + return mt->buffer; +} + +struct pipe_screen * +nv10_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) +{ + struct nv10_screen *screen = CALLOC_STRUCT(nv10_screen); + struct nouveau_channel *chan; + struct pipe_screen *pscreen; + unsigned celsius_class; + int ret; + + if (!screen) + return NULL; + pscreen = &screen->base.base; + + ret = nouveau_screen_init(&screen->base, dev); + if (ret) { + nv10_screen_destroy(pscreen); + return NULL; + } + chan = screen->base.channel; + + pscreen->winsys = ws; + pscreen->destroy = nv10_screen_destroy; + pscreen->get_param = nv10_screen_get_param; + pscreen->get_paramf = nv10_screen_get_paramf; + pscreen->is_format_supported = nv10_screen_is_format_supported; + + nv10_screen_init_miptree_functions(pscreen); + nv10_screen_init_transfer_functions(pscreen); + + /* 3D object */ + if (dev->chipset >= 0x20) + celsius_class = NV11TCL; + else if (dev->chipset >= 0x17) + celsius_class = NV17TCL; + else if (dev->chipset >= 0x11) + celsius_class = NV11TCL; + else + celsius_class = NV10TCL; + + if (!celsius_class) { + NOUVEAU_ERR("Unknown nv1x chipset: nv%02x\n", dev->chipset); + return NULL; + } + + ret = nouveau_grobj_alloc(chan, 0xbeef0001, celsius_class, + &screen->celsius); + if (ret) { + NOUVEAU_ERR("Error creating 3D object: %d\n", ret); + return FALSE; + } + BIND_RING(chan, screen->celsius, 7); + + /* 2D engine setup */ + screen->eng2d = nv04_surface_2d_init(&screen->base); + screen->eng2d->buf = nv10_surface_buffer; + + /* Notifier for sync purposes */ + ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); + if (ret) { + NOUVEAU_ERR("Error creating notifier object: %d\n", ret); + nv10_screen_destroy(pscreen); + return NULL; + } + + return pscreen; +} + diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h new file mode 100644 index 0000000000..86b6d8def5 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_screen.h @@ -0,0 +1,28 @@ +#ifndef __NV10_SCREEN_H__ +#define __NV10_SCREEN_H__ + +#include "nouveau/nouveau_screen.h" +#include "nv04/nv04_surface_2d.h" + +struct nv10_screen { + struct nouveau_screen base; + + struct nouveau_winsys *nvws; + + /* HW graphics objects */ + struct nv04_surface_2d *eng2d; + struct nouveau_grobj *celsius; + struct nouveau_notifier *sync; +}; + +static INLINE struct nv10_screen * +nv10_screen(struct pipe_screen *screen) +{ + return (struct nv10_screen *)screen; +} + + +void +nv10_screen_init_transfer_functions(struct pipe_screen *pscreen); + +#endif diff --git a/src/gallium/drivers/nv10/nv10_state.c b/src/gallium/drivers/nv10/nv10_state.c new file mode 100644 index 0000000000..9b38219b99 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_state.c @@ -0,0 +1,590 @@ +#include "draw/draw_context.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_inlines.h" + +#include "tgsi/tgsi_parse.h" + +#include "nv10_context.h" +#include "nv10_state.h" + +static void * +nv10_blend_state_create(struct pipe_context *pipe, + const struct pipe_blend_state *cso) +{ + struct nv10_blend_state *cb; + + cb = MALLOC(sizeof(struct nv10_blend_state)); + + cb->b_enable = cso->blend_enable ? 1 : 0; + cb->b_srcfunc = ((nvgl_blend_func(cso->alpha_src_factor)<<16) | + (nvgl_blend_func(cso->rgb_src_factor))); + cb->b_dstfunc = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) | + (nvgl_blend_func(cso->rgb_dst_factor))); + + cb->c_mask = (((cso->colormask & PIPE_MASK_A) ? (0x01<<24) : 0) | + ((cso->colormask & PIPE_MASK_R) ? (0x01<<16) : 0) | + ((cso->colormask & PIPE_MASK_G) ? (0x01<< 8) : 0) | + ((cso->colormask & PIPE_MASK_B) ? (0x01<< 0) : 0)); + + cb->d_enable = cso->dither ? 1 : 0; + + return (void *)cb; +} + +static void +nv10_blend_state_bind(struct pipe_context *pipe, void *blend) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + nv10->blend = (struct nv10_blend_state*)blend; + + nv10->dirty |= NV10_NEW_BLEND; +} + +static void +nv10_blend_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + + +static INLINE unsigned +wrap_mode(unsigned wrap) { + unsigned ret; + + switch (wrap) { + case PIPE_TEX_WRAP_REPEAT: + ret = NV10TCL_TX_FORMAT_WRAP_S_REPEAT; + break; + case PIPE_TEX_WRAP_MIRROR_REPEAT: + ret = NV10TCL_TX_FORMAT_WRAP_S_MIRRORED_REPEAT; + break; + case PIPE_TEX_WRAP_CLAMP_TO_EDGE: + ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE; + break; + case PIPE_TEX_WRAP_CLAMP_TO_BORDER: + ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_BORDER; + break; + case PIPE_TEX_WRAP_CLAMP: + ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP; + break; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + case PIPE_TEX_WRAP_MIRROR_CLAMP: + default: + NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); + ret = NV10TCL_TX_FORMAT_WRAP_S_REPEAT; + break; + } + + return ret >> NV10TCL_TX_FORMAT_WRAP_S_SHIFT; +} + +static void * +nv10_sampler_state_create(struct pipe_context *pipe, + const struct pipe_sampler_state *cso) +{ + struct nv10_sampler_state *ps; + uint32_t filter = 0; + + ps = MALLOC(sizeof(struct nv10_sampler_state)); + + ps->wrap = ((wrap_mode(cso->wrap_s) << NV10TCL_TX_FORMAT_WRAP_S_SHIFT) | + (wrap_mode(cso->wrap_t) << NV10TCL_TX_FORMAT_WRAP_T_SHIFT)); + + ps->en = 0; + if (cso->max_anisotropy > 1.0) { + /* no idea, binary driver sets it, works without it.. meh.. */ + ps->wrap |= (1 << 5); + +/* if (cso->max_anisotropy >= 16.0) { + ps->en |= NV10TCL_TX_ENABLE_ANISO_16X; + } else + if (cso->max_anisotropy >= 12.0) { + ps->en |= NV10TCL_TX_ENABLE_ANISO_12X; + } else + if (cso->max_anisotropy >= 10.0) { + ps->en |= NV10TCL_TX_ENABLE_ANISO_10X; + } else + if (cso->max_anisotropy >= 8.0) { + ps->en |= NV10TCL_TX_ENABLE_ANISO_8X; + } else + if (cso->max_anisotropy >= 6.0) { + ps->en |= NV10TCL_TX_ENABLE_ANISO_6X; + } else + if (cso->max_anisotropy >= 4.0) { + ps->en |= NV10TCL_TX_ENABLE_ANISO_4X; + } else { + ps->en |= NV10TCL_TX_ENABLE_ANISO_2X; + }*/ + } + + switch (cso->mag_img_filter) { + case PIPE_TEX_FILTER_LINEAR: + filter |= NV10TCL_TX_FILTER_MAGNIFY_LINEAR; + break; + case PIPE_TEX_FILTER_NEAREST: + default: + filter |= NV10TCL_TX_FILTER_MAGNIFY_NEAREST; + break; + } + + switch (cso->min_img_filter) { + case PIPE_TEX_FILTER_LINEAR: + switch (cso->min_mip_filter) { + case PIPE_TEX_MIPFILTER_NEAREST: + filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST; + break; + case PIPE_TEX_MIPFILTER_LINEAR: + filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR; + break; + case PIPE_TEX_MIPFILTER_NONE: + default: + filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR; + break; + } + break; + case PIPE_TEX_FILTER_NEAREST: + default: + switch (cso->min_mip_filter) { + case PIPE_TEX_MIPFILTER_NEAREST: + filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST; + break; + case PIPE_TEX_MIPFILTER_LINEAR: + filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR; + break; + case PIPE_TEX_MIPFILTER_NONE: + default: + filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST; + break; + } + break; + } + + ps->filt = filter; + +/* if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { + switch (cso->compare_func) { + case PIPE_FUNC_NEVER: + ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NEVER; + break; + case PIPE_FUNC_GREATER: + ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GREATER; + break; + case PIPE_FUNC_EQUAL: + ps->wrap |= NV10TCL_TX_WRAP_RCOMP_EQUAL; + break; + case PIPE_FUNC_GEQUAL: + ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GEQUAL; + break; + case PIPE_FUNC_LESS: + ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LESS; + break; + case PIPE_FUNC_NOTEQUAL: + ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NOTEQUAL; + break; + case PIPE_FUNC_LEQUAL: + ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LEQUAL; + break; + case PIPE_FUNC_ALWAYS: + ps->wrap |= NV10TCL_TX_WRAP_RCOMP_ALWAYS; + break; + default: + break; + } + }*/ + + ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) | + (float_to_ubyte(cso->border_color[0]) << 16) | + (float_to_ubyte(cso->border_color[1]) << 8) | + (float_to_ubyte(cso->border_color[2]) << 0)); + + return (void *)ps; +} + +static void +nv10_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ + struct nv10_context *nv10 = nv10_context(pipe); + unsigned unit; + + for (unit = 0; unit < nr; unit++) { + nv10->tex_sampler[unit] = sampler[unit]; + nv10->dirty_samplers |= (1 << unit); + } +} + +static void +nv10_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void +nv10_set_sampler_texture(struct pipe_context *pipe, unsigned nr, + struct pipe_texture **miptree) +{ + struct nv10_context *nv10 = nv10_context(pipe); + unsigned unit; + + for (unit = 0; unit < nr; unit++) { + nv10->tex_miptree[unit] = (struct nv10_miptree *)miptree[unit]; + nv10->dirty_samplers |= (1 << unit); + } +} + +static void * +nv10_rasterizer_state_create(struct pipe_context *pipe, + const struct pipe_rasterizer_state *cso) +{ + struct nv10_rasterizer_state *rs; + int i; + + /*XXX: ignored: + * light_twoside + * offset_cw/ccw -nohw + * scissor + * point_smooth -nohw + * multisample + * offset_units / offset_scale + */ + rs = MALLOC(sizeof(struct nv10_rasterizer_state)); + + rs->templ = cso; + + rs->shade_model = cso->flatshade ? 0x1d00 : 0x1d01; + + rs->line_width = (unsigned char)(cso->line_width * 8.0) & 0xff; + rs->line_smooth_en = cso->line_smooth ? 1 : 0; + + rs->point_size = *(uint32_t*)&cso->point_size; + + rs->poly_smooth_en = cso->poly_smooth ? 1 : 0; + + if (cso->front_winding == PIPE_WINDING_CCW) { + rs->front_face = NV10TCL_FRONT_FACE_CCW; + rs->poly_mode_front = nvgl_polygon_mode(cso->fill_ccw); + rs->poly_mode_back = nvgl_polygon_mode(cso->fill_cw); + } else { + rs->front_face = NV10TCL_FRONT_FACE_CW; + rs->poly_mode_front = nvgl_polygon_mode(cso->fill_cw); + rs->poly_mode_back = nvgl_polygon_mode(cso->fill_ccw); + } + + switch (cso->cull_mode) { + case PIPE_WINDING_CCW: + rs->cull_face_en = 1; + if (cso->front_winding == PIPE_WINDING_CCW) + rs->cull_face = NV10TCL_CULL_FACE_FRONT; + else + rs->cull_face = NV10TCL_CULL_FACE_BACK; + break; + case PIPE_WINDING_CW: + rs->cull_face_en = 1; + if (cso->front_winding == PIPE_WINDING_CW) + rs->cull_face = NV10TCL_CULL_FACE_FRONT; + else + rs->cull_face = NV10TCL_CULL_FACE_BACK; + break; + case PIPE_WINDING_BOTH: + rs->cull_face_en = 1; + rs->cull_face = NV10TCL_CULL_FACE_FRONT_AND_BACK; + break; + case PIPE_WINDING_NONE: + default: + rs->cull_face_en = 0; + rs->cull_face = 0; + break; + } + + if (cso->point_sprite) { + rs->point_sprite = (1 << 0); + for (i = 0; i < 8; i++) { + if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE) + rs->point_sprite |= (1 << (8 + i)); + } + } else { + rs->point_sprite = 0; + } + + return (void *)rs; +} + +static void +nv10_rasterizer_state_bind(struct pipe_context *pipe, void *rast) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + nv10->rast = (struct nv10_rasterizer_state*)rast; + + draw_set_rasterizer_state(nv10->draw, (nv10->rast ? nv10->rast->templ : NULL)); + + nv10->dirty |= NV10_NEW_RAST; +} + +static void +nv10_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void * +nv10_depth_stencil_alpha_state_create(struct pipe_context *pipe, + const struct pipe_depth_stencil_alpha_state *cso) +{ + struct nv10_depth_stencil_alpha_state *hw; + + hw = MALLOC(sizeof(struct nv10_depth_stencil_alpha_state)); + + hw->depth.func = nvgl_comparison_op(cso->depth.func); + hw->depth.write_enable = cso->depth.writemask ? 1 : 0; + hw->depth.test_enable = cso->depth.enabled ? 1 : 0; + + hw->stencil.enable = cso->stencil[0].enabled ? 1 : 0; + hw->stencil.wmask = cso->stencil[0].writemask; + hw->stencil.func = nvgl_comparison_op(cso->stencil[0].func); + hw->stencil.ref = cso->stencil[0].ref_value; + hw->stencil.vmask = cso->stencil[0].valuemask; + hw->stencil.fail = nvgl_stencil_op(cso->stencil[0].fail_op); + hw->stencil.zfail = nvgl_stencil_op(cso->stencil[0].zfail_op); + hw->stencil.zpass = nvgl_stencil_op(cso->stencil[0].zpass_op); + + hw->alpha.enabled = cso->alpha.enabled ? 1 : 0; + hw->alpha.func = nvgl_comparison_op(cso->alpha.func); + hw->alpha.ref = float_to_ubyte(cso->alpha.ref_value); + + return (void *)hw; +} + +static void +nv10_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *dsa) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + nv10->dsa = (struct nv10_depth_stencil_alpha_state*)dsa; + + nv10->dirty |= NV10_NEW_DSA; +} + +static void +nv10_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void * +nv10_vp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *templ) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + return draw_create_vertex_shader(nv10->draw, templ); +} + +static void +nv10_vp_state_bind(struct pipe_context *pipe, void *shader) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + draw_bind_vertex_shader(nv10->draw, (struct draw_vertex_shader *) shader); + + nv10->dirty |= NV10_NEW_VERTPROG; +} + +static void +nv10_vp_state_delete(struct pipe_context *pipe, void *shader) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + draw_delete_vertex_shader(nv10->draw, (struct draw_vertex_shader *) shader); +} + +static void * +nv10_fp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso) +{ + struct nv10_fragment_program *fp; + + fp = CALLOC(1, sizeof(struct nv10_fragment_program)); + fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); + + tgsi_scan_shader(cso->tokens, &fp->info); + + return (void *)fp; +} + +static void +nv10_fp_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nv10_context *nv10 = nv10_context(pipe); + struct nv10_fragment_program *fp = hwcso; + + nv10->fragprog.current = fp; + nv10->dirty |= NV10_NEW_FRAGPROG; +} + +static void +nv10_fp_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nv10_context *nv10 = nv10_context(pipe); + struct nv10_fragment_program *fp = hwcso; + + nv10_fragprog_destroy(nv10, fp); + FREE((void*)fp->pipe.tokens); + FREE(fp); +} + +static void +nv10_set_blend_color(struct pipe_context *pipe, + const struct pipe_blend_color *bcol) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + nv10->blend_color = (struct pipe_blend_color*)bcol; + + nv10->dirty |= NV10_NEW_BLENDCOL; +} + +static void +nv10_set_clip_state(struct pipe_context *pipe, + const struct pipe_clip_state *clip) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + draw_set_clip_state(nv10->draw, clip); +} + +static void +nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, + const struct pipe_constant_buffer *buf ) +{ + struct nv10_context *nv10 = nv10_context(pipe); + struct pipe_screen *pscreen = pipe->screen; + + assert(shader < PIPE_SHADER_TYPES); + assert(index == 0); + + if (buf) { + void *mapped; + if (buf->buffer && buf->buffer->size && + (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ))) + { + memcpy(nv10->constbuf[shader], mapped, buf->buffer->size); + nv10->constbuf_nr[shader] = + buf->buffer->size / (4 * sizeof(float)); + pipe_buffer_unmap(pscreen, buf->buffer); + } + } +} + +static void +nv10_set_framebuffer_state(struct pipe_context *pipe, + const struct pipe_framebuffer_state *fb) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + nv10->framebuffer = (struct pipe_framebuffer_state*)fb; + + nv10->dirty |= NV10_NEW_FRAMEBUFFER; +} + +static void +nv10_set_polygon_stipple(struct pipe_context *pipe, + const struct pipe_poly_stipple *stipple) +{ + NOUVEAU_ERR("line stipple hahaha\n"); +} + +static void +nv10_set_scissor_state(struct pipe_context *pipe, + const struct pipe_scissor_state *s) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + nv10->scissor = (struct pipe_scissor_state*)s; + + nv10->dirty |= NV10_NEW_SCISSOR; +} + +static void +nv10_set_viewport_state(struct pipe_context *pipe, + const struct pipe_viewport_state *vpt) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + nv10->viewport = (struct pipe_viewport_state*)vpt; + + draw_set_viewport_state(nv10->draw, nv10->viewport); + + nv10->dirty |= NV10_NEW_VIEWPORT; +} + +static void +nv10_set_vertex_buffers(struct pipe_context *pipe, unsigned count, + const struct pipe_vertex_buffer *vb) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + memcpy(nv10->vtxbuf, vb, sizeof(*vb) * count); + nv10->dirty |= NV10_NEW_VTXARRAYS; + + draw_set_vertex_buffers(nv10->draw, count, vb); +} + +static void +nv10_set_vertex_elements(struct pipe_context *pipe, unsigned count, + const struct pipe_vertex_element *ve) +{ + struct nv10_context *nv10 = nv10_context(pipe); + + memcpy(nv10->vtxelt, ve, sizeof(*ve) * count); + nv10->dirty |= NV10_NEW_VTXARRAYS; + + draw_set_vertex_elements(nv10->draw, count, ve); +} + +void +nv10_init_state_functions(struct nv10_context *nv10) +{ + nv10->pipe.create_blend_state = nv10_blend_state_create; + nv10->pipe.bind_blend_state = nv10_blend_state_bind; + nv10->pipe.delete_blend_state = nv10_blend_state_delete; + + nv10->pipe.create_sampler_state = nv10_sampler_state_create; + nv10->pipe.bind_sampler_states = nv10_sampler_state_bind; + nv10->pipe.delete_sampler_state = nv10_sampler_state_delete; + nv10->pipe.set_sampler_textures = nv10_set_sampler_texture; + + nv10->pipe.create_rasterizer_state = nv10_rasterizer_state_create; + nv10->pipe.bind_rasterizer_state = nv10_rasterizer_state_bind; + nv10->pipe.delete_rasterizer_state = nv10_rasterizer_state_delete; + + nv10->pipe.create_depth_stencil_alpha_state = + nv10_depth_stencil_alpha_state_create; + nv10->pipe.bind_depth_stencil_alpha_state = + nv10_depth_stencil_alpha_state_bind; + nv10->pipe.delete_depth_stencil_alpha_state = + nv10_depth_stencil_alpha_state_delete; + + nv10->pipe.create_vs_state = nv10_vp_state_create; + nv10->pipe.bind_vs_state = nv10_vp_state_bind; + nv10->pipe.delete_vs_state = nv10_vp_state_delete; + + nv10->pipe.create_fs_state = nv10_fp_state_create; + nv10->pipe.bind_fs_state = nv10_fp_state_bind; + nv10->pipe.delete_fs_state = nv10_fp_state_delete; + + nv10->pipe.set_blend_color = nv10_set_blend_color; + nv10->pipe.set_clip_state = nv10_set_clip_state; + nv10->pipe.set_constant_buffer = nv10_set_constant_buffer; + nv10->pipe.set_framebuffer_state = nv10_set_framebuffer_state; + nv10->pipe.set_polygon_stipple = nv10_set_polygon_stipple; + nv10->pipe.set_scissor_state = nv10_set_scissor_state; + nv10->pipe.set_viewport_state = nv10_set_viewport_state; + + nv10->pipe.set_vertex_buffers = nv10_set_vertex_buffers; + nv10->pipe.set_vertex_elements = nv10_set_vertex_elements; +} + diff --git a/src/gallium/drivers/nv10/nv10_state.h b/src/gallium/drivers/nv10/nv10_state.h new file mode 100644 index 0000000000..3a3fd0d4f4 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_state.h @@ -0,0 +1,139 @@ +#ifndef __NV10_STATE_H__ +#define __NV10_STATE_H__ + +#include "pipe/p_state.h" +#include "tgsi/tgsi_scan.h" + +struct nv10_blend_state { + uint32_t b_enable; + uint32_t b_srcfunc; + uint32_t b_dstfunc; + + uint32_t c_mask; + + uint32_t d_enable; +}; + +struct nv10_sampler_state { + uint32_t wrap; + uint32_t en; + uint32_t filt; + uint32_t bcol; +}; + +struct nv10_rasterizer_state { + uint32_t shade_model; + + uint32_t line_width; + uint32_t line_smooth_en; + + uint32_t point_size; + + uint32_t poly_smooth_en; + + uint32_t poly_mode_front; + uint32_t poly_mode_back; + + uint32_t front_face; + uint32_t cull_face; + uint32_t cull_face_en; + + uint32_t point_sprite; + + const struct pipe_rasterizer_state *templ; +}; + +struct nv10_vertex_program_exec { + uint32_t data[4]; + boolean has_branch_offset; + int const_index; +}; + +struct nv10_vertex_program_data { + int index; /* immediates == -1 */ + float value[4]; +}; + +struct nv10_vertex_program { + const struct pipe_shader_state *pipe; + + boolean translated; + struct nv10_vertex_program_exec *insns; + unsigned nr_insns; + struct nv10_vertex_program_data *consts; + unsigned nr_consts; + + struct nouveau_resource *exec; + unsigned exec_start; + struct nouveau_resource *data; + unsigned data_start; + unsigned data_start_min; + + uint32_t ir; + uint32_t or; +}; + +struct nv10_fragment_program_data { + unsigned offset; + unsigned index; +}; + +struct nv10_fragment_program { + struct pipe_shader_state pipe; + struct tgsi_shader_info info; + + boolean translated; + boolean on_hw; + unsigned samplers; + + uint32_t *insn; + int insn_len; + + struct nv10_fragment_program_data *consts; + unsigned nr_consts; + + struct pipe_buffer *buffer; + + uint32_t fp_control; + uint32_t fp_reg_control; +}; + + +struct nv10_depth_stencil_alpha_state { + struct { + uint32_t func; + uint32_t write_enable; + uint32_t test_enable; + } depth; + + struct { + uint32_t enable; + uint32_t wmask; + uint32_t func; + uint32_t ref; + uint32_t vmask; + uint32_t fail; + uint32_t zfail; + uint32_t zpass; + } stencil; + + struct { + uint32_t enabled; + uint32_t func; + uint32_t ref; + } alpha; +}; + +struct nv10_miptree { + struct pipe_texture base; + + struct pipe_buffer *buffer; + uint total_size; + + struct { + uint pitch; + uint *image_offset; + } level[PIPE_MAX_TEXTURE_LEVELS]; +}; + +#endif diff --git a/src/gallium/drivers/nv10/nv10_state_emit.c b/src/gallium/drivers/nv10/nv10_state_emit.c new file mode 100644 index 0000000000..d8691ef9c6 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_state_emit.c @@ -0,0 +1,306 @@ +#include "nv10_context.h" +#include "nv10_state.h" + +static void nv10_state_emit_blend(struct nv10_context* nv10) +{ + struct nv10_blend_state *b = nv10->blend; + + BEGIN_RING(celsius, NV10TCL_DITHER_ENABLE, 1); + OUT_RING (b->d_enable); + + BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_ENABLE, 3); + OUT_RING (b->b_enable); + OUT_RING (b->b_srcfunc); + OUT_RING (b->b_dstfunc); + + BEGIN_RING(celsius, NV10TCL_COLOR_MASK, 1); + OUT_RING (b->c_mask); +} + +static void nv10_state_emit_blend_color(struct nv10_context* nv10) +{ + struct pipe_blend_color *c = nv10->blend_color; + + BEGIN_RING(celsius, NV10TCL_BLEND_COLOR, 1); + OUT_RING ((float_to_ubyte(c->color[3]) << 24)| + (float_to_ubyte(c->color[0]) << 16)| + (float_to_ubyte(c->color[1]) << 8) | + (float_to_ubyte(c->color[2]) << 0)); +} + +static void nv10_state_emit_rast(struct nv10_context* nv10) +{ + struct nv10_rasterizer_state *r = nv10->rast; + + BEGIN_RING(celsius, NV10TCL_SHADE_MODEL, 2); + OUT_RING (r->shade_model); + OUT_RING (r->line_width); + + + BEGIN_RING(celsius, NV10TCL_POINT_SIZE, 1); + OUT_RING (r->point_size); + + BEGIN_RING(celsius, NV10TCL_POLYGON_MODE_FRONT, 2); + OUT_RING (r->poly_mode_front); + OUT_RING (r->poly_mode_back); + + + BEGIN_RING(celsius, NV10TCL_CULL_FACE, 2); + OUT_RING (r->cull_face); + OUT_RING (r->front_face); + + BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 2); + OUT_RING (r->line_smooth_en); + OUT_RING (r->poly_smooth_en); + + BEGIN_RING(celsius, NV10TCL_CULL_FACE_ENABLE, 1); + OUT_RING (r->cull_face_en); +} + +static void nv10_state_emit_dsa(struct nv10_context* nv10) +{ + struct nv10_depth_stencil_alpha_state *d = nv10->dsa; + + BEGIN_RING(celsius, NV10TCL_DEPTH_FUNC, 1); + OUT_RING (d->depth.func); + + BEGIN_RING(celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1); + OUT_RING (d->depth.write_enable); + + BEGIN_RING(celsius, NV10TCL_DEPTH_TEST_ENABLE, 1); + OUT_RING (d->depth.test_enable); + +#if 0 + BEGIN_RING(celsius, NV10TCL_STENCIL_ENABLE, 1); + OUT_RING (d->stencil.enable); + BEGIN_RING(celsius, NV10TCL_STENCIL_MASK, 7); + OUT_RINGp ((uint32_t *)&(d->stencil.wmask), 7); +#endif + + BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1); + OUT_RING (d->alpha.enabled); + + BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_FUNC, 1); + OUT_RING (d->alpha.func); + + BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_REF, 1); + OUT_RING (d->alpha.ref); +} + +static void nv10_state_emit_viewport(struct nv10_context* nv10) +{ +} + +static void nv10_state_emit_scissor(struct nv10_context* nv10) +{ + // XXX this is so not working +/* struct pipe_scissor_state *s = nv10->scissor; + BEGIN_RING(celsius, NV10TCL_SCISSOR_HORIZ, 2); + OUT_RING (((s->maxx - s->minx) << 16) | s->minx); + OUT_RING (((s->maxy - s->miny) << 16) | s->miny);*/ +} + +static void nv10_state_emit_framebuffer(struct nv10_context* nv10) +{ + struct pipe_framebuffer_state* fb = nv10->framebuffer; + struct nv04_surface *rt, *zeta = NULL; + uint32_t rt_format, w, h; + int colour_format = 0, zeta_format = 0; + struct nv10_miptree *nv10mt = 0; + + 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; + } + + rt_format = NV10TCL_RT_FORMAT_TYPE_LINEAR; + + switch (colour_format) { + case PIPE_FORMAT_A8R8G8B8_UNORM: + case 0: + rt_format |= NV10TCL_RT_FORMAT_COLOR_A8R8G8B8; + break; + case PIPE_FORMAT_R5G6B5_UNORM: + rt_format |= NV10TCL_RT_FORMAT_COLOR_R5G6B5; + break; + default: + assert(0); + } + + if (zeta) { + BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1); + OUT_RING (rt->pitch | (zeta->pitch << 16)); + } else { + BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1); + OUT_RING (rt->pitch | (rt->pitch << 16)); + } + + nv10mt = (struct nv10_miptree *)rt->base.texture; + nv10->rt[0] = nv10mt->buffer; + + if (zeta_format) + { + nv10mt = (struct nv10_miptree *)zeta->base.texture; + nv10->zeta = nv10mt->buffer; + } + + BEGIN_RING(celsius, NV10TCL_RT_HORIZ, 3); + OUT_RING ((w << 16) | 0); + OUT_RING ((h << 16) | 0); + OUT_RING (rt_format); + BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 2); + OUT_RING (((w - 1) << 16) | 0 | 0x08000800); + OUT_RING (((h - 1) << 16) | 0 | 0x08000800); +} + +static void nv10_vertex_layout(struct nv10_context *nv10) +{ + struct nv10_fragment_program *fp = nv10->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++) { + switch (fp->info.input_semantic_name[i]) { + 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; + } + } + draw_compute_vertex_size(&vinfo); +} + +void +nv10_emit_hw_state(struct nv10_context *nv10) +{ + int i; + + if (nv10->dirty & NV10_NEW_VERTPROG) { + //nv10_vertprog_bind(nv10, nv10->vertprog.current); + nv10->dirty &= ~NV10_NEW_VERTPROG; + } + + if (nv10->dirty & NV10_NEW_FRAGPROG) { + nv10_fragprog_bind(nv10, nv10->fragprog.current); + /*XXX: clear NV10_NEW_FRAGPROG if no new program uploaded */ + nv10->dirty_samplers |= (1<<10); + nv10->dirty_samplers = 0; + } + + if (nv10->dirty_samplers || (nv10->dirty & NV10_NEW_FRAGPROG)) { + nv10_fragtex_bind(nv10); + nv10->dirty &= ~NV10_NEW_FRAGPROG; + } + + if (nv10->dirty & NV10_NEW_VTXARRAYS) { + nv10->dirty &= ~NV10_NEW_VTXARRAYS; + nv10_vertex_layout(nv10); + nv10_vtxbuf_bind(nv10); + } + + if (nv10->dirty & NV10_NEW_BLEND) { + nv10->dirty &= ~NV10_NEW_BLEND; + nv10_state_emit_blend(nv10); + } + + if (nv10->dirty & NV10_NEW_BLENDCOL) { + nv10->dirty &= ~NV10_NEW_BLENDCOL; + nv10_state_emit_blend_color(nv10); + } + + if (nv10->dirty & NV10_NEW_RAST) { + nv10->dirty &= ~NV10_NEW_RAST; + nv10_state_emit_rast(nv10); + } + + if (nv10->dirty & NV10_NEW_DSA) { + nv10->dirty &= ~NV10_NEW_DSA; + nv10_state_emit_dsa(nv10); + } + + if (nv10->dirty & NV10_NEW_VIEWPORT) { + nv10->dirty &= ~NV10_NEW_VIEWPORT; + nv10_state_emit_viewport(nv10); + } + + if (nv10->dirty & NV10_NEW_SCISSOR) { + nv10->dirty &= ~NV10_NEW_SCISSOR; + nv10_state_emit_scissor(nv10); + } + + if (nv10->dirty & NV10_NEW_FRAMEBUFFER) { + nv10->dirty &= ~NV10_NEW_FRAMEBUFFER; + nv10_state_emit_framebuffer(nv10); + } + + /* 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 nv10_vbo.c + */ + + /* Render target */ +// XXX figre out who's who for NV10TCL_DMA_* and fill accordingly +// BEGIN_RING(celsius, NV10TCL_DMA_COLOR0, 1); +// OUT_RELOCo(nv10->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + BEGIN_RING(celsius, NV10TCL_COLOR_OFFSET, 1); + OUT_RELOCl(nv10->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + + if (nv10->zeta) { +// XXX +// BEGIN_RING(celsius, NV10TCL_DMA_ZETA, 1); +// OUT_RELOCo(nv10->zeta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + BEGIN_RING(celsius, NV10TCL_ZETA_OFFSET, 1); + OUT_RELOCl(nv10->zeta, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + /* XXX for when we allocate LMA on nv17 */ +/* BEGIN_RING(celsius, NV10TCL_LMA_DEPTH_BUFFER_OFFSET, 1); + OUT_RELOCl(nv10->zeta + lma_offset);*/ + } + + /* Vertex buffer */ + BEGIN_RING(celsius, NV10TCL_DMA_VTXBUF0, 1); + OUT_RELOCo(nv10->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + BEGIN_RING(celsius, NV10TCL_COLOR_OFFSET, 1); + OUT_RELOCl(nv10->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + + /* Texture images */ + for (i = 0; i < 2; i++) { + if (!(nv10->fp_samplers & (1 << i))) + continue; + BEGIN_RING(celsius, NV10TCL_TX_OFFSET(i), 1); + OUT_RELOCl(nv10->tex[i].buffer, 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_GART | NOUVEAU_BO_RD); + BEGIN_RING(celsius, NV10TCL_TX_FORMAT(i), 1); + OUT_RELOCd(nv10->tex[i].buffer, nv10->tex[i].format, + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | + NOUVEAU_BO_OR, NV10TCL_TX_FORMAT_DMA0, + NV10TCL_TX_FORMAT_DMA1); + } +} + diff --git a/src/gallium/drivers/nv10/nv10_surface.c b/src/gallium/drivers/nv10/nv10_surface.c new file mode 100644 index 0000000000..5b52246a9c --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_surface.c @@ -0,0 +1,63 @@ + +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "nv10_context.h" +#include "pipe/p_defines.h" +#include "pipe/internal/p_winsys_screen.h" +#include "pipe/p_inlines.h" +#include "util/u_tile.h" + +static void +nv10_surface_copy(struct pipe_context *pipe, + struct pipe_surface *dest, unsigned destx, unsigned desty, + struct pipe_surface *src, unsigned srcx, unsigned srcy, + unsigned width, unsigned height) +{ + struct nv10_context *nv10 = nv10_context(pipe); + struct nv04_surface_2d *eng2d = nv10->screen->eng2d; + + eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); +} + +static void +nv10_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, + unsigned destx, unsigned desty, unsigned width, + unsigned height, unsigned value) +{ + struct nv10_context *nv10 = nv10_context(pipe); + struct nv04_surface_2d *eng2d = nv10->screen->eng2d; + + eng2d->fill(eng2d, dest, destx, desty, width, height, value); +} + +void +nv10_init_surface_functions(struct nv10_context *nv10) +{ + nv10->pipe.surface_copy = nv10_surface_copy; + nv10->pipe.surface_fill = nv10_surface_fill; +} diff --git a/src/gallium/drivers/nv10/nv10_transfer.c b/src/gallium/drivers/nv10/nv10_transfer.c new file mode 100644 index 0000000000..c06b8d34c7 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_transfer.c @@ -0,0 +1,195 @@ +#include <pipe/p_state.h> +#include <pipe/p_defines.h> +#include <pipe/p_inlines.h> +#include <util/u_memory.h> +#include <nouveau/nouveau_winsys.h> +#include "nv10_context.h" +#include "nv10_screen.h" +#include "nv10_state.h" + +struct nv10_transfer { + struct pipe_transfer base; + struct pipe_surface *surface; + bool direct; +}; + +static unsigned nv10_usage_tx_to_buf(unsigned tx_usage) +{ + switch (tx_usage) { + case PIPE_TRANSFER_READ: + return PIPE_BUFFER_USAGE_CPU_READ; + case PIPE_TRANSFER_WRITE: + return PIPE_BUFFER_USAGE_CPU_WRITE; + case PIPE_TRANSFER_READ_WRITE: + return PIPE_BUFFER_USAGE_CPU_READ_WRITE; + default: + assert(0); + } + + return -1; +} + +static void +nv10_compatible_transfer_tex(struct pipe_texture *pt, unsigned level, + struct pipe_texture *template) +{ + memset(template, 0, sizeof(struct pipe_texture)); + template->target = pt->target; + template->format = pt->format; + template->width[0] = pt->width[level]; + template->height[0] = pt->height[level]; + template->depth[0] = 1; + template->block = pt->block; + template->nblocksx[0] = pt->nblocksx[level]; + template->nblocksy[0] = pt->nblocksx[level]; + template->last_level = 0; + template->nr_samples = pt->nr_samples; + + template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + NOUVEAU_TEXTURE_USAGE_LINEAR; +} + +static struct pipe_transfer * +nv10_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct nv10_miptree *mt = (struct nv10_miptree *)pt; + struct nv10_transfer *tx; + struct pipe_texture tx_tex_template, *tx_tex; + + tx = CALLOC_STRUCT(nv10_transfer); + if (!tx) + return NULL; + + pipe_texture_reference(&tx->base.texture, pt); + tx->base.format = pt->format; + tx->base.x = x; + tx->base.y = y; + tx->base.width = w; + tx->base.height = h; + tx->base.block = pt->block; + tx->base.nblocksx = pt->nblocksx[level]; + tx->base.nblocksy = pt->nblocksy[level]; + tx->base.stride = mt->level[level].pitch; + tx->base.usage = usage; + tx->base.face = face; + tx->base.level = level; + tx->base.zslice = zslice; + + /* Direct access to texture */ + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || + debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && + pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) + { + tx->direct = true; + tx->surface = pscreen->get_tex_surface(pscreen, pt, + 0, 0, 0, + nv10_usage_tx_to_buf(usage)); + return &tx->base; + } + + tx->direct = false; + + nv10_compatible_transfer_tex(pt, level, &tx_tex_template); + + tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); + if (!tx_tex) + { + FREE(tx); + return NULL; + } + + tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, + face, level, zslice, + nv10_usage_tx_to_buf(usage)); + + pipe_texture_reference(&tx_tex, NULL); + + if (!tx->surface) + { + pipe_surface_reference(&tx->surface, NULL); + FREE(tx); + return NULL; + } + + if (usage != PIPE_TRANSFER_WRITE) { + struct nv10_screen *nvscreen = nv10_screen(pscreen); + struct pipe_surface *src; + + src = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + PIPE_BUFFER_USAGE_GPU_READ); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + /* TODO: Check if SIFM can un-swizzle */ + nvscreen->eng2d->copy(nvscreen->eng2d, + tx->surface, 0, 0, + src, 0, 0, + src->width, src->height); + + pipe_surface_reference(&src, NULL); + } + + return &tx->base; +} + +static void +nv10_transfer_del(struct pipe_transfer *ptx) +{ + struct nv10_transfer *tx = (struct nv10_transfer *)ptx; + + if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) { + struct pipe_screen *pscreen = ptx->texture->screen; + struct nv10_screen *nvscreen = nv10_screen(pscreen); + struct pipe_surface *dst; + + dst = pscreen->get_tex_surface(pscreen, ptx->texture, + ptx->face, ptx->level, ptx->zslice, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + nvscreen->eng2d->copy(nvscreen->eng2d, + dst, 0, 0, + tx->surface, 0, 0, + dst->width, dst->height); + + pipe_surface_reference(&dst, NULL); + } + + pipe_surface_reference(&tx->surface, NULL); + pipe_texture_reference(&ptx->texture, NULL); + FREE(ptx); +} + +static void * +nv10_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv10_transfer *tx = (struct nv10_transfer *)ptx; + struct nv04_surface *ns = (struct nv04_surface *)tx->surface; + struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture; + void *map = pipe_buffer_map(pscreen, mt->buffer, + nv10_usage_tx_to_buf(ptx->usage)); + + return map + ns->base.offset + + ptx->y * ns->pitch + ptx->x * ptx->block.size; +} + +static void +nv10_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv10_transfer *tx = (struct nv10_transfer *)ptx; + struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture; + + pipe_buffer_unmap(pscreen, mt->buffer); +} + +void +nv10_screen_init_transfer_functions(struct pipe_screen *pscreen) +{ + pscreen->get_tex_transfer = nv10_transfer_new; + pscreen->tex_transfer_destroy = nv10_transfer_del; + pscreen->transfer_map = nv10_transfer_map; + pscreen->transfer_unmap = nv10_transfer_unmap; +} diff --git a/src/gallium/drivers/nv10/nv10_vbo.c b/src/gallium/drivers/nv10/nv10_vbo.c new file mode 100644 index 0000000000..441a4f75f3 --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_vbo.c @@ -0,0 +1,78 @@ +#include "draw/draw_context.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_inlines.h" + +#include "nv10_context.h" +#include "nv10_state.h" + +#include "nouveau/nouveau_channel.h" +#include "nouveau/nouveau_pushbuf.h" + +boolean nv10_draw_elements( struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned prim, unsigned start, unsigned count) +{ + struct nv10_context *nv10 = nv10_context( pipe ); + struct draw_context *draw = nv10->draw; + struct pipe_screen *pscreen = pipe->screen; + unsigned i; + + nv10_emit_hw_state(nv10); + + /* + * Map vertex buffers + */ + for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { + if (nv10->vtxbuf[i].buffer) { + void *buf = + pipe_buffer_map(pscreen, nv10->vtxbuf[i].buffer, + PIPE_BUFFER_USAGE_CPU_READ); + draw_set_mapped_vertex_buffer(draw, i, buf); + } + } + /* Map index buffer, if present */ + if (indexBuffer) { + void *mapped_indexes + = pipe_buffer_map(pscreen, indexBuffer, + PIPE_BUFFER_USAGE_CPU_READ); + draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); + } + else { + /* no index/element buffer */ + draw_set_mapped_element_buffer(draw, 0, NULL); + } + + draw_set_mapped_constant_buffer(draw, + nv10->constbuf[PIPE_SHADER_VERTEX], + nv10->constbuf_nr[PIPE_SHADER_VERTEX]); + + /* draw! */ + draw_arrays(nv10->draw, prim, start, count); + + /* + * unmap vertex/index buffers + */ + for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { + if (nv10->vtxbuf[i].buffer) { + pipe_buffer_unmap(pscreen, nv10->vtxbuf[i].buffer); + draw_set_mapped_vertex_buffer(draw, i, NULL); + } + } + if (indexBuffer) { + pipe_buffer_unmap(pscreen, indexBuffer); + draw_set_mapped_element_buffer(draw, 0, NULL); + } + + return TRUE; +} + +boolean nv10_draw_arrays( struct pipe_context *pipe, + unsigned prim, unsigned start, unsigned count) +{ + return nv10_draw_elements(pipe, NULL, 0, prim, start, count); +} + + + |