3b3ff2bcedacff21b5227593536c9253397dd815
[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 #include "glapi/glapi.h"
29
30 #include "i830_context.h"
31 #include "i830_reg.h"
32 #include "intel_batchbuffer.h"
33 #include "intel_regions.h"
34 #include "intel_tris.h"
35 #include "tnl/t_context.h"
36 #include "tnl/t_vertex.h"
37
38 #define FILE_DEBUG_FLAG DEBUG_STATE
39
40 static GLboolean i830_check_vertex_size(struct intel_context *intel,
41 GLuint expected);
42
43 #define SZ_TO_HW(sz) ((sz-2)&0x3)
44 #define EMIT_SZ(sz) (EMIT_1F + (sz) - 1)
45 #define EMIT_ATTR( ATTR, STYLE, V0 ) \
46 do { \
47 intel->vertex_attrs[intel->vertex_attr_count].attrib = (ATTR); \
48 intel->vertex_attrs[intel->vertex_attr_count].format = (STYLE); \
49 intel->vertex_attr_count++; \
50 v0 |= V0; \
51 } while (0)
52
53 #define EMIT_PAD( N ) \
54 do { \
55 intel->vertex_attrs[intel->vertex_attr_count].attrib = 0; \
56 intel->vertex_attrs[intel->vertex_attr_count].format = EMIT_PAD; \
57 intel->vertex_attrs[intel->vertex_attr_count].offset = (N); \
58 intel->vertex_attr_count++; \
59 } while (0)
60
61
62 #define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2))
63 #define TEXBIND_SET(n, x) ((x)<<((n)*4))
64
65 static void
66 i830_render_prevalidate(struct intel_context *intel)
67 {
68 }
69
70 static void
71 i830_render_start(struct intel_context *intel)
72 {
73 GLcontext *ctx = &intel->ctx;
74 struct i830_context *i830 = i830_context(ctx);
75 TNLcontext *tnl = TNL_CONTEXT(ctx);
76 struct vertex_buffer *VB = &tnl->vb;
77 DECLARE_RENDERINPUTS(index_bitset);
78 GLuint v0 = _3DSTATE_VFT0_CMD;
79 GLuint v2 = _3DSTATE_VFT1_CMD;
80 GLuint mcsb1 = 0;
81
82 RENDERINPUTS_COPY(index_bitset, tnl->render_inputs_bitset);
83
84 /* Important:
85 */
86 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
87 intel->vertex_attr_count = 0;
88
89 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
90 * build up a hardware vertex.
91 */
92 if (RENDERINPUTS_TEST_RANGE(index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX)) {
93 EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW);
94 intel->coloroffset = 4;
95 }
96 else {
97 EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VFT0_XYZ);
98 intel->coloroffset = 3;
99 }
100
101 if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_POINTSIZE)) {
102 EMIT_ATTR(_TNL_ATTRIB_POINTSIZE, EMIT_1F, VFT0_POINT_WIDTH);
103 }
104
105 EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VFT0_DIFFUSE);
106
107 intel->specoffset = 0;
108 if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR1) ||
109 RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_FOG)) {
110 if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR1)) {
111 intel->specoffset = intel->coloroffset + 1;
112 EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC);
113 }
114 else
115 EMIT_PAD(3);
116
117 if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_FOG))
118 EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC);
119 else
120 EMIT_PAD(1);
121 }
122
123 if (RENDERINPUTS_TEST_RANGE(index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX)) {
124 int i, count = 0;
125
126 for (i = 0; i < I830_TEX_UNITS; i++) {
127 if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_TEX(i))) {
128 GLuint sz = VB->TexCoordPtr[i]->size;
129 GLuint emit;
130 GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] &
131 ~TEXCOORDTYPE_MASK);
132
133 switch (sz) {
134 case 1:
135 case 2:
136 emit = EMIT_2F;
137 sz = 2;
138 mcs |= TEXCOORDTYPE_CARTESIAN;
139 break;
140 case 3:
141 emit = EMIT_3F;
142 sz = 3;
143 mcs |= TEXCOORDTYPE_VECTOR;
144 break;
145 case 4:
146 emit = EMIT_3F_XYW;
147 sz = 3;
148 mcs |= TEXCOORDTYPE_HOMOGENEOUS;
149 break;
150 default:
151 continue;
152 };
153
154
155 EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, emit, 0);
156 v2 |= VRTX_TEX_SET_FMT(count, SZ_TO_HW(sz));
157 mcsb1 |= (count + 8) << (i * 4);
158
159 if (mcs != i830->state.Tex[i][I830_TEXREG_MCS]) {
160 I830_STATECHANGE(i830, I830_UPLOAD_TEX(i));
161 i830->state.Tex[i][I830_TEXREG_MCS] = mcs;
162 }
163
164 count++;
165 }
166 }
167
168 v0 |= VFT0_TEX_COUNT(count);
169 }
170
171 /* Only need to change the vertex emit code if there has been a
172 * statechange to a new hardware vertex format:
173 */
174 if (v0 != i830->state.Ctx[I830_CTXREG_VF] ||
175 v2 != i830->state.Ctx[I830_CTXREG_VF2] ||
176 mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] ||
177 !RENDERINPUTS_EQUAL(index_bitset, i830->last_index_bitset)) {
178 int k;
179
180 I830_STATECHANGE(i830, I830_UPLOAD_CTX);
181
182 /* Must do this *after* statechange, so as not to affect
183 * buffered vertices reliant on the old state:
184 */
185 intel->vertex_size =
186 _tnl_install_attrs(ctx,
187 intel->vertex_attrs,
188 intel->vertex_attr_count,
189 intel->ViewportMatrix.m, 0);
190
191 intel->vertex_size >>= 2;
192
193 i830->state.Ctx[I830_CTXREG_VF] = v0;
194 i830->state.Ctx[I830_CTXREG_VF2] = v2;
195 i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1;
196 RENDERINPUTS_COPY(i830->last_index_bitset, index_bitset);
197
198 k = i830_check_vertex_size(intel, intel->vertex_size);
199 assert(k);
200 }
201 }
202
203 static void
204 i830_reduced_primitive_state(struct intel_context *intel, GLenum rprim)
205 {
206 struct i830_context *i830 = i830_context(&intel->ctx);
207 GLuint st1 = i830->state.Stipple[I830_STPREG_ST1];
208
209 st1 &= ~ST1_ENABLE;
210
211 switch (rprim) {
212 case GL_TRIANGLES:
213 if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple)
214 st1 |= ST1_ENABLE;
215 break;
216 case GL_LINES:
217 case GL_POINTS:
218 default:
219 break;
220 }
221
222 i830->intel.reduced_primitive = rprim;
223
224 if (st1 != i830->state.Stipple[I830_STPREG_ST1]) {
225 INTEL_FIREVERTICES(intel);
226
227 I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE);
228 i830->state.Stipple[I830_STPREG_ST1] = st1;
229 }
230 }
231
232 /* Pull apart the vertex format registers and figure out how large a
233 * vertex is supposed to be.
234 */
235 static GLboolean
236 i830_check_vertex_size(struct intel_context *intel, GLuint expected)
237 {
238 struct i830_context *i830 = i830_context(&intel->ctx);
239 int vft0 = i830->current->Ctx[I830_CTXREG_VF];
240 int vft1 = i830->current->Ctx[I830_CTXREG_VF2];
241 int nrtex = (vft0 & VFT0_TEX_COUNT_MASK) >> VFT0_TEX_COUNT_SHIFT;
242 int i, sz = 0;
243
244 switch (vft0 & VFT0_XYZW_MASK) {
245 case VFT0_XY:
246 sz = 2;
247 break;
248 case VFT0_XYZ:
249 sz = 3;
250 break;
251 case VFT0_XYW:
252 sz = 3;
253 break;
254 case VFT0_XYZW:
255 sz = 4;
256 break;
257 default:
258 fprintf(stderr, "no xyzw specified\n");
259 return 0;
260 }
261
262 if (vft0 & VFT0_SPEC)
263 sz++;
264 if (vft0 & VFT0_DIFFUSE)
265 sz++;
266 if (vft0 & VFT0_DEPTH_OFFSET)
267 sz++;
268 if (vft0 & VFT0_POINT_WIDTH)
269 sz++;
270
271 for (i = 0; i < nrtex; i++) {
272 switch (vft1 & VFT1_TEX0_MASK) {
273 case TEXCOORDFMT_2D:
274 sz += 2;
275 break;
276 case TEXCOORDFMT_3D:
277 sz += 3;
278 break;
279 case TEXCOORDFMT_4D:
280 sz += 4;
281 break;
282 case TEXCOORDFMT_1D:
283 sz += 1;
284 break;
285 }
286 vft1 >>= VFT1_TEX1_SHIFT;
287 }
288
289 if (sz != expected)
290 fprintf(stderr, "vertex size mismatch %d/%d\n", sz, expected);
291
292 return sz == expected;
293 }
294
295 static void
296 i830_emit_invarient_state(struct intel_context *intel)
297 {
298 BATCH_LOCALS;
299
300 BEGIN_BATCH(40, IGNORE_CLIPRECTS);
301
302 OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
303 OUT_BATCH(0);
304
305 OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
306 OUT_BATCH(0);
307
308 OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
309 OUT_BATCH(0);
310
311 OUT_BATCH(_3DSTATE_FOG_MODE_CMD);
312 OUT_BATCH(FOGFUNC_ENABLE |
313 FOG_LINEAR_CONST | FOGSRC_INDEX_Z | ENABLE_FOG_DENSITY);
314 OUT_BATCH(0);
315 OUT_BATCH(0);
316
317
318 OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
319 MAP_UNIT(0) |
320 DISABLE_TEX_STREAM_BUMP |
321 ENABLE_TEX_STREAM_COORD_SET |
322 TEX_STREAM_COORD_SET(0) |
323 ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(0));
324 OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
325 MAP_UNIT(1) |
326 DISABLE_TEX_STREAM_BUMP |
327 ENABLE_TEX_STREAM_COORD_SET |
328 TEX_STREAM_COORD_SET(1) |
329 ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(1));
330 OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
331 MAP_UNIT(2) |
332 DISABLE_TEX_STREAM_BUMP |
333 ENABLE_TEX_STREAM_COORD_SET |
334 TEX_STREAM_COORD_SET(2) |
335 ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(2));
336 OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
337 MAP_UNIT(3) |
338 DISABLE_TEX_STREAM_BUMP |
339 ENABLE_TEX_STREAM_COORD_SET |
340 TEX_STREAM_COORD_SET(3) |
341 ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(3));
342
343 OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
344 OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(0));
345 OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
346 OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(1));
347 OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
348 OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(2));
349 OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
350 OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3));
351
352 OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
353 ENABLE_POINT_RASTER_RULE |
354 OGL_POINT_RASTER_RULE |
355 ENABLE_LINE_STRIP_PROVOKE_VRTX |
356 ENABLE_TRI_FAN_PROVOKE_VRTX |
357 ENABLE_TRI_STRIP_PROVOKE_VRTX |
358 LINE_STRIP_PROVOKE_VRTX(1) |
359 TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2));
360
361 OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
362 OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
363
364 OUT_BATCH(_3DSTATE_W_STATE_CMD);
365 OUT_BATCH(MAGIC_W_STATE_DWORD1);
366 OUT_BATCH(0x3f800000 /* 1.0 in IEEE float */ );
367
368
369 OUT_BATCH(_3DSTATE_COLOR_FACTOR_CMD);
370 OUT_BATCH(0x80808080); /* .5 required in alpha for GL_DOT3_RGBA_EXT */
371
372 ADVANCE_BATCH();
373 }
374
375
376 #define emit( intel, state, size ) \
377 intel_batchbuffer_data(intel->batch, state, size, IGNORE_CLIPRECTS )
378
379 static GLuint
380 get_dirty(struct i830_hw_state *state)
381 {
382 return state->active & ~state->emitted;
383 }
384
385 static GLuint
386 get_state_size(struct i830_hw_state *state)
387 {
388 GLuint dirty = get_dirty(state);
389 GLuint sz = 0;
390 GLuint i;
391
392 if (dirty & I830_UPLOAD_INVARIENT)
393 sz += 40 * sizeof(int);
394
395 if (dirty & I830_UPLOAD_CTX)
396 sz += sizeof(state->Ctx);
397
398 if (dirty & I830_UPLOAD_BUFFERS)
399 sz += sizeof(state->Buffer);
400
401 if (dirty & I830_UPLOAD_STIPPLE)
402 sz += sizeof(state->Stipple);
403
404 for (i = 0; i < I830_TEX_UNITS; i++) {
405 if ((dirty & I830_UPLOAD_TEX(i)))
406 sz += sizeof(state->Tex[i]);
407
408 if (dirty & I830_UPLOAD_TEXBLEND(i))
409 sz += state->TexBlendWordsUsed[i] * 4;
410 }
411
412 return sz;
413 }
414
415
416 /* Push the state into the sarea and/or texture memory.
417 */
418 static void
419 i830_emit_state(struct intel_context *intel)
420 {
421 struct i830_context *i830 = i830_context(&intel->ctx);
422 struct i830_hw_state *state = i830->current;
423 int i, count;
424 GLuint dirty;
425 GET_CURRENT_CONTEXT(ctx);
426 BATCH_LOCALS;
427 dri_bo *aper_array[3 + I830_TEX_UNITS];
428 int aper_count;
429
430 /* We don't hold the lock at this point, so want to make sure that
431 * there won't be a buffer wrap between the state emits and the primitive
432 * emit header.
433 *
434 * It might be better to talk about explicit places where
435 * scheduling is allowed, rather than assume that it is whenever a
436 * batchbuffer fills up.
437 *
438 * Set the space as LOOP_CLIPRECTS now, since that's what our primitives
439 * will be emitted under.
440 */
441 intel_batchbuffer_require_space(intel->batch,
442 get_state_size(state) + INTEL_PRIM_EMIT_SIZE,
443 LOOP_CLIPRECTS);
444 count = 0;
445 again:
446 aper_count = 0;
447 dirty = get_dirty(state);
448
449 aper_array[aper_count++] = intel->batch->buf;
450 if (dirty & I830_UPLOAD_BUFFERS) {
451 aper_array[aper_count++] = state->draw_region->buffer;
452 if (state->depth_region)
453 aper_array[aper_count++] = state->depth_region->buffer;
454 }
455
456 for (i = 0; i < I830_TEX_UNITS; i++)
457 if (dirty & I830_UPLOAD_TEX(i)) {
458 if (state->tex_buffer[i]) {
459 aper_array[aper_count++] = state->tex_buffer[i];
460 }
461 }
462
463 if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) {
464 if (count == 0) {
465 count++;
466 intel_batchbuffer_flush(intel->batch);
467 goto again;
468 } else {
469 _mesa_error(ctx, GL_OUT_OF_MEMORY, "i830 emit state");
470 assert(0);
471 }
472 }
473
474
475 /* Do this here as we may have flushed the batchbuffer above,
476 * causing more state to be dirty!
477 */
478 dirty = get_dirty(state);
479 state->emitted |= dirty;
480 assert(get_dirty(state) == 0);
481
482 if (dirty & I830_UPLOAD_INVARIENT) {
483 DBG("I830_UPLOAD_INVARIENT:\n");
484 i830_emit_invarient_state(intel);
485 }
486
487 if (dirty & I830_UPLOAD_CTX) {
488 DBG("I830_UPLOAD_CTX:\n");
489 emit(intel, state->Ctx, sizeof(state->Ctx));
490
491 }
492
493 if (dirty & I830_UPLOAD_BUFFERS) {
494 DBG("I830_UPLOAD_BUFFERS:\n");
495 BEGIN_BATCH(I830_DEST_SETUP_SIZE + 2, IGNORE_CLIPRECTS);
496 OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR0]);
497 OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR1]);
498 OUT_RELOC(state->draw_region->buffer,
499 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
500 state->draw_region->draw_offset);
501
502 if (state->depth_region) {
503 OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR0]);
504 OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR1]);
505 OUT_RELOC(state->depth_region->buffer,
506 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
507 state->depth_region->draw_offset);
508 }
509
510 OUT_BATCH(state->Buffer[I830_DESTREG_DV0]);
511 OUT_BATCH(state->Buffer[I830_DESTREG_DV1]);
512 OUT_BATCH(state->Buffer[I830_DESTREG_SENABLE]);
513 OUT_BATCH(state->Buffer[I830_DESTREG_SR0]);
514 OUT_BATCH(state->Buffer[I830_DESTREG_SR1]);
515 OUT_BATCH(state->Buffer[I830_DESTREG_SR2]);
516
517 if (intel->constant_cliprect) {
518 assert(state->Buffer[I830_DESTREG_DRAWRECT0] != MI_NOOP);
519 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT0]);
520 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT1]);
521 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT2]);
522 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT3]);
523 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT4]);
524 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT5]);
525 }
526 ADVANCE_BATCH();
527 }
528
529 if (dirty & I830_UPLOAD_STIPPLE) {
530 DBG("I830_UPLOAD_STIPPLE:\n");
531 emit(intel, state->Stipple, sizeof(state->Stipple));
532 }
533
534 for (i = 0; i < I830_TEX_UNITS; i++) {
535 if ((dirty & I830_UPLOAD_TEX(i))) {
536 DBG("I830_UPLOAD_TEX(%d):\n", i);
537
538 BEGIN_BATCH(I830_TEX_SETUP_SIZE + 1, IGNORE_CLIPRECTS);
539 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0LI]);
540
541 if (state->tex_buffer[i]) {
542 OUT_RELOC(state->tex_buffer[i],
543 I915_GEM_DOMAIN_SAMPLER, 0,
544 state->tex_offset[i] | TM0S0_USE_FENCE);
545 }
546 else if (state == &i830->meta) {
547 assert(i == 0);
548 OUT_BATCH(0);
549 }
550 else {
551 OUT_BATCH(state->tex_offset[i]);
552 }
553
554 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S1]);
555 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S2]);
556 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S3]);
557 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S4]);
558 OUT_BATCH(state->Tex[i][I830_TEXREG_MCS]);
559 OUT_BATCH(state->Tex[i][I830_TEXREG_CUBE]);
560 }
561
562 if (dirty & I830_UPLOAD_TEXBLEND(i)) {
563 DBG("I830_UPLOAD_TEXBLEND(%d): %d words\n", i,
564 state->TexBlendWordsUsed[i]);
565 emit(intel, state->TexBlend[i], state->TexBlendWordsUsed[i] * 4);
566 }
567 }
568
569 intel->batch->dirty_state &= ~dirty;
570 assert(get_dirty(state) == 0);
571 assert((intel->batch->dirty_state & (1<<1)) == 0);
572 }
573
574 static void
575 i830_destroy_context(struct intel_context *intel)
576 {
577 GLuint i;
578 struct i830_context *i830 = i830_context(&intel->ctx);
579
580 intel_region_release(&i830->state.draw_region);
581 intel_region_release(&i830->state.depth_region);
582 intel_region_release(&i830->meta.draw_region);
583 intel_region_release(&i830->meta.depth_region);
584 intel_region_release(&i830->initial.draw_region);
585 intel_region_release(&i830->initial.depth_region);
586
587 for (i = 0; i < I830_TEX_UNITS; i++) {
588 if (i830->state.tex_buffer[i] != NULL) {
589 dri_bo_unreference(i830->state.tex_buffer[i]);
590 i830->state.tex_buffer[i] = NULL;
591 }
592 }
593
594 _tnl_free_vertices(&intel->ctx);
595 }
596
597
598 void
599 i830_state_draw_region(struct intel_context *intel,
600 struct i830_hw_state *state,
601 struct intel_region *color_region,
602 struct intel_region *depth_region)
603 {
604 struct i830_context *i830 = i830_context(&intel->ctx);
605 GLcontext *ctx = &intel->ctx;
606 GLuint value;
607
608 ASSERT(state == &i830->state || state == &i830->meta);
609
610 if (state->draw_region != color_region) {
611 intel_region_release(&state->draw_region);
612 intel_region_reference(&state->draw_region, color_region);
613 }
614 if (state->depth_region != depth_region) {
615 intel_region_release(&state->depth_region);
616 intel_region_reference(&state->depth_region, depth_region);
617 }
618
619 /*
620 * Set stride/cpp values
621 */
622 if (color_region) {
623 state->Buffer[I830_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
624 state->Buffer[I830_DESTREG_CBUFADDR1] =
625 (BUF_3D_ID_COLOR_BACK |
626 BUF_3D_PITCH(color_region->pitch * color_region->cpp) |
627 BUF_3D_USE_FENCE);
628 }
629
630 if (depth_region) {
631 state->Buffer[I830_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
632 state->Buffer[I830_DESTREG_DBUFADDR1] =
633 (BUF_3D_ID_DEPTH |
634 BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) |
635 BUF_3D_USE_FENCE);
636 }
637
638 /*
639 * Compute/set I830_DESTREG_DV1 value
640 */
641 value = (DSTORG_HORT_BIAS(0x8) | /* .5 */
642 DSTORG_VERT_BIAS(0x8) | DEPTH_IS_Z); /* .5 */
643
644 if (color_region && color_region->cpp == 4) {
645 value |= DV_PF_8888;
646 }
647 else {
648 value |= DV_PF_565;
649 }
650 if (depth_region && depth_region->cpp == 4) {
651 value |= DEPTH_FRMT_24_FIXED_8_OTHER;
652 }
653 else {
654 value |= DEPTH_FRMT_16_FIXED;
655 }
656 state->Buffer[I830_DESTREG_DV1] = value;
657
658 if (intel->constant_cliprect) {
659 state->Buffer[I830_DESTREG_DRAWRECT0] = _3DSTATE_DRAWRECT_INFO;
660 state->Buffer[I830_DESTREG_DRAWRECT1] = 0;
661 state->Buffer[I830_DESTREG_DRAWRECT2] = 0; /* xmin, ymin */
662 state->Buffer[I830_DESTREG_DRAWRECT3] =
663 (ctx->DrawBuffer->Width & 0xffff) |
664 (ctx->DrawBuffer->Height << 16);
665 state->Buffer[I830_DESTREG_DRAWRECT4] = 0; /* xoff, yoff */
666 state->Buffer[I830_DESTREG_DRAWRECT5] = 0;
667 } else {
668 state->Buffer[I830_DESTREG_DRAWRECT0] = MI_NOOP;
669 state->Buffer[I830_DESTREG_DRAWRECT1] = MI_NOOP;
670 state->Buffer[I830_DESTREG_DRAWRECT2] = MI_NOOP;
671 state->Buffer[I830_DESTREG_DRAWRECT3] = MI_NOOP;
672 state->Buffer[I830_DESTREG_DRAWRECT4] = MI_NOOP;
673 state->Buffer[I830_DESTREG_DRAWRECT5] = MI_NOOP;
674 }
675
676 I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
677
678
679 }
680
681
682 static void
683 i830_set_draw_region(struct intel_context *intel,
684 struct intel_region *color_regions[],
685 struct intel_region *depth_region,
686 GLuint num_regions)
687 {
688 struct i830_context *i830 = i830_context(&intel->ctx);
689 i830_state_draw_region(intel, &i830->state, color_regions[0], depth_region);
690 }
691
692 #if 0
693 static void
694 i830_update_color_z_regions(intelContextPtr intel,
695 const intelRegion * colorRegion,
696 const intelRegion * depthRegion)
697 {
698 i830ContextPtr i830 = I830_CONTEXT(intel);
699
700 i830->state.Buffer[I830_DESTREG_CBUFADDR1] =
701 (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) |
702 BUF_3D_USE_FENCE);
703 i830->state.Buffer[I830_DESTREG_CBUFADDR2] = colorRegion->offset;
704
705 i830->state.Buffer[I830_DESTREG_DBUFADDR1] =
706 (BUF_3D_ID_DEPTH | BUF_3D_PITCH(depthRegion->pitch) | BUF_3D_USE_FENCE);
707 i830->state.Buffer[I830_DESTREG_DBUFADDR2] = depthRegion->offset;
708 }
709 #endif
710
711
712 /* This isn't really handled at the moment.
713 */
714 static void
715 i830_new_batch(struct intel_context *intel)
716 {
717 struct i830_context *i830 = i830_context(&intel->ctx);
718 i830->state.emitted = 0;
719
720 /* Check that we didn't just wrap our batchbuffer at a bad time. */
721 assert(!intel->no_batch_wrap);
722 }
723
724
725
726 static GLuint
727 i830_flush_cmd(void)
728 {
729 return MI_FLUSH | FLUSH_MAP_CACHE;
730 }
731
732
733 static void
734 i830_assert_not_dirty( struct intel_context *intel )
735 {
736 struct i830_context *i830 = i830_context(&intel->ctx);
737 struct i830_hw_state *state = i830->current;
738 assert(!get_dirty(state));
739 }
740
741 static void
742 i830_note_unlock( struct intel_context *intel )
743 {
744 /* nothing */
745 }
746
747 void
748 i830InitVtbl(struct i830_context *i830)
749 {
750 i830->intel.vtbl.check_vertex_size = i830_check_vertex_size;
751 i830->intel.vtbl.destroy = i830_destroy_context;
752 i830->intel.vtbl.emit_state = i830_emit_state;
753 i830->intel.vtbl.new_batch = i830_new_batch;
754 i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state;
755 i830->intel.vtbl.set_draw_region = i830_set_draw_region;
756 i830->intel.vtbl.update_texture_state = i830UpdateTextureState;
757 i830->intel.vtbl.flush_cmd = i830_flush_cmd;
758 i830->intel.vtbl.render_start = i830_render_start;
759 i830->intel.vtbl.render_prevalidate = i830_render_prevalidate;
760 i830->intel.vtbl.assert_not_dirty = i830_assert_not_dirty;
761 i830->intel.vtbl.note_unlock = i830_note_unlock;
762 i830->intel.vtbl.finish_batch = intel_finish_vb;
763 }