1 /**************************************************************************
3 Copyright 2001 2d3d Inc., Delray Beach, FL
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_tex.c,v 1.5 2003/05/07 21:56:31 dawes Exp $ */
32 * Jeff Hartmann <jhartmann@2d3d.com>
34 * Heavily based on the I810 driver, which was written by:
35 * Keith Whitwell <keithw@tungstengraphics.com>
41 #include "simple_list.h"
45 #include "texformat.h"
47 #include "swrast/swrast.h"
51 #include "i830_screen.h"
53 #include "i830_context.h"
55 #include "i830_state.h"
56 #include "i830_ioctl.h"
59 * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias.
61 static void i830ComputeLodBias( i830ContextPtr imesa
, unsigned unit
,
66 b
= (int) (bias
* 16.0);
68 else if (b
< -64) b
= -64;
69 imesa
->LodBias
[ unit
] = ((b
<< TM0S3_LOD_BIAS_SHIFT
) &
75 * Set the texture wrap modes.
77 * The i830M (and related graphics cores) do not support GL_CLAMP. The Intel
78 * drivers for "other operating systems" implement GL_CLAMP as
79 * GL_CLAMP_TO_EDGE, so the same is done here.
81 * \param t Texture object whose wrap modes are to be set
82 * \param swrap Wrap mode for the \a s texture coordinate
83 * \param twrap Wrap mode for the \a t texture coordinate
86 static void i830SetTexWrapping(i830TextureObjectPtr tex
,
87 GLenum swrap
, GLenum twrap
)
89 tex
->Setup
[I830_TEXREG_MCS
] &= ~(TEXCOORD_ADDR_U_MASK
|TEXCOORD_ADDR_V_MASK
);
93 tex
->Setup
[I830_TEXREG_MCS
] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP
);
96 case GL_CLAMP_TO_EDGE
:
97 tex
->Setup
[I830_TEXREG_MCS
] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP
);
99 case GL_CLAMP_TO_BORDER
:
100 tex
->Setup
[I830_TEXREG_MCS
] |=
101 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER
);
103 case GL_MIRRORED_REPEAT
:
104 tex
->Setup
[I830_TEXREG_MCS
] |=
105 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR
);
108 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
113 tex
->Setup
[I830_TEXREG_MCS
] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP
);
116 case GL_CLAMP_TO_EDGE
:
117 tex
->Setup
[I830_TEXREG_MCS
] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP
);
119 case GL_CLAMP_TO_BORDER
:
120 tex
->Setup
[I830_TEXREG_MCS
] |=
121 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER
);
123 case GL_MIRRORED_REPEAT
:
124 tex
->Setup
[I830_TEXREG_MCS
] |=
125 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR
);
128 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
132 static void i830SetTexMaxAnisotropy( i830TextureObjectPtr t
, GLfloat max
)
134 t
->max_anisotropy
= max
;
139 * Set the texture magnification and minification modes.
141 * \param t Texture whose filter modes are to be set
142 * \param minf Texture minification mode
143 * \param magf Texture magnification mode
144 * \param bias LOD bias for this texture unit.
147 static void i830SetTexFilter( i830TextureObjectPtr t
,
148 GLenum minf
, GLenum magf
)
150 int minFilt
= 0, mipFilt
= 0, magFilt
= 0;
152 if(I830_DEBUG
&DEBUG_DRI
)
153 fprintf(stderr
, "%s\n", __FUNCTION__
);
155 if ( t
->max_anisotropy
> 1.0 ) {
156 minFilt
= FILTER_ANISOTROPIC
;
157 magFilt
= FILTER_ANISOTROPIC
;
162 minFilt
= FILTER_NEAREST
;
163 mipFilt
= MIPFILTER_NONE
;
166 minFilt
= FILTER_LINEAR
;
167 mipFilt
= MIPFILTER_NONE
;
169 case GL_NEAREST_MIPMAP_NEAREST
:
170 minFilt
= FILTER_NEAREST
;
171 mipFilt
= MIPFILTER_NEAREST
;
173 case GL_LINEAR_MIPMAP_NEAREST
:
174 minFilt
= FILTER_LINEAR
;
175 mipFilt
= MIPFILTER_NEAREST
;
177 case GL_NEAREST_MIPMAP_LINEAR
:
178 minFilt
= FILTER_NEAREST
;
179 mipFilt
= MIPFILTER_LINEAR
;
181 case GL_LINEAR_MIPMAP_LINEAR
:
182 minFilt
= FILTER_LINEAR
;
183 mipFilt
= MIPFILTER_LINEAR
;
186 _mesa_problem(NULL
, "%s: Unsupported min. filter %d", __FUNCTION__
,
193 magFilt
= FILTER_NEAREST
;
196 magFilt
= FILTER_LINEAR
;
199 _mesa_problem(NULL
, "%s: Unsupported mag. filter %d", __FUNCTION__
,
205 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MIN_FILTER_MASK
;
206 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MIP_FILTER_MASK
;
207 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MAG_FILTER_MASK
;
208 t
->Setup
[I830_TEXREG_TM0S3
] |= ((minFilt
<< TM0S3_MIN_FILTER_SHIFT
) |
209 (mipFilt
<< TM0S3_MIP_FILTER_SHIFT
) |
210 (magFilt
<< TM0S3_MAG_FILTER_SHIFT
));
213 static void i830SetTexBorderColor(i830TextureObjectPtr t
, GLubyte color
[4])
215 if(I830_DEBUG
&DEBUG_DRI
)
216 fprintf(stderr
, "%s\n", __FUNCTION__
);
218 t
->Setup
[I830_TEXREG_TM0S4
] =
219 I830PACKCOLOR8888(color
[0],color
[1],color
[2],color
[3]);
224 * Allocate space for and load the mesa images into the texture memory block.
225 * This will happen before drawing with a new texture, or drawing with a
226 * texture after it was swapped out or teximaged again.
229 static i830TextureObjectPtr
i830AllocTexObj( struct gl_texture_object
*texObj
)
231 i830TextureObjectPtr t
;
233 t
= CALLOC_STRUCT( i830_texture_object_t
);
234 texObj
->DriverData
= t
;
236 /* Initialize non-image-dependent parts of the state:
238 t
->base
.tObj
= texObj
;
240 t
->Setup
[I830_TEXREG_TM0LI
] = STATE3D_LOAD_STATE_IMMEDIATE_2
;
241 t
->Setup
[I830_TEXREG_TM0S0
] = TM0S0_USE_FENCE
;
242 t
->Setup
[I830_TEXREG_TM0S1
] = 0;
243 t
->Setup
[I830_TEXREG_TM0S2
] = 0;
244 t
->Setup
[I830_TEXREG_TM0S3
] = 0;
246 t
->Setup
[I830_TEXREG_NOP0
] = 0;
247 t
->Setup
[I830_TEXREG_NOP1
] = 0;
248 t
->Setup
[I830_TEXREG_NOP2
] = 0;
250 t
->Setup
[I830_TEXREG_MCS
] = (STATE3D_MAP_COORD_SET_CMD
|
252 ENABLE_TEXCOORD_PARAMS
|
253 TEXCOORDS_ARE_NORMAL
|
254 TEXCOORDTYPE_CARTESIAN
|
256 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP
) |
258 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP
));
260 make_empty_list( & t
->base
);
262 i830SetTexWrapping( t
, texObj
->WrapS
, texObj
->WrapT
);
263 i830SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
264 i830SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
265 i830SetTexBorderColor( t
, texObj
->_BorderChan
);
272 static void i830TexParameter( GLcontext
*ctx
, GLenum target
,
273 struct gl_texture_object
*tObj
,
274 GLenum pname
, const GLfloat
*params
)
276 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
277 i830TextureObjectPtr t
= (i830TextureObjectPtr
) tObj
->DriverData
;
278 GLuint unit
= ctx
->Texture
.CurrentUnit
;
282 if ( target
!= GL_TEXTURE_2D
)
285 /* Can't do the update now as we don't know whether to flush
286 * vertices or not. Setting imesa->NewGLState means that
287 * i830UpdateTextureState() will be called before any triangles are
288 * rendered. If a statechange has occurred, it will be detected at
289 * that point, and buffered vertices flushed.
292 case GL_TEXTURE_MIN_FILTER
:
293 case GL_TEXTURE_MAG_FILTER
:
294 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
295 i830SetTexMaxAnisotropy( t
, tObj
->MaxAnisotropy
);
296 i830SetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
299 case GL_TEXTURE_WRAP_S
:
300 case GL_TEXTURE_WRAP_T
:
301 i830SetTexWrapping( t
, tObj
->WrapS
, tObj
->WrapT
);
304 case GL_TEXTURE_BORDER_COLOR
:
305 i830SetTexBorderColor( t
, tObj
->_BorderChan
);
308 case GL_TEXTURE_BASE_LEVEL
:
309 case GL_TEXTURE_MAX_LEVEL
:
310 case GL_TEXTURE_MIN_LOD
:
311 case GL_TEXTURE_MAX_LOD
:
312 /* The i830 and its successors can do a lot of this without
313 * reloading the textures. A project for someone?
315 I830_FIREVERTICES( I830_CONTEXT(ctx
) );
316 driSwapOutTextureObject( (driTextureObject
*) t
);
323 if (t
== imesa
->CurrentTexObj
[unit
]) {
324 I830_STATECHANGE( imesa
, I830_UPLOAD_TEX0
);
329 static void i830TexEnv( GLcontext
*ctx
, GLenum target
,
330 GLenum pname
, const GLfloat
*param
)
332 i830ContextPtr imesa
= I830_CONTEXT( ctx
);
333 GLuint unit
= ctx
->Texture
.CurrentUnit
;
335 /* Only one env color. Need a fallback if env colors are different
336 * and texture setup references env color in both units.
339 case GL_TEXTURE_ENV_COLOR
:
340 case GL_TEXTURE_ENV_MODE
:
341 case GL_COMBINE_RGB_EXT
:
342 case GL_COMBINE_ALPHA_EXT
:
343 case GL_SOURCE0_RGB_EXT
:
344 case GL_SOURCE1_RGB_EXT
:
345 case GL_SOURCE2_RGB_EXT
:
346 case GL_SOURCE0_ALPHA_EXT
:
347 case GL_SOURCE1_ALPHA_EXT
:
348 case GL_SOURCE2_ALPHA_EXT
:
349 case GL_OPERAND0_RGB_EXT
:
350 case GL_OPERAND1_RGB_EXT
:
351 case GL_OPERAND2_RGB_EXT
:
352 case GL_OPERAND0_ALPHA_EXT
:
353 case GL_OPERAND1_ALPHA_EXT
:
354 case GL_OPERAND2_ALPHA_EXT
:
355 case GL_RGB_SCALE_EXT
:
357 imesa
->TexEnvImageFmt
[unit
] = 0; /* force recalc of env state */
360 case GL_TEXTURE_LOD_BIAS_EXT
:
361 i830ComputeLodBias( imesa
, unit
, *param
);
362 I830_STATECHANGE( imesa
, I830_UPLOAD_TEX_N(unit
) );
370 static void i830TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
371 GLint internalFormat
,
372 GLint width
, GLint height
, GLint border
,
373 GLenum format
, GLenum type
, const GLvoid
*pixels
,
374 const struct gl_pixelstore_attrib
*packing
,
375 struct gl_texture_object
*texObj
,
376 struct gl_texture_image
*texImage
)
378 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
380 I830_FIREVERTICES( I830_CONTEXT(ctx
) );
381 driSwapOutTextureObject( t
);
384 t
= (driTextureObject
*) i830AllocTexObj( texObj
);
386 _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 i830TexSubImage2D( 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 I830_FIREVERTICES( I830_CONTEXT(ctx
) );
410 driSwapOutTextureObject( t
);
412 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
413 height
, format
, type
, pixels
, packing
, texObj
,
419 static void i830BindTexture( GLcontext
*ctx
, GLenum target
,
420 struct gl_texture_object
*tObj
)
422 if (!tObj
->DriverData
) {
423 i830AllocTexObj( tObj
);
428 static void i830DeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
430 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
433 i830ContextPtr imesa
= I830_CONTEXT( ctx
);
436 I830_FIREVERTICES( imesa
);
439 driDestroyTextureObject( t
);
444 static const struct gl_texture_format
*
445 i830ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
446 GLenum format
, GLenum type
)
448 i830ContextPtr imesa
= I830_CONTEXT( ctx
);
449 const GLboolean do32bpt
= ( imesa
->i830Screen
->cpp
== 4 &&
450 imesa
->i830Screen
->textureSize
> 4*1024*1024);
452 switch ( internalFormat
) {
455 case GL_COMPRESSED_RGBA
:
456 if ( format
== GL_BGRA
) {
457 if ( type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
458 return &_mesa_texformat_argb8888
;
460 else if ( type
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
461 return &_mesa_texformat_argb4444
;
463 else if ( type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
464 return &_mesa_texformat_argb1555
;
467 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
471 case GL_COMPRESSED_RGB
:
472 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
473 return &_mesa_texformat_rgb565
;
475 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
481 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
485 return &_mesa_texformat_argb4444
;
488 return &_mesa_texformat_argb1555
;
494 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
499 return &_mesa_texformat_rgb565
;
506 case GL_COMPRESSED_ALPHA
:
507 return &_mesa_texformat_al88
;
515 case GL_COMPRESSED_LUMINANCE
:
516 return &_mesa_texformat_l8
;
519 case GL_LUMINANCE_ALPHA
:
520 case GL_LUMINANCE4_ALPHA4
:
521 case GL_LUMINANCE6_ALPHA2
:
522 case GL_LUMINANCE8_ALPHA8
:
523 case GL_LUMINANCE12_ALPHA4
:
524 case GL_LUMINANCE12_ALPHA12
:
525 case GL_LUMINANCE16_ALPHA16
:
526 case GL_COMPRESSED_LUMINANCE_ALPHA
:
527 return &_mesa_texformat_al88
;
534 case GL_COMPRESSED_INTENSITY
:
535 return &_mesa_texformat_i8
;
538 if (type
== GL_UNSIGNED_SHORT_8_8_MESA
||
539 type
== GL_UNSIGNED_BYTE
)
540 return &_mesa_texformat_ycbcr
;
542 return &_mesa_texformat_ycbcr_rev
;
545 fprintf(stderr
, "unexpected texture format in %s\n", __FUNCTION__
);
549 return NULL
; /* never get here */
552 void i830DDInitTextureFuncs( GLcontext
*ctx
)
554 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
556 ctx
->Driver
.TexEnv
= i830TexEnv
;
557 ctx
->Driver
.ChooseTextureFormat
= i830ChooseTextureFormat
;
558 ctx
->Driver
.TexImage1D
= _mesa_store_teximage1d
;
559 ctx
->Driver
.TexImage2D
= i830TexImage2D
;
560 ctx
->Driver
.TexImage3D
= _mesa_store_teximage3d
;
561 ctx
->Driver
.TexSubImage1D
= _mesa_store_texsubimage1d
;
562 ctx
->Driver
.TexSubImage2D
= i830TexSubImage2D
;
563 ctx
->Driver
.TexSubImage3D
= _mesa_store_texsubimage3d
;
564 ctx
->Driver
.CopyTexImage1D
= _swrast_copy_teximage1d
;
565 ctx
->Driver
.CopyTexImage2D
= _swrast_copy_teximage2d
;
566 ctx
->Driver
.CopyTexSubImage1D
= _swrast_copy_texsubimage1d
;
567 ctx
->Driver
.CopyTexSubImage2D
= _swrast_copy_texsubimage2d
;
568 ctx
->Driver
.CopyTexSubImage3D
= _swrast_copy_texsubimage3d
;
569 ctx
->Driver
.BindTexture
= i830BindTexture
;
570 ctx
->Driver
.DeleteTexture
= i830DeleteTexture
;
571 ctx
->Driver
.TexParameter
= i830TexParameter
;
572 ctx
->Driver
.UpdateTexturePalette
= NULL
;
573 ctx
->Driver
.IsTextureResident
= driIsTextureResident
;
574 ctx
->Driver
.TestProxyTexImage
= _mesa_test_proxy_teximage
;
576 driInitTextureObjects( ctx
, & imesa
->swapped
,
577 DRI_TEXMGR_DO_TEXTURE_2D
578 | DRI_TEXMGR_DO_TEXTURE_RECT
);