2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
33 * \author Keith Whitwell <keith@tungstengraphics.com>
35 * \todo Enable R300 texture tiling code?
38 #include "main/glheader.h"
39 #include "main/imports.h"
40 #include "main/context.h"
41 #include "main/macros.h"
42 #include "main/texformat.h"
43 #include "main/teximage.h"
44 #include "main/texobj.h"
45 #include "main/enums.h"
46 #include "main/simple_list.h"
48 #include "r300_context.h"
49 #include "r300_state.h"
50 #include "r300_ioctl.h"
51 #include "radeon_mipmap_tree.h"
55 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5 \
56 || ((f) >= MESA_FORMAT_RGBA_FLOAT32 && \
57 (f) <= MESA_FORMAT_INTENSITY_FLOAT16)) \
60 #define _ASSIGN(entry, format) \
61 [ MESA_FORMAT_ ## entry ] = { format, 0, 1}
64 * Note that the _REV formats are the same as the non-REV formats. This is
65 * because the REV and non-REV formats are identical as a byte string, but
66 * differ when accessed as 16-bit or 32-bit words depending on the endianness of
67 * the host. Since the textures are transferred to the R300 as a byte string
68 * (i.e. without any byte-swapping), the R300 sees the REV and non-REV formats
69 * identically. -- paulus
72 static const struct tx_table
{
73 GLuint format
, filter
, flag
;
76 #ifdef MESA_LITTLE_ENDIAN
77 _ASSIGN(RGBA8888
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W8Z8Y8X8
)),
78 _ASSIGN(RGBA8888_REV
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, W8Z8Y8X8
)),
79 _ASSIGN(ARGB8888
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
)),
80 _ASSIGN(ARGB8888_REV
, R300_EASY_TX_FORMAT(W
, Z
, Y
, X
, W8Z8Y8X8
)),
82 _ASSIGN(RGBA8888
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, W8Z8Y8X8
)),
83 _ASSIGN(RGBA8888_REV
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W8Z8Y8X8
)),
84 _ASSIGN(ARGB8888
, R300_EASY_TX_FORMAT(W
, Z
, Y
, X
, W8Z8Y8X8
)),
85 _ASSIGN(ARGB8888_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
)),
87 _ASSIGN(RGB888
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, W8Z8Y8X8
)),
88 _ASSIGN(RGB565
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
)),
89 _ASSIGN(RGB565_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
)),
90 _ASSIGN(ARGB4444
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W4Z4Y4X4
)),
91 _ASSIGN(ARGB4444_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W4Z4Y4X4
)),
92 _ASSIGN(ARGB1555
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W1Z5Y5X5
)),
93 _ASSIGN(ARGB1555_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W1Z5Y5X5
)),
94 _ASSIGN(AL88
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, Y8X8
)),
95 _ASSIGN(AL88_REV
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, Y8X8
)),
96 _ASSIGN(RGB332
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z3Y3X2
)),
97 _ASSIGN(A8
, R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, X8
)),
98 _ASSIGN(L8
, R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X8
)),
99 _ASSIGN(I8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X8
)),
100 _ASSIGN(CI8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X8
)),
101 _ASSIGN(YCBCR
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, G8R8_G8B8
) | R300_TX_FORMAT_YUV_MODE
),
102 _ASSIGN(YCBCR_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, G8R8_G8B8
) | R300_TX_FORMAT_YUV_MODE
),
103 _ASSIGN(RGB_DXT1
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, DXT1
)),
104 _ASSIGN(RGBA_DXT1
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, DXT1
)),
105 _ASSIGN(RGBA_DXT3
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, DXT3
)),
106 _ASSIGN(RGBA_DXT5
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, DXT5
)),
107 _ASSIGN(RGBA_FLOAT32
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, FL_R32G32B32A32
)),
108 _ASSIGN(RGBA_FLOAT16
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, FL_R16G16B16A16
)),
109 _ASSIGN(RGB_FLOAT32
, 0xffffffff),
110 _ASSIGN(RGB_FLOAT16
, 0xffffffff),
111 _ASSIGN(ALPHA_FLOAT32
, R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, FL_I32
)),
112 _ASSIGN(ALPHA_FLOAT16
, R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, FL_I16
)),
113 _ASSIGN(LUMINANCE_FLOAT32
, R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, FL_I32
)),
114 _ASSIGN(LUMINANCE_FLOAT16
, R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, FL_I16
)),
115 _ASSIGN(LUMINANCE_ALPHA_FLOAT32
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, FL_I32A32
)),
116 _ASSIGN(LUMINANCE_ALPHA_FLOAT16
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, FL_I16A16
)),
117 _ASSIGN(INTENSITY_FLOAT32
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, FL_I32
)),
118 _ASSIGN(INTENSITY_FLOAT16
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, FL_I16
)),
119 _ASSIGN(Z16
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X16
)),
120 _ASSIGN(Z24_S8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X24_Y8
)),
121 _ASSIGN(S8_Z24
, R300_EASY_TX_FORMAT(Y
, Y
, Y
, Y
, X24_Y8
)),
122 _ASSIGN(Z32
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X32
)),
123 /* EXT_texture_sRGB */
124 _ASSIGN(SRGBA8
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W8Z8Y8X8
) | R300_TX_FORMAT_GAMMA
),
125 _ASSIGN(SLA8
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, Y8X8
) | R300_TX_FORMAT_GAMMA
),
126 _ASSIGN(SL8
, R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X8
) | R300_TX_FORMAT_GAMMA
),
132 void r300SetDepthTexMode(struct gl_texture_object
*tObj
)
134 static const GLuint formats
[3][3] = {
136 R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X16
),
137 R300_EASY_TX_FORMAT(X
, X
, X
, X
, X16
),
138 R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, X16
),
141 R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X24_Y8
),
142 R300_EASY_TX_FORMAT(X
, X
, X
, X
, X24_Y8
),
143 R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, X24_Y8
),
146 R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X32
),
147 R300_EASY_TX_FORMAT(X
, X
, X
, X
, X32
),
148 R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, X32
),
151 const GLuint
*format
;
157 t
= radeon_tex_obj(tObj
);
159 switch (tObj
->Image
[0][tObj
->BaseLevel
]->TexFormat
) {
160 case MESA_FORMAT_Z16
:
163 case MESA_FORMAT_Z24_S8
:
166 case MESA_FORMAT_Z32
:
170 /* Error...which should have already been caught by higher
177 switch (tObj
->DepthMode
) {
179 t
->pp_txformat
= format
[0];
182 t
->pp_txformat
= format
[1];
185 t
->pp_txformat
= format
[2];
188 /* Error...which should have already been caught by higher
198 * Compute the cached hardware register values for the given texture object.
200 * \param rmesa Context pointer
201 * \param t the r300 texture object
203 static void setup_hardware_state(r300ContextPtr rmesa
, radeonTexObj
*t
)
205 const struct gl_texture_image
*firstImage
;
206 int firstlevel
= t
->mt
? t
->mt
->firstLevel
: 0;
208 firstImage
= t
->base
.Image
[0][firstlevel
];
210 if (!t
->image_override
211 && VALID_FORMAT(firstImage
->TexFormat
)) {
212 if (firstImage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
213 r300SetDepthTexMode(&t
->base
);
215 t
->pp_txformat
= tx_table
[firstImage
->TexFormat
].format
;
218 t
->pp_txfilter
|= tx_table
[firstImage
->TexFormat
].filter
;
219 } else if (!t
->image_override
) {
220 _mesa_problem(NULL
, "unexpected texture format in %s",
225 if (t
->image_override
&& t
->bo
)
228 t
->pp_txsize
= (((firstImage
->Width
- 1) << R300_TX_WIDTHMASK_SHIFT
)
229 | ((firstImage
->Height
- 1) << R300_TX_HEIGHTMASK_SHIFT
)
230 | ((firstImage
->DepthLog2
) << R300_TX_DEPTHMASK_SHIFT
)
231 | ((t
->mt
->lastLevel
- t
->mt
->firstLevel
) << R300_TX_MAX_MIP_LEVEL_SHIFT
));
235 if (t
->base
.Target
== GL_TEXTURE_CUBE_MAP
)
236 t
->pp_txformat
|= R300_TX_FORMAT_CUBIC_MAP
;
237 if (t
->base
.Target
== GL_TEXTURE_3D
)
238 t
->pp_txformat
|= R300_TX_FORMAT_3D
;
241 if (t
->base
.Target
== GL_TEXTURE_RECTANGLE_NV
) {
242 unsigned int align
= (64 / t
->mt
->bpp
) - 1;
243 t
->pp_txsize
|= R300_TX_SIZE_TXPITCH_EN
;
244 if (!t
->image_override
)
245 t
->pp_txpitch
= ((firstImage
->Width
+ align
) & ~align
) - 1;
248 if (rmesa
->radeon
.radeonScreen
->chip_family
>= CHIP_FAMILY_RV515
) {
249 if (firstImage
->Width
> 2048)
250 t
->pp_txpitch
|= R500_TXWIDTH_BIT11
;
251 if (firstImage
->Height
> 2048)
252 t
->pp_txpitch
|= R500_TXHEIGHT_BIT11
;
257 * Ensure the given texture is ready for rendering.
259 * Mostly this means populating the texture object's mipmap tree.
261 static GLboolean
r300_validate_texture(GLcontext
* ctx
, struct gl_texture_object
*texObj
)
263 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
264 radeonTexObj
*t
= radeon_tex_obj(texObj
);
266 if (!radeon_validate_texture_miptree(ctx
, texObj
))
269 /* Configure the hardware registers (more precisely, the cached version
270 * of the hardware registers). */
271 setup_hardware_state(rmesa
, t
);
273 t
->validated
= GL_TRUE
;
278 * Ensure all enabled and complete textures are uploaded along with any buffers being used.
280 GLboolean
r300ValidateBuffers(GLcontext
* ctx
)
282 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
283 struct radeon_renderbuffer
*rrb
;
287 radeon_cs_space_reset_bos(rmesa
->radeon
.cmdbuf
.cs
);
289 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
291 if (rrb
&& rrb
->bo
) {
292 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
,
294 RADEON_GEM_DOMAIN_VRAM
);
298 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
299 if (rrb
&& rrb
->bo
) {
300 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
,
302 RADEON_GEM_DOMAIN_VRAM
);
305 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
308 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
311 if (!r300_validate_texture(ctx
, ctx
->Texture
.Unit
[i
]._Current
)) {
313 "failed to validate texture for unit %d.\n",
316 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
317 if (t
->image_override
&& t
->bo
)
318 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
,
320 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
322 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
,
324 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
327 ret
= radeon_cs_space_check_with_bo(rmesa
->radeon
.cmdbuf
.cs
, first_elem(&rmesa
->radeon
.dma
.reserved
)->bo
, RADEON_GEM_DOMAIN_GTT
, 0);
333 void r300SetTexOffset(__DRIcontext
* pDRICtx
, GLint texname
,
334 unsigned long long offset
, GLint depth
, GLuint pitch
)
336 r300ContextPtr rmesa
= pDRICtx
->driverPrivate
;
337 struct gl_texture_object
*tObj
=
338 _mesa_lookup_texture(rmesa
->radeon
.glCtx
, texname
);
339 radeonTexObjPtr t
= radeon_tex_obj(tObj
);
345 t
->image_override
= GL_TRUE
;
351 t
->override_offset
= offset
;
352 t
->pp_txpitch
&= (1 << 13) -1;
357 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
);
358 t
->pp_txfilter
|= tx_table
[2].filter
;
363 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, W8Z8Y8X8
);
364 t
->pp_txfilter
|= tx_table
[4].filter
;
368 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
);
369 t
->pp_txfilter
|= tx_table
[5].filter
;
375 t
->pp_txpitch
|= pitch_val
;
378 void r300SetTexBuffer2(__DRIcontext
*pDRICtx
, GLint target
, GLint glx_texture_format
, __DRIdrawable
*dPriv
)
380 struct gl_texture_unit
*texUnit
;
381 struct gl_texture_object
*texObj
;
382 struct gl_texture_image
*texImage
;
383 struct radeon_renderbuffer
*rb
;
384 radeon_texture_image
*rImage
;
385 radeonContextPtr radeon
;
386 r300ContextPtr rmesa
;
387 struct radeon_framebuffer
*rfb
;
390 uint32_t internalFormat
, type
, format
;
393 format
= GL_UNSIGNED_BYTE
;
394 internalFormat
= (glx_texture_format
== GLX_TEXTURE_FORMAT_RGB_EXT
? 3 : 4);
396 radeon
= pDRICtx
->driverPrivate
;
397 rmesa
= pDRICtx
->driverPrivate
;
399 rfb
= dPriv
->driverPrivate
;
400 texUnit
= &radeon
->glCtx
->Texture
.Unit
[radeon
->glCtx
->Texture
.CurrentUnit
];
401 texObj
= _mesa_select_tex_object(radeon
->glCtx
, texUnit
, target
);
402 texImage
= _mesa_get_tex_image(radeon
->glCtx
, texObj
, target
, 0);
404 rImage
= get_radeon_texture_image(texImage
);
405 t
= radeon_tex_obj(texObj
);
410 radeon_update_renderbuffers(pDRICtx
, dPriv
);
411 /* back & depth buffer are useless free them right away */
412 rb
= (void*)rfb
->base
.Attachment
[BUFFER_DEPTH
].Renderbuffer
;
414 radeon_bo_unref(rb
->bo
);
417 rb
= (void*)rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
419 radeon_bo_unref(rb
->bo
);
422 rb
= rfb
->color_rb
[0];
423 if (rb
->bo
== NULL
) {
424 /* Failed to BO for the buffer */
428 _mesa_lock_texture(radeon
->glCtx
, texObj
);
430 radeon_bo_unref(t
->bo
);
434 radeon_bo_unref(rImage
->bo
);
438 radeon_miptree_unreference(t
->mt
);
442 radeon_miptree_unreference(rImage
->mt
);
445 _mesa_init_teximage_fields(radeon
->glCtx
, target
, texImage
,
446 rb
->base
.Width
, rb
->base
.Height
, 1, 0, rb
->cpp
);
447 texImage
->RowStride
= rb
->pitch
/ rb
->cpp
;
448 texImage
->TexFormat
= radeonChooseTextureFormat(radeon
->glCtx
,
452 radeon_bo_ref(rImage
->bo
);
454 radeon_bo_ref(t
->bo
);
456 t
->image_override
= GL_TRUE
;
457 t
->override_offset
= 0;
458 t
->pp_txpitch
&= (1 << 13) -1;
459 pitch_val
= rb
->pitch
;
462 if (glx_texture_format
== GLX_TEXTURE_FORMAT_RGB_EXT
)
463 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, W8Z8Y8X8
);
465 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
);
466 t
->pp_txfilter
|= tx_table
[2].filter
;
471 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, W8Z8Y8X8
);
472 t
->pp_txfilter
|= tx_table
[4].filter
;
476 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
);
477 t
->pp_txfilter
|= tx_table
[5].filter
;
482 t
->pp_txsize
= ((rb
->base
.Width
- 1) << R300_TX_WIDTHMASK_SHIFT
) |
483 ((rb
->base
.Height
- 1) << R300_TX_HEIGHTMASK_SHIFT
);
484 t
->pp_txsize
|= R300_TX_SIZE_TXPITCH_EN
;
485 t
->pp_txpitch
|= pitch_val
;
487 if (rmesa
->radeon
.radeonScreen
->chip_family
>= CHIP_FAMILY_RV515
) {
488 if (rb
->base
.Width
> 2048)
489 t
->pp_txpitch
|= R500_TXWIDTH_BIT11
;
490 if (rb
->base
.Height
> 2048)
491 t
->pp_txpitch
|= R500_TXHEIGHT_BIT11
;
493 t
->validated
= GL_TRUE
;
494 _mesa_unlock_texture(radeon
->glCtx
, texObj
);
498 void r300SetTexBuffer(__DRIcontext
*pDRICtx
, GLint target
, __DRIdrawable
*dPriv
)
500 r300SetTexBuffer2(pDRICtx
, target
, GLX_TEXTURE_FORMAT_RGBA_EXT
, dPriv
);