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
)
177 if (t
->intel
.image
[0][i
].image
->Height
> 4)
178 total_height
+= t
->intel
.image
[0][i
].image
->Height
/4;
183 total_height
+= MAX2(2, t
->intel
.image
[0][i
].image
->Height
);
188 t
->intel
.Pitch
= pitch
;
189 t
->intel
.base
.totalSize
= total_height
*pitch
;
190 t
->intel
.max_level
= numLevels
-1;
194 static void i945LayoutTextureImages( i915ContextPtr i915
,
195 struct gl_texture_object
*tObj
)
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
;
203 /* Compute which mipmap levels we really want to send to the hardware.
205 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
207 /* Figure out the amount of memory required to hold all the mipmap
208 * levels. Choose the smallest pitch to accomodate the largest
211 firstLevel
= t
->intel
.base
.firstLevel
;
212 lastLevel
= t
->intel
.base
.lastLevel
;
213 numLevels
= lastLevel
- firstLevel
+ 1;
217 /* All images must be loaded at this pitch. Count the number of
220 switch (tObj
->Target
) {
221 case GL_TEXTURE_CUBE_MAP
: {
222 const GLuint dim
= tObj
->Image
[0][firstLevel
]->Width
;
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.
230 pitch
= dim
* t
->intel
.texelBytes
;
231 pitch
*= 2; /* double pitch for cube layouts */
232 pitch
= (pitch
+ 3) & ~3;
235 pitch
= 14 * 8 * t
->intel
.texelBytes
; /* determined by row of
240 total_height
= dim
* 4 + 4;
242 for ( face
= 0 ; face
< 6 ; face
++) {
243 GLuint x
= initial_offsets
[face
][0] * dim
;
244 GLuint y
= initial_offsets
[face
][1] * dim
;
247 if (dim
== 4 && face
>= 4) {
248 y
= total_height
- 4;
252 y
= total_height
- 4;
256 t
->intel
.base
.dirty_images
[face
] = ~0;
258 assert(tObj
->Image
[face
][firstLevel
]->Width
== dim
);
259 assert(tObj
->Image
[face
][firstLevel
]->Height
== dim
);
261 for (i
= 0; i
< numLevels
; i
++) {
264 t
->intel
.image
[face
][i
].image
= tObj
->Image
[face
][firstLevel
+ i
];
265 assert(t
->intel
.image
[face
][i
].image
);
267 t
->intel
.image
[face
][i
].offset
=
268 y
* pitch
+ x
* t
->intel
.texelBytes
;
269 t
->intel
.image
[face
][i
].internalFormat
= baseImage
->_BaseFormat
;
278 x
+= step_offsets
[face
][0] * d
;
279 y
+= step_offsets
[face
][1] * d
;
288 y
= total_height
- 4;
294 y
= total_height
- 4;
303 x
+= step_offsets
[face
][0] * d
;
304 y
+= step_offsets
[face
][1] * d
;
309 max_offset
= total_height
* pitch
;
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
;
319 t
->intel
.base
.dirty_images
[0] = ~0;
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
)
328 t
->intel
.image
[0][i
].offset
= total_height
* pitch
;
329 t
->intel
.image
[0][i
].internalFormat
= baseImage
->_BaseFormat
;
333 total_height
+= MAX2(2, t
->intel
.image
[0][i
].image
->Height
) *
334 MAX2((t
->intel
.image
[0][i
].image
->Depth
>> depth_packing
), 1);
336 /* When alignment dominates, can't increase depth packing?
337 * Or does pitch grow??? What are the alignment constraints,
340 if (depth_pack_pitch
> 4) {
342 depth_pack_pitch
<<= 2;
346 max_offset
= total_height
* pitch
;
350 pitch
= tObj
->Image
[0][firstLevel
]->Width
* t
->intel
.texelBytes
;
351 pitch
= (pitch
+ 3) & ~3;
352 t
->intel
.base
.dirty_images
[0] = ~0;
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
)
360 t
->intel
.image
[0][i
].offset
= offset
;
361 t
->intel
.image
[0][i
].internalFormat
= baseImage
->_BaseFormat
;
363 if (t
->intel
.image
[0][i
].image
->IsCompressed
)
364 sz
= MAX2(1, t
->intel
.image
[0][i
].image
->Height
/4) * pitch
;
366 sz
= MAX2(2, t
->intel
.image
[0][i
].image
->Height
) * pitch
;
368 /* Because the images are packed better, the final offset
369 * might not be the maximal one:
371 max_offset
= MAX2(max_offset
, offset
+ sz
);
373 /* LPT change: step right after second mipmap.
384 t
->intel
.Pitch
= pitch
;
385 t
->intel
.base
.totalSize
= max_offset
;
386 t
->intel
.max_level
= numLevels
-1;
392 static void i915SetTexImages( i915ContextPtr i915
,
393 struct gl_texture_object
*tObj
)
395 GLuint textureFormat
;
396 i915TextureObjectPtr t
= (i915TextureObjectPtr
) tObj
->DriverData
;
397 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
400 switch( baseImage
->TexFormat
->MesaFormat
) {
402 t
->intel
.texelBytes
= 1;
403 textureFormat
= MAPSURF_8BIT
| MT_8BIT_L8
;
407 t
->intel
.texelBytes
= 1;
408 textureFormat
= MAPSURF_8BIT
| MT_8BIT_I8
;
412 t
->intel
.texelBytes
= 1;
413 textureFormat
= MAPSURF_8BIT
| MT_8BIT_A8
;
416 case MESA_FORMAT_AL88
:
417 t
->intel
.texelBytes
= 2;
418 textureFormat
= MAPSURF_16BIT
| MT_16BIT_AY88
;
421 case MESA_FORMAT_RGB565
:
422 t
->intel
.texelBytes
= 2;
423 textureFormat
= MAPSURF_16BIT
| MT_16BIT_RGB565
;
426 case MESA_FORMAT_ARGB1555
:
427 t
->intel
.texelBytes
= 2;
428 textureFormat
= MAPSURF_16BIT
| MT_16BIT_ARGB1555
;
431 case MESA_FORMAT_ARGB4444
:
432 t
->intel
.texelBytes
= 2;
433 textureFormat
= MAPSURF_16BIT
| MT_16BIT_ARGB4444
;
436 case MESA_FORMAT_ARGB8888
:
437 t
->intel
.texelBytes
= 4;
438 textureFormat
= MAPSURF_32BIT
| MT_32BIT_ARGB8888
;
441 case MESA_FORMAT_YCBCR_REV
:
442 t
->intel
.texelBytes
= 2;
443 textureFormat
= (MAPSURF_422
| MT_422_YCRCB_NORMAL
);
444 ss2
|= SS2_COLORSPACE_CONVERSION
;
447 case MESA_FORMAT_YCBCR
:
448 t
->intel
.texelBytes
= 2;
449 textureFormat
= (MAPSURF_422
| MT_422_YCRCB_SWAPY
);
450 ss2
|= SS2_COLORSPACE_CONVERSION
;
453 case MESA_FORMAT_RGB_FXT1
:
454 case MESA_FORMAT_RGBA_FXT1
:
455 t
->intel
.texelBytes
= 2;
456 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_FXT1
);
459 case MESA_FORMAT_Z16
:
460 t
->intel
.texelBytes
= 2;
461 textureFormat
= (MAPSURF_16BIT
| MT_16BIT_L16
);
464 case MESA_FORMAT_RGBA_DXT1
:
465 case MESA_FORMAT_RGB_DXT1
:
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
471 t
->intel
.texelBytes
= 2;
472 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_DXT1
);
475 case MESA_FORMAT_RGBA_DXT3
:
476 t
->intel
.texelBytes
= 4;
477 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_DXT2_3
);
480 case MESA_FORMAT_RGBA_DXT5
:
481 t
->intel
.texelBytes
= 4;
482 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_DXT4_5
);
486 case MESA_FORMAT_Z24_S8
:
487 t
->intel
.texelBytes
= 4;
488 textureFormat
= (MAPSURF_32BIT
| MT_32BIT_xL824
);
493 fprintf(stderr
, "%s: bad image format %x\n", __FUNCTION__
,
494 baseImage
->TexFormat
->MesaFormat
);
499 if (i915
->intel
.intelScreen
->deviceID
== PCI_CHIP_I945_G
||
500 i915
->intel
.intelScreen
->deviceID
== PCI_CHIP_I945_GM
)
501 i945LayoutTextureImages( i915
, tObj
);
503 i915LayoutTextureImages( i915
, tObj
);
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
) |
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
));
517 t
->Setup
[I915_TEXREG_SS2
] &= ~(SS2_COLORSPACE_CONVERSION
);
518 t
->Setup
[I915_TEXREG_SS2
] |= ss2
;
520 t
->intel
.dirty
= I915_UPLOAD_TEX_ALL
;
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.
529 static GLuint
translate_wrap_mode( GLenum 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
;
544 static void i915ImportTexObjState( struct gl_texture_object
*texObj
)
546 i915TextureObjectPtr t
= (i915TextureObjectPtr
)texObj
->DriverData
;
547 int minFilt
= 0, mipFilt
= 0, magFilt
= 0, shadow
= 0;
549 if(INTEL_DEBUG
&DEBUG_DRI
)
550 fprintf(stderr
, "%s\n", __FUNCTION__
);
552 switch (texObj
->MinFilter
) {
554 minFilt
= FILTER_NEAREST
;
555 mipFilt
= MIPFILTER_NONE
;
558 minFilt
= FILTER_LINEAR
;
559 mipFilt
= MIPFILTER_NONE
;
561 case GL_NEAREST_MIPMAP_NEAREST
:
562 minFilt
= FILTER_NEAREST
;
563 mipFilt
= MIPFILTER_NEAREST
;
565 case GL_LINEAR_MIPMAP_NEAREST
:
566 minFilt
= FILTER_LINEAR
;
567 mipFilt
= MIPFILTER_NEAREST
;
569 case GL_NEAREST_MIPMAP_LINEAR
:
570 minFilt
= FILTER_NEAREST
;
571 mipFilt
= MIPFILTER_LINEAR
;
573 case GL_LINEAR_MIPMAP_LINEAR
:
574 minFilt
= FILTER_LINEAR
;
575 mipFilt
= MIPFILTER_LINEAR
;
581 if ( texObj
->MaxAnisotropy
> 1.0 ) {
582 minFilt
= FILTER_ANISOTROPIC
;
583 magFilt
= FILTER_ANISOTROPIC
;
586 switch (texObj
->MagFilter
) {
588 magFilt
= FILTER_NEAREST
;
591 magFilt
= FILTER_LINEAR
;
598 if (texObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
&&
599 texObj
->Target
!= GL_TEXTURE_3D
) {
601 shadow
= SS2_SHADOW_ENABLE
;
602 shadow
|= intel_translate_compare_func( texObj
->CompareFunc
);
604 minFilt
= FILTER_4X4_FLAT
;
605 magFilt
= FILTER_4X4_FLAT
;
609 t
->Setup
[I915_TEXREG_SS2
] &= ~(SS2_MIN_FILTER_MASK
|
610 SS2_MIP_FILTER_MASK
|
611 SS2_MAG_FILTER_MASK
|
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
) |
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
;
627 t
->refs_border_color
= 0;
629 if (texObj
->Target
== GL_TEXTURE_3D
&&
630 (texObj
->MinFilter
!= GL_NEAREST
||
631 texObj
->MagFilter
!= GL_NEAREST
)) {
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
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
;
643 /* 3D textures don't seem to respect the border color.
644 * Fallback if there's ever a danger that they might refer to
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;
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
;
656 if (ss3
!= t
->Setup
[I915_TEXREG_SS3
]) {
657 t
->intel
.dirty
= I915_UPLOAD_TEX_ALL
;
658 t
->Setup
[I915_TEXREG_SS3
] = ss3
;
663 const GLubyte
*color
= texObj
->_BorderChan
;
665 t
->Setup
[I915_TEXREG_SS4
] = INTEL_PACKCOLOR8888(color
[0],color
[1],
672 static void i915_import_tex_unit( i915ContextPtr i915
,
673 i915TextureObjectPtr t
,
676 GLuint state
[I915_TEX_SETUP_SIZE
];
678 if(INTEL_DEBUG
&DEBUG_TEXTURE
)
679 fprintf(stderr
, "%s unit(%d)\n", __FUNCTION__
, unit
);
681 if (i915
->intel
.CurrentTexObj
[unit
])
682 i915
->intel
.CurrentTexObj
[unit
]->base
.bound
&= ~(1U << unit
);
684 i915
->intel
.CurrentTexObj
[unit
] = (intelTextureObjectPtr
)t
;
685 t
->intel
.base
.bound
|= (1 << unit
);
687 if (t
->intel
.dirty
& I915_UPLOAD_TEX(unit
)) {
688 i915ImportTexObjState( t
->intel
.base
.tObj
);
689 t
->intel
.dirty
&= ~I915_UPLOAD_TEX(unit
);
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
];
696 state
[I915_TEXREG_SS2
] = (i915
->state
.Tex
[unit
][I915_TEXREG_SS2
] &
698 state
[I915_TEXREG_SS2
] |= (t
->Setup
[I915_TEXREG_SS2
] & ~SS2_LOD_BIAS_MASK
);
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
));
706 state
[I915_TEXREG_SS3
] |= (unit
<<SS3_TEXTUREMAP_INDEX_SHIFT
);
708 state
[I915_TEXREG_SS4
] = t
->Setup
[I915_TEXREG_SS4
];
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
));
719 static GLboolean
enable_tex_common( GLcontext
*ctx
, GLuint unit
)
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
;
726 if (0) fprintf(stderr
, "%s %d\n", __FUNCTION__
, unit
);
728 if (!(i915
->state
.active
& I915_UPLOAD_TEX(unit
))) {
729 I915_ACTIVESTATE(i915
, I915_UPLOAD_TEX(unit
), GL_TRUE
);
732 /* Fallback if there's a texture border */
733 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
738 /* Update state if this is a different texture object to last
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;
750 static GLboolean
enable_tex_rect( GLcontext
*ctx
, GLuint unit
)
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
];
758 ss3
&= ~SS3_NORMALIZED_COORDS
;
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
;
765 /* Upload teximages (not pipelined)
767 if (t
->intel
.base
.dirty_images
[0]) {
768 i915SetTexImages( i915
, tObj
);
769 if (!intelUploadTexImages( &i915
->intel
, &t
->intel
, 0 )) {
778 static GLboolean
enable_tex_2d( GLcontext
*ctx
, GLuint unit
)
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
];
786 ss3
|= SS3_NORMALIZED_COORDS
;
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
;
793 /* Upload teximages (not pipelined)
795 if (t
->intel
.base
.dirty_images
[0]) {
796 i915SetTexImages( i915
, tObj
);
797 if (!intelUploadTexImages( &i915
->intel
, &t
->intel
, 0 )) {
805 static GLboolean
enable_tex_cube( GLcontext
*ctx
, GLuint unit
)
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
];
814 ss3
|= SS3_NORMALIZED_COORDS
;
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
;
821 /* Upload teximages (not pipelined)
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
);
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
)) {
842 static GLboolean
enable_tex_3d( GLcontext
*ctx
, GLuint unit
)
844 struct gl_texture_object
*tObj
= ctx
->Texture
.Unit
[unit
]._Current
;
845 i915TextureObjectPtr t
= (i915TextureObjectPtr
)tObj
->DriverData
;
847 /* 3D textures on I915 seem to get bogus border colors, hence this
850 if (t
->refs_border_color
)
859 static GLboolean
disable_tex( GLcontext
*ctx
, GLuint unit
)
861 i915ContextPtr i915
= I915_CONTEXT(ctx
);
863 if (i915
->state
.active
& I915_UPLOAD_TEX(unit
)) {
864 I915_ACTIVESTATE(i915
, I915_UPLOAD_TEX(unit
), GL_FALSE
);
867 /* The old texture is no longer bound to this texture unit.
870 if ( i915
->intel
.CurrentTexObj
[unit
] != NULL
) {
871 i915
->intel
.CurrentTexObj
[unit
]->base
.bound
&= ~(1U << 0);
872 i915
->intel
.CurrentTexObj
[unit
] = NULL
;
878 static GLboolean
i915UpdateTexUnit( GLcontext
*ctx
, GLuint unit
)
880 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
882 if (texUnit
->_ReallyEnabled
&&
883 INTEL_CONTEXT(ctx
)->intelScreen
->tex
.size
< 2048 * 1024)
886 switch (texUnit
->_ReallyEnabled
) {
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
));
898 return (enable_tex_2d( ctx
, unit
) &&
899 enable_tex_common( ctx
, unit
) &&
900 enable_tex_3d( ctx
, unit
));
902 return disable_tex( ctx
, unit
);
909 void i915UpdateTextureState( intelContextPtr intel
)
911 GLcontext
*ctx
= &intel
->ctx
;
912 GLboolean ok
= GL_TRUE
;
915 for (i
= 0 ; i
< I915_TEX_UNITS
&& ok
; i
++) {
916 ok
= i915UpdateTexUnit( ctx
, i
);
919 FALLBACK( intel
, I915_FALLBACK_TEXTURE
, !ok
);