1848b8605Smrg/*
2848b8605Smrg * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3848b8605Smrg * Copyright 2010 Marek Olšák <maraeo@gmail.com>
4848b8605Smrg *
5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6848b8605Smrg * copy of this software and associated documentation files (the "Software"),
7848b8605Smrg * to deal in the Software without restriction, including without limitation
8848b8605Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
9848b8605Smrg * license, and/or sell copies of the Software, and to permit persons to whom
10848b8605Smrg * the Software is furnished to do so, subject to the following conditions:
11848b8605Smrg *
12848b8605Smrg * The above copyright notice and this permission notice (including the next
13848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the
14848b8605Smrg * Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19848b8605Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20848b8605Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21848b8605Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22848b8605Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23848b8605Smrg
24848b8605Smrg/* Always include headers in the reverse order!! ~ M. */
25848b8605Smrg#include "r300_texture.h"
26848b8605Smrg
27848b8605Smrg#include "r300_context.h"
28848b8605Smrg#include "r300_reg.h"
29848b8605Smrg#include "r300_texture_desc.h"
30848b8605Smrg#include "r300_transfer.h"
31848b8605Smrg#include "r300_screen.h"
32848b8605Smrg
33848b8605Smrg#include "util/u_format.h"
34848b8605Smrg#include "util/u_format_s3tc.h"
35848b8605Smrg#include "util/u_math.h"
36848b8605Smrg#include "util/u_memory.h"
37848b8605Smrg
38848b8605Smrg#include "pipe/p_screen.h"
39848b8605Smrg
40b8e80941Smrg/* These formats are supported by swapping their bytes.
41b8e80941Smrg * The swizzles must be set exactly like their non-swapped counterparts,
42b8e80941Smrg * because byte-swapping is what reverses the component order, not swizzling.
43b8e80941Smrg *
44b8e80941Smrg * This function returns the format that must be used to program CB and TX
45b8e80941Smrg * swizzles.
46b8e80941Smrg */
47b8e80941Smrgstatic enum pipe_format r300_unbyteswap_array_format(enum pipe_format format)
48b8e80941Smrg{
49b8e80941Smrg    /* FIXME: Disabled on little endian because of a reported regression:
50b8e80941Smrg     * https://bugs.freedesktop.org/show_bug.cgi?id=98869 */
51b8e80941Smrg    if (PIPE_ENDIAN_NATIVE != PIPE_ENDIAN_BIG)
52b8e80941Smrg        return format;
53b8e80941Smrg
54b8e80941Smrg    /* Only BGRA 8888 array formats are supported for simplicity of
55b8e80941Smrg     * the implementation. */
56b8e80941Smrg    switch (format) {
57b8e80941Smrg    case PIPE_FORMAT_A8R8G8B8_UNORM:
58b8e80941Smrg        return PIPE_FORMAT_B8G8R8A8_UNORM;
59b8e80941Smrg    case PIPE_FORMAT_A8R8G8B8_SRGB:
60b8e80941Smrg        return PIPE_FORMAT_B8G8R8A8_SRGB;
61b8e80941Smrg    case PIPE_FORMAT_X8R8G8B8_UNORM:
62b8e80941Smrg        return PIPE_FORMAT_B8G8R8X8_UNORM;
63b8e80941Smrg    case PIPE_FORMAT_X8R8G8B8_SRGB:
64b8e80941Smrg        return PIPE_FORMAT_B8G8R8X8_SRGB;
65b8e80941Smrg    default:
66b8e80941Smrg        return format;
67b8e80941Smrg    }
68b8e80941Smrg}
69b8e80941Smrg
70b8e80941Smrgstatic unsigned r300_get_endian_swap(enum pipe_format format)
71b8e80941Smrg{
72b8e80941Smrg    const struct util_format_description *desc;
73b8e80941Smrg    unsigned swap_size;
74b8e80941Smrg
75b8e80941Smrg    if (r300_unbyteswap_array_format(format) != format)
76b8e80941Smrg        return R300_SURF_DWORD_SWAP;
77b8e80941Smrg
78b8e80941Smrg    if (PIPE_ENDIAN_NATIVE != PIPE_ENDIAN_BIG)
79b8e80941Smrg        return R300_SURF_NO_SWAP;
80b8e80941Smrg
81b8e80941Smrg    desc = util_format_description(format);
82b8e80941Smrg    if (!desc)
83b8e80941Smrg        return R300_SURF_NO_SWAP;
84b8e80941Smrg
85b8e80941Smrg    /* Compressed formats should be in the little endian format. */
86b8e80941Smrg    if (desc->block.width != 1 || desc->block.height != 1)
87b8e80941Smrg        return R300_SURF_NO_SWAP;
88b8e80941Smrg
89b8e80941Smrg    swap_size = desc->is_array ? desc->channel[0].size : desc->block.bits;
90b8e80941Smrg
91b8e80941Smrg    switch (swap_size) {
92b8e80941Smrg    default: /* shouldn't happen? */
93b8e80941Smrg    case 8:
94b8e80941Smrg        return R300_SURF_NO_SWAP;
95b8e80941Smrg    case 16:
96b8e80941Smrg        return R300_SURF_WORD_SWAP;
97b8e80941Smrg    case 32:
98b8e80941Smrg        return R300_SURF_DWORD_SWAP;
99b8e80941Smrg    }
100b8e80941Smrg}
101b8e80941Smrg
102848b8605Smrgunsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
103848b8605Smrg                                   const unsigned char *swizzle_view,
104848b8605Smrg                                   boolean dxtc_swizzle)
105848b8605Smrg{
106848b8605Smrg    unsigned i;
107848b8605Smrg    unsigned char swizzle[4];
108848b8605Smrg    unsigned result = 0;
109848b8605Smrg    const uint32_t swizzle_shift[4] = {
110848b8605Smrg        R300_TX_FORMAT_R_SHIFT,
111848b8605Smrg        R300_TX_FORMAT_G_SHIFT,
112848b8605Smrg        R300_TX_FORMAT_B_SHIFT,
113848b8605Smrg        R300_TX_FORMAT_A_SHIFT
114848b8605Smrg    };
115848b8605Smrg    uint32_t swizzle_bit[4] = {
116848b8605Smrg        dxtc_swizzle ? R300_TX_FORMAT_Z : R300_TX_FORMAT_X,
117848b8605Smrg        R300_TX_FORMAT_Y,
118848b8605Smrg        dxtc_swizzle ? R300_TX_FORMAT_X : R300_TX_FORMAT_Z,
119848b8605Smrg        R300_TX_FORMAT_W
120848b8605Smrg    };
121848b8605Smrg
122848b8605Smrg    if (swizzle_view) {
123848b8605Smrg        /* Combine two sets of swizzles. */
124848b8605Smrg        util_format_compose_swizzles(swizzle_format, swizzle_view, swizzle);
125848b8605Smrg    } else {
126848b8605Smrg        memcpy(swizzle, swizzle_format, 4);
127848b8605Smrg    }
128848b8605Smrg
129848b8605Smrg    /* Get swizzle. */
130848b8605Smrg    for (i = 0; i < 4; i++) {
131848b8605Smrg        switch (swizzle[i]) {
132b8e80941Smrg            case PIPE_SWIZZLE_Y:
133848b8605Smrg                result |= swizzle_bit[1] << swizzle_shift[i];
134848b8605Smrg                break;
135b8e80941Smrg            case PIPE_SWIZZLE_Z:
136848b8605Smrg                result |= swizzle_bit[2] << swizzle_shift[i];
137848b8605Smrg                break;
138b8e80941Smrg            case PIPE_SWIZZLE_W:
139848b8605Smrg                result |= swizzle_bit[3] << swizzle_shift[i];
140848b8605Smrg                break;
141b8e80941Smrg            case PIPE_SWIZZLE_0:
142848b8605Smrg                result |= R300_TX_FORMAT_ZERO << swizzle_shift[i];
143848b8605Smrg                break;
144b8e80941Smrg            case PIPE_SWIZZLE_1:
145848b8605Smrg                result |= R300_TX_FORMAT_ONE << swizzle_shift[i];
146848b8605Smrg                break;
147b8e80941Smrg            default: /* PIPE_SWIZZLE_X */
148848b8605Smrg                result |= swizzle_bit[0] << swizzle_shift[i];
149848b8605Smrg        }
150848b8605Smrg    }
151848b8605Smrg    return result;
152848b8605Smrg}
153848b8605Smrg
154848b8605Smrg/* Translate a pipe_format into a useful texture format for sampling.
155848b8605Smrg *
156848b8605Smrg * Some special formats are translated directly using R300_EASY_TX_FORMAT,
157848b8605Smrg * but the majority of them is translated in a generic way, automatically
158848b8605Smrg * supporting all the formats hw can support.
159848b8605Smrg *
160848b8605Smrg * R300_EASY_TX_FORMAT swizzles the texture.
161848b8605Smrg * Note the signature of R300_EASY_TX_FORMAT:
162848b8605Smrg *   R300_EASY_TX_FORMAT(B, G, R, A, FORMAT);
163848b8605Smrg *
164848b8605Smrg * The FORMAT specifies how the texture sampler will treat the texture, and
165848b8605Smrg * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */
166848b8605Smrguint32_t r300_translate_texformat(enum pipe_format format,
167848b8605Smrg                                  const unsigned char *swizzle_view,
168848b8605Smrg                                  boolean is_r500,
169848b8605Smrg                                  boolean dxtc_swizzle)
170848b8605Smrg{
171848b8605Smrg    uint32_t result = 0;
172848b8605Smrg    const struct util_format_description *desc;
173848b8605Smrg    unsigned i;
174848b8605Smrg    boolean uniform = TRUE;
175848b8605Smrg    const uint32_t sign_bit[4] = {
176848b8605Smrg        R300_TX_FORMAT_SIGNED_W,
177848b8605Smrg        R300_TX_FORMAT_SIGNED_Z,
178848b8605Smrg        R300_TX_FORMAT_SIGNED_Y,
179848b8605Smrg        R300_TX_FORMAT_SIGNED_X,
180848b8605Smrg    };
181848b8605Smrg
182b8e80941Smrg    format = r300_unbyteswap_array_format(format);
183848b8605Smrg    desc = util_format_description(format);
184848b8605Smrg
185848b8605Smrg    /* Colorspace (return non-RGB formats directly). */
186848b8605Smrg    switch (desc->colorspace) {
187848b8605Smrg        /* Depth stencil formats.
188848b8605Smrg         * Swizzles are added in r300_merge_textures_and_samplers. */
189848b8605Smrg        case UTIL_FORMAT_COLORSPACE_ZS:
190848b8605Smrg            switch (format) {
191848b8605Smrg                case PIPE_FORMAT_Z16_UNORM:
192848b8605Smrg                    return R300_TX_FORMAT_X16;
193848b8605Smrg                case PIPE_FORMAT_X8Z24_UNORM:
194848b8605Smrg                case PIPE_FORMAT_S8_UINT_Z24_UNORM:
195848b8605Smrg                    if (is_r500)
196848b8605Smrg                        return R500_TX_FORMAT_Y8X24;
197848b8605Smrg                    else
198848b8605Smrg                        return R300_TX_FORMAT_Y16X16;
199848b8605Smrg                default:
200848b8605Smrg                    return ~0; /* Unsupported. */
201848b8605Smrg            }
202848b8605Smrg
203848b8605Smrg        /* YUV formats. */
204848b8605Smrg        case UTIL_FORMAT_COLORSPACE_YUV:
205848b8605Smrg            result |= R300_TX_FORMAT_YUV_TO_RGB;
206848b8605Smrg
207848b8605Smrg            switch (format) {
208848b8605Smrg                case PIPE_FORMAT_UYVY:
209848b8605Smrg                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result;
210848b8605Smrg                case PIPE_FORMAT_YUYV:
211848b8605Smrg                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result;
212848b8605Smrg                default:
213848b8605Smrg                    return ~0; /* Unsupported/unknown. */
214848b8605Smrg            }
215848b8605Smrg
216848b8605Smrg        /* Add gamma correction. */
217848b8605Smrg        case UTIL_FORMAT_COLORSPACE_SRGB:
218848b8605Smrg            result |= R300_TX_FORMAT_GAMMA;
219848b8605Smrg            break;
220848b8605Smrg
221848b8605Smrg        default:
222848b8605Smrg            switch (format) {
223848b8605Smrg                /* Same as YUV but without the YUR->RGB conversion. */
224848b8605Smrg                case PIPE_FORMAT_R8G8_B8G8_UNORM:
225848b8605Smrg                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result;
226848b8605Smrg                case PIPE_FORMAT_G8R8_G8B8_UNORM:
227848b8605Smrg                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result;
228848b8605Smrg                default:;
229848b8605Smrg            }
230848b8605Smrg    }
231848b8605Smrg
232848b8605Smrg    /* Add swizzling. */
233848b8605Smrg    /* The RGTC1_SNORM and LATC1_SNORM swizzle is done in the shader. */
234b8e80941Smrg    if (util_format_is_compressed(format) &&
235b8e80941Smrg        dxtc_swizzle &&
236b8e80941Smrg        format != PIPE_FORMAT_RGTC2_UNORM &&
237b8e80941Smrg        format != PIPE_FORMAT_RGTC2_SNORM &&
238b8e80941Smrg        format != PIPE_FORMAT_LATC2_UNORM &&
239b8e80941Smrg        format != PIPE_FORMAT_LATC2_SNORM &&
240b8e80941Smrg        format != PIPE_FORMAT_RGTC1_UNORM &&
241b8e80941Smrg        format != PIPE_FORMAT_RGTC1_SNORM &&
242b8e80941Smrg        format != PIPE_FORMAT_LATC1_UNORM &&
243848b8605Smrg        format != PIPE_FORMAT_LATC1_SNORM) {
244b8e80941Smrg        result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,
245b8e80941Smrg                                            TRUE);
246b8e80941Smrg    } else {
247b8e80941Smrg        result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,
248b8e80941Smrg                                            FALSE);
249848b8605Smrg    }
250848b8605Smrg
251848b8605Smrg    /* S3TC formats. */
252848b8605Smrg    if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
253848b8605Smrg        switch (format) {
254848b8605Smrg            case PIPE_FORMAT_DXT1_RGB:
255848b8605Smrg            case PIPE_FORMAT_DXT1_RGBA:
256848b8605Smrg            case PIPE_FORMAT_DXT1_SRGB:
257848b8605Smrg            case PIPE_FORMAT_DXT1_SRGBA:
258848b8605Smrg                return R300_TX_FORMAT_DXT1 | result;
259848b8605Smrg            case PIPE_FORMAT_DXT3_RGBA:
260848b8605Smrg            case PIPE_FORMAT_DXT3_SRGBA:
261848b8605Smrg                return R300_TX_FORMAT_DXT3 | result;
262848b8605Smrg            case PIPE_FORMAT_DXT5_RGBA:
263848b8605Smrg            case PIPE_FORMAT_DXT5_SRGBA:
264848b8605Smrg                return R300_TX_FORMAT_DXT5 | result;
265848b8605Smrg            default:
266848b8605Smrg                return ~0; /* Unsupported/unknown. */
267848b8605Smrg        }
268848b8605Smrg    }
269848b8605Smrg
270848b8605Smrg    /* RGTC formats. */
271848b8605Smrg    if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
272848b8605Smrg        switch (format) {
273848b8605Smrg            case PIPE_FORMAT_RGTC1_SNORM:
274848b8605Smrg            case PIPE_FORMAT_LATC1_SNORM:
275b8e80941Smrg                result |= sign_bit[0];
276848b8605Smrg            case PIPE_FORMAT_LATC1_UNORM:
277848b8605Smrg            case PIPE_FORMAT_RGTC1_UNORM:
278848b8605Smrg                return R500_TX_FORMAT_ATI1N | result;
279848b8605Smrg
280848b8605Smrg            case PIPE_FORMAT_RGTC2_SNORM:
281848b8605Smrg            case PIPE_FORMAT_LATC2_SNORM:
282848b8605Smrg                result |= sign_bit[1] | sign_bit[0];
283848b8605Smrg            case PIPE_FORMAT_RGTC2_UNORM:
284848b8605Smrg            case PIPE_FORMAT_LATC2_UNORM:
285848b8605Smrg                return R400_TX_FORMAT_ATI2N | result;
286848b8605Smrg
287848b8605Smrg            default:
288848b8605Smrg                return ~0; /* Unsupported/unknown. */
289848b8605Smrg        }
290848b8605Smrg    }
291848b8605Smrg
292848b8605Smrg    /* This is truly a special format.
293848b8605Smrg     * It stores R8G8 and B is computed using sqrt(1 - R^2 - G^2)
294848b8605Smrg     * in the sampler unit. Also known as D3DFMT_CxV8U8. */
295848b8605Smrg    if (format == PIPE_FORMAT_R8G8Bx_SNORM) {
296848b8605Smrg        return R300_TX_FORMAT_CxV8U8 | result;
297848b8605Smrg    }
298848b8605Smrg
299848b8605Smrg    /* Integer and fixed-point 16.16 textures are not supported. */
300848b8605Smrg    for (i = 0; i < 4; i++) {
301848b8605Smrg        if (desc->channel[i].type == UTIL_FORMAT_TYPE_FIXED ||
302848b8605Smrg            ((desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED ||
303848b8605Smrg              desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) &&
304848b8605Smrg             (!desc->channel[i].normalized ||
305848b8605Smrg              desc->channel[i].pure_integer))) {
306848b8605Smrg            return ~0; /* Unsupported/unknown. */
307848b8605Smrg        }
308848b8605Smrg    }
309848b8605Smrg
310848b8605Smrg    /* Add sign. */
311848b8605Smrg    for (i = 0; i < desc->nr_channels; i++) {
312848b8605Smrg        if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
313848b8605Smrg            result |= sign_bit[i];
314848b8605Smrg        }
315848b8605Smrg    }
316848b8605Smrg
317848b8605Smrg    /* See whether the components are of the same size. */
318848b8605Smrg    for (i = 1; i < desc->nr_channels; i++) {
319848b8605Smrg        uniform = uniform && desc->channel[0].size == desc->channel[i].size;
320848b8605Smrg    }
321848b8605Smrg
322848b8605Smrg    /* Non-uniform formats. */
323848b8605Smrg    if (!uniform) {
324848b8605Smrg        switch (desc->nr_channels) {
325848b8605Smrg            case 3:
326848b8605Smrg                if (desc->channel[0].size == 5 &&
327848b8605Smrg                    desc->channel[1].size == 6 &&
328848b8605Smrg                    desc->channel[2].size == 5) {
329848b8605Smrg                    return R300_TX_FORMAT_Z5Y6X5 | result;
330848b8605Smrg                }
331848b8605Smrg                if (desc->channel[0].size == 5 &&
332848b8605Smrg                    desc->channel[1].size == 5 &&
333848b8605Smrg                    desc->channel[2].size == 6) {
334848b8605Smrg                    return R300_TX_FORMAT_Z6Y5X5 | result;
335848b8605Smrg                }
336848b8605Smrg                if (desc->channel[0].size == 2 &&
337848b8605Smrg                    desc->channel[1].size == 3 &&
338848b8605Smrg                    desc->channel[2].size == 3) {
339848b8605Smrg                    return R300_TX_FORMAT_Z3Y3X2 | result;
340848b8605Smrg                }
341848b8605Smrg                return ~0; /* Unsupported/unknown. */
342848b8605Smrg
343848b8605Smrg            case 4:
344848b8605Smrg                if (desc->channel[0].size == 5 &&
345848b8605Smrg                    desc->channel[1].size == 5 &&
346848b8605Smrg                    desc->channel[2].size == 5 &&
347848b8605Smrg                    desc->channel[3].size == 1) {
348848b8605Smrg                    return R300_TX_FORMAT_W1Z5Y5X5 | result;
349848b8605Smrg                }
350848b8605Smrg                if (desc->channel[0].size == 10 &&
351848b8605Smrg                    desc->channel[1].size == 10 &&
352848b8605Smrg                    desc->channel[2].size == 10 &&
353848b8605Smrg                    desc->channel[3].size == 2) {
354848b8605Smrg                    return R300_TX_FORMAT_W2Z10Y10X10 | result;
355848b8605Smrg                }
356848b8605Smrg        }
357848b8605Smrg        return ~0; /* Unsupported/unknown. */
358848b8605Smrg    }
359848b8605Smrg
360848b8605Smrg    /* Find the first non-VOID channel. */
361848b8605Smrg    for (i = 0; i < 4; i++) {
362848b8605Smrg        if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
363848b8605Smrg            break;
364848b8605Smrg        }
365848b8605Smrg    }
366848b8605Smrg
367848b8605Smrg    if (i == 4)
368848b8605Smrg        return ~0; /* Unsupported/unknown. */
369848b8605Smrg
370848b8605Smrg    /* And finally, uniform formats. */
371848b8605Smrg    switch (desc->channel[i].type) {
372848b8605Smrg        case UTIL_FORMAT_TYPE_UNSIGNED:
373848b8605Smrg        case UTIL_FORMAT_TYPE_SIGNED:
374848b8605Smrg            if (!desc->channel[i].normalized &&
375848b8605Smrg                desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
376848b8605Smrg                return ~0;
377848b8605Smrg            }
378848b8605Smrg
379848b8605Smrg            switch (desc->channel[i].size) {
380848b8605Smrg                case 4:
381848b8605Smrg                    switch (desc->nr_channels) {
382848b8605Smrg                        case 2:
383848b8605Smrg                            return R300_TX_FORMAT_Y4X4 | result;
384848b8605Smrg                        case 4:
385848b8605Smrg                            return R300_TX_FORMAT_W4Z4Y4X4 | result;
386848b8605Smrg                    }
387848b8605Smrg                    return ~0;
388848b8605Smrg
389848b8605Smrg                case 8:
390848b8605Smrg                    switch (desc->nr_channels) {
391848b8605Smrg                        case 1:
392848b8605Smrg                            return R300_TX_FORMAT_X8 | result;
393848b8605Smrg                        case 2:
394848b8605Smrg                            return R300_TX_FORMAT_Y8X8 | result;
395848b8605Smrg                        case 4:
396848b8605Smrg                            return R300_TX_FORMAT_W8Z8Y8X8 | result;
397848b8605Smrg                    }
398848b8605Smrg                    return ~0;
399848b8605Smrg
400848b8605Smrg                case 16:
401848b8605Smrg                    switch (desc->nr_channels) {
402848b8605Smrg                        case 1:
403848b8605Smrg                            return R300_TX_FORMAT_X16 | result;
404848b8605Smrg                        case 2:
405848b8605Smrg                            return R300_TX_FORMAT_Y16X16 | result;
406848b8605Smrg                        case 4:
407848b8605Smrg                            return R300_TX_FORMAT_W16Z16Y16X16 | result;
408848b8605Smrg                    }
409848b8605Smrg            }
410848b8605Smrg            return ~0;
411848b8605Smrg
412848b8605Smrg        case UTIL_FORMAT_TYPE_FLOAT:
413848b8605Smrg            switch (desc->channel[i].size) {
414848b8605Smrg                case 16:
415848b8605Smrg                    switch (desc->nr_channels) {
416848b8605Smrg                        case 1:
417848b8605Smrg                            return R300_TX_FORMAT_16F | result;
418848b8605Smrg                        case 2:
419848b8605Smrg                            return R300_TX_FORMAT_16F_16F | result;
420848b8605Smrg                        case 4:
421848b8605Smrg                            return R300_TX_FORMAT_16F_16F_16F_16F | result;
422848b8605Smrg                    }
423848b8605Smrg                    return ~0;
424848b8605Smrg
425848b8605Smrg                case 32:
426848b8605Smrg                    switch (desc->nr_channels) {
427848b8605Smrg                        case 1:
428848b8605Smrg                            return R300_TX_FORMAT_32F | result;
429848b8605Smrg                        case 2:
430848b8605Smrg                            return R300_TX_FORMAT_32F_32F | result;
431848b8605Smrg                        case 4:
432848b8605Smrg                            return R300_TX_FORMAT_32F_32F_32F_32F | result;
433848b8605Smrg                    }
434848b8605Smrg            }
435848b8605Smrg    }
436848b8605Smrg
437848b8605Smrg    return ~0; /* Unsupported/unknown. */
438848b8605Smrg}
439848b8605Smrg
440848b8605Smrguint32_t r500_tx_format_msb_bit(enum pipe_format format)
441848b8605Smrg{
442848b8605Smrg    switch (format) {
443848b8605Smrg        case PIPE_FORMAT_RGTC1_UNORM:
444848b8605Smrg        case PIPE_FORMAT_RGTC1_SNORM:
445848b8605Smrg        case PIPE_FORMAT_LATC1_UNORM:
446848b8605Smrg        case PIPE_FORMAT_LATC1_SNORM:
447848b8605Smrg        case PIPE_FORMAT_X8Z24_UNORM:
448848b8605Smrg        case PIPE_FORMAT_S8_UINT_Z24_UNORM:
449848b8605Smrg            return R500_TXFORMAT_MSB;
450848b8605Smrg        default:
451848b8605Smrg            return 0;
452848b8605Smrg    }
453848b8605Smrg}
454848b8605Smrg
455848b8605Smrg/* Buffer formats. */
456848b8605Smrg
457848b8605Smrg/* Colorbuffer formats. This is the unswizzled format of the RB3D block's
458848b8605Smrg * output. For the swizzling of the targets, check the shader's format. */
459848b8605Smrgstatic uint32_t r300_translate_colorformat(enum pipe_format format)
460848b8605Smrg{
461b8e80941Smrg    format = r300_unbyteswap_array_format(format);
462b8e80941Smrg
463848b8605Smrg    switch (format) {
464848b8605Smrg        /* 8-bit buffers. */
465848b8605Smrg        case PIPE_FORMAT_A8_UNORM:
466848b8605Smrg        case PIPE_FORMAT_A8_SNORM:
467848b8605Smrg        case PIPE_FORMAT_I8_UNORM:
468848b8605Smrg        case PIPE_FORMAT_I8_SNORM:
469848b8605Smrg        case PIPE_FORMAT_L8_UNORM:
470848b8605Smrg        case PIPE_FORMAT_L8_SNORM:
471848b8605Smrg        case PIPE_FORMAT_R8_UNORM:
472848b8605Smrg        case PIPE_FORMAT_R8_SNORM:
473848b8605Smrg            return R300_COLOR_FORMAT_I8;
474848b8605Smrg
475848b8605Smrg        /* 16-bit buffers. */
476848b8605Smrg        case PIPE_FORMAT_L8A8_UNORM:
477848b8605Smrg        case PIPE_FORMAT_L8A8_SNORM:
478848b8605Smrg        case PIPE_FORMAT_R8G8_UNORM:
479848b8605Smrg        case PIPE_FORMAT_R8G8_SNORM:
480848b8605Smrg        case PIPE_FORMAT_R8A8_UNORM:
481848b8605Smrg        case PIPE_FORMAT_R8A8_SNORM:
482848b8605Smrg        /* These formats work fine with UV88 if US_OUT_FMT is set correctly. */
483848b8605Smrg        case PIPE_FORMAT_A16_UNORM:
484848b8605Smrg        case PIPE_FORMAT_A16_SNORM:
485848b8605Smrg        case PIPE_FORMAT_A16_FLOAT:
486848b8605Smrg        case PIPE_FORMAT_L16_UNORM:
487848b8605Smrg        case PIPE_FORMAT_L16_SNORM:
488848b8605Smrg        case PIPE_FORMAT_L16_FLOAT:
489848b8605Smrg        case PIPE_FORMAT_I16_UNORM:
490848b8605Smrg        case PIPE_FORMAT_I16_SNORM:
491848b8605Smrg        case PIPE_FORMAT_I16_FLOAT:
492848b8605Smrg        case PIPE_FORMAT_R16_UNORM:
493848b8605Smrg        case PIPE_FORMAT_R16_SNORM:
494848b8605Smrg        case PIPE_FORMAT_R16_FLOAT:
495848b8605Smrg            return R300_COLOR_FORMAT_UV88;
496848b8605Smrg
497848b8605Smrg        case PIPE_FORMAT_B5G6R5_UNORM:
498848b8605Smrg            return R300_COLOR_FORMAT_RGB565;
499848b8605Smrg
500848b8605Smrg        case PIPE_FORMAT_B5G5R5A1_UNORM:
501848b8605Smrg        case PIPE_FORMAT_B5G5R5X1_UNORM:
502848b8605Smrg            return R300_COLOR_FORMAT_ARGB1555;
503848b8605Smrg
504848b8605Smrg        case PIPE_FORMAT_B4G4R4A4_UNORM:
505848b8605Smrg        case PIPE_FORMAT_B4G4R4X4_UNORM:
506848b8605Smrg            return R300_COLOR_FORMAT_ARGB4444;
507848b8605Smrg
508848b8605Smrg        /* 32-bit buffers. */
509848b8605Smrg        case PIPE_FORMAT_B8G8R8A8_UNORM:
510848b8605Smrg        /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/
511848b8605Smrg        case PIPE_FORMAT_B8G8R8X8_UNORM:
512848b8605Smrg        /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/
513848b8605Smrg        case PIPE_FORMAT_R8G8B8A8_UNORM:
514848b8605Smrg        case PIPE_FORMAT_R8G8B8A8_SNORM:
515848b8605Smrg        case PIPE_FORMAT_R8G8B8X8_UNORM:
516848b8605Smrg        case PIPE_FORMAT_R8G8B8X8_SNORM:
517848b8605Smrg        /* These formats work fine with ARGB8888 if US_OUT_FMT is set
518848b8605Smrg         * correctly. */
519848b8605Smrg        case PIPE_FORMAT_R16G16_UNORM:
520848b8605Smrg        case PIPE_FORMAT_R16G16_SNORM:
521848b8605Smrg        case PIPE_FORMAT_R16G16_FLOAT:
522848b8605Smrg        case PIPE_FORMAT_L16A16_UNORM:
523848b8605Smrg        case PIPE_FORMAT_L16A16_SNORM:
524848b8605Smrg        case PIPE_FORMAT_L16A16_FLOAT:
525848b8605Smrg        case PIPE_FORMAT_R16A16_UNORM:
526848b8605Smrg        case PIPE_FORMAT_R16A16_SNORM:
527848b8605Smrg        case PIPE_FORMAT_R16A16_FLOAT:
528848b8605Smrg        case PIPE_FORMAT_A32_FLOAT:
529848b8605Smrg        case PIPE_FORMAT_L32_FLOAT:
530848b8605Smrg        case PIPE_FORMAT_I32_FLOAT:
531848b8605Smrg        case PIPE_FORMAT_R32_FLOAT:
532848b8605Smrg            return R300_COLOR_FORMAT_ARGB8888;
533848b8605Smrg
534848b8605Smrg        case PIPE_FORMAT_R10G10B10A2_UNORM:
535848b8605Smrg        case PIPE_FORMAT_R10G10B10X2_SNORM:
536848b8605Smrg        case PIPE_FORMAT_B10G10R10A2_UNORM:
537848b8605Smrg        case PIPE_FORMAT_B10G10R10X2_UNORM:
538848b8605Smrg            return R500_COLOR_FORMAT_ARGB2101010;  /* R5xx-only? */
539848b8605Smrg
540848b8605Smrg        /* 64-bit buffers. */
541848b8605Smrg        case PIPE_FORMAT_R16G16B16A16_UNORM:
542848b8605Smrg        case PIPE_FORMAT_R16G16B16A16_SNORM:
543848b8605Smrg        case PIPE_FORMAT_R16G16B16A16_FLOAT:
544848b8605Smrg        case PIPE_FORMAT_R16G16B16X16_UNORM:
545848b8605Smrg        case PIPE_FORMAT_R16G16B16X16_SNORM:
546848b8605Smrg        case PIPE_FORMAT_R16G16B16X16_FLOAT:
547848b8605Smrg        /* These formats work fine with ARGB16161616 if US_OUT_FMT is set
548848b8605Smrg         * correctly. */
549848b8605Smrg        case PIPE_FORMAT_R32G32_FLOAT:
550848b8605Smrg        case PIPE_FORMAT_L32A32_FLOAT:
551848b8605Smrg        case PIPE_FORMAT_R32A32_FLOAT:
552848b8605Smrg            return R300_COLOR_FORMAT_ARGB16161616;
553848b8605Smrg
554848b8605Smrg        /* 128-bit buffers. */
555848b8605Smrg        case PIPE_FORMAT_R32G32B32A32_FLOAT:
556848b8605Smrg        case PIPE_FORMAT_R32G32B32X32_FLOAT:
557848b8605Smrg            return R300_COLOR_FORMAT_ARGB32323232;
558848b8605Smrg
559848b8605Smrg        /* YUV buffers. */
560848b8605Smrg        case PIPE_FORMAT_UYVY:
561848b8605Smrg            return R300_COLOR_FORMAT_YVYU;
562848b8605Smrg        case PIPE_FORMAT_YUYV:
563848b8605Smrg            return R300_COLOR_FORMAT_VYUY;
564848b8605Smrg        default:
565848b8605Smrg            return ~0; /* Unsupported. */
566848b8605Smrg    }
567848b8605Smrg}
568848b8605Smrg
569848b8605Smrg/* Depthbuffer and stencilbuffer. Thankfully, we only support two flavors. */
570848b8605Smrgstatic uint32_t r300_translate_zsformat(enum pipe_format format)
571848b8605Smrg{
572848b8605Smrg    switch (format) {
573848b8605Smrg        /* 16-bit depth, no stencil */
574848b8605Smrg        case PIPE_FORMAT_Z16_UNORM:
575848b8605Smrg            return R300_DEPTHFORMAT_16BIT_INT_Z;
576848b8605Smrg        /* 24-bit depth, ignored stencil */
577848b8605Smrg        case PIPE_FORMAT_X8Z24_UNORM:
578848b8605Smrg        /* 24-bit depth, 8-bit stencil */
579848b8605Smrg        case PIPE_FORMAT_S8_UINT_Z24_UNORM:
580848b8605Smrg            return R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
581848b8605Smrg        default:
582848b8605Smrg            return ~0; /* Unsupported. */
583848b8605Smrg    }
584848b8605Smrg}
585848b8605Smrg
586848b8605Smrg/* Shader output formats. This is essentially the swizzle from the shader
587848b8605Smrg * to the RB3D block.
588848b8605Smrg *
589848b8605Smrg * Note that formats are stored from C3 to C0. */
590848b8605Smrgstatic uint32_t r300_translate_out_fmt(enum pipe_format format)
591848b8605Smrg{
592848b8605Smrg    uint32_t modifier = 0;
593848b8605Smrg    unsigned i;
594848b8605Smrg    const struct util_format_description *desc;
595848b8605Smrg    boolean uniform_sign;
596848b8605Smrg
597b8e80941Smrg    format = r300_unbyteswap_array_format(format);
598848b8605Smrg    desc = util_format_description(format);
599848b8605Smrg
600848b8605Smrg    /* Find the first non-VOID channel. */
601848b8605Smrg    for (i = 0; i < 4; i++) {
602848b8605Smrg        if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
603848b8605Smrg            break;
604848b8605Smrg        }
605848b8605Smrg    }
606848b8605Smrg
607848b8605Smrg    if (i == 4)
608848b8605Smrg        return ~0; /* Unsupported/unknown. */
609848b8605Smrg
610848b8605Smrg    /* Specifies how the shader output is written to the fog unit. */
611848b8605Smrg    switch (desc->channel[i].type) {
612848b8605Smrg    case UTIL_FORMAT_TYPE_FLOAT:
613848b8605Smrg        switch (desc->channel[i].size) {
614848b8605Smrg        case 32:
615848b8605Smrg            switch (desc->nr_channels) {
616848b8605Smrg            case 1:
617848b8605Smrg                modifier |= R300_US_OUT_FMT_C_32_FP;
618848b8605Smrg                break;
619848b8605Smrg            case 2:
620848b8605Smrg                modifier |= R300_US_OUT_FMT_C2_32_FP;
621848b8605Smrg                break;
622848b8605Smrg            case 4:
623848b8605Smrg                modifier |= R300_US_OUT_FMT_C4_32_FP;
624848b8605Smrg                break;
625848b8605Smrg            }
626848b8605Smrg            break;
627848b8605Smrg
628848b8605Smrg        case 16:
629848b8605Smrg            switch (desc->nr_channels) {
630848b8605Smrg            case 1:
631848b8605Smrg                modifier |= R300_US_OUT_FMT_C_16_FP;
632848b8605Smrg                break;
633848b8605Smrg            case 2:
634848b8605Smrg                modifier |= R300_US_OUT_FMT_C2_16_FP;
635848b8605Smrg                break;
636848b8605Smrg            case 4:
637848b8605Smrg                modifier |= R300_US_OUT_FMT_C4_16_FP;
638848b8605Smrg                break;
639848b8605Smrg            }
640848b8605Smrg            break;
641848b8605Smrg        }
642848b8605Smrg        break;
643848b8605Smrg
644848b8605Smrg    default:
645848b8605Smrg        switch (desc->channel[i].size) {
646848b8605Smrg        case 16:
647848b8605Smrg            switch (desc->nr_channels) {
648848b8605Smrg            case 1:
649848b8605Smrg                modifier |= R300_US_OUT_FMT_C_16;
650848b8605Smrg                break;
651848b8605Smrg            case 2:
652848b8605Smrg                modifier |= R300_US_OUT_FMT_C2_16;
653848b8605Smrg                break;
654848b8605Smrg            case 4:
655848b8605Smrg                modifier |= R300_US_OUT_FMT_C4_16;
656848b8605Smrg                break;
657848b8605Smrg            }
658848b8605Smrg            break;
659848b8605Smrg
660848b8605Smrg        case 10:
661848b8605Smrg            modifier |= R300_US_OUT_FMT_C4_10;
662848b8605Smrg            break;
663848b8605Smrg
664848b8605Smrg        default:
665848b8605Smrg            /* C4_8 seems to be used for the formats whose pixel size
666848b8605Smrg             * is <= 32 bits. */
667848b8605Smrg            modifier |= R300_US_OUT_FMT_C4_8;
668848b8605Smrg            break;
669848b8605Smrg        }
670848b8605Smrg    }
671848b8605Smrg
672848b8605Smrg    /* Add sign. */
673848b8605Smrg    uniform_sign = TRUE;
674848b8605Smrg    for (i = 0; i < desc->nr_channels; i++)
675848b8605Smrg        if (desc->channel[i].type != UTIL_FORMAT_TYPE_SIGNED)
676848b8605Smrg            uniform_sign = FALSE;
677848b8605Smrg
678848b8605Smrg    if (uniform_sign)
679848b8605Smrg        modifier |= R300_OUT_SIGN(0xf);
680848b8605Smrg
681848b8605Smrg    /* Add swizzles and return. */
682848b8605Smrg    switch (format) {
683848b8605Smrg        /*** Special cases (non-standard channel mapping) ***/
684848b8605Smrg
685848b8605Smrg        /* X8
686848b8605Smrg         * COLORFORMAT_I8 stores the Z component (C2). */
687848b8605Smrg        case PIPE_FORMAT_A8_UNORM:
688848b8605Smrg        case PIPE_FORMAT_A8_SNORM:
689848b8605Smrg            return modifier | R300_C2_SEL_A;
690848b8605Smrg        case PIPE_FORMAT_I8_UNORM:
691848b8605Smrg        case PIPE_FORMAT_I8_SNORM:
692848b8605Smrg        case PIPE_FORMAT_L8_UNORM:
693848b8605Smrg        case PIPE_FORMAT_L8_SNORM:
694848b8605Smrg        case PIPE_FORMAT_R8_UNORM:
695848b8605Smrg        case PIPE_FORMAT_R8_SNORM:
696848b8605Smrg            return modifier | R300_C2_SEL_R;
697848b8605Smrg
698848b8605Smrg        /* X8Y8
699848b8605Smrg         * COLORFORMAT_UV88 stores ZX (C2 and C0). */
700848b8605Smrg        case PIPE_FORMAT_L8A8_SNORM:
701848b8605Smrg        case PIPE_FORMAT_L8A8_UNORM:
702848b8605Smrg        case PIPE_FORMAT_R8A8_SNORM:
703848b8605Smrg        case PIPE_FORMAT_R8A8_UNORM:
704848b8605Smrg            return modifier | R300_C0_SEL_A | R300_C2_SEL_R;
705848b8605Smrg        case PIPE_FORMAT_R8G8_SNORM:
706848b8605Smrg        case PIPE_FORMAT_R8G8_UNORM:
707848b8605Smrg            return modifier | R300_C0_SEL_G | R300_C2_SEL_R;
708848b8605Smrg
709848b8605Smrg        /* X32Y32
710848b8605Smrg         * ARGB16161616 stores XZ for RG32F */
711848b8605Smrg        case PIPE_FORMAT_R32G32_FLOAT:
712848b8605Smrg            return modifier | R300_C0_SEL_R | R300_C2_SEL_G;
713848b8605Smrg
714848b8605Smrg        /*** Generic cases (standard channel mapping) ***/
715848b8605Smrg
716848b8605Smrg        /* BGRA outputs. */
717848b8605Smrg        case PIPE_FORMAT_B5G6R5_UNORM:
718848b8605Smrg        case PIPE_FORMAT_B5G5R5A1_UNORM:
719848b8605Smrg        case PIPE_FORMAT_B5G5R5X1_UNORM:
720848b8605Smrg        case PIPE_FORMAT_B4G4R4A4_UNORM:
721848b8605Smrg        case PIPE_FORMAT_B4G4R4X4_UNORM:
722848b8605Smrg        case PIPE_FORMAT_B8G8R8A8_UNORM:
723848b8605Smrg        /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/
724848b8605Smrg        case PIPE_FORMAT_B8G8R8X8_UNORM:
725848b8605Smrg        /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/
726848b8605Smrg        case PIPE_FORMAT_B10G10R10A2_UNORM:
727848b8605Smrg        case PIPE_FORMAT_B10G10R10X2_UNORM:
728848b8605Smrg            return modifier |
729848b8605Smrg                R300_C0_SEL_B | R300_C1_SEL_G |
730848b8605Smrg                R300_C2_SEL_R | R300_C3_SEL_A;
731848b8605Smrg
732848b8605Smrg        /* ARGB outputs. */
733848b8605Smrg        case PIPE_FORMAT_A16_UNORM:
734848b8605Smrg        case PIPE_FORMAT_A16_SNORM:
735848b8605Smrg        case PIPE_FORMAT_A16_FLOAT:
736848b8605Smrg        case PIPE_FORMAT_A32_FLOAT:
737848b8605Smrg            return modifier |
738848b8605Smrg                R300_C0_SEL_A | R300_C1_SEL_R |
739848b8605Smrg                R300_C2_SEL_G | R300_C3_SEL_B;
740848b8605Smrg
741848b8605Smrg        /* RGBA outputs. */
742848b8605Smrg        case PIPE_FORMAT_R8G8B8X8_UNORM:
743848b8605Smrg        case PIPE_FORMAT_R8G8B8X8_SNORM:
744848b8605Smrg        case PIPE_FORMAT_R8G8B8A8_UNORM:
745848b8605Smrg        case PIPE_FORMAT_R8G8B8A8_SNORM:
746848b8605Smrg        case PIPE_FORMAT_R10G10B10A2_UNORM:
747848b8605Smrg        case PIPE_FORMAT_R10G10B10X2_SNORM:
748848b8605Smrg        case PIPE_FORMAT_R16_UNORM:
749848b8605Smrg        case PIPE_FORMAT_R16G16_UNORM:
750848b8605Smrg        case PIPE_FORMAT_R16G16B16A16_UNORM:
751848b8605Smrg        case PIPE_FORMAT_R16_SNORM:
752848b8605Smrg        case PIPE_FORMAT_R16G16_SNORM:
753848b8605Smrg        case PIPE_FORMAT_R16G16B16A16_SNORM:
754848b8605Smrg        case PIPE_FORMAT_R16_FLOAT:
755848b8605Smrg        case PIPE_FORMAT_R16G16_FLOAT:
756848b8605Smrg        case PIPE_FORMAT_R16G16B16A16_FLOAT:
757848b8605Smrg        case PIPE_FORMAT_R32_FLOAT:
758848b8605Smrg        case PIPE_FORMAT_R32G32B32A32_FLOAT:
759848b8605Smrg        case PIPE_FORMAT_R32G32B32X32_FLOAT:
760848b8605Smrg        case PIPE_FORMAT_L16_UNORM:
761848b8605Smrg        case PIPE_FORMAT_L16_SNORM:
762848b8605Smrg        case PIPE_FORMAT_L16_FLOAT:
763848b8605Smrg        case PIPE_FORMAT_L32_FLOAT:
764848b8605Smrg        case PIPE_FORMAT_I16_UNORM:
765848b8605Smrg        case PIPE_FORMAT_I16_SNORM:
766848b8605Smrg        case PIPE_FORMAT_I16_FLOAT:
767848b8605Smrg        case PIPE_FORMAT_I32_FLOAT:
768848b8605Smrg        case PIPE_FORMAT_R16G16B16X16_UNORM:
769848b8605Smrg        case PIPE_FORMAT_R16G16B16X16_SNORM:
770848b8605Smrg        case PIPE_FORMAT_R16G16B16X16_FLOAT:
771848b8605Smrg            return modifier |
772848b8605Smrg                R300_C0_SEL_R | R300_C1_SEL_G |
773848b8605Smrg                R300_C2_SEL_B | R300_C3_SEL_A;
774848b8605Smrg
775848b8605Smrg        /* LA outputs. */
776848b8605Smrg        case PIPE_FORMAT_L16A16_UNORM:
777848b8605Smrg        case PIPE_FORMAT_L16A16_SNORM:
778848b8605Smrg        case PIPE_FORMAT_L16A16_FLOAT:
779848b8605Smrg        case PIPE_FORMAT_R16A16_UNORM:
780848b8605Smrg        case PIPE_FORMAT_R16A16_SNORM:
781848b8605Smrg        case PIPE_FORMAT_R16A16_FLOAT:
782848b8605Smrg        case PIPE_FORMAT_L32A32_FLOAT:
783848b8605Smrg        case PIPE_FORMAT_R32A32_FLOAT:
784848b8605Smrg            return modifier |
785848b8605Smrg                R300_C0_SEL_R | R300_C1_SEL_A;
786848b8605Smrg
787848b8605Smrg        default:
788848b8605Smrg            return ~0; /* Unsupported. */
789848b8605Smrg    }
790848b8605Smrg}
791848b8605Smrg
792848b8605Smrgstatic uint32_t r300_translate_colormask_swizzle(enum pipe_format format)
793848b8605Smrg{
794b8e80941Smrg    format = r300_unbyteswap_array_format(format);
795b8e80941Smrg
796848b8605Smrg    switch (format) {
797848b8605Smrg    case PIPE_FORMAT_A8_UNORM:
798848b8605Smrg    case PIPE_FORMAT_A8_SNORM:
799848b8605Smrg    case PIPE_FORMAT_A16_UNORM:
800848b8605Smrg    case PIPE_FORMAT_A16_SNORM:
801848b8605Smrg    case PIPE_FORMAT_A16_FLOAT:
802848b8605Smrg    case PIPE_FORMAT_A32_FLOAT:
803848b8605Smrg        return COLORMASK_AAAA;
804848b8605Smrg
805848b8605Smrg    case PIPE_FORMAT_I8_UNORM:
806848b8605Smrg    case PIPE_FORMAT_I8_SNORM:
807848b8605Smrg    case PIPE_FORMAT_L8_UNORM:
808848b8605Smrg    case PIPE_FORMAT_L8_SNORM:
809848b8605Smrg    case PIPE_FORMAT_R8_UNORM:
810848b8605Smrg    case PIPE_FORMAT_R8_SNORM:
811848b8605Smrg    case PIPE_FORMAT_R32_FLOAT:
812848b8605Smrg    case PIPE_FORMAT_L32_FLOAT:
813848b8605Smrg    case PIPE_FORMAT_I32_FLOAT:
814848b8605Smrg        return COLORMASK_RRRR;
815848b8605Smrg
816848b8605Smrg    case PIPE_FORMAT_L8A8_SNORM:
817848b8605Smrg    case PIPE_FORMAT_L8A8_UNORM:
818848b8605Smrg    case PIPE_FORMAT_R8A8_UNORM:
819848b8605Smrg    case PIPE_FORMAT_R8A8_SNORM:
820848b8605Smrg    case PIPE_FORMAT_L16A16_UNORM:
821848b8605Smrg    case PIPE_FORMAT_L16A16_SNORM:
822848b8605Smrg    case PIPE_FORMAT_L16A16_FLOAT:
823848b8605Smrg    case PIPE_FORMAT_R16A16_UNORM:
824848b8605Smrg    case PIPE_FORMAT_R16A16_SNORM:
825848b8605Smrg    case PIPE_FORMAT_R16A16_FLOAT:
826848b8605Smrg    case PIPE_FORMAT_L32A32_FLOAT:
827848b8605Smrg    case PIPE_FORMAT_R32A32_FLOAT:
828848b8605Smrg        return COLORMASK_ARRA;
829848b8605Smrg
830848b8605Smrg    case PIPE_FORMAT_R8G8_SNORM:
831848b8605Smrg    case PIPE_FORMAT_R8G8_UNORM:
832848b8605Smrg    case PIPE_FORMAT_R16G16_UNORM:
833848b8605Smrg    case PIPE_FORMAT_R16G16_SNORM:
834848b8605Smrg    case PIPE_FORMAT_R16G16_FLOAT:
835848b8605Smrg    case PIPE_FORMAT_R32G32_FLOAT:
836848b8605Smrg        return COLORMASK_GRRG;
837848b8605Smrg
838848b8605Smrg    case PIPE_FORMAT_B5G5R5X1_UNORM:
839848b8605Smrg    case PIPE_FORMAT_B4G4R4X4_UNORM:
840848b8605Smrg    case PIPE_FORMAT_B8G8R8X8_UNORM:
841848b8605Smrg    /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/
842848b8605Smrg    case PIPE_FORMAT_B10G10R10X2_UNORM:
843848b8605Smrg        return COLORMASK_BGRX;
844848b8605Smrg
845848b8605Smrg    case PIPE_FORMAT_B5G6R5_UNORM:
846848b8605Smrg    case PIPE_FORMAT_B5G5R5A1_UNORM:
847848b8605Smrg    case PIPE_FORMAT_B4G4R4A4_UNORM:
848848b8605Smrg    case PIPE_FORMAT_B8G8R8A8_UNORM:
849848b8605Smrg    /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/
850848b8605Smrg    case PIPE_FORMAT_B10G10R10A2_UNORM:
851848b8605Smrg        return COLORMASK_BGRA;
852848b8605Smrg
853848b8605Smrg    case PIPE_FORMAT_R8G8B8X8_UNORM:
854848b8605Smrg    /* RGBX_SNORM formats are broken for an unknown reason */
855848b8605Smrg    /*case PIPE_FORMAT_R8G8B8X8_SNORM:*/
856848b8605Smrg    /*case PIPE_FORMAT_R10G10B10X2_SNORM:*/
857848b8605Smrg    case PIPE_FORMAT_R16G16B16X16_UNORM:
858848b8605Smrg    /*case PIPE_FORMAT_R16G16B16X16_SNORM:*/
859848b8605Smrg    case PIPE_FORMAT_R16G16B16X16_FLOAT:
860848b8605Smrg    case PIPE_FORMAT_R32G32B32X32_FLOAT:
861848b8605Smrg        return COLORMASK_RGBX;
862848b8605Smrg
863848b8605Smrg    case PIPE_FORMAT_R8G8B8A8_UNORM:
864848b8605Smrg    case PIPE_FORMAT_R8G8B8A8_SNORM:
865848b8605Smrg    case PIPE_FORMAT_R10G10B10A2_UNORM:
866848b8605Smrg    case PIPE_FORMAT_R16_UNORM:
867848b8605Smrg    case PIPE_FORMAT_R16G16B16A16_UNORM:
868848b8605Smrg    case PIPE_FORMAT_R16_SNORM:
869848b8605Smrg    case PIPE_FORMAT_R16G16B16A16_SNORM:
870848b8605Smrg    case PIPE_FORMAT_R16_FLOAT:
871848b8605Smrg    case PIPE_FORMAT_R16G16B16A16_FLOAT:
872848b8605Smrg    case PIPE_FORMAT_R32G32B32A32_FLOAT:
873848b8605Smrg    case PIPE_FORMAT_L16_UNORM:
874848b8605Smrg    case PIPE_FORMAT_L16_SNORM:
875848b8605Smrg    case PIPE_FORMAT_L16_FLOAT:
876848b8605Smrg    case PIPE_FORMAT_I16_UNORM:
877848b8605Smrg    case PIPE_FORMAT_I16_SNORM:
878848b8605Smrg    case PIPE_FORMAT_I16_FLOAT:
879848b8605Smrg        return COLORMASK_RGBA;
880848b8605Smrg
881848b8605Smrg    default:
882848b8605Smrg        return ~0; /* Unsupported. */
883848b8605Smrg    }
884848b8605Smrg}
885848b8605Smrg
886848b8605Smrgboolean r300_is_colorbuffer_format_supported(enum pipe_format format)
887848b8605Smrg{
888848b8605Smrg    return r300_translate_colorformat(format) != ~0 &&
889848b8605Smrg           r300_translate_out_fmt(format) != ~0 &&
890848b8605Smrg           r300_translate_colormask_swizzle(format) != ~0;
891848b8605Smrg}
892848b8605Smrg
893848b8605Smrgboolean r300_is_zs_format_supported(enum pipe_format format)
894848b8605Smrg{
895848b8605Smrg    return r300_translate_zsformat(format) != ~0;
896848b8605Smrg}
897848b8605Smrg
898848b8605Smrgboolean r300_is_sampler_format_supported(enum pipe_format format)
899848b8605Smrg{
900848b8605Smrg    return r300_translate_texformat(format, 0, TRUE, FALSE) != ~0;
901848b8605Smrg}
902848b8605Smrg
903848b8605Smrgvoid r300_texture_setup_format_state(struct r300_screen *screen,
904848b8605Smrg                                     struct r300_resource *tex,
905848b8605Smrg                                     enum pipe_format format,
906848b8605Smrg                                     unsigned level,
907848b8605Smrg                                     unsigned width0_override,
908848b8605Smrg                                     unsigned height0_override,
909848b8605Smrg                                     struct r300_texture_format_state *out)
910848b8605Smrg{
911848b8605Smrg    struct pipe_resource *pt = &tex->b.b;
912848b8605Smrg    struct r300_texture_desc *desc = &tex->tex;
913848b8605Smrg    boolean is_r500 = screen->caps.is_r500;
914848b8605Smrg    unsigned width, height, depth;
915848b8605Smrg    unsigned txwidth, txheight, txdepth;
916848b8605Smrg
917848b8605Smrg    width = u_minify(width0_override, level);
918848b8605Smrg    height = u_minify(height0_override, level);
919848b8605Smrg    depth = u_minify(desc->depth0, level);
920848b8605Smrg
921848b8605Smrg    txwidth = (width - 1) & 0x7ff;
922848b8605Smrg    txheight = (height - 1) & 0x7ff;
923848b8605Smrg    txdepth = util_logbase2(depth) & 0xf;
924848b8605Smrg
925848b8605Smrg    /* Mask out all the fields we change. */
926848b8605Smrg    out->format0 = 0;
927848b8605Smrg    out->format1 &= ~R300_TX_FORMAT_TEX_COORD_TYPE_MASK;
928848b8605Smrg    out->format2 &= R500_TXFORMAT_MSB;
929848b8605Smrg    out->tile_config = 0;
930848b8605Smrg
931848b8605Smrg    /* Set sampler state. */
932848b8605Smrg    out->format0 =
933848b8605Smrg        R300_TX_WIDTH(txwidth) |
934848b8605Smrg        R300_TX_HEIGHT(txheight) |
935848b8605Smrg        R300_TX_DEPTH(txdepth);
936848b8605Smrg
937848b8605Smrg    if (desc->uses_stride_addressing) {
938848b8605Smrg        unsigned stride =
939848b8605Smrg            r300_stride_to_width(format, desc->stride_in_bytes[level]);
940848b8605Smrg        /* rectangles love this */
941848b8605Smrg        out->format0 |= R300_TX_PITCH_EN;
942848b8605Smrg        out->format2 = (stride - 1) & 0x1fff;
943848b8605Smrg    }
944848b8605Smrg
945848b8605Smrg    if (pt->target == PIPE_TEXTURE_CUBE) {
946848b8605Smrg        out->format1 |= R300_TX_FORMAT_CUBIC_MAP;
947848b8605Smrg    }
948848b8605Smrg    if (pt->target == PIPE_TEXTURE_3D) {
949848b8605Smrg        out->format1 |= R300_TX_FORMAT_3D;
950848b8605Smrg    }
951848b8605Smrg
952848b8605Smrg    /* large textures on r500 */
953848b8605Smrg    if (is_r500)
954848b8605Smrg    {
955848b8605Smrg        unsigned us_width = txwidth;
956848b8605Smrg        unsigned us_height = txheight;
957848b8605Smrg        unsigned us_depth = txdepth;
958848b8605Smrg
959848b8605Smrg        if (width > 2048) {
960848b8605Smrg            out->format2 |= R500_TXWIDTH_BIT11;
961848b8605Smrg        }
962848b8605Smrg        if (height > 2048) {
963848b8605Smrg            out->format2 |= R500_TXHEIGHT_BIT11;
964848b8605Smrg        }
965848b8605Smrg
966848b8605Smrg        /* The US_FORMAT register fixes an R500 TX addressing bug.
967848b8605Smrg         * Don't ask why it must be set like this. I don't know it either. */
968848b8605Smrg        if (width > 2048) {
969848b8605Smrg            us_width = (0x000007FF + us_width) >> 1;
970848b8605Smrg            us_depth |= 0x0000000D;
971848b8605Smrg        }
972848b8605Smrg        if (height > 2048) {
973848b8605Smrg            us_height = (0x000007FF + us_height) >> 1;
974848b8605Smrg            us_depth |= 0x0000000E;
975848b8605Smrg        }
976848b8605Smrg
977848b8605Smrg        out->us_format0 =
978848b8605Smrg            R300_TX_WIDTH(us_width) |
979848b8605Smrg            R300_TX_HEIGHT(us_height) |
980848b8605Smrg            R300_TX_DEPTH(us_depth);
981848b8605Smrg    }
982848b8605Smrg
983848b8605Smrg    out->tile_config = R300_TXO_MACRO_TILE(desc->macrotile[level]) |
984b8e80941Smrg                       R300_TXO_MICRO_TILE(desc->microtile) |
985b8e80941Smrg                       R300_TXO_ENDIAN(r300_get_endian_swap(format));
986848b8605Smrg}
987848b8605Smrg
988848b8605Smrgstatic void r300_texture_setup_fb_state(struct r300_surface *surf)
989848b8605Smrg{
990848b8605Smrg    struct r300_resource *tex = r300_resource(surf->base.texture);
991848b8605Smrg    unsigned level = surf->base.u.tex.level;
992848b8605Smrg    unsigned stride =
993848b8605Smrg      r300_stride_to_width(surf->base.format, tex->tex.stride_in_bytes[level]);
994848b8605Smrg
995848b8605Smrg    /* Set framebuffer state. */
996848b8605Smrg    if (util_format_is_depth_or_stencil(surf->base.format)) {
997848b8605Smrg        surf->pitch =
998848b8605Smrg                stride |
999848b8605Smrg                R300_DEPTHMACROTILE(tex->tex.macrotile[level]) |
1000b8e80941Smrg                R300_DEPTHMICROTILE(tex->tex.microtile) |
1001b8e80941Smrg                R300_DEPTHENDIAN(r300_get_endian_swap(surf->base.format));
1002848b8605Smrg        surf->format = r300_translate_zsformat(surf->base.format);
1003848b8605Smrg        surf->pitch_zmask = tex->tex.zmask_stride_in_pixels[level];
1004848b8605Smrg        surf->pitch_hiz = tex->tex.hiz_stride_in_pixels[level];
1005848b8605Smrg    } else {
1006b8e80941Smrg        enum pipe_format format = util_format_linear(surf->base.format);
1007b8e80941Smrg
1008848b8605Smrg        surf->pitch =
1009848b8605Smrg                stride |
1010b8e80941Smrg                r300_translate_colorformat(format) |
1011848b8605Smrg                R300_COLOR_TILE(tex->tex.macrotile[level]) |
1012b8e80941Smrg                R300_COLOR_MICROTILE(tex->tex.microtile) |
1013b8e80941Smrg                R300_COLOR_ENDIAN(r300_get_endian_swap(format));
1014b8e80941Smrg        surf->format = r300_translate_out_fmt(format);
1015848b8605Smrg        surf->colormask_swizzle =
1016b8e80941Smrg            r300_translate_colormask_swizzle(format);
1017848b8605Smrg        surf->pitch_cmask = tex->tex.cmask_stride_in_pixels;
1018848b8605Smrg    }
1019848b8605Smrg}
1020848b8605Smrg
1021848b8605Smrgstatic void r300_texture_destroy(struct pipe_screen *screen,
1022848b8605Smrg                                 struct pipe_resource* texture)
1023848b8605Smrg{
1024848b8605Smrg    struct r300_screen *rscreen = r300_screen(screen);
1025848b8605Smrg    struct r300_resource* tex = (struct r300_resource*)texture;
1026848b8605Smrg
1027848b8605Smrg    if (tex->tex.cmask_dwords) {
1028b8e80941Smrg        mtx_lock(&rscreen->cmask_mutex);
1029848b8605Smrg        if (texture == rscreen->cmask_resource) {
1030848b8605Smrg            rscreen->cmask_resource = NULL;
1031848b8605Smrg        }
1032b8e80941Smrg        mtx_unlock(&rscreen->cmask_mutex);
1033848b8605Smrg    }
1034848b8605Smrg    pb_reference(&tex->buf, NULL);
1035848b8605Smrg    FREE(tex);
1036848b8605Smrg}
1037848b8605Smrg
1038848b8605Smrgboolean r300_resource_get_handle(struct pipe_screen* screen,
1039b8e80941Smrg                                 struct pipe_context *ctx,
1040848b8605Smrg                                 struct pipe_resource *texture,
1041b8e80941Smrg                                 struct winsys_handle *whandle,
1042b8e80941Smrg                                 unsigned usage)
1043848b8605Smrg{
1044848b8605Smrg    struct radeon_winsys *rws = r300_screen(screen)->rws;
1045848b8605Smrg    struct r300_resource* tex = (struct r300_resource*)texture;
1046848b8605Smrg
1047848b8605Smrg    if (!tex) {
1048848b8605Smrg        return FALSE;
1049848b8605Smrg    }
1050848b8605Smrg
1051b8e80941Smrg    return rws->buffer_get_handle(tex->buf, tex->tex.stride_in_bytes[0],
1052b8e80941Smrg                                  0, 0, whandle);
1053848b8605Smrg}
1054848b8605Smrg
1055848b8605Smrgstatic const struct u_resource_vtbl r300_texture_vtbl =
1056848b8605Smrg{
1057848b8605Smrg    NULL,                           /* get_handle */
1058848b8605Smrg    r300_texture_destroy,           /* resource_destroy */
1059848b8605Smrg    r300_texture_transfer_map,      /* transfer_map */
1060848b8605Smrg    NULL,                           /* transfer_flush_region */
1061848b8605Smrg    r300_texture_transfer_unmap,    /* transfer_unmap */
1062848b8605Smrg};
1063848b8605Smrg
1064848b8605Smrg/* The common texture constructor. */
1065848b8605Smrgstatic struct r300_resource*
1066848b8605Smrgr300_texture_create_object(struct r300_screen *rscreen,
1067848b8605Smrg                           const struct pipe_resource *base,
1068848b8605Smrg                           enum radeon_bo_layout microtile,
1069848b8605Smrg                           enum radeon_bo_layout macrotile,
1070848b8605Smrg                           unsigned stride_in_bytes_override,
1071848b8605Smrg                           struct pb_buffer *buffer)
1072848b8605Smrg{
1073848b8605Smrg    struct radeon_winsys *rws = rscreen->rws;
1074848b8605Smrg    struct r300_resource *tex = NULL;
1075b8e80941Smrg    struct radeon_bo_metadata tiling = {};
1076848b8605Smrg
1077848b8605Smrg    tex = CALLOC_STRUCT(r300_resource);
1078848b8605Smrg    if (!tex) {
1079848b8605Smrg        goto fail;
1080848b8605Smrg    }
1081848b8605Smrg
1082848b8605Smrg    pipe_reference_init(&tex->b.b.reference, 1);
1083848b8605Smrg    tex->b.b.screen = &rscreen->screen;
1084848b8605Smrg    tex->b.b.usage = base->usage;
1085848b8605Smrg    tex->b.b.bind = base->bind;
1086848b8605Smrg    tex->b.b.flags = base->flags;
1087848b8605Smrg    tex->b.vtbl = &r300_texture_vtbl;
1088848b8605Smrg    tex->tex.microtile = microtile;
1089848b8605Smrg    tex->tex.macrotile[0] = macrotile;
1090848b8605Smrg    tex->tex.stride_in_bytes_override = stride_in_bytes_override;
1091848b8605Smrg    tex->domain = (base->flags & R300_RESOURCE_FLAG_TRANSFER ||
1092848b8605Smrg                   base->usage == PIPE_USAGE_STAGING) ? RADEON_DOMAIN_GTT :
1093848b8605Smrg                  base->nr_samples > 1 ? RADEON_DOMAIN_VRAM :
1094848b8605Smrg                                         RADEON_DOMAIN_VRAM | RADEON_DOMAIN_GTT;
1095848b8605Smrg    tex->buf = buffer;
1096848b8605Smrg
1097848b8605Smrg    r300_texture_desc_init(rscreen, tex, base);
1098848b8605Smrg
1099848b8605Smrg    /* Figure out the ideal placement for the texture.. */
1100848b8605Smrg    if (tex->domain & RADEON_DOMAIN_VRAM &&
1101848b8605Smrg        tex->tex.size_in_bytes >= rscreen->info.vram_size) {
1102848b8605Smrg        tex->domain &= ~RADEON_DOMAIN_VRAM;
1103848b8605Smrg        tex->domain |= RADEON_DOMAIN_GTT;
1104848b8605Smrg    }
1105848b8605Smrg    if (tex->domain & RADEON_DOMAIN_GTT &&
1106848b8605Smrg        tex->tex.size_in_bytes >= rscreen->info.gart_size) {
1107848b8605Smrg        tex->domain &= ~RADEON_DOMAIN_GTT;
1108848b8605Smrg    }
1109848b8605Smrg    /* Just fail if the texture is too large. */
1110848b8605Smrg    if (!tex->domain) {
1111848b8605Smrg        goto fail;
1112848b8605Smrg    }
1113848b8605Smrg
1114848b8605Smrg    /* Create the backing buffer if needed. */
1115848b8605Smrg    if (!tex->buf) {
1116b8e80941Smrg        /* Only use the first domain for allocation. Multiple domains are not allowed. */
1117b8e80941Smrg        unsigned alloc_domain =
1118b8e80941Smrg            tex->domain & RADEON_DOMAIN_VRAM ? RADEON_DOMAIN_VRAM :
1119b8e80941Smrg                                               RADEON_DOMAIN_GTT;
1120b8e80941Smrg
1121b8e80941Smrg        tex->buf = rws->buffer_create(rws, tex->tex.size_in_bytes, 2048,
1122b8e80941Smrg                                      alloc_domain,
1123b8e80941Smrg                                      RADEON_FLAG_NO_SUBALLOC |
1124b8e80941Smrg                                      /* Use the reusable pool: */
1125b8e80941Smrg                                      RADEON_FLAG_NO_INTERPROCESS_SHARING);
1126848b8605Smrg
1127848b8605Smrg        if (!tex->buf) {
1128848b8605Smrg            goto fail;
1129848b8605Smrg        }
1130848b8605Smrg    }
1131848b8605Smrg
1132848b8605Smrg    if (SCREEN_DBG_ON(rscreen, DBG_MSAA) && base->nr_samples > 1) {
1133848b8605Smrg        fprintf(stderr, "r300: %ix MSAA %s buffer created\n",
1134848b8605Smrg                base->nr_samples,
1135848b8605Smrg                util_format_is_depth_or_stencil(base->format) ? "depth" : "color");
1136848b8605Smrg    }
1137848b8605Smrg
1138b8e80941Smrg    tiling.u.legacy.microtile = tex->tex.microtile;
1139b8e80941Smrg    tiling.u.legacy.macrotile = tex->tex.macrotile[0];
1140b8e80941Smrg    tiling.u.legacy.stride = tex->tex.stride_in_bytes[0];
1141b8e80941Smrg    rws->buffer_set_metadata(tex->buf, &tiling);
1142848b8605Smrg
1143848b8605Smrg    return tex;
1144848b8605Smrg
1145848b8605Smrgfail:
1146848b8605Smrg    FREE(tex);
1147848b8605Smrg    if (buffer)
1148848b8605Smrg        pb_reference(&buffer, NULL);
1149848b8605Smrg    return NULL;
1150848b8605Smrg}
1151848b8605Smrg
1152848b8605Smrg/* Create a new texture. */
1153848b8605Smrgstruct pipe_resource *r300_texture_create(struct pipe_screen *screen,
1154848b8605Smrg                                          const struct pipe_resource *base)
1155848b8605Smrg{
1156848b8605Smrg    struct r300_screen *rscreen = r300_screen(screen);
1157848b8605Smrg    enum radeon_bo_layout microtile, macrotile;
1158848b8605Smrg
1159848b8605Smrg    if ((base->flags & R300_RESOURCE_FLAG_TRANSFER) ||
1160848b8605Smrg        (base->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_LINEAR))) {
1161848b8605Smrg        microtile = RADEON_LAYOUT_LINEAR;
1162848b8605Smrg        macrotile = RADEON_LAYOUT_LINEAR;
1163848b8605Smrg    } else {
1164848b8605Smrg        /* This will make the texture_create_function select the layout. */
1165848b8605Smrg        microtile = RADEON_LAYOUT_UNKNOWN;
1166848b8605Smrg        macrotile = RADEON_LAYOUT_UNKNOWN;
1167848b8605Smrg    }
1168848b8605Smrg
1169848b8605Smrg    return (struct pipe_resource*)
1170848b8605Smrg           r300_texture_create_object(rscreen, base, microtile, macrotile,
1171848b8605Smrg                                      0, NULL);
1172848b8605Smrg}
1173848b8605Smrg
1174848b8605Smrgstruct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen,
1175848b8605Smrg                                               const struct pipe_resource *base,
1176b8e80941Smrg                                               struct winsys_handle *whandle,
1177b8e80941Smrg                                               unsigned usage)
1178848b8605Smrg{
1179848b8605Smrg    struct r300_screen *rscreen = r300_screen(screen);
1180848b8605Smrg    struct radeon_winsys *rws = rscreen->rws;
1181848b8605Smrg    struct pb_buffer *buffer;
1182848b8605Smrg    unsigned stride;
1183b8e80941Smrg    struct radeon_bo_metadata tiling = {};
1184848b8605Smrg
1185848b8605Smrg    /* Support only 2D textures without mipmaps */
1186848b8605Smrg    if ((base->target != PIPE_TEXTURE_2D &&
1187848b8605Smrg          base->target != PIPE_TEXTURE_RECT) ||
1188848b8605Smrg        base->depth0 != 1 ||
1189848b8605Smrg        base->last_level != 0) {
1190848b8605Smrg        return NULL;
1191848b8605Smrg    }
1192848b8605Smrg
1193b8e80941Smrg    buffer = rws->buffer_from_handle(rws, whandle, 0, &stride, NULL);
1194848b8605Smrg    if (!buffer)
1195848b8605Smrg        return NULL;
1196848b8605Smrg
1197b8e80941Smrg    rws->buffer_get_metadata(buffer, &tiling);
1198848b8605Smrg
1199848b8605Smrg    /* Enforce a microtiled zbuffer. */
1200848b8605Smrg    if (util_format_is_depth_or_stencil(base->format) &&
1201b8e80941Smrg        tiling.u.legacy.microtile == RADEON_LAYOUT_LINEAR) {
1202848b8605Smrg        switch (util_format_get_blocksize(base->format)) {
1203848b8605Smrg            case 4:
1204b8e80941Smrg                tiling.u.legacy.microtile = RADEON_LAYOUT_TILED;
1205848b8605Smrg                break;
1206848b8605Smrg
1207848b8605Smrg            case 2:
1208b8e80941Smrg                tiling.u.legacy.microtile = RADEON_LAYOUT_SQUARETILED;
1209848b8605Smrg                break;
1210848b8605Smrg        }
1211848b8605Smrg    }
1212848b8605Smrg
1213848b8605Smrg    return (struct pipe_resource*)
1214b8e80941Smrg           r300_texture_create_object(rscreen, base, tiling.u.legacy.microtile, tiling.u.legacy.macrotile,
1215848b8605Smrg                                      stride, buffer);
1216848b8605Smrg}
1217848b8605Smrg
1218848b8605Smrg/* Not required to implement u_resource_vtbl, consider moving to another file:
1219848b8605Smrg */
1220848b8605Smrgstruct pipe_surface* r300_create_surface_custom(struct pipe_context * ctx,
1221848b8605Smrg                                         struct pipe_resource* texture,
1222848b8605Smrg                                         const struct pipe_surface *surf_tmpl,
1223848b8605Smrg                                         unsigned width0_override,
1224848b8605Smrg					 unsigned height0_override)
1225848b8605Smrg{
1226848b8605Smrg    struct r300_resource* tex = r300_resource(texture);
1227848b8605Smrg    struct r300_surface* surface = CALLOC_STRUCT(r300_surface);
1228848b8605Smrg    unsigned level = surf_tmpl->u.tex.level;
1229848b8605Smrg
1230848b8605Smrg    assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
1231848b8605Smrg
1232848b8605Smrg    if (surface) {
1233848b8605Smrg        uint32_t offset, tile_height;
1234848b8605Smrg
1235848b8605Smrg        pipe_reference_init(&surface->base.reference, 1);
1236848b8605Smrg        pipe_resource_reference(&surface->base.texture, texture);
1237848b8605Smrg        surface->base.context = ctx;
1238848b8605Smrg        surface->base.format = surf_tmpl->format;
1239848b8605Smrg        surface->base.width = u_minify(width0_override, level);
1240848b8605Smrg        surface->base.height = u_minify(height0_override, level);
1241848b8605Smrg        surface->base.u.tex.level = level;
1242848b8605Smrg        surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
1243848b8605Smrg        surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
1244848b8605Smrg
1245848b8605Smrg        surface->buf = tex->buf;
1246848b8605Smrg
1247848b8605Smrg        /* Prefer VRAM if there are multiple domains to choose from. */
1248848b8605Smrg        surface->domain = tex->domain;
1249848b8605Smrg        if (surface->domain & RADEON_DOMAIN_VRAM)
1250848b8605Smrg            surface->domain &= ~RADEON_DOMAIN_GTT;
1251848b8605Smrg
1252848b8605Smrg        surface->offset = r300_texture_get_offset(tex, level,
1253848b8605Smrg                                                  surf_tmpl->u.tex.first_layer);
1254848b8605Smrg        r300_texture_setup_fb_state(surface);
1255848b8605Smrg
1256848b8605Smrg        /* Parameters for the CBZB clear. */
1257848b8605Smrg        surface->cbzb_allowed = tex->tex.cbzb_allowed[level];
1258848b8605Smrg        surface->cbzb_width = align(surface->base.width, 64);
1259848b8605Smrg
1260848b8605Smrg        /* Height must be aligned to the size of a tile. */
1261848b8605Smrg        tile_height = r300_get_pixel_alignment(surface->base.format,
1262848b8605Smrg                                               tex->b.b.nr_samples,
1263848b8605Smrg                                               tex->tex.microtile,
1264848b8605Smrg                                               tex->tex.macrotile[level],
1265848b8605Smrg                                               DIM_HEIGHT, 0);
1266848b8605Smrg
1267848b8605Smrg        surface->cbzb_height = align((surface->base.height + 1) / 2,
1268848b8605Smrg                                     tile_height);
1269848b8605Smrg
1270848b8605Smrg        /* Offset must be aligned to 2K and must point at the beginning
1271848b8605Smrg         * of a scanline. */
1272848b8605Smrg        offset = surface->offset +
1273848b8605Smrg                 tex->tex.stride_in_bytes[level] * surface->cbzb_height;
1274848b8605Smrg        surface->cbzb_midpoint_offset = offset & ~2047;
1275848b8605Smrg
1276848b8605Smrg        surface->cbzb_pitch = surface->pitch & 0x1ffffc;
1277848b8605Smrg
1278848b8605Smrg        if (util_format_get_blocksizebits(surface->base.format) == 32)
1279848b8605Smrg            surface->cbzb_format = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
1280848b8605Smrg        else
1281848b8605Smrg            surface->cbzb_format = R300_DEPTHFORMAT_16BIT_INT_Z;
1282848b8605Smrg
1283848b8605Smrg        DBG(r300_context(ctx), DBG_CBZB,
1284848b8605Smrg            "CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n",
1285848b8605Smrg            surface->cbzb_allowed ? "YES" : " NO",
1286848b8605Smrg            surface->cbzb_width, surface->cbzb_height,
1287848b8605Smrg            offset & 2047,
1288848b8605Smrg            tex->tex.microtile ? "YES" : " NO",
1289848b8605Smrg            tex->tex.macrotile[level] ? "YES" : " NO");
1290848b8605Smrg    }
1291848b8605Smrg
1292848b8605Smrg    return &surface->base;
1293848b8605Smrg}
1294848b8605Smrg
1295848b8605Smrgstruct pipe_surface* r300_create_surface(struct pipe_context * ctx,
1296848b8605Smrg                                         struct pipe_resource* texture,
1297848b8605Smrg                                         const struct pipe_surface *surf_tmpl)
1298848b8605Smrg{
1299848b8605Smrg    return r300_create_surface_custom(ctx, texture, surf_tmpl,
1300848b8605Smrg                                      texture->width0,
1301848b8605Smrg                                      texture->height0);
1302848b8605Smrg}
1303848b8605Smrg
1304848b8605Smrg/* Not required to implement u_resource_vtbl, consider moving to another file:
1305848b8605Smrg */
1306848b8605Smrgvoid r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s)
1307848b8605Smrg{
1308848b8605Smrg    pipe_resource_reference(&s->texture, NULL);
1309848b8605Smrg    FREE(s);
1310848b8605Smrg}
1311