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"
47 #include "r300_context.h"
48 #include "r300_state.h"
49 #include "r300_ioctl.h"
50 #include "radeon_mipmap_tree.h"
54 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5 \
55 || ((f) >= MESA_FORMAT_RGBA_FLOAT32 && \
56 (f) <= MESA_FORMAT_INTENSITY_FLOAT16)) \
59 #define _ASSIGN(entry, format) \
60 [ MESA_FORMAT_ ## entry ] = { format, 0, 1}
63 * Note that the _REV formats are the same as the non-REV formats. This is
64 * because the REV and non-REV formats are identical as a byte string, but
65 * differ when accessed as 16-bit or 32-bit words depending on the endianness of
66 * the host. Since the textures are transferred to the R300 as a byte string
67 * (i.e. without any byte-swapping), the R300 sees the REV and non-REV formats
68 * identically. -- paulus
71 static const struct tx_table
{
72 GLuint format
, filter
, flag
;
75 #ifdef MESA_LITTLE_ENDIAN
76 _ASSIGN(RGBA8888
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W8Z8Y8X8
)),
77 _ASSIGN(RGBA8888_REV
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, W8Z8Y8X8
)),
78 _ASSIGN(ARGB8888
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
)),
79 _ASSIGN(ARGB8888_REV
, R300_EASY_TX_FORMAT(W
, Z
, Y
, X
, W8Z8Y8X8
)),
81 _ASSIGN(RGBA8888
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, W8Z8Y8X8
)),
82 _ASSIGN(RGBA8888_REV
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W8Z8Y8X8
)),
83 _ASSIGN(ARGB8888
, R300_EASY_TX_FORMAT(W
, Z
, Y
, X
, W8Z8Y8X8
)),
84 _ASSIGN(ARGB8888_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
)),
86 _ASSIGN(RGB888
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, W8Z8Y8X8
)),
87 _ASSIGN(RGB565
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
)),
88 _ASSIGN(RGB565_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
)),
89 _ASSIGN(ARGB4444
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W4Z4Y4X4
)),
90 _ASSIGN(ARGB4444_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W4Z4Y4X4
)),
91 _ASSIGN(ARGB1555
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W1Z5Y5X5
)),
92 _ASSIGN(ARGB1555_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W1Z5Y5X5
)),
93 _ASSIGN(AL88
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, Y8X8
)),
94 _ASSIGN(AL88_REV
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, Y8X8
)),
95 _ASSIGN(RGB332
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z3Y3X2
)),
96 _ASSIGN(A8
, R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, X8
)),
97 _ASSIGN(L8
, R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X8
)),
98 _ASSIGN(I8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X8
)),
99 _ASSIGN(CI8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X8
)),
100 _ASSIGN(YCBCR
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, G8R8_G8B8
) | R300_TX_FORMAT_YUV_MODE
),
101 _ASSIGN(YCBCR_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, G8R8_G8B8
) | R300_TX_FORMAT_YUV_MODE
),
102 _ASSIGN(RGB_DXT1
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, DXT1
)),
103 _ASSIGN(RGBA_DXT1
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, DXT1
)),
104 _ASSIGN(RGBA_DXT3
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, DXT3
)),
105 _ASSIGN(RGBA_DXT5
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, DXT5
)),
106 _ASSIGN(RGBA_FLOAT32
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, FL_R32G32B32A32
)),
107 _ASSIGN(RGBA_FLOAT16
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, FL_R16G16B16A16
)),
108 _ASSIGN(RGB_FLOAT32
, 0xffffffff),
109 _ASSIGN(RGB_FLOAT16
, 0xffffffff),
110 _ASSIGN(ALPHA_FLOAT32
, R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, FL_I32
)),
111 _ASSIGN(ALPHA_FLOAT16
, R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, FL_I16
)),
112 _ASSIGN(LUMINANCE_FLOAT32
, R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, FL_I32
)),
113 _ASSIGN(LUMINANCE_FLOAT16
, R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, FL_I16
)),
114 _ASSIGN(LUMINANCE_ALPHA_FLOAT32
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, FL_I32A32
)),
115 _ASSIGN(LUMINANCE_ALPHA_FLOAT16
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, FL_I16A16
)),
116 _ASSIGN(INTENSITY_FLOAT32
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, FL_I32
)),
117 _ASSIGN(INTENSITY_FLOAT16
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, FL_I16
)),
118 _ASSIGN(Z16
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X16
)),
119 _ASSIGN(Z24_S8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X24_Y8
)),
120 _ASSIGN(S8_Z24
, R300_EASY_TX_FORMAT(Y
, Y
, Y
, Y
, X24_Y8
)),
121 _ASSIGN(Z32
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X32
)),
122 /* EXT_texture_sRGB */
123 _ASSIGN(SRGBA8
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W8Z8Y8X8
) | R300_TX_FORMAT_GAMMA
),
124 _ASSIGN(SLA8
, R300_EASY_TX_FORMAT(X
, X
, X
, Y
, Y8X8
) | R300_TX_FORMAT_GAMMA
),
125 _ASSIGN(SL8
, R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X8
) | R300_TX_FORMAT_GAMMA
),
131 void r300SetDepthTexMode(struct gl_texture_object
*tObj
)
133 static const GLuint formats
[3][3] = {
135 R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X16
),
136 R300_EASY_TX_FORMAT(X
, X
, X
, X
, X16
),
137 R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, X16
),
140 R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X24_Y8
),
141 R300_EASY_TX_FORMAT(X
, X
, X
, X
, X24_Y8
),
142 R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, X24_Y8
),
145 R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X32
),
146 R300_EASY_TX_FORMAT(X
, X
, X
, X
, X32
),
147 R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, X32
),
150 const GLuint
*format
;
156 t
= radeon_tex_obj(tObj
);
158 switch (tObj
->Image
[0][tObj
->BaseLevel
]->TexFormat
->MesaFormat
) {
159 case MESA_FORMAT_Z16
:
162 case MESA_FORMAT_Z24_S8
:
165 case MESA_FORMAT_Z32
:
169 /* Error...which should have already been caught by higher
176 switch (tObj
->DepthMode
) {
178 t
->pp_txformat
= format
[0];
181 t
->pp_txformat
= format
[1];
184 t
->pp_txformat
= format
[2];
187 /* Error...which should have already been caught by higher
197 * Compute the cached hardware register values for the given texture object.
199 * \param rmesa Context pointer
200 * \param t the r300 texture object
202 static void setup_hardware_state(r300ContextPtr rmesa
, radeonTexObj
*t
)
204 const struct gl_texture_image
*firstImage
;
205 int firstlevel
= t
->mt
? t
->mt
->firstLevel
: 0;
207 firstImage
= t
->base
.Image
[0][firstlevel
];
209 if (!t
->image_override
210 && VALID_FORMAT(firstImage
->TexFormat
->MesaFormat
)) {
211 if (firstImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
) {
212 r300SetDepthTexMode(&t
->base
);
214 t
->pp_txformat
= tx_table
[firstImage
->TexFormat
->MesaFormat
].format
;
217 t
->pp_txfilter
|= tx_table
[firstImage
->TexFormat
->MesaFormat
].filter
;
218 } else if (!t
->image_override
) {
219 _mesa_problem(NULL
, "unexpected texture format in %s",
224 if (t
->image_override
&& t
->bo
)
227 t
->pp_txsize
= (((firstImage
->Width
- 1) << R300_TX_WIDTHMASK_SHIFT
)
228 | ((firstImage
->Height
- 1) << R300_TX_HEIGHTMASK_SHIFT
)
229 | ((firstImage
->DepthLog2
) << R300_TX_DEPTHMASK_SHIFT
)
230 | ((t
->mt
->lastLevel
- t
->mt
->firstLevel
) << R300_TX_MAX_MIP_LEVEL_SHIFT
));
234 if (t
->base
.Target
== GL_TEXTURE_CUBE_MAP
)
235 t
->pp_txformat
|= R300_TX_FORMAT_CUBIC_MAP
;
236 if (t
->base
.Target
== GL_TEXTURE_3D
)
237 t
->pp_txformat
|= R300_TX_FORMAT_3D
;
240 if (t
->base
.Target
== GL_TEXTURE_RECTANGLE_NV
) {
241 unsigned int align
= (64 / t
->mt
->bpp
) - 1;
242 t
->pp_txsize
|= R300_TX_SIZE_TXPITCH_EN
;
243 if (!t
->image_override
)
244 t
->pp_txpitch
= ((firstImage
->Width
+ align
) & ~align
) - 1;
247 if (rmesa
->radeon
.radeonScreen
->chip_family
>= CHIP_FAMILY_RV515
) {
248 if (firstImage
->Width
> 2048)
249 t
->pp_txpitch
|= R500_TXWIDTH_BIT11
;
250 if (firstImage
->Height
> 2048)
251 t
->pp_txpitch
|= R500_TXHEIGHT_BIT11
;
256 * Ensure the given texture is ready for rendering.
258 * Mostly this means populating the texture object's mipmap tree.
260 static GLboolean
r300_validate_texture(GLcontext
* ctx
, struct gl_texture_object
*texObj
)
262 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
263 radeonTexObj
*t
= radeon_tex_obj(texObj
);
265 if (!radeon_validate_texture_miptree(ctx
, texObj
))
268 /* Configure the hardware registers (more precisely, the cached version
269 * of the hardware registers). */
270 setup_hardware_state(rmesa
, t
);
272 t
->validated
= GL_TRUE
;
277 * Ensure all enabled and complete textures are uploaded along with any buffers being used.
279 GLboolean
r300ValidateBuffers(GLcontext
* ctx
)
281 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
282 struct radeon_renderbuffer
*rrb
;
285 radeon_validate_reset_bos(&rmesa
->radeon
);
287 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
289 if (rrb
&& rrb
->bo
) {
290 radeon_validate_bo(&rmesa
->radeon
, rrb
->bo
,
291 0, RADEON_GEM_DOMAIN_VRAM
);
295 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
296 if (rrb
&& rrb
->bo
) {
297 radeon_validate_bo(&rmesa
->radeon
, rrb
->bo
,
298 0, RADEON_GEM_DOMAIN_VRAM
);
301 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
304 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
307 if (!r300_validate_texture(ctx
, ctx
->Texture
.Unit
[i
]._Current
)) {
309 "failed to validate texture for unit %d.\n",
312 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
313 if (t
->image_override
&& t
->bo
)
314 radeon_validate_bo(&rmesa
->radeon
, t
->bo
,
315 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
318 radeon_validate_bo(&rmesa
->radeon
, t
->mt
->bo
,
319 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
321 if (rmesa
->radeon
.dma
.current
)
322 radeon_validate_bo(&rmesa
->radeon
, rmesa
->radeon
.dma
.current
, RADEON_GEM_DOMAIN_GTT
, 0);
324 return radeon_revalidate_bos(ctx
);
327 void r300SetTexOffset(__DRIcontext
* pDRICtx
, GLint texname
,
328 unsigned long long offset
, GLint depth
, GLuint pitch
)
330 r300ContextPtr rmesa
= pDRICtx
->driverPrivate
;
331 struct gl_texture_object
*tObj
=
332 _mesa_lookup_texture(rmesa
->radeon
.glCtx
, texname
);
333 radeonTexObjPtr t
= radeon_tex_obj(tObj
);
339 t
->image_override
= GL_TRUE
;
345 t
->override_offset
= offset
;
346 t
->pp_txpitch
&= (1 << 13) -1;
351 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
);
352 t
->pp_txfilter
|= tx_table
[2].filter
;
357 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, W8Z8Y8X8
);
358 t
->pp_txfilter
|= tx_table
[4].filter
;
362 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
);
363 t
->pp_txfilter
|= tx_table
[5].filter
;
369 t
->pp_txpitch
|= pitch_val
;
372 void r300SetTexBuffer2(__DRIcontext
*pDRICtx
, GLint target
, GLint glx_texture_format
, __DRIdrawable
*dPriv
)
374 struct gl_texture_unit
*texUnit
;
375 struct gl_texture_object
*texObj
;
376 struct gl_texture_image
*texImage
;
377 struct radeon_renderbuffer
*rb
;
378 radeon_texture_image
*rImage
;
379 radeonContextPtr radeon
;
380 r300ContextPtr rmesa
;
381 struct radeon_framebuffer
*rfb
;
384 uint32_t internalFormat
, type
, format
;
387 format
= GL_UNSIGNED_BYTE
;
388 internalFormat
= (glx_texture_format
== GLX_TEXTURE_FORMAT_RGB_EXT
? 3 : 4);
390 radeon
= pDRICtx
->driverPrivate
;
391 rmesa
= pDRICtx
->driverPrivate
;
393 rfb
= dPriv
->driverPrivate
;
394 texUnit
= &radeon
->glCtx
->Texture
.Unit
[radeon
->glCtx
->Texture
.CurrentUnit
];
395 texObj
= _mesa_select_tex_object(radeon
->glCtx
, texUnit
, target
);
396 texImage
= _mesa_get_tex_image(radeon
->glCtx
, texObj
, target
, 0);
398 rImage
= get_radeon_texture_image(texImage
);
399 t
= radeon_tex_obj(texObj
);
404 radeon_update_renderbuffers(pDRICtx
, dPriv
);
405 /* back & depth buffer are useless free them right away */
406 rb
= (void*)rfb
->base
.Attachment
[BUFFER_DEPTH
].Renderbuffer
;
408 radeon_bo_unref(rb
->bo
);
411 rb
= (void*)rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
413 radeon_bo_unref(rb
->bo
);
416 rb
= rfb
->color_rb
[0];
417 if (rb
->bo
== NULL
) {
418 /* Failed to BO for the buffer */
422 _mesa_lock_texture(radeon
->glCtx
, texObj
);
424 radeon_bo_unref(t
->bo
);
428 radeon_bo_unref(rImage
->bo
);
432 radeon_miptree_unreference(t
->mt
);
436 radeon_miptree_unreference(rImage
->mt
);
439 _mesa_init_teximage_fields(radeon
->glCtx
, target
, texImage
,
440 rb
->width
, rb
->height
, 1, 0, rb
->cpp
);
441 texImage
->RowStride
= rb
->pitch
/ rb
->cpp
;
442 texImage
->TexFormat
= radeonChooseTextureFormat(radeon
->glCtx
,
446 radeon_bo_ref(rImage
->bo
);
448 radeon_bo_ref(t
->bo
);
450 t
->image_override
= GL_TRUE
;
451 t
->override_offset
= 0;
452 t
->pp_txpitch
&= (1 << 13) -1;
453 pitch_val
= rb
->pitch
;
456 if (glx_texture_format
== GLX_TEXTURE_FORMAT_RGB_EXT
)
457 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, W8Z8Y8X8
);
459 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
);
460 t
->pp_txfilter
|= tx_table
[2].filter
;
465 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, W8Z8Y8X8
);
466 t
->pp_txfilter
|= tx_table
[4].filter
;
470 t
->pp_txformat
= R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
);
471 t
->pp_txfilter
|= tx_table
[5].filter
;
476 t
->pp_txsize
= ((rb
->width
- 1) << R300_TX_WIDTHMASK_SHIFT
) |
477 ((rb
->height
- 1) << R300_TX_HEIGHTMASK_SHIFT
);
478 t
->pp_txsize
|= R300_TX_SIZE_TXPITCH_EN
;
479 t
->pp_txpitch
|= pitch_val
;
481 if (rmesa
->radeon
.radeonScreen
->chip_family
>= CHIP_FAMILY_RV515
) {
482 if (rb
->width
> 2048)
483 t
->pp_txpitch
|= R500_TXWIDTH_BIT11
;
484 if (rb
->height
> 2048)
485 t
->pp_txpitch
|= R500_TXHEIGHT_BIT11
;
487 t
->validated
= GL_TRUE
;
488 _mesa_unlock_texture(radeon
->glCtx
, texObj
);
492 void r300SetTexBuffer(__DRIcontext
*pDRICtx
, GLint target
, __DRIdrawable
*dPriv
)
494 r300SetTexBuffer2(pDRICtx
, target
, GLX_TEXTURE_FORMAT_RGBA_EXT
, dPriv
);