Add support for GLX_SGI_make_current_read.
[mesa.git] / src / mesa / drivers / dri / i830 / i830_texstate.c
1 /**************************************************************************
2
3 Copyright 2001 2d3d Inc., Delray Beach, FL
4
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_texstate.c,v 1.3 2002/12/10 01:26:53 dawes Exp $ */
29
30 /**
31 * \file i830_texstate.c
32 *
33 * Heavily based on the I810 driver, which was written by Keith Whitwell.
34 *
35 * \author Jeff Hartmann <jhartmann@2d3d.com>
36 * \author Keith Whitwell <keithw@tungstengraphics.com>
37 */
38
39 #include "glheader.h"
40 #include "macros.h"
41 #include "mtypes.h"
42 #include "simple_list.h"
43 #include "enums.h"
44 #include "texformat.h"
45 #include "texstore.h"
46
47 #include "mm.h"
48
49 #include "i830_screen.h"
50 #include "i830_dri.h"
51
52 #include "i830_context.h"
53 #include "i830_tex.h"
54 #include "i830_state.h"
55 #include "i830_ioctl.h"
56
57 #define I830_TEX_UNIT_ENABLED(unit) (1<<unit)
58
59 static void i830SetTexImages( i830ContextPtr imesa,
60 struct gl_texture_object *tObj )
61 {
62 GLuint total_height, pitch, i, textureFormat;
63 i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
64 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
65 GLint numLevels;
66
67 switch( baseImage->TexFormat->MesaFormat ) {
68 case MESA_FORMAT_L8:
69 t->texelBytes = 1;
70 textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
71 break;
72
73 case MESA_FORMAT_I8:
74 t->texelBytes = 1;
75 textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
76 break;
77
78 case MESA_FORMAT_AL88:
79 t->texelBytes = 2;
80 textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
81 break;
82
83 case MESA_FORMAT_RGB565:
84 t->texelBytes = 2;
85 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
86 break;
87
88 case MESA_FORMAT_ARGB1555:
89 t->texelBytes = 2;
90 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
91 break;
92
93 case MESA_FORMAT_ARGB4444:
94 t->texelBytes = 2;
95 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
96 break;
97
98 case MESA_FORMAT_ARGB8888:
99 t->texelBytes = 4;
100 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
101 break;
102
103 case MESA_FORMAT_YCBCR_REV:
104 t->texelBytes = 2;
105 textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL |
106 TM0S1_COLORSPACE_CONVERSION);
107 break;
108
109 case MESA_FORMAT_YCBCR:
110 t->texelBytes = 2;
111 textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */
112 TM0S1_COLORSPACE_CONVERSION);
113 break;
114
115 default:
116 fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
117 free( t );
118 return;
119 }
120
121 /* Compute which mipmap levels we really want to send to the hardware.
122 */
123
124 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
125
126
127 /* Figure out the amount of memory required to hold all the mipmap
128 * levels. Choose the smallest pitch to accomodate the largest
129 * mipmap:
130 */
131 numLevels = t->base.lastLevel - t->base.firstLevel + 1;
132
133 /* Pitch would be subject to additional rules if texture memory were
134 * tiled. Currently it isn't.
135 */
136 if (0) {
137 pitch = 128;
138 while (pitch < tObj->Image[0][t->base.firstLevel]->Width * t->texelBytes)
139 pitch *= 2;
140 }
141 else {
142 pitch = tObj->Image[0][t->base.firstLevel]->Width * t->texelBytes;
143 pitch = (pitch + 3) & ~3;
144 }
145
146
147 /* All images must be loaded at this pitch. Count the number of
148 * lines required:
149 */
150 for ( total_height = i = 0 ; i < numLevels ; i++ ) {
151 t->image[0][i].image = tObj->Image[0][t->base.firstLevel + i];
152 if (!t->image[0][i].image)
153 break;
154
155 t->image[0][i].offset = total_height * pitch;
156 t->image[0][i].internalFormat = baseImage->Format;
157 total_height += t->image[0][i].image->Height;
158 }
159
160 t->Pitch = pitch;
161 t->base.totalSize = total_height*pitch;
162 t->Setup[I830_TEXREG_TM0S1] =
163 (((tObj->Image[0][t->base.firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) |
164 ((tObj->Image[0][t->base.firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) |
165 textureFormat);
166 t->Setup[I830_TEXREG_TM0S2] =
167 ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));
168 t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
169 t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
170 t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
171 t->dirty = I830_UPLOAD_TEX0 | I830_UPLOAD_TEX1
172 | I830_UPLOAD_TEX2 | I830_UPLOAD_TEX3;
173
174 LOCK_HARDWARE( imesa );
175 i830UploadTexImagesLocked( imesa, t );
176 UNLOCK_HARDWARE( imesa );
177 }
178
179 /* ================================================================
180 * Texture combine functions
181 */
182
183
184 /**
185 * Calculate the hardware instuctions to setup the current texture enviromnemt
186 * settings. Since \c gl_texture_unit::_CurrentCombine is used, both
187 * "classic" texture enviroments and GL_ARB_texture_env_combine type texture
188 * environments are treated identically.
189 *
190 * \todo
191 * This function should return \c GLboolean. When \c GL_FALSE is returned,
192 * it means that an environment is selected that the hardware cannot do. This
193 * is the way the Radeon and R200 drivers work.
194 *
195 * \todo
196 * Looking at i830_3d_regs.h, it seems the i830 can do part of
197 * GL_ATI_texture_env_combine3. It can handle using \c GL_ONE and
198 * \c GL_ZERO as combine inputs (which the code already supports). It can
199 * also handle the \c GL_MODULATE_ADD_ATI mode. Is it worth investigating
200 * partial support for the extension?
201 *
202 * \todo
203 * Some thought needs to be put into the way combiners work. The driver
204 * treats the hardware as if there's a specific combine unit tied to each
205 * texture unit. That's why there's the special case for a disabled texture
206 * unit. That's not the way the hardware works. In reality, there are 4
207 * texture units and four general instruction slots. Each instruction slot
208 * can use any texture as an input. There's no need for this wierd "no-op"
209 * stuff. If texture units 0 and 3 are enabled, the instructions to combine
210 * them should be in slots 0 and 1, not 0 and 3 with two no-ops inbetween.
211 */
212
213 static void i830UpdateTexEnv( GLcontext *ctx, GLuint unit )
214 {
215 i830ContextPtr imesa = I830_CONTEXT(ctx);
216 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
217 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
218 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
219
220 GLboolean need_constant_color = GL_FALSE;
221 GLuint blendop;
222 GLuint ablendop;
223 GLuint args_RGB[3];
224 GLuint args_A[3];
225 GLuint rgb_shift = texUnit->Combine.ScaleShiftRGB;
226 GLuint alpha_shift = texUnit->Combine.ScaleShiftA;
227 int i;
228 unsigned used;
229 static const GLuint tex_blend_rgb[3] = {
230 TEXPIPE_COLOR | TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS,
231 TEXPIPE_COLOR | TEXBLEND_ARG2 | TEXBLENDARG_MODIFY_PARMS,
232 TEXPIPE_COLOR | TEXBLEND_ARG0 | TEXBLENDARG_MODIFY_PARMS,
233 };
234 static const GLuint tex_blend_a[3] = {
235 TEXPIPE_ALPHA | TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS,
236 TEXPIPE_ALPHA | TEXBLEND_ARG2 | TEXBLENDARG_MODIFY_PARMS,
237 TEXPIPE_ALPHA | TEXBLEND_ARG0 | TEXBLENDARG_MODIFY_PARMS,
238 };
239 static const GLuint op_rgb[4] = {
240 0,
241 TEXBLENDARG_INV_ARG,
242 TEXBLENDARG_REPLICATE_ALPHA,
243 TEXBLENDARG_REPLICATE_ALPHA | TEXBLENDARG_INV_ARG,
244 };
245
246
247
248 imesa->TexBlendWordsUsed[unit] = 0;
249
250 if(I830_DEBUG&DEBUG_TEXTURE)
251 fprintf(stderr, "[%s:%u] env. mode = %s\n", __FUNCTION__, __LINE__,
252 _mesa_lookup_enum_by_nr(texUnit->EnvMode));
253
254
255 if ( !texUnit->_ReallyEnabled ) {
256 imesa->TexBlend[unit][0] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
257 TEXPIPE_COLOR |
258 ENABLE_TEXOUTPUT_WRT_SEL |
259 TEXOP_OUTPUT_CURRENT |
260 DISABLE_TEX_CNTRL_STAGE |
261 TEXOP_SCALE_1X |
262 TEXOP_MODIFY_PARMS |
263 TEXBLENDOP_ARG1);
264 imesa->TexBlend[unit][1] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
265 TEXPIPE_ALPHA |
266 ENABLE_TEXOUTPUT_WRT_SEL |
267 TEXOP_OUTPUT_CURRENT |
268 TEXOP_SCALE_1X |
269 TEXOP_MODIFY_PARMS |
270 TEXBLENDOP_ARG1);
271 imesa->TexBlend[unit][2] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
272 TEXPIPE_COLOR |
273 TEXBLEND_ARG1 |
274 TEXBLENDARG_MODIFY_PARMS |
275 TEXBLENDARG_CURRENT);
276 imesa->TexBlend[unit][3] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
277 TEXPIPE_ALPHA |
278 TEXBLEND_ARG1 |
279 TEXBLENDARG_MODIFY_PARMS |
280 TEXBLENDARG_CURRENT);
281 imesa->TexBlendColorPipeNum[unit] = 0;
282 imesa->TexBlendWordsUsed[unit] = 4;
283 }
284 else {
285 switch(texUnit->_CurrentCombine->ModeRGB) {
286 case GL_REPLACE:
287 blendop = TEXBLENDOP_ARG1;
288 break;
289 case GL_MODULATE:
290 blendop = TEXBLENDOP_MODULATE;
291 break;
292 case GL_ADD:
293 blendop = TEXBLENDOP_ADD;
294 break;
295 case GL_ADD_SIGNED:
296 blendop = TEXBLENDOP_ADDSIGNED;
297 break;
298 case GL_INTERPOLATE:
299 blendop = TEXBLENDOP_BLEND;
300 break;
301 case GL_SUBTRACT:
302 blendop = TEXBLENDOP_SUBTRACT;
303 break;
304 case GL_DOT3_RGB_EXT:
305 case GL_DOT3_RGBA_EXT:
306 /* The EXT version of the DOT3 extension does not support the
307 * scale factor, but the ARB version (and the version in OpenGL
308 * 1.3) does.
309 */
310 rgb_shift = 0;
311 alpha_shift = 0;
312 /* FALLTHROUGH */
313
314 case GL_DOT3_RGB:
315 case GL_DOT3_RGBA:
316 blendop = TEXBLENDOP_DOT3;
317 break;
318 default:
319 return;
320 }
321
322 blendop |= (rgb_shift << TEXOP_SCALE_SHIFT);
323
324 switch(texUnit->_CurrentCombine->ModeA) {
325 case GL_REPLACE:
326 ablendop = TEXBLENDOP_ARG1;
327 break;
328 case GL_MODULATE:
329 ablendop = TEXBLENDOP_MODULATE;
330 break;
331 case GL_ADD:
332 ablendop = TEXBLENDOP_ADD;
333 break;
334 case GL_ADD_SIGNED:
335 ablendop = TEXBLENDOP_ADDSIGNED;
336 break;
337 case GL_INTERPOLATE:
338 ablendop = TEXBLENDOP_BLEND;
339 break;
340 case GL_SUBTRACT:
341 ablendop = TEXBLENDOP_SUBTRACT;
342 break;
343 default:
344 return;
345 }
346
347 if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT)
348 || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) {
349 ablendop = TEXBLENDOP_DOT3;
350 }
351
352 ablendop |= (alpha_shift << TEXOP_SCALE_SHIFT);
353
354 /* Handle RGB args */
355 for( i = 0 ; i < numColorArgs ; i++ ) {
356 const int op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
357
358 assert( (op >= 0) && (op <= 3) );
359 switch(texUnit->_CurrentCombine->SourceRGB[i]) {
360 case GL_TEXTURE:
361 args_RGB[i] = TEXBLENDARG_TEXEL0 + unit;
362 break;
363 case GL_TEXTURE0:
364 case GL_TEXTURE1:
365 case GL_TEXTURE2:
366 case GL_TEXTURE3:
367 args_RGB[i] = TEXBLENDARG_TEXEL0
368 + (texUnit->_CurrentCombine->SourceRGB[i] & 0x03);
369 break;
370 case GL_CONSTANT:
371 args_RGB[i] = TEXBLENDARG_FACTOR_N;
372 need_constant_color = GL_TRUE;
373 break;
374 case GL_PRIMARY_COLOR:
375 args_RGB[i] = TEXBLENDARG_DIFFUSE;
376 break;
377 case GL_PREVIOUS:
378 args_RGB[i] = TEXBLENDARG_CURRENT;
379 break;
380 case GL_ONE:
381 args_RGB[i] = TEXBLENDARG_ONE;
382 break;
383 case GL_ZERO:
384 args_RGB[i] = TEXBLENDARG_ONE | TEXBLENDARG_INV_ARG;
385 break;
386 default:
387 return;
388 }
389
390 /* Xor is used so that GL_ONE_MINUS_SRC_COLOR with GL_ZERO
391 * works correctly.
392 */
393 args_RGB[i] ^= op_rgb[op];
394 }
395
396 /* Handle A args */
397 for( i = 0 ; i < numAlphaArgs ; i++ ) {
398 const int op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
399
400 assert( (op >= 0) && (op <= 1) );
401 switch(texUnit->_CurrentCombine->SourceA[i]) {
402 case GL_TEXTURE:
403 args_A[i] = TEXBLENDARG_TEXEL0 + unit;
404 break;
405 case GL_TEXTURE0:
406 case GL_TEXTURE1:
407 case GL_TEXTURE2:
408 case GL_TEXTURE3:
409 args_A[i] = TEXBLENDARG_TEXEL0
410 + (texUnit->_CurrentCombine->SourceA[i] & 0x03);
411 break;
412 case GL_CONSTANT:
413 args_A[i] = TEXBLENDARG_FACTOR_N;
414 need_constant_color = GL_TRUE;
415 break;
416 case GL_PRIMARY_COLOR:
417 args_A[i] = TEXBLENDARG_DIFFUSE;
418 break;
419 case GL_PREVIOUS:
420 args_A[i] = TEXBLENDARG_CURRENT;
421 break;
422 case GL_ONE:
423 args_A[i] = TEXBLENDARG_ONE;
424 break;
425 case GL_ZERO:
426 args_A[i] = TEXBLENDARG_ONE | TEXBLENDARG_INV_ARG;
427 break;
428 default:
429 return;
430 }
431
432 /* We cheat. :) The register values for this are the same as for
433 * RGB. Xor is used so that GL_ONE_MINUS_SRC_ALPHA with GL_ZERO
434 * works correctly.
435 */
436 args_A[i] ^= op_rgb[op];
437 }
438
439 /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */
440 /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */
441 /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */
442
443 /* When we render we need to figure out which is the last really enabled
444 * tex unit, and put last stage on it
445 */
446
447 imesa->TexBlendColorPipeNum[unit] = 0;
448 used = 0;
449
450 /* Build color pipeline */
451
452 imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
453 TEXPIPE_COLOR |
454 ENABLE_TEXOUTPUT_WRT_SEL |
455 TEXOP_OUTPUT_CURRENT |
456 DISABLE_TEX_CNTRL_STAGE |
457 TEXOP_MODIFY_PARMS |
458 blendop);
459
460 imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
461 TEXPIPE_ALPHA |
462 ENABLE_TEXOUTPUT_WRT_SEL |
463 TEXOP_OUTPUT_CURRENT |
464 TEXOP_MODIFY_PARMS |
465 ablendop);
466
467 for ( i = 0 ; i < numColorArgs ; i++ ) {
468 imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
469 tex_blend_rgb[i] |
470 args_RGB[i]);
471 }
472
473 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
474 imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
475 tex_blend_a[i] |
476 args_A[i]);
477 }
478
479
480 if ( need_constant_color ) {
481 GLubyte r, g, b, a;
482 const GLfloat * const fc = texUnit->EnvColor;
483
484 FLOAT_COLOR_TO_UBYTE_COLOR(r, fc[RCOMP]);
485 FLOAT_COLOR_TO_UBYTE_COLOR(g, fc[GCOMP]);
486 FLOAT_COLOR_TO_UBYTE_COLOR(b, fc[BCOMP]);
487 FLOAT_COLOR_TO_UBYTE_COLOR(a, fc[ACOMP]);
488
489 imesa->TexBlend[unit][used++] = STATE3D_COLOR_FACTOR_CMD(unit);
490 imesa->TexBlend[unit][used++] = ((a << 24) | (r << 16) | (g << 8) | b);
491 }
492
493 imesa->TexBlendWordsUsed[unit] = used;
494 }
495
496 I830_STATECHANGE( imesa, I830_UPLOAD_TEXBLEND_N(unit) );
497 }
498
499
500 /* This is bogus -- can't load the same texture object on two units.
501 */
502 static void i830TexSetUnit( i830TextureObjectPtr t, GLuint unit )
503 {
504 if(I830_DEBUG&DEBUG_TEXTURE)
505 fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
506
507 t->Setup[I830_TEXREG_TM0LI] = (STATE3D_LOAD_STATE_IMMEDIATE_2 |
508 (LOAD_TEXTURE_MAP0 << unit) | 4);
509
510 I830_SET_FIELD(t->Setup[I830_TEXREG_MCS], MAP_UNIT_MASK, MAP_UNIT(unit));
511
512 t->current_unit = unit;
513 t->base.bound |= (1U << unit);
514 }
515
516 #define TEXCOORDTYPE_MASK (~((1<<13)|(1<<12)|(1<<11)))
517
518
519 static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
520 {
521 i830ContextPtr imesa = I830_CONTEXT(ctx);
522 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
523 struct gl_texture_object *tObj = texUnit->_Current;
524 i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
525
526 /* Fallback if there's a texture border */
527 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
528 return GL_FALSE;
529 }
530
531 /* Upload teximages (not pipelined)
532 */
533 if (t->base.dirty_images[0]) {
534 i830SetTexImages( imesa, tObj );
535 if (!t->base.memBlock) {
536 return GL_FALSE;
537 }
538 }
539
540 /* Update state if this is a different texture object to last
541 * time.
542 */
543 if (imesa->CurrentTexObj[unit] != t) {
544
545 if ( imesa->CurrentTexObj[unit] != NULL ) {
546 /* The old texture is no longer bound to this texture unit.
547 * Mark it as such.
548 */
549
550 imesa->CurrentTexObj[unit]->base.bound &= ~(1U << unit);
551 }
552
553 I830_STATECHANGE( imesa, I830_UPLOAD_TEX_N(unit) );
554 imesa->CurrentTexObj[unit] = t;
555 i830TexSetUnit(t, unit);
556 }
557
558 /* Update texture environment if texture object image format or
559 * texture environment state has changed.
560 *
561 * KW: doesn't work -- change from tex0 only to tex0+tex1 gets
562 * missed (need to update last stage flag?). Call
563 * i830UpdateTexEnv always.
564 */
565 if (tObj->Image[0][tObj->BaseLevel]->Format !=
566 imesa->TexEnvImageFmt[unit]) {
567 imesa->TexEnvImageFmt[unit] = tObj->Image[0][tObj->BaseLevel]->Format;
568 }
569 i830UpdateTexEnv( ctx, unit );
570 imesa->TexEnabledMask |= I830_TEX_UNIT_ENABLED(unit);
571
572 return GL_TRUE;
573 }
574
575 static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
576 {
577 i830ContextPtr imesa = I830_CONTEXT(ctx);
578 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
579 struct gl_texture_object *tObj = texUnit->_Current;
580 i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
581 GLuint mcs = t->Setup[I830_TEXREG_MCS];
582
583 mcs &= ~TEXCOORDS_ARE_NORMAL;
584 mcs |= TEXCOORDS_ARE_IN_TEXELUNITS;
585
586 if (mcs != t->Setup[I830_TEXREG_MCS]) {
587 I830_STATECHANGE( imesa, I830_UPLOAD_TEX_N(unit) );
588 t->Setup[I830_TEXREG_MCS] = mcs;
589 }
590
591 return GL_TRUE;
592 }
593
594
595 static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
596 {
597 i830ContextPtr imesa = I830_CONTEXT(ctx);
598 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
599 struct gl_texture_object *tObj = texUnit->_Current;
600 i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
601 GLuint mcs = t->Setup[I830_TEXREG_MCS];
602
603 mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
604 mcs |= TEXCOORDS_ARE_NORMAL;
605
606 if (mcs != t->Setup[I830_TEXREG_MCS]) {
607 I830_STATECHANGE( imesa, I830_UPLOAD_TEX_N(unit) );
608 t->Setup[I830_TEXREG_MCS] = mcs;
609 }
610
611 return GL_TRUE;
612 }
613
614
615 static GLboolean disable_tex( GLcontext *ctx, int unit )
616 {
617 i830ContextPtr imesa = I830_CONTEXT(ctx);
618
619 /* This is happening too often. I need to conditionally send diffuse
620 * state to the card. Perhaps a diffuse dirty flag of some kind.
621 * Will need to change this logic if more than 2 texture units are
622 * used. We need to only do this up to the last unit enabled, or unit
623 * one if nothing is enabled.
624 */
625
626 if ( imesa->CurrentTexObj[unit] != NULL ) {
627 /* The old texture is no longer bound to this texture unit.
628 * Mark it as such.
629 */
630
631 imesa->CurrentTexObj[unit]->base.bound &= ~(1U << unit);
632 imesa->CurrentTexObj[unit] = NULL;
633 }
634
635 imesa->TexEnvImageFmt[unit] = 0;
636 imesa->dirty &= ~(I830_UPLOAD_TEX_N(unit));
637
638 i830UpdateTexEnv( ctx, unit );
639
640 return GL_TRUE;
641 }
642
643 static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
644 {
645 i830ContextPtr imesa = I830_CONTEXT(ctx);
646 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
647
648 imesa->TexEnabledMask &= ~(I830_TEX_UNIT_ENABLED(unit));
649
650 if (texUnit->_ReallyEnabled == TEXTURE_2D_BIT) {
651 return (enable_tex_common( ctx, unit ) &&
652 enable_tex_2d( ctx, unit ));
653 }
654 else if (texUnit->_ReallyEnabled == TEXTURE_RECT_BIT) {
655 return (enable_tex_common( ctx, unit ) &&
656 enable_tex_rect( ctx, unit ));
657 }
658 else if (texUnit->_ReallyEnabled) {
659 return GL_FALSE;
660 }
661 else {
662 disable_tex( ctx, unit );
663 return GL_TRUE;
664 }
665 }
666
667
668
669 /* Only deal with unit 0 and 1 for right now */
670 void i830UpdateTextureState( GLcontext *ctx )
671 {
672 i830ContextPtr imesa = I830_CONTEXT(ctx);
673 int pipe_num = 0;
674 GLboolean ok;
675
676 ok = (i830UpdateTexUnit( ctx, 0 ) &&
677 i830UpdateTexUnit( ctx, 1 ) &&
678 i830UpdateTexUnit( ctx, 2 ) &&
679 i830UpdateTexUnit( ctx, 3 ));
680
681 FALLBACK( imesa, I830_FALLBACK_TEXTURE, !ok );
682
683
684 /* Make sure last stage is set correctly */
685 if(imesa->TexEnabledMask & I830_TEX_UNIT_ENABLED(3)) {
686 pipe_num = imesa->TexBlendColorPipeNum[3];
687 imesa->TexBlend[3][pipe_num] |= TEXOP_LAST_STAGE;
688 } else if(imesa->TexEnabledMask & I830_TEX_UNIT_ENABLED(2)) {
689 pipe_num = imesa->TexBlendColorPipeNum[2];
690 imesa->TexBlend[2][pipe_num] |= TEXOP_LAST_STAGE;
691 } else if(imesa->TexEnabledMask & I830_TEX_UNIT_ENABLED(1)) {
692 pipe_num = imesa->TexBlendColorPipeNum[1];
693 imesa->TexBlend[1][pipe_num] |= TEXOP_LAST_STAGE;
694 } else {
695 pipe_num = imesa->TexBlendColorPipeNum[0];
696 imesa->TexBlend[0][pipe_num] |= TEXOP_LAST_STAGE;
697 }
698 }