1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3bf215546Sopenharmony_ci * Copyright 2010 Marek Olšák <maraeo@gmail.com>
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci/* Always include headers in the reverse order!! ~ M. */
25bf215546Sopenharmony_ci#include "r300_texture.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "r300_context.h"
28bf215546Sopenharmony_ci#include "r300_reg.h"
29bf215546Sopenharmony_ci#include "r300_texture_desc.h"
30bf215546Sopenharmony_ci#include "r300_transfer.h"
31bf215546Sopenharmony_ci#include "r300_screen.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "util/format/u_format.h"
34bf215546Sopenharmony_ci#include "util/format/u_format_s3tc.h"
35bf215546Sopenharmony_ci#include "util/u_math.h"
36bf215546Sopenharmony_ci#include "util/u_memory.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include "pipe/p_screen.h"
39bf215546Sopenharmony_ci#include "frontend/winsys_handle.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci/* These formats are supported by swapping their bytes.
42bf215546Sopenharmony_ci * The swizzles must be set exactly like their non-swapped counterparts,
43bf215546Sopenharmony_ci * because byte-swapping is what reverses the component order, not swizzling.
44bf215546Sopenharmony_ci *
45bf215546Sopenharmony_ci * This function returns the format that must be used to program CB and TX
46bf215546Sopenharmony_ci * swizzles.
47bf215546Sopenharmony_ci */
48bf215546Sopenharmony_cistatic enum pipe_format r300_unbyteswap_array_format(enum pipe_format format)
49bf215546Sopenharmony_ci{
50bf215546Sopenharmony_ci    /* FIXME: Disabled on little endian because of a reported regression:
51bf215546Sopenharmony_ci     * https://bugs.freedesktop.org/show_bug.cgi?id=98869 */
52bf215546Sopenharmony_ci    if (PIPE_ENDIAN_NATIVE != PIPE_ENDIAN_BIG)
53bf215546Sopenharmony_ci        return format;
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci    /* Only BGRA 8888 array formats are supported for simplicity of
56bf215546Sopenharmony_ci     * the implementation. */
57bf215546Sopenharmony_ci    switch (format) {
58bf215546Sopenharmony_ci    case PIPE_FORMAT_A8R8G8B8_UNORM:
59bf215546Sopenharmony_ci        return PIPE_FORMAT_B8G8R8A8_UNORM;
60bf215546Sopenharmony_ci    case PIPE_FORMAT_A8R8G8B8_SRGB:
61bf215546Sopenharmony_ci        return PIPE_FORMAT_B8G8R8A8_SRGB;
62bf215546Sopenharmony_ci    case PIPE_FORMAT_X8R8G8B8_UNORM:
63bf215546Sopenharmony_ci        return PIPE_FORMAT_B8G8R8X8_UNORM;
64bf215546Sopenharmony_ci    case PIPE_FORMAT_X8R8G8B8_SRGB:
65bf215546Sopenharmony_ci        return PIPE_FORMAT_B8G8R8X8_SRGB;
66bf215546Sopenharmony_ci    default:
67bf215546Sopenharmony_ci        return format;
68bf215546Sopenharmony_ci    }
69bf215546Sopenharmony_ci}
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_cistatic unsigned r300_get_endian_swap(enum pipe_format format)
72bf215546Sopenharmony_ci{
73bf215546Sopenharmony_ci    const struct util_format_description *desc;
74bf215546Sopenharmony_ci    unsigned swap_size;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci    if (r300_unbyteswap_array_format(format) != format)
77bf215546Sopenharmony_ci        return R300_SURF_DWORD_SWAP;
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci    if (PIPE_ENDIAN_NATIVE != PIPE_ENDIAN_BIG)
80bf215546Sopenharmony_ci        return R300_SURF_NO_SWAP;
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci    desc = util_format_description(format);
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci    /* Compressed formats should be in the little endian format. */
85bf215546Sopenharmony_ci    if (desc->block.width != 1 || desc->block.height != 1)
86bf215546Sopenharmony_ci        return R300_SURF_NO_SWAP;
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci    swap_size = desc->is_array ? desc->channel[0].size : desc->block.bits;
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci    switch (swap_size) {
91bf215546Sopenharmony_ci    default: /* shouldn't happen? */
92bf215546Sopenharmony_ci    case 8:
93bf215546Sopenharmony_ci        return R300_SURF_NO_SWAP;
94bf215546Sopenharmony_ci    case 16:
95bf215546Sopenharmony_ci        return R300_SURF_WORD_SWAP;
96bf215546Sopenharmony_ci    case 32:
97bf215546Sopenharmony_ci        return R300_SURF_DWORD_SWAP;
98bf215546Sopenharmony_ci    }
99bf215546Sopenharmony_ci}
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ciunsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
102bf215546Sopenharmony_ci                                   const unsigned char *swizzle_view,
103bf215546Sopenharmony_ci                                   boolean dxtc_swizzle)
104bf215546Sopenharmony_ci{
105bf215546Sopenharmony_ci    unsigned i;
106bf215546Sopenharmony_ci    unsigned char swizzle[4];
107bf215546Sopenharmony_ci    unsigned result = 0;
108bf215546Sopenharmony_ci    const uint32_t swizzle_shift[4] = {
109bf215546Sopenharmony_ci        R300_TX_FORMAT_R_SHIFT,
110bf215546Sopenharmony_ci        R300_TX_FORMAT_G_SHIFT,
111bf215546Sopenharmony_ci        R300_TX_FORMAT_B_SHIFT,
112bf215546Sopenharmony_ci        R300_TX_FORMAT_A_SHIFT
113bf215546Sopenharmony_ci    };
114bf215546Sopenharmony_ci    uint32_t swizzle_bit[4] = {
115bf215546Sopenharmony_ci        dxtc_swizzle ? R300_TX_FORMAT_Z : R300_TX_FORMAT_X,
116bf215546Sopenharmony_ci        R300_TX_FORMAT_Y,
117bf215546Sopenharmony_ci        dxtc_swizzle ? R300_TX_FORMAT_X : R300_TX_FORMAT_Z,
118bf215546Sopenharmony_ci        R300_TX_FORMAT_W
119bf215546Sopenharmony_ci    };
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci    if (swizzle_view) {
122bf215546Sopenharmony_ci        /* Combine two sets of swizzles. */
123bf215546Sopenharmony_ci        util_format_compose_swizzles(swizzle_format, swizzle_view, swizzle);
124bf215546Sopenharmony_ci    } else {
125bf215546Sopenharmony_ci        memcpy(swizzle, swizzle_format, 4);
126bf215546Sopenharmony_ci    }
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci    /* Get swizzle. */
129bf215546Sopenharmony_ci    for (i = 0; i < 4; i++) {
130bf215546Sopenharmony_ci        switch (swizzle[i]) {
131bf215546Sopenharmony_ci            case PIPE_SWIZZLE_Y:
132bf215546Sopenharmony_ci                result |= swizzle_bit[1] << swizzle_shift[i];
133bf215546Sopenharmony_ci                break;
134bf215546Sopenharmony_ci            case PIPE_SWIZZLE_Z:
135bf215546Sopenharmony_ci                result |= swizzle_bit[2] << swizzle_shift[i];
136bf215546Sopenharmony_ci                break;
137bf215546Sopenharmony_ci            case PIPE_SWIZZLE_W:
138bf215546Sopenharmony_ci                result |= swizzle_bit[3] << swizzle_shift[i];
139bf215546Sopenharmony_ci                break;
140bf215546Sopenharmony_ci            case PIPE_SWIZZLE_0:
141bf215546Sopenharmony_ci                result |= R300_TX_FORMAT_ZERO << swizzle_shift[i];
142bf215546Sopenharmony_ci                break;
143bf215546Sopenharmony_ci            case PIPE_SWIZZLE_1:
144bf215546Sopenharmony_ci                result |= R300_TX_FORMAT_ONE << swizzle_shift[i];
145bf215546Sopenharmony_ci                break;
146bf215546Sopenharmony_ci            default: /* PIPE_SWIZZLE_X */
147bf215546Sopenharmony_ci                result |= swizzle_bit[0] << swizzle_shift[i];
148bf215546Sopenharmony_ci        }
149bf215546Sopenharmony_ci    }
150bf215546Sopenharmony_ci    return result;
151bf215546Sopenharmony_ci}
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci/* Translate a pipe_format into a useful texture format for sampling.
154bf215546Sopenharmony_ci *
155bf215546Sopenharmony_ci * Some special formats are translated directly using R300_EASY_TX_FORMAT,
156bf215546Sopenharmony_ci * but the majority of them is translated in a generic way, automatically
157bf215546Sopenharmony_ci * supporting all the formats hw can support.
158bf215546Sopenharmony_ci *
159bf215546Sopenharmony_ci * R300_EASY_TX_FORMAT swizzles the texture.
160bf215546Sopenharmony_ci * Note the signature of R300_EASY_TX_FORMAT:
161bf215546Sopenharmony_ci *   R300_EASY_TX_FORMAT(B, G, R, A, FORMAT);
162bf215546Sopenharmony_ci *
163bf215546Sopenharmony_ci * The FORMAT specifies how the texture sampler will treat the texture, and
164bf215546Sopenharmony_ci * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */
165bf215546Sopenharmony_ciuint32_t r300_translate_texformat(enum pipe_format format,
166bf215546Sopenharmony_ci                                  const unsigned char *swizzle_view,
167bf215546Sopenharmony_ci                                  boolean is_r500,
168bf215546Sopenharmony_ci                                  boolean dxtc_swizzle)
169bf215546Sopenharmony_ci{
170bf215546Sopenharmony_ci    uint32_t result = 0;
171bf215546Sopenharmony_ci    const struct util_format_description *desc;
172bf215546Sopenharmony_ci    unsigned i;
173bf215546Sopenharmony_ci    boolean uniform = TRUE;
174bf215546Sopenharmony_ci    const uint32_t sign_bit[4] = {
175bf215546Sopenharmony_ci        R300_TX_FORMAT_SIGNED_W,
176bf215546Sopenharmony_ci        R300_TX_FORMAT_SIGNED_Z,
177bf215546Sopenharmony_ci        R300_TX_FORMAT_SIGNED_Y,
178bf215546Sopenharmony_ci        R300_TX_FORMAT_SIGNED_X,
179bf215546Sopenharmony_ci    };
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci    format = r300_unbyteswap_array_format(format);
182bf215546Sopenharmony_ci    desc = util_format_description(format);
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci    /* Colorspace (return non-RGB formats directly). */
185bf215546Sopenharmony_ci    switch (desc->colorspace) {
186bf215546Sopenharmony_ci        /* Depth stencil formats.
187bf215546Sopenharmony_ci         * Swizzles are added in r300_merge_textures_and_samplers. */
188bf215546Sopenharmony_ci        case UTIL_FORMAT_COLORSPACE_ZS:
189bf215546Sopenharmony_ci            switch (format) {
190bf215546Sopenharmony_ci                case PIPE_FORMAT_Z16_UNORM:
191bf215546Sopenharmony_ci                    return R300_TX_FORMAT_X16;
192bf215546Sopenharmony_ci                case PIPE_FORMAT_X8Z24_UNORM:
193bf215546Sopenharmony_ci                case PIPE_FORMAT_S8_UINT_Z24_UNORM:
194bf215546Sopenharmony_ci                    if (is_r500)
195bf215546Sopenharmony_ci                        return R500_TX_FORMAT_Y8X24;
196bf215546Sopenharmony_ci                    else
197bf215546Sopenharmony_ci                        return R300_TX_FORMAT_Y16X16;
198bf215546Sopenharmony_ci                default:
199bf215546Sopenharmony_ci                    return ~0; /* Unsupported. */
200bf215546Sopenharmony_ci            }
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci        /* YUV formats. */
203bf215546Sopenharmony_ci        case UTIL_FORMAT_COLORSPACE_YUV:
204bf215546Sopenharmony_ci            result |= R300_TX_FORMAT_YUV_TO_RGB;
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci            switch (format) {
207bf215546Sopenharmony_ci                case PIPE_FORMAT_UYVY:
208bf215546Sopenharmony_ci                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result;
209bf215546Sopenharmony_ci                case PIPE_FORMAT_YUYV:
210bf215546Sopenharmony_ci                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result;
211bf215546Sopenharmony_ci                default:
212bf215546Sopenharmony_ci                    return ~0; /* Unsupported/unknown. */
213bf215546Sopenharmony_ci            }
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci        /* Add gamma correction. */
216bf215546Sopenharmony_ci        case UTIL_FORMAT_COLORSPACE_SRGB:
217bf215546Sopenharmony_ci            result |= R300_TX_FORMAT_GAMMA;
218bf215546Sopenharmony_ci            break;
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci        default:
221bf215546Sopenharmony_ci            switch (format) {
222bf215546Sopenharmony_ci                /* Same as YUV but without the YUR->RGB conversion. */
223bf215546Sopenharmony_ci                case PIPE_FORMAT_R8G8_B8G8_UNORM:
224bf215546Sopenharmony_ci                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result;
225bf215546Sopenharmony_ci                case PIPE_FORMAT_G8R8_G8B8_UNORM:
226bf215546Sopenharmony_ci                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result;
227bf215546Sopenharmony_ci                default:;
228bf215546Sopenharmony_ci            }
229bf215546Sopenharmony_ci    }
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci    /* Add swizzling. */
232bf215546Sopenharmony_ci    /* The RGTC1_SNORM and LATC1_SNORM swizzle is done in the shader. */
233bf215546Sopenharmony_ci    if (util_format_is_compressed(format) &&
234bf215546Sopenharmony_ci        dxtc_swizzle &&
235bf215546Sopenharmony_ci        format != PIPE_FORMAT_RGTC2_UNORM &&
236bf215546Sopenharmony_ci        format != PIPE_FORMAT_RGTC2_SNORM &&
237bf215546Sopenharmony_ci        format != PIPE_FORMAT_LATC2_UNORM &&
238bf215546Sopenharmony_ci        format != PIPE_FORMAT_LATC2_SNORM &&
239bf215546Sopenharmony_ci        format != PIPE_FORMAT_RGTC1_UNORM &&
240bf215546Sopenharmony_ci        format != PIPE_FORMAT_RGTC1_SNORM &&
241bf215546Sopenharmony_ci        format != PIPE_FORMAT_LATC1_UNORM &&
242bf215546Sopenharmony_ci        format != PIPE_FORMAT_LATC1_SNORM) {
243bf215546Sopenharmony_ci        result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,
244bf215546Sopenharmony_ci                                            TRUE);
245bf215546Sopenharmony_ci    } else {
246bf215546Sopenharmony_ci        result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view,
247bf215546Sopenharmony_ci                                            FALSE);
248bf215546Sopenharmony_ci    }
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci    /* S3TC formats. */
251bf215546Sopenharmony_ci    if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
252bf215546Sopenharmony_ci        switch (format) {
253bf215546Sopenharmony_ci            case PIPE_FORMAT_DXT1_RGB:
254bf215546Sopenharmony_ci            case PIPE_FORMAT_DXT1_RGBA:
255bf215546Sopenharmony_ci            case PIPE_FORMAT_DXT1_SRGB:
256bf215546Sopenharmony_ci            case PIPE_FORMAT_DXT1_SRGBA:
257bf215546Sopenharmony_ci                return R300_TX_FORMAT_DXT1 | result;
258bf215546Sopenharmony_ci            case PIPE_FORMAT_DXT3_RGBA:
259bf215546Sopenharmony_ci            case PIPE_FORMAT_DXT3_SRGBA:
260bf215546Sopenharmony_ci                return R300_TX_FORMAT_DXT3 | result;
261bf215546Sopenharmony_ci            case PIPE_FORMAT_DXT5_RGBA:
262bf215546Sopenharmony_ci            case PIPE_FORMAT_DXT5_SRGBA:
263bf215546Sopenharmony_ci                return R300_TX_FORMAT_DXT5 | result;
264bf215546Sopenharmony_ci            default:
265bf215546Sopenharmony_ci                return ~0; /* Unsupported/unknown. */
266bf215546Sopenharmony_ci        }
267bf215546Sopenharmony_ci    }
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci    /* RGTC formats. */
270bf215546Sopenharmony_ci    if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
271bf215546Sopenharmony_ci        switch (format) {
272bf215546Sopenharmony_ci            case PIPE_FORMAT_RGTC1_SNORM:
273bf215546Sopenharmony_ci            case PIPE_FORMAT_LATC1_SNORM:
274bf215546Sopenharmony_ci                result |= sign_bit[0];
275bf215546Sopenharmony_ci                FALLTHROUGH;
276bf215546Sopenharmony_ci            case PIPE_FORMAT_LATC1_UNORM:
277bf215546Sopenharmony_ci            case PIPE_FORMAT_RGTC1_UNORM:
278bf215546Sopenharmony_ci                return R500_TX_FORMAT_ATI1N | result;
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci            case PIPE_FORMAT_RGTC2_SNORM:
281bf215546Sopenharmony_ci            case PIPE_FORMAT_LATC2_SNORM:
282bf215546Sopenharmony_ci                result |= sign_bit[1] | sign_bit[0];
283bf215546Sopenharmony_ci                FALLTHROUGH;
284bf215546Sopenharmony_ci            case PIPE_FORMAT_RGTC2_UNORM:
285bf215546Sopenharmony_ci            case PIPE_FORMAT_LATC2_UNORM:
286bf215546Sopenharmony_ci                return R400_TX_FORMAT_ATI2N | result;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci            default:
289bf215546Sopenharmony_ci                return ~0; /* Unsupported/unknown. */
290bf215546Sopenharmony_ci        }
291bf215546Sopenharmony_ci    }
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci    /* This is truly a special format.
294bf215546Sopenharmony_ci     * It stores R8G8 and B is computed using sqrt(1 - R^2 - G^2)
295bf215546Sopenharmony_ci     * in the sampler unit. Also known as D3DFMT_CxV8U8. */
296bf215546Sopenharmony_ci    if (format == PIPE_FORMAT_R8G8Bx_SNORM) {
297bf215546Sopenharmony_ci        return R300_TX_FORMAT_CxV8U8 | result;
298bf215546Sopenharmony_ci    }
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci    /* Integer and fixed-point 16.16 textures are not supported. */
301bf215546Sopenharmony_ci    for (i = 0; i < 4; i++) {
302bf215546Sopenharmony_ci        if (desc->channel[i].type == UTIL_FORMAT_TYPE_FIXED ||
303bf215546Sopenharmony_ci            ((desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED ||
304bf215546Sopenharmony_ci              desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) &&
305bf215546Sopenharmony_ci             (!desc->channel[i].normalized ||
306bf215546Sopenharmony_ci              desc->channel[i].pure_integer))) {
307bf215546Sopenharmony_ci            return ~0; /* Unsupported/unknown. */
308bf215546Sopenharmony_ci        }
309bf215546Sopenharmony_ci    }
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci    /* Add sign. */
312bf215546Sopenharmony_ci    for (i = 0; i < desc->nr_channels; i++) {
313bf215546Sopenharmony_ci        if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
314bf215546Sopenharmony_ci            result |= sign_bit[i];
315bf215546Sopenharmony_ci        }
316bf215546Sopenharmony_ci    }
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci    /* See whether the components are of the same size. */
319bf215546Sopenharmony_ci    for (i = 1; i < desc->nr_channels; i++) {
320bf215546Sopenharmony_ci        uniform = uniform && desc->channel[0].size == desc->channel[i].size;
321bf215546Sopenharmony_ci    }
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci    /* Non-uniform formats. */
324bf215546Sopenharmony_ci    if (!uniform) {
325bf215546Sopenharmony_ci        switch (desc->nr_channels) {
326bf215546Sopenharmony_ci            case 3:
327bf215546Sopenharmony_ci                if (desc->channel[0].size == 5 &&
328bf215546Sopenharmony_ci                    desc->channel[1].size == 6 &&
329bf215546Sopenharmony_ci                    desc->channel[2].size == 5) {
330bf215546Sopenharmony_ci                    return R300_TX_FORMAT_Z5Y6X5 | result;
331bf215546Sopenharmony_ci                }
332bf215546Sopenharmony_ci                if (desc->channel[0].size == 5 &&
333bf215546Sopenharmony_ci                    desc->channel[1].size == 5 &&
334bf215546Sopenharmony_ci                    desc->channel[2].size == 6) {
335bf215546Sopenharmony_ci                    return R300_TX_FORMAT_Z6Y5X5 | result;
336bf215546Sopenharmony_ci                }
337bf215546Sopenharmony_ci                if (desc->channel[0].size == 2 &&
338bf215546Sopenharmony_ci                    desc->channel[1].size == 3 &&
339bf215546Sopenharmony_ci                    desc->channel[2].size == 3) {
340bf215546Sopenharmony_ci                    return R300_TX_FORMAT_Z3Y3X2 | result;
341bf215546Sopenharmony_ci                }
342bf215546Sopenharmony_ci                return ~0; /* Unsupported/unknown. */
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci            case 4:
345bf215546Sopenharmony_ci                if (desc->channel[0].size == 5 &&
346bf215546Sopenharmony_ci                    desc->channel[1].size == 5 &&
347bf215546Sopenharmony_ci                    desc->channel[2].size == 5 &&
348bf215546Sopenharmony_ci                    desc->channel[3].size == 1) {
349bf215546Sopenharmony_ci                    return R300_TX_FORMAT_W1Z5Y5X5 | result;
350bf215546Sopenharmony_ci                }
351bf215546Sopenharmony_ci                if (desc->channel[0].size == 10 &&
352bf215546Sopenharmony_ci                    desc->channel[1].size == 10 &&
353bf215546Sopenharmony_ci                    desc->channel[2].size == 10 &&
354bf215546Sopenharmony_ci                    desc->channel[3].size == 2) {
355bf215546Sopenharmony_ci                    return R300_TX_FORMAT_W2Z10Y10X10 | result;
356bf215546Sopenharmony_ci                }
357bf215546Sopenharmony_ci        }
358bf215546Sopenharmony_ci        return ~0; /* Unsupported/unknown. */
359bf215546Sopenharmony_ci    }
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_ci    /* Find the first non-VOID channel. */
362bf215546Sopenharmony_ci    for (i = 0; i < 4; i++) {
363bf215546Sopenharmony_ci        if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
364bf215546Sopenharmony_ci            break;
365bf215546Sopenharmony_ci        }
366bf215546Sopenharmony_ci    }
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci    if (i == 4)
369bf215546Sopenharmony_ci        return ~0; /* Unsupported/unknown. */
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci    /* And finally, uniform formats. */
372bf215546Sopenharmony_ci    switch (desc->channel[i].type) {
373bf215546Sopenharmony_ci        case UTIL_FORMAT_TYPE_UNSIGNED:
374bf215546Sopenharmony_ci        case UTIL_FORMAT_TYPE_SIGNED:
375bf215546Sopenharmony_ci            if (!desc->channel[i].normalized &&
376bf215546Sopenharmony_ci                desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
377bf215546Sopenharmony_ci                return ~0;
378bf215546Sopenharmony_ci            }
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci            switch (desc->channel[i].size) {
381bf215546Sopenharmony_ci                case 4:
382bf215546Sopenharmony_ci                    switch (desc->nr_channels) {
383bf215546Sopenharmony_ci                        case 2:
384bf215546Sopenharmony_ci                            return R300_TX_FORMAT_Y4X4 | result;
385bf215546Sopenharmony_ci                        case 4:
386bf215546Sopenharmony_ci                            return R300_TX_FORMAT_W4Z4Y4X4 | result;
387bf215546Sopenharmony_ci                    }
388bf215546Sopenharmony_ci                    return ~0;
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci                case 8:
391bf215546Sopenharmony_ci                    switch (desc->nr_channels) {
392bf215546Sopenharmony_ci                        case 1:
393bf215546Sopenharmony_ci                            return R300_TX_FORMAT_X8 | result;
394bf215546Sopenharmony_ci                        case 2:
395bf215546Sopenharmony_ci                            return R300_TX_FORMAT_Y8X8 | result;
396bf215546Sopenharmony_ci                        case 4:
397bf215546Sopenharmony_ci                            return R300_TX_FORMAT_W8Z8Y8X8 | result;
398bf215546Sopenharmony_ci                    }
399bf215546Sopenharmony_ci                    return ~0;
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci                case 16:
402bf215546Sopenharmony_ci                    switch (desc->nr_channels) {
403bf215546Sopenharmony_ci                        case 1:
404bf215546Sopenharmony_ci                            return R300_TX_FORMAT_X16 | result;
405bf215546Sopenharmony_ci                        case 2:
406bf215546Sopenharmony_ci                            return R300_TX_FORMAT_Y16X16 | result;
407bf215546Sopenharmony_ci                        case 4:
408bf215546Sopenharmony_ci                            return R300_TX_FORMAT_W16Z16Y16X16 | result;
409bf215546Sopenharmony_ci                    }
410bf215546Sopenharmony_ci            }
411bf215546Sopenharmony_ci            return ~0;
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci        case UTIL_FORMAT_TYPE_FLOAT:
414bf215546Sopenharmony_ci            switch (desc->channel[i].size) {
415bf215546Sopenharmony_ci                case 16:
416bf215546Sopenharmony_ci                    switch (desc->nr_channels) {
417bf215546Sopenharmony_ci                        case 1:
418bf215546Sopenharmony_ci                            return R300_TX_FORMAT_16F | result;
419bf215546Sopenharmony_ci                        case 2:
420bf215546Sopenharmony_ci                            return R300_TX_FORMAT_16F_16F | result;
421bf215546Sopenharmony_ci                        case 4:
422bf215546Sopenharmony_ci                            return R300_TX_FORMAT_16F_16F_16F_16F | result;
423bf215546Sopenharmony_ci                    }
424bf215546Sopenharmony_ci                    return ~0;
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci                case 32:
427bf215546Sopenharmony_ci                    switch (desc->nr_channels) {
428bf215546Sopenharmony_ci                        case 1:
429bf215546Sopenharmony_ci                            return R300_TX_FORMAT_32F | result;
430bf215546Sopenharmony_ci                        case 2:
431bf215546Sopenharmony_ci                            return R300_TX_FORMAT_32F_32F | result;
432bf215546Sopenharmony_ci                        case 4:
433bf215546Sopenharmony_ci                            return R300_TX_FORMAT_32F_32F_32F_32F | result;
434bf215546Sopenharmony_ci                    }
435bf215546Sopenharmony_ci            }
436bf215546Sopenharmony_ci    }
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci    return ~0; /* Unsupported/unknown. */
439bf215546Sopenharmony_ci}
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ciuint32_t r500_tx_format_msb_bit(enum pipe_format format)
442bf215546Sopenharmony_ci{
443bf215546Sopenharmony_ci    switch (format) {
444bf215546Sopenharmony_ci        case PIPE_FORMAT_RGTC1_UNORM:
445bf215546Sopenharmony_ci        case PIPE_FORMAT_RGTC1_SNORM:
446bf215546Sopenharmony_ci        case PIPE_FORMAT_LATC1_UNORM:
447bf215546Sopenharmony_ci        case PIPE_FORMAT_LATC1_SNORM:
448bf215546Sopenharmony_ci        case PIPE_FORMAT_X8Z24_UNORM:
449bf215546Sopenharmony_ci        case PIPE_FORMAT_S8_UINT_Z24_UNORM:
450bf215546Sopenharmony_ci            return R500_TXFORMAT_MSB;
451bf215546Sopenharmony_ci        default:
452bf215546Sopenharmony_ci            return 0;
453bf215546Sopenharmony_ci    }
454bf215546Sopenharmony_ci}
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci/* Buffer formats. */
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci/* Colorbuffer formats. This is the unswizzled format of the RB3D block's
459bf215546Sopenharmony_ci * output. For the swizzling of the targets, check the shader's format. */
460bf215546Sopenharmony_cistatic uint32_t r300_translate_colorformat(enum pipe_format format)
461bf215546Sopenharmony_ci{
462bf215546Sopenharmony_ci    format = r300_unbyteswap_array_format(format);
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_ci    switch (format) {
465bf215546Sopenharmony_ci        /* 8-bit buffers. */
466bf215546Sopenharmony_ci        case PIPE_FORMAT_A8_UNORM:
467bf215546Sopenharmony_ci        case PIPE_FORMAT_A8_SNORM:
468bf215546Sopenharmony_ci        case PIPE_FORMAT_I8_UNORM:
469bf215546Sopenharmony_ci        case PIPE_FORMAT_I8_SNORM:
470bf215546Sopenharmony_ci        case PIPE_FORMAT_L8_UNORM:
471bf215546Sopenharmony_ci        case PIPE_FORMAT_L8_SNORM:
472bf215546Sopenharmony_ci        case PIPE_FORMAT_R8_UNORM:
473bf215546Sopenharmony_ci        case PIPE_FORMAT_R8_SNORM:
474bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_I8;
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_ci        /* 16-bit buffers. */
477bf215546Sopenharmony_ci        case PIPE_FORMAT_L8A8_UNORM:
478bf215546Sopenharmony_ci        case PIPE_FORMAT_L8A8_SNORM:
479bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8_UNORM:
480bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8_SNORM:
481bf215546Sopenharmony_ci        case PIPE_FORMAT_R8A8_UNORM:
482bf215546Sopenharmony_ci        case PIPE_FORMAT_R8A8_SNORM:
483bf215546Sopenharmony_ci        /* These formats work fine with UV88 if US_OUT_FMT is set correctly. */
484bf215546Sopenharmony_ci        case PIPE_FORMAT_A16_UNORM:
485bf215546Sopenharmony_ci        case PIPE_FORMAT_A16_SNORM:
486bf215546Sopenharmony_ci        case PIPE_FORMAT_A16_FLOAT:
487bf215546Sopenharmony_ci        case PIPE_FORMAT_L16_UNORM:
488bf215546Sopenharmony_ci        case PIPE_FORMAT_L16_SNORM:
489bf215546Sopenharmony_ci        case PIPE_FORMAT_L16_FLOAT:
490bf215546Sopenharmony_ci        case PIPE_FORMAT_I16_UNORM:
491bf215546Sopenharmony_ci        case PIPE_FORMAT_I16_SNORM:
492bf215546Sopenharmony_ci        case PIPE_FORMAT_I16_FLOAT:
493bf215546Sopenharmony_ci        case PIPE_FORMAT_R16_UNORM:
494bf215546Sopenharmony_ci        case PIPE_FORMAT_R16_SNORM:
495bf215546Sopenharmony_ci        case PIPE_FORMAT_R16_FLOAT:
496bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_UV88;
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci        case PIPE_FORMAT_B5G6R5_UNORM:
499bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_RGB565;
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci        case PIPE_FORMAT_B5G5R5A1_UNORM:
502bf215546Sopenharmony_ci        case PIPE_FORMAT_B5G5R5X1_UNORM:
503bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_ARGB1555;
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_ci        case PIPE_FORMAT_B4G4R4A4_UNORM:
506bf215546Sopenharmony_ci        case PIPE_FORMAT_B4G4R4X4_UNORM:
507bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_ARGB4444;
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci        /* 32-bit buffers. */
510bf215546Sopenharmony_ci        case PIPE_FORMAT_B8G8R8A8_UNORM:
511bf215546Sopenharmony_ci        /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/
512bf215546Sopenharmony_ci        case PIPE_FORMAT_B8G8R8X8_UNORM:
513bf215546Sopenharmony_ci        /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/
514bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8B8A8_UNORM:
515bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8B8A8_SNORM:
516bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8B8X8_UNORM:
517bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8B8X8_SNORM:
518bf215546Sopenharmony_ci        /* These formats work fine with ARGB8888 if US_OUT_FMT is set
519bf215546Sopenharmony_ci         * correctly. */
520bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16_UNORM:
521bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16_SNORM:
522bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16_FLOAT:
523bf215546Sopenharmony_ci        case PIPE_FORMAT_L16A16_UNORM:
524bf215546Sopenharmony_ci        case PIPE_FORMAT_L16A16_SNORM:
525bf215546Sopenharmony_ci        case PIPE_FORMAT_L16A16_FLOAT:
526bf215546Sopenharmony_ci        case PIPE_FORMAT_R16A16_UNORM:
527bf215546Sopenharmony_ci        case PIPE_FORMAT_R16A16_SNORM:
528bf215546Sopenharmony_ci        case PIPE_FORMAT_R16A16_FLOAT:
529bf215546Sopenharmony_ci        case PIPE_FORMAT_A32_FLOAT:
530bf215546Sopenharmony_ci        case PIPE_FORMAT_L32_FLOAT:
531bf215546Sopenharmony_ci        case PIPE_FORMAT_I32_FLOAT:
532bf215546Sopenharmony_ci        case PIPE_FORMAT_R32_FLOAT:
533bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_ARGB8888;
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_ci        case PIPE_FORMAT_R10G10B10A2_UNORM:
536bf215546Sopenharmony_ci        case PIPE_FORMAT_R10G10B10X2_SNORM:
537bf215546Sopenharmony_ci        case PIPE_FORMAT_B10G10R10A2_UNORM:
538bf215546Sopenharmony_ci        case PIPE_FORMAT_B10G10R10X2_UNORM:
539bf215546Sopenharmony_ci            return R500_COLOR_FORMAT_ARGB2101010;  /* R5xx-only? */
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci        /* 64-bit buffers. */
542bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16A16_UNORM:
543bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16A16_SNORM:
544bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16A16_FLOAT:
545bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16X16_UNORM:
546bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16X16_SNORM:
547bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16X16_FLOAT:
548bf215546Sopenharmony_ci        /* These formats work fine with ARGB16161616 if US_OUT_FMT is set
549bf215546Sopenharmony_ci         * correctly. */
550bf215546Sopenharmony_ci        case PIPE_FORMAT_R32G32_FLOAT:
551bf215546Sopenharmony_ci        case PIPE_FORMAT_L32A32_FLOAT:
552bf215546Sopenharmony_ci        case PIPE_FORMAT_R32A32_FLOAT:
553bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_ARGB16161616;
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci        /* 128-bit buffers. */
556bf215546Sopenharmony_ci        case PIPE_FORMAT_R32G32B32A32_FLOAT:
557bf215546Sopenharmony_ci        case PIPE_FORMAT_R32G32B32X32_FLOAT:
558bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_ARGB32323232;
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ci        /* YUV buffers. */
561bf215546Sopenharmony_ci        case PIPE_FORMAT_UYVY:
562bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_YVYU;
563bf215546Sopenharmony_ci        case PIPE_FORMAT_YUYV:
564bf215546Sopenharmony_ci            return R300_COLOR_FORMAT_VYUY;
565bf215546Sopenharmony_ci        default:
566bf215546Sopenharmony_ci            return ~0; /* Unsupported. */
567bf215546Sopenharmony_ci    }
568bf215546Sopenharmony_ci}
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_ci/* Depthbuffer and stencilbuffer. Thankfully, we only support two flavors. */
571bf215546Sopenharmony_cistatic uint32_t r300_translate_zsformat(enum pipe_format format)
572bf215546Sopenharmony_ci{
573bf215546Sopenharmony_ci    switch (format) {
574bf215546Sopenharmony_ci        /* 16-bit depth, no stencil */
575bf215546Sopenharmony_ci        case PIPE_FORMAT_Z16_UNORM:
576bf215546Sopenharmony_ci            return R300_DEPTHFORMAT_16BIT_INT_Z;
577bf215546Sopenharmony_ci        /* 24-bit depth, ignored stencil */
578bf215546Sopenharmony_ci        case PIPE_FORMAT_X8Z24_UNORM:
579bf215546Sopenharmony_ci        /* 24-bit depth, 8-bit stencil */
580bf215546Sopenharmony_ci        case PIPE_FORMAT_S8_UINT_Z24_UNORM:
581bf215546Sopenharmony_ci            return R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
582bf215546Sopenharmony_ci        default:
583bf215546Sopenharmony_ci            return ~0; /* Unsupported. */
584bf215546Sopenharmony_ci    }
585bf215546Sopenharmony_ci}
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci/* Shader output formats. This is essentially the swizzle from the shader
588bf215546Sopenharmony_ci * to the RB3D block.
589bf215546Sopenharmony_ci *
590bf215546Sopenharmony_ci * Note that formats are stored from C3 to C0. */
591bf215546Sopenharmony_cistatic uint32_t r300_translate_out_fmt(enum pipe_format format)
592bf215546Sopenharmony_ci{
593bf215546Sopenharmony_ci    uint32_t modifier = 0;
594bf215546Sopenharmony_ci    unsigned i;
595bf215546Sopenharmony_ci    const struct util_format_description *desc;
596bf215546Sopenharmony_ci    boolean uniform_sign;
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci    format = r300_unbyteswap_array_format(format);
599bf215546Sopenharmony_ci    desc = util_format_description(format);
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci    /* Find the first non-VOID channel. */
602bf215546Sopenharmony_ci    for (i = 0; i < 4; i++) {
603bf215546Sopenharmony_ci        if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
604bf215546Sopenharmony_ci            break;
605bf215546Sopenharmony_ci        }
606bf215546Sopenharmony_ci    }
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci    if (i == 4)
609bf215546Sopenharmony_ci        return ~0; /* Unsupported/unknown. */
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci    /* Specifies how the shader output is written to the fog unit. */
612bf215546Sopenharmony_ci    switch (desc->channel[i].type) {
613bf215546Sopenharmony_ci    case UTIL_FORMAT_TYPE_FLOAT:
614bf215546Sopenharmony_ci        switch (desc->channel[i].size) {
615bf215546Sopenharmony_ci        case 32:
616bf215546Sopenharmony_ci            switch (desc->nr_channels) {
617bf215546Sopenharmony_ci            case 1:
618bf215546Sopenharmony_ci                modifier |= R300_US_OUT_FMT_C_32_FP;
619bf215546Sopenharmony_ci                break;
620bf215546Sopenharmony_ci            case 2:
621bf215546Sopenharmony_ci                modifier |= R300_US_OUT_FMT_C2_32_FP;
622bf215546Sopenharmony_ci                break;
623bf215546Sopenharmony_ci            case 4:
624bf215546Sopenharmony_ci                modifier |= R300_US_OUT_FMT_C4_32_FP;
625bf215546Sopenharmony_ci                break;
626bf215546Sopenharmony_ci            }
627bf215546Sopenharmony_ci            break;
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_ci        case 16:
630bf215546Sopenharmony_ci            switch (desc->nr_channels) {
631bf215546Sopenharmony_ci            case 1:
632bf215546Sopenharmony_ci                modifier |= R300_US_OUT_FMT_C_16_FP;
633bf215546Sopenharmony_ci                break;
634bf215546Sopenharmony_ci            case 2:
635bf215546Sopenharmony_ci                modifier |= R300_US_OUT_FMT_C2_16_FP;
636bf215546Sopenharmony_ci                break;
637bf215546Sopenharmony_ci            case 4:
638bf215546Sopenharmony_ci                modifier |= R300_US_OUT_FMT_C4_16_FP;
639bf215546Sopenharmony_ci                break;
640bf215546Sopenharmony_ci            }
641bf215546Sopenharmony_ci            break;
642bf215546Sopenharmony_ci        }
643bf215546Sopenharmony_ci        break;
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci    default:
646bf215546Sopenharmony_ci        switch (desc->channel[i].size) {
647bf215546Sopenharmony_ci        case 16:
648bf215546Sopenharmony_ci            switch (desc->nr_channels) {
649bf215546Sopenharmony_ci            case 1:
650bf215546Sopenharmony_ci                modifier |= R300_US_OUT_FMT_C_16;
651bf215546Sopenharmony_ci                break;
652bf215546Sopenharmony_ci            case 2:
653bf215546Sopenharmony_ci                modifier |= R300_US_OUT_FMT_C2_16;
654bf215546Sopenharmony_ci                break;
655bf215546Sopenharmony_ci            case 4:
656bf215546Sopenharmony_ci                modifier |= R300_US_OUT_FMT_C4_16;
657bf215546Sopenharmony_ci                break;
658bf215546Sopenharmony_ci            }
659bf215546Sopenharmony_ci            break;
660bf215546Sopenharmony_ci
661bf215546Sopenharmony_ci        case 10:
662bf215546Sopenharmony_ci            modifier |= R300_US_OUT_FMT_C4_10;
663bf215546Sopenharmony_ci            break;
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci        default:
666bf215546Sopenharmony_ci            /* C4_8 seems to be used for the formats whose pixel size
667bf215546Sopenharmony_ci             * is <= 32 bits. */
668bf215546Sopenharmony_ci            modifier |= R300_US_OUT_FMT_C4_8;
669bf215546Sopenharmony_ci            break;
670bf215546Sopenharmony_ci        }
671bf215546Sopenharmony_ci    }
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci    /* Add sign. */
674bf215546Sopenharmony_ci    uniform_sign = TRUE;
675bf215546Sopenharmony_ci    for (i = 0; i < desc->nr_channels; i++)
676bf215546Sopenharmony_ci        if (desc->channel[i].type != UTIL_FORMAT_TYPE_SIGNED)
677bf215546Sopenharmony_ci            uniform_sign = FALSE;
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci    if (uniform_sign)
680bf215546Sopenharmony_ci        modifier |= R300_OUT_SIGN(0xf);
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci    /* Add swizzles and return. */
683bf215546Sopenharmony_ci    switch (format) {
684bf215546Sopenharmony_ci        /*** Special cases (non-standard channel mapping) ***/
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci        /* X8
687bf215546Sopenharmony_ci         * COLORFORMAT_I8 stores the Z component (C2). */
688bf215546Sopenharmony_ci        case PIPE_FORMAT_A8_UNORM:
689bf215546Sopenharmony_ci        case PIPE_FORMAT_A8_SNORM:
690bf215546Sopenharmony_ci            return modifier | R300_C2_SEL_A;
691bf215546Sopenharmony_ci        case PIPE_FORMAT_I8_UNORM:
692bf215546Sopenharmony_ci        case PIPE_FORMAT_I8_SNORM:
693bf215546Sopenharmony_ci        case PIPE_FORMAT_L8_UNORM:
694bf215546Sopenharmony_ci        case PIPE_FORMAT_L8_SNORM:
695bf215546Sopenharmony_ci        case PIPE_FORMAT_R8_UNORM:
696bf215546Sopenharmony_ci        case PIPE_FORMAT_R8_SNORM:
697bf215546Sopenharmony_ci            return modifier | R300_C2_SEL_R;
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci        /* X8Y8
700bf215546Sopenharmony_ci         * COLORFORMAT_UV88 stores ZX (C2 and C0). */
701bf215546Sopenharmony_ci        case PIPE_FORMAT_L8A8_SNORM:
702bf215546Sopenharmony_ci        case PIPE_FORMAT_L8A8_UNORM:
703bf215546Sopenharmony_ci        case PIPE_FORMAT_R8A8_SNORM:
704bf215546Sopenharmony_ci        case PIPE_FORMAT_R8A8_UNORM:
705bf215546Sopenharmony_ci            return modifier | R300_C0_SEL_A | R300_C2_SEL_R;
706bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8_SNORM:
707bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8_UNORM:
708bf215546Sopenharmony_ci            return modifier | R300_C0_SEL_G | R300_C2_SEL_R;
709bf215546Sopenharmony_ci
710bf215546Sopenharmony_ci        /* X32Y32
711bf215546Sopenharmony_ci         * ARGB16161616 stores XZ for RG32F */
712bf215546Sopenharmony_ci        case PIPE_FORMAT_R32G32_FLOAT:
713bf215546Sopenharmony_ci            return modifier | R300_C0_SEL_R | R300_C2_SEL_G;
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci        /*** Generic cases (standard channel mapping) ***/
716bf215546Sopenharmony_ci
717bf215546Sopenharmony_ci        /* BGRA outputs. */
718bf215546Sopenharmony_ci        case PIPE_FORMAT_B5G6R5_UNORM:
719bf215546Sopenharmony_ci        case PIPE_FORMAT_B5G5R5A1_UNORM:
720bf215546Sopenharmony_ci        case PIPE_FORMAT_B5G5R5X1_UNORM:
721bf215546Sopenharmony_ci        case PIPE_FORMAT_B4G4R4A4_UNORM:
722bf215546Sopenharmony_ci        case PIPE_FORMAT_B4G4R4X4_UNORM:
723bf215546Sopenharmony_ci        case PIPE_FORMAT_B8G8R8A8_UNORM:
724bf215546Sopenharmony_ci        /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/
725bf215546Sopenharmony_ci        case PIPE_FORMAT_B8G8R8X8_UNORM:
726bf215546Sopenharmony_ci        /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/
727bf215546Sopenharmony_ci        case PIPE_FORMAT_B10G10R10A2_UNORM:
728bf215546Sopenharmony_ci        case PIPE_FORMAT_B10G10R10X2_UNORM:
729bf215546Sopenharmony_ci            return modifier |
730bf215546Sopenharmony_ci                R300_C0_SEL_B | R300_C1_SEL_G |
731bf215546Sopenharmony_ci                R300_C2_SEL_R | R300_C3_SEL_A;
732bf215546Sopenharmony_ci
733bf215546Sopenharmony_ci        /* ARGB outputs. */
734bf215546Sopenharmony_ci        case PIPE_FORMAT_A16_UNORM:
735bf215546Sopenharmony_ci        case PIPE_FORMAT_A16_SNORM:
736bf215546Sopenharmony_ci        case PIPE_FORMAT_A16_FLOAT:
737bf215546Sopenharmony_ci        case PIPE_FORMAT_A32_FLOAT:
738bf215546Sopenharmony_ci            return modifier |
739bf215546Sopenharmony_ci                R300_C0_SEL_A | R300_C1_SEL_R |
740bf215546Sopenharmony_ci                R300_C2_SEL_G | R300_C3_SEL_B;
741bf215546Sopenharmony_ci
742bf215546Sopenharmony_ci        /* RGBA outputs. */
743bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8B8X8_UNORM:
744bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8B8X8_SNORM:
745bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8B8A8_UNORM:
746bf215546Sopenharmony_ci        case PIPE_FORMAT_R8G8B8A8_SNORM:
747bf215546Sopenharmony_ci        case PIPE_FORMAT_R10G10B10A2_UNORM:
748bf215546Sopenharmony_ci        case PIPE_FORMAT_R10G10B10X2_SNORM:
749bf215546Sopenharmony_ci        case PIPE_FORMAT_R16_UNORM:
750bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16_UNORM:
751bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16A16_UNORM:
752bf215546Sopenharmony_ci        case PIPE_FORMAT_R16_SNORM:
753bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16_SNORM:
754bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16A16_SNORM:
755bf215546Sopenharmony_ci        case PIPE_FORMAT_R16_FLOAT:
756bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16_FLOAT:
757bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16A16_FLOAT:
758bf215546Sopenharmony_ci        case PIPE_FORMAT_R32_FLOAT:
759bf215546Sopenharmony_ci        case PIPE_FORMAT_R32G32B32A32_FLOAT:
760bf215546Sopenharmony_ci        case PIPE_FORMAT_R32G32B32X32_FLOAT:
761bf215546Sopenharmony_ci        case PIPE_FORMAT_L16_UNORM:
762bf215546Sopenharmony_ci        case PIPE_FORMAT_L16_SNORM:
763bf215546Sopenharmony_ci        case PIPE_FORMAT_L16_FLOAT:
764bf215546Sopenharmony_ci        case PIPE_FORMAT_L32_FLOAT:
765bf215546Sopenharmony_ci        case PIPE_FORMAT_I16_UNORM:
766bf215546Sopenharmony_ci        case PIPE_FORMAT_I16_SNORM:
767bf215546Sopenharmony_ci        case PIPE_FORMAT_I16_FLOAT:
768bf215546Sopenharmony_ci        case PIPE_FORMAT_I32_FLOAT:
769bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16X16_UNORM:
770bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16X16_SNORM:
771bf215546Sopenharmony_ci        case PIPE_FORMAT_R16G16B16X16_FLOAT:
772bf215546Sopenharmony_ci            return modifier |
773bf215546Sopenharmony_ci                R300_C0_SEL_R | R300_C1_SEL_G |
774bf215546Sopenharmony_ci                R300_C2_SEL_B | R300_C3_SEL_A;
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci        /* LA outputs. */
777bf215546Sopenharmony_ci        case PIPE_FORMAT_L16A16_UNORM:
778bf215546Sopenharmony_ci        case PIPE_FORMAT_L16A16_SNORM:
779bf215546Sopenharmony_ci        case PIPE_FORMAT_L16A16_FLOAT:
780bf215546Sopenharmony_ci        case PIPE_FORMAT_R16A16_UNORM:
781bf215546Sopenharmony_ci        case PIPE_FORMAT_R16A16_SNORM:
782bf215546Sopenharmony_ci        case PIPE_FORMAT_R16A16_FLOAT:
783bf215546Sopenharmony_ci        case PIPE_FORMAT_L32A32_FLOAT:
784bf215546Sopenharmony_ci        case PIPE_FORMAT_R32A32_FLOAT:
785bf215546Sopenharmony_ci            return modifier |
786bf215546Sopenharmony_ci                R300_C0_SEL_R | R300_C1_SEL_A;
787bf215546Sopenharmony_ci
788bf215546Sopenharmony_ci        default:
789bf215546Sopenharmony_ci            return ~0; /* Unsupported. */
790bf215546Sopenharmony_ci    }
791bf215546Sopenharmony_ci}
792bf215546Sopenharmony_ci
793bf215546Sopenharmony_cistatic uint32_t r300_translate_colormask_swizzle(enum pipe_format format)
794bf215546Sopenharmony_ci{
795bf215546Sopenharmony_ci    format = r300_unbyteswap_array_format(format);
796bf215546Sopenharmony_ci
797bf215546Sopenharmony_ci    switch (format) {
798bf215546Sopenharmony_ci    case PIPE_FORMAT_A8_UNORM:
799bf215546Sopenharmony_ci    case PIPE_FORMAT_A8_SNORM:
800bf215546Sopenharmony_ci    case PIPE_FORMAT_A16_UNORM:
801bf215546Sopenharmony_ci    case PIPE_FORMAT_A16_SNORM:
802bf215546Sopenharmony_ci    case PIPE_FORMAT_A16_FLOAT:
803bf215546Sopenharmony_ci    case PIPE_FORMAT_A32_FLOAT:
804bf215546Sopenharmony_ci        return COLORMASK_AAAA;
805bf215546Sopenharmony_ci
806bf215546Sopenharmony_ci    case PIPE_FORMAT_I8_UNORM:
807bf215546Sopenharmony_ci    case PIPE_FORMAT_I8_SNORM:
808bf215546Sopenharmony_ci    case PIPE_FORMAT_L8_UNORM:
809bf215546Sopenharmony_ci    case PIPE_FORMAT_L8_SNORM:
810bf215546Sopenharmony_ci    case PIPE_FORMAT_R8_UNORM:
811bf215546Sopenharmony_ci    case PIPE_FORMAT_R8_SNORM:
812bf215546Sopenharmony_ci    case PIPE_FORMAT_R32_FLOAT:
813bf215546Sopenharmony_ci    case PIPE_FORMAT_L32_FLOAT:
814bf215546Sopenharmony_ci    case PIPE_FORMAT_I32_FLOAT:
815bf215546Sopenharmony_ci        return COLORMASK_RRRR;
816bf215546Sopenharmony_ci
817bf215546Sopenharmony_ci    case PIPE_FORMAT_L8A8_SNORM:
818bf215546Sopenharmony_ci    case PIPE_FORMAT_L8A8_UNORM:
819bf215546Sopenharmony_ci    case PIPE_FORMAT_R8A8_UNORM:
820bf215546Sopenharmony_ci    case PIPE_FORMAT_R8A8_SNORM:
821bf215546Sopenharmony_ci    case PIPE_FORMAT_L16A16_UNORM:
822bf215546Sopenharmony_ci    case PIPE_FORMAT_L16A16_SNORM:
823bf215546Sopenharmony_ci    case PIPE_FORMAT_L16A16_FLOAT:
824bf215546Sopenharmony_ci    case PIPE_FORMAT_R16A16_UNORM:
825bf215546Sopenharmony_ci    case PIPE_FORMAT_R16A16_SNORM:
826bf215546Sopenharmony_ci    case PIPE_FORMAT_R16A16_FLOAT:
827bf215546Sopenharmony_ci    case PIPE_FORMAT_L32A32_FLOAT:
828bf215546Sopenharmony_ci    case PIPE_FORMAT_R32A32_FLOAT:
829bf215546Sopenharmony_ci        return COLORMASK_ARRA;
830bf215546Sopenharmony_ci
831bf215546Sopenharmony_ci    case PIPE_FORMAT_R8G8_SNORM:
832bf215546Sopenharmony_ci    case PIPE_FORMAT_R8G8_UNORM:
833bf215546Sopenharmony_ci    case PIPE_FORMAT_R16G16_UNORM:
834bf215546Sopenharmony_ci    case PIPE_FORMAT_R16G16_SNORM:
835bf215546Sopenharmony_ci    case PIPE_FORMAT_R16G16_FLOAT:
836bf215546Sopenharmony_ci    case PIPE_FORMAT_R32G32_FLOAT:
837bf215546Sopenharmony_ci        return COLORMASK_GRRG;
838bf215546Sopenharmony_ci
839bf215546Sopenharmony_ci    case PIPE_FORMAT_B5G5R5X1_UNORM:
840bf215546Sopenharmony_ci    case PIPE_FORMAT_B4G4R4X4_UNORM:
841bf215546Sopenharmony_ci    case PIPE_FORMAT_B8G8R8X8_UNORM:
842bf215546Sopenharmony_ci    /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/
843bf215546Sopenharmony_ci    case PIPE_FORMAT_B10G10R10X2_UNORM:
844bf215546Sopenharmony_ci        return COLORMASK_BGRX;
845bf215546Sopenharmony_ci
846bf215546Sopenharmony_ci    case PIPE_FORMAT_B5G6R5_UNORM:
847bf215546Sopenharmony_ci    case PIPE_FORMAT_B5G5R5A1_UNORM:
848bf215546Sopenharmony_ci    case PIPE_FORMAT_B4G4R4A4_UNORM:
849bf215546Sopenharmony_ci    case PIPE_FORMAT_B8G8R8A8_UNORM:
850bf215546Sopenharmony_ci    /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/
851bf215546Sopenharmony_ci    case PIPE_FORMAT_B10G10R10A2_UNORM:
852bf215546Sopenharmony_ci        return COLORMASK_BGRA;
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci    case PIPE_FORMAT_R8G8B8X8_UNORM:
855bf215546Sopenharmony_ci    /* RGBX_SNORM formats are broken for an unknown reason */
856bf215546Sopenharmony_ci    /*case PIPE_FORMAT_R8G8B8X8_SNORM:*/
857bf215546Sopenharmony_ci    /*case PIPE_FORMAT_R10G10B10X2_SNORM:*/
858bf215546Sopenharmony_ci    case PIPE_FORMAT_R16G16B16X16_UNORM:
859bf215546Sopenharmony_ci    /*case PIPE_FORMAT_R16G16B16X16_SNORM:*/
860bf215546Sopenharmony_ci    case PIPE_FORMAT_R16G16B16X16_FLOAT:
861bf215546Sopenharmony_ci    case PIPE_FORMAT_R32G32B32X32_FLOAT:
862bf215546Sopenharmony_ci        return COLORMASK_RGBX;
863bf215546Sopenharmony_ci
864bf215546Sopenharmony_ci    case PIPE_FORMAT_R8G8B8A8_UNORM:
865bf215546Sopenharmony_ci    case PIPE_FORMAT_R8G8B8A8_SNORM:
866bf215546Sopenharmony_ci    case PIPE_FORMAT_R10G10B10A2_UNORM:
867bf215546Sopenharmony_ci    case PIPE_FORMAT_R16_UNORM:
868bf215546Sopenharmony_ci    case PIPE_FORMAT_R16G16B16A16_UNORM:
869bf215546Sopenharmony_ci    case PIPE_FORMAT_R16_SNORM:
870bf215546Sopenharmony_ci    case PIPE_FORMAT_R16G16B16A16_SNORM:
871bf215546Sopenharmony_ci    case PIPE_FORMAT_R16_FLOAT:
872bf215546Sopenharmony_ci    case PIPE_FORMAT_R16G16B16A16_FLOAT:
873bf215546Sopenharmony_ci    case PIPE_FORMAT_R32G32B32A32_FLOAT:
874bf215546Sopenharmony_ci    case PIPE_FORMAT_L16_UNORM:
875bf215546Sopenharmony_ci    case PIPE_FORMAT_L16_SNORM:
876bf215546Sopenharmony_ci    case PIPE_FORMAT_L16_FLOAT:
877bf215546Sopenharmony_ci    case PIPE_FORMAT_I16_UNORM:
878bf215546Sopenharmony_ci    case PIPE_FORMAT_I16_SNORM:
879bf215546Sopenharmony_ci    case PIPE_FORMAT_I16_FLOAT:
880bf215546Sopenharmony_ci        return COLORMASK_RGBA;
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci    default:
883bf215546Sopenharmony_ci        return ~0; /* Unsupported. */
884bf215546Sopenharmony_ci    }
885bf215546Sopenharmony_ci}
886bf215546Sopenharmony_ci
887bf215546Sopenharmony_ciboolean r300_is_colorbuffer_format_supported(enum pipe_format format)
888bf215546Sopenharmony_ci{
889bf215546Sopenharmony_ci    return r300_translate_colorformat(format) != ~0 &&
890bf215546Sopenharmony_ci           r300_translate_out_fmt(format) != ~0 &&
891bf215546Sopenharmony_ci           r300_translate_colormask_swizzle(format) != ~0;
892bf215546Sopenharmony_ci}
893bf215546Sopenharmony_ci
894bf215546Sopenharmony_ciboolean r300_is_zs_format_supported(enum pipe_format format)
895bf215546Sopenharmony_ci{
896bf215546Sopenharmony_ci    return r300_translate_zsformat(format) != ~0;
897bf215546Sopenharmony_ci}
898bf215546Sopenharmony_ci
899bf215546Sopenharmony_ciboolean r300_is_sampler_format_supported(enum pipe_format format)
900bf215546Sopenharmony_ci{
901bf215546Sopenharmony_ci    return r300_translate_texformat(format, NULL, TRUE, FALSE) != ~0;
902bf215546Sopenharmony_ci}
903bf215546Sopenharmony_ci
904bf215546Sopenharmony_civoid r300_texture_setup_format_state(struct r300_screen *screen,
905bf215546Sopenharmony_ci                                     struct r300_resource *tex,
906bf215546Sopenharmony_ci                                     enum pipe_format format,
907bf215546Sopenharmony_ci                                     unsigned level,
908bf215546Sopenharmony_ci                                     unsigned width0_override,
909bf215546Sopenharmony_ci                                     unsigned height0_override,
910bf215546Sopenharmony_ci                                     struct r300_texture_format_state *out)
911bf215546Sopenharmony_ci{
912bf215546Sopenharmony_ci    struct pipe_resource *pt = &tex->b;
913bf215546Sopenharmony_ci    struct r300_texture_desc *desc = &tex->tex;
914bf215546Sopenharmony_ci    boolean is_r500 = screen->caps.is_r500;
915bf215546Sopenharmony_ci    unsigned width, height, depth;
916bf215546Sopenharmony_ci    unsigned txwidth, txheight, txdepth;
917bf215546Sopenharmony_ci
918bf215546Sopenharmony_ci    width = u_minify(width0_override, level);
919bf215546Sopenharmony_ci    height = u_minify(height0_override, level);
920bf215546Sopenharmony_ci    depth = u_minify(desc->depth0, level);
921bf215546Sopenharmony_ci
922bf215546Sopenharmony_ci    txwidth = (width - 1) & 0x7ff;
923bf215546Sopenharmony_ci    txheight = (height - 1) & 0x7ff;
924bf215546Sopenharmony_ci    txdepth = util_logbase2(depth) & 0xf;
925bf215546Sopenharmony_ci
926bf215546Sopenharmony_ci    /* Mask out all the fields we change. */
927bf215546Sopenharmony_ci    out->format0 = 0;
928bf215546Sopenharmony_ci    out->format1 &= ~R300_TX_FORMAT_TEX_COORD_TYPE_MASK;
929bf215546Sopenharmony_ci    out->format2 &= R500_TXFORMAT_MSB;
930bf215546Sopenharmony_ci    out->tile_config = 0;
931bf215546Sopenharmony_ci
932bf215546Sopenharmony_ci    /* Set sampler state. */
933bf215546Sopenharmony_ci    out->format0 =
934bf215546Sopenharmony_ci        R300_TX_WIDTH(txwidth) |
935bf215546Sopenharmony_ci        R300_TX_HEIGHT(txheight) |
936bf215546Sopenharmony_ci        R300_TX_DEPTH(txdepth);
937bf215546Sopenharmony_ci
938bf215546Sopenharmony_ci    if (desc->uses_stride_addressing) {
939bf215546Sopenharmony_ci        unsigned stride =
940bf215546Sopenharmony_ci            r300_stride_to_width(format, desc->stride_in_bytes[level]);
941bf215546Sopenharmony_ci        /* rectangles love this */
942bf215546Sopenharmony_ci        out->format0 |= R300_TX_PITCH_EN;
943bf215546Sopenharmony_ci        out->format2 = (stride - 1) & 0x1fff;
944bf215546Sopenharmony_ci    }
945bf215546Sopenharmony_ci
946bf215546Sopenharmony_ci    if (pt->target == PIPE_TEXTURE_CUBE) {
947bf215546Sopenharmony_ci        out->format1 |= R300_TX_FORMAT_CUBIC_MAP;
948bf215546Sopenharmony_ci    }
949bf215546Sopenharmony_ci    if (pt->target == PIPE_TEXTURE_3D) {
950bf215546Sopenharmony_ci        out->format1 |= R300_TX_FORMAT_3D;
951bf215546Sopenharmony_ci    }
952bf215546Sopenharmony_ci
953bf215546Sopenharmony_ci    /* large textures on r500 */
954bf215546Sopenharmony_ci    if (is_r500)
955bf215546Sopenharmony_ci    {
956bf215546Sopenharmony_ci        unsigned us_width = txwidth;
957bf215546Sopenharmony_ci        unsigned us_height = txheight;
958bf215546Sopenharmony_ci        unsigned us_depth = txdepth;
959bf215546Sopenharmony_ci
960bf215546Sopenharmony_ci        if (width > 2048) {
961bf215546Sopenharmony_ci            out->format2 |= R500_TXWIDTH_BIT11;
962bf215546Sopenharmony_ci        }
963bf215546Sopenharmony_ci        if (height > 2048) {
964bf215546Sopenharmony_ci            out->format2 |= R500_TXHEIGHT_BIT11;
965bf215546Sopenharmony_ci        }
966bf215546Sopenharmony_ci
967bf215546Sopenharmony_ci        /* The US_FORMAT register fixes an R500 TX addressing bug.
968bf215546Sopenharmony_ci         * Don't ask why it must be set like this. I don't know it either. */
969bf215546Sopenharmony_ci        if (width > 2048) {
970bf215546Sopenharmony_ci            us_width = (0x000007FF + us_width) >> 1;
971bf215546Sopenharmony_ci            us_depth |= 0x0000000D;
972bf215546Sopenharmony_ci        }
973bf215546Sopenharmony_ci        if (height > 2048) {
974bf215546Sopenharmony_ci            us_height = (0x000007FF + us_height) >> 1;
975bf215546Sopenharmony_ci            us_depth |= 0x0000000E;
976bf215546Sopenharmony_ci        }
977bf215546Sopenharmony_ci
978bf215546Sopenharmony_ci        out->us_format0 =
979bf215546Sopenharmony_ci            R300_TX_WIDTH(us_width) |
980bf215546Sopenharmony_ci            R300_TX_HEIGHT(us_height) |
981bf215546Sopenharmony_ci            R300_TX_DEPTH(us_depth);
982bf215546Sopenharmony_ci    }
983bf215546Sopenharmony_ci
984bf215546Sopenharmony_ci    out->tile_config = R300_TXO_MACRO_TILE(desc->macrotile[level]) |
985bf215546Sopenharmony_ci                       R300_TXO_MICRO_TILE(desc->microtile) |
986bf215546Sopenharmony_ci                       R300_TXO_ENDIAN(r300_get_endian_swap(format));
987bf215546Sopenharmony_ci}
988bf215546Sopenharmony_ci
989bf215546Sopenharmony_cistatic void r300_texture_setup_fb_state(struct r300_surface *surf)
990bf215546Sopenharmony_ci{
991bf215546Sopenharmony_ci    struct r300_resource *tex = r300_resource(surf->base.texture);
992bf215546Sopenharmony_ci    unsigned level = surf->base.u.tex.level;
993bf215546Sopenharmony_ci    unsigned stride =
994bf215546Sopenharmony_ci      r300_stride_to_width(surf->base.format, tex->tex.stride_in_bytes[level]);
995bf215546Sopenharmony_ci
996bf215546Sopenharmony_ci    /* Set framebuffer state. */
997bf215546Sopenharmony_ci    if (util_format_is_depth_or_stencil(surf->base.format)) {
998bf215546Sopenharmony_ci        surf->pitch =
999bf215546Sopenharmony_ci                stride |
1000bf215546Sopenharmony_ci                R300_DEPTHMACROTILE(tex->tex.macrotile[level]) |
1001bf215546Sopenharmony_ci                R300_DEPTHMICROTILE(tex->tex.microtile) |
1002bf215546Sopenharmony_ci                R300_DEPTHENDIAN(r300_get_endian_swap(surf->base.format));
1003bf215546Sopenharmony_ci        surf->format = r300_translate_zsformat(surf->base.format);
1004bf215546Sopenharmony_ci        surf->pitch_zmask = tex->tex.zmask_stride_in_pixels[level];
1005bf215546Sopenharmony_ci        surf->pitch_hiz = tex->tex.hiz_stride_in_pixels[level];
1006bf215546Sopenharmony_ci    } else {
1007bf215546Sopenharmony_ci        enum pipe_format format = util_format_linear(surf->base.format);
1008bf215546Sopenharmony_ci
1009bf215546Sopenharmony_ci        surf->pitch =
1010bf215546Sopenharmony_ci                stride |
1011bf215546Sopenharmony_ci                r300_translate_colorformat(format) |
1012bf215546Sopenharmony_ci                R300_COLOR_TILE(tex->tex.macrotile[level]) |
1013bf215546Sopenharmony_ci                R300_COLOR_MICROTILE(tex->tex.microtile) |
1014bf215546Sopenharmony_ci                R300_COLOR_ENDIAN(r300_get_endian_swap(format));
1015bf215546Sopenharmony_ci        surf->format = r300_translate_out_fmt(format);
1016bf215546Sopenharmony_ci        surf->colormask_swizzle =
1017bf215546Sopenharmony_ci            r300_translate_colormask_swizzle(format);
1018bf215546Sopenharmony_ci        surf->pitch_cmask = tex->tex.cmask_stride_in_pixels;
1019bf215546Sopenharmony_ci    }
1020bf215546Sopenharmony_ci}
1021bf215546Sopenharmony_ci
1022bf215546Sopenharmony_cibool r300_resource_get_handle(struct pipe_screen* screen,
1023bf215546Sopenharmony_ci                              struct pipe_context *ctx,
1024bf215546Sopenharmony_ci                              struct pipe_resource *texture,
1025bf215546Sopenharmony_ci                              struct winsys_handle *whandle,
1026bf215546Sopenharmony_ci                              unsigned usage)
1027bf215546Sopenharmony_ci{
1028bf215546Sopenharmony_ci    struct radeon_winsys *rws = r300_screen(screen)->rws;
1029bf215546Sopenharmony_ci    struct r300_resource* tex = (struct r300_resource*)texture;
1030bf215546Sopenharmony_ci
1031bf215546Sopenharmony_ci    if (!tex) {
1032bf215546Sopenharmony_ci        return false;
1033bf215546Sopenharmony_ci    }
1034bf215546Sopenharmony_ci
1035bf215546Sopenharmony_ci    whandle->stride = tex->tex.stride_in_bytes[0];
1036bf215546Sopenharmony_ci    whandle->offset = 0;
1037bf215546Sopenharmony_ci
1038bf215546Sopenharmony_ci    return rws->buffer_get_handle(rws, tex->buf, whandle);
1039bf215546Sopenharmony_ci}
1040bf215546Sopenharmony_ci
1041bf215546Sopenharmony_ci/* The common texture constructor. */
1042bf215546Sopenharmony_cistatic struct r300_resource*
1043bf215546Sopenharmony_cir300_texture_create_object(struct r300_screen *rscreen,
1044bf215546Sopenharmony_ci                           const struct pipe_resource *base,
1045bf215546Sopenharmony_ci                           enum radeon_bo_layout microtile,
1046bf215546Sopenharmony_ci                           enum radeon_bo_layout macrotile,
1047bf215546Sopenharmony_ci                           unsigned stride_in_bytes_override,
1048bf215546Sopenharmony_ci                           struct pb_buffer *buffer)
1049bf215546Sopenharmony_ci{
1050bf215546Sopenharmony_ci    struct radeon_winsys *rws = rscreen->rws;
1051bf215546Sopenharmony_ci    struct r300_resource *tex = NULL;
1052bf215546Sopenharmony_ci    struct radeon_bo_metadata tiling = {};
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_ci    tex = CALLOC_STRUCT(r300_resource);
1055bf215546Sopenharmony_ci    if (!tex) {
1056bf215546Sopenharmony_ci        goto fail;
1057bf215546Sopenharmony_ci    }
1058bf215546Sopenharmony_ci
1059bf215546Sopenharmony_ci    pipe_reference_init(&tex->b.reference, 1);
1060bf215546Sopenharmony_ci    tex->b.screen = &rscreen->screen;
1061bf215546Sopenharmony_ci    tex->b.usage = base->usage;
1062bf215546Sopenharmony_ci    tex->b.bind = base->bind;
1063bf215546Sopenharmony_ci    tex->b.flags = base->flags;
1064bf215546Sopenharmony_ci    tex->tex.microtile = microtile;
1065bf215546Sopenharmony_ci    tex->tex.macrotile[0] = macrotile;
1066bf215546Sopenharmony_ci    tex->tex.stride_in_bytes_override = stride_in_bytes_override;
1067bf215546Sopenharmony_ci    tex->domain = (base->flags & R300_RESOURCE_FLAG_TRANSFER ||
1068bf215546Sopenharmony_ci                   base->usage == PIPE_USAGE_STAGING) ? RADEON_DOMAIN_GTT :
1069bf215546Sopenharmony_ci                  base->nr_samples > 1 ? RADEON_DOMAIN_VRAM :
1070bf215546Sopenharmony_ci                                         RADEON_DOMAIN_VRAM | RADEON_DOMAIN_GTT;
1071bf215546Sopenharmony_ci    tex->buf = buffer;
1072bf215546Sopenharmony_ci
1073bf215546Sopenharmony_ci    r300_texture_desc_init(rscreen, tex, base);
1074bf215546Sopenharmony_ci
1075bf215546Sopenharmony_ci    /* Figure out the ideal placement for the texture.. */
1076bf215546Sopenharmony_ci    if (tex->domain & RADEON_DOMAIN_VRAM &&
1077bf215546Sopenharmony_ci        tex->tex.size_in_bytes >= (uint64_t)rscreen->info.vram_size_kb * 1024) {
1078bf215546Sopenharmony_ci        tex->domain &= ~RADEON_DOMAIN_VRAM;
1079bf215546Sopenharmony_ci        tex->domain |= RADEON_DOMAIN_GTT;
1080bf215546Sopenharmony_ci    }
1081bf215546Sopenharmony_ci    if (tex->domain & RADEON_DOMAIN_GTT &&
1082bf215546Sopenharmony_ci        tex->tex.size_in_bytes >= (uint64_t)rscreen->info.gart_size_kb * 1024) {
1083bf215546Sopenharmony_ci        tex->domain &= ~RADEON_DOMAIN_GTT;
1084bf215546Sopenharmony_ci    }
1085bf215546Sopenharmony_ci    /* Just fail if the texture is too large. */
1086bf215546Sopenharmony_ci    if (!tex->domain) {
1087bf215546Sopenharmony_ci        goto fail;
1088bf215546Sopenharmony_ci    }
1089bf215546Sopenharmony_ci
1090bf215546Sopenharmony_ci    /* Create the backing buffer if needed. */
1091bf215546Sopenharmony_ci    if (!tex->buf) {
1092bf215546Sopenharmony_ci        /* Only use the first domain for allocation. Multiple domains are not allowed. */
1093bf215546Sopenharmony_ci        unsigned alloc_domain =
1094bf215546Sopenharmony_ci            tex->domain & RADEON_DOMAIN_VRAM ? RADEON_DOMAIN_VRAM :
1095bf215546Sopenharmony_ci                                               RADEON_DOMAIN_GTT;
1096bf215546Sopenharmony_ci
1097bf215546Sopenharmony_ci        tex->buf = rws->buffer_create(rws, tex->tex.size_in_bytes, 2048,
1098bf215546Sopenharmony_ci                                      alloc_domain,
1099bf215546Sopenharmony_ci                                      RADEON_FLAG_NO_SUBALLOC |
1100bf215546Sopenharmony_ci                                      /* Use the reusable pool: */
1101bf215546Sopenharmony_ci                                      RADEON_FLAG_NO_INTERPROCESS_SHARING);
1102bf215546Sopenharmony_ci
1103bf215546Sopenharmony_ci        if (!tex->buf) {
1104bf215546Sopenharmony_ci            goto fail;
1105bf215546Sopenharmony_ci        }
1106bf215546Sopenharmony_ci    }
1107bf215546Sopenharmony_ci
1108bf215546Sopenharmony_ci    if (SCREEN_DBG_ON(rscreen, DBG_MSAA) && base->nr_samples > 1) {
1109bf215546Sopenharmony_ci        fprintf(stderr, "r300: %ix MSAA %s buffer created\n",
1110bf215546Sopenharmony_ci                base->nr_samples,
1111bf215546Sopenharmony_ci                util_format_is_depth_or_stencil(base->format) ? "depth" : "color");
1112bf215546Sopenharmony_ci    }
1113bf215546Sopenharmony_ci
1114bf215546Sopenharmony_ci    tiling.u.legacy.microtile = tex->tex.microtile;
1115bf215546Sopenharmony_ci    tiling.u.legacy.macrotile = tex->tex.macrotile[0];
1116bf215546Sopenharmony_ci    tiling.u.legacy.stride = tex->tex.stride_in_bytes[0];
1117bf215546Sopenharmony_ci    rws->buffer_set_metadata(rws, tex->buf, &tiling, NULL);
1118bf215546Sopenharmony_ci
1119bf215546Sopenharmony_ci    return tex;
1120bf215546Sopenharmony_ci
1121bf215546Sopenharmony_cifail:
1122bf215546Sopenharmony_ci    FREE(tex);
1123bf215546Sopenharmony_ci    if (buffer)
1124bf215546Sopenharmony_ci        pb_reference(&buffer, NULL);
1125bf215546Sopenharmony_ci    return NULL;
1126bf215546Sopenharmony_ci}
1127bf215546Sopenharmony_ci
1128bf215546Sopenharmony_ci/* Create a new texture. */
1129bf215546Sopenharmony_cistruct pipe_resource *r300_texture_create(struct pipe_screen *screen,
1130bf215546Sopenharmony_ci                                          const struct pipe_resource *base)
1131bf215546Sopenharmony_ci{
1132bf215546Sopenharmony_ci    struct r300_screen *rscreen = r300_screen(screen);
1133bf215546Sopenharmony_ci    enum radeon_bo_layout microtile, macrotile;
1134bf215546Sopenharmony_ci
1135bf215546Sopenharmony_ci    if ((base->flags & R300_RESOURCE_FLAG_TRANSFER) ||
1136bf215546Sopenharmony_ci        (base->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_LINEAR))) {
1137bf215546Sopenharmony_ci        microtile = RADEON_LAYOUT_LINEAR;
1138bf215546Sopenharmony_ci        macrotile = RADEON_LAYOUT_LINEAR;
1139bf215546Sopenharmony_ci    } else {
1140bf215546Sopenharmony_ci        /* This will make the texture_create_function select the layout. */
1141bf215546Sopenharmony_ci        microtile = RADEON_LAYOUT_UNKNOWN;
1142bf215546Sopenharmony_ci        macrotile = RADEON_LAYOUT_UNKNOWN;
1143bf215546Sopenharmony_ci    }
1144bf215546Sopenharmony_ci
1145bf215546Sopenharmony_ci    return (struct pipe_resource*)
1146bf215546Sopenharmony_ci           r300_texture_create_object(rscreen, base, microtile, macrotile,
1147bf215546Sopenharmony_ci                                      0, NULL);
1148bf215546Sopenharmony_ci}
1149bf215546Sopenharmony_ci
1150bf215546Sopenharmony_cistruct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen,
1151bf215546Sopenharmony_ci                                               const struct pipe_resource *base,
1152bf215546Sopenharmony_ci                                               struct winsys_handle *whandle,
1153bf215546Sopenharmony_ci                                               unsigned usage)
1154bf215546Sopenharmony_ci{
1155bf215546Sopenharmony_ci    struct r300_screen *rscreen = r300_screen(screen);
1156bf215546Sopenharmony_ci    struct radeon_winsys *rws = rscreen->rws;
1157bf215546Sopenharmony_ci    struct pb_buffer *buffer;
1158bf215546Sopenharmony_ci    struct radeon_bo_metadata tiling = {};
1159bf215546Sopenharmony_ci
1160bf215546Sopenharmony_ci    /* Support only 2D textures without mipmaps */
1161bf215546Sopenharmony_ci    if ((base->target != PIPE_TEXTURE_2D &&
1162bf215546Sopenharmony_ci          base->target != PIPE_TEXTURE_RECT) ||
1163bf215546Sopenharmony_ci        base->depth0 != 1 ||
1164bf215546Sopenharmony_ci        base->last_level != 0) {
1165bf215546Sopenharmony_ci        return NULL;
1166bf215546Sopenharmony_ci    }
1167bf215546Sopenharmony_ci
1168bf215546Sopenharmony_ci    buffer = rws->buffer_from_handle(rws, whandle, 0, false);
1169bf215546Sopenharmony_ci    if (!buffer)
1170bf215546Sopenharmony_ci        return NULL;
1171bf215546Sopenharmony_ci
1172bf215546Sopenharmony_ci    rws->buffer_get_metadata(rws, buffer, &tiling, NULL);
1173bf215546Sopenharmony_ci
1174bf215546Sopenharmony_ci    /* Enforce a microtiled zbuffer. */
1175bf215546Sopenharmony_ci    if (util_format_is_depth_or_stencil(base->format) &&
1176bf215546Sopenharmony_ci        tiling.u.legacy.microtile == RADEON_LAYOUT_LINEAR) {
1177bf215546Sopenharmony_ci        switch (util_format_get_blocksize(base->format)) {
1178bf215546Sopenharmony_ci            case 4:
1179bf215546Sopenharmony_ci                tiling.u.legacy.microtile = RADEON_LAYOUT_TILED;
1180bf215546Sopenharmony_ci                break;
1181bf215546Sopenharmony_ci
1182bf215546Sopenharmony_ci            case 2:
1183bf215546Sopenharmony_ci                tiling.u.legacy.microtile = RADEON_LAYOUT_SQUARETILED;
1184bf215546Sopenharmony_ci                break;
1185bf215546Sopenharmony_ci        }
1186bf215546Sopenharmony_ci    }
1187bf215546Sopenharmony_ci
1188bf215546Sopenharmony_ci    return (struct pipe_resource*)
1189bf215546Sopenharmony_ci           r300_texture_create_object(rscreen, base, tiling.u.legacy.microtile, tiling.u.legacy.macrotile,
1190bf215546Sopenharmony_ci                                      whandle->stride, buffer);
1191bf215546Sopenharmony_ci}
1192bf215546Sopenharmony_ci
1193bf215546Sopenharmony_cistruct pipe_surface* r300_create_surface_custom(struct pipe_context * ctx,
1194bf215546Sopenharmony_ci                                         struct pipe_resource* texture,
1195bf215546Sopenharmony_ci                                         const struct pipe_surface *surf_tmpl,
1196bf215546Sopenharmony_ci                                         unsigned width0_override,
1197bf215546Sopenharmony_ci					 unsigned height0_override)
1198bf215546Sopenharmony_ci{
1199bf215546Sopenharmony_ci    struct r300_resource* tex = r300_resource(texture);
1200bf215546Sopenharmony_ci    struct r300_surface* surface = CALLOC_STRUCT(r300_surface);
1201bf215546Sopenharmony_ci    unsigned level = surf_tmpl->u.tex.level;
1202bf215546Sopenharmony_ci
1203bf215546Sopenharmony_ci    assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
1204bf215546Sopenharmony_ci
1205bf215546Sopenharmony_ci    if (surface) {
1206bf215546Sopenharmony_ci        uint32_t offset, tile_height;
1207bf215546Sopenharmony_ci
1208bf215546Sopenharmony_ci        pipe_reference_init(&surface->base.reference, 1);
1209bf215546Sopenharmony_ci        pipe_resource_reference(&surface->base.texture, texture);
1210bf215546Sopenharmony_ci        surface->base.context = ctx;
1211bf215546Sopenharmony_ci        surface->base.format = surf_tmpl->format;
1212bf215546Sopenharmony_ci        surface->base.width = u_minify(width0_override, level);
1213bf215546Sopenharmony_ci        surface->base.height = u_minify(height0_override, level);
1214bf215546Sopenharmony_ci        surface->base.u.tex.level = level;
1215bf215546Sopenharmony_ci        surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
1216bf215546Sopenharmony_ci        surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
1217bf215546Sopenharmony_ci
1218bf215546Sopenharmony_ci        surface->buf = tex->buf;
1219bf215546Sopenharmony_ci
1220bf215546Sopenharmony_ci        /* Prefer VRAM if there are multiple domains to choose from. */
1221bf215546Sopenharmony_ci        surface->domain = tex->domain;
1222bf215546Sopenharmony_ci        if (surface->domain & RADEON_DOMAIN_VRAM)
1223bf215546Sopenharmony_ci            surface->domain &= ~RADEON_DOMAIN_GTT;
1224bf215546Sopenharmony_ci
1225bf215546Sopenharmony_ci        surface->offset = r300_texture_get_offset(tex, level,
1226bf215546Sopenharmony_ci                                                  surf_tmpl->u.tex.first_layer);
1227bf215546Sopenharmony_ci        r300_texture_setup_fb_state(surface);
1228bf215546Sopenharmony_ci
1229bf215546Sopenharmony_ci        /* Parameters for the CBZB clear. */
1230bf215546Sopenharmony_ci        surface->cbzb_allowed = tex->tex.cbzb_allowed[level];
1231bf215546Sopenharmony_ci        surface->cbzb_width = align(surface->base.width, 64);
1232bf215546Sopenharmony_ci
1233bf215546Sopenharmony_ci        /* Height must be aligned to the size of a tile. */
1234bf215546Sopenharmony_ci        tile_height = r300_get_pixel_alignment(surface->base.format,
1235bf215546Sopenharmony_ci                                               tex->b.nr_samples,
1236bf215546Sopenharmony_ci                                               tex->tex.microtile,
1237bf215546Sopenharmony_ci                                               tex->tex.macrotile[level],
1238bf215546Sopenharmony_ci                                               DIM_HEIGHT, 0);
1239bf215546Sopenharmony_ci
1240bf215546Sopenharmony_ci        surface->cbzb_height = align((surface->base.height + 1) / 2,
1241bf215546Sopenharmony_ci                                     tile_height);
1242bf215546Sopenharmony_ci
1243bf215546Sopenharmony_ci        /* Offset must be aligned to 2K and must point at the beginning
1244bf215546Sopenharmony_ci         * of a scanline. */
1245bf215546Sopenharmony_ci        offset = surface->offset +
1246bf215546Sopenharmony_ci                 tex->tex.stride_in_bytes[level] * surface->cbzb_height;
1247bf215546Sopenharmony_ci        surface->cbzb_midpoint_offset = offset & ~2047;
1248bf215546Sopenharmony_ci
1249bf215546Sopenharmony_ci        surface->cbzb_pitch = surface->pitch & 0x1ffffc;
1250bf215546Sopenharmony_ci
1251bf215546Sopenharmony_ci        if (util_format_get_blocksizebits(surface->base.format) == 32)
1252bf215546Sopenharmony_ci            surface->cbzb_format = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
1253bf215546Sopenharmony_ci        else
1254bf215546Sopenharmony_ci            surface->cbzb_format = R300_DEPTHFORMAT_16BIT_INT_Z;
1255bf215546Sopenharmony_ci
1256bf215546Sopenharmony_ci        DBG(r300_context(ctx), DBG_CBZB,
1257bf215546Sopenharmony_ci            "CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n",
1258bf215546Sopenharmony_ci            surface->cbzb_allowed ? "YES" : " NO",
1259bf215546Sopenharmony_ci            surface->cbzb_width, surface->cbzb_height,
1260bf215546Sopenharmony_ci            offset & 2047,
1261bf215546Sopenharmony_ci            tex->tex.microtile ? "YES" : " NO",
1262bf215546Sopenharmony_ci            tex->tex.macrotile[level] ? "YES" : " NO");
1263bf215546Sopenharmony_ci    }
1264bf215546Sopenharmony_ci
1265bf215546Sopenharmony_ci    return &surface->base;
1266bf215546Sopenharmony_ci}
1267bf215546Sopenharmony_ci
1268bf215546Sopenharmony_cistruct pipe_surface* r300_create_surface(struct pipe_context * ctx,
1269bf215546Sopenharmony_ci                                         struct pipe_resource* texture,
1270bf215546Sopenharmony_ci                                         const struct pipe_surface *surf_tmpl)
1271bf215546Sopenharmony_ci{
1272bf215546Sopenharmony_ci    return r300_create_surface_custom(ctx, texture, surf_tmpl,
1273bf215546Sopenharmony_ci                                      texture->width0,
1274bf215546Sopenharmony_ci                                      texture->height0);
1275bf215546Sopenharmony_ci}
1276bf215546Sopenharmony_ci
1277bf215546Sopenharmony_civoid r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s)
1278bf215546Sopenharmony_ci{
1279bf215546Sopenharmony_ci    pipe_resource_reference(&s->texture, NULL);
1280bf215546Sopenharmony_ci    FREE(s);
1281bf215546Sopenharmony_ci}
1282