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 "nv10_3d.xml.h"
30#include "nv10_driver.h"
31
32#define NUM_VERTEX_ATTRS 8
33
34static void
35nv10_emit_material(struct gl_context *ctx, struct nouveau_array *a,
36		   const void *v);
37
38/* Vertex attribute format. */
39static struct nouveau_attr_info nv10_vertex_attrs[VERT_ATTRIB_MAX] = {
40	[VERT_ATTRIB_POS] = {
41		.vbo_index = 0,
42		.imm_method = NV10_3D_VERTEX_POS_4F_X,
43		.imm_fields = 4,
44	},
45	[VERT_ATTRIB_COLOR0] = {
46		.vbo_index = 1,
47		.imm_method = NV10_3D_VERTEX_COL_4F_R,
48		.imm_fields = 4,
49	},
50	[VERT_ATTRIB_COLOR1] = {
51		.vbo_index = 2,
52		.imm_method = NV10_3D_VERTEX_COL2_3F_R,
53		.imm_fields = 3,
54	},
55	[VERT_ATTRIB_TEX0] = {
56		.vbo_index = 3,
57		.imm_method = NV10_3D_VERTEX_TX0_4F_S,
58		.imm_fields = 4,
59	},
60	[VERT_ATTRIB_TEX1] = {
61		.vbo_index = 4,
62		.imm_method = NV10_3D_VERTEX_TX1_4F_S,
63		.imm_fields = 4,
64	},
65	[VERT_ATTRIB_NORMAL] = {
66		.vbo_index = 5,
67		.imm_method = NV10_3D_VERTEX_NOR_3F_X,
68		.imm_fields = 3,
69	},
70	[VERT_ATTRIB_FOG] = {
71		.vbo_index = 7,
72		.imm_method = NV10_3D_VERTEX_FOG_1F,
73		.imm_fields = 1,
74	},
75	[VERT_ATTRIB_GENERIC0] = {
76		.emit = nv10_emit_material,
77	},
78	[VERT_ATTRIB_GENERIC2] = {
79		.emit = nv10_emit_material,
80	},
81	[VERT_ATTRIB_GENERIC4] = {
82		.emit = nv10_emit_material,
83	},
84	[VERT_ATTRIB_GENERIC6] = {
85		.emit = nv10_emit_material,
86	},
87	[VERT_ATTRIB_GENERIC8] = {
88		.emit = nv10_emit_material,
89	},
90};
91
92static int
93get_hw_format(int type)
94{
95	switch (type) {
96	case GL_FLOAT:
97		return NV10_3D_VTXBUF_FMT_TYPE_V32_FLOAT;
98	case GL_SHORT:
99	case GL_UNSIGNED_SHORT:
100		return NV10_3D_VTXBUF_FMT_TYPE_V16_SNORM;
101	case GL_UNSIGNED_BYTE:
102		return NV10_3D_VTXBUF_FMT_TYPE_U8_UNORM;
103	default:
104		assert(0);
105	}
106}
107
108static void
109nv10_render_set_format(struct gl_context *ctx)
110{
111	struct nouveau_render_state *render = to_render_state(ctx);
112	struct nouveau_pushbuf *push = context_push(ctx);
113	int i, attr, hw_format;
114
115	FOR_EACH_ATTR(render, i, attr) {
116		if (attr >= 0) {
117			struct nouveau_array *a = &render->attrs[attr];
118
119			hw_format = a->stride << 8 |
120				a->fields << 4 |
121				get_hw_format(a->type);
122
123			if (attr == VERT_ATTRIB_POS && a->fields == 4)
124				hw_format |= NV10_3D_VTXBUF_FMT_HOMOGENEOUS;
125		} else {
126			/* Unused attribute. */
127			hw_format = NV10_3D_VTXBUF_FMT_TYPE_V32_FLOAT;
128		}
129
130		BEGIN_NV04(push, NV10_3D(VTXBUF_FMT(i)), 1);
131		PUSH_DATA (push, hw_format);
132	}
133}
134
135static void
136nv10_render_bind_vertices(struct gl_context *ctx)
137{
138	struct nouveau_render_state *render = to_render_state(ctx);
139	struct nouveau_pushbuf *push = context_push(ctx);
140	int i, attr;
141
142	FOR_EACH_BOUND_ATTR(render, i, attr) {
143		struct nouveau_array *a = &render->attrs[attr];
144
145		BEGIN_NV04(push, NV10_3D(VTXBUF_OFFSET(i)), 1);
146		PUSH_MTHDl(push, NV10_3D(VTXBUF_OFFSET(i)), BUFCTX_VTX,
147				 a->bo, a->offset, NOUVEAU_BO_GART |
148				 NOUVEAU_BO_RD);
149	}
150}
151
152static void
153nv10_render_release_vertices(struct gl_context *ctx)
154{
155	PUSH_RESET(context_push(ctx), BUFCTX_VTX);
156}
157
158/* Vertex array rendering defs. */
159#define RENDER_LOCALS(ctx)
160
161#define BATCH_VALIDATE()						\
162	BEGIN_NV04(push, NV10_3D(VTXBUF_VALIDATE), 1);	\
163	PUSH_DATA (push, 0)
164
165#define BATCH_BEGIN(prim)						\
166	BEGIN_NV04(push, NV10_3D(VTXBUF_BEGIN_END), 1);	\
167	PUSH_DATA (push, prim)
168#define BATCH_END()							\
169	BEGIN_NV04(push, NV10_3D(VTXBUF_BEGIN_END), 1);	\
170	PUSH_DATA (push, 0)
171
172#define MAX_PACKET 0x400
173
174#define MAX_OUT_L 0x100
175#define BATCH_PACKET_L(n)						\
176	BEGIN_NI04(push, NV10_3D(VTXBUF_BATCH), n)
177#define BATCH_OUT_L(i, n)			\
178	PUSH_DATA (push, ((n) - 1) << 24 | (i))
179
180#define MAX_OUT_I16 0x2
181#define BATCH_PACKET_I16(n)						\
182	BEGIN_NI04(push, NV10_3D(VTXBUF_ELEMENT_U16), n)
183#define BATCH_OUT_I16(i0, i1)			\
184	PUSH_DATA (push, (i1) << 16 | (i0))
185
186#define MAX_OUT_I32 0x1
187#define BATCH_PACKET_I32(n)						\
188	BEGIN_NI04(push, NV10_3D(VTXBUF_ELEMENT_U32), n)
189#define BATCH_OUT_I32(i)			\
190	PUSH_DATA (push, i)
191
192#define IMM_PACKET(m, n)			\
193	BEGIN_NV04(push, SUBC_3D(m), n)
194#define IMM_OUT(x)				\
195	PUSH_DATAf(push, x)
196
197#define TAG(x) nv10_##x
198#include "nouveau_render_t.c"
199#include "nouveau_vbo_t.c"
200#include "nouveau_swtnl_t.c"
201