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