Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 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
/*
28
 * Vertex submission helper definitions shared among the software and
29
 * hardware TnL paths.
30
 */
31
 
32
#include "nouveau_gldefs.h"
33
 
34
#include "main/light.h"
35
#include "vbo/vbo.h"
36
#include "tnl/tnl.h"
37
 
38
#define OUT_INDICES_L(r, i, d, n)		\
39
	BATCH_OUT_L(i + d, n);			\
40
	(void)r
41
#define OUT_INDICES_I16(r, i, d, n)				\
42
	BATCH_OUT_I16(r->ib.extract_u(&r->ib, 0, i) + d,	\
43
		      r->ib.extract_u(&r->ib, 0, i + 1) + d)
44
#define OUT_INDICES_I32(r, i, d, n)			\
45
	BATCH_OUT_I32(r->ib.extract_u(&r->ib, 0, i) + d)
46
 
47
/*
48
 * Emit  vertices using BATCH_OUT_, MAX_OUT_ at a time,
49
 * grouping them in packets of length MAX_PACKET.
50
 *
51
 * out:   hardware index data type.
52
 * ctx:   GL context.
53
 * start: element within the index buffer to begin with.
54
 * delta: integer correction that will be added to each index found in
55
 *        the index buffer.
56
 */
57
#define EMIT_VBO(out, ctx, start, delta, n) do {			\
58
		struct nouveau_render_state *render = to_render_state(ctx); \
59
		int npush = n;						\
60
									\
61
		while (npush) {						\
62
			int npack = MIN2(npush, MAX_PACKET * MAX_OUT_##out); \
63
			npush -= npack;					\
64
									\
65
			BATCH_PACKET_##out((npack + MAX_OUT_##out - 1)	\
66
					   / MAX_OUT_##out);		\
67
			while (npack) {					\
68
				int nout = MIN2(npack, MAX_OUT_##out);	\
69
				npack -= nout;				\
70
									\
71
				OUT_INDICES_##out(render, start, delta, \
72
						  nout);		\
73
				start += nout;				\
74
			}						\
75
		}							\
76
	} while (0)
77
 
78
/*
79
 * Emit the -th element of the array , using IMM_OUT.
80
 */
81
#define EMIT_IMM(ctx, a, n) do {					\
82
		struct nouveau_attr_info *info =			\
83
			&TAG(vertex_attrs)[(a)->attr];			\
84
		int m;							\
85
									\
86
		if (!info->emit) {					\
87
			IMM_PACKET(info->imm_method, info->imm_fields);	\
88
									\
89
			for (m = 0; m < (a)->fields; m++)		\
90
				IMM_OUT((a)->extract_f(a, n, m));	\
91
									\
92
			for (m = (a)->fields; m < info->imm_fields; m++) \
93
				IMM_OUT(((float []){0, 0, 0, 1})[m]);	\
94
									\
95
		} else {						\
96
			info->emit(ctx, a, (a)->buf + n * (a)->stride);	\
97
		}							\
98
	} while (0)
99
 
100
static void
101
dispatch_l(struct gl_context *ctx, unsigned int start, int delta,
102
	   unsigned int n)
103
{
104
	struct nouveau_pushbuf *push = context_push(ctx);
105
	RENDER_LOCALS(ctx);
106
 
107
	EMIT_VBO(L, ctx, start, delta, n);
108
}
109
 
110
static void
111
dispatch_i32(struct gl_context *ctx, unsigned int start, int delta,
112
	     unsigned int n)
113
{
114
	struct nouveau_pushbuf *push = context_push(ctx);
115
	RENDER_LOCALS(ctx);
116
 
117
	EMIT_VBO(I32, ctx, start, delta, n);
118
}
119
 
120
static void
121
dispatch_i16(struct gl_context *ctx, unsigned int start, int delta,
122
	     unsigned int n)
123
{
124
	struct nouveau_pushbuf *push = context_push(ctx);
125
	RENDER_LOCALS(ctx);
126
 
127
	EMIT_VBO(I32, ctx, start, delta, n & 1);
128
	EMIT_VBO(I16, ctx, start, delta, n & ~1);
129
}
130
 
131
/*
132
 * Select an appropriate dispatch function for the given index buffer.
133
 */
134
static dispatch_t
135
get_array_dispatch(struct nouveau_array *a)
136
{
137
	if (!a->fields)
138
		return dispatch_l;
139
	else if (a->type == GL_UNSIGNED_INT)
140
		return dispatch_i32;
141
	else
142
		return dispatch_i16;
143
}
144
 
145
/*
146
 * Returns how many vertices you can draw using  pushbuf dwords.
147
 */
148
static inline unsigned
149
get_max_vertices(struct gl_context *ctx, const struct _mesa_index_buffer *ib,
150
		 int n)
151
{
152
	struct nouveau_render_state *render = to_render_state(ctx);
153
 
154
	if (render->mode == IMM) {
155
		return MAX2(0, n - 4) / (render->vertex_size / 4 +
156
					 render->attr_count);
157
	} else {
158
		unsigned max_out;
159
 
160
		if (ib) {
161
			switch (ib->type) {
162
			case GL_UNSIGNED_INT:
163
				max_out = MAX_OUT_I32;
164
				break;
165
 
166
			case GL_UNSIGNED_SHORT:
167
				max_out = MAX_OUT_I16;
168
				break;
169
 
170
			case GL_UNSIGNED_BYTE:
171
				max_out = MAX_OUT_I16;
172
				break;
173
 
174
			default:
175
				assert(0);
176
				max_out = 0;
177
				break;
178
			}
179
		} else {
180
			max_out = MAX_OUT_L;
181
		}
182
 
183
		return MAX2(0, n - 7) * max_out * MAX_PACKET / (1 + MAX_PACKET);
184
	}
185
}
186
 
187
static void
188
TAG(emit_material)(struct gl_context *ctx, struct nouveau_array *a,
189
		   const void *v)
190
{
191
	int attr = a->attr - VERT_ATTRIB_GENERIC0;
192
	int state = ((int []) {
193
			NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT,
194
			NOUVEAU_STATE_MATERIAL_BACK_AMBIENT,
195
			NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE,
196
			NOUVEAU_STATE_MATERIAL_BACK_DIFFUSE,
197
			NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR,
198
			NOUVEAU_STATE_MATERIAL_BACK_SPECULAR,
199
			NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT,
200
			NOUVEAU_STATE_MATERIAL_BACK_AMBIENT,
201
			NOUVEAU_STATE_MATERIAL_FRONT_SHININESS,
202
			NOUVEAU_STATE_MATERIAL_BACK_SHININESS
203
		}) [attr];
204
 
205
	COPY_4V(ctx->Light.Material.Attrib[attr], (float *)v);
206
	_mesa_update_material(ctx, 1 << attr);
207
 
208
	context_drv(ctx)->emit[state](ctx, state);
209
}