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 $ */
26 #include "main/glheader.h"
27 #include "main/mtypes.h"
28 #include "main/imports.h"
29 #include "main/simple_list.h"
30 #include "main/enums.h"
31 #include "main/texstore.h"
32 #include "main/texformat.h"
33 #include "main/teximage.h"
34 #include "main/texobj.h"
35 #include "main/colormac.h"
36 #include "main/texobj.h"
38 #include "swrast/swrast.h"
42 #include "i810screen.h"
45 #include "i810context.h"
47 #include "i810state.h"
48 #include "i810ioctl.h"
52 * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias.
54 static GLuint
i810ComputeLodBias(GLfloat bias
)
56 int b
= (int) (bias
* 16.0) + 12;
61 return (GLuint
) (b
& MLC_LOD_BIAS_MASK
);
65 static void i810SetTexWrapping(i810TextureObjectPtr tex
,
66 GLenum swrap
, GLenum twrap
)
68 tex
->Setup
[I810_TEXREG_MCS
] &= ~(MCS_U_STATE_MASK
| MCS_V_STATE_MASK
);
72 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_U_WRAP
;
75 case GL_CLAMP_TO_EDGE
:
76 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_U_CLAMP
;
78 case GL_MIRRORED_REPEAT
:
79 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_U_MIRROR
;
82 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
87 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_V_WRAP
;
90 case GL_CLAMP_TO_EDGE
:
91 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_V_CLAMP
;
93 case GL_MIRRORED_REPEAT
:
94 tex
->Setup
[I810_TEXREG_MCS
] |= MCS_V_MIRROR
;
97 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
102 static void i810SetTexFilter(i810ContextPtr imesa
,
103 i810TextureObjectPtr t
,
104 GLenum minf
, GLenum magf
,
107 t
->Setup
[I810_TEXREG_MF
] &= ~(MF_MIN_MASK
|
110 t
->Setup
[I810_TEXREG_MLC
] &= ~(MLC_LOD_BIAS_MASK
);
114 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_NEAREST
| MF_MIP_NONE
;
117 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_LINEAR
| MF_MIP_NONE
;
119 case GL_NEAREST_MIPMAP_NEAREST
:
120 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_NEAREST
| MF_MIP_NEAREST
;
121 if (magf
== GL_LINEAR
) {
122 /*bias -= 0.5;*/ /* this doesn't work too good */
125 case GL_LINEAR_MIPMAP_NEAREST
:
126 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_LINEAR
| MF_MIP_NEAREST
;
128 case GL_NEAREST_MIPMAP_LINEAR
:
130 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_NEAREST
| MF_MIP_LINEAR
;
132 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_NEAREST
| MF_MIP_DITHER
;
134 if (magf == GL_LINEAR) {
138 bias
-= 0.5; /* always biasing here looks better */
140 case GL_LINEAR_MIPMAP_LINEAR
:
142 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_LINEAR
| MF_MIP_LINEAR
;
144 t
->Setup
[I810_TEXREG_MF
] |= MF_MIN_LINEAR
| MF_MIP_DITHER
;
152 t
->Setup
[I810_TEXREG_MF
] |= MF_MAG_NEAREST
;
155 t
->Setup
[I810_TEXREG_MF
] |= MF_MAG_LINEAR
;
161 t
->Setup
[I810_TEXREG_MLC
] |= i810ComputeLodBias(bias
);
166 i810SetTexBorderColor( i810TextureObjectPtr t
, GLubyte color
[4] )
173 static i810TextureObjectPtr
174 i810AllocTexObj( GLcontext
*ctx
, struct gl_texture_object
*texObj
)
176 i810TextureObjectPtr t
;
177 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
179 t
= CALLOC_STRUCT( i810_texture_object_t
);
180 texObj
->DriverData
= t
;
182 GLfloat bias
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].LodBias
;
183 /* Initialize non-image-dependent parts of the state:
185 t
->base
.tObj
= texObj
;
186 t
->Setup
[I810_TEXREG_MI0
] = GFX_OP_MAP_INFO
;
187 t
->Setup
[I810_TEXREG_MI1
] = MI1_MAP_0
;
188 t
->Setup
[I810_TEXREG_MI2
] = MI2_DIMENSIONS_ARE_LOG2
;
189 t
->Setup
[I810_TEXREG_MLC
] = (GFX_OP_MAP_LOD_CTL
|
191 /*MLC_DITHER_WEIGHT_FULL |*/
192 MLC_DITHER_WEIGHT_12
|
193 MLC_UPDATE_LOD_BIAS
|
195 t
->Setup
[I810_TEXREG_MCS
] = (GFX_OP_MAP_COORD_SETS
|
197 MCS_UPDATE_NORMALIZED
|
198 MCS_NORMALIZED_COORDS
|
203 t
->Setup
[I810_TEXREG_MF
] = (GFX_OP_MAP_FILTER
|
205 MF_UPDATE_ANISOTROPIC
|
206 MF_UPDATE_MIP_FILTER
|
207 MF_UPDATE_MAG_FILTER
|
208 MF_UPDATE_MIN_FILTER
);
210 make_empty_list( & t
->base
);
212 i810SetTexWrapping( t
, texObj
->WrapS
, texObj
->WrapT
);
213 /*i830SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );*/
214 i810SetTexFilter( imesa
, t
, texObj
->MinFilter
, texObj
->MagFilter
, bias
);
215 i810SetTexBorderColor( t
, texObj
->_BorderChan
);
222 static void i810TexParameter( GLcontext
*ctx
, GLenum target
,
223 struct gl_texture_object
*tObj
,
224 GLenum pname
, const GLfloat
*params
)
226 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
227 i810TextureObjectPtr t
= (i810TextureObjectPtr
) tObj
->DriverData
;
232 if ( target
!= GL_TEXTURE_2D
)
235 /* Can't do the update now as we don't know whether to flush
236 * vertices or not. Setting imesa->new_state means that
237 * i810UpdateTextureState() will be called before any triangles are
238 * rendered. If a statechange has occurred, it will be detected at
239 * that point, and buffered vertices flushed.
242 case GL_TEXTURE_MIN_FILTER
:
243 case GL_TEXTURE_MAG_FILTER
:
245 GLfloat bias
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].LodBias
;
246 i810SetTexFilter( imesa
, t
, tObj
->MinFilter
, tObj
->MagFilter
, bias
);
250 case GL_TEXTURE_WRAP_S
:
251 case GL_TEXTURE_WRAP_T
:
252 i810SetTexWrapping( t
, tObj
->WrapS
, tObj
->WrapT
);
255 case GL_TEXTURE_BORDER_COLOR
:
256 i810SetTexBorderColor( t
, tObj
->_BorderChan
);
259 case GL_TEXTURE_BASE_LEVEL
:
260 case GL_TEXTURE_MAX_LEVEL
:
261 case GL_TEXTURE_MIN_LOD
:
262 case GL_TEXTURE_MAX_LOD
:
263 /* This isn't the most efficient solution but there doesn't appear to
264 * be a nice alternative for Radeon. Since there's no LOD clamping,
265 * we just have to rely on loading the right subset of mipmap levels
266 * to simulate a clamped LOD.
268 I810_FIREVERTICES( I810_CONTEXT(ctx
) );
269 driSwapOutTextureObject( (driTextureObject
*) t
);
276 if (t
== imesa
->CurrentTexObj
[0]) {
277 I810_STATECHANGE( imesa
, I810_UPLOAD_TEX0
);
280 if (t
== imesa
->CurrentTexObj
[1]) {
281 I810_STATECHANGE( imesa
, I810_UPLOAD_TEX1
);
287 * Setup hardware bits for new texture environment settings.
290 * Determine whether or not \c param can be used instead of
291 * \c texUnit->EnvColor in the \c GL_TEXTURE_ENV_COLOR case.
293 static void i810TexEnv( GLcontext
*ctx
, GLenum target
,
294 GLenum pname
, const GLfloat
*param
)
296 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
297 const GLuint unit
= ctx
->Texture
.CurrentUnit
;
298 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
300 /* Only one env color. Need a fallback if env colors are different
301 * and texture setup references env color in both units.
304 case GL_TEXTURE_ENV_COLOR
: {
308 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
309 envColor
= PACK_COLOR_8888( c
[3], c
[0], c
[1], c
[2] );
311 if (imesa
->Setup
[I810_CTXREG_CF1
] != envColor
) {
312 I810_STATECHANGE(imesa
, I810_UPLOAD_CTX
);
313 imesa
->Setup
[I810_CTXREG_CF1
] = envColor
;
318 case GL_TEXTURE_ENV_MODE
:
319 imesa
->TexEnvImageFmt
[unit
] = 0; /* force recalc of env state */
322 case GL_TEXTURE_LOD_BIAS
: {
323 if ( texUnit
->_Current
!= NULL
) {
324 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
325 i810TextureObjectPtr t
= (i810TextureObjectPtr
) tObj
->DriverData
;
327 t
->Setup
[I810_TEXREG_MLC
] &= ~(MLC_LOD_BIAS_MASK
);
328 t
->Setup
[I810_TEXREG_MLC
] |= i810ComputeLodBias(*param
);
341 static void i810TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
342 GLint internalFormat
,
343 GLint width
, GLint border
,
344 GLenum format
, GLenum type
,
345 const GLvoid
*pixels
,
346 const struct gl_pixelstore_attrib
*pack
,
347 struct gl_texture_object
*texObj
,
348 struct gl_texture_image
*texImage
)
350 i810TextureObjectPtr t
= (i810TextureObjectPtr
) texObj
->DriverData
;
352 i810SwapOutTexObj( imesa
, t
);
356 static void i810TexSubImage1D( GLcontext
*ctx
,
361 GLenum format
, GLenum type
,
362 const GLvoid
*pixels
,
363 const struct gl_pixelstore_attrib
*pack
,
364 struct gl_texture_object
*texObj
,
365 struct gl_texture_image
*texImage
)
371 static void i810TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
372 GLint internalFormat
,
373 GLint width
, GLint height
, GLint border
,
374 GLenum format
, GLenum type
, const GLvoid
*pixels
,
375 const struct gl_pixelstore_attrib
*packing
,
376 struct gl_texture_object
*texObj
,
377 struct gl_texture_image
*texImage
)
379 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
381 I810_FIREVERTICES( I810_CONTEXT(ctx
) );
382 driSwapOutTextureObject( t
);
385 t
= (driTextureObject
*) i810AllocTexObj( ctx
, texObj
);
387 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
391 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
392 width
, height
, border
, format
, type
,
393 pixels
, packing
, texObj
, texImage
);
396 static void i810TexSubImage2D( GLcontext
*ctx
,
399 GLint xoffset
, GLint yoffset
,
400 GLsizei width
, GLsizei height
,
401 GLenum format
, GLenum type
,
402 const GLvoid
*pixels
,
403 const struct gl_pixelstore_attrib
*packing
,
404 struct gl_texture_object
*texObj
,
405 struct gl_texture_image
*texImage
)
407 driTextureObject
*t
= (driTextureObject
*)texObj
->DriverData
;
409 I810_FIREVERTICES( I810_CONTEXT(ctx
) );
410 driSwapOutTextureObject( t
);
412 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
413 height
, format
, type
, pixels
, packing
, texObj
,
418 static void i810BindTexture( GLcontext
*ctx
, GLenum target
,
419 struct gl_texture_object
*tObj
)
421 assert( (target
!= GL_TEXTURE_2D
) || (tObj
->DriverData
!= NULL
) );
425 static void i810DeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
427 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
429 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
431 I810_FIREVERTICES( imesa
);
432 driDestroyTextureObject( t
);
434 /* Free mipmap images and the texture object itself */
435 _mesa_delete_texture_object(ctx
, tObj
);
439 * Choose a Mesa texture format to match the requested format.
441 * The i810 only supports 5 texture modes that are useful to Mesa. That
442 * makes this routine pretty simple.
444 static const struct gl_texture_format
*
445 i810ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
446 GLenum format
, GLenum type
)
448 switch ( internalFormat
) {
458 case GL_COMPRESSED_RGBA
:
459 if ( ((format
== GL_BGRA
) && (type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
))
460 || ((format
== GL_RGBA
) && (type
== GL_UNSIGNED_SHORT_5_5_5_1
))
461 || (internalFormat
== GL_RGB5_A1
) ) {
462 return &_mesa_texformat_argb1555
;
464 return &_mesa_texformat_argb4444
;
468 case GL_COMPRESSED_RGB
:
476 return &_mesa_texformat_rgb565
;
483 case GL_COMPRESSED_ALPHA
:
490 case GL_COMPRESSED_LUMINANCE
:
492 case GL_LUMINANCE_ALPHA
:
493 case GL_LUMINANCE4_ALPHA4
:
494 case GL_LUMINANCE6_ALPHA2
:
495 case GL_LUMINANCE8_ALPHA8
:
496 case GL_LUMINANCE12_ALPHA4
:
497 case GL_LUMINANCE12_ALPHA12
:
498 case GL_LUMINANCE16_ALPHA16
:
499 case GL_COMPRESSED_LUMINANCE_ALPHA
:
505 case GL_COMPRESSED_INTENSITY
:
506 return &_mesa_texformat_al88
;
509 if (type
== GL_UNSIGNED_SHORT_8_8_MESA
||
510 type
== GL_UNSIGNED_BYTE
)
511 return &_mesa_texformat_ycbcr
;
513 return &_mesa_texformat_ycbcr_rev
;
516 fprintf(stderr
, "unexpected texture format in %s\n", __FUNCTION__
);
520 return NULL
; /* never get here */
524 * Allocate a new texture object.
525 * Called via ctx->Driver.NewTextureObject.
526 * Note: this function will be called during context creation to
527 * allocate the default texture objects.
528 * Note: we could use containment here to 'derive' the driver-specific
529 * texture object from the core mesa gl_texture_object. Not done at this time.
531 static struct gl_texture_object
*
532 i810NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
534 struct gl_texture_object
*obj
;
535 obj
= _mesa_new_texture_object(ctx
, name
, target
);
536 i810AllocTexObj( ctx
, obj
);
540 void i810InitTextureFuncs( struct dd_function_table
*functions
)
542 functions
->ChooseTextureFormat
= i810ChooseTextureFormat
;
543 functions
->TexImage2D
= i810TexImage2D
;
544 functions
->TexSubImage2D
= i810TexSubImage2D
;
545 functions
->BindTexture
= i810BindTexture
;
546 functions
->NewTextureObject
= i810NewTextureObject
;
547 functions
->DeleteTexture
= i810DeleteTexture
;
548 functions
->TexParameter
= i810TexParameter
;
549 functions
->TexEnv
= i810TexEnv
;
550 functions
->IsTextureResident
= driIsTextureResident
;