fix up radeon span functions using latest r200 code from Brian,
[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_DEPTH_COMPONENT16:
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_DEPTH_COMPONENT_X8Z24:
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 i945LayoutTextureImages( i915, tObj );
501 else
502 i915LayoutTextureImages( i915, tObj );
503
504 t->Setup[I915_TEXREG_MS3] =
505 (((tObj->Image[0][t->intel.base.firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) |
506 ((tObj->Image[0][t->intel.base.firstLevel]->Width - 1) << MS3_WIDTH_SHIFT) |
507 textureFormat |
508 MS3_USE_FENCE_REGS);
509
510 t->Setup[I915_TEXREG_MS4] =
511 ((((t->intel.Pitch / 4) - 1) << MS4_PITCH_SHIFT) |
512 MS4_CUBE_FACE_ENA_MASK |
513 (((t->intel.max_level * 4)) << MS4_MAX_LOD_SHIFT) |
514 ((tObj->Image[0][t->intel.base.firstLevel]->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
515
516 t->Setup[I915_TEXREG_SS2] &= ~(SS2_COLORSPACE_CONVERSION);
517 t->Setup[I915_TEXREG_SS2] |= ss2;
518
519 t->intel.dirty = I915_UPLOAD_TEX_ALL;
520
521 }
522
523
524 /* The i915 (and related graphics cores) do not support GL_CLAMP. The
525 * Intel drivers for "other operating systems" implement GL_CLAMP as
526 * GL_CLAMP_TO_EDGE, so the same is done here.
527 */
528 static GLuint translate_wrap_mode( GLenum wrap )
529 {
530 switch( wrap ) {
531 case GL_REPEAT: return TEXCOORDMODE_WRAP;
532 case GL_CLAMP: return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
533 case GL_CLAMP_TO_EDGE: return TEXCOORDMODE_CLAMP_EDGE;
534 case GL_CLAMP_TO_BORDER: return TEXCOORDMODE_CLAMP_BORDER;
535 case GL_MIRRORED_REPEAT: return TEXCOORDMODE_MIRROR;
536 default: return TEXCOORDMODE_WRAP;
537 }
538 }
539
540
541 /**
542 */
543 static void i915ImportTexObjState( struct gl_texture_object *texObj )
544 {
545 i915TextureObjectPtr t = (i915TextureObjectPtr)texObj->DriverData;
546 int minFilt = 0, mipFilt = 0, magFilt = 0, shadow = 0;
547
548 if(INTEL_DEBUG&DEBUG_DRI)
549 fprintf(stderr, "%s\n", __FUNCTION__);
550
551 switch (texObj->MinFilter) {
552 case GL_NEAREST:
553 minFilt = FILTER_NEAREST;
554 mipFilt = MIPFILTER_NONE;
555 break;
556 case GL_LINEAR:
557 minFilt = FILTER_LINEAR;
558 mipFilt = MIPFILTER_NONE;
559 break;
560 case GL_NEAREST_MIPMAP_NEAREST:
561 minFilt = FILTER_NEAREST;
562 mipFilt = MIPFILTER_NEAREST;
563 break;
564 case GL_LINEAR_MIPMAP_NEAREST:
565 minFilt = FILTER_LINEAR;
566 mipFilt = MIPFILTER_NEAREST;
567 break;
568 case GL_NEAREST_MIPMAP_LINEAR:
569 minFilt = FILTER_NEAREST;
570 mipFilt = MIPFILTER_LINEAR;
571 break;
572 case GL_LINEAR_MIPMAP_LINEAR:
573 minFilt = FILTER_LINEAR;
574 mipFilt = MIPFILTER_LINEAR;
575 break;
576 default:
577 break;
578 }
579
580 if ( texObj->MaxAnisotropy > 1.0 ) {
581 minFilt = FILTER_ANISOTROPIC;
582 magFilt = FILTER_ANISOTROPIC;
583 }
584 else {
585 switch (texObj->MagFilter) {
586 case GL_NEAREST:
587 magFilt = FILTER_NEAREST;
588 break;
589 case GL_LINEAR:
590 magFilt = FILTER_LINEAR;
591 break;
592 default:
593 break;
594 }
595 }
596
597 if (texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
598 texObj->Target != GL_TEXTURE_3D) {
599
600 shadow = SS2_SHADOW_ENABLE;
601 shadow |= intel_translate_compare_func( texObj->CompareFunc );
602
603 minFilt = FILTER_4X4_FLAT;
604 magFilt = FILTER_4X4_FLAT;
605 }
606
607
608 t->Setup[I915_TEXREG_SS2] &= ~(SS2_MIN_FILTER_MASK |
609 SS2_MIP_FILTER_MASK |
610 SS2_MAG_FILTER_MASK |
611 SS2_SHADOW_ENABLE |
612 SS2_SHADOW_FUNC_MASK);
613 t->Setup[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
614 (mipFilt << SS2_MIP_FILTER_SHIFT) |
615 (magFilt << SS2_MAG_FILTER_SHIFT) |
616 shadow);
617
618 {
619 GLuint ss3 = t->Setup[I915_TEXREG_SS3] & ~(SS3_TCX_ADDR_MODE_MASK |
620 SS3_TCY_ADDR_MODE_MASK |
621 SS3_TCZ_ADDR_MODE_MASK);
622 GLenum ws = texObj->WrapS;
623 GLenum wt = texObj->WrapT;
624 GLenum wr = texObj->WrapR;
625
626 t->refs_border_color = 0;
627
628 if (texObj->Target == GL_TEXTURE_3D &&
629 (texObj->MinFilter != GL_NEAREST ||
630 texObj->MagFilter != GL_NEAREST)) {
631
632 /* Try to mimic GL_CLAMP functionality a little better -
633 * switch to CLAMP_TO_BORDER whenever a non-NEAREST filter is
634 * in use. Only do this for 3D textures at the moment --
635 * doing it universally would fix the conform texbc.c
636 * failure, though.
637 */
638 if (ws == GL_CLAMP) ws = GL_CLAMP_TO_BORDER;
639 if (wt == GL_CLAMP) wt = GL_CLAMP_TO_BORDER;
640 if (wr == GL_CLAMP) wr = GL_CLAMP_TO_BORDER;
641
642 /* 3D textures don't seem to respect the border color.
643 * Fallback if there's ever a danger that they might refer to
644 * it.
645 */
646 if (ws == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
647 if (wt == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
648 if (wr == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
649 }
650
651 ss3 |= translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT;
652 ss3 |= translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT;
653 ss3 |= translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT;
654
655 if (ss3 != t->Setup[I915_TEXREG_SS3]) {
656 t->intel.dirty = I915_UPLOAD_TEX_ALL;
657 t->Setup[I915_TEXREG_SS3] = ss3;
658 }
659 }
660
661 {
662 const GLubyte *color = texObj->_BorderChan;
663
664 t->Setup[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(color[0],color[1],
665 color[2],color[3]);
666 }
667 }
668
669
670
671 static void i915_import_tex_unit( i915ContextPtr i915,
672 i915TextureObjectPtr t,
673 GLuint unit )
674 {
675 GLuint state[I915_TEX_SETUP_SIZE];
676
677 if(INTEL_DEBUG&DEBUG_TEXTURE)
678 fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
679
680 if (i915->intel.CurrentTexObj[unit])
681 i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
682
683 i915->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
684 t->intel.base.bound |= (1 << unit);
685
686 if (t->intel.dirty & I915_UPLOAD_TEX(unit)) {
687 i915ImportTexObjState( t->intel.base.tObj );
688 t->intel.dirty &= ~I915_UPLOAD_TEX(unit);
689 }
690
691 state[I915_TEXREG_MS2] = t->intel.TextureOffset;
692 state[I915_TEXREG_MS3] = t->Setup[I915_TEXREG_MS3];
693 state[I915_TEXREG_MS4] = t->Setup[I915_TEXREG_MS4];
694
695 state[I915_TEXREG_SS2] = (i915->state.Tex[unit][I915_TEXREG_SS2] &
696 SS2_LOD_BIAS_MASK);
697 state[I915_TEXREG_SS2] |= (t->Setup[I915_TEXREG_SS2] & ~SS2_LOD_BIAS_MASK);
698
699 state[I915_TEXREG_SS3] = (i915->state.Tex[unit][I915_TEXREG_SS3] &
700 SS3_NORMALIZED_COORDS);
701 state[I915_TEXREG_SS3] |= (t->Setup[I915_TEXREG_SS3] &
702 ~(SS3_NORMALIZED_COORDS|
703 SS3_TEXTUREMAP_INDEX_MASK));
704
705 state[I915_TEXREG_SS3] |= (unit<<SS3_TEXTUREMAP_INDEX_SHIFT);
706
707 state[I915_TEXREG_SS4] = t->Setup[I915_TEXREG_SS4];
708
709
710 if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) {
711 I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) );
712 memcpy(i915->state.Tex[unit], state, sizeof(state));
713 }
714 }
715
716
717
718 static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
719 {
720 i915ContextPtr i915 = I915_CONTEXT(ctx);
721 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
722 struct gl_texture_object *tObj = texUnit->_Current;
723 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
724
725 if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, unit);
726
727 if (!(i915->state.active & I915_UPLOAD_TEX(unit))) {
728 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
729 }
730
731 /* Fallback if there's a texture border */
732 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
733 return GL_FALSE;
734 }
735
736
737 /* Update state if this is a different texture object to last
738 * time.
739 */
740 if (i915->intel.CurrentTexObj[unit] != &t->intel ||
741 (t->intel.dirty & I915_UPLOAD_TEX(unit))) {
742 i915_import_tex_unit( i915, t, unit);
743 i915->tex_program.translated = 0;
744 }
745
746 return GL_TRUE;
747 }
748
749 static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
750 {
751 i915ContextPtr i915 = I915_CONTEXT(ctx);
752 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
753 struct gl_texture_object *tObj = texUnit->_Current;
754 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
755 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
756
757 ss3 &= ~SS3_NORMALIZED_COORDS;
758
759 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
760 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
761 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
762 }
763
764 /* Upload teximages (not pipelined)
765 */
766 if (t->intel.base.dirty_images[0]) {
767 i915SetTexImages( i915, tObj );
768 if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
769 return GL_FALSE;
770 }
771 }
772
773 return GL_TRUE;
774 }
775
776
777 static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
778 {
779 i915ContextPtr i915 = I915_CONTEXT(ctx);
780 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
781 struct gl_texture_object *tObj = texUnit->_Current;
782 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
783 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
784
785 ss3 |= SS3_NORMALIZED_COORDS;
786
787 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
788 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
789 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
790 }
791
792 /* Upload teximages (not pipelined)
793 */
794 if (t->intel.base.dirty_images[0]) {
795 i915SetTexImages( i915, tObj );
796 if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
797 return GL_FALSE;
798 }
799 }
800
801 return GL_TRUE;
802 }
803
804 static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
805 {
806 i915ContextPtr i915 = I915_CONTEXT(ctx);
807 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
808 struct gl_texture_object *tObj = texUnit->_Current;
809 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
810 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
811 GLuint face;
812
813 ss3 |= SS3_NORMALIZED_COORDS;
814
815 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
816 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
817 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
818 }
819
820 /* Upload teximages (not pipelined)
821 */
822 if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
823 t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
824 t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
825 i915SetTexImages( i915, tObj );
826 }
827
828 /* upload (per face) */
829 for (face = 0; face < 6; face++) {
830 if (t->intel.base.dirty_images[face]) {
831 if (!intelUploadTexImages( &i915->intel, &t->intel, face )) {
832 return GL_FALSE;
833 }
834 }
835 }
836
837
838 return GL_TRUE;
839 }
840
841 static GLboolean enable_tex_3d( GLcontext *ctx, GLuint unit )
842 {
843 struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
844 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
845
846 /* 3D textures on I915 seem to get bogus border colors, hence this
847 * fallback:
848 */
849 if (t->refs_border_color)
850 return GL_FALSE;
851
852 return GL_TRUE;
853 }
854
855
856
857
858 static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
859 {
860 i915ContextPtr i915 = I915_CONTEXT(ctx);
861
862 if (i915->state.active & I915_UPLOAD_TEX(unit)) {
863 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_FALSE);
864 }
865
866 /* The old texture is no longer bound to this texture unit.
867 * Mark it as such.
868 */
869 if ( i915->intel.CurrentTexObj[unit] != NULL ) {
870 i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
871 i915->intel.CurrentTexObj[unit] = NULL;
872 }
873
874 return GL_TRUE;
875 }
876
877 static GLboolean i915UpdateTexUnit( GLcontext *ctx, GLuint unit )
878 {
879 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
880
881 if (texUnit->_ReallyEnabled &&
882 INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024)
883 return GL_FALSE;
884
885 switch (texUnit->_ReallyEnabled) {
886 case TEXTURE_1D_BIT:
887 case TEXTURE_2D_BIT:
888 return (enable_tex_2d( ctx, unit ) &&
889 enable_tex_common( ctx, unit ));
890 case TEXTURE_RECT_BIT:
891 return (enable_tex_rect( ctx, unit ) &&
892 enable_tex_common( ctx, unit ));
893 case TEXTURE_CUBE_BIT:
894 return (enable_tex_cube( ctx, unit ) &&
895 enable_tex_common( ctx, unit ));
896 case TEXTURE_3D_BIT:
897 return (enable_tex_2d( ctx, unit ) &&
898 enable_tex_common( ctx, unit ) &&
899 enable_tex_3d( ctx, unit));
900 case 0:
901 return disable_tex( ctx, unit );
902 default:
903 return GL_FALSE;
904 }
905 }
906
907
908 void i915UpdateTextureState( intelContextPtr intel )
909 {
910 GLcontext *ctx = &intel->ctx;
911 GLboolean ok = GL_TRUE;
912 GLuint i;
913
914 for (i = 0 ; i < I915_TEX_UNITS && ok ; i++) {
915 ok = i915UpdateTexUnit( ctx, i );
916 }
917
918 FALLBACK( intel, I915_FALLBACK_TEXTURE, !ok );
919 }
920
921
922