Merge branch 'mesa_7_6_branch' into mesa_7_7_branch
[mesa.git] / src / mesa / drivers / dri / i915 / i830_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 "main/mtypes.h"
29 #include "main/enums.h"
30
31 #include "intel_mipmap_tree.h"
32 #include "intel_tex.h"
33
34 #include "i830_context.h"
35 #include "i830_reg.h"
36
37
38
39 static GLuint
40 translate_texture_format(GLuint mesa_format, GLuint internal_format)
41 {
42 switch (mesa_format) {
43 case MESA_FORMAT_L8:
44 return MAPSURF_8BIT | MT_8BIT_L8;
45 case MESA_FORMAT_I8:
46 return MAPSURF_8BIT | MT_8BIT_I8;
47 case MESA_FORMAT_A8:
48 return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */
49 case MESA_FORMAT_AL88:
50 return MAPSURF_16BIT | MT_16BIT_AY88;
51 case MESA_FORMAT_RGB565:
52 return MAPSURF_16BIT | MT_16BIT_RGB565;
53 case MESA_FORMAT_ARGB1555:
54 return MAPSURF_16BIT | MT_16BIT_ARGB1555;
55 case MESA_FORMAT_ARGB4444:
56 return MAPSURF_16BIT | MT_16BIT_ARGB4444;
57 case MESA_FORMAT_ARGB8888:
58 return MAPSURF_32BIT | MT_32BIT_ARGB8888;
59 case MESA_FORMAT_XRGB8888:
60 return MAPSURF_32BIT | MT_32BIT_XRGB8888;
61 case MESA_FORMAT_YCBCR_REV:
62 return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
63 case MESA_FORMAT_YCBCR:
64 return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
65 case MESA_FORMAT_RGB_FXT1:
66 case MESA_FORMAT_RGBA_FXT1:
67 return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
68 case MESA_FORMAT_RGBA_DXT1:
69 case MESA_FORMAT_RGB_DXT1:
70 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
71 case MESA_FORMAT_RGBA_DXT3:
72 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
73 case MESA_FORMAT_RGBA_DXT5:
74 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
75 default:
76 fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format);
77 abort();
78 return 0;
79 }
80 }
81
82
83
84
85 /* The i915 (and related graphics cores) do not support GL_CLAMP. The
86 * Intel drivers for "other operating systems" implement GL_CLAMP as
87 * GL_CLAMP_TO_EDGE, so the same is done here.
88 */
89 static GLuint
90 translate_wrap_mode(GLenum wrap)
91 {
92 switch (wrap) {
93 case GL_REPEAT:
94 return TEXCOORDMODE_WRAP;
95 case GL_CLAMP:
96 case GL_CLAMP_TO_EDGE:
97 return TEXCOORDMODE_CLAMP; /* not really correct */
98 case GL_CLAMP_TO_BORDER:
99 return TEXCOORDMODE_CLAMP_BORDER;
100 case GL_MIRRORED_REPEAT:
101 return TEXCOORDMODE_MIRROR;
102 default:
103 return TEXCOORDMODE_WRAP;
104 }
105 }
106
107
108 /* Recalculate all state from scratch. Perhaps not the most
109 * efficient, but this has gotten complex enough that we need
110 * something which is understandable and reliable.
111 */
112 static GLboolean
113 i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
114 {
115 GLcontext *ctx = &intel->ctx;
116 struct i830_context *i830 = i830_context(ctx);
117 struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
118 struct gl_texture_object *tObj = tUnit->_Current;
119 struct intel_texture_object *intelObj = intel_texture_object(tObj);
120 struct gl_texture_image *firstImage;
121 GLuint *state = i830->state.Tex[unit], format, pitch;
122 GLint lodbias;
123 GLubyte border[4];
124
125 memset(state, 0, sizeof(state));
126
127 /*We need to refcount these. */
128
129 if (i830->state.tex_buffer[unit] != NULL) {
130 dri_bo_unreference(i830->state.tex_buffer[unit]);
131 i830->state.tex_buffer[unit] = NULL;
132 }
133
134 if (!intelObj->imageOverride && !intel_finalize_mipmap_tree(intel, unit))
135 return GL_FALSE;
136
137 /* Get first image here, since intelObj->firstLevel will get set in
138 * the intel_finalize_mipmap_tree() call above.
139 */
140 firstImage = tObj->Image[0][intelObj->firstLevel];
141
142 if (intelObj->imageOverride) {
143 i830->state.tex_buffer[unit] = NULL;
144 i830->state.tex_offset[unit] = intelObj->textureOffset;
145
146 switch (intelObj->depthOverride) {
147 case 32:
148 format = MAPSURF_32BIT | MT_32BIT_ARGB8888;
149 break;
150 case 24:
151 default:
152 format = MAPSURF_32BIT | MT_32BIT_XRGB8888;
153 break;
154 case 16:
155 format = MAPSURF_16BIT | MT_16BIT_RGB565;
156 break;
157 }
158
159 pitch = intelObj->pitchOverride;
160 } else {
161 GLuint dst_x, dst_y;
162
163 intel_miptree_get_image_offset(intelObj->mt, intelObj->firstLevel, 0, 0,
164 &dst_x, &dst_y);
165
166 dri_bo_reference(intelObj->mt->region->buffer);
167 i830->state.tex_buffer[unit] = intelObj->mt->region->buffer;
168 /* XXX: This calculation is probably broken for tiled images with
169 * a non-page-aligned offset.
170 */
171 i830->state.tex_offset[unit] = (dst_x + dst_y * intelObj->mt->pitch) *
172 intelObj->mt->cpp;
173
174 format = translate_texture_format(firstImage->TexFormat,
175 firstImage->InternalFormat);
176 pitch = intelObj->mt->pitch * intelObj->mt->cpp;
177 }
178
179 state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
180 (LOAD_TEXTURE_MAP0 << unit) | 4);
181
182 state[I830_TEXREG_TM0S1] =
183 (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
184 ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format);
185
186 if (intelObj->mt->region->tiling != I915_TILING_NONE) {
187 state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE;
188 if (intelObj->mt->region->tiling == I915_TILING_Y)
189 state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK;
190 }
191
192 state[I830_TEXREG_TM0S2] =
193 ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);
194
195 {
196 if (tObj->Target == GL_TEXTURE_CUBE_MAP)
197 state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
198 CUBE_NEGX_ENABLE |
199 CUBE_POSX_ENABLE |
200 CUBE_NEGY_ENABLE |
201 CUBE_POSY_ENABLE |
202 CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE);
203 else
204 state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
205 }
206
207
208
209
210 {
211 GLuint minFilt, mipFilt, magFilt;
212
213 switch (tObj->MinFilter) {
214 case GL_NEAREST:
215 minFilt = FILTER_NEAREST;
216 mipFilt = MIPFILTER_NONE;
217 break;
218 case GL_LINEAR:
219 minFilt = FILTER_LINEAR;
220 mipFilt = MIPFILTER_NONE;
221 break;
222 case GL_NEAREST_MIPMAP_NEAREST:
223 minFilt = FILTER_NEAREST;
224 mipFilt = MIPFILTER_NEAREST;
225 break;
226 case GL_LINEAR_MIPMAP_NEAREST:
227 minFilt = FILTER_LINEAR;
228 mipFilt = MIPFILTER_NEAREST;
229 break;
230 case GL_NEAREST_MIPMAP_LINEAR:
231 minFilt = FILTER_NEAREST;
232 mipFilt = MIPFILTER_LINEAR;
233 break;
234 case GL_LINEAR_MIPMAP_LINEAR:
235 minFilt = FILTER_LINEAR;
236 mipFilt = MIPFILTER_LINEAR;
237 break;
238 default:
239 return GL_FALSE;
240 }
241
242 if (tObj->MaxAnisotropy > 1.0) {
243 minFilt = FILTER_ANISOTROPIC;
244 magFilt = FILTER_ANISOTROPIC;
245 }
246 else {
247 switch (tObj->MagFilter) {
248 case GL_NEAREST:
249 magFilt = FILTER_NEAREST;
250 break;
251 case GL_LINEAR:
252 magFilt = FILTER_LINEAR;
253 break;
254 default:
255 return GL_FALSE;
256 }
257 }
258
259 lodbias = (int) ((tUnit->LodBias + tObj->LodBias) * 16.0);
260 if (lodbias < -64)
261 lodbias = -64;
262 if (lodbias > 63)
263 lodbias = 63;
264
265 state[I830_TEXREG_TM0S3] = ((lodbias << TM0S3_LOD_BIAS_SHIFT) &
266 TM0S3_LOD_BIAS_MASK);
267 #if 0
268 /* YUV conversion:
269 */
270 if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
271 firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
272 state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION;
273 #endif
274
275 state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel -
276 intelObj->firstLevel) *
277 4) << TM0S3_MIN_MIP_SHIFT;
278
279 state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
280 (mipFilt << TM0S3_MIP_FILTER_SHIFT) |
281 (magFilt << TM0S3_MAG_FILTER_SHIFT));
282 }
283
284 {
285 GLenum ws = tObj->WrapS;
286 GLenum wt = tObj->WrapT;
287
288
289 /* 3D textures not available on i830
290 */
291 if (tObj->Target == GL_TEXTURE_3D)
292 return GL_FALSE;
293
294 state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
295 MAP_UNIT(unit) |
296 ENABLE_TEXCOORD_PARAMS |
297 ss3 |
298 ENABLE_ADDR_V_CNTL |
299 TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt))
300 | ENABLE_ADDR_U_CNTL |
301 TEXCOORD_ADDR_U_MODE(translate_wrap_mode
302 (ws)));
303 }
304
305 /* convert border color from float to ubyte */
306 CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor[0]);
307 CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor[1]);
308 CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor[2]);
309 CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor[3]);
310
311 state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(border[0],
312 border[1],
313 border[2],
314 border[3]);
315
316
317 I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
318 /* memcmp was already disabled, but definitely won't work as the
319 * region might now change and that wouldn't be detected:
320 */
321 I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
322 return GL_TRUE;
323 }
324
325
326
327
328 void
329 i830UpdateTextureState(struct intel_context *intel)
330 {
331 struct i830_context *i830 = i830_context(&intel->ctx);
332 GLboolean ok = GL_TRUE;
333 GLuint i;
334
335 for (i = 0; i < I830_TEX_UNITS && ok; i++) {
336 switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
337 case TEXTURE_1D_BIT:
338 case TEXTURE_2D_BIT:
339 case TEXTURE_CUBE_BIT:
340 ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_NORMAL);
341 break;
342 case TEXTURE_RECT_BIT:
343 ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_IN_TEXELUNITS);
344 break;
345 case 0:{
346 struct i830_context *i830 = i830_context(&intel->ctx);
347 if (i830->state.active & I830_UPLOAD_TEX(i))
348 I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE);
349
350 if (i830->state.tex_buffer[i] != NULL) {
351 dri_bo_unreference(i830->state.tex_buffer[i]);
352 i830->state.tex_buffer[i] = NULL;
353 }
354 break;
355 }
356 case TEXTURE_3D_BIT:
357 default:
358 ok = GL_FALSE;
359 break;
360 }
361 }
362
363 FALLBACK(intel, I830_FALLBACK_TEXTURE, !ok);
364
365 if (ok)
366 i830EmitTextureBlend(i830);
367 }