2 * GLX Hardware Device Driver for Intel i810
3 * Copyright (C) 1999 Keith Whitwell
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:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
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.
24 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810tex.c,v 1.9 2002/10/30 12:51:33 alanh Exp $ */
29 #include "simple_list.h"
32 #include "texformat.h"
35 #include "swrast/swrast.h"
40 #include "i810screen.h"
43 #include "i810context.h"
45 #include "i810state.h"
46 #include "i810ioctl.h"
50 * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias.
52 static GLuint
i810ComputeLodBias(GLfloat bias
)
54 int b
= (int) (bias
* 16.0) + 12;
59 return (GLuint
) (b
& MLC_LOD_BIAS_MASK
);
63 static void i810SetTexWrapping(i810TextureObjectPtr tex
,
64 GLenum swrap
, GLenum twrap
)
66 tex
->Setup
[I810_TEXREG_MCS
] &= ~(MCS_U_STATE_MASK
| MCS_V_STATE_MASK
);
70 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_U_WRAP
;
73 case GL_CLAMP_TO_EDGE
:
74 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_U_CLAMP
;
76 case GL_MIRRORED_REPEAT
:
77 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_U_MIRROR
;
80 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
85 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_V_WRAP
;
88 case GL_CLAMP_TO_EDGE
:
89 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_V_CLAMP
;
91 case GL_MIRRORED_REPEAT
:
92 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_V_MIRROR
;
95 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
100 static void i810SetTexFilter(i810ContextPtr imesa
,
101 i810TextureObjectPtr t
,
102 GLenum minf
, GLenum magf
,
105 t
->Setup
[I810_TEXREG_MF
] &= ~(MF_MIN_MASK
|
108 t
->Setup
[I810_TEXREG_MLC
] &= ~(MLC_LOD_BIAS_MASK
);
112 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_NEAREST
| MF_MIP_NONE
;
115 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_LINEAR
| MF_MIP_NONE
;
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 */
123 case GL_LINEAR_MIPMAP_NEAREST
:
124 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_LINEAR
| MF_MIP_NEAREST
;
126 case GL_NEAREST_MIPMAP_LINEAR
:
128 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_NEAREST
| MF_MIP_LINEAR
;
130 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_NEAREST
| MF_MIP_DITHER
;
132 if (magf == GL_LINEAR) {
136 bias
-= 0.5; /* always biasing here looks better */
138 case GL_LINEAR_MIPMAP_LINEAR
:
140 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_LINEAR
| MF_MIP_LINEAR
;
142 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_LINEAR
| MF_MIP_DITHER
;
150 t
->Setup
[I810_TEXREG_MF
] |= MF_MAG_NEAREST
;
153 t
->Setup
[I810_TEXREG_MF
] |= MF_MAG_LINEAR
;
159 t
->Setup
[I810_TEXREG_MLC
] |= i810ComputeLodBias(bias
);
163 static void i810SetTexBorderColor(i810TextureObjectPtr t
,
169 static i810TextureObjectPtr
i810AllocTexObj( GLcontext
*ctx
, struct gl_texture_object
*texObj
)
171 i810TextureObjectPtr t
;
172 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
174 t
= CALLOC_STRUCT( i810_texture_object_t
);
175 texObj
->DriverData
= t
;
177 GLfloat bias
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].LodBias
;
178 /* Initialize non-image-dependent parts of the state:
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
|
186 /*MLC_DITHER_WEIGHT_FULL |*/
187 MLC_DITHER_WEIGHT_12
|
188 MLC_UPDATE_LOD_BIAS
|
190 t
->Setup
[I810_TEXREG_MCS
] = (GFX_OP_MAP_COORD_SETS
|
192 MCS_UPDATE_NORMALIZED
|
193 MCS_NORMALIZED_COORDS
|
198 t
->Setup
[I810_TEXREG_MF
] = (GFX_OP_MAP_FILTER
|
200 MF_UPDATE_ANISOTROPIC
|
201 MF_UPDATE_MIP_FILTER
|
202 MF_UPDATE_MAG_FILTER
|
203 MF_UPDATE_MIN_FILTER
);
205 make_empty_list( & t
->base
);
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
);
217 static void i810TexParameter( GLcontext
*ctx
, GLenum target
,
218 struct gl_texture_object
*tObj
,
219 GLenum pname
, const GLfloat
*params
)
221 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
222 i810TextureObjectPtr t
= (i810TextureObjectPtr
) tObj
->DriverData
;
226 if ( target
!= GL_TEXTURE_2D
)
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.
236 case GL_TEXTURE_MIN_FILTER
:
237 case GL_TEXTURE_MAG_FILTER
:
239 GLfloat bias
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].LodBias
;
240 i810SetTexFilter( imesa
, t
, tObj
->MinFilter
, tObj
->MagFilter
, bias
);
244 case GL_TEXTURE_WRAP_S
:
245 case GL_TEXTURE_WRAP_T
:
246 i810SetTexWrapping( t
, tObj
->WrapS
, tObj
->WrapT
);
249 case GL_TEXTURE_BORDER_COLOR
:
250 i810SetTexBorderColor( t
, tObj
->_BorderChan
);
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.
262 I810_FIREVERTICES( I810_CONTEXT(ctx
) );
263 driSwapOutTextureObject( (driTextureObject
*) t
);
270 if (t
== imesa
->CurrentTexObj
[0]) {
271 I810_STATECHANGE( imesa
, I810_UPLOAD_TEX0
);
274 if (t
== imesa
->CurrentTexObj
[1]) {
275 I810_STATECHANGE( imesa
, I810_UPLOAD_TEX1
);
280 static void i810TexEnv( GLcontext
*ctx
, GLenum target
,
281 GLenum pname
, const GLfloat
*param
)
283 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
284 GLuint unit
= ctx
->Texture
.CurrentUnit
;
286 /* Only one env color. Need a fallback if env colors are different
287 * and texture setup references env color in both units.
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]);
304 if (imesa
->Setup
[I810_CTXREG_CF1
] != col
) {
305 I810_STATECHANGE(imesa
, I810_UPLOAD_CTX
);
306 imesa
->Setup
[I810_CTXREG_CF1
] = col
;
310 case GL_TEXTURE_ENV_MODE
:
311 imesa
->TexEnvImageFmt
[unit
] = 0; /* force recalc of env state */
314 case GL_TEXTURE_LOD_BIAS_EXT
:
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
);
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
)
340 i810TextureObjectPtr t
= (i810TextureObjectPtr
) texObj
->DriverData
;
342 i810SwapOutTexObj( imesa
, t
);
346 static void i810TexSubImage1D( GLcontext
*ctx
,
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
)
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
)
369 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
371 I810_FIREVERTICES( I810_CONTEXT(ctx
) );
372 driSwapOutTextureObject( t
);
375 t
= (driTextureObject
*) i810AllocTexObj( ctx
, texObj
);
377 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
381 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
382 width
, height
, border
, format
, type
,
383 pixels
, packing
, texObj
, texImage
);
387 static void i810TexSubImage2D( GLcontext
*ctx
,
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
)
398 driTextureObject
*t
= (driTextureObject
*)texObj
->DriverData
;
401 I810_FIREVERTICES( I810_CONTEXT(ctx
) );
402 driSwapOutTextureObject( t
);
404 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
405 height
, format
, type
, pixels
, packing
, texObj
,
411 static void i810BindTexture( GLcontext
*ctx
, GLenum target
,
412 struct gl_texture_object
*tObj
)
414 if (!tObj
->DriverData
) {
415 i810AllocTexObj( ctx
, tObj
);
420 static void i810DeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
422 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
424 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
426 I810_FIREVERTICES( imesa
);
427 driDestroyTextureObject( t
);
431 static const struct gl_texture_format
*
432 i810ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
433 GLenum format
, GLenum type
)
435 switch ( internalFormat
) {
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
;
444 return &_mesa_texformat_argb4444
;
448 case GL_COMPRESSED_RGB
:
456 return &_mesa_texformat_rgb565
;
464 return &_mesa_texformat_argb4444
;
467 return &_mesa_texformat_argb1555
;
474 case GL_COMPRESSED_ALPHA
:
475 return &_mesa_texformat_al88
;
483 case GL_COMPRESSED_LUMINANCE
:
484 return &_mesa_texformat_rgb565
;
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
:
500 case GL_COMPRESSED_INTENSITY
:
501 return &_mesa_texformat_argb4444
;
504 if (type
== GL_UNSIGNED_SHORT_8_8_MESA
||
505 type
== GL_UNSIGNED_BYTE
)
506 return &_mesa_texformat_ycbcr
;
508 return &_mesa_texformat_ycbcr_rev
;
511 fprintf(stderr
, "unexpected texture format in %s\n", __FUNCTION__
);
515 return NULL
; /* never get here */
518 void i810InitTextureFuncs( GLcontext
*ctx
)
520 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
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
;
542 driInitTextureObjects( ctx
, &imesa
->swapped
, DRI_TEXMGR_DO_TEXTURE_2D
);