enable feedback rendering
[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 i915LayoutTextureImages( i915ContextPtr i915,
64 struct gl_texture_object *tObj )
65 {
66 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
67 i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
68 GLint firstLevel, lastLevel, numLevels;
69 GLint i, total_height, pitch;
70
71 /* Compute which mipmap levels we really want to send to the hardware.
72 */
73 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
74
75 /* Figure out the amount of memory required to hold all the mipmap
76 * levels. Choose the smallest pitch to accomodate the largest
77 * mipmap:
78 */
79 firstLevel = t->intel.base.firstLevel;
80 lastLevel = t->intel.base.lastLevel;
81 numLevels = lastLevel - firstLevel + 1;
82
83
84
85 /* All images must be loaded at this pitch. Count the number of
86 * lines required:
87 */
88 switch (tObj->Target) {
89 case GL_TEXTURE_CUBE_MAP: {
90 const GLuint dim = tObj->Image[0][firstLevel]->Width;
91 GLuint face;
92
93 pitch = dim * t->intel.texelBytes;
94 pitch *= 2; /* double pitch for cube layouts */
95 pitch = (pitch + 3) & ~3;
96
97 total_height = dim * 4;
98
99 for ( face = 0 ; face < 6 ; face++) {
100 GLuint x = initial_offsets[face][0] * dim;
101 GLuint y = initial_offsets[face][1] * dim;
102 GLuint d = dim;
103
104 t->intel.base.dirty_images[face] = ~0;
105
106 assert(tObj->Image[face][firstLevel]->Width == dim);
107 assert(tObj->Image[face][firstLevel]->Height == dim);
108
109 for (i = 0; i < numLevels; i++) {
110 t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
111 if (!t->intel.image[face][i].image) {
112 fprintf(stderr, "no image %d %d\n", face, i);
113 break; /* can't happen */
114 }
115
116 t->intel.image[face][i].offset =
117 y * pitch + x * t->intel.texelBytes;
118 t->intel.image[face][i].internalFormat = baseImage->_BaseFormat;
119
120 d >>= 1;
121 x += step_offsets[face][0] * d;
122 y += step_offsets[face][1] * d;
123 }
124 }
125 break;
126 }
127 case GL_TEXTURE_3D: {
128 GLuint virtual_height;
129 GLuint tmp_numLevels = numLevels;
130 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
131 pitch = (pitch + 3) & ~3;
132 t->intel.base.dirty_images[0] = ~0;
133
134 /* Calculate the size of a single slice. Hardware demands a
135 * minimum of 8 mipmaps, some of which might ultimately not be
136 * used:
137 */
138 if (tmp_numLevels < 9)
139 tmp_numLevels = 9;
140
141 virtual_height = tObj->Image[0][firstLevel]->Height;
142
143 for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) {
144 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
145 if (t->intel.image[0][i].image) {
146 t->intel.image[0][i].offset = total_height * pitch;
147 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
148 }
149
150 total_height += MAX2(2, virtual_height);
151 virtual_height >>= 1;
152 }
153
154 t->intel.depth_pitch = total_height * pitch;
155
156 /* Multiply slice size by texture depth for total size. It's
157 * remarkable how wasteful of memory all the i8x0 texture
158 * layouts are.
159 */
160 total_height *= t->intel.image[0][0].image->Depth;
161 break;
162 }
163 default:
164 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
165 pitch = (pitch + 3) & ~3;
166 t->intel.base.dirty_images[0] = ~0;
167
168 for ( total_height = i = 0 ; i < numLevels ; i++ ) {
169 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
170 if (!t->intel.image[0][i].image)
171 break;
172
173 t->intel.image[0][i].offset = total_height * pitch;
174 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
175 if (t->intel.image[0][i].image->IsCompressed)
176 {
177 if (t->intel.image[0][i].image->Height > 4)
178 total_height += t->intel.image[0][i].image->Height/4;
179 else
180 total_height += 1;
181 }
182 else
183 total_height += MAX2(2, t->intel.image[0][i].image->Height);
184 }
185 break;
186 }
187
188 t->intel.Pitch = pitch;
189 t->intel.base.totalSize = total_height*pitch;
190 t->intel.max_level = numLevels-1;
191 }
192
193
194 static void i945LayoutTextureImages( i915ContextPtr i915,
195 struct gl_texture_object *tObj )
196 {
197 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
198 i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
199 GLint firstLevel, lastLevel, numLevels;
200 GLint i, total_height, pitch, sz, max_offset = 0, offset;
201
202
203 /* Compute which mipmap levels we really want to send to the hardware.
204 */
205 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
206
207 /* Figure out the amount of memory required to hold all the mipmap
208 * levels. Choose the smallest pitch to accomodate the largest
209 * mipmap:
210 */
211 firstLevel = t->intel.base.firstLevel;
212 lastLevel = t->intel.base.lastLevel;
213 numLevels = lastLevel - firstLevel + 1;
214
215
216
217 /* All images must be loaded at this pitch. Count the number of
218 * lines required:
219 */
220 switch (tObj->Target) {
221 case GL_TEXTURE_CUBE_MAP: {
222 const GLuint dim = tObj->Image[0][firstLevel]->Width;
223 GLuint face;
224
225 /* Depending on the size of the largest images, pitch can be
226 * determined either by the old-style packing of cubemap faces,
227 * or the final row of 4x4, 2x2 and 1x1 faces below this.
228 */
229 if (dim > 32) {
230 pitch = dim * t->intel.texelBytes;
231 pitch *= 2; /* double pitch for cube layouts */
232 pitch = (pitch + 3) & ~3;
233 }
234 else {
235 pitch = 14 * 8 * t->intel.texelBytes; /* determined by row of
236 * little maps at
237 * bottom */
238 }
239
240 total_height = dim * 4 + 4;
241
242 for ( face = 0 ; face < 6 ; face++) {
243 GLuint x = initial_offsets[face][0] * dim;
244 GLuint y = initial_offsets[face][1] * dim;
245 GLuint d = dim;
246
247 if (dim == 4 && face >= 4) {
248 y = total_height - 4;
249 x = (face - 4) * 8;
250 }
251 else if (dim < 4) {
252 y = total_height - 4;
253 x = face * 8;
254 }
255
256 t->intel.base.dirty_images[face] = ~0;
257
258 assert(tObj->Image[face][firstLevel]->Width == dim);
259 assert(tObj->Image[face][firstLevel]->Height == dim);
260
261 for (i = 0; i < numLevels; i++) {
262
263
264 t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
265 assert(t->intel.image[face][i].image);
266
267 t->intel.image[face][i].offset =
268 y * pitch + x * t->intel.texelBytes;
269 t->intel.image[face][i].internalFormat = baseImage->_BaseFormat;
270
271 d >>= 1;
272
273 switch (d) {
274 case 4:
275 switch (face) {
276 case FACE_POS_X:
277 case FACE_NEG_X:
278 x += step_offsets[face][0] * d;
279 y += step_offsets[face][1] * d;
280 break;
281 case FACE_POS_Y:
282 case FACE_NEG_Y:
283 y += 12;
284 x -= 8;
285 break;
286 case FACE_POS_Z:
287 case FACE_NEG_Z:
288 y = total_height - 4;
289 x = (face - 4) * 8;
290 break;
291 }
292
293 case 2:
294 y = total_height - 4;
295 x = 16 + face * 8;
296 break;
297
298 case 1:
299 x += 48;
300 break;
301
302 default:
303 x += step_offsets[face][0] * d;
304 y += step_offsets[face][1] * d;
305 break;
306 }
307 }
308 }
309 max_offset = total_height * pitch;
310 break;
311 }
312 case GL_TEXTURE_3D: {
313 GLuint depth_packing = 0, depth_pack_pitch;
314 GLuint tmp_numLevels = numLevels;
315 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
316 pitch = (pitch + 3) & ~3;
317 depth_pack_pitch = pitch;
318
319 t->intel.base.dirty_images[0] = ~0;
320
321
322 for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) {
323 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
324 if (!t->intel.image[0][i].image)
325 break;
326
327
328 t->intel.image[0][i].offset = total_height * pitch;
329 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
330
331
332
333 total_height += MAX2(2, t->intel.image[0][i].image->Height) *
334 MAX2((t->intel.image[0][i].image->Depth >> depth_packing), 1);
335
336 /* When alignment dominates, can't increase depth packing?
337 * Or does pitch grow??? What are the alignment constraints,
338 * anyway?
339 */
340 if (depth_pack_pitch > 4) {
341 depth_packing++;
342 depth_pack_pitch <<= 2;
343 }
344 }
345
346 max_offset = total_height * pitch;
347 break;
348 }
349 default:
350 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
351 pitch = (pitch + 3) & ~3;
352 t->intel.base.dirty_images[0] = ~0;
353 max_offset = 0;
354
355 for ( offset = i = 0 ; i < numLevels ; i++ ) {
356 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
357 if (!t->intel.image[0][i].image)
358 break;
359
360 t->intel.image[0][i].offset = offset;
361 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
362
363 if (t->intel.image[0][i].image->IsCompressed)
364 sz = MAX2(1, t->intel.image[0][i].image->Height/4) * pitch;
365 else
366 sz = MAX2(2, t->intel.image[0][i].image->Height) * pitch;
367
368 /* Because the images are packed better, the final offset
369 * might not be the maximal one:
370 */
371 max_offset = MAX2(max_offset, offset + sz);
372
373 /* LPT change: step right after second mipmap.
374 */
375 if (i == 1)
376 offset += pitch / 2;
377 else
378 offset += sz;
379
380 }
381 break;
382 }
383
384 t->intel.Pitch = pitch;
385 t->intel.base.totalSize = max_offset;
386 t->intel.max_level = numLevels-1;
387 }
388
389
390
391
392 static void i915SetTexImages( i915ContextPtr i915,
393 struct gl_texture_object *tObj )
394 {
395 GLuint textureFormat;
396 i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
397 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
398 GLint ss2 = 0;
399
400 switch( baseImage->TexFormat->MesaFormat ) {
401 case MESA_FORMAT_L8:
402 t->intel.texelBytes = 1;
403 textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
404 break;
405
406 case MESA_FORMAT_I8:
407 t->intel.texelBytes = 1;
408 textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
409 break;
410
411 case MESA_FORMAT_A8:
412 t->intel.texelBytes = 1;
413 textureFormat = MAPSURF_8BIT | MT_8BIT_A8;
414 break;
415
416 case MESA_FORMAT_AL88:
417 t->intel.texelBytes = 2;
418 textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
419 break;
420
421 case MESA_FORMAT_RGB565:
422 t->intel.texelBytes = 2;
423 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
424 break;
425
426 case MESA_FORMAT_ARGB1555:
427 t->intel.texelBytes = 2;
428 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
429 break;
430
431 case MESA_FORMAT_ARGB4444:
432 t->intel.texelBytes = 2;
433 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
434 break;
435
436 case MESA_FORMAT_ARGB8888:
437 t->intel.texelBytes = 4;
438 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
439 break;
440
441 case MESA_FORMAT_YCBCR_REV:
442 t->intel.texelBytes = 2;
443 textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL);
444 ss2 |= SS2_COLORSPACE_CONVERSION;
445 break;
446
447 case MESA_FORMAT_YCBCR:
448 t->intel.texelBytes = 2;
449 textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY);
450 ss2 |= SS2_COLORSPACE_CONVERSION;
451 break;
452
453 case MESA_FORMAT_RGB_FXT1:
454 case MESA_FORMAT_RGBA_FXT1:
455 t->intel.texelBytes = 2;
456 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
457 break;
458
459 case MESA_FORMAT_Z16:
460 t->intel.texelBytes = 2;
461 textureFormat = (MAPSURF_16BIT | MT_16BIT_L16);
462 break;
463
464 case MESA_FORMAT_RGBA_DXT1:
465 case MESA_FORMAT_RGB_DXT1:
466 /*
467 * DXTn pitches are Width/4 * blocksize in bytes
468 * for DXT1: blocksize=8 so Width/4*8 = Width * 2
469 * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
470 */
471 t->intel.texelBytes = 2;
472 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
473 break;
474
475 case MESA_FORMAT_RGBA_DXT3:
476 t->intel.texelBytes = 4;
477 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
478 break;
479
480 case MESA_FORMAT_RGBA_DXT5:
481 t->intel.texelBytes = 4;
482 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
483 break;
484
485 #if 0
486 case MESA_FORMAT_Z24_S8:
487 t->intel.texelBytes = 4;
488 textureFormat = (MAPSURF_32BIT | MT_32BIT_xL824);
489 break;
490 #endif
491
492 default:
493 fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__,
494 baseImage->TexFormat->MesaFormat);
495 abort();
496 }
497
498
499 if (i915->intel.intelScreen->deviceID == PCI_CHIP_I945_G ||
500 i915->intel.intelScreen->deviceID == PCI_CHIP_I945_GM)
501 i945LayoutTextureImages( i915, tObj );
502 else
503 i915LayoutTextureImages( i915, tObj );
504
505 t->Setup[I915_TEXREG_MS3] =
506 (((tObj->Image[0][t->intel.base.firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) |
507 ((tObj->Image[0][t->intel.base.firstLevel]->Width - 1) << MS3_WIDTH_SHIFT) |
508 textureFormat |
509 MS3_USE_FENCE_REGS);
510
511 t->Setup[I915_TEXREG_MS4] =
512 ((((t->intel.Pitch / 4) - 1) << MS4_PITCH_SHIFT) |
513 MS4_CUBE_FACE_ENA_MASK |
514 (((t->intel.max_level * 4)) << MS4_MAX_LOD_SHIFT) |
515 ((tObj->Image[0][t->intel.base.firstLevel]->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
516
517 t->Setup[I915_TEXREG_SS2] &= ~(SS2_COLORSPACE_CONVERSION);
518 t->Setup[I915_TEXREG_SS2] |= ss2;
519
520 t->intel.dirty = I915_UPLOAD_TEX_ALL;
521
522 }
523
524
525 /* The i915 (and related graphics cores) do not support GL_CLAMP. The
526 * Intel drivers for "other operating systems" implement GL_CLAMP as
527 * GL_CLAMP_TO_EDGE, so the same is done here.
528 */
529 static GLuint translate_wrap_mode( GLenum wrap )
530 {
531 switch( wrap ) {
532 case GL_REPEAT: return TEXCOORDMODE_WRAP;
533 case GL_CLAMP: return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
534 case GL_CLAMP_TO_EDGE: return TEXCOORDMODE_CLAMP_EDGE;
535 case GL_CLAMP_TO_BORDER: return TEXCOORDMODE_CLAMP_BORDER;
536 case GL_MIRRORED_REPEAT: return TEXCOORDMODE_MIRROR;
537 default: return TEXCOORDMODE_WRAP;
538 }
539 }
540
541
542 /**
543 */
544 static void i915ImportTexObjState( struct gl_texture_object *texObj )
545 {
546 i915TextureObjectPtr t = (i915TextureObjectPtr)texObj->DriverData;
547 int minFilt = 0, mipFilt = 0, magFilt = 0, shadow = 0;
548
549 if(INTEL_DEBUG&DEBUG_DRI)
550 fprintf(stderr, "%s\n", __FUNCTION__);
551
552 switch (texObj->MinFilter) {
553 case GL_NEAREST:
554 minFilt = FILTER_NEAREST;
555 mipFilt = MIPFILTER_NONE;
556 break;
557 case GL_LINEAR:
558 minFilt = FILTER_LINEAR;
559 mipFilt = MIPFILTER_NONE;
560 break;
561 case GL_NEAREST_MIPMAP_NEAREST:
562 minFilt = FILTER_NEAREST;
563 mipFilt = MIPFILTER_NEAREST;
564 break;
565 case GL_LINEAR_MIPMAP_NEAREST:
566 minFilt = FILTER_LINEAR;
567 mipFilt = MIPFILTER_NEAREST;
568 break;
569 case GL_NEAREST_MIPMAP_LINEAR:
570 minFilt = FILTER_NEAREST;
571 mipFilt = MIPFILTER_LINEAR;
572 break;
573 case GL_LINEAR_MIPMAP_LINEAR:
574 minFilt = FILTER_LINEAR;
575 mipFilt = MIPFILTER_LINEAR;
576 break;
577 default:
578 break;
579 }
580
581 if ( texObj->MaxAnisotropy > 1.0 ) {
582 minFilt = FILTER_ANISOTROPIC;
583 magFilt = FILTER_ANISOTROPIC;
584 }
585 else {
586 switch (texObj->MagFilter) {
587 case GL_NEAREST:
588 magFilt = FILTER_NEAREST;
589 break;
590 case GL_LINEAR:
591 magFilt = FILTER_LINEAR;
592 break;
593 default:
594 break;
595 }
596 }
597
598 if (texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
599 texObj->Target != GL_TEXTURE_3D) {
600
601 shadow = SS2_SHADOW_ENABLE;
602 shadow |= intel_translate_compare_func( texObj->CompareFunc );
603
604 minFilt = FILTER_4X4_FLAT;
605 magFilt = FILTER_4X4_FLAT;
606 }
607
608
609 t->Setup[I915_TEXREG_SS2] &= ~(SS2_MIN_FILTER_MASK |
610 SS2_MIP_FILTER_MASK |
611 SS2_MAG_FILTER_MASK |
612 SS2_SHADOW_ENABLE |
613 SS2_SHADOW_FUNC_MASK);
614 t->Setup[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
615 (mipFilt << SS2_MIP_FILTER_SHIFT) |
616 (magFilt << SS2_MAG_FILTER_SHIFT) |
617 shadow);
618
619 {
620 GLuint ss3 = t->Setup[I915_TEXREG_SS3] & ~(SS3_TCX_ADDR_MODE_MASK |
621 SS3_TCY_ADDR_MODE_MASK |
622 SS3_TCZ_ADDR_MODE_MASK);
623 GLenum ws = texObj->WrapS;
624 GLenum wt = texObj->WrapT;
625 GLenum wr = texObj->WrapR;
626
627 t->refs_border_color = 0;
628
629 if (texObj->Target == GL_TEXTURE_3D &&
630 (texObj->MinFilter != GL_NEAREST ||
631 texObj->MagFilter != GL_NEAREST)) {
632
633 /* Try to mimic GL_CLAMP functionality a little better -
634 * switch to CLAMP_TO_BORDER whenever a non-NEAREST filter is
635 * in use. Only do this for 3D textures at the moment --
636 * doing it universally would fix the conform texbc.c
637 * failure, though.
638 */
639 if (ws == GL_CLAMP) ws = GL_CLAMP_TO_BORDER;
640 if (wt == GL_CLAMP) wt = GL_CLAMP_TO_BORDER;
641 if (wr == GL_CLAMP) wr = GL_CLAMP_TO_BORDER;
642
643 /* 3D textures don't seem to respect the border color.
644 * Fallback if there's ever a danger that they might refer to
645 * it.
646 */
647 if (ws == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
648 if (wt == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
649 if (wr == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
650 }
651
652 ss3 |= translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT;
653 ss3 |= translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT;
654 ss3 |= translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT;
655
656 if (ss3 != t->Setup[I915_TEXREG_SS3]) {
657 t->intel.dirty = I915_UPLOAD_TEX_ALL;
658 t->Setup[I915_TEXREG_SS3] = ss3;
659 }
660 }
661
662 {
663 const GLubyte *color = texObj->_BorderChan;
664
665 t->Setup[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(color[0],color[1],
666 color[2],color[3]);
667 }
668 }
669
670
671
672 static void i915_import_tex_unit( i915ContextPtr i915,
673 i915TextureObjectPtr t,
674 GLuint unit )
675 {
676 GLuint state[I915_TEX_SETUP_SIZE];
677
678 if(INTEL_DEBUG&DEBUG_TEXTURE)
679 fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
680
681 if (i915->intel.CurrentTexObj[unit])
682 i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
683
684 i915->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
685 t->intel.base.bound |= (1 << unit);
686
687 if (t->intel.dirty & I915_UPLOAD_TEX(unit)) {
688 i915ImportTexObjState( t->intel.base.tObj );
689 t->intel.dirty &= ~I915_UPLOAD_TEX(unit);
690 }
691
692 state[I915_TEXREG_MS2] = t->intel.TextureOffset;
693 state[I915_TEXREG_MS3] = t->Setup[I915_TEXREG_MS3];
694 state[I915_TEXREG_MS4] = t->Setup[I915_TEXREG_MS4];
695
696 state[I915_TEXREG_SS2] = (i915->state.Tex[unit][I915_TEXREG_SS2] &
697 SS2_LOD_BIAS_MASK);
698 state[I915_TEXREG_SS2] |= (t->Setup[I915_TEXREG_SS2] & ~SS2_LOD_BIAS_MASK);
699
700 state[I915_TEXREG_SS3] = (i915->state.Tex[unit][I915_TEXREG_SS3] &
701 SS3_NORMALIZED_COORDS);
702 state[I915_TEXREG_SS3] |= (t->Setup[I915_TEXREG_SS3] &
703 ~(SS3_NORMALIZED_COORDS|
704 SS3_TEXTUREMAP_INDEX_MASK));
705
706 state[I915_TEXREG_SS3] |= (unit<<SS3_TEXTUREMAP_INDEX_SHIFT);
707
708 state[I915_TEXREG_SS4] = t->Setup[I915_TEXREG_SS4];
709
710
711 if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) {
712 I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) );
713 memcpy(i915->state.Tex[unit], state, sizeof(state));
714 }
715 }
716
717
718
719 static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
720 {
721 i915ContextPtr i915 = I915_CONTEXT(ctx);
722 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
723 struct gl_texture_object *tObj = texUnit->_Current;
724 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
725
726 if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, unit);
727
728 if (!(i915->state.active & I915_UPLOAD_TEX(unit))) {
729 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
730 }
731
732 /* Fallback if there's a texture border */
733 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
734 return GL_FALSE;
735 }
736
737
738 /* Update state if this is a different texture object to last
739 * time.
740 */
741 if (i915->intel.CurrentTexObj[unit] != &t->intel ||
742 (t->intel.dirty & I915_UPLOAD_TEX(unit))) {
743 i915_import_tex_unit( i915, t, unit);
744 i915->tex_program.translated = 0;
745 }
746
747 return GL_TRUE;
748 }
749
750 static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
751 {
752 i915ContextPtr i915 = I915_CONTEXT(ctx);
753 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
754 struct gl_texture_object *tObj = texUnit->_Current;
755 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
756 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
757
758 ss3 &= ~SS3_NORMALIZED_COORDS;
759
760 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
761 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
762 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
763 }
764
765 /* Upload teximages (not pipelined)
766 */
767 if (t->intel.base.dirty_images[0]) {
768 i915SetTexImages( i915, tObj );
769 if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
770 return GL_FALSE;
771 }
772 }
773
774 return GL_TRUE;
775 }
776
777
778 static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
779 {
780 i915ContextPtr i915 = I915_CONTEXT(ctx);
781 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
782 struct gl_texture_object *tObj = texUnit->_Current;
783 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
784 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
785
786 ss3 |= SS3_NORMALIZED_COORDS;
787
788 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
789 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
790 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
791 }
792
793 /* Upload teximages (not pipelined)
794 */
795 if (t->intel.base.dirty_images[0]) {
796 i915SetTexImages( i915, tObj );
797 if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
798 return GL_FALSE;
799 }
800 }
801
802 return GL_TRUE;
803 }
804
805 static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
806 {
807 i915ContextPtr i915 = I915_CONTEXT(ctx);
808 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
809 struct gl_texture_object *tObj = texUnit->_Current;
810 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
811 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
812 GLuint face;
813
814 ss3 |= SS3_NORMALIZED_COORDS;
815
816 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
817 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
818 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
819 }
820
821 /* Upload teximages (not pipelined)
822 */
823 if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
824 t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
825 t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
826 i915SetTexImages( i915, tObj );
827 }
828
829 /* upload (per face) */
830 for (face = 0; face < 6; face++) {
831 if (t->intel.base.dirty_images[face]) {
832 if (!intelUploadTexImages( &i915->intel, &t->intel, face )) {
833 return GL_FALSE;
834 }
835 }
836 }
837
838
839 return GL_TRUE;
840 }
841
842 static GLboolean enable_tex_3d( GLcontext *ctx, GLuint unit )
843 {
844 struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
845 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
846
847 /* 3D textures on I915 seem to get bogus border colors, hence this
848 * fallback:
849 */
850 if (t->refs_border_color)
851 return GL_FALSE;
852
853 return GL_TRUE;
854 }
855
856
857
858
859 static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
860 {
861 i915ContextPtr i915 = I915_CONTEXT(ctx);
862
863 if (i915->state.active & I915_UPLOAD_TEX(unit)) {
864 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_FALSE);
865 }
866
867 /* The old texture is no longer bound to this texture unit.
868 * Mark it as such.
869 */
870 if ( i915->intel.CurrentTexObj[unit] != NULL ) {
871 i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
872 i915->intel.CurrentTexObj[unit] = NULL;
873 }
874
875 return GL_TRUE;
876 }
877
878 static GLboolean i915UpdateTexUnit( GLcontext *ctx, GLuint unit )
879 {
880 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
881
882 if (texUnit->_ReallyEnabled &&
883 INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024)
884 return GL_FALSE;
885
886 switch (texUnit->_ReallyEnabled) {
887 case TEXTURE_1D_BIT:
888 case TEXTURE_2D_BIT:
889 return (enable_tex_2d( ctx, unit ) &&
890 enable_tex_common( ctx, unit ));
891 case TEXTURE_RECT_BIT:
892 return (enable_tex_rect( ctx, unit ) &&
893 enable_tex_common( ctx, unit ));
894 case TEXTURE_CUBE_BIT:
895 return (enable_tex_cube( ctx, unit ) &&
896 enable_tex_common( ctx, unit ));
897 case TEXTURE_3D_BIT:
898 return (enable_tex_2d( ctx, unit ) &&
899 enable_tex_common( ctx, unit ) &&
900 enable_tex_3d( ctx, unit));
901 case 0:
902 return disable_tex( ctx, unit );
903 default:
904 return GL_FALSE;
905 }
906 }
907
908
909 void i915UpdateTextureState( intelContextPtr intel )
910 {
911 GLcontext *ctx = &intel->ctx;
912 GLboolean ok = GL_TRUE;
913 GLuint i;
914
915 for (i = 0 ; i < I915_TEX_UNITS && ok ; i++) {
916 ok = i915UpdateTexUnit( ctx, i );
917 }
918
919 FALLBACK( intel, I915_FALLBACK_TEXTURE, !ok );
920 }
921
922
923