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 "i830_context.h"
46 #define I830_TEX_UNIT_ENABLED(unit) (1<<unit)
48 static GLboolean
i830SetTexImages( i830ContextPtr i830
,
49 struct gl_texture_object
*tObj
)
51 GLuint total_height
, pitch
, i
, textureFormat
;
52 i830TextureObjectPtr t
= (i830TextureObjectPtr
) tObj
->DriverData
;
53 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
54 GLint firstLevel
, lastLevel
, numLevels
;
56 switch( baseImage
->TexFormat
->MesaFormat
) {
58 t
->intel
.texelBytes
= 1;
59 textureFormat
= MAPSURF_8BIT
| MT_8BIT_L8
;
63 t
->intel
.texelBytes
= 1;
64 textureFormat
= MAPSURF_8BIT
| MT_8BIT_I8
;
68 t
->intel
.texelBytes
= 1;
69 textureFormat
= MAPSURF_8BIT
| MT_8BIT_I8
; /* Kludge -- check with conform, glean */
72 case MESA_FORMAT_AL88
:
73 t
->intel
.texelBytes
= 2;
74 textureFormat
= MAPSURF_16BIT
| MT_16BIT_AY88
;
77 case MESA_FORMAT_RGB565
:
78 t
->intel
.texelBytes
= 2;
79 textureFormat
= MAPSURF_16BIT
| MT_16BIT_RGB565
;
82 case MESA_FORMAT_ARGB1555
:
83 t
->intel
.texelBytes
= 2;
84 textureFormat
= MAPSURF_16BIT
| MT_16BIT_ARGB1555
;
87 case MESA_FORMAT_ARGB4444
:
88 t
->intel
.texelBytes
= 2;
89 textureFormat
= MAPSURF_16BIT
| MT_16BIT_ARGB4444
;
92 case MESA_FORMAT_ARGB8888
:
93 t
->intel
.texelBytes
= 4;
94 textureFormat
= MAPSURF_32BIT
| MT_32BIT_ARGB8888
;
97 case MESA_FORMAT_YCBCR_REV
:
98 t
->intel
.texelBytes
= 2;
99 textureFormat
= (MAPSURF_422
| MT_422_YCRCB_NORMAL
|
100 TM0S1_COLORSPACE_CONVERSION
);
103 case MESA_FORMAT_YCBCR
:
104 t
->intel
.texelBytes
= 2;
105 textureFormat
= (MAPSURF_422
| MT_422_YCRCB_SWAPY
| /* ??? */
106 TM0S1_COLORSPACE_CONVERSION
);
109 case MESA_FORMAT_RGB_FXT1
:
110 case MESA_FORMAT_RGBA_FXT1
:
111 t
->intel
.texelBytes
= 2;
112 textureFormat
= MAPSURF_COMPRESSED
| MT_COMPRESS_FXT1
;
116 fprintf(stderr
, "%s: bad image format\n", __FUNCTION__
);
120 /* Compute which mipmap levels we really want to send to the hardware.
121 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
122 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
123 * Yes, this looks overly complicated, but it's all needed.
125 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
128 /* Figure out the amount of memory required to hold all the mipmap
129 * levels. Choose the smallest pitch to accomodate the largest
132 firstLevel
= t
->intel
.base
.firstLevel
;
133 lastLevel
= t
->intel
.base
.lastLevel
;
134 numLevels
= lastLevel
- firstLevel
+ 1;
136 /* Pitch would be subject to additional rules if texture memory were
137 * tiled. Currently it isn't.
141 while (pitch
< tObj
->Image
[0][firstLevel
]->Width
* t
->intel
.texelBytes
)
145 pitch
= tObj
->Image
[0][firstLevel
]->Width
* t
->intel
.texelBytes
;
146 pitch
= (pitch
+ 3) & ~3;
150 /* All images must be loaded at this pitch. Count the number of
153 for ( total_height
= i
= 0 ; i
< numLevels
; i
++ ) {
154 t
->intel
.image
[0][i
].image
= tObj
->Image
[0][firstLevel
+ i
];
155 if (!t
->intel
.image
[0][i
].image
)
158 t
->intel
.image
[0][i
].offset
= total_height
* pitch
;
159 t
->intel
.image
[0][i
].internalFormat
= baseImage
->Format
;
160 if (t
->intel
.image
[0][i
].image
->IsCompressed
)
162 if (t
->intel
.image
[0][i
].image
->Height
> 4)
163 total_height
+= t
->intel
.image
[0][i
].image
->Height
/4;
168 total_height
+= MAX2(2, t
->intel
.image
[0][i
].image
->Height
);
171 t
->intel
.Pitch
= pitch
;
172 t
->intel
.base
.totalSize
= total_height
*pitch
;
173 t
->intel
.max_level
= i
-1;
174 t
->Setup
[I830_TEXREG_TM0S1
] =
175 (((tObj
->Image
[0][firstLevel
]->Height
- 1) << TM0S1_HEIGHT_SHIFT
) |
176 ((tObj
->Image
[0][firstLevel
]->Width
- 1) << TM0S1_WIDTH_SHIFT
) |
178 t
->Setup
[I830_TEXREG_TM0S2
] =
179 (((pitch
/ 4) - 1) << TM0S2_PITCH_SHIFT
);
180 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MAX_MIP_MASK
;
181 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MIN_MIP_MASK
;
182 t
->Setup
[I830_TEXREG_TM0S3
] |= ((numLevels
- 1)*4) << TM0S3_MIN_MIP_SHIFT
;
183 t
->intel
.dirty
= I830_UPLOAD_TEX_ALL
;
185 return intelUploadTexImages( &i830
->intel
, &t
->intel
, 0 );
189 static void i830_import_tex_unit( i830ContextPtr i830
,
190 i830TextureObjectPtr t
,
193 if(INTEL_DEBUG
&DEBUG_TEXTURE
)
194 fprintf(stderr
, "%s unit(%d)\n", __FUNCTION__
, unit
);
196 if (i830
->intel
.CurrentTexObj
[unit
])
197 i830
->intel
.CurrentTexObj
[unit
]->base
.bound
&= ~(1U << unit
);
199 i830
->intel
.CurrentTexObj
[unit
] = (intelTextureObjectPtr
)t
;
200 t
->intel
.base
.bound
|= (1 << unit
);
202 I830_STATECHANGE( i830
, I830_UPLOAD_TEX(unit
) );
204 i830
->state
.Tex
[unit
][I830_TEXREG_TM0LI
] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2
|
205 (LOAD_TEXTURE_MAP0
<< unit
) | 4);
206 i830
->state
.Tex
[unit
][I830_TEXREG_TM0S0
] = (TM0S0_USE_FENCE
|
207 t
->intel
.TextureOffset
);
209 i830
->state
.Tex
[unit
][I830_TEXREG_TM0S1
] = t
->Setup
[I830_TEXREG_TM0S1
];
210 i830
->state
.Tex
[unit
][I830_TEXREG_TM0S2
] = t
->Setup
[I830_TEXREG_TM0S2
];
212 i830
->state
.Tex
[unit
][I830_TEXREG_TM0S3
] &= TM0S3_LOD_BIAS_MASK
;
213 i830
->state
.Tex
[unit
][I830_TEXREG_TM0S3
] |= (t
->Setup
[I830_TEXREG_TM0S3
] &
214 ~TM0S3_LOD_BIAS_MASK
);
216 i830
->state
.Tex
[unit
][I830_TEXREG_TM0S4
] = t
->Setup
[I830_TEXREG_TM0S4
];
217 i830
->state
.Tex
[unit
][I830_TEXREG_MCS
] = (t
->Setup
[I830_TEXREG_MCS
] &
219 i830
->state
.Tex
[unit
][I830_TEXREG_MCS
] |= MAP_UNIT(unit
);
221 t
->intel
.dirty
&= ~I830_UPLOAD_TEX(unit
);
226 static GLboolean
enable_tex_common( GLcontext
*ctx
, GLuint unit
)
228 i830ContextPtr i830
= I830_CONTEXT(ctx
);
229 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
230 struct gl_texture_object
*tObj
= texUnit
->_Current
;
231 i830TextureObjectPtr t
= (i830TextureObjectPtr
)tObj
->DriverData
;
233 if (0) fprintf(stderr
, "%s\n", __FUNCTION__
);
235 /* Fallback if there's a texture border */
236 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
237 fprintf(stderr
, "Texture border\n");
241 /* Upload teximages (not pipelined)
243 if (t
->intel
.base
.dirty_images
[0]) {
244 if (!i830SetTexImages( i830
, tObj
)) {
249 /* Update state if this is a different texture object to last
252 if (i830
->intel
.CurrentTexObj
[unit
] != &t
->intel
||
253 (t
->intel
.dirty
& I830_UPLOAD_TEX(unit
))) {
254 i830_import_tex_unit( i830
, t
, unit
);
257 I830_ACTIVESTATE(i830
, I830_UPLOAD_TEX(unit
), GL_TRUE
);
262 static GLboolean
enable_tex_rect( GLcontext
*ctx
, GLuint unit
)
264 i830ContextPtr i830
= I830_CONTEXT(ctx
);
265 GLuint mcs
= i830
->state
.Tex
[unit
][I830_TEXREG_MCS
];
267 mcs
&= ~TEXCOORDS_ARE_NORMAL
;
268 mcs
|= TEXCOORDS_ARE_IN_TEXELUNITS
;
270 if (mcs
!= i830
->state
.Tex
[unit
][I830_TEXREG_MCS
]) {
271 I830_STATECHANGE(i830
, I830_UPLOAD_TEX(unit
));
272 i830
->state
.Tex
[unit
][I830_TEXREG_MCS
] = mcs
;
279 static GLboolean
enable_tex_2d( GLcontext
*ctx
, GLuint unit
)
281 i830ContextPtr i830
= I830_CONTEXT(ctx
);
282 GLuint mcs
= i830
->state
.Tex
[unit
][I830_TEXREG_MCS
];
284 mcs
&= ~TEXCOORDS_ARE_IN_TEXELUNITS
;
285 mcs
|= TEXCOORDS_ARE_NORMAL
;
287 if (mcs
!= i830
->state
.Tex
[unit
][I830_TEXREG_MCS
]) {
288 I830_STATECHANGE(i830
, I830_UPLOAD_TEX(unit
));
289 i830
->state
.Tex
[unit
][I830_TEXREG_MCS
] = mcs
;
296 static GLboolean
disable_tex( GLcontext
*ctx
, GLuint unit
)
298 i830ContextPtr i830
= I830_CONTEXT(ctx
);
300 /* This is happening too often. I need to conditionally send diffuse
301 * state to the card. Perhaps a diffuse dirty flag of some kind.
302 * Will need to change this logic if more than 2 texture units are
303 * used. We need to only do this up to the last unit enabled, or unit
304 * one if nothing is enabled.
307 if ( i830
->intel
.CurrentTexObj
[unit
] != NULL
) {
308 /* The old texture is no longer bound to this texture unit.
312 i830
->intel
.CurrentTexObj
[unit
]->base
.bound
&= ~(1U << 0);
313 i830
->intel
.CurrentTexObj
[unit
] = NULL
;
319 static GLboolean
i830UpdateTexUnit( GLcontext
*ctx
, GLuint unit
)
321 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
323 if (texUnit
->_ReallyEnabled
&&
324 INTEL_CONTEXT(ctx
)->intelScreen
->textureSize
< 2048 * 1024)
327 if (texUnit
->_ReallyEnabled
== TEXTURE_1D_BIT
||
328 texUnit
->_ReallyEnabled
== TEXTURE_2D_BIT
) {
329 return (enable_tex_common( ctx
, unit
) &&
330 enable_tex_2d( ctx
, unit
));
332 else if (texUnit
->_ReallyEnabled
== TEXTURE_RECT_BIT
) {
333 return (enable_tex_common( ctx
, unit
) &&
334 enable_tex_rect( ctx
, unit
));
336 else if (texUnit
->_ReallyEnabled
) {
340 return disable_tex( ctx
, unit
);
345 void i830UpdateTextureState( intelContextPtr intel
)
347 i830ContextPtr i830
= I830_CONTEXT(intel
);
348 GLcontext
*ctx
= &intel
->ctx
;
351 if (0) fprintf(stderr
, "%s\n", __FUNCTION__
);
353 I830_ACTIVESTATE(i830
, I830_UPLOAD_TEX_ALL
, GL_FALSE
);
355 ok
= (i830UpdateTexUnit( ctx
, 0 ) &&
356 i830UpdateTexUnit( ctx
, 1 ) &&
357 i830UpdateTexUnit( ctx
, 2 ) &&
358 i830UpdateTexUnit( ctx
, 3 ));
360 FALLBACK( intel
, I830_FALLBACK_TEXTURE
, !ok
);
363 i830EmitTextureBlend( i830
);