r300_texture_desc.c revision c92d232061c1aef6f5f56cbd815625778db2fd8c
1/*
2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3 * Copyright 2010 Marek Olšák <maraeo@gmail.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
24#include "r300_texture_desc.h"
25
26#include "r300_context.h"
27#include "r300_winsys.h"
28
29#include "util/u_format.h"
30
31/* Returns the number of pixels that the texture should be aligned to
32 * in the given dimension. */
33unsigned r300_get_pixel_alignment(enum pipe_format format,
34                                  unsigned num_samples,
35                                  enum r300_buffer_tiling microtile,
36                                  enum r300_buffer_tiling macrotile,
37                                  enum r300_dim dim)
38{
39    static const unsigned table[2][5][3][2] =
40    {
41        {
42    /* Macro: linear    linear    linear
43       Micro: linear    tiled  square-tiled */
44            {{ 32, 1}, { 8,  4}, { 0,  0}}, /*   8 bits per pixel */
45            {{ 16, 1}, { 8,  2}, { 4,  4}}, /*  16 bits per pixel */
46            {{  8, 1}, { 4,  2}, { 0,  0}}, /*  32 bits per pixel */
47            {{  4, 1}, { 0,  0}, { 2,  2}}, /*  64 bits per pixel */
48            {{  2, 1}, { 0,  0}, { 0,  0}}  /* 128 bits per pixel */
49        },
50        {
51    /* Macro: tiled     tiled     tiled
52       Micro: linear    tiled  square-tiled */
53            {{256, 8}, {64, 32}, { 0,  0}}, /*   8 bits per pixel */
54            {{128, 8}, {64, 16}, {32, 32}}, /*  16 bits per pixel */
55            {{ 64, 8}, {32, 16}, { 0,  0}}, /*  32 bits per pixel */
56            {{ 32, 8}, { 0,  0}, {16, 16}}, /*  64 bits per pixel */
57            {{ 16, 8}, { 0,  0}, { 0,  0}}  /* 128 bits per pixel */
58        }
59    };
60    static const unsigned aa_block[2] = {4, 8};
61    unsigned tile = 0;
62    unsigned pixsize = util_format_get_blocksize(format);
63
64    assert(macrotile <= R300_BUFFER_TILED);
65    assert(microtile <= R300_BUFFER_SQUARETILED);
66    assert(pixsize <= 16);
67    assert(dim <= DIM_HEIGHT);
68
69    if (num_samples > 1) {
70        /* Multisampled textures have their own alignment scheme. */
71        if (pixsize == 4)
72            tile = aa_block[dim];
73        /* XXX FP16 AA. */
74    } else {
75        /* Standard alignment. */
76        tile = table[macrotile][util_logbase2(pixsize)][microtile][dim];
77    }
78
79    assert(tile);
80    return tile;
81}
82
83/* Return true if macrotiling should be enabled on the miplevel. */
84static boolean r300_texture_macro_switch(struct r300_texture_desc *desc,
85                                         unsigned level,
86                                         boolean rv350_mode,
87                                         enum r300_dim dim)
88{
89    unsigned tile, texdim;
90
91    tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples,
92                                    desc->microtile, R300_BUFFER_TILED, dim);
93    if (dim == DIM_WIDTH) {
94        texdim = u_minify(desc->b.b.width0, level);
95    } else {
96        texdim = u_minify(desc->b.b.height0, level);
97    }
98
99    /* See TX_FILTER1_n.MACRO_SWITCH. */
100    if (rv350_mode) {
101        return texdim >= tile;
102    } else {
103        return texdim > tile;
104    }
105}
106
107/**
108 * Return the stride, in bytes, of the texture image of the given texture
109 * at the given level.
110 */
111static unsigned r300_texture_get_stride(struct r300_screen *screen,
112                                        struct r300_texture_desc *desc,
113                                        unsigned level)
114{
115    unsigned tile_width, width, stride;
116
117    if (desc->stride_in_bytes_override)
118        return desc->stride_in_bytes_override;
119
120    /* Check the level. */
121    if (level > desc->b.b.last_level) {
122        SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n",
123                   __FUNCTION__, level, desc->b.b.last_level);
124        return 0;
125    }
126
127    width = u_minify(desc->b.b.width0, level);
128
129    if (util_format_is_plain(desc->b.b.format)) {
130        tile_width = r300_get_pixel_alignment(desc->b.b.format,
131                                              desc->b.b.nr_samples,
132                                              desc->microtile,
133                                              desc->macrotile[level],
134                                              DIM_WIDTH);
135        width = align(width, tile_width);
136
137        stride = util_format_get_stride(desc->b.b.format, width);
138
139        /* Some IGPs need a minimum stride of 64 bytes, hmm...
140         * This doesn't seem to apply to tiled textures, according to r300c. */
141        if (!desc->microtile && !desc->macrotile[level] &&
142            (screen->caps.family == CHIP_FAMILY_RS600 ||
143             screen->caps.family == CHIP_FAMILY_RS690 ||
144             screen->caps.family == CHIP_FAMILY_RS740)) {
145            return stride < 64 ? 64 : stride;
146        }
147
148        /* The alignment to 32 bytes is sort of implied by the layout... */
149        return stride;
150    } else {
151        return align(util_format_get_stride(desc->b.b.format, width), 32);
152    }
153}
154
155static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc,
156                                          unsigned level,
157                                          boolean align_for_cbzb)
158{
159    unsigned height, tile_height;
160
161    height = u_minify(desc->b.b.height0, level);
162
163    if (util_format_is_plain(desc->b.b.format)) {
164        tile_height = r300_get_pixel_alignment(desc->b.b.format,
165                                               desc->b.b.nr_samples,
166                                               desc->microtile,
167                                               desc->macrotile[level],
168                                               DIM_HEIGHT);
169        height = align(height, tile_height);
170
171        /* This is needed for the kernel checker, unfortunately. */
172        if ((desc->b.b.target != PIPE_TEXTURE_1D &&
173             desc->b.b.target != PIPE_TEXTURE_2D) ||
174            desc->b.b.last_level != 0) {
175            height = util_next_power_of_two(height);
176        }
177
178        /* Allocate an even number of macrotiles for the CBZB clear.
179         * Do so for 3 or more macrotiles in the Y direction. */
180        if (align_for_cbzb &&
181            level == 0 && desc->b.b.last_level == 0 &&
182            desc->macrotile[0] && height >= tile_height * 3) {
183            height = align(height, tile_height * 2);
184        }
185    }
186
187    return util_format_get_nblocksy(desc->b.b.format, height);
188}
189
190static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen,
191                                           struct r300_texture_desc *desc)
192{
193    /* The kernels <= 2.6.34-rc4 compute the size of mipmapped 3D textures
194     * incorrectly. This is a workaround to prevent CS from being rejected. */
195
196    unsigned i, size;
197
198    if (!screen->rws->get_value(screen->rws, R300_VID_DRM_2_3_0) &&
199        desc->b.b.target == PIPE_TEXTURE_3D &&
200        desc->b.b.last_level > 0) {
201        size = 0;
202
203        for (i = 0; i <= desc->b.b.last_level; i++) {
204            size += desc->stride_in_bytes[i] *
205                    r300_texture_get_nblocksy(desc, i, FALSE);
206        }
207
208        size *= desc->b.b.depth0;
209        desc->size_in_bytes = size;
210    }
211}
212
213/* Get a width in pixels from a stride in bytes. */
214static unsigned stride_to_width(enum pipe_format format,
215                                unsigned stride_in_bytes)
216{
217    return (stride_in_bytes / util_format_get_blocksize(format)) *
218            util_format_get_blockwidth(format);
219}
220
221static void r300_setup_miptree(struct r300_screen *screen,
222                               struct r300_texture_desc *desc)
223{
224    struct pipe_resource *base = &desc->b.b;
225    unsigned stride, size, layer_size, nblocksy, i;
226    boolean rv350_mode = screen->caps.is_rv350;
227
228    SCREEN_DBG(screen, DBG_TEXALLOC,
229        "r300: Making miptree for texture, format %s\n",
230        util_format_short_name(base->format));
231
232    for (i = 0; i <= base->last_level; i++) {
233        /* Let's see if this miplevel can be macrotiled. */
234        desc->macrotile[i] =
235            (desc->macrotile[0] == R300_BUFFER_TILED &&
236             r300_texture_macro_switch(desc, i, rv350_mode, DIM_WIDTH) &&
237             r300_texture_macro_switch(desc, i, rv350_mode, DIM_HEIGHT)) ?
238             R300_BUFFER_TILED : R300_BUFFER_LINEAR;
239
240        stride = r300_texture_get_stride(screen, desc, i);
241        nblocksy = r300_texture_get_nblocksy(desc, i, desc->stride_in_bytes_override == 0);
242        layer_size = stride * nblocksy;
243
244        if (base->nr_samples) {
245            layer_size *= base->nr_samples;
246        }
247
248        if (base->target == PIPE_TEXTURE_CUBE)
249            size = layer_size * 6;
250        else
251            size = layer_size * u_minify(base->depth0, i);
252
253        desc->offset_in_bytes[i] = desc->size_in_bytes;
254        desc->size_in_bytes = desc->offset_in_bytes[i] + size;
255        desc->layer_size_in_bytes[i] = layer_size;
256        desc->stride_in_bytes[i] = stride;
257        desc->stride_in_pixels[i] = stride_to_width(desc->b.b.format, stride);
258
259        SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d "
260                "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n",
261                i, u_minify(base->width0, i), u_minify(base->height0, i),
262                u_minify(base->depth0, i), stride, desc->size_in_bytes,
263                desc->macrotile[i] ? "TRUE" : "FALSE");
264    }
265}
266
267static void r300_setup_flags(struct r300_texture_desc *desc)
268{
269    desc->uses_stride_addressing =
270        !util_is_power_of_two(desc->b.b.width0) ||
271        !util_is_power_of_two(desc->b.b.height0) ||
272        (desc->stride_in_bytes_override &&
273         stride_to_width(desc->b.b.format,
274                         desc->stride_in_bytes_override) != desc->b.b.width0);
275}
276
277static void r300_setup_cbzb_flags(struct r300_screen *rscreen,
278                                  struct r300_texture_desc *desc)
279{
280    unsigned i, bpp;
281    boolean first_level_valid;
282
283    bpp = util_format_get_blocksizebits(desc->b.b.format);
284
285    /* 1) The texture must be point-sampled,
286     * 2) The depth must be 16 or 32 bits.
287     * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage
288     *    with certain texture sizes. Macrotiling ensures the alignment. */
289    first_level_valid = desc->b.b.nr_samples <= 1 &&
290                       (bpp == 16 || bpp == 32) &&
291                       desc->macrotile[0];
292
293    for (i = 0; i <= desc->b.b.last_level; i++)
294        desc->cbzb_allowed[i] = first_level_valid && desc->macrotile[i];
295    return;
296#if 0
297    /* When clearing, the layer (width*height) is horizontally split
298     * into two, and the upper and lower halves are cleared by the CB
299     * and ZB units, respectively. Therefore, the number of macrotiles
300     * in the Y direction must be even. */
301
302    if (desc->b.b.last_level > 0 ||
303        desc->b.b.target == PIPE_TEXTURE_3D ||
304        desc->b.b.target == PIPE_TEXTURE_CUBE) {
305        /* For mipmapped, 3D, or cube textures, just check if there are
306         * enough macrotiles per layer. */
307        for (i = 0; i <= desc->b.b.last_level; i++) {
308            desc->cbzb_allowed[i] = FALSE;
309
310            if (first_level_valid && desc->macrotile[i]) {
311                unsigned height, tile_height, num_macrotiles;
312
313                /* Compute the number of macrotiles in the Y direction. */
314                tile_height = r300_get_pixel_alignment(desc->b.b.format,
315                                                       desc->b.b.nr_samples,
316                                                       desc->microtile,
317                                                       R300_BUFFER_TILED,
318                                                       DIM_HEIGHT);
319                height = r300_texture_get_height(desc, i);
320                num_macrotiles = height / tile_height;
321
322                desc->cbzb_allowed[i] = num_macrotiles % 2 == 0;
323            }
324        }
325    } else {
326        /* For 1D and 2D non-mipmapped textures */
327        unsigned layer_size;
328
329        layer_size = desc->stride_in_bytes[0] *
330                     r300_texture_get_nblocksy(desc, 0, TRUE);
331    }
332#endif
333}
334
335static void r300_setup_tiling(struct r300_screen *screen,
336                              struct r300_texture_desc *desc)
337{
338    struct r300_winsys_screen *rws = screen->rws;
339    enum pipe_format format = desc->b.b.format;
340    boolean rv350_mode = screen->caps.is_rv350;
341    boolean is_zb = util_format_is_depth_or_stencil(format);
342    boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING);
343
344    if (!util_format_is_plain(format)) {
345        return;
346    }
347
348    /* If height == 1, disable microtiling except for zbuffer. */
349    if (!is_zb && (desc->b.b.height0 == 1 || dbg_no_tiling)) {
350        return;
351    }
352
353    /* Set microtiling. */
354    switch (util_format_get_blocksize(format)) {
355        case 1:
356        case 4:
357            desc->microtile = R300_BUFFER_TILED;
358            break;
359
360        case 2:
361        case 8:
362            if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) {
363                desc->microtile = R300_BUFFER_SQUARETILED;
364            }
365            break;
366    }
367
368    if (dbg_no_tiling) {
369        return;
370    }
371
372    /* Set macrotiling. */
373    if (r300_texture_macro_switch(desc, 0, rv350_mode, DIM_WIDTH) &&
374        r300_texture_macro_switch(desc, 0, rv350_mode, DIM_HEIGHT)) {
375        desc->macrotile[0] = R300_BUFFER_TILED;
376    }
377}
378
379static void r300_tex_print_info(struct r300_screen *rscreen,
380                                struct r300_texture_desc *desc,
381                                const char *func)
382{
383    fprintf(stderr,
384            "r300: %s: Macro: %s, Micro: %s, Pitch: %i, Dim: %ix%ix%i, "
385            "LastLevel: %i, Size: %i, Format: %s\n",
386            func,
387            desc->macrotile[0] ? "YES" : " NO",
388            desc->microtile ? "YES" : " NO",
389            desc->stride_in_pixels[0],
390            desc->b.b.width0, desc->b.b.height0, desc->b.b.depth0,
391            desc->b.b.last_level, desc->size_in_bytes,
392            util_format_short_name(desc->b.b.format));
393}
394
395boolean r300_texture_desc_init(struct r300_screen *rscreen,
396                               struct r300_texture_desc *desc,
397                               const struct pipe_resource *base,
398                               enum r300_buffer_tiling microtile,
399                               enum r300_buffer_tiling macrotile,
400                               unsigned stride_in_bytes_override,
401                               unsigned max_buffer_size)
402{
403    desc->b.b = *base;
404    desc->b.b.screen = &rscreen->screen;
405
406    desc->stride_in_bytes_override = stride_in_bytes_override;
407
408    r300_setup_flags(desc);
409
410    if (microtile == R300_BUFFER_SELECT_LAYOUT ||
411        macrotile == R300_BUFFER_SELECT_LAYOUT) {
412        r300_setup_tiling(rscreen, desc);
413    } else {
414        desc->microtile = microtile;
415        desc->macrotile[0] = macrotile;
416        assert(desc->b.b.last_level == 0);
417    }
418
419    r300_setup_miptree(rscreen, desc);
420    r300_texture_3d_fix_mipmapping(rscreen, desc);
421    r300_setup_cbzb_flags(rscreen, desc);
422
423    if (max_buffer_size) {
424        /* Make sure the buffer we got is large enough. */
425        if (desc->size_in_bytes > max_buffer_size) {
426            fprintf(stderr, "r300: texture_from_handle: The buffer is not "
427                            "large enough. Got: %i, Need: %i, Info:\n",
428                            max_buffer_size, desc->size_in_bytes);
429            r300_tex_print_info(rscreen, desc, "texture_from_handle");
430            return FALSE;
431        }
432
433        desc->buffer_size_in_bytes = max_buffer_size;
434    } else {
435        desc->buffer_size_in_bytes = desc->size_in_bytes;
436
437    }
438
439    if (SCREEN_DBG_ON(rscreen, DBG_TEX))
440        r300_tex_print_info(rscreen, desc, "texture_from_handle");
441
442    return TRUE;
443}
444
445unsigned r300_texture_get_offset(struct r300_texture_desc *desc,
446                                 unsigned level, unsigned zslice,
447                                 unsigned face)
448{
449    unsigned offset = desc->offset_in_bytes[level];
450
451    switch (desc->b.b.target) {
452        case PIPE_TEXTURE_3D:
453            assert(face == 0);
454            return offset + zslice * desc->layer_size_in_bytes[level];
455
456        case PIPE_TEXTURE_CUBE:
457            assert(zslice == 0);
458            return offset + face * desc->layer_size_in_bytes[level];
459
460        default:
461            assert(zslice == 0 && face == 0);
462            return offset;
463    }
464}
465