2 * \file radeon_subset_tex.c
5 * \author Gareth Hughes <gareth@valinux.com>
6 * \author Brian Paul <brianp@valinux.com>
10 * Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
11 * VA Linux Systems Inc., Fremont, California.
13 * All Rights Reserved.
15 * Permission is hereby granted, free of charge, to any person obtaining a
16 * copy of this software and associated documentation files (the "Software"),
17 * to deal in the Software without restriction, including without limitation
18 * on the rights to use, copy, modify, merge, publish, distribute, sub
19 * license, and/or sell copies of the Software, and to permit persons to whom
20 * the Software is furnished to do so, subject to the following conditions:
22 * The above copyright notice and this permission notice (including the next
23 * paragraph) shall be included in all copies or substantial portions of the
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
29 * ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
30 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
31 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
32 * USE OR OTHER DEALINGS IN THE SOFTWARE.
35 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.6 2002/09/16 18:05:20 eich Exp $ */
43 #include "simple_list.h"
44 #include "texformat.h"
47 #include "radeon_context.h"
48 #include "radeon_state.h"
49 #include "radeon_ioctl.h"
50 #include "radeon_subset.h"
57 * \brief Destroy hardware state associated with a texture.
59 * \param rmesa Radeon context.
60 * \param t Radeon texture object to be destroyed.
62 * Frees the memory associated with the texture and if the texture is bound to
63 * a texture unit cleans the associated hardware state.
65 void radeonDestroyTexObj( radeonContextPtr rmesa
, radeonTexObjPtr t
)
68 mmFreeMem( t
->memBlock
);
73 t
->tObj
->DriverData
= NULL
;
76 if ( t
== rmesa
->state
.texture
.unit
[0].texobj
) {
77 rmesa
->state
.texture
.unit
[0].texobj
= NULL
;
78 remove_from_list( &rmesa
->hw
.tex
[0] );
79 make_empty_list( &rmesa
->hw
.tex
[0] );
83 remove_from_list( t
);
89 * \brief Keep track of swapped out texture objects.
91 * \param rmesa Radeon context.
92 * \param t Radeon texture object.
94 * Frees the memory associated with the texture, marks all mipmap images in
95 * the texture as dirty and add it to the radeon_texture::swapped list.
97 static void radeonSwapOutTexObj( radeonContextPtr rmesa
, radeonTexObjPtr t
)
100 mmFreeMem( t
->memBlock
);
104 t
->dirty_images
= ~0;
105 move_to_tail( &rmesa
->texture
.swapped
, t
);
110 * Texture space has been invalidated.
112 * \param rmesa Radeon context.
113 * \param heap texture heap number.
115 * Swaps out every texture in the specified heap.
117 void radeonAgeTextures( radeonContextPtr rmesa
, int heap
)
119 radeonTexObjPtr t
, tmp
;
121 foreach_s ( t
, tmp
, &rmesa
->texture
.objects
[heap
] )
122 radeonSwapOutTexObj( rmesa
, t
);
126 /***************************************************************/
127 /** \name Texture image conversions
132 * \brief Upload texture image.
134 * \param rmesa Radeon context.
135 * \param t Radeon texture object.
136 * \param level level of the image to take the sub-image.
137 * \param x sub-image abscissa.
138 * \param y sub-image ordinate.
139 * \param width sub-image width.
140 * \param height sub-image height.
142 * Fills in a drmRadeonTexture and drmRadeonTexImage structures and uploads the
143 * texture via the DRM_RADEON_TEXTURE ioctl, aborting in case of failure.
145 static void radeonUploadSubImage( radeonContextPtr rmesa
,
146 radeonTexObjPtr t
, GLint level
,
147 GLint x
, GLint y
, GLint width
, GLint height
)
149 struct gl_texture_image
*texImage
;
151 drmRadeonTexture tex
;
152 drmRadeonTexImage tmp
;
154 level
+= t
->firstLevel
;
155 texImage
= t
->tObj
->Image
[0][level
];
157 if ( !texImage
|| !texImage
->Data
)
160 t
->image
[level
].data
= texImage
->Data
;
162 tex
.offset
= t
->bufAddr
;
163 tex
.pitch
= (t
->image
[0].width
* texImage
->TexFormat
->TexelBytes
) / 64;
164 tex
.format
= t
->pp_txformat
& RADEON_TXFORMAT_FORMAT_MASK
;
165 tex
.width
= texImage
->Width
;
166 tex
.height
= texImage
->Height
;
169 memcpy( &tmp
, &t
->image
[level
], sizeof(drmRadeonTexImage
) );
172 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_TEXTURE
,
173 &tex
, sizeof(drmRadeonTexture
) );
174 } while ( ret
&& errno
== EAGAIN
);
177 UNLOCK_HARDWARE( rmesa
);
178 fprintf( stderr
, "DRM_RADEON_TEXTURE: return = %d\n", ret
);
184 * \brief Upload texture images.
186 * This might require removing our own and/or other client's texture objects to
187 * make room for these images.
189 * \param rmesa Radeon context.
190 * \param tObj texture object to upload.
192 * Sets the matching hardware texture format. Calculates which mipmap levels to
193 * send, depending of the base image size, GL_TEXTURE_MIN_LOD,
194 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL and the
195 * Radeon offset rules. Kicks out textures until the requested texture fits,
196 * sets the texture hardware state and, while holding the hardware lock,
197 * uploads any images that are new.
199 static void radeonSetTexImages( radeonContextPtr rmesa
,
200 struct gl_texture_object
*tObj
)
202 radeonTexObjPtr t
= (radeonTexObjPtr
)tObj
->DriverData
;
203 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
205 GLint texelsPerDword
= 0, blitWidth
= 0, blitPitch
= 0;
206 GLint x
, y
, width
, height
;
208 GLint firstLevel
, lastLevel
, numLevels
;
209 GLint log2Width
, log2Height
;
212 /* This code cannot be reached once we have lost focus
214 assert(rmesa
->radeonScreen
->buffers
);
216 /* Set the hardware texture format
218 switch (baseImage
->TexFormat
->MesaFormat
) {
220 txformat
= RADEON_TXFORMAT_I8
;
224 case MESA_FORMAT_RGBA8888
:
225 txformat
= RADEON_TXFORMAT_RGBA8888
| RADEON_TXFORMAT_ALPHA_IN_MAP
;
229 case MESA_FORMAT_RGB565
:
230 txformat
= RADEON_TXFORMAT_RGB565
;
235 _mesa_problem(NULL
, "unexpected texture format in radeonTexImage2D");
239 t
->pp_txformat
&= ~(RADEON_TXFORMAT_FORMAT_MASK
|
240 RADEON_TXFORMAT_ALPHA_IN_MAP
);
241 t
->pp_txformat
|= txformat
;
244 /* Select the larger of the two widths for our global texture image
245 * coordinate space. As the Radeon has very strict offset rules, we
246 * can't upload mipmaps directly and have to reference their location
247 * from the aligned start of the whole image.
249 blitWidth
= MAX2( baseImage
->Width
, blitPitch
);
251 /* Calculate mipmap offsets and dimensions.
257 /* Compute which mipmap levels we really want to send to the hardware.
258 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
259 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
260 * Yes, this looks overly complicated, but it's all needed.
262 firstLevel
= tObj
->BaseLevel
+ (GLint
) (tObj
->MinLod
+ 0.5);
263 firstLevel
= MAX2(firstLevel
, tObj
->BaseLevel
);
264 lastLevel
= tObj
->BaseLevel
+ (GLint
) (tObj
->MaxLod
+ 0.5);
265 lastLevel
= MAX2(lastLevel
, tObj
->BaseLevel
);
266 lastLevel
= MIN2(lastLevel
, tObj
->BaseLevel
+ baseImage
->MaxLog2
);
267 lastLevel
= MIN2(lastLevel
, tObj
->MaxLevel
);
268 lastLevel
= MAX2(firstLevel
, lastLevel
); /* need at least one level */
270 /* save these values */
271 t
->firstLevel
= firstLevel
;
272 t
->lastLevel
= lastLevel
;
274 numLevels
= lastLevel
- firstLevel
+ 1;
276 log2Width
= tObj
->Image
[0][firstLevel
]->WidthLog2
;
277 log2Height
= tObj
->Image
[0][firstLevel
]->HeightLog2
;
279 for ( i
= 0 ; i
< numLevels
; i
++ ) {
280 const struct gl_texture_image
*texImage
= tObj
->Image
[0][i
+ firstLevel
];
284 width
= texImage
->Width
;
285 height
= texImage
->Height
;
287 /* Texture images have a minimum pitch of 32 bytes (half of the
288 * 64-byte minimum pitch for blits). For images that have a
289 * width smaller than this, we must pad each texture image
290 * scanline out to this amount.
292 if ( width
< blitPitch
/ 2 ) {
293 width
= blitPitch
/ 2;
296 totalSize
+= width
* height
* baseImage
->TexFormat
->TexelBytes
;
297 ASSERT( (totalSize
& 31) == 0 );
299 while ( width
< blitWidth
&& height
> 1 ) {
304 ASSERT(i
< RADEON_MAX_TEXTURE_LEVELS
);
307 t
->image
[i
].width
= width
;
308 t
->image
[i
].height
= height
;
310 /* While blits must have a pitch of at least 64 bytes, mipmaps
311 * must be aligned on a 32-byte boundary (just like each texture
314 if ( width
>= blitWidth
) {
318 if ( x
>= blitWidth
) {
325 /* Align the total size of texture memory block.
327 t
->totalSize
= (totalSize
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
331 t
->pp_txfilter
&= ~RADEON_MAX_MIP_LEVEL_MASK
;
332 t
->pp_txfilter
|= (numLevels
- 1) << RADEON_MAX_MIP_LEVEL_SHIFT
;
334 t
->pp_txformat
&= ~(RADEON_TXFORMAT_WIDTH_MASK
|
335 RADEON_TXFORMAT_HEIGHT_MASK
);
336 t
->pp_txformat
|= ((log2Width
<< RADEON_TXFORMAT_WIDTH_SHIFT
) |
337 (log2Height
<< RADEON_TXFORMAT_HEIGHT_SHIFT
));
338 t
->dirty_state
= TEX_ALL
;
340 /* Update the local texture LRU.
342 move_to_head( &rmesa
->texture
.objects
[0], t
);
344 LOCK_HARDWARE( rmesa
);
346 /* Kick out textures until the requested texture fits */
347 while ( !t
->memBlock
) {
348 t
->memBlock
= mmAllocMem( rmesa
->texture
.heap
[0], t
->totalSize
, 12, 0);
351 radeonSwapOutTexObj( rmesa
, rmesa
->texture
.objects
[0].prev
);
355 /* Set the base offset of the texture image */
356 t
->bufAddr
= rmesa
->radeonScreen
->texOffset
[0] + t
->memBlock
->ofs
;
357 t
->pp_txoffset
= t
->bufAddr
;
359 /* Upload any images that are new
361 for ( i
= 0 ; i
< numLevels
; i
++ ) {
362 if ( t
->dirty_images
& (1 << i
) ) {
363 radeonUploadSubImage( rmesa
, t
, i
, 0, 0,
364 t
->image
[i
].width
, t
->image
[i
].height
);
368 rmesa
->texture
.age
[0] = ++rmesa
->sarea
->texAge
[0];
369 UNLOCK_HARDWARE( rmesa
);
376 /******************************************************************/
377 /** \name Texture combine functions
382 RADEON_DISABLE
= 0, /**< \brief disabled */
383 RADEON_REPLACE
= 1, /**< \brief replace function */
384 RADEON_MODULATE
= 2, /**< \brief modulate function */
385 RADEON_DECAL
= 3, /**< \brief decal function */
386 RADEON_BLEND
= 4, /**< \brief blend function */
387 RADEON_MAX_COMBFUNC
= 5 /**< \brief max number of combine functions */
392 * \brief Color combine function hardware state table.
394 static GLuint radeon_color_combine
[][RADEON_MAX_COMBFUNC
] =
399 /* Disable combiner stage
401 (RADEON_COLOR_ARG_A_ZERO
|
402 RADEON_COLOR_ARG_B_ZERO
|
403 RADEON_COLOR_ARG_C_CURRENT_COLOR
|
404 RADEON_BLEND_CTL_ADD
|
408 /* GL_REPLACE = 0x00802800
410 (RADEON_COLOR_ARG_A_ZERO
|
411 RADEON_COLOR_ARG_B_ZERO
|
412 RADEON_COLOR_ARG_C_T0_COLOR
|
413 RADEON_BLEND_CTL_ADD
|
417 /* GL_MODULATE = 0x00800142
419 (RADEON_COLOR_ARG_A_CURRENT_COLOR
|
420 RADEON_COLOR_ARG_B_T0_COLOR
|
421 RADEON_COLOR_ARG_C_ZERO
|
422 RADEON_BLEND_CTL_ADD
|
426 /* GL_DECAL = 0x008c2d42
428 (RADEON_COLOR_ARG_A_CURRENT_COLOR
|
429 RADEON_COLOR_ARG_B_T0_COLOR
|
430 RADEON_COLOR_ARG_C_T0_ALPHA
|
431 RADEON_BLEND_CTL_BLEND
|
435 /* GL_BLEND = 0x008c2902
437 (RADEON_COLOR_ARG_A_CURRENT_COLOR
|
438 RADEON_COLOR_ARG_B_TFACTOR_COLOR
|
439 RADEON_COLOR_ARG_C_T0_COLOR
|
440 RADEON_BLEND_CTL_BLEND
|
448 * \brief Alpha combine function hardware state table.
450 static GLuint radeon_alpha_combine
[][RADEON_MAX_COMBFUNC
] =
455 /* Disable combiner stage
457 (RADEON_ALPHA_ARG_A_ZERO
|
458 RADEON_ALPHA_ARG_B_ZERO
|
459 RADEON_ALPHA_ARG_C_CURRENT_ALPHA
|
460 RADEON_BLEND_CTL_ADD
|
464 /* GL_REPLACE = 0x00800500
466 (RADEON_ALPHA_ARG_A_ZERO
|
467 RADEON_ALPHA_ARG_B_ZERO
|
468 RADEON_ALPHA_ARG_C_T0_ALPHA
|
469 RADEON_BLEND_CTL_ADD
|
473 /* GL_MODULATE = 0x00800051
475 (RADEON_ALPHA_ARG_A_CURRENT_ALPHA
|
476 RADEON_ALPHA_ARG_B_T0_ALPHA
|
477 RADEON_ALPHA_ARG_C_ZERO
|
478 RADEON_BLEND_CTL_ADD
|
482 /* GL_DECAL = 0x00800100
484 (RADEON_ALPHA_ARG_A_ZERO
|
485 RADEON_ALPHA_ARG_B_ZERO
|
486 RADEON_ALPHA_ARG_C_CURRENT_ALPHA
|
487 RADEON_BLEND_CTL_ADD
|
491 /* GL_BLEND = 0x00800051
493 (RADEON_ALPHA_ARG_A_CURRENT_ALPHA
|
494 RADEON_ALPHA_ARG_B_TFACTOR_ALPHA
|
495 RADEON_ALPHA_ARG_C_T0_ALPHA
|
496 RADEON_BLEND_CTL_BLEND
|
507 /******************************************************************/
508 /** \name Texture unit state management
513 * \brief Update the texture environment.
515 * \param ctx GL context
516 * \param unit texture unit to update.
518 * Sets the state of the RADEON_TEX_PP_TXCBLEND and RADEON_TEX_PP_TXABLEND
519 * registers using the ::radeon_color_combine and ::radeon_alpha_combine tables,
520 * and informs of the state change.
522 static void radeonUpdateTextureEnv( GLcontext
*ctx
, int unit
)
524 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
525 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
526 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
527 const GLenum format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
528 GLuint color_combine
= radeon_color_combine
[unit
][RADEON_DISABLE
];
529 GLuint alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
532 /* Set the texture environment state. Isn't this nice and clean?
533 * The Radeon will automagically set the texture alpha to 0xff when
534 * the texture format does not include an alpha component. This
535 * reduces the amount of special-casing we have to do, alpha-only
536 * textures being a notable exception.
538 switch ( texUnit
->EnvMode
) {
543 color_combine
= radeon_color_combine
[unit
][RADEON_REPLACE
];
544 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_REPLACE
];
547 color_combine
= radeon_color_combine
[unit
][RADEON_REPLACE
];
548 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
559 color_combine
= radeon_color_combine
[unit
][RADEON_MODULATE
];
560 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_MODULATE
];
563 color_combine
= radeon_color_combine
[unit
][RADEON_MODULATE
];
564 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
575 color_combine
= radeon_color_combine
[unit
][RADEON_DECAL
];
576 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
579 color_combine
= radeon_color_combine
[unit
][RADEON_DISABLE
];
580 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
591 color_combine
= radeon_color_combine
[unit
][RADEON_BLEND
];
592 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_MODULATE
];
595 color_combine
= radeon_color_combine
[unit
][RADEON_BLEND
];
596 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_BLEND
];
607 if ( rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXCBLEND
] != color_combine
||
608 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXABLEND
] != alpha_combine
) {
609 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
610 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXCBLEND
] = color_combine
;
611 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXABLEND
] = alpha_combine
;
616 #define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
617 RADEON_MIN_FILTER_MASK | \
618 RADEON_MAG_FILTER_MASK | \
619 RADEON_MAX_ANISO_MASK | \
620 RADEON_CLAMP_S_MASK | \
623 #define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \
624 RADEON_TXFORMAT_HEIGHT_MASK | \
625 RADEON_TXFORMAT_FORMAT_MASK | \
626 RADEON_TXFORMAT_ALPHA_IN_MAP)
630 void radeonUpdateTextureState( GLcontext
*ctx
)
632 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
633 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[0];
635 if ( texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) ) {
636 struct gl_texture_object
*tObj
= texUnit
->_Current
;
637 radeonTexObjPtr t
= (radeonTexObjPtr
) tObj
->DriverData
;
639 /* Upload teximages (not pipelined)
641 if ( t
->dirty_images
) {
642 RADEON_FIREVERTICES( rmesa
);
643 radeonSetTexImages( rmesa
, tObj
);
646 /* Update state if this is a different texture object to last
649 if ( rmesa
->state
.texture
.unit
[0].texobj
!= t
) {
650 rmesa
->state
.texture
.unit
[0].texobj
= t
;
651 t
->dirty_state
|= 1<<0;
652 move_to_head( &rmesa
->texture
.objects
[0], t
);
655 if (t
->dirty_state
) {
656 GLuint
*cmd
= RADEON_DB_STATE( tex
[0] );
658 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
659 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
660 cmd
[TEX_PP_TXFILTER
] |= t
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
661 cmd
[TEX_PP_TXFORMAT
] |= t
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
662 cmd
[TEX_PP_TXOFFSET
] = t
->pp_txoffset
;
663 cmd
[TEX_PP_BORDER_COLOR
] = t
->pp_border_color
;
665 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tex
[0] );
671 if (!(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & RADEON_TEX_0_ENABLE
)) {
672 RADEON_STATECHANGE( rmesa
, ctx
);
673 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= (RADEON_TEX_0_ENABLE
|
674 RADEON_TEX_BLEND_0_ENABLE
);
676 RADEON_STATECHANGE( rmesa
, tcl
);
677 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_ST0
;
680 radeonUpdateTextureEnv( ctx
, 0 );
682 else if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (RADEON_TEX_0_ENABLE
<<0)) {
683 /* Texture unit disabled */
684 rmesa
->state
.texture
.unit
[0].texobj
= 0;
685 RADEON_STATECHANGE( rmesa
, ctx
);
686 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &=
687 ~((RADEON_TEX_0_ENABLE
| RADEON_TEX_BLEND_0_ENABLE
) << 0);
689 RADEON_STATECHANGE( rmesa
, tcl
);
690 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] &= ~(RADEON_TCL_VTX_ST0
|
698 * \brief Choose texture format.
700 * \param ctx GL context.
701 * \param internalFormat texture internal format.
702 * \param format pixel format. Not used.
703 * \param type pixel data type. Not used.
705 * \return pointer to chosen texture format.
707 * Returns a pointer to one of the Mesa texture formats which is supported by
708 * Radeon and matches the internal format.
710 static const struct gl_texture_format
*
711 radeonChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
712 GLenum format
, GLenum type
)
714 switch ( internalFormat
) {
717 return &_mesa_texformat_rgba8888
;
721 return &_mesa_texformat_rgb565
;
725 return &_mesa_texformat_i8
;
728 _mesa_problem(ctx
, "unexpected texture format in radeonChoosTexFormat");
734 * \brief Allocate a Radeon texture object.
736 * \param texObj texture object.
738 * \return pointer to the device specific texture object on success, or NULL on failure.
740 * Allocates and initializes a radeon_tex_obj structure to connect it to the
741 * driver private data pointer in \p texObj.
743 static radeonTexObjPtr
radeonAllocTexObj( struct gl_texture_object
*texObj
)
747 t
= CALLOC_STRUCT( radeon_tex_obj
);
752 texObj
->DriverData
= t
;
753 make_empty_list( t
);
754 t
->dirty_images
= ~0;
760 * \brief Load a texture image.
762 * \param ctx GL context.
763 * \param texObj texture object
764 * \param target target texture.
765 * \param level level of detail number.
766 * \param internalFormat internal format.
767 * \param width texture image width.
768 * \param height texture image height.
769 * \param border border width.
770 * \param format pixel format.
771 * \param type pixel data type.
772 * \param pixels image data.
773 * \param packing passed to _mesa_store_teximage2d() unchanged.
774 * \param texImage passed to _mesa_store_teximage2d() unchanged.
776 * If there is a device specific texture object associated with the given
777 * texture object then swaps that texture out. Calls _mesa_store_teximage2d()
778 * with all other parameters unchanged.
780 static void radeonTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
781 GLint internalFormat
,
782 GLint width
, GLint height
, GLint border
,
783 GLenum format
, GLenum type
, const GLvoid
*pixels
,
784 const struct gl_pixelstore_attrib
*packing
,
785 struct gl_texture_object
*texObj
,
786 struct gl_texture_image
*texImage
)
788 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
789 radeonTexObjPtr t
= (radeonTexObjPtr
)texObj
->DriverData
;
792 radeonSwapOutTexObj( rmesa
, t
);
794 /* Note, this will call radeonChooseTextureFormat */
795 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
796 width
, height
, border
, format
, type
, pixels
,
797 &ctx
->Unpack
, texObj
, texImage
);
801 * \brief Set texture environment parameters.
803 * \param ctx GL context.
804 * \param target texture environment.
805 * \param pname texture parameter. Accepted value is GL_TEXTURE_ENV_COLOR.
806 * \param param parameter value.
808 * Updates the current unit's RADEON_TEX_PP_TFACTOR register and informs of the
811 static void radeonTexEnv( GLcontext
*ctx
, GLenum target
,
812 GLenum pname
, const GLfloat
*param
)
814 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
815 GLuint unit
= ctx
->Texture
.CurrentUnit
;
816 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
819 case GL_TEXTURE_ENV_COLOR
: {
822 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
823 envColor
= radeonPackColor( 4, c
[0], c
[1], c
[2], c
[3] );
824 if ( rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TFACTOR
] != envColor
) {
825 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
826 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TFACTOR
] = envColor
;
837 * \brief Set texture parameter.
839 * \param ctx GL context.
840 * \param target target texture.
841 * \param texObj texture object.
842 * \param pname texture parameter.
843 * \param params parameter value.
845 * Allocates the device specific texture object data if it doesn't exist
848 * Updates the texture object radeon_tex_obj::pp_txfilter register and marks
849 * the texture state (radeon_tex_obj::dirty_state) as dirty.
851 static void radeonTexParameter( GLcontext
*ctx
, GLenum target
,
852 struct gl_texture_object
*texObj
,
853 GLenum pname
, const GLfloat
*params
)
855 radeonTexObjPtr t
= (radeonTexObjPtr
) texObj
->DriverData
;
858 t
= radeonAllocTexObj( texObj
);
861 case GL_TEXTURE_MIN_FILTER
:
862 t
->pp_txfilter
&= ~RADEON_MIN_FILTER_MASK
;
863 switch ( texObj
->MinFilter
) {
865 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST
;
868 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR
;
870 case GL_NEAREST_MIPMAP_NEAREST
:
871 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST
;
873 case GL_NEAREST_MIPMAP_LINEAR
:
874 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST
;
876 case GL_LINEAR_MIPMAP_NEAREST
:
877 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR
;
879 case GL_LINEAR_MIPMAP_LINEAR
:
880 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR
;
885 case GL_TEXTURE_MAG_FILTER
:
886 t
->pp_txfilter
&= ~RADEON_MAG_FILTER_MASK
;
887 switch ( texObj
->MagFilter
) {
889 t
->pp_txfilter
|= RADEON_MAG_FILTER_NEAREST
;
892 t
->pp_txfilter
|= RADEON_MAG_FILTER_LINEAR
;
897 case GL_TEXTURE_WRAP_S
:
898 t
->pp_txfilter
&= ~RADEON_CLAMP_S_MASK
;
899 switch ( texObj
->WrapS
) {
901 t
->pp_txfilter
|= RADEON_CLAMP_S_WRAP
;
903 case GL_CLAMP_TO_EDGE
:
904 t
->pp_txfilter
|= RADEON_CLAMP_S_CLAMP_LAST
;
909 case GL_TEXTURE_WRAP_T
:
910 t
->pp_txfilter
&= ~RADEON_CLAMP_T_MASK
;
911 switch ( texObj
->WrapT
) {
913 t
->pp_txfilter
|= RADEON_CLAMP_T_WRAP
;
915 case GL_CLAMP_TO_EDGE
:
916 t
->pp_txfilter
|= RADEON_CLAMP_T_CLAMP_LAST
;
925 /* Mark this texobj as dirty (one bit per tex unit)
927 t
->dirty_state
= TEX_ALL
;
931 * \brief Bind texture.
933 * \param ctx GL context.
934 * \param target not used.
935 * \param texObj texture object.
937 * Allocates the device specific texture data if it doesn't exist already.
939 static void radeonBindTexture( GLcontext
*ctx
, GLenum target
,
940 struct gl_texture_object
*texObj
)
942 if ( !texObj
->DriverData
)
943 radeonAllocTexObj( texObj
);
947 * \brief Delete texture.
949 * \param ctx GL context.
950 * \param texObj texture object.
952 * Fires any outstanding vertices and destroy the device specific texture
955 static void radeonDeleteTexture( GLcontext
*ctx
,
956 struct gl_texture_object
*texObj
)
958 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
959 radeonTexObjPtr t
= (radeonTexObjPtr
) texObj
->DriverData
;
963 RADEON_FIREVERTICES( rmesa
);
964 radeonDestroyTexObj( rmesa
, t
);
969 * \brief Initialize context texture object data.
971 * \param ctx GL context.
973 * Called by radeonInitTextureFuncs() to setup the context initial texture
976 static void radeonInitTextureObjects( GLcontext
*ctx
)
978 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
979 struct gl_texture_object
*texObj
;
980 GLuint tmp
= ctx
->Texture
.CurrentUnit
;
982 ctx
->Texture
.CurrentUnit
= 0;
984 texObj
= ctx
->Texture
.Unit
[0].Current2D
;
985 radeonBindTexture( ctx
, GL_TEXTURE_2D
, texObj
);
986 move_to_tail( &rmesa
->texture
.swapped
,
987 (radeonTexObjPtr
)texObj
->DriverData
);
990 ctx
->Texture
.CurrentUnit
= tmp
;
994 * \brief Setup the GL context driver callbacks.
996 * \param ctx GL context.
998 * \sa Called by radeonCreateContext().
1000 void radeonInitTextureFuncs( GLcontext
*ctx
)
1002 ctx
->Driver
.ChooseTextureFormat
= radeonChooseTextureFormat
;
1003 ctx
->Driver
.TexImage2D
= radeonTexImage2D
;
1005 ctx
->Driver
.BindTexture
= radeonBindTexture
;
1006 ctx
->Driver
.CreateTexture
= NULL
; /* FIXME: Is this used??? */
1007 ctx
->Driver
.DeleteTexture
= radeonDeleteTexture
;
1008 ctx
->Driver
.PrioritizeTexture
= NULL
;
1009 ctx
->Driver
.ActiveTexture
= NULL
;
1010 ctx
->Driver
.UpdateTexturePalette
= NULL
;
1012 ctx
->Driver
.TexEnv
= radeonTexEnv
;
1013 ctx
->Driver
.TexParameter
= radeonTexParameter
;
1015 radeonInitTextureObjects( ctx
);