diff options
| author | Pekka Paalanen <pq@iki.fi> | 2008-11-12 23:13:22 +0200 | 
|---|---|---|
| committer | Pekka Paalanen <pq@iki.fi> | 2008-11-12 23:13:22 +0200 | 
| commit | 5aaeb13a768f0c7d3706f6c170901b118ae1aa2d (patch) | |
| tree | 53b72b178245c254cfe2328e9bacba1244833c52 /src | |
| parent | 1d6cba6572cc008760e9d4ff803b0b7e1420e41b (diff) | |
| parent | 94631e63a8d56562b782ec30a6ec5b9d77ca70a0 (diff) | |
Merge commit 'origin/gallium-0.1' into gallium-0.2
* commit 'origin/gallium-0.1':
  Mesa: fix number of buffers in st_draw_vbo().
  Nouveau: fix nv20_vertex_layout()
  Nouveau: update nv20 miptree according to nv40.
  Nouveau: build, link and use nv20.
  Nouveau: name replace for nv20.
  Nouveau: Rename nv20/ files as nv20.
  Nouveau: copy nv30_vertprog.c to nv20.
  Nouveau: start nv20 by copying the nv10 tree.
Diffstat (limited to 'src')
21 files changed, 3307 insertions, 3 deletions
| diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index 48feeba309..a89b056244 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -70,6 +70,12 @@ extern struct pipe_context *  nv10_create(struct pipe_screen *, unsigned pctx_id);  extern struct pipe_screen * +nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); + +extern struct pipe_context * +nv20_create(struct pipe_screen *, unsigned pctx_id); + +extern struct pipe_screen *  nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);  extern struct pipe_context * diff --git a/src/gallium/drivers/nv20/Makefile b/src/gallium/drivers/nv20/Makefile new file mode 100644 index 0000000000..d777fd3d8b --- /dev/null +++ b/src/gallium/drivers/nv20/Makefile @@ -0,0 +1,29 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nv20 + +DRIVER_SOURCES = \ +	nv20_clear.c \ +	nv20_context.c \ +	nv20_fragprog.c \ +	nv20_fragtex.c \ +	nv20_miptree.c \ +	nv20_prim_vbuf.c \ +	nv20_screen.c \ +	nv20_state.c \ +	nv20_state_emit.c \ +	nv20_surface.c \ +	nv20_vbo.c +#	nv20_vertprog.c + +C_SOURCES = \ +	$(COMMON_SOURCES) \ +	$(DRIVER_SOURCES) + +ASM_SOURCES =  + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/drivers/nv20/nv20_clear.c b/src/gallium/drivers/nv20/nv20_clear.c new file mode 100644 index 0000000000..81b6f3e78a --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_clear.c @@ -0,0 +1,12 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" + +#include "nv20_context.h" + +void +nv20_clear(struct pipe_context *pipe, struct pipe_surface *ps, +	   unsigned clearValue) +{ +	pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); +} diff --git a/src/gallium/drivers/nv20/nv20_context.c b/src/gallium/drivers/nv20/nv20_context.c new file mode 100644 index 0000000000..2af5b0203e --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_context.c @@ -0,0 +1,296 @@ +#include "draw/draw_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_winsys.h" + +#include "nv20_context.h" +#include "nv20_screen.h" + +static void +nv20_flush(struct pipe_context *pipe, unsigned flags, +	   struct pipe_fence_handle **fence) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	draw_flush(nv20->draw); + +	FIRE_RING(fence); +} + +static void +nv20_destroy(struct pipe_context *pipe) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	if (nv20->draw) +		draw_destroy(nv20->draw); + +	FREE(nv20); +} + +static void nv20_init_hwctx(struct nv20_context *nv20) +{ +	struct nv20_screen *screen = nv20->screen; +	struct nouveau_winsys *nvws = screen->nvws; +	int i; +	float projectionmatrix[16]; + +	BEGIN_RING(kelvin, NV10TCL_DMA_NOTIFY, 1); +	OUT_RING  (screen->sync->handle); +	BEGIN_RING(kelvin, NV10TCL_DMA_IN_MEMORY0, 2); +	OUT_RING  (nvws->channel->vram->handle); +	OUT_RING  (nvws->channel->gart->handle); +	BEGIN_RING(kelvin, NV10TCL_DMA_IN_MEMORY2, 2); +	OUT_RING  (nvws->channel->vram->handle); +	OUT_RING  (nvws->channel->vram->handle); + +	BEGIN_RING(kelvin, NV10TCL_NOP, 1); +	OUT_RING  (0); + +	BEGIN_RING(kelvin, NV10TCL_RT_HORIZ, 2); +	OUT_RING  (0); +	OUT_RING  (0); + +	BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1); +	OUT_RING  ((0x7ff<<16)|0x800); +	BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_VERT(0), 1); +	OUT_RING  ((0x7ff<<16)|0x800); + +	for (i=1;i<8;i++) { +		BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1); +		OUT_RING  (0); +		BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_VERT(i), 1); +		OUT_RING  (0); +	} + +	BEGIN_RING(kelvin, 0x290, 1); +	OUT_RING  ((0x10<<16)|1); +	BEGIN_RING(kelvin, 0x3f4, 1); +	OUT_RING  (0); + +	BEGIN_RING(kelvin, NV10TCL_NOP, 1); +	OUT_RING  (0); + +	if (nv20->screen->kelvin->grclass != NV10TCL) { +		/* For nv11, nv17 */ +		BEGIN_RING(kelvin, 0x120, 3); +		OUT_RING  (0); +		OUT_RING  (1); +		OUT_RING  (2); + +		BEGIN_RING(kelvin, NV10TCL_NOP, 1); +		OUT_RING  (0); +	} + +	BEGIN_RING(kelvin, NV10TCL_NOP, 1); +	OUT_RING  (0); + +	/* Set state */ +	BEGIN_RING(kelvin, NV10TCL_FOG_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_FUNC, 2); +	OUT_RING  (0x207); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_TX_ENABLE(0), 2); +	OUT_RING  (0); +	OUT_RING  (0); + +	BEGIN_RING(kelvin, 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(kelvin, NV10TCL_BLEND_FUNC_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_DITHER_ENABLE, 2); +	OUT_RING  (1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_LINE_SMOOTH_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_VERTEX_WEIGHT_ENABLE, 2); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_BLEND_FUNC_SRC, 4); +	OUT_RING  (1); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RING  (0x8006); +	BEGIN_RING(kelvin, 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(kelvin, NV10TCL_NORMALIZE_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_FOG_ENABLE, 2); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_LIGHT_MODEL, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_COLOR_CONTROL, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_ENABLED_LIGHTS, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_DEPTH_FUNC, 1); +	OUT_RING  (0x201); +	BEGIN_RING(kelvin, NV10TCL_DEPTH_WRITE_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_DEPTH_TEST_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_POLYGON_OFFSET_FACTOR, 2); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_POINT_SIZE, 1); +	OUT_RING  (8); +	BEGIN_RING(kelvin, NV10TCL_POINT_PARAMETERS_ENABLE, 2); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_LINE_WIDTH, 1); +	OUT_RING  (8); +	BEGIN_RING(kelvin, NV10TCL_LINE_SMOOTH_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_POLYGON_MODE_FRONT, 2); +	OUT_RING  (0x1b02); +	OUT_RING  (0x1b02); +	BEGIN_RING(kelvin, NV10TCL_CULL_FACE, 2); +	OUT_RING  (0x405); +	OUT_RING  (0x901); +	BEGIN_RING(kelvin, NV10TCL_POLYGON_SMOOTH_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_CULL_FACE_ENABLE, 1); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_CLIP_PLANE_ENABLE(0), 8); +	for (i=0;i<8;i++) { +		OUT_RING  (0); +	} +	BEGIN_RING(kelvin, NV10TCL_FOG_EQUATION_CONSTANT, 3); +	OUT_RING  (0x3fc00000);	/* -1.50 */ +	OUT_RING  (0xbdb8aa0a);	/* -0.09 */ +	OUT_RING  (0);		/*  0.00 */ + +	BEGIN_RING(kelvin, NV10TCL_NOP, 1); +	OUT_RING  (0); + +	BEGIN_RING(kelvin, 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(kelvin, NV10TCL_VIEW_MATRIX_ENABLE, 1); +	OUT_RING  (6); +	BEGIN_RING(kelvin, NV10TCL_COLOR_MASK, 1); +	OUT_RING  (0x01010101); + +	/* Set vertex component */ +	BEGIN_RING(kelvin, NV10TCL_VERTEX_COL_4F_R, 4); +	OUT_RINGf (1.0); +	OUT_RINGf (1.0); +	OUT_RINGf (1.0); +	OUT_RINGf (1.0); +	BEGIN_RING(kelvin, NV10TCL_VERTEX_COL2_3F_R, 3); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RING  (0); +	BEGIN_RING(kelvin, NV10TCL_VERTEX_NOR_3F_X, 3); +	OUT_RING  (0); +	OUT_RING  (0); +	OUT_RINGf (1.0); +	BEGIN_RING(kelvin, NV10TCL_VERTEX_TX0_4F_S, 4); +	OUT_RINGf (0.0); +	OUT_RINGf (0.0); +	OUT_RINGf (0.0); +	OUT_RINGf (1.0); +	BEGIN_RING(kelvin, NV10TCL_VERTEX_TX1_4F_S, 4); +	OUT_RINGf (0.0); +	OUT_RINGf (0.0); +	OUT_RINGf (0.0); +	OUT_RINGf (1.0); +	BEGIN_RING(kelvin, NV10TCL_VERTEX_FOG_1F, 1); +	OUT_RINGf (0.0); +	BEGIN_RING(kelvin, NV10TCL_EDGEFLAG_ENABLE, 1); +	OUT_RING  (1); + +	memset(projectionmatrix, 0, sizeof(projectionmatrix)); +	BEGIN_RING(kelvin, 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(kelvin, NV10TCL_DEPTH_RANGE_NEAR, 2); +	OUT_RING  (0.0); +	OUT_RINGf  (16777216.0); + +	BEGIN_RING(kelvin, 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 +nv20_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield) +{ +} + +struct pipe_context * +nv20_create(struct pipe_screen *pscreen, unsigned pctx_id) +{ +	struct nv20_screen *screen = nv20_screen(pscreen); +	struct pipe_winsys *ws = pscreen->winsys; +	struct nv20_context *nv20; +	struct nouveau_winsys *nvws = screen->nvws; + +	nv20 = CALLOC(1, sizeof(struct nv20_context)); +	if (!nv20) +		return NULL; +	nv20->screen = screen; +	nv20->pctx_id = pctx_id; + +	nv20->nvws = nvws; + +	nv20->pipe.winsys = ws; +	nv20->pipe.screen = pscreen; +	nv20->pipe.destroy = nv20_destroy; +	nv20->pipe.set_edgeflags = nv20_set_edgeflags; +	nv20->pipe.draw_arrays = nv20_draw_arrays; +	nv20->pipe.draw_elements = nv20_draw_elements; +	nv20->pipe.clear = nv20_clear; +	nv20->pipe.flush = nv20_flush; + +	nv20_init_surface_functions(nv20); +	nv20_init_state_functions(nv20); + +	nv20->draw = draw_create(); +	assert(nv20->draw); +	draw_set_rasterize_stage(nv20->draw, nv20_draw_vbuf_stage(nv20)); + +	nv20_init_hwctx(nv20); + +	return &nv20->pipe; +} + diff --git a/src/gallium/drivers/nv20/nv20_context.h b/src/gallium/drivers/nv20/nv20_context.h new file mode 100644 index 0000000000..8ad926db20 --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_context.h @@ -0,0 +1,153 @@ +#ifndef __NV20_CONTEXT_H__ +#define __NV20_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 nv20_screen *ctx = nv20->screen +#include "nouveau/nouveau_push.h" + +#include "nv20_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 NV20_NEW_VERTPROG	(1 << 0) +#define NV20_NEW_FRAGPROG	(1 << 1) +#define NV20_NEW_VTXARRAYS	(1 << 2) +#define NV20_NEW_BLEND		(1 << 3) +#define NV20_NEW_BLENDCOL	(1 << 4) +#define NV20_NEW_RAST 		(1 << 5) +#define NV20_NEW_DSA  		(1 << 6) +#define NV20_NEW_VIEWPORT	(1 << 7) +#define NV20_NEW_SCISSOR	(1 << 8) +#define NV20_NEW_FRAMEBUFFER	(1 << 9) + +#include "nv20_screen.h" + +struct nv20_context { +	struct pipe_context pipe; + +	struct nouveau_winsys *nvws; +	struct nv20_screen *screen; +	unsigned pctx_id; + +	struct draw_context *draw; + +	uint32_t dirty; + +	struct nv20_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; +	struct nv20_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 nv20_blend_state *blend; +	struct pipe_blend_color *blend_color; +	struct nv20_rasterizer_state *rast; +	struct nv20_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 nv20_vertex_program *active; + +		struct nv20_vertex_program *current; +	} vertprog; +*/ +	struct { +		struct nv20_fragment_program *active; + +		struct nv20_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 nv20_context * +nv20_context(struct pipe_context *pipe) +{ +	return (struct nv20_context *)pipe; +} + +extern void nv20_init_state_functions(struct nv20_context *nv20); +extern void nv20_init_surface_functions(struct nv20_context *nv20); + +extern void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen); + +/* nv20_clear.c */ +extern void nv20_clear(struct pipe_context *pipe, struct pipe_surface *ps, +		       unsigned clearValue); + +/* nv20_draw.c */ +extern struct draw_stage *nv20_draw_render_stage(struct nv20_context *nv20); + +/* nv20_fragprog.c */ +extern void nv20_fragprog_bind(struct nv20_context *, +			       struct nv20_fragment_program *); +extern void nv20_fragprog_destroy(struct nv20_context *, +				  struct nv20_fragment_program *); + +/* nv20_fragtex.c */ +extern void nv20_fragtex_bind(struct nv20_context *); + +/* nv20_prim_vbuf.c */ +struct draw_stage *nv20_draw_vbuf_stage( struct nv20_context *nv20 ); +extern void nv20_vtxbuf_bind(struct nv20_context* nv20); + +/* nv20_state.c and friends */ +extern void nv20_emit_hw_state(struct nv20_context *nv20); +extern void nv20_state_tex_update(struct nv20_context *nv20); + +/* nv20_vbo.c */ +extern boolean nv20_draw_arrays(struct pipe_context *, unsigned mode, +				unsigned start, unsigned count); +extern boolean nv20_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/nv20/nv20_fragprog.c b/src/gallium/drivers/nv20/nv20_fragprog.c new file mode 100644 index 0000000000..4f496369dd --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_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 "nv20_context.h" + +void +nv20_fragprog_bind(struct nv20_context *nv20, struct nv20_fragment_program *fp) +{ +} + +void +nv20_fragprog_destroy(struct nv20_context *nv20, +		      struct nv20_fragment_program *fp) +{ +} + diff --git a/src/gallium/drivers/nv20/nv20_fragtex.c b/src/gallium/drivers/nv20/nv20_fragtex.c new file mode 100644 index 0000000000..77c34897e2 --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_fragtex.c @@ -0,0 +1,149 @@ +#include "nv20_context.h" + +static INLINE int log2i(int i) +{ +	int r = 0; + +	if (i & 0xffff0000) { +		i >>= 16; +		r += 16; +	} +	if (i & 0x0000ff00) { +		i >>= 8; +		r += 8; +	} +	if (i & 0x000000f0) { +		i >>= 4; +		r += 4; +	} +	if (i & 0x0000000c) { +		i >>= 2; +		r += 2; +	} +	if (i & 0x00000002) { +		r += 1; +	} +	return r; +} + +#define _(m,tf)                                                                \ +{                                                                              \ +  TRUE,                                                                        \ +  PIPE_FORMAT_##m,                                                             \ +  NV10TCL_TX_FORMAT_FORMAT_##tf,                                               \ +} + +struct nv20_texture_format { +	boolean defined; +	uint	pipe; +	int     format; +}; + +static struct nv20_texture_format +nv20_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 nv20_texture_format * +nv20_fragtex_format(uint pipe_format) +{ +	struct nv20_texture_format *tf = nv20_texture_formats; + +	while (tf->defined) { +		if (tf->pipe == pipe_format) +			return tf; +		tf++; +	} + +	return NULL; +} + + +static void +nv20_fragtex_build(struct nv20_context *nv20, int unit) +{ +#if 0 +	struct nv20_sampler_state *ps = nv20->tex_sampler[unit]; +	struct nv20_miptree *nv20mt = nv20->tex_miptree[unit]; +	struct pipe_texture *pt = &nv20mt->base; +	struct nv20_texture_format *tf; +	uint32_t txf, txs, txp; + +	tf = nv20_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(kelvin, NV10TCL_TX_OFFSET(unit), 8); +	OUT_RELOCl(nv20mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); +	OUT_RELOCd(nv20mt->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 +nv20_fragtex_bind(struct nv20_context *nv20) +{ +#if 0 +	struct nv20_fragment_program *fp = nv20->fragprog.active; +	unsigned samplers, unit; + +	samplers = nv20->fp_samplers & ~fp->samplers; +	while (samplers) { +		unit = ffs(samplers) - 1; +		samplers &= ~(1 << unit); + +		BEGIN_RING(kelvin, NV10TCL_TX_ENABLE(unit), 1); +		OUT_RING  (0); +	} + +	samplers = nv20->dirty_samplers & fp->samplers; +	while (samplers) { +		unit = ffs(samplers) - 1; +		samplers &= ~(1 << unit); + +		nv20_fragtex_build(nv20, unit); +	} + +	nv20->fp_samplers = fp->samplers; +#endif +} + diff --git a/src/gallium/drivers/nv20/nv20_miptree.c b/src/gallium/drivers/nv20/nv20_miptree.c new file mode 100644 index 0000000000..b014f4c22e --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_miptree.c @@ -0,0 +1,154 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_inlines.h" + +#include "nv20_context.h" +#include "nv20_screen.h" + +static void +nv20_miptree_layout(struct nv20_miptree *nv20mt) +{ +	struct pipe_texture *pt = &nv20mt->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) +			nv20mt->level[l].pitch = pt->nblocksx[l] * pt->block.size; +		else +			nv20mt->level[l].pitch = pt->nblocksx[0] * pt->block.size; +		nv20mt->level[l].pitch = (nv20mt->level[l].pitch + 63) & ~63; + +		nv20mt->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++) { +			nv20mt->level[l].image_offset[f] = offset; +			offset += nv20mt->level[l].pitch * pt->height[l]; +		} +	} + +	nv20mt->total_size = offset; +} + +static struct pipe_texture * +nv20_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) +{ +	struct pipe_winsys *ws = screen->winsys; +	struct nv20_miptree *mt; + +	mt = MALLOC(sizeof(struct nv20_miptree)); +	if (!mt) +		return NULL; +	mt->base = *pt; +	mt->base.refcount = 1; +	mt->base.screen = screen; + +	nv20_miptree_layout(mt); + +	mt->buffer = ws->buffer_create(ws, 256, PIPE_BUFFER_USAGE_PIXEL, +					   mt->total_size); +	if (!mt->buffer) { +		FREE(mt); +		return NULL; +	} +	 +	return &mt->base; +} + +static void +nv20_miptree_release(struct pipe_screen *screen, struct pipe_texture **pt) +{ +	struct pipe_texture *mt = *pt; + +	*pt = NULL; +	if (--mt->refcount <= 0) { +		struct nv20_miptree *nv20mt = (struct nv20_miptree *)mt; +		int l; + +		pipe_buffer_reference(screen, &nv20mt->buffer, NULL); +		for (l = 0; l <= mt->last_level; l++) { +			if (nv20mt->level[l].image_offset) +				FREE(nv20mt->level[l].image_offset); +		} +		FREE(nv20mt); +	} +} + +static struct pipe_surface * +nv20_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt, +			 unsigned face, unsigned level, unsigned zslice, +			 unsigned flags) +{ +	struct nv20_miptree *nv20mt = (struct nv20_miptree *)pt; +	struct pipe_surface *ps; + +	ps = CALLOC_STRUCT(pipe_surface); +	if (!ps) +		return NULL; +	pipe_texture_reference(&ps->texture, pt); +	pipe_buffer_reference(screen, &ps->buffer, nv20mt->buffer); +	ps->format = pt->format; +	ps->width = pt->width[level]; +	ps->height = pt->height[level]; +	ps->block = pt->block; +	ps->nblocksx = pt->nblocksx[level]; +	ps->nblocksy = pt->nblocksy[level]; +	ps->stride = nv20mt->level[level].pitch; +	ps->usage = flags; +	ps->status = PIPE_SURFACE_STATUS_DEFINED; + +	if (pt->target == PIPE_TEXTURE_CUBE) { +		ps->offset = nv20mt->level[level].image_offset[face]; +	} else +	if (pt->target == PIPE_TEXTURE_3D) { +		ps->offset = nv20mt->level[level].image_offset[zslice]; +	} else { +		ps->offset = nv20mt->level[level].image_offset[0]; +	} + +	return ps; +} + +static void +nv20_miptree_surface_release(struct pipe_screen *pscreen, +			     struct pipe_surface **psurface) +{ +	struct pipe_surface *ps = *psurface; + +	*psurface = NULL; +	if (--ps->refcount > 0) +		return; + +	pipe_texture_reference(&ps->texture, NULL); +	pipe_buffer_reference(pscreen, &ps->buffer, NULL); +	FREE(ps); +} + +void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen) +{ +	pscreen->texture_create = nv20_miptree_create; +	pscreen->texture_release = nv20_miptree_release; +	pscreen->get_tex_surface = nv20_miptree_surface_get; +	pscreen->tex_surface_release = nv20_miptree_surface_release; +} + diff --git a/src/gallium/drivers/nv20/nv20_prim_vbuf.c b/src/gallium/drivers/nv20/nv20_prim_vbuf.c new file mode 100644 index 0000000000..a51d657d27 --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_prim_vbuf.c @@ -0,0 +1,240 @@ +/************************************************************************** + *  + * 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 "pipe/p_debug.h" +#include "pipe/p_inlines.h" +#include "pipe/p_winsys.h" + +#include "nv20_context.h" +#include "nv20_state.h" + +#include "draw/draw_vbuf.h" + +/** + * Primitive renderer for nv20. + */ +struct nv20_vbuf_render { +	struct vbuf_render base; + +	struct nv20_context *nv20;    + +	/** Vertex buffer */ +	struct pipe_buffer* buffer; + +	/** Vertex size in bytes */ +	unsigned vertex_size; + +	/** Hardware primitive */ +	unsigned hwprim; +}; + + +void nv20_vtxbuf_bind( struct nv20_context* nv20 ) +{ +	int i; +	for(i = 0; i < 8; i++) { +		BEGIN_RING(kelvin, NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET(i), 1); +		OUT_RING(0/*nv20->vtxbuf*/); +		BEGIN_RING(kelvin, NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT(i) ,1); +		OUT_RING(0/*XXX*/); +	} +} + +/** + * Basically a cast wrapper. + */ +static INLINE struct nv20_vbuf_render * +nv20_vbuf_render( struct vbuf_render *render ) +{ +	assert(render); +	return (struct nv20_vbuf_render *)render; +} + + +static const struct vertex_info * +nv20_vbuf_render_get_vertex_info( struct vbuf_render *render ) +{ +	struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); +	struct nv20_context *nv20 = nv20_render->nv20; + +	nv20_emit_hw_state(nv20); + +	return &nv20->vertex_info; +} + + +static void * +nv20_vbuf_render_allocate_vertices( struct vbuf_render *render, +		ushort vertex_size, +		ushort nr_vertices ) +{ +	struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); +	struct nv20_context *nv20 = nv20_render->nv20; +	struct pipe_winsys *winsys = nv20->pipe.winsys; +	size_t size = (size_t)vertex_size * (size_t)nr_vertices; + +	assert(!nv20_render->buffer); +	nv20_render->buffer = winsys->buffer_create(winsys, 64, PIPE_BUFFER_USAGE_VERTEX, size); + +	nv20->dirty |= NV20_NEW_VTXARRAYS; + +	return winsys->buffer_map(winsys,  +			nv20_render->buffer,  +			PIPE_BUFFER_USAGE_CPU_WRITE); +} + + +static void  +nv20_vbuf_render_set_primitive( struct vbuf_render *render,  +		unsigned prim ) +{ +	struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); +	nv20_render->hwprim = prim + 1; +} + + +static void  +nv20_vbuf_render_draw( struct vbuf_render *render, +		const ushort *indices, +		uint nr_indices) +{ +	struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); +	struct nv20_context *nv20 = nv20_render->nv20; +	int push, i; + +	nv20_emit_hw_state(nv20); + +	BEGIN_RING(kelvin, NV10TCL_VERTEX_ARRAY_OFFSET_POS, 1); +	OUT_RELOCl(nv20_render->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); + +	BEGIN_RING(kelvin, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); +	OUT_RING(nv20_render->hwprim); + +	if (nr_indices & 1) { +		BEGIN_RING(kelvin, 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(kelvin, 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(kelvin, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); +	OUT_RING  (0); +} + + +static void +nv20_vbuf_render_release_vertices( struct vbuf_render *render, +		void *vertices,  +		unsigned vertex_size, +		unsigned vertices_used ) +{ +	struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); +	struct nv20_context *nv20 = nv20_render->nv20; +	struct pipe_winsys *winsys = nv20->pipe.winsys; +	struct pipe_screen *pscreen = &nv20->screen->pipe; + +	assert(nv20_render->buffer); +	winsys->buffer_unmap(winsys, nv20_render->buffer); +	pipe_buffer_reference(pscreen, &nv20_render->buffer, NULL); +} + + +static void +nv20_vbuf_render_destroy( struct vbuf_render *render ) +{ +	struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); +	FREE(nv20_render); +} + + +/** + * Create a new primitive render. + */ +static struct vbuf_render * +nv20_vbuf_render_create( struct nv20_context *nv20 ) +{ +	struct nv20_vbuf_render *nv20_render = CALLOC_STRUCT(nv20_vbuf_render); + +	nv20_render->nv20 = nv20; + +	nv20_render->base.max_vertex_buffer_bytes = 16*1024; +	nv20_render->base.max_indices = 1024; +	nv20_render->base.get_vertex_info = nv20_vbuf_render_get_vertex_info; +	nv20_render->base.allocate_vertices = nv20_vbuf_render_allocate_vertices; +	nv20_render->base.set_primitive = nv20_vbuf_render_set_primitive; +	nv20_render->base.draw = nv20_vbuf_render_draw; +	nv20_render->base.release_vertices = nv20_vbuf_render_release_vertices; +	nv20_render->base.destroy = nv20_vbuf_render_destroy; + +	return &nv20_render->base; +} + + +/** + * Create a new primitive vbuf/render stage. + */ +struct draw_stage *nv20_draw_vbuf_stage( struct nv20_context *nv20 ) +{ +	struct vbuf_render *render; +	struct draw_stage *stage; + +	render = nv20_vbuf_render_create(nv20); +	if(!render) +		return NULL; + +	stage = draw_vbuf_stage( nv20->draw, render ); +	if(!stage) { +		render->destroy(render); +		return NULL; +	} + +	return stage; +} diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c new file mode 100644 index 0000000000..b7f5ea8512 --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_screen.c @@ -0,0 +1,208 @@ +#include "pipe/p_screen.h" + +#include "nv20_context.h" +#include "nv20_screen.h" + +static const char * +nv20_screen_get_name(struct pipe_screen *screen) +{ +	struct nv20_screen *nv20screen = nv20_screen(screen); +	struct nouveau_device *dev = nv20screen->nvws->channel->device; +	static char buffer[128]; + +	snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); +	return buffer; +} + +static const char * +nv20_screen_get_vendor(struct pipe_screen *screen) +{ +	return "nouveau"; +} + +static int +nv20_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 NOUVEAU_CAP_HW_VTXBUF: +	case NOUVEAU_CAP_HW_IDXBUF: +		return 0; +	default: +		NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); +		return 0; +	} +} + +static float +nv20_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 +nv20_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:  +		case PIPE_FORMAT_Z24S8_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 * +nv20_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, +		 unsigned flags ) +{ +	struct pipe_winsys *ws = screen->winsys; +	void *map; + +	map = ws->buffer_map(ws, surface->buffer, flags); +	if (!map) +		return NULL; + +	return map + surface->offset; +} + +static void +nv20_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) +{ +	struct pipe_winsys *ws = screen->winsys; + +	ws->buffer_unmap(ws, surface->buffer); +} + +static void +nv20_screen_destroy(struct pipe_screen *pscreen) +{ +	struct nv20_screen *screen = nv20_screen(pscreen); +	struct nouveau_winsys *nvws = screen->nvws; + +	nvws->notifier_free(&screen->sync); +	nvws->grobj_free(&screen->kelvin); + +	FREE(pscreen); +} + +struct pipe_screen * +nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +{ +	struct nv20_screen *screen = CALLOC_STRUCT(nv20_screen); +	unsigned celsius_class; +	unsigned chipset = nvws->channel->device->chipset; +	int ret; + +	if (!screen) +		return NULL; +	screen->nvws = nvws; + +	/* 3D object */ +	if (chipset>=0x20) +		celsius_class=NV11TCL; +	else if (chipset>=0x17) +		celsius_class=NV17TCL; +	else if (chipset>=0x11) +		celsius_class=NV11TCL; +	else +		celsius_class=NV10TCL; + +	if (!celsius_class) { +		NOUVEAU_ERR("Unknown nv1x chipset: nv%02x\n", chipset); +		return NULL; +	} + +	ret = nvws->grobj_alloc(nvws, celsius_class, &screen->kelvin); +	if (ret) { +		NOUVEAU_ERR("Error creating 3D object: %d\n", ret); +		return FALSE; +	} + +	/* Notifier for sync purposes */ +	ret = nvws->notifier_alloc(nvws, 1, &screen->sync); +	if (ret) { +		NOUVEAU_ERR("Error creating notifier object: %d\n", ret); +		nv20_screen_destroy(&screen->pipe); +		return NULL; +	} + +	screen->pipe.winsys = ws; +	screen->pipe.destroy = nv20_screen_destroy; + +	screen->pipe.get_name = nv20_screen_get_name; +	screen->pipe.get_vendor = nv20_screen_get_vendor; +	screen->pipe.get_param = nv20_screen_get_param; +	screen->pipe.get_paramf = nv20_screen_get_paramf; + +	screen->pipe.is_format_supported = nv20_screen_is_format_supported; + +	screen->pipe.surface_map = nv20_surface_map; +	screen->pipe.surface_unmap = nv20_surface_unmap; + +	nv20_screen_init_miptree_functions(&screen->pipe); + +	return &screen->pipe; +} + diff --git a/src/gallium/drivers/nv20/nv20_screen.h b/src/gallium/drivers/nv20/nv20_screen.h new file mode 100644 index 0000000000..8f2f2e341d --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_screen.h @@ -0,0 +1,22 @@ +#ifndef __NV20_SCREEN_H__ +#define __NV20_SCREEN_H__ + +#include "pipe/p_screen.h" + +struct nv20_screen { +	struct pipe_screen pipe; + +	struct nouveau_winsys *nvws; + +	/* HW graphics objects */ +	struct nouveau_grobj *kelvin; +	struct nouveau_notifier *sync; +}; + +static INLINE struct nv20_screen * +nv20_screen(struct pipe_screen *screen) +{ +	return (struct nv20_screen *)screen; +} + +#endif diff --git a/src/gallium/drivers/nv20/nv20_state.c b/src/gallium/drivers/nv20/nv20_state.c new file mode 100644 index 0000000000..c3b87230b7 --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_state.c @@ -0,0 +1,588 @@ +#include "draw/draw_context.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_shader_tokens.h" + +#include "tgsi/tgsi_parse.h" + +#include "nv20_context.h" +#include "nv20_state.h" + +static void * +nv20_blend_state_create(struct pipe_context *pipe, +			const struct pipe_blend_state *cso) +{ +	struct nv20_blend_state *cb; + +	cb = MALLOC(sizeof(struct nv20_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 +nv20_blend_state_bind(struct pipe_context *pipe, void *blend) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	nv20->blend = (struct nv20_blend_state*)blend; + +	nv20->dirty |= NV20_NEW_BLEND; +} + +static void +nv20_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 * +nv20_sampler_state_create(struct pipe_context *pipe, +			  const struct pipe_sampler_state *cso) +{ +	struct nv20_sampler_state *ps; +	uint32_t filter = 0; + +	ps = MALLOC(sizeof(struct nv20_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 +nv20_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ +	struct nv20_context *nv20 = nv20_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		nv20->tex_sampler[unit] = sampler[unit]; +		nv20->dirty_samplers |= (1 << unit); +	} +} + +static void +nv20_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + +static void +nv20_set_sampler_texture(struct pipe_context *pipe, unsigned nr, +			 struct pipe_texture **miptree) +{ +	struct nv20_context *nv20 = nv20_context(pipe); +	unsigned unit; + +	for (unit = 0; unit < nr; unit++) { +		nv20->tex_miptree[unit] = (struct nv20_miptree *)miptree[unit]; +		nv20->dirty_samplers |= (1 << unit); +	} +} + +static void * +nv20_rasterizer_state_create(struct pipe_context *pipe, +			     const struct pipe_rasterizer_state *cso) +{ +	struct nv20_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 nv20_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 +nv20_rasterizer_state_bind(struct pipe_context *pipe, void *rast) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	nv20->rast = (struct nv20_rasterizer_state*)rast; + +	draw_set_rasterizer_state(nv20->draw, (nv20->rast ? nv20->rast->templ : NULL)); + +	nv20->dirty |= NV20_NEW_RAST; +} + +static void +nv20_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + +static void * +nv20_depth_stencil_alpha_state_create(struct pipe_context *pipe, +			const struct pipe_depth_stencil_alpha_state *cso) +{ +	struct nv20_depth_stencil_alpha_state *hw; + +	hw = MALLOC(sizeof(struct nv20_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].write_mask; +	hw->stencil.func = nvgl_comparison_op(cso->stencil[0].func); +	hw->stencil.ref	= cso->stencil[0].ref_value; +	hw->stencil.vmask = cso->stencil[0].value_mask; +	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); + +	return (void *)hw; +} + +static void +nv20_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *dsa) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	nv20->dsa = (struct nv20_depth_stencil_alpha_state*)dsa; + +	nv20->dirty |= NV20_NEW_DSA; +} + +static void +nv20_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	FREE(hwcso); +} + +static void * +nv20_vp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *templ) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	return draw_create_vertex_shader(nv20->draw, templ); +} + +static void +nv20_vp_state_bind(struct pipe_context *pipe, void *shader) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	draw_bind_vertex_shader(nv20->draw, (struct draw_vertex_shader *) shader); + +	nv20->dirty |= NV20_NEW_VERTPROG; +} + +static void +nv20_vp_state_delete(struct pipe_context *pipe, void *shader) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	draw_delete_vertex_shader(nv20->draw, (struct draw_vertex_shader *) shader); +} + +static void * +nv20_fp_state_create(struct pipe_context *pipe, +		     const struct pipe_shader_state *cso) +{ +	struct nv20_fragment_program *fp; + +	fp = CALLOC(1, sizeof(struct nv20_fragment_program)); +	fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); +	 +	tgsi_scan_shader(cso->tokens, &fp->info); + +	return (void *)fp; +} + +static void +nv20_fp_state_bind(struct pipe_context *pipe, void *hwcso) +{ +	struct nv20_context *nv20 = nv20_context(pipe); +	struct nv20_fragment_program *fp = hwcso; + +	nv20->fragprog.current = fp; +	nv20->dirty |= NV20_NEW_FRAGPROG; +} + +static void +nv20_fp_state_delete(struct pipe_context *pipe, void *hwcso) +{ +	struct nv20_context *nv20 = nv20_context(pipe); +	struct nv20_fragment_program *fp = hwcso; + +	nv20_fragprog_destroy(nv20, fp); +	FREE((void*)fp->pipe.tokens); +	FREE(fp); +} + +static void +nv20_set_blend_color(struct pipe_context *pipe, +		     const struct pipe_blend_color *bcol) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	nv20->blend_color = (struct pipe_blend_color*)bcol; + +	nv20->dirty |= NV20_NEW_BLENDCOL; +} + +static void +nv20_set_clip_state(struct pipe_context *pipe, +		    const struct pipe_clip_state *clip) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	draw_set_clip_state(nv20->draw, clip); +} + +static void +nv20_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, +			 const struct pipe_constant_buffer *buf ) +{ +	struct nv20_context *nv20 = nv20_context(pipe); +	struct pipe_winsys *ws = pipe->winsys; + +	assert(shader < PIPE_SHADER_TYPES); +	assert(index == 0); + +	if (buf) { +		void *mapped; +		if (buf->size && (mapped = ws->buffer_map(ws, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ))) +		{ +			memcpy(nv20->constbuf[shader], mapped, buf->size); +			nv20->constbuf_nr[shader] = +				buf->size / (4 * sizeof(float)); +			ws->buffer_unmap(ws, buf->buffer); +		} +	} +} + +static void +nv20_set_framebuffer_state(struct pipe_context *pipe, +			   const struct pipe_framebuffer_state *fb) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	nv20->framebuffer = (struct pipe_framebuffer_state*)fb; + +	nv20->dirty |= NV20_NEW_FRAMEBUFFER; +} + +static void +nv20_set_polygon_stipple(struct pipe_context *pipe, +			 const struct pipe_poly_stipple *stipple) +{ +	NOUVEAU_ERR("line stipple hahaha\n"); +} + +static void +nv20_set_scissor_state(struct pipe_context *pipe, +		       const struct pipe_scissor_state *s) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	nv20->scissor = (struct pipe_scissor_state*)s; + +	nv20->dirty |= NV20_NEW_SCISSOR; +} + +static void +nv20_set_viewport_state(struct pipe_context *pipe, +			const struct pipe_viewport_state *vpt) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	nv20->viewport = (struct pipe_viewport_state*)vpt; + +	draw_set_viewport_state(nv20->draw, nv20->viewport); + +	nv20->dirty |= NV20_NEW_VIEWPORT; +} + +static void +nv20_set_vertex_buffers(struct pipe_context *pipe, unsigned count, +			const struct pipe_vertex_buffer *vb) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	memcpy(nv20->vtxbuf, vb, sizeof(*vb) * count); +	nv20->dirty |= NV20_NEW_VTXARRAYS; + +	draw_set_vertex_buffers(nv20->draw, count, vb); +} + +static void +nv20_set_vertex_elements(struct pipe_context *pipe, unsigned count, +			 const struct pipe_vertex_element *ve) +{ +	struct nv20_context *nv20 = nv20_context(pipe); + +	memcpy(nv20->vtxelt, ve, sizeof(*ve) * count); +	nv20->dirty |= NV20_NEW_VTXARRAYS; + +	draw_set_vertex_elements(nv20->draw, count, ve); +} + +void +nv20_init_state_functions(struct nv20_context *nv20) +{ +	nv20->pipe.create_blend_state = nv20_blend_state_create; +	nv20->pipe.bind_blend_state = nv20_blend_state_bind; +	nv20->pipe.delete_blend_state = nv20_blend_state_delete; + +	nv20->pipe.create_sampler_state = nv20_sampler_state_create; +	nv20->pipe.bind_sampler_states = nv20_sampler_state_bind; +	nv20->pipe.delete_sampler_state = nv20_sampler_state_delete; +	nv20->pipe.set_sampler_textures = nv20_set_sampler_texture; + +	nv20->pipe.create_rasterizer_state = nv20_rasterizer_state_create; +	nv20->pipe.bind_rasterizer_state = nv20_rasterizer_state_bind; +	nv20->pipe.delete_rasterizer_state = nv20_rasterizer_state_delete; + +	nv20->pipe.create_depth_stencil_alpha_state = +		nv20_depth_stencil_alpha_state_create; +	nv20->pipe.bind_depth_stencil_alpha_state = +		nv20_depth_stencil_alpha_state_bind; +	nv20->pipe.delete_depth_stencil_alpha_state = +		nv20_depth_stencil_alpha_state_delete; + +	nv20->pipe.create_vs_state = nv20_vp_state_create; +	nv20->pipe.bind_vs_state = nv20_vp_state_bind; +	nv20->pipe.delete_vs_state = nv20_vp_state_delete; + +	nv20->pipe.create_fs_state = nv20_fp_state_create; +	nv20->pipe.bind_fs_state = nv20_fp_state_bind; +	nv20->pipe.delete_fs_state = nv20_fp_state_delete; + +	nv20->pipe.set_blend_color = nv20_set_blend_color; +	nv20->pipe.set_clip_state = nv20_set_clip_state; +	nv20->pipe.set_constant_buffer = nv20_set_constant_buffer; +	nv20->pipe.set_framebuffer_state = nv20_set_framebuffer_state; +	nv20->pipe.set_polygon_stipple = nv20_set_polygon_stipple; +	nv20->pipe.set_scissor_state = nv20_set_scissor_state; +	nv20->pipe.set_viewport_state = nv20_set_viewport_state; + +	nv20->pipe.set_vertex_buffers = nv20_set_vertex_buffers; +	nv20->pipe.set_vertex_elements = nv20_set_vertex_elements; +} + diff --git a/src/gallium/drivers/nv20/nv20_state.h b/src/gallium/drivers/nv20/nv20_state.h new file mode 100644 index 0000000000..34f402fdcb --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_state.h @@ -0,0 +1,139 @@ +#ifndef __NV20_STATE_H__ +#define __NV20_STATE_H__ + +#include "pipe/p_state.h" +#include "tgsi/tgsi_scan.h" + +struct nv20_blend_state { +	uint32_t b_enable; +	uint32_t b_srcfunc; +	uint32_t b_dstfunc; + +	uint32_t c_mask; + +	uint32_t d_enable; +}; + +struct nv20_sampler_state { +	uint32_t wrap; +	uint32_t en; +	uint32_t filt; +	uint32_t bcol; +}; + +struct nv20_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 nv20_vertex_program_exec { +	uint32_t data[4]; +	boolean has_branch_offset; +	int const_index; +}; + +struct nv20_vertex_program_data { +	int index; /* immediates == -1 */ +	float value[4]; +}; + +struct nv20_vertex_program { +	const struct pipe_shader_state *pipe; + +	boolean translated; +	struct nv20_vertex_program_exec *insns; +	unsigned nr_insns; +	struct nv20_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 nv20_fragment_program_data { +	unsigned offset; +	unsigned index; +}; + +struct nv20_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 nv20_fragment_program_data *consts; +	unsigned nr_consts; + +	struct pipe_buffer *buffer; + +	uint32_t fp_control; +	uint32_t fp_reg_control; +}; + + +struct nv20_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 nv20_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/nv20/nv20_state_emit.c b/src/gallium/drivers/nv20/nv20_state_emit.c new file mode 100644 index 0000000000..e8dd22925c --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_state_emit.c @@ -0,0 +1,303 @@ +#include "nv20_context.h" +#include "nv20_state.h" + +static void nv20_state_emit_blend(struct nv20_context* nv20) +{ +	struct nv20_blend_state *b = nv20->blend; + +	BEGIN_RING(kelvin, NV10TCL_DITHER_ENABLE, 1); +	OUT_RING  (b->d_enable); + +	BEGIN_RING(kelvin, NV10TCL_BLEND_FUNC_ENABLE, 3); +	OUT_RING  (b->b_enable); +	OUT_RING  (b->b_srcfunc); +	OUT_RING  (b->b_dstfunc); + +	BEGIN_RING(kelvin, NV10TCL_COLOR_MASK, 1); +	OUT_RING  (b->c_mask); +} + +static void nv20_state_emit_blend_color(struct nv20_context* nv20) +{ +	struct pipe_blend_color *c = nv20->blend_color; + +	BEGIN_RING(kelvin, 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 nv20_state_emit_rast(struct nv20_context* nv20) +{ +	struct nv20_rasterizer_state *r = nv20->rast; + +	BEGIN_RING(kelvin, NV10TCL_SHADE_MODEL, 2); +	OUT_RING  (r->shade_model); +	OUT_RING  (r->line_width); + + +	BEGIN_RING(kelvin, NV10TCL_POINT_SIZE, 1); +	OUT_RING  (r->point_size); + +	BEGIN_RING(kelvin, NV10TCL_POLYGON_MODE_FRONT, 2); +	OUT_RING  (r->poly_mode_front); +	OUT_RING  (r->poly_mode_back); + + +	BEGIN_RING(kelvin, NV10TCL_CULL_FACE, 2); +	OUT_RING  (r->cull_face); +	OUT_RING  (r->front_face); + +	BEGIN_RING(kelvin, NV10TCL_LINE_SMOOTH_ENABLE, 2); +	OUT_RING  (r->line_smooth_en); +	OUT_RING  (r->poly_smooth_en); + +	BEGIN_RING(kelvin, NV10TCL_CULL_FACE_ENABLE, 1); +	OUT_RING  (r->cull_face_en); +} + +static void nv20_state_emit_dsa(struct nv20_context* nv20) +{ +	struct nv20_depth_stencil_alpha_state *d = nv20->dsa; + +	BEGIN_RING(kelvin, NV10TCL_DEPTH_FUNC, 1); +	OUT_RING (d->depth.func); + +	BEGIN_RING(kelvin, NV10TCL_DEPTH_WRITE_ENABLE, 1); +	OUT_RING (d->depth.write_enable); + +	BEGIN_RING(kelvin, NV10TCL_DEPTH_TEST_ENABLE, 1); +	OUT_RING (d->depth.test_enable); + +#if 0 +	BEGIN_RING(kelvin, NV10TCL_STENCIL_ENABLE, 1); +	OUT_RING (d->stencil.enable); +	BEGIN_RING(kelvin, NV10TCL_STENCIL_MASK, 7); +	OUT_RINGp ((uint32_t *)&(d->stencil.wmask), 7); +#endif + +	BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_ENABLE, 1); +	OUT_RING (d->alpha.enabled); + +	BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_FUNC, 1); +	OUT_RING (d->alpha.func); + +	BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_REF, 1); +	OUT_RING (d->alpha.ref); +} + +static void nv20_state_emit_viewport(struct nv20_context* nv20) +{ +} + +static void nv20_state_emit_scissor(struct nv20_context* nv20) +{ +	// XXX this is so not working +/*	struct pipe_scissor_state *s = nv20->scissor; +	BEGIN_RING(kelvin, NV10TCL_SCISSOR_HORIZ, 2); +	OUT_RING  (((s->maxx - s->minx) << 16) | s->minx); +	OUT_RING  (((s->maxy - s->miny) << 16) | s->miny);*/ +} + +static void nv20_state_emit_framebuffer(struct nv20_context* nv20) +{ +	struct pipe_framebuffer_state* fb = nv20->framebuffer; +	struct pipe_surface *rt, *zeta = NULL; +	uint32_t rt_format, w, h; +	int colour_format = 0, zeta_format = 0; + +	w = fb->cbufs[0]->width; +	h = fb->cbufs[0]->height; +	colour_format = fb->cbufs[0]->format; +	rt = 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 = 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(kelvin, NV10TCL_RT_PITCH, 1); +		OUT_RING  (rt->stride | (zeta->stride << 16)); +	} else { +		BEGIN_RING(kelvin, NV10TCL_RT_PITCH, 1); +		OUT_RING  (rt->stride | (rt->stride << 16)); +	} + +	nv20->rt[0] = rt->buffer; + +	if (zeta_format) +	{ +		nv20->zeta = zeta->buffer; +	} + +	BEGIN_RING(kelvin, NV10TCL_RT_HORIZ, 3); +	OUT_RING  ((w << 16) | 0); +	OUT_RING  ((h << 16) | 0); +	OUT_RING  (rt_format); +	BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 2); +	OUT_RING  (((w - 1) << 16) | 0 | 0x08000800); +	OUT_RING  (((h - 1) << 16) | 0 | 0x08000800); +} + +static void nv20_vertex_layout(struct nv20_context *nv20) +{ +	struct nv20_fragment_program *fp = nv20->fragprog.current; +	uint32_t src = 0; +	int i; +	struct vertex_info *vinfo = &nv20->vertex_info; + +	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 +nv20_emit_hw_state(struct nv20_context *nv20) +{ +	int i; + +	if (nv20->dirty & NV20_NEW_VERTPROG) { +		//nv20_vertprog_bind(nv20, nv20->vertprog.current); +		nv20->dirty &= ~NV20_NEW_VERTPROG; +	} + +	if (nv20->dirty & NV20_NEW_FRAGPROG) { +		nv20_fragprog_bind(nv20, nv20->fragprog.current); +		/*XXX: clear NV20_NEW_FRAGPROG if no new program uploaded */ +		nv20->dirty_samplers |= (1<<10); +		nv20->dirty_samplers = 0; +	} + +	if (nv20->dirty_samplers || (nv20->dirty & NV20_NEW_FRAGPROG)) { +		nv20_fragtex_bind(nv20); +		nv20->dirty &= ~NV20_NEW_FRAGPROG; +	} + +	if (nv20->dirty & NV20_NEW_VTXARRAYS) { +		nv20->dirty &= ~NV20_NEW_VTXARRAYS; +		nv20_vertex_layout(nv20); +		nv20_vtxbuf_bind(nv20); +	} + +	if (nv20->dirty & NV20_NEW_BLEND) { +		nv20->dirty &= ~NV20_NEW_BLEND; +		nv20_state_emit_blend(nv20); +	} + +	if (nv20->dirty & NV20_NEW_BLENDCOL) { +		nv20->dirty &= ~NV20_NEW_BLENDCOL; +		nv20_state_emit_blend_color(nv20); +	} + +	if (nv20->dirty & NV20_NEW_RAST) { +		nv20->dirty &= ~NV20_NEW_RAST; +		nv20_state_emit_rast(nv20); +	} + +	if (nv20->dirty & NV20_NEW_DSA) { +		nv20->dirty &= ~NV20_NEW_DSA; +		nv20_state_emit_dsa(nv20); +	} + + 	if (nv20->dirty & NV20_NEW_VIEWPORT) { +		nv20->dirty &= ~NV20_NEW_VIEWPORT; +		nv20_state_emit_viewport(nv20); +	} + + 	if (nv20->dirty & NV20_NEW_SCISSOR) { +		nv20->dirty &= ~NV20_NEW_SCISSOR; +		nv20_state_emit_scissor(nv20); +	} + + 	if (nv20->dirty & NV20_NEW_FRAMEBUFFER) { +		nv20->dirty &= ~NV20_NEW_FRAMEBUFFER; +		nv20_state_emit_framebuffer(nv20); +	} + +	/* 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 nv20_vbo.c +	 */ + +	/* Render target */ +// XXX figre out who's who for NV10TCL_DMA_* and fill accordingly +//	BEGIN_RING(kelvin, NV10TCL_DMA_COLOR0, 1); +//	OUT_RELOCo(nv20->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	BEGIN_RING(kelvin, NV10TCL_COLOR_OFFSET, 1); +	OUT_RELOCl(nv20->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	if (nv20->zeta) { +// XXX +//		BEGIN_RING(kelvin, NV10TCL_DMA_ZETA, 1); +//		OUT_RELOCo(nv20->zeta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +		BEGIN_RING(kelvin, NV10TCL_ZETA_OFFSET, 1); +		OUT_RELOCl(nv20->zeta, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +		/* XXX for when we allocate LMA on nv17 */ +/*		BEGIN_RING(kelvin, NV10TCL_LMA_DEPTH_BUFFER_OFFSET, 1); +		OUT_RELOCl(nv20->zeta + lma_offset);*/ +	} + +	/* Vertex buffer */ +	BEGIN_RING(kelvin, NV10TCL_DMA_VTXBUF0, 1); +	OUT_RELOCo(nv20->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	BEGIN_RING(kelvin, NV10TCL_COLOR_OFFSET, 1); +	OUT_RELOCl(nv20->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	/* Texture images */ +	for (i = 0; i < 2; i++) { +		if (!(nv20->fp_samplers & (1 << i))) +			continue; +		BEGIN_RING(kelvin, NV10TCL_TX_OFFSET(i), 1); +		OUT_RELOCl(nv20->tex[i].buffer, 0, NOUVEAU_BO_VRAM | +			   NOUVEAU_BO_GART | NOUVEAU_BO_RD); +		BEGIN_RING(kelvin, NV10TCL_TX_FORMAT(i), 1); +		OUT_RELOCd(nv20->tex[i].buffer, nv20->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/nv20/nv20_surface.c b/src/gallium/drivers/nv20/nv20_surface.c new file mode 100644 index 0000000000..41b6d6ad35 --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_surface.c @@ -0,0 +1,64 @@ + +/************************************************************************** + *  + * 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 "nv20_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_winsys.h" +#include "pipe/p_inlines.h" +#include "util/u_tile.h" + +static void +nv20_surface_copy(struct pipe_context *pipe, unsigned do_flip, +		  struct pipe_surface *dest, unsigned destx, unsigned desty, +		  struct pipe_surface *src, unsigned srcx, unsigned srcy, +		  unsigned width, unsigned height) +{ +	struct nv20_context *nv20 = nv20_context(pipe); +	struct nouveau_winsys *nvws = nv20->nvws; + +	nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, +			   width, height); +} + +static void +nv20_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, +		  unsigned destx, unsigned desty, unsigned width, +		  unsigned height, unsigned value) +{ +	struct nv20_context *nv20 = nv20_context(pipe); +	struct nouveau_winsys *nvws = nv20->nvws; + +	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +} + +void +nv20_init_surface_functions(struct nv20_context *nv20) +{ +	nv20->pipe.surface_copy = nv20_surface_copy; +	nv20->pipe.surface_fill = nv20_surface_fill; +} diff --git a/src/gallium/drivers/nv20/nv20_vbo.c b/src/gallium/drivers/nv20/nv20_vbo.c new file mode 100644 index 0000000000..4edc4efebd --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_vbo.c @@ -0,0 +1,77 @@ +#include "draw/draw_context.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" + +#include "nv20_context.h" +#include "nv20_state.h" + +#include "nouveau/nouveau_channel.h" +#include "nouveau/nouveau_pushbuf.h" + +boolean nv20_draw_elements( struct pipe_context *pipe, +                    struct pipe_buffer *indexBuffer, +                    unsigned indexSize, +                    unsigned prim, unsigned start, unsigned count) +{ +	struct nv20_context *nv20 = nv20_context( pipe ); +	struct draw_context *draw = nv20->draw; +	unsigned i; + +	nv20_emit_hw_state(nv20); + +	/* +	 * Map vertex buffers +	 */ +	for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { +		if (nv20->vtxbuf[i].buffer) { +			void *buf +				= pipe->winsys->buffer_map(pipe->winsys, +						nv20->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->winsys->buffer_map(pipe->winsys, 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, +					nv20->constbuf[PIPE_SHADER_VERTEX], +					nv20->constbuf_nr[PIPE_SHADER_VERTEX]); + +	/* draw! */ +	draw_arrays(nv20->draw, prim, start, count); + +	/* +	 * unmap vertex/index buffers +	 */ +	for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { +		if (nv20->vtxbuf[i].buffer) { +			pipe->winsys->buffer_unmap(pipe->winsys, nv20->vtxbuf[i].buffer); +			draw_set_mapped_vertex_buffer(draw, i, NULL); +		} +	} +	if (indexBuffer) { +		pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer); +		draw_set_mapped_element_buffer(draw, 0, NULL); +	} + +	return TRUE; +} + +boolean nv20_draw_arrays( struct pipe_context *pipe, +				 unsigned prim, unsigned start, unsigned count) +{ +	return nv20_draw_elements(pipe, NULL, 0, prim, start, count); +} + + + diff --git a/src/gallium/drivers/nv20/nv20_vertprog.c b/src/gallium/drivers/nv20/nv20_vertprog.c new file mode 100644 index 0000000000..a885fcd7a5 --- /dev/null +++ b/src/gallium/drivers/nv20/nv20_vertprog.c @@ -0,0 +1,838 @@ +#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_dump.h" + +#include "nv20_context.h" +#include "nv20_state.h" + +/* TODO (at least...): + *  1. Indexed consts  + ARL + *  2. Arb. swz/negation + *  3. NV_vp11, NV_vp2, NV_vp3 features + *       - extra arith opcodes + *       - branching + *       - texture sampling + *       - indexed attribs + *       - indexed results + *  4. bugs + */ + +#define SWZ_X 0 +#define SWZ_Y 1 +#define SWZ_Z 2 +#define SWZ_W 3 +#define MASK_X 8 +#define MASK_Y 4 +#define MASK_Z 2 +#define MASK_W 1 +#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) +#define DEF_SCALE 0 +#define DEF_CTEST 0 +#include "nv20_shader.h" + +#define swz(s,x,y,z,w) nv20_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) +#define neg(s) nv20_sr_neg((s)) +#define abs(s) nv20_sr_abs((s)) + +struct nv20_vpc { +	struct nv20_vertex_program *vp; + +	struct nv20_vertex_program_exec *vpi; + +	unsigned output_map[PIPE_MAX_SHADER_OUTPUTS]; + +	int high_temp; +	int temp_temp_count; + +	struct nv20_sreg *imm; +	unsigned nr_imm; +}; + +static struct nv20_sreg +temp(struct nv20_vpc *vpc) +{ +	int idx; + +	idx  = vpc->temp_temp_count++; +	idx += vpc->high_temp + 1; +	return nv20_sr(NV30SR_TEMP, idx); +} + +static struct nv20_sreg +constant(struct nv20_vpc *vpc, int pipe, float x, float y, float z, float w) +{ +	struct nv20_vertex_program *vp = vpc->vp; +	struct nv20_vertex_program_data *vpd; +	int idx; + +	if (pipe >= 0) { +		for (idx = 0; idx < vp->nr_consts; idx++) { +			if (vp->consts[idx].index == pipe) +				return nv20_sr(NV30SR_CONST, idx); +		} +	} + +	idx = vp->nr_consts++; +	vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts); +	vpd = &vp->consts[idx]; + +	vpd->index = pipe; +	vpd->value[0] = x; +	vpd->value[1] = y; +	vpd->value[2] = z; +	vpd->value[3] = w; +	return nv20_sr(NV30SR_CONST, idx); +} + +#define arith(cc,s,o,d,m,s0,s1,s2) \ +	nv20_vp_arith((cc), (s), NV30_VP_INST_##o, (d), (m), (s0), (s1), (s2)) + +static void +emit_src(struct nv20_vpc *vpc, uint32_t *hw, int pos, struct nv20_sreg src) +{ +	struct nv20_vertex_program *vp = vpc->vp; +	uint32_t sr = 0; + +	switch (src.type) { +	case NV30SR_TEMP: +		sr |= (NV30_VP_SRC_REG_TYPE_TEMP << NV30_VP_SRC_REG_TYPE_SHIFT); +		sr |= (src.index << NV30_VP_SRC_TEMP_SRC_SHIFT); +		break; +	case NV30SR_INPUT: +		sr |= (NV30_VP_SRC_REG_TYPE_INPUT << +		       NV30_VP_SRC_REG_TYPE_SHIFT); +		vp->ir |= (1 << src.index); +		hw[1] |= (src.index << NV30_VP_INST_INPUT_SRC_SHIFT); +		break; +	case NV30SR_CONST: +		sr |= (NV30_VP_SRC_REG_TYPE_CONST << +		       NV30_VP_SRC_REG_TYPE_SHIFT); +		assert(vpc->vpi->const_index == -1 || +		       vpc->vpi->const_index == src.index); +		vpc->vpi->const_index = src.index; +		break; +	case NV30SR_NONE: +		sr |= (NV30_VP_SRC_REG_TYPE_INPUT << +		       NV30_VP_SRC_REG_TYPE_SHIFT); +		break; +	default: +		assert(0); +	} + +	if (src.negate) +		sr |= NV30_VP_SRC_NEGATE; + +	if (src.abs) +		hw[0] |= (1 << (21 + pos)); + +	sr |= ((src.swz[0] << NV30_VP_SRC_SWZ_X_SHIFT) | +	       (src.swz[1] << NV30_VP_SRC_SWZ_Y_SHIFT) | +	       (src.swz[2] << NV30_VP_SRC_SWZ_Z_SHIFT) | +	       (src.swz[3] << NV30_VP_SRC_SWZ_W_SHIFT)); + +/* + * |VVV| + * d�.�b + *  \u/ + * + */ + +	switch (pos) { +	case 0: +		hw[1] |= ((sr & NV30_VP_SRC0_HIGH_MASK) >> +			  NV30_VP_SRC0_HIGH_SHIFT) << NV30_VP_INST_SRC0H_SHIFT; +		hw[2] |= (sr & NV30_VP_SRC0_LOW_MASK) << +			  NV30_VP_INST_SRC0L_SHIFT; +		break; +	case 1: +		hw[2] |= sr << NV30_VP_INST_SRC1_SHIFT; +		break; +	case 2: +		hw[2] |= ((sr & NV30_VP_SRC2_HIGH_MASK) >> +			  NV30_VP_SRC2_HIGH_SHIFT) << NV30_VP_INST_SRC2H_SHIFT; +		hw[3] |= (sr & NV30_VP_SRC2_LOW_MASK) << +			  NV30_VP_INST_SRC2L_SHIFT; +		break; +	default: +		assert(0); +	} +} + +static void +emit_dst(struct nv20_vpc *vpc, uint32_t *hw, int slot, struct nv20_sreg dst) +{ +	struct nv20_vertex_program *vp = vpc->vp; + +	switch (dst.type) { +	case NV30SR_TEMP: +		hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT); +		break; +	case NV30SR_OUTPUT: +		switch (dst.index) { +		case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; +		case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; +		case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; +		case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; +		case NV30_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break; +		case NV30_VP_INST_DEST_PSZ  : vp->or |= (1 << 5); break; +		case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; +		case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; +		case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; +		case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; +		case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; +		case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; +		case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; +		case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; +		default: +			break; +		} + +		hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT); +		hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); + +		/*XXX: no way this is entirely correct, someone needs to +		 *     figure out what exactly it is. +		 */ +		hw[3] |= 0x800; +		break; +	default: +		assert(0); +	} +} + +static void +nv20_vp_arith(struct nv20_vpc *vpc, int slot, int op, +	      struct nv20_sreg dst, int mask, +	      struct nv20_sreg s0, struct nv20_sreg s1, +	      struct nv20_sreg s2) +{ +	struct nv20_vertex_program *vp = vpc->vp; +	uint32_t *hw; + +	vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi)); +	vpc->vpi = &vp->insns[vp->nr_insns - 1]; +	memset(vpc->vpi, 0, sizeof(*vpc->vpi)); +	vpc->vpi->const_index = -1; + +	hw = vpc->vpi->data; + +	hw[0] |= (NV30_VP_INST_COND_TR << NV30_VP_INST_COND_SHIFT); +	hw[0] |= ((0 << NV30_VP_INST_COND_SWZ_X_SHIFT) | +		  (1 << NV30_VP_INST_COND_SWZ_Y_SHIFT) | +		  (2 << NV30_VP_INST_COND_SWZ_Z_SHIFT) | +		  (3 << NV30_VP_INST_COND_SWZ_W_SHIFT)); + +	hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT); +//	hw[3] |= NV30_VP_INST_SCA_DEST_TEMP_MASK; +//	hw[3] |= (mask << NV30_VP_INST_VEC_WRITEMASK_SHIFT); + +	if (dst.type == NV30SR_OUTPUT) { +		if (slot) +			hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT); +		else +			hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT); +	} else { +		if (slot) +			hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT); +		else +			hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT); +	} + +	emit_dst(vpc, hw, slot, dst); +	emit_src(vpc, hw, 0, s0); +	emit_src(vpc, hw, 1, s1); +	emit_src(vpc, hw, 2, s2); +} + +static INLINE struct nv20_sreg +tgsi_src(struct nv20_vpc *vpc, const struct tgsi_full_src_register *fsrc) { +	struct nv20_sreg src; + +	switch (fsrc->SrcRegister.File) { +	case TGSI_FILE_INPUT: +		src = nv20_sr(NV30SR_INPUT, fsrc->SrcRegister.Index); +		break; +	case TGSI_FILE_CONSTANT: +		src = constant(vpc, fsrc->SrcRegister.Index, 0, 0, 0, 0); +		break; +	case TGSI_FILE_IMMEDIATE: +		src = vpc->imm[fsrc->SrcRegister.Index]; +		break; +	case TGSI_FILE_TEMPORARY: +		if (vpc->high_temp < fsrc->SrcRegister.Index) +			vpc->high_temp = fsrc->SrcRegister.Index; +		src = nv20_sr(NV30SR_TEMP, fsrc->SrcRegister.Index); +		break; +	default: +		NOUVEAU_ERR("bad src file\n"); +		break; +	} + +	src.abs = fsrc->SrcRegisterExtMod.Absolute; +	src.negate = fsrc->SrcRegister.Negate; +	src.swz[0] = fsrc->SrcRegister.SwizzleX; +	src.swz[1] = fsrc->SrcRegister.SwizzleY; +	src.swz[2] = fsrc->SrcRegister.SwizzleZ; +	src.swz[3] = fsrc->SrcRegister.SwizzleW; +	return src; +} + +static INLINE struct nv20_sreg +tgsi_dst(struct nv20_vpc *vpc, const struct tgsi_full_dst_register *fdst) { +	struct nv20_sreg dst; + +	switch (fdst->DstRegister.File) { +	case TGSI_FILE_OUTPUT: +		dst = nv20_sr(NV30SR_OUTPUT, +			      vpc->output_map[fdst->DstRegister.Index]); + +		break; +	case TGSI_FILE_TEMPORARY: +		dst = nv20_sr(NV30SR_TEMP, fdst->DstRegister.Index); +		if (vpc->high_temp < dst.index) +			vpc->high_temp = dst.index; +		break; +	default: +		NOUVEAU_ERR("bad dst file\n"); +		break; +	} + +	return dst; +} + +static INLINE int +tgsi_mask(uint tgsi) +{ +	int mask = 0; + +	if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; +	if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; +	if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; +	if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; +	return mask; +} + +static boolean +nv20_vertprog_parse_instruction(struct nv20_vpc *vpc, +				const struct tgsi_full_instruction *finst) +{ +	struct nv20_sreg src[3], dst, tmp; +	struct nv20_sreg none = nv20_sr(NV30SR_NONE, 0); +	int mask; +	int ai = -1, ci = -1; +	int i; + +	if (finst->Instruction.Opcode == TGSI_OPCODE_END) +		return TRUE; + +	vpc->temp_temp_count = 0; +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; +		if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) { +			src[i] = tgsi_src(vpc, fsrc); +		} +	} + +	for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { +		const struct tgsi_full_src_register *fsrc; + +		fsrc = &finst->FullSrcRegisters[i]; +		switch (fsrc->SrcRegister.File) { +		case TGSI_FILE_INPUT: +			if (ai == -1 || ai == fsrc->SrcRegister.Index) { +				ai = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(vpc, fsrc); +			} else { +				src[i] = temp(vpc); +				arith(vpc, 0, OP_MOV, src[i], MASK_ALL, +				      tgsi_src(vpc, fsrc), none, none); +			} +			break; +		/*XXX: index comparison is broken now that consts come from +		 *     two different register files. +		 */ +		case TGSI_FILE_CONSTANT: +		case TGSI_FILE_IMMEDIATE: +			if (ci == -1 || ci == fsrc->SrcRegister.Index) { +				ci = fsrc->SrcRegister.Index; +				src[i] = tgsi_src(vpc, fsrc); +			} else { +				src[i] = temp(vpc); +				arith(vpc, 0, OP_MOV, src[i], MASK_ALL, +				      tgsi_src(vpc, fsrc), none, none); +			} +			break; +		case TGSI_FILE_TEMPORARY: +			/* handled above */ +			break; +		default: +			NOUVEAU_ERR("bad src file\n"); +			return FALSE; +		} +	} + +	dst  = tgsi_dst(vpc, &finst->FullDstRegisters[0]); +	mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask); + +	switch (finst->Instruction.Opcode) { +	case TGSI_OPCODE_ABS: +		arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none); +		break; +	case TGSI_OPCODE_ADD: +		arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]); +		break; +	case TGSI_OPCODE_ARL: +		arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_DP3: +		arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DP4: +		arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DPH: +		arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_DST: +		arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_EX2: +		arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_EXP: +		arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_FLR: +		arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_FRC: +		arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_LG2: +		arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_LIT: +		arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_LOG: +		arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_MAD: +		arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]); +		break; +	case TGSI_OPCODE_MAX: +		arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MIN: +		arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_MOV: +		arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none); +		break; +	case TGSI_OPCODE_MUL: +		arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_POW: +		tmp = temp(vpc); +		arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none, +		      swz(src[0], X, X, X, X)); +		arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X), +		      swz(src[1], X, X, X, X), none); +		arith(vpc, 1, OP_EX2, dst, mask, none, none, +		      swz(tmp, X, X, X, X)); +		break; +	case TGSI_OPCODE_RCP: +		arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_RET: +		break; +	case TGSI_OPCODE_RSQ: +		arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]); +		break; +	case TGSI_OPCODE_SGE: +		arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SGT: +		arith(vpc, 0, OP_SGT, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SLT: +		arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none); +		break; +	case TGSI_OPCODE_SUB: +		arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1])); +		break; +	case TGSI_OPCODE_XPD: +		tmp = temp(vpc); +		arith(vpc, 0, OP_MUL, tmp, mask, +		      swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); +		arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W), +		      swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), +		      neg(tmp)); +		break; +	default: +		NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); +		return FALSE; +	} + +	return TRUE; +} + +static boolean +nv20_vertprog_parse_decl_output(struct nv20_vpc *vpc, +				const struct tgsi_full_declaration *fdec) +{ +	int hw; + +	switch (fdec->Semantic.SemanticName) { +	case TGSI_SEMANTIC_POSITION: +		hw = NV30_VP_INST_DEST_POS; +		break; +	case TGSI_SEMANTIC_COLOR: +		if (fdec->Semantic.SemanticIndex == 0) { +			hw = NV30_VP_INST_DEST_COL0; +		} else +		if (fdec->Semantic.SemanticIndex == 1) { +			hw = NV30_VP_INST_DEST_COL1; +		} else { +			NOUVEAU_ERR("bad colour semantic index\n"); +			return FALSE; +		} +		break; +	case TGSI_SEMANTIC_BCOLOR: +		if (fdec->Semantic.SemanticIndex == 0) { +			hw = NV30_VP_INST_DEST_BFC0; +		} else +		if (fdec->Semantic.SemanticIndex == 1) { +			hw = NV30_VP_INST_DEST_BFC1; +		} else { +			NOUVEAU_ERR("bad bcolour semantic index\n"); +			return FALSE; +		} +		break; +	case TGSI_SEMANTIC_FOG: +		hw = NV30_VP_INST_DEST_FOGC; +		break; +	case TGSI_SEMANTIC_PSIZE: +		hw = NV30_VP_INST_DEST_PSZ; +		break; +	case TGSI_SEMANTIC_GENERIC: +		if (fdec->Semantic.SemanticIndex <= 7) { +			hw = NV30_VP_INST_DEST_TC(fdec->Semantic.SemanticIndex); +		} else { +			NOUVEAU_ERR("bad generic semantic index\n"); +			return FALSE; +		} +		break; +	default: +		NOUVEAU_ERR("bad output semantic\n"); +		return FALSE; +	} + +	vpc->output_map[fdec->DeclarationRange.First] = hw; +	return TRUE; +} + +static boolean +nv20_vertprog_prepare(struct nv20_vpc *vpc) +{ +	struct tgsi_parse_context p; +	int nr_imm = 0; + +	tgsi_parse_init(&p, vpc->vp->pipe.tokens); +	while (!tgsi_parse_end_of_tokens(&p)) { +		const union tgsi_full_token *tok = &p.FullToken; + +		tgsi_parse_token(&p); +		switch(tok->Token.Type) { +		case TGSI_TOKEN_TYPE_IMMEDIATE: +			nr_imm++; +			break; +		default: +			break; +		} +	} +	tgsi_parse_free(&p); + +	if (nr_imm) { +		vpc->imm = CALLOC(nr_imm, sizeof(struct nv20_sreg)); +		assert(vpc->imm); +	} + +	return TRUE; +} + +static void +nv20_vertprog_translate(struct nv20_context *nv20, +			struct nv20_vertex_program *vp) +{ +	struct tgsi_parse_context parse; +	struct nv20_vpc *vpc = NULL; + +	tgsi_dump(vp->pipe.tokens,0); + +	vpc = CALLOC(1, sizeof(struct nv20_vpc)); +	if (!vpc) +		return; +	vpc->vp = vp; +	vpc->high_temp = -1; + +	if (!nv20_vertprog_prepare(vpc)) { +		FREE(vpc); +		return; +	} + +	tgsi_parse_init(&parse, vp->pipe.tokens); + +	while (!tgsi_parse_end_of_tokens(&parse)) { +		tgsi_parse_token(&parse); + +		switch (parse.FullToken.Token.Type) { +		case TGSI_TOKEN_TYPE_DECLARATION: +		{ +			const struct tgsi_full_declaration *fdec; +			fdec = &parse.FullToken.FullDeclaration; +			switch (fdec->Declaration.File) { +			case TGSI_FILE_OUTPUT: +				if (!nv20_vertprog_parse_decl_output(vpc, fdec)) +					goto out_err; +				break; +			default: +				break; +			} +		} +			break; +		case TGSI_TOKEN_TYPE_IMMEDIATE: +		{ +			const struct tgsi_full_immediate *imm; + +			imm = &parse.FullToken.FullImmediate; +			assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); +//			assert(imm->Immediate.Size == 4); +			vpc->imm[vpc->nr_imm++] = +				constant(vpc, -1, +					 imm->u.ImmediateFloat32[0].Float, +					 imm->u.ImmediateFloat32[1].Float, +					 imm->u.ImmediateFloat32[2].Float, +					 imm->u.ImmediateFloat32[3].Float); +		} +			break; +		case TGSI_TOKEN_TYPE_INSTRUCTION: +		{ +			const struct tgsi_full_instruction *finst; +			finst = &parse.FullToken.FullInstruction; +			if (!nv20_vertprog_parse_instruction(vpc, finst)) +				goto out_err; +		} +			break; +		default: +			break; +		} +	} + +	vp->insns[vp->nr_insns - 1].data[3] |= NV30_VP_INST_LAST; +	vp->translated = TRUE; +out_err: +	tgsi_parse_free(&parse); +	FREE(vpc); +} + +static boolean +nv20_vertprog_validate(struct nv20_context *nv20) +{  +	struct nouveau_winsys *nvws = nv20->nvws; +	struct pipe_winsys *ws = nv20->pipe.winsys; +	struct nouveau_grobj *rankine = nv20->screen->rankine; +	struct nv20_vertex_program *vp; +	struct pipe_buffer *constbuf; +	boolean upload_code = FALSE, upload_data = FALSE; +	int i; + +	vp = nv20->vertprog; +	constbuf = nv20->constbuf[PIPE_SHADER_VERTEX]; + +	/* Translate TGSI shader into hw bytecode */ +	if (!vp->translated) { +		nv20_vertprog_translate(nv20, vp); +		if (!vp->translated) +			return FALSE; +	} + +	/* Allocate hw vtxprog exec slots */ +	if (!vp->exec) { +		struct nouveau_resource *heap = nv20->screen->vp_exec_heap; +		struct nouveau_stateobj *so; +		uint vplen = vp->nr_insns; + +		if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) { +			while (heap->next && heap->size < vplen) { +				struct nv20_vertex_program *evict; +				 +				evict = heap->next->priv; +				nvws->res_free(&evict->exec); +			} + +			if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) +				assert(0); +		} + +		so = so_new(2, 0); +		so_method(so, rankine, NV34TCL_VP_START_FROM_ID, 1); +		so_data  (so, vp->exec->start); +		so_ref(so, &vp->so); + +		upload_code = TRUE; +	} + +	/* Allocate hw vtxprog const slots */ +	if (vp->nr_consts && !vp->data) { +		struct nouveau_resource *heap = nv20->screen->vp_data_heap; + +		if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) { +			while (heap->next && heap->size < vp->nr_consts) { +				struct nv20_vertex_program *evict; +				 +				evict = heap->next->priv; +				nvws->res_free(&evict->data); +			} + +			if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) +				assert(0); +		} + +		/*XXX: handle this some day */ +		assert(vp->data->start >= vp->data_start_min); + +		upload_data = TRUE; +		if (vp->data_start != vp->data->start) +			upload_code = TRUE; +	} + +	/* If exec or data segments moved we need to patch the program to +	 * fixup offsets and register IDs. +	 */ +	if (vp->exec_start != vp->exec->start) { +		for (i = 0; i < vp->nr_insns; i++) { +			struct nv20_vertex_program_exec *vpi = &vp->insns[i]; + +			if (vpi->has_branch_offset) { +				assert(0); +			} +		} + +		vp->exec_start = vp->exec->start; +	} + +	if (vp->nr_consts && vp->data_start != vp->data->start) { +		for (i = 0; i < vp->nr_insns; i++) { +			struct nv20_vertex_program_exec *vpi = &vp->insns[i]; + +			if (vpi->const_index >= 0) { +				vpi->data[1] &= ~NV30_VP_INST_CONST_SRC_MASK; +				vpi->data[1] |= +					(vpi->const_index + vp->data->start) << +					NV30_VP_INST_CONST_SRC_SHIFT; + +			} +		} + +		vp->data_start = vp->data->start; +	} + +	/* Update + Upload constant values */ +	if (vp->nr_consts) { +		float *map = NULL; + +		if (constbuf) { +			map = ws->buffer_map(ws, constbuf, +					     PIPE_BUFFER_USAGE_CPU_READ); +		} + +		for (i = 0; i < vp->nr_consts; i++) { +			struct nv20_vertex_program_data *vpd = &vp->consts[i]; + +			if (vpd->index >= 0) { +				if (!upload_data && +				    !memcmp(vpd->value, &map[vpd->index * 4], +					    4 * sizeof(float))) +					continue; +				memcpy(vpd->value, &map[vpd->index * 4], +				       4 * sizeof(float)); +			} + +			BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5); +			OUT_RING  (i + vp->data->start); +			OUT_RINGp ((uint32_t *)vpd->value, 4); +		} + +		if (constbuf) { +			ws->buffer_unmap(ws, constbuf); +		} +	} + +	/* Upload vtxprog */ +	if (upload_code) { +#if 0 +		for (i = 0; i < vp->nr_insns; i++) { +			NOUVEAU_MSG("VP inst %d: 0x%08x 0x%08x 0x%08x 0x%08x\n", +				i, vp->insns[i].data[0], vp->insns[i].data[1], +				vp->insns[i].data[2], vp->insns[i].data[3]); +		} +#endif +		BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1); +		OUT_RING  (vp->exec->start); +		for (i = 0; i < vp->nr_insns; i++) { +			BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_INST(0), 4); +			OUT_RINGp (vp->insns[i].data, 4); +		} +	} + +	if (vp->so != nv20->state.hw[NV30_STATE_VERTPROG]) { +		so_ref(vp->so, &nv20->state.hw[NV30_STATE_VERTPROG]); +		return TRUE; +	} + +	return FALSE; +} + +void +nv20_vertprog_destroy(struct nv20_context *nv20, struct nv20_vertex_program *vp) +{ +	struct nouveau_winsys *nvws = nv20->screen->nvws; + +	vp->translated = FALSE; + +	if (vp->nr_insns) { +		FREE(vp->insns); +		vp->insns = NULL; +		vp->nr_insns = 0; +	} + +	if (vp->nr_consts) { +		FREE(vp->consts); +		vp->consts = NULL; +		vp->nr_consts = 0; +	} + +	nvws->res_free(&vp->exec); +	vp->exec_start = 0; +	nvws->res_free(&vp->data); +	vp->data_start = 0; +	vp->data_start_min = 0; + +	vp->ir = vp->or = 0; +	so_ref(NULL, &vp->so); +} + +struct nv20_state_entry nv20_state_vertprog = { +	.validate = nv20_vertprog_validate, +	.dirty = { +		.pipe = NV30_NEW_VERTPROG /*| NV30_NEW_UCP*/, +		.hw = NV30_STATE_VERTPROG, +	} +}; diff --git a/src/gallium/winsys/drm/nouveau/Makefile b/src/gallium/winsys/drm/nouveau/Makefile index be630ff6d1..81562ca78d 100644 --- a/src/gallium/winsys/drm/nouveau/Makefile +++ b/src/gallium/winsys/drm/nouveau/Makefile @@ -10,6 +10,7 @@ PIPE_DRIVERS = \  	$(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \  	$(TOP)/src/gallium/drivers/nv04/libnv04.a \  	$(TOP)/src/gallium/drivers/nv10/libnv10.a \ +	$(TOP)/src/gallium/drivers/nv20/libnv20.a \  	$(TOP)/src/gallium/drivers/nv30/libnv30.a \  	$(TOP)/src/gallium/drivers/nv40/libnv40.a \  	$(TOP)/src/gallium/drivers/nv50/libnv50.a diff --git a/src/gallium/winsys/drm/nouveau/nouveau_winsys.c b/src/gallium/winsys/drm/nouveau/nouveau_winsys.c index 0878840dcc..364340e1d3 100644 --- a/src/gallium/winsys/drm/nouveau/nouveau_winsys.c +++ b/src/gallium/winsys/drm/nouveau/nouveau_winsys.c @@ -101,10 +101,13 @@ nouveau_pipe_create(struct nouveau_context *nv)  	switch (chipset & 0xf0) {  	case 0x10: -	case 0x20:  		hws_create = nv10_screen_create;  		hw_create = nv10_create;  		break; +	case 0x20: +		hws_create = nv20_screen_create; +		hw_create = nv20_create; +		break;  	case 0x30:  		hws_create = nv30_screen_create;  		hw_create = nv30_create; diff --git a/src/gallium/winsys/g3dvl/nouveau/Makefile b/src/gallium/winsys/g3dvl/nouveau/Makefile index 5d11bde322..ff43327778 100644 --- a/src/gallium/winsys/g3dvl/nouveau/Makefile +++ b/src/gallium/winsys/g3dvl/nouveau/Makefile @@ -26,11 +26,12 @@ LDFLAGS		+= -L${DRMDIR}/lib			\  		   -L${GALLIUMDIR}/auxiliary/rtasm	\  		   -L${GALLIUMDIR}/auxiliary/cso_cache	\  		   -L${GALLIUMDIR}/drivers/nv10		\ +		   -L${GALLIUMDIR}/drivers/nv20		\  		   -L${GALLIUMDIR}/drivers/nv30		\  		   -L${GALLIUMDIR}/drivers/nv40		\  		   -L${GALLIUMDIR}/drivers/nv50 -LIBS		+= -ldriclient -ldrm -lnv10 -lnv30 -lnv40 -lnv50 -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lm +LIBS		+= -ldriclient -ldrm -lnv10 -lnv20 -lnv30 -lnv40 -lnv50 -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lm  ############################################# diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 7cf06da43c..4bc734bad3 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -672,7 +672,7 @@ st_draw_vbo(GLcontext *ctx,        pipe_buffer_reference(pipe->screen, &vbuffer[attr].buffer, NULL);        assert(!vbuffer[attr].buffer);     } -   pipe->set_vertex_buffers(pipe, vp->num_inputs, vbuffer); +   pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer);  } | 
