1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
31 #include "simple_list.h"
33 #include "texformat.h"
38 #include "intel_screen.h"
39 #include "intel_ioctl.h"
40 #include "intel_tex.h"
42 #include "i915_context.h"
45 static GLint initial_offsets
[6][2] = { {0,0},
53 static GLint step_offsets
[6][2] = { {0,2},
61 #define I915_TEX_UNIT_ENABLED(unit) (1<<unit)
63 static void i915LayoutTextureImages( i915ContextPtr i915
,
64 struct gl_texture_object
*tObj
)
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
;
71 /* Compute which mipmap levels we really want to send to the hardware.
73 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
75 /* Figure out the amount of memory required to hold all the mipmap
76 * levels. Choose the smallest pitch to accomodate the largest
79 firstLevel
= t
->intel
.base
.firstLevel
;
80 lastLevel
= t
->intel
.base
.lastLevel
;
81 numLevels
= lastLevel
- firstLevel
+ 1;
85 /* All images must be loaded at this pitch. Count the number of
88 switch (tObj
->Target
) {
89 case GL_TEXTURE_CUBE_MAP
: {
90 const GLuint dim
= tObj
->Image
[0][firstLevel
]->Width
;
93 pitch
= dim
* t
->intel
.texelBytes
;
94 pitch
*= 2; /* double pitch for cube layouts */
95 pitch
= (pitch
+ 3) & ~3;
97 total_height
= dim
* 4;
99 for ( face
= 0 ; face
< 6 ; face
++) {
100 GLuint x
= initial_offsets
[face
][0] * dim
;
101 GLuint y
= initial_offsets
[face
][1] * dim
;
104 t
->intel
.base
.dirty_images
[face
] = ~0;
106 assert(tObj
->Image
[face
][firstLevel
]->Width
== dim
);
107 assert(tObj
->Image
[face
][firstLevel
]->Height
== dim
);
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 */
116 t
->intel
.image
[face
][i
].offset
=
117 y
* pitch
+ x
* t
->intel
.texelBytes
;
118 t
->intel
.image
[face
][i
].internalFormat
= baseImage
->_BaseFormat
;
121 x
+= step_offsets
[face
][0] * d
;
122 y
+= step_offsets
[face
][1] * d
;
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;
134 /* Calculate the size of a single slice. Hardware demands a
135 * minimum of 8 mipmaps, some of which might ultimately not be
138 if (tmp_numLevels
< 9)
141 virtual_height
= tObj
->Image
[0][firstLevel
]->Height
;
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
;
150 total_height
+= MAX2(2, virtual_height
);
151 virtual_height
>>= 1;
154 t
->intel
.depth_pitch
= total_height
* pitch
;
156 /* Multiply slice size by texture depth for total size. It's
157 * remarkable how wasteful of memory all the i8x0 texture
160 total_height
*= t
->intel
.image
[0][0].image
->Depth
;
164 pitch
= tObj
->Image
[0][firstLevel
]->Width
* t
->intel
.texelBytes
;
165 pitch
= (pitch
+ 3) & ~3;
166 t
->intel
.base
.dirty_images
[0] = ~0;
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
)
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;
179 total_height
+= MAX2(2, t
->intel
.image
[0][i
].image
->Height
);
184 t
->intel
.Pitch
= pitch
;
185 t
->intel
.base
.totalSize
= total_height
*pitch
;
186 t
->intel
.max_level
= numLevels
-1;
190 static void i945LayoutTextureImages( i915ContextPtr i915
,
191 struct gl_texture_object
*tObj
)
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
;
199 /* Compute which mipmap levels we really want to send to the hardware.
201 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
203 /* Figure out the amount of memory required to hold all the mipmap
204 * levels. Choose the smallest pitch to accomodate the largest
207 firstLevel
= t
->intel
.base
.firstLevel
;
208 lastLevel
= t
->intel
.base
.lastLevel
;
209 numLevels
= lastLevel
- firstLevel
+ 1;
213 /* All images must be loaded at this pitch. Count the number of
216 switch (tObj
->Target
) {
217 case GL_TEXTURE_CUBE_MAP
: {
218 const GLuint dim
= tObj
->Image
[0][firstLevel
]->Width
;
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.
226 pitch
= dim
* t
->intel
.texelBytes
;
227 pitch
*= 2; /* double pitch for cube layouts */
228 pitch
= (pitch
+ 3) & ~3;
231 pitch
= 14 * 8 * t
->intel
.texelBytes
; /* determined by row of
236 total_height
= dim
* 4 + 4;
238 for ( face
= 0 ; face
< 6 ; face
++) {
239 GLuint x
= initial_offsets
[face
][0] * dim
;
240 GLuint y
= initial_offsets
[face
][1] * dim
;
243 if (dim
== 4 && face
>= 4) {
244 y
= total_height
- 4;
248 y
= total_height
- 4;
252 t
->intel
.base
.dirty_images
[face
] = ~0;
254 assert(tObj
->Image
[face
][firstLevel
]->Width
== dim
);
255 assert(tObj
->Image
[face
][firstLevel
]->Height
== dim
);
257 for (i
= 0; i
< numLevels
; i
++) {
260 t
->intel
.image
[face
][i
].image
= tObj
->Image
[face
][firstLevel
+ i
];
261 assert(t
->intel
.image
[face
][i
].image
);
263 t
->intel
.image
[face
][i
].offset
=
264 y
* pitch
+ x
* t
->intel
.texelBytes
;
265 t
->intel
.image
[face
][i
].internalFormat
= baseImage
->_BaseFormat
;
274 x
+= step_offsets
[face
][0] * d
;
275 y
+= step_offsets
[face
][1] * d
;
284 y
= total_height
- 4;
290 y
= total_height
- 4;
299 x
+= step_offsets
[face
][0] * d
;
300 y
+= step_offsets
[face
][1] * d
;
305 max_offset
= total_height
* pitch
;
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
;
315 t
->intel
.base
.dirty_images
[0] = ~0;
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
)
324 t
->intel
.image
[0][i
].offset
= total_height
* pitch
;
325 t
->intel
.image
[0][i
].internalFormat
= baseImage
->_BaseFormat
;
329 total_height
+= MAX2(2, t
->intel
.image
[0][i
].image
->Height
) *
330 MAX2((t
->intel
.image
[0][i
].image
->Depth
>> depth_packing
), 1);
332 /* When alignment dominates, can't increase depth packing?
333 * Or does pitch grow??? What are the alignment constraints,
336 if (depth_pack_pitch
> 4) {
338 depth_pack_pitch
<<= 2;
342 max_offset
= total_height
* pitch
;
346 pitch
= tObj
->Image
[0][firstLevel
]->Width
* t
->intel
.texelBytes
;
347 pitch
= (pitch
+ 3) & ~3;
348 t
->intel
.base
.dirty_images
[0] = ~0;
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
)
356 t
->intel
.image
[0][i
].offset
= offset
;
357 t
->intel
.image
[0][i
].internalFormat
= baseImage
->_BaseFormat
;
359 if (t
->intel
.image
[0][i
].image
->IsCompressed
)
360 sz
= MAX2(1, t
->intel
.image
[0][i
].image
->Height
/4) * pitch
;
362 sz
= MAX2(2, t
->intel
.image
[0][i
].image
->Height
) * pitch
;
364 /* Because the images are packed better, the final offset
365 * might not be the maximal one:
367 max_offset
= MAX2(max_offset
, offset
+ sz
);
369 /* LPT change: step right after second mipmap.
380 t
->intel
.Pitch
= pitch
;
381 t
->intel
.base
.totalSize
= max_offset
;
382 t
->intel
.max_level
= numLevels
-1;
388 static void i915SetTexImages( i915ContextPtr i915
,
389 struct gl_texture_object
*tObj
)
391 GLuint textureFormat
;
392 i915TextureObjectPtr t
= (i915TextureObjectPtr
) tObj
->DriverData
;
393 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
396 switch( baseImage
->TexFormat
->MesaFormat
) {
398 t
->intel
.texelBytes
= 1;
399 textureFormat
= MAPSURF_8BIT
| MT_8BIT_L8
;
403 t
->intel
.texelBytes
= 1;
404 textureFormat
= MAPSURF_8BIT
| MT_8BIT_I8
;
408 t
->intel
.texelBytes
= 1;
409 textureFormat
= MAPSURF_8BIT
| MT_8BIT_A8
;
412 case MESA_FORMAT_AL88
:
413 t
->intel
.texelBytes
= 2;
414 textureFormat
= MAPSURF_16BIT
| MT_16BIT_AY88
;
417 case MESA_FORMAT_RGB565
:
418 t
->intel
.texelBytes
= 2;
419 textureFormat
= MAPSURF_16BIT
| MT_16BIT_RGB565
;
422 case MESA_FORMAT_ARGB1555
:
423 t
->intel
.texelBytes
= 2;
424 textureFormat
= MAPSURF_16BIT
| MT_16BIT_ARGB1555
;
427 case MESA_FORMAT_ARGB4444
:
428 t
->intel
.texelBytes
= 2;
429 textureFormat
= MAPSURF_16BIT
| MT_16BIT_ARGB4444
;
432 case MESA_FORMAT_ARGB8888
:
433 t
->intel
.texelBytes
= 4;
434 textureFormat
= MAPSURF_32BIT
| MT_32BIT_ARGB8888
;
437 case MESA_FORMAT_YCBCR_REV
:
438 t
->intel
.texelBytes
= 2;
439 textureFormat
= (MAPSURF_422
| MT_422_YCRCB_NORMAL
);
440 ss2
|= SS2_COLORSPACE_CONVERSION
;
443 case MESA_FORMAT_YCBCR
:
444 t
->intel
.texelBytes
= 2;
445 textureFormat
= (MAPSURF_422
| MT_422_YCRCB_SWAPY
);
446 ss2
|= SS2_COLORSPACE_CONVERSION
;
449 case MESA_FORMAT_RGB_FXT1
:
450 case MESA_FORMAT_RGBA_FXT1
:
451 t
->intel
.texelBytes
= 2;
452 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_FXT1
);
455 case MESA_FORMAT_Z16
:
456 t
->intel
.texelBytes
= 2;
457 textureFormat
= (MAPSURF_16BIT
| MT_16BIT_L16
);
460 case MESA_FORMAT_RGBA_DXT1
:
461 case MESA_FORMAT_RGB_DXT1
:
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
467 t
->intel
.texelBytes
= 2;
468 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_DXT1
);
471 case MESA_FORMAT_RGBA_DXT3
:
472 t
->intel
.texelBytes
= 4;
473 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_DXT2_3
);
476 case MESA_FORMAT_RGBA_DXT5
:
477 t
->intel
.texelBytes
= 4;
478 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_DXT4_5
);
482 case MESA_FORMAT_Z24_S8
:
483 t
->intel
.texelBytes
= 4;
484 textureFormat
= (MAPSURF_32BIT
| MT_32BIT_xL824
);
489 fprintf(stderr
, "%s: bad image format %x\n", __FUNCTION__
,
490 baseImage
->TexFormat
->MesaFormat
);
494 switch (i915
->intel
.intelScreen
->deviceID
) {
495 case PCI_CHIP_I945_G
:
496 case PCI_CHIP_I945_GM
:
497 case PCI_CHIP_I945_GME
:
501 i945LayoutTextureImages( i915
, tObj
);
504 i915LayoutTextureImages( i915
, tObj
);
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
) |
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
));
520 t
->Setup
[I915_TEXREG_SS2
] &= ~(SS2_COLORSPACE_CONVERSION
);
521 t
->Setup
[I915_TEXREG_SS2
] |= ss2
;
523 t
->intel
.dirty
= I915_UPLOAD_TEX_ALL
;
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.
532 static GLuint
translate_wrap_mode( GLenum 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
;
547 static void i915ImportTexObjState( struct gl_texture_object
*texObj
)
549 i915TextureObjectPtr t
= (i915TextureObjectPtr
)texObj
->DriverData
;
550 int minFilt
= 0, mipFilt
= 0, magFilt
= 0, shadow
= 0;
552 if(INTEL_DEBUG
&DEBUG_DRI
)
553 fprintf(stderr
, "%s\n", __FUNCTION__
);
555 switch (texObj
->MinFilter
) {
557 minFilt
= FILTER_NEAREST
;
558 mipFilt
= MIPFILTER_NONE
;
561 minFilt
= FILTER_LINEAR
;
562 mipFilt
= MIPFILTER_NONE
;
564 case GL_NEAREST_MIPMAP_NEAREST
:
565 minFilt
= FILTER_NEAREST
;
566 mipFilt
= MIPFILTER_NEAREST
;
568 case GL_LINEAR_MIPMAP_NEAREST
:
569 minFilt
= FILTER_LINEAR
;
570 mipFilt
= MIPFILTER_NEAREST
;
572 case GL_NEAREST_MIPMAP_LINEAR
:
573 minFilt
= FILTER_NEAREST
;
574 mipFilt
= MIPFILTER_LINEAR
;
576 case GL_LINEAR_MIPMAP_LINEAR
:
577 minFilt
= FILTER_LINEAR
;
578 mipFilt
= MIPFILTER_LINEAR
;
584 if ( texObj
->MaxAnisotropy
> 1.0 ) {
585 minFilt
= FILTER_ANISOTROPIC
;
586 magFilt
= FILTER_ANISOTROPIC
;
589 switch (texObj
->MagFilter
) {
591 magFilt
= FILTER_NEAREST
;
594 magFilt
= FILTER_LINEAR
;
601 if (texObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
&&
602 texObj
->Target
!= GL_TEXTURE_3D
) {
604 shadow
= SS2_SHADOW_ENABLE
;
605 shadow
|= intel_translate_compare_func( texObj
->CompareFunc
);
607 minFilt
= FILTER_4X4_FLAT
;
608 magFilt
= FILTER_4X4_FLAT
;
612 t
->Setup
[I915_TEXREG_SS2
] &= ~(SS2_MIN_FILTER_MASK
|
613 SS2_MIP_FILTER_MASK
|
614 SS2_MAG_FILTER_MASK
|
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
) |
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
;
630 t
->refs_border_color
= 0;
632 if (texObj
->Target
== GL_TEXTURE_3D
&&
633 (texObj
->MinFilter
!= GL_NEAREST
||
634 texObj
->MagFilter
!= GL_NEAREST
)) {
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
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
;
646 /* 3D textures don't seem to respect the border color.
647 * Fallback if there's ever a danger that they might refer to
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;
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
;
659 if (ss3
!= t
->Setup
[I915_TEXREG_SS3
]) {
660 t
->intel
.dirty
= I915_UPLOAD_TEX_ALL
;
661 t
->Setup
[I915_TEXREG_SS3
] = ss3
;
666 const GLubyte
*color
= texObj
->_BorderChan
;
668 t
->Setup
[I915_TEXREG_SS4
] = INTEL_PACKCOLOR8888(color
[0],color
[1],
675 static void i915_import_tex_unit( i915ContextPtr i915
,
676 i915TextureObjectPtr t
,
679 GLuint state
[I915_TEX_SETUP_SIZE
];
681 if(INTEL_DEBUG
&DEBUG_TEXTURE
)
682 fprintf(stderr
, "%s unit(%d)\n", __FUNCTION__
, unit
);
684 if (i915
->intel
.CurrentTexObj
[unit
])
685 i915
->intel
.CurrentTexObj
[unit
]->base
.bound
&= ~(1U << unit
);
687 i915
->intel
.CurrentTexObj
[unit
] = (intelTextureObjectPtr
)t
;
688 t
->intel
.base
.bound
|= (1 << unit
);
690 if (t
->intel
.dirty
& I915_UPLOAD_TEX(unit
)) {
691 i915ImportTexObjState( t
->intel
.base
.tObj
);
692 t
->intel
.dirty
&= ~I915_UPLOAD_TEX(unit
);
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
];
699 state
[I915_TEXREG_SS2
] = (i915
->state
.Tex
[unit
][I915_TEXREG_SS2
] &
701 state
[I915_TEXREG_SS2
] |= (t
->Setup
[I915_TEXREG_SS2
] & ~SS2_LOD_BIAS_MASK
);
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
));
709 state
[I915_TEXREG_SS3
] |= (unit
<<SS3_TEXTUREMAP_INDEX_SHIFT
);
711 state
[I915_TEXREG_SS4
] = t
->Setup
[I915_TEXREG_SS4
];
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
));
722 static GLboolean
enable_tex_common( GLcontext
*ctx
, GLuint unit
)
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
;
729 if (0) fprintf(stderr
, "%s %d\n", __FUNCTION__
, unit
);
731 if (!(i915
->state
.active
& I915_UPLOAD_TEX(unit
))) {
732 I915_ACTIVESTATE(i915
, I915_UPLOAD_TEX(unit
), GL_TRUE
);
735 /* Fallback if there's a texture border */
736 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
741 /* Update state if this is a different texture object to last
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;
753 static GLboolean
enable_tex_rect( GLcontext
*ctx
, GLuint unit
)
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
];
761 ss3
&= ~SS3_NORMALIZED_COORDS
;
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
;
768 /* Upload teximages (not pipelined)
770 if (t
->intel
.base
.dirty_images
[0]) {
771 i915SetTexImages( i915
, tObj
);
772 if (!intelUploadTexImages( &i915
->intel
, &t
->intel
, 0 )) {
781 static GLboolean
enable_tex_2d( GLcontext
*ctx
, GLuint unit
)
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
];
789 ss3
|= SS3_NORMALIZED_COORDS
;
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
;
796 /* Upload teximages (not pipelined)
798 if (t
->intel
.base
.dirty_images
[0]) {
799 i915SetTexImages( i915
, tObj
);
800 if (!intelUploadTexImages( &i915
->intel
, &t
->intel
, 0 )) {
808 static GLboolean
enable_tex_cube( GLcontext
*ctx
, GLuint unit
)
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
];
817 ss3
|= SS3_NORMALIZED_COORDS
;
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
;
824 /* Upload teximages (not pipelined)
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
);
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
)) {
845 static GLboolean
enable_tex_3d( GLcontext
*ctx
, GLuint unit
)
847 struct gl_texture_object
*tObj
= ctx
->Texture
.Unit
[unit
]._Current
;
848 i915TextureObjectPtr t
= (i915TextureObjectPtr
)tObj
->DriverData
;
850 /* 3D textures on I915 seem to get bogus border colors, hence this
853 if (t
->refs_border_color
)
862 static GLboolean
disable_tex( GLcontext
*ctx
, GLuint unit
)
864 i915ContextPtr i915
= I915_CONTEXT(ctx
);
866 if (i915
->state
.active
& I915_UPLOAD_TEX(unit
)) {
867 I915_ACTIVESTATE(i915
, I915_UPLOAD_TEX(unit
), GL_FALSE
);
870 /* The old texture is no longer bound to this texture unit.
873 if ( i915
->intel
.CurrentTexObj
[unit
] != NULL
) {
874 i915
->intel
.CurrentTexObj
[unit
]->base
.bound
&= ~(1U << 0);
875 i915
->intel
.CurrentTexObj
[unit
] = NULL
;
881 static GLboolean
i915UpdateTexUnit( GLcontext
*ctx
, GLuint unit
)
883 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
885 if (texUnit
->_ReallyEnabled
&&
886 INTEL_CONTEXT(ctx
)->intelScreen
->tex
.size
< 2048 * 1024)
889 switch (texUnit
->_ReallyEnabled
) {
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
));
901 return (enable_tex_2d( ctx
, unit
) &&
902 enable_tex_common( ctx
, unit
) &&
903 enable_tex_3d( ctx
, unit
));
905 return disable_tex( ctx
, unit
);
912 void i915UpdateTextureState( intelContextPtr intel
)
914 GLcontext
*ctx
= &intel
->ctx
;
915 GLboolean ok
= GL_TRUE
;
918 for (i
= 0 ; i
< I915_TEX_UNITS
&& ok
; i
++) {
919 ok
= i915UpdateTexUnit( ctx
, i
);
922 FALLBACK( intel
, I915_FALLBACK_TEXTURE
, !ok
);