1/*
2 * Copyright (C) 2009-2010 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "nouveau_driver.h"
28#include "nouveau_context.h"
29#include "nv20_3d.xml.h"
30#include "nv20_driver.h"
31
32#define NUM_VERTEX_ATTRS 16
33
34static void
35nv20_emit_material(struct gl_context *ctx, struct nouveau_array *a,
36		   const void *v);
37
38/* Vertex attribute format. */
39static struct nouveau_attr_info nv20_vertex_attrs[VERT_ATTRIB_MAX] = {
40	[VERT_ATTRIB_POS] = {
41		.vbo_index = 0,
42		.imm_method = NV20_3D_VERTEX_POS_4F_X,
43		.imm_fields = 4,
44	},
45	[VERT_ATTRIB_NORMAL] = {
46		.vbo_index = 2,
47		.imm_method = NV20_3D_VERTEX_NOR_3F_X,
48		.imm_fields = 3,
49	},
50	[VERT_ATTRIB_COLOR0] = {
51		.vbo_index = 3,
52		.imm_method = NV20_3D_VERTEX_COL_4F,
53		.imm_fields = 4,
54	},
55	[VERT_ATTRIB_COLOR1] = {
56		.vbo_index = 4,
57		.imm_method = NV20_3D_VERTEX_COL2_3F,
58		.imm_fields = 3,
59	},
60	[VERT_ATTRIB_FOG] = {
61		.vbo_index = 5,
62		.imm_method = NV20_3D_VERTEX_FOG_1F,
63		.imm_fields = 1,
64	},
65	[VERT_ATTRIB_TEX0] = {
66		.vbo_index = 9,
67		.imm_method = NV20_3D_VERTEX_TX0_4F_S,
68		.imm_fields = 4,
69	},
70	[VERT_ATTRIB_TEX1] = {
71		.vbo_index = 10,
72		.imm_method = NV20_3D_VERTEX_TX1_4F_S,
73		.imm_fields = 4,
74	},
75	[VERT_ATTRIB_TEX2] = {
76		.vbo_index = 11,
77		.imm_method = NV20_3D_VERTEX_TX2_4F_S,
78		.imm_fields = 4,
79	},
80	[VERT_ATTRIB_TEX3] = {
81		.vbo_index = 12,
82		.imm_method = NV20_3D_VERTEX_TX3_4F_S,
83		.imm_fields = 4,
84	},
85	[VERT_ATTRIB_GENERIC0] = {
86		.emit = nv20_emit_material,
87	},
88	[VERT_ATTRIB_GENERIC1] = {
89		.emit = nv20_emit_material,
90	},
91	[VERT_ATTRIB_GENERIC2] = {
92		.emit = nv20_emit_material,
93	},
94	[VERT_ATTRIB_GENERIC3] = {
95		.emit = nv20_emit_material,
96	},
97	[VERT_ATTRIB_GENERIC4] = {
98		.emit = nv20_emit_material,
99	},
100	[VERT_ATTRIB_GENERIC5] = {
101		.emit = nv20_emit_material,
102	},
103	[VERT_ATTRIB_GENERIC6] = {
104		.emit = nv20_emit_material,
105	},
106	[VERT_ATTRIB_GENERIC7] = {
107		.emit = nv20_emit_material,
108	},
109	[VERT_ATTRIB_GENERIC8] = {
110		.emit = nv20_emit_material,
111	},
112	[VERT_ATTRIB_GENERIC9] = {
113		.emit = nv20_emit_material,
114	},
115};
116
117static int
118get_hw_format(int type)
119{
120	switch (type) {
121	case GL_FLOAT:
122		return NV20_3D_VTXBUF_FMT_TYPE_FLOAT;
123	case GL_UNSIGNED_SHORT:
124		return NV20_3D_VTXBUF_FMT_TYPE_USHORT;
125	case GL_UNSIGNED_BYTE:
126		return NV20_3D_VTXBUF_FMT_TYPE_UBYTE;
127	default:
128		assert(0);
129	}
130}
131
132static void
133nv20_render_set_format(struct gl_context *ctx)
134{
135	struct nouveau_render_state *render = to_render_state(ctx);
136	struct nouveau_pushbuf *push = context_push(ctx);
137	int i, attr, hw_format;
138
139	FOR_EACH_ATTR(render, i, attr) {
140		if (attr >= 0) {
141			struct nouveau_array *a = &render->attrs[attr];
142
143			hw_format = a->stride << 8 |
144				a->fields << 4 |
145				get_hw_format(a->type);
146
147		} else {
148			/* Unused attribute. */
149			hw_format = NV20_3D_VTXBUF_FMT_TYPE_FLOAT;
150		}
151
152		BEGIN_NV04(push, NV20_3D(VTXBUF_FMT(i)), 1);
153		PUSH_DATA (push, hw_format);
154	}
155}
156
157static void
158nv20_render_bind_vertices(struct gl_context *ctx)
159{
160	struct nouveau_render_state *render = to_render_state(ctx);
161	struct nouveau_pushbuf *push = context_push(ctx);
162	int i, attr;
163
164	FOR_EACH_BOUND_ATTR(render, i, attr) {
165		struct nouveau_array *a = &render->attrs[attr];
166
167		BEGIN_NV04(push, NV20_3D(VTXBUF_OFFSET(i)), 1);
168		PUSH_MTHD (push, NV20_3D(VTXBUF_OFFSET(i)), BUFCTX_VTX,
169				 a->bo, a->offset, NOUVEAU_BO_LOW |
170				 NOUVEAU_BO_OR | NOUVEAU_BO_GART |
171				 NOUVEAU_BO_RD, 0,
172				 NV20_3D_VTXBUF_OFFSET_DMA1);
173	}
174}
175
176static void
177nv20_render_release_vertices(struct gl_context *ctx)
178{
179	PUSH_RESET(context_push(ctx), BUFCTX_VTX);
180}
181
182/* Vertex array rendering defs. */
183#define RENDER_LOCALS(ctx)
184
185#define BATCH_VALIDATE()						\
186	BEGIN_NV04(push, NV20_3D(VTXBUF_VALIDATE), 1);	\
187	PUSH_DATA (push, 0)
188
189#define BATCH_BEGIN(prim)					\
190	BEGIN_NV04(push, NV20_3D(VERTEX_BEGIN_END), 1);	\
191	PUSH_DATA (push, prim)
192#define BATCH_END()						\
193	BEGIN_NV04(push, NV20_3D(VERTEX_BEGIN_END), 1);	\
194	PUSH_DATA (push, 0)
195
196#define MAX_PACKET 0x400
197
198#define MAX_OUT_L 0x100
199#define BATCH_PACKET_L(n)						\
200	BEGIN_NI04(push, NV20_3D(VTXBUF_BATCH), n)
201#define BATCH_OUT_L(i, n)			\
202	PUSH_DATA (push, ((n) - 1) << 24 | (i))
203
204#define MAX_OUT_I16 0x2
205#define BATCH_PACKET_I16(n)					\
206	BEGIN_NI04(push, NV20_3D(VTXBUF_ELEMENT_U16), n)
207#define BATCH_OUT_I16(i0, i1)			\
208	PUSH_DATA (push, (i1) << 16 | (i0))
209
210#define MAX_OUT_I32 0x1
211#define BATCH_PACKET_I32(n)					\
212	BEGIN_NI04(push, NV20_3D(VTXBUF_ELEMENT_U32), n)
213#define BATCH_OUT_I32(i)			\
214	PUSH_DATA (push, i)
215
216#define IMM_PACKET(m, n)			\
217	BEGIN_NV04(push, SUBC_3D(m), n)
218#define IMM_OUT(x)				\
219	PUSH_DATAf(push, x)
220
221#define TAG(x) nv20_##x
222#include "nouveau_render_t.c"
223#include "nouveau_vbo_t.c"
224#include "nouveau_swtnl_t.c"
225