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
;
381 I830_FIREVERTICES( I830_CONTEXT(ctx
) );
382 driSwapOutTextureObject( t
);
385 t
= (driTextureObject
*) i830AllocTexObj( texObj
);
387 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
392 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
393 width
, height
, border
, format
, type
,
394 pixels
, packing
, texObj
, texImage
);
397 static void i830TexSubImage2D( GLcontext
*ctx
,
400 GLint xoffset
, GLint yoffset
,
401 GLsizei width
, GLsizei height
,
402 GLenum format
, GLenum type
,
403 const GLvoid
*pixels
,
404 const struct gl_pixelstore_attrib
*packing
,
405 struct gl_texture_object
*texObj
,
406 struct gl_texture_image
*texImage
)
408 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
411 I830_FIREVERTICES( I830_CONTEXT(ctx
) );
412 driSwapOutTextureObject( t
);
414 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
415 height
, format
, type
, pixels
, packing
, texObj
,
422 /* no longer needed */
423 static void i830BindTexture( GLcontext
*ctx
, GLenum target
,
424 struct gl_texture_object
*tObj
)
426 if (!tObj
->DriverData
) {
427 i830AllocTexObj( tObj
);
433 static void i830DeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
435 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
438 i830ContextPtr imesa
= I830_CONTEXT( ctx
);
441 I830_FIREVERTICES( imesa
);
444 driDestroyTextureObject( t
);
446 /* Free mipmap images and the texture object itself */
447 _mesa_delete_texture_object(ctx
, tObj
);
451 static const struct gl_texture_format
*
452 i830ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
453 GLenum format
, GLenum type
)
455 i830ContextPtr imesa
= I830_CONTEXT( ctx
);
456 const GLboolean do32bpt
= ( imesa
->i830Screen
->cpp
== 4 &&
457 imesa
->i830Screen
->textureSize
> 4*1024*1024);
459 switch ( internalFormat
) {
462 case GL_COMPRESSED_RGBA
:
463 if ( format
== GL_BGRA
) {
464 if ( type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
465 return &_mesa_texformat_argb8888
;
467 else if ( type
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
468 return &_mesa_texformat_argb4444
;
470 else if ( type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
471 return &_mesa_texformat_argb1555
;
474 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
478 case GL_COMPRESSED_RGB
:
479 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
480 return &_mesa_texformat_rgb565
;
482 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
488 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
492 return &_mesa_texformat_argb4444
;
495 return &_mesa_texformat_argb1555
;
501 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
506 return &_mesa_texformat_rgb565
;
513 case GL_COMPRESSED_ALPHA
:
514 return &_mesa_texformat_al88
;
522 case GL_COMPRESSED_LUMINANCE
:
523 return &_mesa_texformat_l8
;
526 case GL_LUMINANCE_ALPHA
:
527 case GL_LUMINANCE4_ALPHA4
:
528 case GL_LUMINANCE6_ALPHA2
:
529 case GL_LUMINANCE8_ALPHA8
:
530 case GL_LUMINANCE12_ALPHA4
:
531 case GL_LUMINANCE12_ALPHA12
:
532 case GL_LUMINANCE16_ALPHA16
:
533 case GL_COMPRESSED_LUMINANCE_ALPHA
:
534 return &_mesa_texformat_al88
;
541 case GL_COMPRESSED_INTENSITY
:
542 return &_mesa_texformat_i8
;
545 if (type
== GL_UNSIGNED_SHORT_8_8_MESA
||
546 type
== GL_UNSIGNED_BYTE
)
547 return &_mesa_texformat_ycbcr
;
549 return &_mesa_texformat_ycbcr_rev
;
552 fprintf(stderr
, "unexpected texture format in %s\n", __FUNCTION__
);
556 return NULL
; /* never get here */
560 * Allocate a new texture object.
561 * Called via ctx->Driver.NewTextureObject.
562 * Note: this function will be called during context creation to
563 * allocate the default texture objects.
565 static struct gl_texture_object
*
566 i830NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
568 struct gl_texture_object
*obj
;
570 obj
= _mesa_new_texture_object(ctx
, name
, target
);
573 t
= (driTextureObject
*) i830AllocTexObj( obj
);
575 _mesa_delete_texture_object(ctx
, obj
);
581 void i830InitTextureFuncs( struct dd_function_table
*functions
)
583 functions
->NewTextureObject
= i830NewTextureObject
;
584 functions
->DeleteTexture
= i830DeleteTexture
;
585 functions
->ChooseTextureFormat
= i830ChooseTextureFormat
;
586 functions
->TexImage2D
= i830TexImage2D
;
587 functions
->TexSubImage2D
= i830TexSubImage2D
;
588 /*functions->BindTexture = i830BindTexture;*/
589 functions
->TexParameter
= i830TexParameter
;
590 functions
->TexEnv
= i830TexEnv
;
591 functions
->IsTextureResident
= driIsTextureResident
;