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 rmesa
->hw
.tex
[0].dirty
= GL_FALSE
;
82 remove_from_list( t
);
88 * \brief Keep track of swapped out texture objects.
90 * \param rmesa Radeon context.
91 * \param t Radeon texture object.
93 * Frees the memory associated with the texture, marks all mipmap images in
94 * the texture as dirty and add it to the radeon_texture::swapped list.
96 static void radeonSwapOutTexObj( radeonContextPtr rmesa
, radeonTexObjPtr t
)
99 mmFreeMem( t
->memBlock
);
103 t
->dirty_images
= ~0;
104 move_to_tail( &rmesa
->texture
.swapped
, t
);
109 * Texture space has been invalidated.
111 * \param rmesa Radeon context.
112 * \param heap texture heap number.
114 * Swaps out every texture in the specified heap.
116 void radeonAgeTextures( radeonContextPtr rmesa
, int heap
)
118 radeonTexObjPtr t
, tmp
;
120 foreach_s ( t
, tmp
, &rmesa
->texture
.objects
[heap
] )
121 radeonSwapOutTexObj( rmesa
, t
);
125 /***************************************************************/
126 /** \name Texture image conversions
131 * \brief Upload texture image.
133 * \param rmesa Radeon context.
134 * \param t Radeon texture object.
135 * \param level level of the image to take the sub-image.
136 * \param x sub-image abscissa.
137 * \param y sub-image ordinate.
138 * \param width sub-image width.
139 * \param height sub-image height.
141 * Fills in a drmRadeonTexture and drmRadeonTexImage structures and uploads the
142 * texture via the DRM_RADEON_TEXTURE ioctl, aborting in case of failure.
144 static void radeonUploadSubImage( radeonContextPtr rmesa
,
145 radeonTexObjPtr t
, GLint level
,
146 GLint x
, GLint y
, GLint width
, GLint height
)
148 struct gl_texture_image
*texImage
;
150 drmRadeonTexture tex
;
151 drmRadeonTexImage tmp
;
153 level
+= t
->firstLevel
;
154 texImage
= t
->tObj
->Image
[0][level
];
156 if ( !texImage
|| !texImage
->Data
)
159 t
->image
[level
].data
= texImage
->Data
;
161 tex
.offset
= t
->bufAddr
;
162 tex
.pitch
= (t
->image
[0].width
* texImage
->TexFormat
->TexelBytes
) / 64;
163 tex
.format
= t
->pp_txformat
& RADEON_TXFORMAT_FORMAT_MASK
;
164 tex
.width
= texImage
->Width
;
165 tex
.height
= texImage
->Height
;
168 memcpy( &tmp
, &t
->image
[level
], sizeof(drmRadeonTexImage
) );
171 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_TEXTURE
,
172 &tex
, sizeof(drmRadeonTexture
) );
173 } while ( ret
&& errno
== EAGAIN
);
176 UNLOCK_HARDWARE( rmesa
);
177 fprintf( stderr
, "DRM_RADEON_TEXTURE: return = %d\n", ret
);
183 * \brief Upload texture images.
185 * This might require removing our own and/or other client's texture objects to
186 * make room for these images.
188 * \param rmesa Radeon context.
189 * \param tObj texture object to upload.
191 * Sets the matching hardware texture format. Calculates which mipmap levels to
192 * send, depending of the base image size, GL_TEXTURE_MIN_LOD,
193 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL and the
194 * Radeon offset rules. Kicks out textures until the requested texture fits,
195 * sets the texture hardware state and, while holding the hardware lock,
196 * uploads any images that are new.
198 static void radeonSetTexImages( radeonContextPtr rmesa
,
199 struct gl_texture_object
*tObj
)
201 radeonTexObjPtr t
= (radeonTexObjPtr
)tObj
->DriverData
;
202 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
204 GLint texelsPerDword
= 0, blitWidth
= 0, blitPitch
= 0;
205 GLint x
, y
, width
, height
;
207 GLint firstLevel
, lastLevel
, numLevels
;
208 GLint log2Width
, log2Height
;
211 /* This code cannot be reached once we have lost focus
213 assert(rmesa
->radeonScreen
->buffers
);
215 /* Set the hardware texture format
217 switch (baseImage
->TexFormat
->MesaFormat
) {
219 txformat
= RADEON_TXFORMAT_I8
;
223 case MESA_FORMAT_RGBA8888
:
224 txformat
= RADEON_TXFORMAT_RGBA8888
| RADEON_TXFORMAT_ALPHA_IN_MAP
;
228 case MESA_FORMAT_RGB565
:
229 txformat
= RADEON_TXFORMAT_RGB565
;
234 _mesa_problem(NULL
, "unexpected texture format in radeonTexImage2D");
238 t
->pp_txformat
&= ~(RADEON_TXFORMAT_FORMAT_MASK
|
239 RADEON_TXFORMAT_ALPHA_IN_MAP
);
240 t
->pp_txformat
|= txformat
;
243 /* Select the larger of the two widths for our global texture image
244 * coordinate space. As the Radeon has very strict offset rules, we
245 * can't upload mipmaps directly and have to reference their location
246 * from the aligned start of the whole image.
248 blitWidth
= MAX2( baseImage
->Width
, blitPitch
);
250 /* Calculate mipmap offsets and dimensions.
256 /* Compute which mipmap levels we really want to send to the hardware.
257 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
258 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
259 * Yes, this looks overly complicated, but it's all needed.
261 firstLevel
= tObj
->BaseLevel
+ (GLint
) (tObj
->MinLod
+ 0.5);
262 firstLevel
= MAX2(firstLevel
, tObj
->BaseLevel
);
263 lastLevel
= tObj
->BaseLevel
+ (GLint
) (tObj
->MaxLod
+ 0.5);
264 lastLevel
= MAX2(lastLevel
, tObj
->BaseLevel
);
265 lastLevel
= MIN2(lastLevel
, tObj
->BaseLevel
+ baseImage
->MaxLog2
);
266 lastLevel
= MIN2(lastLevel
, tObj
->MaxLevel
);
267 lastLevel
= MAX2(firstLevel
, lastLevel
); /* need at least one level */
269 /* save these values */
270 t
->firstLevel
= firstLevel
;
271 t
->lastLevel
= lastLevel
;
273 numLevels
= lastLevel
- firstLevel
+ 1;
275 log2Width
= tObj
->Image
[0][firstLevel
]->WidthLog2
;
276 log2Height
= tObj
->Image
[0][firstLevel
]->HeightLog2
;
278 for ( i
= 0 ; i
< numLevels
; i
++ ) {
279 const struct gl_texture_image
*texImage
= tObj
->Image
[0][i
+ firstLevel
];
283 width
= texImage
->Width
;
284 height
= texImage
->Height
;
286 /* Texture images have a minimum pitch of 32 bytes (half of the
287 * 64-byte minimum pitch for blits). For images that have a
288 * width smaller than this, we must pad each texture image
289 * scanline out to this amount.
291 if ( width
< blitPitch
/ 2 ) {
292 width
= blitPitch
/ 2;
295 totalSize
+= width
* height
* baseImage
->TexFormat
->TexelBytes
;
296 ASSERT( (totalSize
& 31) == 0 );
298 while ( width
< blitWidth
&& height
> 1 ) {
303 ASSERT(i
< RADEON_MAX_TEXTURE_LEVELS
);
306 t
->image
[i
].width
= width
;
307 t
->image
[i
].height
= height
;
309 /* While blits must have a pitch of at least 64 bytes, mipmaps
310 * must be aligned on a 32-byte boundary (just like each texture
313 if ( width
>= blitWidth
) {
317 if ( x
>= blitWidth
) {
324 /* Align the total size of texture memory block.
326 t
->totalSize
= (totalSize
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
330 t
->pp_txfilter
&= ~RADEON_MAX_MIP_LEVEL_MASK
;
331 t
->pp_txfilter
|= (numLevels
- 1) << RADEON_MAX_MIP_LEVEL_SHIFT
;
333 t
->pp_txformat
&= ~(RADEON_TXFORMAT_WIDTH_MASK
|
334 RADEON_TXFORMAT_HEIGHT_MASK
);
335 t
->pp_txformat
|= ((log2Width
<< RADEON_TXFORMAT_WIDTH_SHIFT
) |
336 (log2Height
<< RADEON_TXFORMAT_HEIGHT_SHIFT
));
337 t
->dirty_state
= TEX_ALL
;
339 /* Update the local texture LRU.
341 move_to_head( &rmesa
->texture
.objects
[0], t
);
343 LOCK_HARDWARE( rmesa
);
345 /* Kick out textures until the requested texture fits */
346 while ( !t
->memBlock
) {
347 t
->memBlock
= mmAllocMem( rmesa
->texture
.heap
[0], t
->totalSize
, 12, 0);
350 radeonSwapOutTexObj( rmesa
, rmesa
->texture
.objects
[0].prev
);
354 /* Set the base offset of the texture image */
355 t
->bufAddr
= rmesa
->radeonScreen
->texOffset
[0] + t
->memBlock
->ofs
;
356 t
->pp_txoffset
= t
->bufAddr
;
358 /* Upload any images that are new
360 for ( i
= 0 ; i
< numLevels
; i
++ ) {
361 if ( t
->dirty_images
& (1 << i
) ) {
362 radeonUploadSubImage( rmesa
, t
, i
, 0, 0,
363 t
->image
[i
].width
, t
->image
[i
].height
);
367 rmesa
->texture
.age
[0] = ++rmesa
->sarea
->texAge
[0];
368 UNLOCK_HARDWARE( rmesa
);
375 /******************************************************************/
376 /** \name Texture combine functions
381 RADEON_DISABLE
= 0, /**< \brief disabled */
382 RADEON_REPLACE
= 1, /**< \brief replace function */
383 RADEON_MODULATE
= 2, /**< \brief modulate function */
384 RADEON_DECAL
= 3, /**< \brief decal function */
385 RADEON_BLEND
= 4, /**< \brief blend function */
386 RADEON_MAX_COMBFUNC
= 5 /**< \brief max number of combine functions */
391 * \brief Color combine function hardware state table.
393 static GLuint radeon_color_combine
[][RADEON_MAX_COMBFUNC
] =
398 /* Disable combiner stage
400 (RADEON_COLOR_ARG_A_ZERO
|
401 RADEON_COLOR_ARG_B_ZERO
|
402 RADEON_COLOR_ARG_C_CURRENT_COLOR
|
403 RADEON_BLEND_CTL_ADD
|
407 /* GL_REPLACE = 0x00802800
409 (RADEON_COLOR_ARG_A_ZERO
|
410 RADEON_COLOR_ARG_B_ZERO
|
411 RADEON_COLOR_ARG_C_T0_COLOR
|
412 RADEON_BLEND_CTL_ADD
|
416 /* GL_MODULATE = 0x00800142
418 (RADEON_COLOR_ARG_A_CURRENT_COLOR
|
419 RADEON_COLOR_ARG_B_T0_COLOR
|
420 RADEON_COLOR_ARG_C_ZERO
|
421 RADEON_BLEND_CTL_ADD
|
425 /* GL_DECAL = 0x008c2d42
427 (RADEON_COLOR_ARG_A_CURRENT_COLOR
|
428 RADEON_COLOR_ARG_B_T0_COLOR
|
429 RADEON_COLOR_ARG_C_T0_ALPHA
|
430 RADEON_BLEND_CTL_BLEND
|
434 /* GL_BLEND = 0x008c2902
436 (RADEON_COLOR_ARG_A_CURRENT_COLOR
|
437 RADEON_COLOR_ARG_B_TFACTOR_COLOR
|
438 RADEON_COLOR_ARG_C_T0_COLOR
|
439 RADEON_BLEND_CTL_BLEND
|
447 * \brief Alpha combine function hardware state table.
449 static GLuint radeon_alpha_combine
[][RADEON_MAX_COMBFUNC
] =
454 /* Disable combiner stage
456 (RADEON_ALPHA_ARG_A_ZERO
|
457 RADEON_ALPHA_ARG_B_ZERO
|
458 RADEON_ALPHA_ARG_C_CURRENT_ALPHA
|
459 RADEON_BLEND_CTL_ADD
|
463 /* GL_REPLACE = 0x00800500
465 (RADEON_ALPHA_ARG_A_ZERO
|
466 RADEON_ALPHA_ARG_B_ZERO
|
467 RADEON_ALPHA_ARG_C_T0_ALPHA
|
468 RADEON_BLEND_CTL_ADD
|
472 /* GL_MODULATE = 0x00800051
474 (RADEON_ALPHA_ARG_A_CURRENT_ALPHA
|
475 RADEON_ALPHA_ARG_B_T0_ALPHA
|
476 RADEON_ALPHA_ARG_C_ZERO
|
477 RADEON_BLEND_CTL_ADD
|
481 /* GL_DECAL = 0x00800100
483 (RADEON_ALPHA_ARG_A_ZERO
|
484 RADEON_ALPHA_ARG_B_ZERO
|
485 RADEON_ALPHA_ARG_C_CURRENT_ALPHA
|
486 RADEON_BLEND_CTL_ADD
|
490 /* GL_BLEND = 0x00800051
492 (RADEON_ALPHA_ARG_A_CURRENT_ALPHA
|
493 RADEON_ALPHA_ARG_B_TFACTOR_ALPHA
|
494 RADEON_ALPHA_ARG_C_T0_ALPHA
|
495 RADEON_BLEND_CTL_BLEND
|
506 /******************************************************************/
507 /** \name Texture unit state management
512 * \brief Update the texture environment.
514 * \param ctx GL context
515 * \param unit texture unit to update.
517 * Sets the state of the RADEON_TEX_PP_TXCBLEND and RADEON_TEX_PP_TXABLEND
518 * registers using the ::radeon_color_combine and ::radeon_alpha_combine tables,
519 * and informs of the state change.
521 static void radeonUpdateTextureEnv( GLcontext
*ctx
, int unit
)
523 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
524 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
525 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
526 const GLenum format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
527 GLuint color_combine
= radeon_color_combine
[unit
][RADEON_DISABLE
];
528 GLuint alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
531 /* Set the texture environment state. Isn't this nice and clean?
532 * The Radeon will automagically set the texture alpha to 0xff when
533 * the texture format does not include an alpha component. This
534 * reduces the amount of special-casing we have to do, alpha-only
535 * textures being a notable exception.
537 switch ( texUnit
->EnvMode
) {
542 color_combine
= radeon_color_combine
[unit
][RADEON_REPLACE
];
543 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_REPLACE
];
546 color_combine
= radeon_color_combine
[unit
][RADEON_REPLACE
];
547 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
558 color_combine
= radeon_color_combine
[unit
][RADEON_MODULATE
];
559 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_MODULATE
];
562 color_combine
= radeon_color_combine
[unit
][RADEON_MODULATE
];
563 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
574 color_combine
= radeon_color_combine
[unit
][RADEON_DECAL
];
575 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
578 color_combine
= radeon_color_combine
[unit
][RADEON_DISABLE
];
579 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_DISABLE
];
590 color_combine
= radeon_color_combine
[unit
][RADEON_BLEND
];
591 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_MODULATE
];
594 color_combine
= radeon_color_combine
[unit
][RADEON_BLEND
];
595 alpha_combine
= radeon_alpha_combine
[unit
][RADEON_BLEND
];
606 if ( rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXCBLEND
] != color_combine
||
607 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXABLEND
] != alpha_combine
) {
608 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
609 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXCBLEND
] = color_combine
;
610 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXABLEND
] = alpha_combine
;
615 #define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
616 RADEON_MIN_FILTER_MASK | \
617 RADEON_MAG_FILTER_MASK | \
618 RADEON_MAX_ANISO_MASK | \
619 RADEON_CLAMP_S_MASK | \
622 #define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \
623 RADEON_TXFORMAT_HEIGHT_MASK | \
624 RADEON_TXFORMAT_FORMAT_MASK | \
625 RADEON_TXFORMAT_ALPHA_IN_MAP)
629 void radeonUpdateTextureState( GLcontext
*ctx
)
631 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
632 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[0];
634 if ( texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) ) {
635 struct gl_texture_object
*tObj
= texUnit
->_Current
;
636 radeonTexObjPtr t
= (radeonTexObjPtr
) tObj
->DriverData
;
638 /* Upload teximages (not pipelined)
640 if ( t
->dirty_images
) {
641 RADEON_FIREVERTICES( rmesa
);
642 radeonSetTexImages( rmesa
, tObj
);
645 /* Update state if this is a different texture object to last
648 if ( rmesa
->state
.texture
.unit
[0].texobj
!= t
) {
649 rmesa
->state
.texture
.unit
[0].texobj
= t
;
650 t
->dirty_state
|= 1<<0;
651 move_to_head( &rmesa
->texture
.objects
[0], t
);
654 if (t
->dirty_state
) {
655 GLuint
*cmd
= RADEON_DB_STATE( tex
[0] );
657 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
658 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
659 cmd
[TEX_PP_TXFILTER
] |= t
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
660 cmd
[TEX_PP_TXFORMAT
] |= t
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
661 cmd
[TEX_PP_TXOFFSET
] = t
->pp_txoffset
;
662 cmd
[TEX_PP_BORDER_COLOR
] = t
->pp_border_color
;
664 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tex
[0] );
670 if (!(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & RADEON_TEX_0_ENABLE
)) {
671 RADEON_STATECHANGE( rmesa
, ctx
);
672 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= (RADEON_TEX_0_ENABLE
|
673 RADEON_TEX_BLEND_0_ENABLE
);
675 RADEON_STATECHANGE( rmesa
, tcl
);
676 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_ST0
;
679 radeonUpdateTextureEnv( ctx
, 0 );
681 else if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (RADEON_TEX_0_ENABLE
<<0)) {
682 /* Texture unit disabled */
683 rmesa
->state
.texture
.unit
[0].texobj
= 0;
684 RADEON_STATECHANGE( rmesa
, ctx
);
685 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &=
686 ~((RADEON_TEX_0_ENABLE
| RADEON_TEX_BLEND_0_ENABLE
) << 0);
688 RADEON_STATECHANGE( rmesa
, tcl
);
689 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] &= ~(RADEON_TCL_VTX_ST0
|
697 * \brief Choose texture format.
699 * \param ctx GL context.
700 * \param internalFormat texture internal format.
701 * \param format pixel format. Not used.
702 * \param type pixel data type. Not used.
704 * \return pointer to chosen texture format.
706 * Returns a pointer to one of the Mesa texture formats which is supported by
707 * Radeon and matches the internal format.
709 static const struct gl_texture_format
*
710 radeonChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
711 GLenum format
, GLenum type
)
713 switch ( internalFormat
) {
716 return &_mesa_texformat_rgba8888
;
720 return &_mesa_texformat_rgb565
;
724 return &_mesa_texformat_i8
;
727 _mesa_problem(ctx
, "unexpected texture format in radeonChoosTexFormat");
733 * \brief Allocate a Radeon texture object.
735 * \param texObj texture object.
737 * \return pointer to the device specific texture object on success, or NULL on failure.
739 * Allocates and initializes a radeon_tex_obj structure to connect it to the
740 * driver private data pointer in \p texObj.
742 static radeonTexObjPtr
radeonAllocTexObj( struct gl_texture_object
*texObj
)
746 t
= CALLOC_STRUCT( radeon_tex_obj
);
751 texObj
->DriverData
= t
;
752 make_empty_list( t
);
753 t
->dirty_images
= ~0;
759 * \brief Load a texture image.
761 * \param ctx GL context.
762 * \param texObj texture object
763 * \param target target texture.
764 * \param level level of detail number.
765 * \param internalFormat internal format.
766 * \param width texture image width.
767 * \param height texture image height.
768 * \param border border width.
769 * \param format pixel format.
770 * \param type pixel data type.
771 * \param pixels image data.
772 * \param packing passed to _mesa_store_teximage2d() unchanged.
773 * \param texImage passed to _mesa_store_teximage2d() unchanged.
775 * If there is a device specific texture object associated with the given
776 * texture object then swaps that texture out. Calls _mesa_store_teximage2d()
777 * with all other parameters unchanged.
779 static void radeonTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
780 GLint internalFormat
,
781 GLint width
, GLint height
, GLint border
,
782 GLenum format
, GLenum type
, const GLvoid
*pixels
,
783 const struct gl_pixelstore_attrib
*packing
,
784 struct gl_texture_object
*texObj
,
785 struct gl_texture_image
*texImage
)
787 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
788 radeonTexObjPtr t
= (radeonTexObjPtr
)texObj
->DriverData
;
791 radeonSwapOutTexObj( rmesa
, t
);
793 /* Note, this will call radeonChooseTextureFormat */
794 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
795 width
, height
, border
, format
, type
, pixels
,
796 &ctx
->Unpack
, texObj
, texImage
);
800 * \brief Set texture environment parameters.
802 * \param ctx GL context.
803 * \param target texture environment.
804 * \param pname texture parameter. Accepted value is GL_TEXTURE_ENV_COLOR.
805 * \param param parameter value.
807 * Updates the current unit's RADEON_TEX_PP_TFACTOR register and informs of the
810 static void radeonTexEnv( GLcontext
*ctx
, GLenum target
,
811 GLenum pname
, const GLfloat
*param
)
813 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
814 GLuint unit
= ctx
->Texture
.CurrentUnit
;
815 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
818 case GL_TEXTURE_ENV_COLOR
: {
821 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
822 envColor
= radeonPackColor( 4, c
[0], c
[1], c
[2], c
[3] );
823 if ( rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TFACTOR
] != envColor
) {
824 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
825 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TFACTOR
] = envColor
;
836 * \brief Set texture parameter.
838 * \param ctx GL context.
839 * \param target target texture.
840 * \param texObj texture object.
841 * \param pname texture parameter.
842 * \param params parameter value.
844 * Allocates the device specific texture object data if it doesn't exist
847 * Updates the texture object radeon_tex_obj::pp_txfilter register and marks
848 * the texture state (radeon_tex_obj::dirty_state) as dirty.
850 static void radeonTexParameter( GLcontext
*ctx
, GLenum target
,
851 struct gl_texture_object
*texObj
,
852 GLenum pname
, const GLfloat
*params
)
854 radeonTexObjPtr t
= (radeonTexObjPtr
) texObj
->DriverData
;
857 t
= radeonAllocTexObj( texObj
);
860 case GL_TEXTURE_MIN_FILTER
:
861 t
->pp_txfilter
&= ~RADEON_MIN_FILTER_MASK
;
862 switch ( texObj
->MinFilter
) {
864 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST
;
867 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR
;
869 case GL_NEAREST_MIPMAP_NEAREST
:
870 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST
;
872 case GL_NEAREST_MIPMAP_LINEAR
:
873 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST
;
875 case GL_LINEAR_MIPMAP_NEAREST
:
876 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR
;
878 case GL_LINEAR_MIPMAP_LINEAR
:
879 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR
;
884 case GL_TEXTURE_MAG_FILTER
:
885 t
->pp_txfilter
&= ~RADEON_MAG_FILTER_MASK
;
886 switch ( texObj
->MagFilter
) {
888 t
->pp_txfilter
|= RADEON_MAG_FILTER_NEAREST
;
891 t
->pp_txfilter
|= RADEON_MAG_FILTER_LINEAR
;
896 case GL_TEXTURE_WRAP_S
:
897 t
->pp_txfilter
&= ~RADEON_CLAMP_S_MASK
;
898 switch ( texObj
->WrapS
) {
900 t
->pp_txfilter
|= RADEON_CLAMP_S_WRAP
;
902 case GL_CLAMP_TO_EDGE
:
903 t
->pp_txfilter
|= RADEON_CLAMP_S_CLAMP_LAST
;
908 case GL_TEXTURE_WRAP_T
:
909 t
->pp_txfilter
&= ~RADEON_CLAMP_T_MASK
;
910 switch ( texObj
->WrapT
) {
912 t
->pp_txfilter
|= RADEON_CLAMP_T_WRAP
;
914 case GL_CLAMP_TO_EDGE
:
915 t
->pp_txfilter
|= RADEON_CLAMP_T_CLAMP_LAST
;
924 /* Mark this texobj as dirty (one bit per tex unit)
926 t
->dirty_state
= TEX_ALL
;
930 * \brief Bind texture.
932 * \param ctx GL context.
933 * \param target not used.
934 * \param texObj texture object.
936 * Allocates the device specific texture data if it doesn't exist already.
938 static void radeonBindTexture( GLcontext
*ctx
, GLenum target
,
939 struct gl_texture_object
*texObj
)
941 if ( !texObj
->DriverData
)
942 radeonAllocTexObj( texObj
);
946 * \brief Delete texture.
948 * \param ctx GL context.
949 * \param texObj texture object.
951 * Fires any outstanding vertices and destroy the device specific texture
954 static void radeonDeleteTexture( GLcontext
*ctx
,
955 struct gl_texture_object
*texObj
)
957 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
958 radeonTexObjPtr t
= (radeonTexObjPtr
) texObj
->DriverData
;
962 RADEON_FIREVERTICES( rmesa
);
963 radeonDestroyTexObj( rmesa
, t
);
968 * \brief Initialize context texture object data.
970 * \param ctx GL context.
972 * Called by radeonInitTextureFuncs() to setup the context initial texture
975 static void radeonInitTextureObjects( GLcontext
*ctx
)
977 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
978 struct gl_texture_object
*texObj
;
979 GLuint tmp
= ctx
->Texture
.CurrentUnit
;
981 ctx
->Texture
.CurrentUnit
= 0;
983 texObj
= ctx
->Texture
.Unit
[0].Current2D
;
984 radeonBindTexture( ctx
, GL_TEXTURE_2D
, texObj
);
985 move_to_tail( &rmesa
->texture
.swapped
,
986 (radeonTexObjPtr
)texObj
->DriverData
);
989 ctx
->Texture
.CurrentUnit
= tmp
;
993 * \brief Setup the GL context driver callbacks.
995 * \param ctx GL context.
997 * \sa Called by radeonCreateContext().
999 void radeonInitTextureFuncs( GLcontext
*ctx
)
1001 ctx
->Driver
.ChooseTextureFormat
= radeonChooseTextureFormat
;
1002 ctx
->Driver
.TexImage2D
= radeonTexImage2D
;
1004 ctx
->Driver
.BindTexture
= radeonBindTexture
;
1005 ctx
->Driver
.CreateTexture
= NULL
; /* FIXME: Is this used??? */
1006 ctx
->Driver
.DeleteTexture
= radeonDeleteTexture
;
1007 ctx
->Driver
.PrioritizeTexture
= NULL
;
1008 ctx
->Driver
.ActiveTexture
= NULL
;
1009 ctx
->Driver
.UpdateTexturePalette
= NULL
;
1011 ctx
->Driver
.TexEnv
= radeonTexEnv
;
1012 ctx
->Driver
.TexParameter
= radeonTexParameter
;
1014 radeonInitTextureObjects( ctx
);