Add Roland Scheidegger's S3TC patch. This patch does not implement the
[mesa.git] / src / mesa / drivers / dri / i915 / i915_texstate.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 "glheader.h"
29 #include "macros.h"
30 #include "mtypes.h"
31 #include "simple_list.h"
32 #include "enums.h"
33 #include "texformat.h"
34 #include "texstore.h"
35
36 #include "mm.h"
37
38 #include "intel_screen.h"
39 #include "intel_ioctl.h"
40 #include "intel_tex.h"
41
42 #include "i915_context.h"
43 #include "i915_reg.h"
44
45 static GLint initial_offsets[6][2] = { {0,0},
46 {0,2},
47 {1,0},
48 {1,2},
49 {1,1},
50 {1,3} };
51
52
53 static GLint step_offsets[6][2] = { {0,2},
54 {0,2},
55 {-1,2},
56 {-1,2},
57 {-1,1},
58 {-1,1} };
59
60
61 #define I915_TEX_UNIT_ENABLED(unit) (1<<unit)
62
63 static void i915SetTexImages( i915ContextPtr i915,
64 struct gl_texture_object *tObj )
65 {
66 GLuint total_height, pitch, i, textureFormat;
67 i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
68 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
69 GLint firstLevel, lastLevel, numLevels;
70 GLint ss2 = 0;
71
72 switch( baseImage->TexFormat->MesaFormat ) {
73 case MESA_FORMAT_L8:
74 t->intel.texelBytes = 1;
75 textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
76 break;
77
78 case MESA_FORMAT_I8:
79 t->intel.texelBytes = 1;
80 textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
81 break;
82
83 case MESA_FORMAT_A8:
84 t->intel.texelBytes = 1;
85 textureFormat = MAPSURF_8BIT | MT_8BIT_A8;
86 break;
87
88 case MESA_FORMAT_AL88:
89 t->intel.texelBytes = 2;
90 textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
91 break;
92
93 case MESA_FORMAT_RGB565:
94 t->intel.texelBytes = 2;
95 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
96 break;
97
98 case MESA_FORMAT_ARGB1555:
99 t->intel.texelBytes = 2;
100 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
101 break;
102
103 case MESA_FORMAT_ARGB4444:
104 t->intel.texelBytes = 2;
105 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
106 break;
107
108 case MESA_FORMAT_ARGB8888:
109 t->intel.texelBytes = 4;
110 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
111 break;
112
113 case MESA_FORMAT_YCBCR_REV:
114 t->intel.texelBytes = 2;
115 textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL);
116 ss2 |= SS2_COLORSPACE_CONVERSION;
117 break;
118
119 case MESA_FORMAT_YCBCR:
120 t->intel.texelBytes = 2;
121 textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY);
122 ss2 |= SS2_COLORSPACE_CONVERSION;
123 break;
124
125 case MESA_FORMAT_RGB_FXT1:
126 case MESA_FORMAT_RGBA_FXT1:
127 t->intel.texelBytes = 2;
128 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
129 break;
130 case MESA_FORMAT_RGBA_DXT1:
131 case MESA_FORMAT_RGB_DXT1:
132 /*
133 * DXTn pitches are Width/4 * blocksize in bytes
134 * for DXT1: blocksize=8 so Width/4*8 = Width * 2
135 * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
136 */
137 t->intel.texelBytes = 2;
138 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
139 break;
140 case MESA_FORMAT_RGBA_DXT3:
141 t->intel.texelBytes = 4;
142 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
143 break;
144 case MESA_FORMAT_RGBA_DXT5:
145 t->intel.texelBytes = 4;
146 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
147 break;
148
149 default:
150 fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
151 abort();
152 }
153
154 /* Compute which mipmap levels we really want to send to the hardware.
155 */
156 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
157
158
159 /* Figure out the amount of memory required to hold all the mipmap
160 * levels. Choose the smallest pitch to accomodate the largest
161 * mipmap:
162 */
163 firstLevel = t->intel.base.firstLevel;
164 lastLevel = t->intel.base.lastLevel;
165 numLevels = lastLevel - firstLevel + 1;
166
167
168
169 /* All images must be loaded at this pitch. Count the number of
170 * lines required:
171 */
172 switch (tObj->Target) {
173 case GL_TEXTURE_CUBE_MAP: {
174 const GLuint dim = tObj->Image[0][firstLevel]->Width;
175 GLuint face;
176
177 pitch = dim * t->intel.texelBytes;
178 pitch *= 2; /* double pitch for cube layouts */
179 pitch = (pitch + 3) & ~3;
180
181 total_height = dim * 4;
182
183 for ( face = 0 ; face < 6 ; face++) {
184 GLuint x = initial_offsets[face][0] * dim;
185 GLuint y = initial_offsets[face][1] * dim;
186 GLuint d = dim;
187
188 t->intel.base.dirty_images[face] = ~0;
189
190 assert(tObj->Image[face][firstLevel]->Width == dim);
191 assert(tObj->Image[face][firstLevel]->Height == dim);
192
193 for (i = 0; i < numLevels; i++) {
194 t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
195 if (!t->intel.image[face][i].image) {
196 fprintf(stderr, "no image %d %d\n", face, i);
197 break; /* can't happen */
198 }
199
200 t->intel.image[face][i].offset =
201 y * pitch + x * t->intel.texelBytes;
202 t->intel.image[face][i].internalFormat = baseImage->Format;
203
204 d >>= 1;
205 x += step_offsets[face][0] * d;
206 y += step_offsets[face][1] * d;
207 }
208 }
209 break;
210 }
211 case GL_TEXTURE_3D: {
212 GLuint virtual_height;
213 GLuint tmp_numLevels = numLevels;
214 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
215 pitch = (pitch + 3) & ~3;
216 t->intel.base.dirty_images[0] = ~0;
217
218 /* Calculate the size of a single slice. Hardware demands a
219 * minimum of 8 mipmaps, some of which might ultimately not be
220 * used:
221 */
222 if (tmp_numLevels < 9)
223 tmp_numLevels = 9;
224
225 virtual_height = tObj->Image[0][firstLevel]->Height;
226
227 for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) {
228 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
229 if (t->intel.image[0][i].image) {
230 t->intel.image[0][i].offset = total_height * pitch;
231 t->intel.image[0][i].internalFormat = baseImage->Format;
232 }
233
234 total_height += MAX2(2, virtual_height);
235 virtual_height >>= 1;
236 }
237
238 t->intel.depth_pitch = total_height * pitch;
239
240 /* Multiply slice size by texture depth for total size. It's
241 * remarkable how wasteful of memory all the i8x0 texture
242 * layouts are.
243 */
244 total_height *= t->intel.image[0][0].image->Depth;
245 break;
246 }
247 default:
248 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
249 pitch = (pitch + 3) & ~3;
250 t->intel.base.dirty_images[0] = ~0;
251
252 for ( total_height = i = 0 ; i < numLevels ; i++ ) {
253 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
254 if (!t->intel.image[0][i].image)
255 break;
256
257 t->intel.image[0][i].offset = total_height * pitch;
258 t->intel.image[0][i].internalFormat = baseImage->Format;
259 if (t->intel.image[0][i].image->IsCompressed)
260 {
261 if (t->intel.image[0][i].image->Height > 4)
262 total_height += t->intel.image[0][i].image->Height/4;
263 else
264 total_height += 1;
265 }
266 else
267 total_height += MAX2(2, t->intel.image[0][i].image->Height);
268 }
269 break;
270 }
271
272 t->intel.Pitch = pitch;
273 t->intel.base.totalSize = total_height*pitch;
274 t->intel.max_level = numLevels-1;
275 t->Setup[I915_TEXREG_MS3] =
276 (((tObj->Image[0][firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) |
277 ((tObj->Image[0][firstLevel]->Width - 1) << MS3_WIDTH_SHIFT) |
278 textureFormat |
279 MS3_USE_FENCE_REGS);
280 t->Setup[I915_TEXREG_MS4] =
281 ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
282 MS4_CUBE_FACE_ENA_MASK |
283 (((t->intel.max_level * 4)) << MS4_MAX_LOD_SHIFT) |
284 ((tObj->Image[0][firstLevel]->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
285
286 t->Setup[I915_TEXREG_SS2] &= ~SS2_COLORSPACE_CONVERSION;
287 t->Setup[I915_TEXREG_SS2] |= ss2;
288
289 t->intel.dirty = I915_UPLOAD_TEX_ALL;
290 }
291
292
293 /* The i915 (and related graphics cores) do not support GL_CLAMP. The
294 * Intel drivers for "other operating systems" implement GL_CLAMP as
295 * GL_CLAMP_TO_EDGE, so the same is done here.
296 */
297 static GLuint translate_wrap_mode( GLenum wrap )
298 {
299 switch( wrap ) {
300 case GL_REPEAT: return TEXCOORDMODE_WRAP;
301 case GL_CLAMP: return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
302 case GL_CLAMP_TO_EDGE: return TEXCOORDMODE_CLAMP_EDGE;
303 case GL_CLAMP_TO_BORDER: return TEXCOORDMODE_CLAMP_BORDER;
304 case GL_MIRRORED_REPEAT: return TEXCOORDMODE_MIRROR;
305 default: return TEXCOORDMODE_WRAP;
306 }
307 }
308
309
310 /**
311 */
312 static void i915ImportTexObjState( struct gl_texture_object *texObj )
313 {
314 i915TextureObjectPtr t = (i915TextureObjectPtr)texObj->DriverData;
315 int minFilt = 0, mipFilt = 0, magFilt = 0;
316
317 if(INTEL_DEBUG&DEBUG_DRI)
318 fprintf(stderr, "%s\n", __FUNCTION__);
319
320 switch (texObj->MinFilter) {
321 case GL_NEAREST:
322 minFilt = FILTER_NEAREST;
323 mipFilt = MIPFILTER_NONE;
324 break;
325 case GL_LINEAR:
326 minFilt = FILTER_LINEAR;
327 mipFilt = MIPFILTER_NONE;
328 break;
329 case GL_NEAREST_MIPMAP_NEAREST:
330 minFilt = FILTER_NEAREST;
331 mipFilt = MIPFILTER_NEAREST;
332 break;
333 case GL_LINEAR_MIPMAP_NEAREST:
334 minFilt = FILTER_LINEAR;
335 mipFilt = MIPFILTER_NEAREST;
336 break;
337 case GL_NEAREST_MIPMAP_LINEAR:
338 minFilt = FILTER_NEAREST;
339 mipFilt = MIPFILTER_LINEAR;
340 break;
341 case GL_LINEAR_MIPMAP_LINEAR:
342 minFilt = FILTER_LINEAR;
343 mipFilt = MIPFILTER_LINEAR;
344 break;
345 default:
346 break;
347 }
348
349 if ( texObj->MaxAnisotropy > 1.0 ) {
350 minFilt = FILTER_ANISOTROPIC;
351 magFilt = FILTER_ANISOTROPIC;
352 }
353 else {
354 switch (texObj->MagFilter) {
355 case GL_NEAREST:
356 magFilt = FILTER_NEAREST;
357 break;
358 case GL_LINEAR:
359 magFilt = FILTER_LINEAR;
360 break;
361 default:
362 break;
363 }
364 }
365
366 t->Setup[I915_TEXREG_SS2] &= ~SS2_MIN_FILTER_MASK;
367 t->Setup[I915_TEXREG_SS2] &= ~SS2_MIP_FILTER_MASK;
368 t->Setup[I915_TEXREG_SS2] &= ~SS2_MAG_FILTER_MASK;
369 t->Setup[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
370 (mipFilt << SS2_MIP_FILTER_SHIFT) |
371 (magFilt << SS2_MAG_FILTER_SHIFT));
372
373 {
374 GLuint ss3 = t->Setup[I915_TEXREG_SS3] & ~(SS3_TCX_ADDR_MODE_MASK |
375 SS3_TCY_ADDR_MODE_MASK |
376 SS3_TCZ_ADDR_MODE_MASK);
377 GLenum ws = texObj->WrapS;
378 GLenum wt = texObj->WrapT;
379 GLenum wr = texObj->WrapR;
380
381 t->refs_border_color = 0;
382
383 if (texObj->Target == GL_TEXTURE_3D &&
384 (texObj->MinFilter != GL_NEAREST ||
385 texObj->MagFilter != GL_NEAREST)) {
386
387 /* Try to mimic GL_CLAMP functionality a little better -
388 * switch to CLAMP_TO_BORDER whenever a non-NEAREST filter is
389 * in use. Only do this for 3D textures at the moment --
390 * doing it universally would fix the conform texbc.c
391 * failure, though.
392 */
393 if (ws == GL_CLAMP) ws = GL_CLAMP_TO_BORDER;
394 if (wt == GL_CLAMP) wt = GL_CLAMP_TO_BORDER;
395 if (wr == GL_CLAMP) wr = GL_CLAMP_TO_BORDER;
396
397 /* 3D textures don't seem to respect the border color.
398 * Fallback if there's ever a danger that they might refer to
399 * it.
400 */
401 if (ws == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
402 if (wt == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
403 if (wr == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
404 }
405
406 ss3 |= translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT;
407 ss3 |= translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT;
408 ss3 |= translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT;
409
410 if (ss3 != t->Setup[I915_TEXREG_SS3]) {
411 t->intel.dirty = I915_UPLOAD_TEX_ALL;
412 t->Setup[I915_TEXREG_SS3] = ss3;
413 }
414 }
415
416 {
417 const GLubyte *color = texObj->_BorderChan;
418
419 t->Setup[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(color[0],color[1],
420 color[2],color[3]);
421 }
422 }
423
424
425
426 static void i915_import_tex_unit( i915ContextPtr i915,
427 i915TextureObjectPtr t,
428 GLuint unit )
429 {
430 GLuint state[I915_TEX_SETUP_SIZE];
431
432 if(INTEL_DEBUG&DEBUG_TEXTURE)
433 fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
434
435 if (i915->intel.CurrentTexObj[unit])
436 i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
437
438 i915->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
439 t->intel.base.bound |= (1 << unit);
440
441 if (t->intel.dirty & I915_UPLOAD_TEX(unit)) {
442 i915ImportTexObjState( t->intel.base.tObj );
443 t->intel.dirty &= ~I915_UPLOAD_TEX(unit);
444 }
445
446 state[I915_TEXREG_MS2] = t->intel.TextureOffset;
447 state[I915_TEXREG_MS3] = t->Setup[I915_TEXREG_MS3];
448 state[I915_TEXREG_MS4] = t->Setup[I915_TEXREG_MS4];
449
450 state[I915_TEXREG_SS2] = (i915->state.Tex[unit][I915_TEXREG_SS2] &
451 SS2_LOD_BIAS_MASK);
452 state[I915_TEXREG_SS2] |= (t->Setup[I915_TEXREG_SS2] & ~SS2_LOD_BIAS_MASK);
453
454 state[I915_TEXREG_SS3] = (i915->state.Tex[unit][I915_TEXREG_SS3] &
455 SS3_NORMALIZED_COORDS);
456 state[I915_TEXREG_SS3] |= (t->Setup[I915_TEXREG_SS3] &
457 ~(SS3_NORMALIZED_COORDS|
458 SS3_TEXTUREMAP_INDEX_MASK));
459
460 state[I915_TEXREG_SS3] |= (unit<<SS3_TEXTUREMAP_INDEX_SHIFT);
461
462 state[I915_TEXREG_SS4] = t->Setup[I915_TEXREG_SS4];
463
464
465 if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) {
466 I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) );
467 memcpy(i915->state.Tex[unit], state, sizeof(state));
468 }
469 }
470
471
472
473 static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
474 {
475 i915ContextPtr i915 = I915_CONTEXT(ctx);
476 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
477 struct gl_texture_object *tObj = texUnit->_Current;
478 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
479
480 if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, unit);
481
482 if (!(i915->state.active & I915_UPLOAD_TEX(unit))) {
483 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
484 }
485
486 /* Fallback if there's a texture border */
487 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
488 return GL_FALSE;
489 }
490
491
492 /* Update state if this is a different texture object to last
493 * time.
494 */
495 if (i915->intel.CurrentTexObj[unit] != &t->intel ||
496 (t->intel.dirty & I915_UPLOAD_TEX(unit))) {
497 i915_import_tex_unit( i915, t, unit);
498 i915->tex_program.translated = 0;
499 }
500
501 return GL_TRUE;
502 }
503
504 static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
505 {
506 i915ContextPtr i915 = I915_CONTEXT(ctx);
507 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
508 struct gl_texture_object *tObj = texUnit->_Current;
509 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
510 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
511
512 ss3 &= ~SS3_NORMALIZED_COORDS;
513
514 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
515 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
516 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
517 }
518
519 /* Upload teximages (not pipelined)
520 */
521 if (t->intel.base.dirty_images[0]) {
522 i915SetTexImages( i915, tObj );
523 if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
524 return GL_FALSE;
525 }
526 }
527
528 return GL_TRUE;
529 }
530
531
532 static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
533 {
534 i915ContextPtr i915 = I915_CONTEXT(ctx);
535 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
536 struct gl_texture_object *tObj = texUnit->_Current;
537 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
538 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
539
540 ss3 |= SS3_NORMALIZED_COORDS;
541
542 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
543 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
544 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
545 }
546
547 /* Upload teximages (not pipelined)
548 */
549 if (t->intel.base.dirty_images[0]) {
550 i915SetTexImages( i915, tObj );
551 if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
552 return GL_FALSE;
553 }
554 }
555
556 return GL_TRUE;
557 }
558
559 static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
560 {
561 i915ContextPtr i915 = I915_CONTEXT(ctx);
562 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
563 struct gl_texture_object *tObj = texUnit->_Current;
564 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
565 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
566 GLuint face;
567
568 ss3 |= SS3_NORMALIZED_COORDS;
569
570 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
571 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
572 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
573 }
574
575 /* Upload teximages (not pipelined)
576 */
577 if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
578 t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
579 t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
580 i915SetTexImages( i915, tObj );
581 }
582
583 /* upload (per face) */
584 for (face = 0; face < 6; face++) {
585 if (t->intel.base.dirty_images[face]) {
586 if (!intelUploadTexImages( &i915->intel, &t->intel, face )) {
587 return GL_FALSE;
588 }
589 }
590 }
591
592
593 return GL_TRUE;
594 }
595
596 static GLboolean enable_tex_3d( GLcontext *ctx, GLuint unit )
597 {
598 struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
599 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
600
601 /* 3D textures on I915 seem to get bogus border colors, hence this
602 * fallback:
603 */
604 if (t->refs_border_color)
605 return GL_FALSE;
606
607 return GL_TRUE;
608 }
609
610
611
612
613 static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
614 {
615 i915ContextPtr i915 = I915_CONTEXT(ctx);
616
617 if (i915->state.active & I915_UPLOAD_TEX(unit)) {
618 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_FALSE);
619 }
620
621 /* The old texture is no longer bound to this texture unit.
622 * Mark it as such.
623 */
624 if ( i915->intel.CurrentTexObj[unit] != NULL ) {
625 i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
626 i915->intel.CurrentTexObj[unit] = NULL;
627 }
628
629 return GL_TRUE;
630 }
631
632 static GLboolean i915UpdateTexUnit( GLcontext *ctx, GLuint unit )
633 {
634 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
635
636 if (texUnit->_ReallyEnabled &&
637 INTEL_CONTEXT(ctx)->intelScreen->textureSize < 2048 * 1024)
638 return GL_FALSE;
639
640 switch (texUnit->_ReallyEnabled) {
641 case TEXTURE_1D_BIT:
642 case TEXTURE_2D_BIT:
643 return (enable_tex_2d( ctx, unit ) &&
644 enable_tex_common( ctx, unit ));
645 case TEXTURE_RECT_BIT:
646 return (enable_tex_rect( ctx, unit ) &&
647 enable_tex_common( ctx, unit ));
648 case TEXTURE_CUBE_BIT:
649 return (enable_tex_cube( ctx, unit ) &&
650 enable_tex_common( ctx, unit ));
651 case TEXTURE_3D_BIT:
652 return (enable_tex_2d( ctx, unit ) &&
653 enable_tex_common( ctx, unit ) &&
654 enable_tex_3d( ctx, unit));
655 case 0:
656 return disable_tex( ctx, unit );
657 default:
658 return GL_FALSE;
659 }
660 }
661
662
663 void i915UpdateTextureState( intelContextPtr intel )
664 {
665 GLcontext *ctx = &intel->ctx;
666 GLboolean ok = GL_TRUE;
667 GLuint i;
668
669 for (i = 0 ; i < I915_TEX_UNITS && ok ; i++) {
670 ok = i915UpdateTexUnit( ctx, i );
671 }
672
673 FALLBACK( intel, I915_FALLBACK_TEXTURE, !ok );
674 }
675
676
677