add missing license texts
[mesa.git] / src / mesa / drivers / dri / i915 / i830_vtbl.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 #include "i830_context.h"
30 #include "i830_reg.h"
31
32 #include "intel_batchbuffer.h"
33
34 #include "tnl/t_context.h"
35 #include "tnl/t_vertex.h"
36
37 static GLboolean i830_check_vertex_size( intelContextPtr intel,
38 GLuint expected );
39
40 #define SZ_TO_HW(sz) ((sz-2)&0x3)
41 #define EMIT_SZ(sz) (EMIT_1F + (sz) - 1)
42 #define EMIT_ATTR( ATTR, STYLE, V0 ) \
43 do { \
44 intel->vertex_attrs[intel->vertex_attr_count].attrib = (ATTR); \
45 intel->vertex_attrs[intel->vertex_attr_count].format = (STYLE); \
46 intel->vertex_attr_count++; \
47 v0 |= V0; \
48 } while (0)
49
50 #define EMIT_PAD( N ) \
51 do { \
52 intel->vertex_attrs[intel->vertex_attr_count].attrib = 0; \
53 intel->vertex_attrs[intel->vertex_attr_count].format = EMIT_PAD; \
54 intel->vertex_attrs[intel->vertex_attr_count].offset = (N); \
55 intel->vertex_attr_count++; \
56 } while (0)
57
58
59 #define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2))
60 #define TEXBIND_SET(n, x) ((x)<<((n)*4))
61
62 static void i830_render_start( intelContextPtr intel )
63 {
64 GLcontext *ctx = &intel->ctx;
65 i830ContextPtr i830 = I830_CONTEXT(intel);
66 TNLcontext *tnl = TNL_CONTEXT(ctx);
67 struct vertex_buffer *VB = &tnl->vb;
68 GLuint index = tnl->render_inputs;
69 GLuint v0 = _3DSTATE_VFT0_CMD;
70 GLuint v2 = _3DSTATE_VFT1_CMD;
71 GLuint mcsb1 = 0;
72
73 /* Important:
74 */
75 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
76 intel->vertex_attr_count = 0;
77
78 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
79 * build up a hardware vertex.
80 */
81 if (index & _TNL_BITS_TEX_ANY) {
82 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW );
83 intel->coloroffset = 4;
84 }
85 else {
86 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VFT0_XYZ );
87 intel->coloroffset = 3;
88 }
89
90 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, VFT0_DIFFUSE );
91
92 intel->specoffset = 0;
93 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
94 if (index & _TNL_BIT_COLOR1) {
95 intel->specoffset = intel->coloroffset + 1;
96 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, VFT0_SPEC );
97 }
98 else
99 EMIT_PAD( 3 );
100
101 if (index & _TNL_BIT_FOG)
102 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC );
103 else
104 EMIT_PAD( 1 );
105 }
106
107 if (index & _TNL_BITS_TEX_ANY) {
108 int i, count = 0;
109
110 for (i = 0; i < I830_TEX_UNITS; i++) {
111 if (index & _TNL_BIT_TEX(i)) {
112 GLuint sz = VB->TexCoordPtr[i]->size;
113 GLuint emit;
114 GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] &
115 ~TEXCOORDTYPE_MASK);
116
117 switch (sz) {
118 case 1:
119 case 2:
120 case 3: /* XXX: fix for CUBE/VOLUME textures */
121 emit = EMIT_2F;
122 sz = 2;
123 mcs |= TEXCOORDTYPE_CARTESIAN;
124 break;
125 case 4:
126 emit = EMIT_3F_XYW;
127 sz = 3;
128 mcs |= TEXCOORDTYPE_HOMOGENEOUS;
129 break;
130 default:
131 continue;
132 };
133
134
135 EMIT_ATTR( _TNL_ATTRIB_TEX0+i, emit, 0 );
136 v2 |= VRTX_TEX_SET_FMT(count, SZ_TO_HW(sz));
137 mcsb1 |= (count+8)<<(i*4);
138
139 if (mcs != i830->state.Tex[i][I830_TEXREG_MCS]) {
140 I830_STATECHANGE(i830, I830_UPLOAD_TEX(i));
141 i830->state.Tex[i][I830_TEXREG_MCS] = mcs;
142 }
143
144 count++;
145 }
146 }
147
148 v0 |= VFT0_TEX_COUNT(count);
149 }
150
151 /* Only need to change the vertex emit code if there has been a
152 * statechange to a new hardware vertex format:
153 */
154 if (v0 != i830->state.Ctx[I830_CTXREG_VF] ||
155 v2 != i830->state.Ctx[I830_CTXREG_VF2] ||
156 mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] ||
157 index != i830->last_index) {
158
159 I830_STATECHANGE( i830, I830_UPLOAD_CTX );
160
161 /* Must do this *after* statechange, so as not to affect
162 * buffered vertices reliant on the old state:
163 */
164 intel->vertex_size =
165 _tnl_install_attrs( ctx,
166 intel->vertex_attrs,
167 intel->vertex_attr_count,
168 intel->ViewportMatrix.m, 0 );
169
170 intel->vertex_size >>= 2;
171
172 i830->state.Ctx[I830_CTXREG_VF] = v0;
173 i830->state.Ctx[I830_CTXREG_VF2] = v2;
174 i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1;
175 i830->last_index = index;
176
177 assert(i830_check_vertex_size( intel, intel->vertex_size ));
178 }
179 }
180
181 static void i830_reduced_primitive_state( intelContextPtr intel,
182 GLenum rprim )
183 {
184 i830ContextPtr i830 = I830_CONTEXT(intel);
185 GLuint st1 = i830->state.Stipple[I830_STPREG_ST1];
186
187 st1 &= ~ST1_ENABLE;
188
189 switch (rprim) {
190 case GL_TRIANGLES:
191 if (intel->ctx.Polygon.StippleFlag &&
192 intel->hw_stipple)
193 st1 |= ST1_ENABLE;
194 break;
195 case GL_LINES:
196 case GL_POINTS:
197 default:
198 break;
199 }
200
201 i830->intel.reduced_primitive = rprim;
202
203 if (st1 != i830->state.Stipple[I830_STPREG_ST1]) {
204 I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE);
205 i830->state.Stipple[I830_STPREG_ST1] = st1;
206 }
207 }
208
209 /* Pull apart the vertex format registers and figure out how large a
210 * vertex is supposed to be.
211 */
212 static GLboolean i830_check_vertex_size( intelContextPtr intel,
213 GLuint expected )
214 {
215 i830ContextPtr i830 = I830_CONTEXT(intel);
216 int vft0 = i830->current->Ctx[I830_CTXREG_VF];
217 int vft1 = i830->current->Ctx[I830_CTXREG_VF2];
218 int nrtex = (vft0 & VFT0_TEX_COUNT_MASK) >> VFT0_TEX_COUNT_SHIFT;
219 int i, sz = 0;
220
221 switch (vft0 & VFT0_XYZW_MASK) {
222 case VFT0_XY: sz = 2; break;
223 case VFT0_XYZ: sz = 3; break;
224 case VFT0_XYW: sz = 3; break;
225 case VFT0_XYZW: sz = 4; break;
226 default:
227 fprintf(stderr, "no xyzw specified\n");
228 return 0;
229 }
230
231 if (vft0 & VFT0_SPEC) sz++;
232 if (vft0 & VFT0_DIFFUSE) sz++;
233 if (vft0 & VFT0_DEPTH_OFFSET) sz++;
234 if (vft0 & VFT0_POINT_WIDTH) sz++;
235
236 for (i = 0 ; i < nrtex ; i++) {
237 switch (vft1 & VFT1_TEX0_MASK) {
238 case TEXCOORDFMT_2D: sz += 2; break;
239 case TEXCOORDFMT_3D: sz += 3; break;
240 case TEXCOORDFMT_4D: sz += 4; break;
241 case TEXCOORDFMT_1D: sz += 1; break;
242 }
243 vft1 >>= VFT1_TEX1_SHIFT;
244 }
245
246 if (sz != expected)
247 fprintf(stderr, "vertex size mismatch %d/%d\n", sz, expected);
248
249 return sz == expected;
250 }
251
252 static void i830_emit_invarient_state( intelContextPtr intel )
253 {
254 BATCH_LOCALS;
255
256 BEGIN_BATCH( 200 );
257
258 OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0));
259 OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1));
260 OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(2));
261 OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(3));
262
263 OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
264 OUT_BATCH(0);
265
266 OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
267 OUT_BATCH(0);
268
269 OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
270 OUT_BATCH(0);
271
272 OUT_BATCH(_3DSTATE_FOG_MODE_CMD);
273 OUT_BATCH(FOGFUNC_ENABLE |
274 FOG_LINEAR_CONST |
275 FOGSRC_INDEX_Z |
276 ENABLE_FOG_DENSITY);
277 OUT_BATCH(0);
278 OUT_BATCH(0);
279
280
281 OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
282 MAP_UNIT(0) |
283 DISABLE_TEX_STREAM_BUMP |
284 ENABLE_TEX_STREAM_COORD_SET |
285 TEX_STREAM_COORD_SET(0) |
286 ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(0));
287 OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
288 MAP_UNIT(1) |
289 DISABLE_TEX_STREAM_BUMP |
290 ENABLE_TEX_STREAM_COORD_SET |
291 TEX_STREAM_COORD_SET(1) |
292 ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(1));
293 OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
294 MAP_UNIT(2) |
295 DISABLE_TEX_STREAM_BUMP |
296 ENABLE_TEX_STREAM_COORD_SET |
297 TEX_STREAM_COORD_SET(2) |
298 ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(2));
299 OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
300 MAP_UNIT(3) |
301 DISABLE_TEX_STREAM_BUMP |
302 ENABLE_TEX_STREAM_COORD_SET |
303 TEX_STREAM_COORD_SET(3) |
304 ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(3));
305
306 OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
307 OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(0));
308 OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
309 OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(1));
310 OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
311 OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(2));
312 OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
313 OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3));
314
315 OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
316 ENABLE_POINT_RASTER_RULE |
317 OGL_POINT_RASTER_RULE |
318 ENABLE_LINE_STRIP_PROVOKE_VRTX |
319 ENABLE_TRI_FAN_PROVOKE_VRTX |
320 ENABLE_TRI_STRIP_PROVOKE_VRTX |
321 LINE_STRIP_PROVOKE_VRTX(1) |
322 TRI_FAN_PROVOKE_VRTX(2) |
323 TRI_STRIP_PROVOKE_VRTX(2));
324
325 OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD |
326 DISABLE_SCISSOR_RECT);
327
328 OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
329 OUT_BATCH(0);
330 OUT_BATCH(0);
331
332 OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
333 OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
334
335 OUT_BATCH(_3DSTATE_W_STATE_CMD);
336 OUT_BATCH(MAGIC_W_STATE_DWORD1);
337 OUT_BATCH(0x3f800000 /* 1.0 in IEEE float */ );
338
339
340 OUT_BATCH(_3DSTATE_COLOR_FACTOR_CMD);
341 OUT_BATCH(0x80808080); /* .5 required in alpha for GL_DOT3_RGBA_EXT */
342
343 ADVANCE_BATCH();
344 }
345
346
347 #define emit( intel, state, size ) \
348 do { \
349 int k; \
350 BEGIN_BATCH( size / sizeof(GLuint)); \
351 for (k = 0 ; k < size / sizeof(GLuint) ; k++) \
352 OUT_BATCH(state[k]); \
353 ADVANCE_BATCH(); \
354 } while (0);
355
356
357 /* Push the state into the sarea and/or texture memory.
358 */
359 static void i830_emit_state( intelContextPtr intel )
360 {
361 i830ContextPtr i830 = I830_CONTEXT(intel);
362 struct i830_hw_state *state = i830->current;
363 BATCH_LOCALS;
364 int i;
365 GLuint dirty = state->active & ~state->emitted;
366
367 if (dirty & I830_UPLOAD_CTX) {
368 if (VERBOSE) fprintf(stderr, "I830_UPLOAD_CTX:\n");
369 emit( i830, state->Ctx, sizeof(state->Ctx) );
370 }
371
372 if (dirty & I830_UPLOAD_BUFFERS) {
373 if (VERBOSE) fprintf(stderr, "I830_UPLOAD_BUFFERS:\n");
374 emit( i830, state->Buffer, sizeof(state->Buffer) );
375 }
376
377 if (dirty & I830_UPLOAD_STIPPLE) {
378 if (VERBOSE) fprintf(stderr, "I830_UPLOAD_STIPPLE:\n");
379 emit( i830, state->Stipple, sizeof(state->Stipple) );
380 }
381
382 for (i = 0; i < I830_TEX_UNITS; i++) {
383 if ((dirty & I830_UPLOAD_TEX(i))) {
384 if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i);
385 emit( i830, state->Tex[i], sizeof(state->Tex[i]));
386 }
387
388 if (dirty & I830_UPLOAD_TEXBLEND(i)) {
389 if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d):\n", i);
390 emit( i830, state->TexBlend[i],
391 state->TexBlendWordsUsed[i] * 4 );
392 }
393 }
394
395 state->emitted |= dirty;
396 }
397
398 static void i830_destroy_context( intelContextPtr intel )
399 {
400 _tnl_free_vertices(&intel->ctx);
401 }
402
403 static void i830_set_draw_offset( intelContextPtr intel, int offset )
404 {
405 i830ContextPtr i830 = I830_CONTEXT(intel);
406 I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS );
407 i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset;
408 }
409
410 /* This isn't really handled at the moment.
411 */
412 static void i830_lost_hardware( intelContextPtr intel )
413 {
414 I830_CONTEXT(intel)->state.emitted = 0;
415 }
416
417
418
419 static void i830_emit_flush( intelContextPtr intel )
420 {
421 BATCH_LOCALS;
422
423 BEGIN_BATCH(2);
424 OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE );
425 OUT_BATCH( 0 );
426 ADVANCE_BATCH();
427 }
428
429
430
431
432 void i830InitVtbl( i830ContextPtr i830 )
433 {
434 i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj;
435 i830->intel.vtbl.check_vertex_size = i830_check_vertex_size;
436 i830->intel.vtbl.clear_with_tris = i830ClearWithTris;
437 i830->intel.vtbl.destroy = i830_destroy_context;
438 i830->intel.vtbl.emit_invarient_state = i830_emit_invarient_state;
439 i830->intel.vtbl.emit_state = i830_emit_state;
440 i830->intel.vtbl.lost_hardware = i830_lost_hardware;
441 i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state;
442 i830->intel.vtbl.set_draw_offset = i830_set_draw_offset;
443 i830->intel.vtbl.update_texture_state = i830UpdateTextureState;
444 i830->intel.vtbl.emit_flush = i830_emit_flush;
445 i830->intel.vtbl.render_start = i830_render_start;
446 }