f2ebd35c9acb59e3fd837ac1509a38cd015b4c09
[mesa.git] / src / mesa / drivers / dri / i810 / i810tex.c
1 /*
2 * GLX Hardware Device Driver for Intel i810
3 * Copyright (C) 1999 Keith Whitwell
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810tex.c,v 1.9 2002/10/30 12:51:33 alanh Exp $ */
25
26 #include "glheader.h"
27 #include "mtypes.h"
28 #include "imports.h"
29 #include "simple_list.h"
30 #include "enums.h"
31 #include "texstore.h"
32 #include "texformat.h"
33 #include "teximage.h"
34 #include "texmem.h"
35 #include "swrast/swrast.h"
36 #include "colormac.h"
37
38 #include "mm.h"
39
40 #include "i810screen.h"
41 #include "i810_dri.h"
42
43 #include "i810context.h"
44 #include "i810tex.h"
45 #include "i810state.h"
46 #include "i810ioctl.h"
47
48
49 /*
50 * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias.
51 */
52 static GLuint i810ComputeLodBias(GLfloat bias)
53 {
54 int b = (int) (bias * 16.0) + 12;
55 if (b > 63)
56 b = 63;
57 else if (b < -64)
58 b = -64;
59 return (GLuint) (b & MLC_LOD_BIAS_MASK);
60 }
61
62
63 static void i810SetTexWrapping(i810TextureObjectPtr tex,
64 GLenum swrap, GLenum twrap)
65 {
66 tex->Setup[I810_TEXREG_MCS] &= ~(MCS_U_STATE_MASK| MCS_V_STATE_MASK);
67
68 switch( swrap ) {
69 case GL_REPEAT:
70 tex->Setup[I810_TEXREG_MCS] |= MCS_U_WRAP;
71 break;
72 case GL_CLAMP:
73 case GL_CLAMP_TO_EDGE:
74 tex->Setup[I810_TEXREG_MCS] |= MCS_U_CLAMP;
75 break;
76 case GL_MIRRORED_REPEAT:
77 tex->Setup[I810_TEXREG_MCS] |= MCS_U_MIRROR;
78 break;
79 default:
80 _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
81 }
82
83 switch( twrap ) {
84 case GL_REPEAT:
85 tex->Setup[I810_TEXREG_MCS] |= MCS_V_WRAP;
86 break;
87 case GL_CLAMP:
88 case GL_CLAMP_TO_EDGE:
89 tex->Setup[I810_TEXREG_MCS] |= MCS_V_CLAMP;
90 break;
91 case GL_MIRRORED_REPEAT:
92 tex->Setup[I810_TEXREG_MCS] |= MCS_V_MIRROR;
93 break;
94 default:
95 _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
96 }
97 }
98
99
100 static void i810SetTexFilter(i810ContextPtr imesa,
101 i810TextureObjectPtr t,
102 GLenum minf, GLenum magf,
103 GLfloat bias)
104 {
105 t->Setup[I810_TEXREG_MF] &= ~(MF_MIN_MASK|
106 MF_MAG_MASK|
107 MF_MIP_MASK);
108 t->Setup[I810_TEXREG_MLC] &= ~(MLC_LOD_BIAS_MASK);
109
110 switch (minf) {
111 case GL_NEAREST:
112 t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_NONE;
113 break;
114 case GL_LINEAR:
115 t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_NONE;
116 break;
117 case GL_NEAREST_MIPMAP_NEAREST:
118 t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_NEAREST;
119 if (magf == GL_LINEAR) {
120 /*bias -= 0.5;*/ /* this doesn't work too good */
121 }
122 break;
123 case GL_LINEAR_MIPMAP_NEAREST:
124 t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_NEAREST;
125 break;
126 case GL_NEAREST_MIPMAP_LINEAR:
127 if (IS_I815(imesa))
128 t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_LINEAR;
129 else
130 t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_DITHER;
131 /*
132 if (magf == GL_LINEAR) {
133 bias -= 0.5;
134 }
135 */
136 bias -= 0.5; /* always biasing here looks better */
137 break;
138 case GL_LINEAR_MIPMAP_LINEAR:
139 if (IS_I815(imesa))
140 t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_LINEAR;
141 else
142 t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_DITHER;
143 break;
144 default:
145 return;
146 }
147
148 switch (magf) {
149 case GL_NEAREST:
150 t->Setup[I810_TEXREG_MF] |= MF_MAG_NEAREST;
151 break;
152 case GL_LINEAR:
153 t->Setup[I810_TEXREG_MF] |= MF_MAG_LINEAR;
154 break;
155 default:
156 return;
157 }
158
159 t->Setup[I810_TEXREG_MLC] |= i810ComputeLodBias(bias);
160 }
161
162
163 static void i810SetTexBorderColor(i810TextureObjectPtr t,
164 GLubyte color[4])
165 {
166 /* Need a fallback.
167 */
168 }
169 static i810TextureObjectPtr i810AllocTexObj( GLcontext *ctx, struct gl_texture_object *texObj )
170 {
171 i810TextureObjectPtr t;
172 i810ContextPtr imesa = I810_CONTEXT(ctx);
173
174 t = CALLOC_STRUCT( i810_texture_object_t );
175 texObj->DriverData = t;
176 if ( t != NULL ) {
177 GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
178 /* Initialize non-image-dependent parts of the state:
179 */
180 t->base.tObj = texObj;
181 t->Setup[I810_TEXREG_MI0] = GFX_OP_MAP_INFO;
182 t->Setup[I810_TEXREG_MI1] = MI1_MAP_0;
183 t->Setup[I810_TEXREG_MI2] = MI2_DIMENSIONS_ARE_LOG2;
184 t->Setup[I810_TEXREG_MLC] = (GFX_OP_MAP_LOD_CTL |
185 MLC_MAP_0 |
186 /*MLC_DITHER_WEIGHT_FULL |*/
187 MLC_DITHER_WEIGHT_12 |
188 MLC_UPDATE_LOD_BIAS |
189 0x0);
190 t->Setup[I810_TEXREG_MCS] = (GFX_OP_MAP_COORD_SETS |
191 MCS_COORD_0 |
192 MCS_UPDATE_NORMALIZED |
193 MCS_NORMALIZED_COORDS |
194 MCS_UPDATE_V_STATE |
195 MCS_V_WRAP |
196 MCS_UPDATE_U_STATE |
197 MCS_U_WRAP);
198 t->Setup[I810_TEXREG_MF] = (GFX_OP_MAP_FILTER |
199 MF_MAP_0 |
200 MF_UPDATE_ANISOTROPIC |
201 MF_UPDATE_MIP_FILTER |
202 MF_UPDATE_MAG_FILTER |
203 MF_UPDATE_MIN_FILTER);
204
205 make_empty_list( & t->base );
206
207 i810SetTexWrapping( t, texObj->WrapS, texObj->WrapT );
208 /*i830SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );*/
209 i810SetTexFilter( imesa, t, texObj->MinFilter, texObj->MagFilter, bias );
210 i810SetTexBorderColor( t, texObj->_BorderChan );
211 }
212
213 return t;
214 }
215
216
217 static void i810TexParameter( GLcontext *ctx, GLenum target,
218 struct gl_texture_object *tObj,
219 GLenum pname, const GLfloat *params )
220 {
221 i810ContextPtr imesa = I810_CONTEXT(ctx);
222 i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData;
223 if (!t)
224 return;
225
226 if ( target != GL_TEXTURE_2D )
227 return;
228
229 /* Can't do the update now as we don't know whether to flush
230 * vertices or not. Setting imesa->new_state means that
231 * i810UpdateTextureState() will be called before any triangles are
232 * rendered. If a statechange has occurred, it will be detected at
233 * that point, and buffered vertices flushed.
234 */
235 switch (pname) {
236 case GL_TEXTURE_MIN_FILTER:
237 case GL_TEXTURE_MAG_FILTER:
238 {
239 GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
240 i810SetTexFilter( imesa, t, tObj->MinFilter, tObj->MagFilter, bias );
241 }
242 break;
243
244 case GL_TEXTURE_WRAP_S:
245 case GL_TEXTURE_WRAP_T:
246 i810SetTexWrapping( t, tObj->WrapS, tObj->WrapT );
247 break;
248
249 case GL_TEXTURE_BORDER_COLOR:
250 i810SetTexBorderColor( t, tObj->_BorderChan );
251 break;
252
253 case GL_TEXTURE_BASE_LEVEL:
254 case GL_TEXTURE_MAX_LEVEL:
255 case GL_TEXTURE_MIN_LOD:
256 case GL_TEXTURE_MAX_LOD:
257 /* This isn't the most efficient solution but there doesn't appear to
258 * be a nice alternative for Radeon. Since there's no LOD clamping,
259 * we just have to rely on loading the right subset of mipmap levels
260 * to simulate a clamped LOD.
261 */
262 I810_FIREVERTICES( I810_CONTEXT(ctx) );
263 driSwapOutTextureObject( (driTextureObject *) t );
264 break;
265
266 default:
267 return;
268 }
269
270 if (t == imesa->CurrentTexObj[0]) {
271 I810_STATECHANGE( imesa, I810_UPLOAD_TEX0 );
272 }
273
274 if (t == imesa->CurrentTexObj[1]) {
275 I810_STATECHANGE( imesa, I810_UPLOAD_TEX1 );
276 }
277 }
278
279
280 static void i810TexEnv( GLcontext *ctx, GLenum target,
281 GLenum pname, const GLfloat *param )
282 {
283 i810ContextPtr imesa = I810_CONTEXT( ctx );
284 GLuint unit = ctx->Texture.CurrentUnit;
285
286 /* Only one env color. Need a fallback if env colors are different
287 * and texture setup references env color in both units.
288 */
289 switch (pname) {
290 case GL_TEXTURE_ENV_COLOR: {
291 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
292 GLfloat *fc = texUnit->EnvColor;
293 GLuint r, g, b, a, col;
294 CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
295 CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
296 CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
297 CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
298
299 col = ((a << 24) |
300 (r << 16) |
301 (g << 8) |
302 (b << 0));
303
304 if (imesa->Setup[I810_CTXREG_CF1] != col) {
305 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
306 imesa->Setup[I810_CTXREG_CF1] = col;
307 }
308 break;
309 }
310 case GL_TEXTURE_ENV_MODE:
311 imesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */
312 break;
313
314 case GL_TEXTURE_LOD_BIAS_EXT:
315 {
316 struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
317 i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData;
318 t->Setup[I810_TEXREG_MLC] &= ~(MLC_LOD_BIAS_MASK);
319 t->Setup[I810_TEXREG_MLC] |= i810ComputeLodBias(*param);
320 }
321 break;
322
323 default:
324 break;
325 }
326 }
327
328
329
330 #if 0
331 static void i810TexImage1D( GLcontext *ctx, GLenum target, GLint level,
332 GLint internalFormat,
333 GLint width, GLint border,
334 GLenum format, GLenum type,
335 const GLvoid *pixels,
336 const struct gl_pixelstore_attrib *pack,
337 struct gl_texture_object *texObj,
338 struct gl_texture_image *texImage )
339 {
340 i810TextureObjectPtr t = (i810TextureObjectPtr) texObj->DriverData;
341 if (t) {
342 i810SwapOutTexObj( imesa, t );
343 }
344 }
345
346 static void i810TexSubImage1D( GLcontext *ctx,
347 GLenum target,
348 GLint level,
349 GLint xoffset,
350 GLsizei width,
351 GLenum format, GLenum type,
352 const GLvoid *pixels,
353 const struct gl_pixelstore_attrib *pack,
354 struct gl_texture_object *texObj,
355 struct gl_texture_image *texImage )
356 {
357 }
358 #endif
359
360
361 static void i810TexImage2D( GLcontext *ctx, GLenum target, GLint level,
362 GLint internalFormat,
363 GLint width, GLint height, GLint border,
364 GLenum format, GLenum type, const GLvoid *pixels,
365 const struct gl_pixelstore_attrib *packing,
366 struct gl_texture_object *texObj,
367 struct gl_texture_image *texImage )
368 {
369 driTextureObject *t = (driTextureObject *) texObj->DriverData;
370 if (t) {
371 I810_FIREVERTICES( I810_CONTEXT(ctx) );
372 driSwapOutTextureObject( t );
373 }
374 else {
375 t = (driTextureObject *) i810AllocTexObj( ctx, texObj );
376 if (!t) {
377 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
378 return;
379 }
380 }
381 _mesa_store_teximage2d( ctx, target, level, internalFormat,
382 width, height, border, format, type,
383 pixels, packing, texObj, texImage );
384
385 }
386
387 static void i810TexSubImage2D( GLcontext *ctx,
388 GLenum target,
389 GLint level,
390 GLint xoffset, GLint yoffset,
391 GLsizei width, GLsizei height,
392 GLenum format, GLenum type,
393 const GLvoid *pixels,
394 const struct gl_pixelstore_attrib *packing,
395 struct gl_texture_object *texObj,
396 struct gl_texture_image *texImage )
397 {
398 driTextureObject *t = (driTextureObject *)texObj->DriverData;
399
400 if (t) {
401 I810_FIREVERTICES( I810_CONTEXT(ctx) );
402 driSwapOutTextureObject( t );
403 }
404 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
405 height, format, type, pixels, packing, texObj,
406 texImage);
407
408 }
409
410
411 static void i810BindTexture( GLcontext *ctx, GLenum target,
412 struct gl_texture_object *tObj )
413 {
414 if (!tObj->DriverData) {
415 i810AllocTexObj( ctx, tObj );
416 }
417 }
418
419
420 static void i810DeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
421 {
422 driTextureObject * t = (driTextureObject *) tObj->DriverData;
423 if (t) {
424 i810ContextPtr imesa = I810_CONTEXT( ctx );
425 if (imesa)
426 I810_FIREVERTICES( imesa );
427 driDestroyTextureObject( t );
428 }
429 }
430
431 static const struct gl_texture_format *
432 i810ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
433 GLenum format, GLenum type )
434 {
435 switch ( internalFormat ) {
436 case 4:
437 case GL_RGBA:
438 case GL_COMPRESSED_RGBA:
439 if ( format == GL_BGRA ) {
440 if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
441 return &_mesa_texformat_argb1555;
442 }
443 }
444 return &_mesa_texformat_argb4444;
445
446 case 3:
447 case GL_RGB:
448 case GL_COMPRESSED_RGB:
449 case GL_R3_G3_B2:
450 case GL_RGB4:
451 case GL_RGB5:
452 case GL_RGB8:
453 case GL_RGB10:
454 case GL_RGB12:
455 case GL_RGB16:
456 return &_mesa_texformat_rgb565;
457
458 case GL_RGBA2:
459 case GL_RGBA4:
460 case GL_RGBA8:
461 case GL_RGB10_A2:
462 case GL_RGBA12:
463 case GL_RGBA16:
464 return &_mesa_texformat_argb4444;
465
466 case GL_RGB5_A1:
467 return &_mesa_texformat_argb1555;
468
469 case GL_ALPHA:
470 case GL_ALPHA4:
471 case GL_ALPHA8:
472 case GL_ALPHA12:
473 case GL_ALPHA16:
474 case GL_COMPRESSED_ALPHA:
475 return &_mesa_texformat_al88;
476
477 case 1:
478 case GL_LUMINANCE:
479 case GL_LUMINANCE4:
480 case GL_LUMINANCE8:
481 case GL_LUMINANCE12:
482 case GL_LUMINANCE16:
483 case GL_COMPRESSED_LUMINANCE:
484 return &_mesa_texformat_rgb565;
485
486 case 2:
487 case GL_LUMINANCE_ALPHA:
488 case GL_LUMINANCE4_ALPHA4:
489 case GL_LUMINANCE6_ALPHA2:
490 case GL_LUMINANCE8_ALPHA8:
491 case GL_LUMINANCE12_ALPHA4:
492 case GL_LUMINANCE12_ALPHA12:
493 case GL_LUMINANCE16_ALPHA16:
494 case GL_COMPRESSED_LUMINANCE_ALPHA:
495 case GL_INTENSITY:
496 case GL_INTENSITY4:
497 case GL_INTENSITY8:
498 case GL_INTENSITY12:
499 case GL_INTENSITY16:
500 case GL_COMPRESSED_INTENSITY:
501 return &_mesa_texformat_argb4444;
502
503 case GL_YCBCR_MESA:
504 if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
505 type == GL_UNSIGNED_BYTE)
506 return &_mesa_texformat_ycbcr;
507 else
508 return &_mesa_texformat_ycbcr_rev;
509
510 default:
511 fprintf(stderr, "unexpected texture format in %s\n", __FUNCTION__);
512 return NULL;
513 }
514
515 return NULL; /* never get here */
516 }
517
518 void i810InitTextureFuncs( GLcontext *ctx )
519 {
520 i810ContextPtr imesa = I810_CONTEXT(ctx);
521
522 ctx->Driver.TexEnv = i810TexEnv;
523 ctx->Driver.ChooseTextureFormat = i810ChooseTextureFormat;
524 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
525 ctx->Driver.TexImage2D = i810TexImage2D;
526 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
527 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
528 ctx->Driver.TexSubImage2D = i810TexSubImage2D;
529 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
530 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
531 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
532 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
533 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
534 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
535 ctx->Driver.BindTexture = i810BindTexture;
536 ctx->Driver.DeleteTexture = i810DeleteTexture;
537 ctx->Driver.TexParameter = i810TexParameter;
538 ctx->Driver.UpdateTexturePalette = 0;
539 ctx->Driver.IsTextureResident = driIsTextureResident;
540 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
541
542 driInitTextureObjects( ctx, &imesa->swapped, DRI_TEXMGR_DO_TEXTURE_2D);
543
544 }