radeon_surface.c revision a7d7de1e
1e88f27b3Smrg/*
2e88f27b3Smrg * Copyright © 2011 Red Hat All Rights Reserved.
3e88f27b3Smrg *
4e88f27b3Smrg * Permission is hereby granted, free of charge, to any person obtaining
5e88f27b3Smrg * a copy of this software and associated documentation files (the
6e88f27b3Smrg * "Software"), to deal in the Software without restriction, including
7e88f27b3Smrg * without limitation the rights to use, copy, modify, merge, publish,
8e88f27b3Smrg * distribute, sub license, and/or sell copies of the Software, and to
9e88f27b3Smrg * permit persons to whom the Software is furnished to do so, subject to
10e88f27b3Smrg * the following conditions:
11e88f27b3Smrg *
12e88f27b3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13e88f27b3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
14e88f27b3Smrg * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15e88f27b3Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
16e88f27b3Smrg * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17e88f27b3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18e88f27b3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19e88f27b3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
20e88f27b3Smrg *
21e88f27b3Smrg * The above copyright notice and this permission notice (including the
22e88f27b3Smrg * next paragraph) shall be included in all copies or substantial portions
23e88f27b3Smrg * of the Software.
24e88f27b3Smrg */
25e88f27b3Smrg/*
26e88f27b3Smrg * Authors:
27e88f27b3Smrg *      Jérôme Glisse <jglisse@redhat.com>
28e88f27b3Smrg */
29e88f27b3Smrg#include <stdbool.h>
30e88f27b3Smrg#include <assert.h>
31e88f27b3Smrg#include <errno.h>
32e88f27b3Smrg#include <stdio.h>
33e88f27b3Smrg#include <stdlib.h>
34e88f27b3Smrg#include <string.h>
35e88f27b3Smrg#include <sys/mman.h>
36e88f27b3Smrg#include <sys/ioctl.h>
37e88f27b3Smrg#include "drm.h"
38e88f27b3Smrg#include "xf86drm.h"
39e88f27b3Smrg#include "radeon_drm.h"
40e88f27b3Smrg#include "radeon_surface.h"
41e88f27b3Smrg
42e88f27b3Smrg#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
43e88f27b3Smrg#define MAX2(A, B)              ((A) > (B) ? (A) : (B))
44e88f27b3Smrg#define MIN2(A, B)              ((A) < (B) ? (A) : (B))
45e88f27b3Smrg
46e88f27b3Smrg/* keep this private */
47e88f27b3Smrgenum radeon_family {
48e88f27b3Smrg    CHIP_UNKNOWN,
49e88f27b3Smrg    CHIP_R600,
50e88f27b3Smrg    CHIP_RV610,
51e88f27b3Smrg    CHIP_RV630,
52e88f27b3Smrg    CHIP_RV670,
53e88f27b3Smrg    CHIP_RV620,
54e88f27b3Smrg    CHIP_RV635,
55e88f27b3Smrg    CHIP_RS780,
56e88f27b3Smrg    CHIP_RS880,
57e88f27b3Smrg    CHIP_RV770,
58e88f27b3Smrg    CHIP_RV730,
59e88f27b3Smrg    CHIP_RV710,
60e88f27b3Smrg    CHIP_RV740,
61e88f27b3Smrg    CHIP_CEDAR,
62e88f27b3Smrg    CHIP_REDWOOD,
63e88f27b3Smrg    CHIP_JUNIPER,
64e88f27b3Smrg    CHIP_CYPRESS,
65e88f27b3Smrg    CHIP_HEMLOCK,
66e88f27b3Smrg    CHIP_PALM,
67e88f27b3Smrg    CHIP_SUMO,
68e88f27b3Smrg    CHIP_SUMO2,
69e88f27b3Smrg    CHIP_BARTS,
70e88f27b3Smrg    CHIP_TURKS,
71e88f27b3Smrg    CHIP_CAICOS,
72e88f27b3Smrg    CHIP_CAYMAN,
73e88f27b3Smrg    CHIP_ARUBA,
74e88f27b3Smrg    CHIP_TAHITI,
75e88f27b3Smrg    CHIP_PITCAIRN,
76e88f27b3Smrg    CHIP_VERDE,
77e88f27b3Smrg    CHIP_OLAND,
78e88f27b3Smrg    CHIP_HAINAN,
79e88f27b3Smrg    CHIP_BONAIRE,
80e88f27b3Smrg    CHIP_KAVERI,
81e88f27b3Smrg    CHIP_KABINI,
82e88f27b3Smrg    CHIP_HAWAII,
83a7d7de1eSmrg    CHIP_MULLINS,
84e88f27b3Smrg    CHIP_LAST,
85e88f27b3Smrg};
86e88f27b3Smrg
87e88f27b3Smrgtypedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
88e88f27b3Smrg                                 struct radeon_surface *surf);
89e88f27b3Smrgtypedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
90e88f27b3Smrg                                 struct radeon_surface *surf);
91e88f27b3Smrg
92e88f27b3Smrgstruct radeon_hw_info {
93e88f27b3Smrg    /* apply to r6, eg */
94e88f27b3Smrg    uint32_t                        group_bytes;
95e88f27b3Smrg    uint32_t                        num_banks;
96e88f27b3Smrg    uint32_t                        num_pipes;
97e88f27b3Smrg    /* apply to eg */
98e88f27b3Smrg    uint32_t                        row_size;
99e88f27b3Smrg    unsigned                        allow_2d;
100e88f27b3Smrg    /* apply to si */
101e88f27b3Smrg    uint32_t                        tile_mode_array[32];
102e88f27b3Smrg    /* apply to cik */
103e88f27b3Smrg    uint32_t                        macrotile_mode_array[16];
104e88f27b3Smrg};
105e88f27b3Smrg
106e88f27b3Smrgstruct radeon_surface_manager {
107e88f27b3Smrg    int                         fd;
108e88f27b3Smrg    uint32_t                    device_id;
109e88f27b3Smrg    struct radeon_hw_info       hw_info;
110e88f27b3Smrg    unsigned                    family;
111e88f27b3Smrg    hw_init_surface_t           surface_init;
112e88f27b3Smrg    hw_best_surface_t           surface_best;
113e88f27b3Smrg};
114e88f27b3Smrg
115e88f27b3Smrg/* helper */
116e88f27b3Smrgstatic int radeon_get_value(int fd, unsigned req, uint32_t *value)
117e88f27b3Smrg{
118e88f27b3Smrg    struct drm_radeon_info info = {};
119e88f27b3Smrg    int r;
120e88f27b3Smrg
121e88f27b3Smrg    *value = 0;
122e88f27b3Smrg    info.request = req;
123e88f27b3Smrg    info.value = (uintptr_t)value;
124e88f27b3Smrg    r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
125e88f27b3Smrg                            sizeof(struct drm_radeon_info));
126e88f27b3Smrg    return r;
127e88f27b3Smrg}
128e88f27b3Smrg
129e88f27b3Smrgstatic int radeon_get_family(struct radeon_surface_manager *surf_man)
130e88f27b3Smrg{
131e88f27b3Smrg    switch (surf_man->device_id) {
132e88f27b3Smrg#define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
133e88f27b3Smrg#include "r600_pci_ids.h"
134e88f27b3Smrg#undef CHIPSET
135e88f27b3Smrg    default:
136e88f27b3Smrg        return -EINVAL;
137e88f27b3Smrg    }
138e88f27b3Smrg    return 0;
139e88f27b3Smrg}
140e88f27b3Smrg
141e88f27b3Smrgstatic unsigned next_power_of_two(unsigned x)
142e88f27b3Smrg{
143e88f27b3Smrg   if (x <= 1)
144e88f27b3Smrg       return 1;
145e88f27b3Smrg
146e88f27b3Smrg   return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
147e88f27b3Smrg}
148e88f27b3Smrg
149e88f27b3Smrgstatic unsigned mip_minify(unsigned size, unsigned level)
150e88f27b3Smrg{
151e88f27b3Smrg    unsigned val;
152e88f27b3Smrg
153e88f27b3Smrg    val = MAX2(1, size >> level);
154e88f27b3Smrg    if (level > 0)
155e88f27b3Smrg        val = next_power_of_two(val);
156e88f27b3Smrg    return val;
157e88f27b3Smrg}
158e88f27b3Smrg
159e88f27b3Smrgstatic void surf_minify(struct radeon_surface *surf,
160e88f27b3Smrg                        struct radeon_surface_level *surflevel,
161e88f27b3Smrg                        unsigned bpe, unsigned level,
162e88f27b3Smrg                        uint32_t xalign, uint32_t yalign, uint32_t zalign,
163e88f27b3Smrg                        unsigned offset)
164e88f27b3Smrg{
165e88f27b3Smrg    surflevel->npix_x = mip_minify(surf->npix_x, level);
166e88f27b3Smrg    surflevel->npix_y = mip_minify(surf->npix_y, level);
167e88f27b3Smrg    surflevel->npix_z = mip_minify(surf->npix_z, level);
168e88f27b3Smrg    surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
169e88f27b3Smrg    surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
170e88f27b3Smrg    surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
171e88f27b3Smrg    if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
172e88f27b3Smrg        !(surf->flags & RADEON_SURF_FMASK)) {
173e88f27b3Smrg        if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
174e88f27b3Smrg            surflevel->mode = RADEON_SURF_MODE_1D;
175e88f27b3Smrg            return;
176e88f27b3Smrg        }
177e88f27b3Smrg    }
178e88f27b3Smrg    surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
179e88f27b3Smrg    surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
180e88f27b3Smrg    surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
181e88f27b3Smrg
182e88f27b3Smrg    surflevel->offset = offset;
183e88f27b3Smrg    surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
184e88f27b3Smrg    surflevel->slice_size = surflevel->pitch_bytes * surflevel->nblk_y;
185e88f27b3Smrg
186e88f27b3Smrg    surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
187e88f27b3Smrg}
188e88f27b3Smrg
189e88f27b3Smrg/* ===========================================================================
190e88f27b3Smrg * r600/r700 family
191e88f27b3Smrg */
192e88f27b3Smrgstatic int r6_init_hw_info(struct radeon_surface_manager *surf_man)
193e88f27b3Smrg{
194e88f27b3Smrg    uint32_t tiling_config;
195e88f27b3Smrg    drmVersionPtr version;
196e88f27b3Smrg    int r;
197e88f27b3Smrg
198e88f27b3Smrg    r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
199e88f27b3Smrg                         &tiling_config);
200e88f27b3Smrg    if (r) {
201e88f27b3Smrg        return r;
202e88f27b3Smrg    }
203e88f27b3Smrg
204e88f27b3Smrg    surf_man->hw_info.allow_2d = 0;
205e88f27b3Smrg    version = drmGetVersion(surf_man->fd);
206e88f27b3Smrg    if (version && version->version_minor >= 14) {
207e88f27b3Smrg        surf_man->hw_info.allow_2d = 1;
208e88f27b3Smrg    }
209e88f27b3Smrg    drmFreeVersion(version);
210e88f27b3Smrg
211e88f27b3Smrg    switch ((tiling_config & 0xe) >> 1) {
212e88f27b3Smrg    case 0:
213e88f27b3Smrg        surf_man->hw_info.num_pipes = 1;
214e88f27b3Smrg        break;
215e88f27b3Smrg    case 1:
216e88f27b3Smrg        surf_man->hw_info.num_pipes = 2;
217e88f27b3Smrg        break;
218e88f27b3Smrg    case 2:
219e88f27b3Smrg        surf_man->hw_info.num_pipes = 4;
220e88f27b3Smrg        break;
221e88f27b3Smrg    case 3:
222e88f27b3Smrg        surf_man->hw_info.num_pipes = 8;
223e88f27b3Smrg        break;
224e88f27b3Smrg    default:
225e88f27b3Smrg        surf_man->hw_info.num_pipes = 8;
226e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
227e88f27b3Smrg        break;
228e88f27b3Smrg    }
229e88f27b3Smrg
230e88f27b3Smrg    switch ((tiling_config & 0x30) >> 4) {
231e88f27b3Smrg    case 0:
232e88f27b3Smrg        surf_man->hw_info.num_banks = 4;
233e88f27b3Smrg        break;
234e88f27b3Smrg    case 1:
235e88f27b3Smrg        surf_man->hw_info.num_banks = 8;
236e88f27b3Smrg        break;
237e88f27b3Smrg    default:
238e88f27b3Smrg        surf_man->hw_info.num_banks = 8;
239e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
240e88f27b3Smrg        break;
241e88f27b3Smrg    }
242e88f27b3Smrg
243e88f27b3Smrg    switch ((tiling_config & 0xc0) >> 6) {
244e88f27b3Smrg    case 0:
245e88f27b3Smrg        surf_man->hw_info.group_bytes = 256;
246e88f27b3Smrg        break;
247e88f27b3Smrg    case 1:
248e88f27b3Smrg        surf_man->hw_info.group_bytes = 512;
249e88f27b3Smrg        break;
250e88f27b3Smrg    default:
251e88f27b3Smrg        surf_man->hw_info.group_bytes = 256;
252e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
253e88f27b3Smrg        break;
254e88f27b3Smrg    }
255e88f27b3Smrg    return 0;
256e88f27b3Smrg}
257e88f27b3Smrg
258e88f27b3Smrgstatic int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
259e88f27b3Smrg                                  struct radeon_surface *surf,
260e88f27b3Smrg                                  uint64_t offset, unsigned start_level)
261e88f27b3Smrg{
262e88f27b3Smrg    uint32_t xalign, yalign, zalign;
263e88f27b3Smrg    unsigned i;
264e88f27b3Smrg
265e88f27b3Smrg    /* compute alignment */
266e88f27b3Smrg    if (!start_level) {
267e88f27b3Smrg        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
268e88f27b3Smrg    }
269e88f27b3Smrg    /* the 32 alignment is for scanout, cb or db but to allow texture to be
270e88f27b3Smrg     * easily bound as such we force this alignment to all surface
271e88f27b3Smrg     */
272e88f27b3Smrg    xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
273e88f27b3Smrg    yalign = 1;
274e88f27b3Smrg    zalign = 1;
275e88f27b3Smrg    if (surf->flags & RADEON_SURF_SCANOUT) {
276e88f27b3Smrg        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
277e88f27b3Smrg    }
278e88f27b3Smrg
279e88f27b3Smrg    /* build mipmap tree */
280e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
281e88f27b3Smrg        surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
282e88f27b3Smrg        surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
283e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
284e88f27b3Smrg        offset = surf->bo_size;
285aad13f10Swiz        if (i == 0) {
286e88f27b3Smrg            offset = ALIGN(offset, surf->bo_alignment);
287e88f27b3Smrg        }
288e88f27b3Smrg    }
289e88f27b3Smrg    return 0;
290e88f27b3Smrg}
291e88f27b3Smrg
292e88f27b3Smrgstatic int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
293e88f27b3Smrg                                          struct radeon_surface *surf,
294e88f27b3Smrg                                          uint64_t offset, unsigned start_level)
295e88f27b3Smrg{
296e88f27b3Smrg    uint32_t xalign, yalign, zalign;
297e88f27b3Smrg    unsigned i;
298e88f27b3Smrg
299e88f27b3Smrg    /* compute alignment */
300e88f27b3Smrg    if (!start_level) {
301e88f27b3Smrg        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
302e88f27b3Smrg    }
303e88f27b3Smrg    xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
304e88f27b3Smrg    yalign = 1;
305e88f27b3Smrg    zalign = 1;
306e88f27b3Smrg
307e88f27b3Smrg    /* build mipmap tree */
308e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
309e88f27b3Smrg        surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
310e88f27b3Smrg        surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
311e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
312e88f27b3Smrg        offset = surf->bo_size;
313aad13f10Swiz        if (i == 0) {
314e88f27b3Smrg            offset = ALIGN(offset, surf->bo_alignment);
315e88f27b3Smrg        }
316e88f27b3Smrg    }
317e88f27b3Smrg    return 0;
318e88f27b3Smrg}
319e88f27b3Smrg
320e88f27b3Smrgstatic int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
321e88f27b3Smrg                              struct radeon_surface *surf,
322e88f27b3Smrg                              uint64_t offset, unsigned start_level)
323e88f27b3Smrg{
324e88f27b3Smrg    uint32_t xalign, yalign, zalign, tilew;
325e88f27b3Smrg    unsigned i;
326e88f27b3Smrg
327e88f27b3Smrg    /* compute alignment */
328e88f27b3Smrg    tilew = 8;
329e88f27b3Smrg    xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
330e88f27b3Smrg    xalign = MAX2(tilew, xalign);
331e88f27b3Smrg    yalign = tilew;
332e88f27b3Smrg    zalign = 1;
333e88f27b3Smrg    if (surf->flags & RADEON_SURF_SCANOUT) {
334e88f27b3Smrg        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
335e88f27b3Smrg    }
336e88f27b3Smrg    if (!start_level) {
337e88f27b3Smrg        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
338e88f27b3Smrg    }
339e88f27b3Smrg
340e88f27b3Smrg    /* build mipmap tree */
341e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
342e88f27b3Smrg        surf->level[i].mode = RADEON_SURF_MODE_1D;
343e88f27b3Smrg        surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
344e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
345e88f27b3Smrg        offset = surf->bo_size;
346aad13f10Swiz        if (i == 0) {
347e88f27b3Smrg            offset = ALIGN(offset, surf->bo_alignment);
348e88f27b3Smrg        }
349e88f27b3Smrg    }
350e88f27b3Smrg    return 0;
351e88f27b3Smrg}
352e88f27b3Smrg
353e88f27b3Smrgstatic int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
354e88f27b3Smrg                              struct radeon_surface *surf,
355e88f27b3Smrg                              uint64_t offset, unsigned start_level)
356e88f27b3Smrg{
357e88f27b3Smrg    uint32_t xalign, yalign, zalign, tilew;
358e88f27b3Smrg    unsigned i;
359e88f27b3Smrg
360e88f27b3Smrg    /* compute alignment */
361e88f27b3Smrg    tilew = 8;
362e88f27b3Smrg    zalign = 1;
363e88f27b3Smrg    xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
364e88f27b3Smrg             (tilew * surf->bpe * surf->nsamples);
365e88f27b3Smrg    xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
366e88f27b3Smrg    yalign = tilew * surf_man->hw_info.num_pipes;
367e88f27b3Smrg    if (surf->flags & RADEON_SURF_SCANOUT) {
368e88f27b3Smrg        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
369e88f27b3Smrg    }
370e88f27b3Smrg    if (!start_level) {
371e88f27b3Smrg        surf->bo_alignment =
372e88f27b3Smrg            MAX2(surf_man->hw_info.num_pipes *
373e88f27b3Smrg                 surf_man->hw_info.num_banks *
374e88f27b3Smrg                 surf->nsamples * surf->bpe * 64,
375e88f27b3Smrg                 xalign * yalign * surf->nsamples * surf->bpe);
376e88f27b3Smrg    }
377e88f27b3Smrg
378e88f27b3Smrg    /* build mipmap tree */
379e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
380e88f27b3Smrg        surf->level[i].mode = RADEON_SURF_MODE_2D;
381e88f27b3Smrg        surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
382e88f27b3Smrg        if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
383e88f27b3Smrg            return r6_surface_init_1d(surf_man, surf, offset, i);
384e88f27b3Smrg        }
385e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
386e88f27b3Smrg        offset = surf->bo_size;
387aad13f10Swiz        if (i == 0) {
388e88f27b3Smrg            offset = ALIGN(offset, surf->bo_alignment);
389e88f27b3Smrg        }
390e88f27b3Smrg    }
391e88f27b3Smrg    return 0;
392e88f27b3Smrg}
393e88f27b3Smrg
394e88f27b3Smrgstatic int r6_surface_init(struct radeon_surface_manager *surf_man,
395e88f27b3Smrg                           struct radeon_surface *surf)
396e88f27b3Smrg{
397e88f27b3Smrg    unsigned mode;
398e88f27b3Smrg    int r;
399e88f27b3Smrg
400e88f27b3Smrg    /* MSAA surfaces support the 2D mode only. */
401e88f27b3Smrg    if (surf->nsamples > 1) {
402e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
403e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
404e88f27b3Smrg    }
405e88f27b3Smrg
406e88f27b3Smrg    /* tiling mode */
407e88f27b3Smrg    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
408e88f27b3Smrg
409e88f27b3Smrg    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
410e88f27b3Smrg        /* zbuffer only support 1D or 2D tiled surface */
411e88f27b3Smrg        switch (mode) {
412e88f27b3Smrg        case RADEON_SURF_MODE_1D:
413e88f27b3Smrg        case RADEON_SURF_MODE_2D:
414e88f27b3Smrg            break;
415e88f27b3Smrg        default:
416e88f27b3Smrg            mode = RADEON_SURF_MODE_1D;
417e88f27b3Smrg            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
418e88f27b3Smrg            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
419e88f27b3Smrg            break;
420e88f27b3Smrg        }
421e88f27b3Smrg    }
422e88f27b3Smrg
423e88f27b3Smrg    /* force 1d on kernel that can't do 2d */
424e88f27b3Smrg    if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
425e88f27b3Smrg        if (surf->nsamples > 1) {
426e88f27b3Smrg            fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
427e88f27b3Smrg            return -EFAULT;
428e88f27b3Smrg        }
429e88f27b3Smrg        mode = RADEON_SURF_MODE_1D;
430e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
431e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(mode, MODE);
432e88f27b3Smrg    }
433e88f27b3Smrg
434e88f27b3Smrg    /* check surface dimension */
435e88f27b3Smrg    if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
436e88f27b3Smrg        return -EINVAL;
437e88f27b3Smrg    }
438e88f27b3Smrg
439e88f27b3Smrg    /* check mipmap last_level */
440e88f27b3Smrg    if (surf->last_level > 14) {
441e88f27b3Smrg        return -EINVAL;
442e88f27b3Smrg    }
443e88f27b3Smrg
444e88f27b3Smrg    /* check tiling mode */
445e88f27b3Smrg    switch (mode) {
446e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR:
447e88f27b3Smrg        r = r6_surface_init_linear(surf_man, surf, 0, 0);
448e88f27b3Smrg        break;
449e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR_ALIGNED:
450e88f27b3Smrg        r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
451e88f27b3Smrg        break;
452e88f27b3Smrg    case RADEON_SURF_MODE_1D:
453e88f27b3Smrg        r = r6_surface_init_1d(surf_man, surf, 0, 0);
454e88f27b3Smrg        break;
455e88f27b3Smrg    case RADEON_SURF_MODE_2D:
456e88f27b3Smrg        r = r6_surface_init_2d(surf_man, surf, 0, 0);
457e88f27b3Smrg        break;
458e88f27b3Smrg    default:
459e88f27b3Smrg        return -EINVAL;
460e88f27b3Smrg    }
461e88f27b3Smrg    return r;
462e88f27b3Smrg}
463e88f27b3Smrg
464e88f27b3Smrgstatic int r6_surface_best(struct radeon_surface_manager *surf_man,
465e88f27b3Smrg                           struct radeon_surface *surf)
466e88f27b3Smrg{
467e88f27b3Smrg    /* no value to optimize for r6xx/r7xx */
468e88f27b3Smrg    return 0;
469e88f27b3Smrg}
470e88f27b3Smrg
471e88f27b3Smrg
472e88f27b3Smrg/* ===========================================================================
473e88f27b3Smrg * evergreen family
474e88f27b3Smrg */
475e88f27b3Smrgstatic int eg_init_hw_info(struct radeon_surface_manager *surf_man)
476e88f27b3Smrg{
477e88f27b3Smrg    uint32_t tiling_config;
478e88f27b3Smrg    drmVersionPtr version;
479e88f27b3Smrg    int r;
480e88f27b3Smrg
481e88f27b3Smrg    r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
482e88f27b3Smrg                         &tiling_config);
483e88f27b3Smrg    if (r) {
484e88f27b3Smrg        return r;
485e88f27b3Smrg    }
486e88f27b3Smrg
487e88f27b3Smrg    surf_man->hw_info.allow_2d = 0;
488e88f27b3Smrg    version = drmGetVersion(surf_man->fd);
489e88f27b3Smrg    if (version && version->version_minor >= 16) {
490e88f27b3Smrg        surf_man->hw_info.allow_2d = 1;
491e88f27b3Smrg    }
492e88f27b3Smrg    drmFreeVersion(version);
493e88f27b3Smrg
494e88f27b3Smrg    switch (tiling_config & 0xf) {
495e88f27b3Smrg    case 0:
496e88f27b3Smrg        surf_man->hw_info.num_pipes = 1;
497e88f27b3Smrg        break;
498e88f27b3Smrg    case 1:
499e88f27b3Smrg        surf_man->hw_info.num_pipes = 2;
500e88f27b3Smrg        break;
501e88f27b3Smrg    case 2:
502e88f27b3Smrg        surf_man->hw_info.num_pipes = 4;
503e88f27b3Smrg        break;
504e88f27b3Smrg    case 3:
505e88f27b3Smrg        surf_man->hw_info.num_pipes = 8;
506e88f27b3Smrg        break;
507e88f27b3Smrg    default:
508e88f27b3Smrg        surf_man->hw_info.num_pipes = 8;
509e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
510e88f27b3Smrg        break;
511e88f27b3Smrg    }
512e88f27b3Smrg
513e88f27b3Smrg    switch ((tiling_config & 0xf0) >> 4) {
514e88f27b3Smrg    case 0:
515e88f27b3Smrg        surf_man->hw_info.num_banks = 4;
516e88f27b3Smrg        break;
517e88f27b3Smrg    case 1:
518e88f27b3Smrg        surf_man->hw_info.num_banks = 8;
519e88f27b3Smrg        break;
520e88f27b3Smrg    case 2:
521e88f27b3Smrg        surf_man->hw_info.num_banks = 16;
522e88f27b3Smrg        break;
523e88f27b3Smrg    default:
524e88f27b3Smrg        surf_man->hw_info.num_banks = 8;
525e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
526e88f27b3Smrg        break;
527e88f27b3Smrg    }
528e88f27b3Smrg
529e88f27b3Smrg    switch ((tiling_config & 0xf00) >> 8) {
530e88f27b3Smrg    case 0:
531e88f27b3Smrg        surf_man->hw_info.group_bytes = 256;
532e88f27b3Smrg        break;
533e88f27b3Smrg    case 1:
534e88f27b3Smrg        surf_man->hw_info.group_bytes = 512;
535e88f27b3Smrg        break;
536e88f27b3Smrg    default:
537e88f27b3Smrg        surf_man->hw_info.group_bytes = 256;
538e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
539e88f27b3Smrg        break;
540e88f27b3Smrg    }
541e88f27b3Smrg
542e88f27b3Smrg    switch ((tiling_config & 0xf000) >> 12) {
543e88f27b3Smrg    case 0:
544e88f27b3Smrg        surf_man->hw_info.row_size = 1024;
545e88f27b3Smrg        break;
546e88f27b3Smrg    case 1:
547e88f27b3Smrg        surf_man->hw_info.row_size = 2048;
548e88f27b3Smrg        break;
549e88f27b3Smrg    case 2:
550e88f27b3Smrg        surf_man->hw_info.row_size = 4096;
551e88f27b3Smrg        break;
552e88f27b3Smrg    default:
553e88f27b3Smrg        surf_man->hw_info.row_size = 4096;
554e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
555e88f27b3Smrg        break;
556e88f27b3Smrg    }
557e88f27b3Smrg    return 0;
558e88f27b3Smrg}
559e88f27b3Smrg
560e88f27b3Smrgstatic void eg_surf_minify(struct radeon_surface *surf,
561e88f27b3Smrg                           struct radeon_surface_level *surflevel,
562e88f27b3Smrg                           unsigned bpe,
563e88f27b3Smrg                           unsigned level,
564e88f27b3Smrg                           unsigned slice_pt,
565e88f27b3Smrg                           unsigned mtilew,
566e88f27b3Smrg                           unsigned mtileh,
567e88f27b3Smrg                           unsigned mtileb,
568e88f27b3Smrg                           unsigned offset)
569e88f27b3Smrg{
570e88f27b3Smrg    unsigned mtile_pr, mtile_ps;
571e88f27b3Smrg
572e88f27b3Smrg    surflevel->npix_x = mip_minify(surf->npix_x, level);
573e88f27b3Smrg    surflevel->npix_y = mip_minify(surf->npix_y, level);
574e88f27b3Smrg    surflevel->npix_z = mip_minify(surf->npix_z, level);
575e88f27b3Smrg    surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
576e88f27b3Smrg    surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
577e88f27b3Smrg    surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
578e88f27b3Smrg    if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
579e88f27b3Smrg        !(surf->flags & RADEON_SURF_FMASK)) {
580e88f27b3Smrg        if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
581e88f27b3Smrg            surflevel->mode = RADEON_SURF_MODE_1D;
582e88f27b3Smrg            return;
583e88f27b3Smrg        }
584e88f27b3Smrg    }
585e88f27b3Smrg    surflevel->nblk_x  = ALIGN(surflevel->nblk_x, mtilew);
586e88f27b3Smrg    surflevel->nblk_y  = ALIGN(surflevel->nblk_y, mtileh);
587e88f27b3Smrg    surflevel->nblk_z  = ALIGN(surflevel->nblk_z, 1);
588e88f27b3Smrg
589e88f27b3Smrg    /* macro tile per row */
590e88f27b3Smrg    mtile_pr = surflevel->nblk_x / mtilew;
591e88f27b3Smrg    /* macro tile per slice */
592e88f27b3Smrg    mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
593e88f27b3Smrg
594e88f27b3Smrg    surflevel->offset = offset;
595e88f27b3Smrg    surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
596e88f27b3Smrg    surflevel->slice_size = mtile_ps * mtileb * slice_pt;
597e88f27b3Smrg
598e88f27b3Smrg    surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
599e88f27b3Smrg}
600e88f27b3Smrg
601e88f27b3Smrgstatic int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
602e88f27b3Smrg                              struct radeon_surface *surf,
603e88f27b3Smrg                              struct radeon_surface_level *level,
604e88f27b3Smrg                              unsigned bpe,
605e88f27b3Smrg                              uint64_t offset, unsigned start_level)
606e88f27b3Smrg{
607e88f27b3Smrg    uint32_t xalign, yalign, zalign, tilew;
608e88f27b3Smrg    unsigned i;
609e88f27b3Smrg
610e88f27b3Smrg    /* compute alignment */
611e88f27b3Smrg    tilew = 8;
612e88f27b3Smrg    xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
613e88f27b3Smrg    xalign = MAX2(tilew, xalign);
614e88f27b3Smrg    yalign = tilew;
615e88f27b3Smrg    zalign = 1;
616e88f27b3Smrg    if (surf->flags & RADEON_SURF_SCANOUT) {
617e88f27b3Smrg        xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
618e88f27b3Smrg    }
619e88f27b3Smrg
620e88f27b3Smrg    if (!start_level) {
621e88f27b3Smrg        unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
622e88f27b3Smrg        surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
623e88f27b3Smrg
624e88f27b3Smrg        if (offset) {
625e88f27b3Smrg            offset = ALIGN(offset, alignment);
626e88f27b3Smrg        }
627e88f27b3Smrg    }
628e88f27b3Smrg
629e88f27b3Smrg    /* build mipmap tree */
630e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
631e88f27b3Smrg        level[i].mode = RADEON_SURF_MODE_1D;
632e88f27b3Smrg        surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
633e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
634e88f27b3Smrg        offset = surf->bo_size;
635aad13f10Swiz        if (i == 0) {
636e88f27b3Smrg            offset = ALIGN(offset, surf->bo_alignment);
637e88f27b3Smrg        }
638e88f27b3Smrg    }
639e88f27b3Smrg    return 0;
640e88f27b3Smrg}
641e88f27b3Smrg
642e88f27b3Smrgstatic int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
643e88f27b3Smrg                              struct radeon_surface *surf,
644e88f27b3Smrg                              struct radeon_surface_level *level,
645e88f27b3Smrg                              unsigned bpe, unsigned tile_split,
646e88f27b3Smrg                              uint64_t offset, unsigned start_level)
647e88f27b3Smrg{
648e88f27b3Smrg    unsigned tilew, tileh, tileb;
649e88f27b3Smrg    unsigned mtilew, mtileh, mtileb;
650e88f27b3Smrg    unsigned slice_pt;
651e88f27b3Smrg    unsigned i;
652e88f27b3Smrg
653e88f27b3Smrg    /* compute tile values */
654e88f27b3Smrg    tilew = 8;
655e88f27b3Smrg    tileh = 8;
656e88f27b3Smrg    tileb = tilew * tileh * bpe * surf->nsamples;
657e88f27b3Smrg    /* slices per tile */
658e88f27b3Smrg    slice_pt = 1;
659e88f27b3Smrg    if (tileb > tile_split && tile_split) {
660e88f27b3Smrg        slice_pt = tileb / tile_split;
661e88f27b3Smrg    }
662e88f27b3Smrg    tileb = tileb / slice_pt;
663e88f27b3Smrg
664e88f27b3Smrg    /* macro tile width & height */
665e88f27b3Smrg    mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
666e88f27b3Smrg    mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
667e88f27b3Smrg    /* macro tile bytes */
668e88f27b3Smrg    mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
669e88f27b3Smrg
670e88f27b3Smrg    if (!start_level) {
671e88f27b3Smrg        unsigned alignment = MAX2(256, mtileb);
672e88f27b3Smrg        surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
673e88f27b3Smrg
674e88f27b3Smrg        if (offset) {
675e88f27b3Smrg            offset = ALIGN(offset, alignment);
676e88f27b3Smrg        }
677e88f27b3Smrg    }
678e88f27b3Smrg
679e88f27b3Smrg    /* build mipmap tree */
680e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
681e88f27b3Smrg        level[i].mode = RADEON_SURF_MODE_2D;
682e88f27b3Smrg        eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
683e88f27b3Smrg        if (level[i].mode == RADEON_SURF_MODE_1D) {
684e88f27b3Smrg            return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
685e88f27b3Smrg        }
686e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
687e88f27b3Smrg        offset = surf->bo_size;
688aad13f10Swiz        if (i == 0) {
689e88f27b3Smrg            offset = ALIGN(offset, surf->bo_alignment);
690e88f27b3Smrg        }
691e88f27b3Smrg    }
692e88f27b3Smrg    return 0;
693e88f27b3Smrg}
694e88f27b3Smrg
695e88f27b3Smrgstatic int eg_surface_sanity(struct radeon_surface_manager *surf_man,
696e88f27b3Smrg                             struct radeon_surface *surf,
697e88f27b3Smrg                             unsigned mode)
698e88f27b3Smrg{
699e88f27b3Smrg    unsigned tileb;
700e88f27b3Smrg
701e88f27b3Smrg    /* check surface dimension */
702e88f27b3Smrg    if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
703e88f27b3Smrg        return -EINVAL;
704e88f27b3Smrg    }
705e88f27b3Smrg
706e88f27b3Smrg    /* check mipmap last_level */
707e88f27b3Smrg    if (surf->last_level > 15) {
708e88f27b3Smrg        return -EINVAL;
709e88f27b3Smrg    }
710e88f27b3Smrg
711e88f27b3Smrg    /* force 1d on kernel that can't do 2d */
712e88f27b3Smrg    if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
713e88f27b3Smrg        if (surf->nsamples > 1) {
714e88f27b3Smrg            fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
715e88f27b3Smrg            return -EFAULT;
716e88f27b3Smrg        }
717e88f27b3Smrg        mode = RADEON_SURF_MODE_1D;
718e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
719e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(mode, MODE);
720e88f27b3Smrg    }
721e88f27b3Smrg
722e88f27b3Smrg    /* check tile split */
723e88f27b3Smrg    if (mode == RADEON_SURF_MODE_2D) {
724e88f27b3Smrg        switch (surf->tile_split) {
725e88f27b3Smrg        case 64:
726e88f27b3Smrg        case 128:
727e88f27b3Smrg        case 256:
728e88f27b3Smrg        case 512:
729e88f27b3Smrg        case 1024:
730e88f27b3Smrg        case 2048:
731e88f27b3Smrg        case 4096:
732e88f27b3Smrg            break;
733e88f27b3Smrg        default:
734e88f27b3Smrg            return -EINVAL;
735e88f27b3Smrg        }
736e88f27b3Smrg        switch (surf->mtilea) {
737e88f27b3Smrg        case 1:
738e88f27b3Smrg        case 2:
739e88f27b3Smrg        case 4:
740e88f27b3Smrg        case 8:
741e88f27b3Smrg            break;
742e88f27b3Smrg        default:
743e88f27b3Smrg            return -EINVAL;
744e88f27b3Smrg        }
745e88f27b3Smrg        /* check aspect ratio */
746e88f27b3Smrg        if (surf_man->hw_info.num_banks < surf->mtilea) {
747e88f27b3Smrg            return -EINVAL;
748e88f27b3Smrg        }
749e88f27b3Smrg        /* check bank width */
750e88f27b3Smrg        switch (surf->bankw) {
751e88f27b3Smrg        case 1:
752e88f27b3Smrg        case 2:
753e88f27b3Smrg        case 4:
754e88f27b3Smrg        case 8:
755e88f27b3Smrg            break;
756e88f27b3Smrg        default:
757e88f27b3Smrg            return -EINVAL;
758e88f27b3Smrg        }
759e88f27b3Smrg        /* check bank height */
760e88f27b3Smrg        switch (surf->bankh) {
761e88f27b3Smrg        case 1:
762e88f27b3Smrg        case 2:
763e88f27b3Smrg        case 4:
764e88f27b3Smrg        case 8:
765e88f27b3Smrg            break;
766e88f27b3Smrg        default:
767e88f27b3Smrg            return -EINVAL;
768e88f27b3Smrg        }
769e88f27b3Smrg        tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
770e88f27b3Smrg        if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
771e88f27b3Smrg            return -EINVAL;
772e88f27b3Smrg        }
773e88f27b3Smrg    }
774e88f27b3Smrg
775e88f27b3Smrg    return 0;
776e88f27b3Smrg}
777e88f27b3Smrg
778e88f27b3Smrgstatic int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
779e88f27b3Smrg                                       struct radeon_surface *surf)
780e88f27b3Smrg{
781e88f27b3Smrg    unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
782e88f27b3Smrg    int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
783e88f27b3Smrg    /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
784e88f27b3Smrg    struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
785e88f27b3Smrg    struct radeon_surface_level *stencil_level =
786e88f27b3Smrg        (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
787e88f27b3Smrg
788e88f27b3Smrg    r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
789e88f27b3Smrg    if (r)
790e88f27b3Smrg        return r;
791e88f27b3Smrg
792e88f27b3Smrg    if (is_depth_stencil) {
793e88f27b3Smrg        r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
794e88f27b3Smrg                               surf->bo_size, 0);
795e88f27b3Smrg        surf->stencil_offset = stencil_level[0].offset;
796e88f27b3Smrg    }
797e88f27b3Smrg    return r;
798e88f27b3Smrg}
799e88f27b3Smrg
800e88f27b3Smrgstatic int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
801e88f27b3Smrg                                       struct radeon_surface *surf)
802e88f27b3Smrg{
803e88f27b3Smrg    unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
804e88f27b3Smrg    int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
805e88f27b3Smrg    /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
806e88f27b3Smrg    struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
807e88f27b3Smrg    struct radeon_surface_level *stencil_level =
808e88f27b3Smrg        (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
809e88f27b3Smrg
810e88f27b3Smrg    r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
811e88f27b3Smrg                           surf->tile_split, 0, 0);
812e88f27b3Smrg    if (r)
813e88f27b3Smrg        return r;
814e88f27b3Smrg
815e88f27b3Smrg    if (is_depth_stencil) {
816e88f27b3Smrg        r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
817e88f27b3Smrg                               surf->stencil_tile_split, surf->bo_size, 0);
818e88f27b3Smrg        surf->stencil_offset = stencil_level[0].offset;
819e88f27b3Smrg    }
820e88f27b3Smrg    return r;
821e88f27b3Smrg}
822e88f27b3Smrg
823e88f27b3Smrgstatic int eg_surface_init(struct radeon_surface_manager *surf_man,
824e88f27b3Smrg                           struct radeon_surface *surf)
825e88f27b3Smrg{
826e88f27b3Smrg    unsigned mode;
827e88f27b3Smrg    int r;
828e88f27b3Smrg
829e88f27b3Smrg    /* MSAA surfaces support the 2D mode only. */
830e88f27b3Smrg    if (surf->nsamples > 1) {
831e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
832e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
833e88f27b3Smrg    }
834e88f27b3Smrg
835e88f27b3Smrg    /* tiling mode */
836e88f27b3Smrg    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
837e88f27b3Smrg
838e88f27b3Smrg    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
839e88f27b3Smrg        /* zbuffer only support 1D or 2D tiled surface */
840e88f27b3Smrg        switch (mode) {
841e88f27b3Smrg        case RADEON_SURF_MODE_1D:
842e88f27b3Smrg        case RADEON_SURF_MODE_2D:
843e88f27b3Smrg            break;
844e88f27b3Smrg        default:
845e88f27b3Smrg            mode = RADEON_SURF_MODE_1D;
846e88f27b3Smrg            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
847e88f27b3Smrg            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
848e88f27b3Smrg            break;
849e88f27b3Smrg        }
850e88f27b3Smrg    }
851e88f27b3Smrg
852e88f27b3Smrg    r = eg_surface_sanity(surf_man, surf, mode);
853e88f27b3Smrg    if (r) {
854e88f27b3Smrg        return r;
855e88f27b3Smrg    }
856e88f27b3Smrg
857e88f27b3Smrg    surf->stencil_offset = 0;
858e88f27b3Smrg    surf->bo_alignment = 0;
859e88f27b3Smrg
860e88f27b3Smrg    /* check tiling mode */
861e88f27b3Smrg    switch (mode) {
862e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR:
863e88f27b3Smrg        r = r6_surface_init_linear(surf_man, surf, 0, 0);
864e88f27b3Smrg        break;
865e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR_ALIGNED:
866e88f27b3Smrg        r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
867e88f27b3Smrg        break;
868e88f27b3Smrg    case RADEON_SURF_MODE_1D:
869e88f27b3Smrg        r = eg_surface_init_1d_miptrees(surf_man, surf);
870e88f27b3Smrg        break;
871e88f27b3Smrg    case RADEON_SURF_MODE_2D:
872e88f27b3Smrg        r = eg_surface_init_2d_miptrees(surf_man, surf);
873e88f27b3Smrg        break;
874e88f27b3Smrg    default:
875e88f27b3Smrg        return -EINVAL;
876e88f27b3Smrg    }
877e88f27b3Smrg    return r;
878e88f27b3Smrg}
879e88f27b3Smrg
880e88f27b3Smrgstatic unsigned log2_int(unsigned x)
881e88f27b3Smrg{
882e88f27b3Smrg    unsigned l;
883e88f27b3Smrg
884e88f27b3Smrg    if (x < 2) {
885e88f27b3Smrg        return 0;
886e88f27b3Smrg    }
887e88f27b3Smrg    for (l = 2; ; l++) {
888e88f27b3Smrg        if ((unsigned)(1 << l) > x) {
889e88f27b3Smrg            return l - 1;
890e88f27b3Smrg        }
891e88f27b3Smrg    }
892e88f27b3Smrg    return 0;
893e88f27b3Smrg}
894e88f27b3Smrg
895e88f27b3Smrg/* compute best tile_split, bankw, bankh, mtilea
896e88f27b3Smrg * depending on surface
897e88f27b3Smrg */
898e88f27b3Smrgstatic int eg_surface_best(struct radeon_surface_manager *surf_man,
899e88f27b3Smrg                           struct radeon_surface *surf)
900e88f27b3Smrg{
901e88f27b3Smrg    unsigned mode, tileb, h_over_w;
902e88f27b3Smrg    int r;
903e88f27b3Smrg
904e88f27b3Smrg    /* tiling mode */
905e88f27b3Smrg    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
906e88f27b3Smrg
907e88f27b3Smrg    /* set some default value to avoid sanity check choking on them */
908e88f27b3Smrg    surf->tile_split = 1024;
909e88f27b3Smrg    surf->bankw = 1;
910e88f27b3Smrg    surf->bankh = 1;
911e88f27b3Smrg    surf->mtilea = surf_man->hw_info.num_banks;
912e88f27b3Smrg    tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
913e88f27b3Smrg    for (; surf->bankh <= 8; surf->bankh *= 2) {
914e88f27b3Smrg        if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
915e88f27b3Smrg            break;
916e88f27b3Smrg        }
917e88f27b3Smrg    }
918e88f27b3Smrg    if (surf->mtilea > 8) {
919e88f27b3Smrg        surf->mtilea = 8;
920e88f27b3Smrg    }
921e88f27b3Smrg
922e88f27b3Smrg    r = eg_surface_sanity(surf_man, surf, mode);
923e88f27b3Smrg    if (r) {
924e88f27b3Smrg        return r;
925e88f27b3Smrg    }
926e88f27b3Smrg
927e88f27b3Smrg    if (mode != RADEON_SURF_MODE_2D) {
928e88f27b3Smrg        /* nothing to do for non 2D tiled surface */
929e88f27b3Smrg        return 0;
930e88f27b3Smrg    }
931e88f27b3Smrg
932e88f27b3Smrg    /* Tweak TILE_SPLIT for performance here. */
933e88f27b3Smrg    if (surf->nsamples > 1) {
934e88f27b3Smrg        if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
935e88f27b3Smrg            switch (surf->nsamples) {
936e88f27b3Smrg            case 2:
937e88f27b3Smrg                surf->tile_split = 128;
938e88f27b3Smrg                break;
939e88f27b3Smrg            case 4:
940e88f27b3Smrg                surf->tile_split = 128;
941e88f27b3Smrg                break;
942e88f27b3Smrg            case 8:
943e88f27b3Smrg                surf->tile_split = 256;
944e88f27b3Smrg                break;
945e88f27b3Smrg            case 16: /* cayman only */
946e88f27b3Smrg                surf->tile_split = 512;
947e88f27b3Smrg                break;
948e88f27b3Smrg            default:
949e88f27b3Smrg                fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
950e88f27b3Smrg                        surf->nsamples, __LINE__);
951e88f27b3Smrg                return -EINVAL;
952e88f27b3Smrg            }
953e88f27b3Smrg            surf->stencil_tile_split = 64;
954e88f27b3Smrg        } else {
955e88f27b3Smrg            /* tile split must be >= 256 for colorbuffer surfaces */
956e88f27b3Smrg            surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
957e88f27b3Smrg            if (surf->tile_split > 4096)
958e88f27b3Smrg                surf->tile_split = 4096;
959e88f27b3Smrg        }
960e88f27b3Smrg    } else {
961e88f27b3Smrg        /* set tile split to row size */
962e88f27b3Smrg        surf->tile_split = surf_man->hw_info.row_size;
963e88f27b3Smrg        surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
964e88f27b3Smrg    }
965e88f27b3Smrg
966e88f27b3Smrg    /* bankw or bankh greater than 1 increase alignment requirement, not
967e88f27b3Smrg     * sure if it's worth using smaller bankw & bankh to stick with 2D
968e88f27b3Smrg     * tiling on small surface rather than falling back to 1D tiling.
969e88f27b3Smrg     * Use recommanded value based on tile size for now.
970e88f27b3Smrg     *
971e88f27b3Smrg     * fmask buffer has different optimal value figure them out once we
972e88f27b3Smrg     * use it.
973e88f27b3Smrg     */
974e88f27b3Smrg    if (surf->flags & RADEON_SURF_SBUFFER) {
975e88f27b3Smrg        /* assume 1 bytes for stencil, we optimize for stencil as stencil
976e88f27b3Smrg         * and depth shares surface values
977e88f27b3Smrg         */
978e88f27b3Smrg        tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
979e88f27b3Smrg    } else {
980e88f27b3Smrg        tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
981e88f27b3Smrg    }
982e88f27b3Smrg
983e88f27b3Smrg    /* use bankw of 1 to minimize width alignment, might be interesting to
984e88f27b3Smrg     * increase it for large surface
985e88f27b3Smrg     */
986e88f27b3Smrg    surf->bankw = 1;
987e88f27b3Smrg    switch (tileb) {
988e88f27b3Smrg    case 64:
989e88f27b3Smrg        surf->bankh = 4;
990e88f27b3Smrg        break;
991e88f27b3Smrg    case 128:
992e88f27b3Smrg    case 256:
993e88f27b3Smrg        surf->bankh = 2;
994e88f27b3Smrg        break;
995e88f27b3Smrg    default:
996e88f27b3Smrg        surf->bankh = 1;
997e88f27b3Smrg        break;
998e88f27b3Smrg    }
999e88f27b3Smrg    /* double check the constraint */
1000e88f27b3Smrg    for (; surf->bankh <= 8; surf->bankh *= 2) {
1001e88f27b3Smrg        if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
1002e88f27b3Smrg            break;
1003e88f27b3Smrg        }
1004e88f27b3Smrg    }
1005e88f27b3Smrg
1006e88f27b3Smrg    h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
1007e88f27b3Smrg                (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
1008e88f27b3Smrg    surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
1009e88f27b3Smrg
1010e88f27b3Smrg    return 0;
1011e88f27b3Smrg}
1012e88f27b3Smrg
1013e88f27b3Smrg
1014e88f27b3Smrg/* ===========================================================================
1015e88f27b3Smrg * Southern Islands family
1016e88f27b3Smrg */
1017e88f27b3Smrg#define SI__GB_TILE_MODE__PIPE_CONFIG(x)        (((x) >> 6) & 0x1f)
1018e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P2               0
1019e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P4_8x16          4
1020e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P4_16x16         5
1021e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P4_16x32         6
1022e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P4_32x32         7
1023e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16    8
1024e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16    9
1025e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16    10
1026e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16   11
1027e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16   12
1028e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32   13
1029e88f27b3Smrg#define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32   14
1030e88f27b3Smrg#define SI__GB_TILE_MODE__TILE_SPLIT(x)         (((x) >> 11) & 0x7)
1031e88f27b3Smrg#define     SI__TILE_SPLIT__64B                         0
1032e88f27b3Smrg#define     SI__TILE_SPLIT__128B                        1
1033e88f27b3Smrg#define     SI__TILE_SPLIT__256B                        2
1034e88f27b3Smrg#define     SI__TILE_SPLIT__512B                        3
1035e88f27b3Smrg#define     SI__TILE_SPLIT__1024B                       4
1036e88f27b3Smrg#define     SI__TILE_SPLIT__2048B                       5
1037e88f27b3Smrg#define     SI__TILE_SPLIT__4096B                       6
1038e88f27b3Smrg#define SI__GB_TILE_MODE__BANK_WIDTH(x)         (((x) >> 14) & 0x3)
1039e88f27b3Smrg#define     SI__BANK_WIDTH__1                           0
1040e88f27b3Smrg#define     SI__BANK_WIDTH__2                           1
1041e88f27b3Smrg#define     SI__BANK_WIDTH__4                           2
1042e88f27b3Smrg#define     SI__BANK_WIDTH__8                           3
1043e88f27b3Smrg#define SI__GB_TILE_MODE__BANK_HEIGHT(x)        (((x) >> 16) & 0x3)
1044e88f27b3Smrg#define     SI__BANK_HEIGHT__1                          0
1045e88f27b3Smrg#define     SI__BANK_HEIGHT__2                          1
1046e88f27b3Smrg#define     SI__BANK_HEIGHT__4                          2
1047e88f27b3Smrg#define     SI__BANK_HEIGHT__8                          3
1048e88f27b3Smrg#define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x)  (((x) >> 18) & 0x3)
1049e88f27b3Smrg#define     SI__MACRO_TILE_ASPECT__1                    0
1050e88f27b3Smrg#define     SI__MACRO_TILE_ASPECT__2                    1
1051e88f27b3Smrg#define     SI__MACRO_TILE_ASPECT__4                    2
1052e88f27b3Smrg#define     SI__MACRO_TILE_ASPECT__8                    3
1053e88f27b3Smrg#define SI__GB_TILE_MODE__NUM_BANKS(x)          (((x) >> 20) & 0x3)
1054e88f27b3Smrg#define     SI__NUM_BANKS__2_BANK                       0
1055e88f27b3Smrg#define     SI__NUM_BANKS__4_BANK                       1
1056e88f27b3Smrg#define     SI__NUM_BANKS__8_BANK                       2
1057e88f27b3Smrg#define     SI__NUM_BANKS__16_BANK                      3
1058e88f27b3Smrg
1059e88f27b3Smrg
1060e88f27b3Smrgstatic void si_gb_tile_mode(uint32_t gb_tile_mode,
1061e88f27b3Smrg                            unsigned *num_pipes,
1062e88f27b3Smrg                            unsigned *num_banks,
1063e88f27b3Smrg                            uint32_t *macro_tile_aspect,
1064e88f27b3Smrg                            uint32_t *bank_w,
1065e88f27b3Smrg                            uint32_t *bank_h,
1066e88f27b3Smrg                            uint32_t *tile_split)
1067e88f27b3Smrg{
1068e88f27b3Smrg    if (num_pipes) {
1069e88f27b3Smrg        switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1070e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P2:
1071e88f27b3Smrg        default:
1072e88f27b3Smrg            *num_pipes = 2;
1073e88f27b3Smrg            break;
1074e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1075e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1076e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1077e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1078e88f27b3Smrg            *num_pipes = 4;
1079e88f27b3Smrg            break;
1080e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1081e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1082e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1083e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1084e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1085e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1086e88f27b3Smrg        case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1087e88f27b3Smrg            *num_pipes = 8;
1088e88f27b3Smrg            break;
1089e88f27b3Smrg        }
1090e88f27b3Smrg    }
1091e88f27b3Smrg    if (num_banks) {
1092e88f27b3Smrg        switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
1093e88f27b3Smrg        default:
1094e88f27b3Smrg        case SI__NUM_BANKS__2_BANK:
1095e88f27b3Smrg            *num_banks = 2;
1096e88f27b3Smrg            break;
1097e88f27b3Smrg        case SI__NUM_BANKS__4_BANK:
1098e88f27b3Smrg            *num_banks = 4;
1099e88f27b3Smrg            break;
1100e88f27b3Smrg        case SI__NUM_BANKS__8_BANK:
1101e88f27b3Smrg            *num_banks = 8;
1102e88f27b3Smrg            break;
1103e88f27b3Smrg        case SI__NUM_BANKS__16_BANK:
1104e88f27b3Smrg            *num_banks = 16;
1105e88f27b3Smrg            break;
1106e88f27b3Smrg        }
1107e88f27b3Smrg    }
1108e88f27b3Smrg    if (macro_tile_aspect) {
1109e88f27b3Smrg        switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
1110e88f27b3Smrg        default:
1111e88f27b3Smrg        case SI__MACRO_TILE_ASPECT__1:
1112e88f27b3Smrg            *macro_tile_aspect = 1;
1113e88f27b3Smrg            break;
1114e88f27b3Smrg        case SI__MACRO_TILE_ASPECT__2:
1115e88f27b3Smrg            *macro_tile_aspect = 2;
1116e88f27b3Smrg            break;
1117e88f27b3Smrg        case SI__MACRO_TILE_ASPECT__4:
1118e88f27b3Smrg            *macro_tile_aspect = 4;
1119e88f27b3Smrg            break;
1120e88f27b3Smrg        case SI__MACRO_TILE_ASPECT__8:
1121e88f27b3Smrg            *macro_tile_aspect = 8;
1122e88f27b3Smrg            break;
1123e88f27b3Smrg        }
1124e88f27b3Smrg    }
1125e88f27b3Smrg    if (bank_w) {
1126e88f27b3Smrg        switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
1127e88f27b3Smrg        default:
1128e88f27b3Smrg        case SI__BANK_WIDTH__1:
1129e88f27b3Smrg            *bank_w = 1;
1130e88f27b3Smrg            break;
1131e88f27b3Smrg        case SI__BANK_WIDTH__2:
1132e88f27b3Smrg            *bank_w = 2;
1133e88f27b3Smrg            break;
1134e88f27b3Smrg        case SI__BANK_WIDTH__4:
1135e88f27b3Smrg            *bank_w = 4;
1136e88f27b3Smrg            break;
1137e88f27b3Smrg        case SI__BANK_WIDTH__8:
1138e88f27b3Smrg            *bank_w = 8;
1139e88f27b3Smrg            break;
1140e88f27b3Smrg        }
1141e88f27b3Smrg    }
1142e88f27b3Smrg    if (bank_h) {
1143e88f27b3Smrg        switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
1144e88f27b3Smrg        default:
1145e88f27b3Smrg        case SI__BANK_HEIGHT__1:
1146e88f27b3Smrg            *bank_h = 1;
1147e88f27b3Smrg            break;
1148e88f27b3Smrg        case SI__BANK_HEIGHT__2:
1149e88f27b3Smrg            *bank_h = 2;
1150e88f27b3Smrg            break;
1151e88f27b3Smrg        case SI__BANK_HEIGHT__4:
1152e88f27b3Smrg            *bank_h = 4;
1153e88f27b3Smrg            break;
1154e88f27b3Smrg        case SI__BANK_HEIGHT__8:
1155e88f27b3Smrg            *bank_h = 8;
1156e88f27b3Smrg            break;
1157e88f27b3Smrg        }
1158e88f27b3Smrg    }
1159e88f27b3Smrg    if (tile_split) {
1160e88f27b3Smrg        switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1161e88f27b3Smrg        default:
1162e88f27b3Smrg        case SI__TILE_SPLIT__64B:
1163e88f27b3Smrg            *tile_split = 64;
1164e88f27b3Smrg            break;
1165e88f27b3Smrg        case SI__TILE_SPLIT__128B:
1166e88f27b3Smrg            *tile_split = 128;
1167e88f27b3Smrg            break;
1168e88f27b3Smrg        case SI__TILE_SPLIT__256B:
1169e88f27b3Smrg            *tile_split = 256;
1170e88f27b3Smrg            break;
1171e88f27b3Smrg        case SI__TILE_SPLIT__512B:
1172e88f27b3Smrg            *tile_split = 512;
1173e88f27b3Smrg            break;
1174e88f27b3Smrg        case SI__TILE_SPLIT__1024B:
1175e88f27b3Smrg            *tile_split = 1024;
1176e88f27b3Smrg            break;
1177e88f27b3Smrg        case SI__TILE_SPLIT__2048B:
1178e88f27b3Smrg            *tile_split = 2048;
1179e88f27b3Smrg            break;
1180e88f27b3Smrg        case SI__TILE_SPLIT__4096B:
1181e88f27b3Smrg            *tile_split = 4096;
1182e88f27b3Smrg            break;
1183e88f27b3Smrg        }
1184e88f27b3Smrg    }
1185e88f27b3Smrg}
1186e88f27b3Smrg
1187e88f27b3Smrgstatic int si_init_hw_info(struct radeon_surface_manager *surf_man)
1188e88f27b3Smrg{
1189e88f27b3Smrg    uint32_t tiling_config;
1190e88f27b3Smrg    drmVersionPtr version;
1191e88f27b3Smrg    int r;
1192e88f27b3Smrg
1193e88f27b3Smrg    r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
1194e88f27b3Smrg                         &tiling_config);
1195e88f27b3Smrg    if (r) {
1196e88f27b3Smrg        return r;
1197e88f27b3Smrg    }
1198e88f27b3Smrg
1199e88f27b3Smrg    surf_man->hw_info.allow_2d = 0;
1200e88f27b3Smrg    version = drmGetVersion(surf_man->fd);
1201e88f27b3Smrg    if (version && version->version_minor >= 33) {
1202e88f27b3Smrg        if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
1203e88f27b3Smrg            surf_man->hw_info.allow_2d = 1;
1204e88f27b3Smrg        }
1205e88f27b3Smrg    }
1206e88f27b3Smrg    drmFreeVersion(version);
1207e88f27b3Smrg
1208e88f27b3Smrg    switch (tiling_config & 0xf) {
1209e88f27b3Smrg    case 0:
1210e88f27b3Smrg        surf_man->hw_info.num_pipes = 1;
1211e88f27b3Smrg        break;
1212e88f27b3Smrg    case 1:
1213e88f27b3Smrg        surf_man->hw_info.num_pipes = 2;
1214e88f27b3Smrg        break;
1215e88f27b3Smrg    case 2:
1216e88f27b3Smrg        surf_man->hw_info.num_pipes = 4;
1217e88f27b3Smrg        break;
1218e88f27b3Smrg    case 3:
1219e88f27b3Smrg        surf_man->hw_info.num_pipes = 8;
1220e88f27b3Smrg        break;
1221e88f27b3Smrg    default:
1222e88f27b3Smrg        surf_man->hw_info.num_pipes = 8;
1223e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
1224e88f27b3Smrg        break;
1225e88f27b3Smrg    }
1226e88f27b3Smrg
1227e88f27b3Smrg    switch ((tiling_config & 0xf0) >> 4) {
1228e88f27b3Smrg    case 0:
1229e88f27b3Smrg        surf_man->hw_info.num_banks = 4;
1230e88f27b3Smrg        break;
1231e88f27b3Smrg    case 1:
1232e88f27b3Smrg        surf_man->hw_info.num_banks = 8;
1233e88f27b3Smrg        break;
1234e88f27b3Smrg    case 2:
1235e88f27b3Smrg        surf_man->hw_info.num_banks = 16;
1236e88f27b3Smrg        break;
1237e88f27b3Smrg    default:
1238e88f27b3Smrg        surf_man->hw_info.num_banks = 8;
1239e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
1240e88f27b3Smrg        break;
1241e88f27b3Smrg    }
1242e88f27b3Smrg
1243e88f27b3Smrg    switch ((tiling_config & 0xf00) >> 8) {
1244e88f27b3Smrg    case 0:
1245e88f27b3Smrg        surf_man->hw_info.group_bytes = 256;
1246e88f27b3Smrg        break;
1247e88f27b3Smrg    case 1:
1248e88f27b3Smrg        surf_man->hw_info.group_bytes = 512;
1249e88f27b3Smrg        break;
1250e88f27b3Smrg    default:
1251e88f27b3Smrg        surf_man->hw_info.group_bytes = 256;
1252e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
1253e88f27b3Smrg        break;
1254e88f27b3Smrg    }
1255e88f27b3Smrg
1256e88f27b3Smrg    switch ((tiling_config & 0xf000) >> 12) {
1257e88f27b3Smrg    case 0:
1258e88f27b3Smrg        surf_man->hw_info.row_size = 1024;
1259e88f27b3Smrg        break;
1260e88f27b3Smrg    case 1:
1261e88f27b3Smrg        surf_man->hw_info.row_size = 2048;
1262e88f27b3Smrg        break;
1263e88f27b3Smrg    case 2:
1264e88f27b3Smrg        surf_man->hw_info.row_size = 4096;
1265e88f27b3Smrg        break;
1266e88f27b3Smrg    default:
1267e88f27b3Smrg        surf_man->hw_info.row_size = 4096;
1268e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
1269e88f27b3Smrg        break;
1270e88f27b3Smrg    }
1271e88f27b3Smrg    return 0;
1272e88f27b3Smrg}
1273e88f27b3Smrg
1274e88f27b3Smrgstatic int si_surface_sanity(struct radeon_surface_manager *surf_man,
1275e88f27b3Smrg                             struct radeon_surface *surf,
1276e88f27b3Smrg                             unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
1277e88f27b3Smrg{
1278e88f27b3Smrg    uint32_t gb_tile_mode;
1279e88f27b3Smrg
1280e88f27b3Smrg    /* check surface dimension */
1281e88f27b3Smrg    if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
1282e88f27b3Smrg        return -EINVAL;
1283e88f27b3Smrg    }
1284e88f27b3Smrg
1285e88f27b3Smrg    /* check mipmap last_level */
1286e88f27b3Smrg    if (surf->last_level > 15) {
1287e88f27b3Smrg        return -EINVAL;
1288e88f27b3Smrg    }
1289e88f27b3Smrg
1290e88f27b3Smrg    /* force 1d on kernel that can't do 2d */
1291e88f27b3Smrg    if (mode > RADEON_SURF_MODE_1D &&
1292e88f27b3Smrg        (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
1293e88f27b3Smrg        if (surf->nsamples > 1) {
1294e88f27b3Smrg            fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
1295e88f27b3Smrg            return -EFAULT;
1296e88f27b3Smrg        }
1297e88f27b3Smrg        mode = RADEON_SURF_MODE_1D;
1298e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1299e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(mode, MODE);
1300e88f27b3Smrg    }
1301e88f27b3Smrg
1302e88f27b3Smrg    if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
1303e88f27b3Smrg        return -EINVAL;
1304e88f27b3Smrg    }
1305e88f27b3Smrg
1306e88f27b3Smrg    if (!surf->tile_split) {
1307e88f27b3Smrg        /* default value */
1308e88f27b3Smrg        surf->mtilea = 1;
1309e88f27b3Smrg        surf->bankw = 1;
1310e88f27b3Smrg        surf->bankw = 1;
1311e88f27b3Smrg        surf->tile_split = 64;
1312e88f27b3Smrg        surf->stencil_tile_split = 64;
1313e88f27b3Smrg    }
1314e88f27b3Smrg
1315e88f27b3Smrg    switch (mode) {
1316e88f27b3Smrg    case RADEON_SURF_MODE_2D:
1317e88f27b3Smrg        if (surf->flags & RADEON_SURF_SBUFFER) {
1318e88f27b3Smrg            switch (surf->nsamples) {
1319e88f27b3Smrg            case 1:
1320e88f27b3Smrg                *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1321e88f27b3Smrg                break;
1322e88f27b3Smrg            case 2:
1323e88f27b3Smrg                *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1324e88f27b3Smrg                break;
1325e88f27b3Smrg            case 4:
1326e88f27b3Smrg                *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1327e88f27b3Smrg                break;
1328e88f27b3Smrg            case 8:
1329e88f27b3Smrg                *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1330e88f27b3Smrg                break;
1331e88f27b3Smrg            default:
1332e88f27b3Smrg                return -EINVAL;
1333e88f27b3Smrg            }
1334e88f27b3Smrg            /* retrieve tiling mode value */
1335e88f27b3Smrg            gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
1336e88f27b3Smrg            si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
1337e88f27b3Smrg        }
1338e88f27b3Smrg        if (surf->flags & RADEON_SURF_ZBUFFER) {
1339e88f27b3Smrg            switch (surf->nsamples) {
1340e88f27b3Smrg            case 1:
1341e88f27b3Smrg                *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1342e88f27b3Smrg                break;
1343e88f27b3Smrg            case 2:
1344e88f27b3Smrg                *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1345e88f27b3Smrg                break;
1346e88f27b3Smrg            case 4:
1347e88f27b3Smrg                *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1348e88f27b3Smrg                break;
1349e88f27b3Smrg            case 8:
1350e88f27b3Smrg                *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1351e88f27b3Smrg                break;
1352e88f27b3Smrg            default:
1353e88f27b3Smrg                return -EINVAL;
1354e88f27b3Smrg            }
1355e88f27b3Smrg        } else if (surf->flags & RADEON_SURF_SCANOUT) {
1356e88f27b3Smrg            switch (surf->bpe) {
1357e88f27b3Smrg            case 2:
1358e88f27b3Smrg                *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
1359e88f27b3Smrg                break;
1360e88f27b3Smrg            case 4:
1361e88f27b3Smrg                *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
1362e88f27b3Smrg                break;
1363e88f27b3Smrg            default:
1364e88f27b3Smrg                return -EINVAL;
1365e88f27b3Smrg            }
1366e88f27b3Smrg        } else {
1367e88f27b3Smrg            switch (surf->bpe) {
1368e88f27b3Smrg            case 1:
1369e88f27b3Smrg                *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
1370e88f27b3Smrg                break;
1371e88f27b3Smrg            case 2:
1372e88f27b3Smrg                *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
1373e88f27b3Smrg                break;
1374e88f27b3Smrg            case 4:
1375e88f27b3Smrg                *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
1376e88f27b3Smrg                break;
1377e88f27b3Smrg            case 8:
1378e88f27b3Smrg            case 16:
1379e88f27b3Smrg                *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
1380e88f27b3Smrg                break;
1381e88f27b3Smrg            default:
1382e88f27b3Smrg                return -EINVAL;
1383e88f27b3Smrg            }
1384e88f27b3Smrg        }
1385e88f27b3Smrg        /* retrieve tiling mode value */
1386e88f27b3Smrg        gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
1387e88f27b3Smrg        si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
1388e88f27b3Smrg        break;
1389e88f27b3Smrg    case RADEON_SURF_MODE_1D:
1390e88f27b3Smrg        if (surf->flags & RADEON_SURF_SBUFFER) {
1391e88f27b3Smrg            *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1392e88f27b3Smrg        }
1393e88f27b3Smrg        if (surf->flags & RADEON_SURF_ZBUFFER) {
1394e88f27b3Smrg            *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1395e88f27b3Smrg        } else if (surf->flags & RADEON_SURF_SCANOUT) {
1396e88f27b3Smrg            *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1397e88f27b3Smrg        } else {
1398e88f27b3Smrg            *tile_mode = SI_TILE_MODE_COLOR_1D;
1399e88f27b3Smrg        }
1400e88f27b3Smrg        break;
1401e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR_ALIGNED:
1402e88f27b3Smrg    default:
1403e88f27b3Smrg        *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
1404e88f27b3Smrg    }
1405e88f27b3Smrg
1406e88f27b3Smrg    return 0;
1407e88f27b3Smrg}
1408e88f27b3Smrg
1409e88f27b3Smrgstatic void si_surf_minify(struct radeon_surface *surf,
1410e88f27b3Smrg                           struct radeon_surface_level *surflevel,
1411e88f27b3Smrg                           unsigned bpe, unsigned level,
1412e88f27b3Smrg                           uint32_t xalign, uint32_t yalign, uint32_t zalign,
1413e88f27b3Smrg                           uint32_t slice_align, unsigned offset)
1414e88f27b3Smrg{
1415e88f27b3Smrg    if (level == 0) {
1416e88f27b3Smrg        surflevel->npix_x = surf->npix_x;
1417e88f27b3Smrg    } else {
1418e88f27b3Smrg        surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1419e88f27b3Smrg    }
1420e88f27b3Smrg    surflevel->npix_y = mip_minify(surf->npix_y, level);
1421e88f27b3Smrg    surflevel->npix_z = mip_minify(surf->npix_z, level);
1422e88f27b3Smrg
1423e88f27b3Smrg    if (level == 0 && surf->last_level > 0) {
1424e88f27b3Smrg        surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1425e88f27b3Smrg        surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1426e88f27b3Smrg        surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1427e88f27b3Smrg    } else {
1428e88f27b3Smrg        surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1429e88f27b3Smrg        surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1430e88f27b3Smrg        surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1431e88f27b3Smrg    }
1432e88f27b3Smrg
1433e88f27b3Smrg    surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
1434e88f27b3Smrg
1435e88f27b3Smrg    /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1436e88f27b3Smrg     * these are just guesses for the rules behind those
1437e88f27b3Smrg     */
1438e88f27b3Smrg    if (level == 0 && surf->last_level == 0)
1439e88f27b3Smrg        /* Non-mipmap pitch padded to slice alignment */
1440e88f27b3Smrg        /* Using just bpe here breaks stencil blitting; surf->bpe works. */
1441e88f27b3Smrg        xalign = MAX2(xalign, slice_align / surf->bpe);
1442e88f27b3Smrg    else if (surflevel->mode == RADEON_SURF_MODE_LINEAR_ALIGNED)
1443e88f27b3Smrg        /* Small rows evenly distributed across slice */
1444e88f27b3Smrg        xalign = MAX2(xalign, slice_align / bpe / surflevel->nblk_y);
1445e88f27b3Smrg
1446e88f27b3Smrg    surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
1447e88f27b3Smrg    surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
1448e88f27b3Smrg
1449e88f27b3Smrg    surflevel->offset = offset;
1450e88f27b3Smrg    surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
1451e88f27b3Smrg    surflevel->slice_size = ALIGN(surflevel->pitch_bytes * surflevel->nblk_y, slice_align);
1452e88f27b3Smrg
1453e88f27b3Smrg    surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1454e88f27b3Smrg}
1455e88f27b3Smrg
1456e88f27b3Smrgstatic void si_surf_minify_2d(struct radeon_surface *surf,
1457e88f27b3Smrg                              struct radeon_surface_level *surflevel,
1458e88f27b3Smrg                              unsigned bpe, unsigned level, unsigned slice_pt,
1459e88f27b3Smrg                              uint32_t xalign, uint32_t yalign, uint32_t zalign,
1460e88f27b3Smrg                              unsigned mtileb, unsigned offset)
1461e88f27b3Smrg{
1462e88f27b3Smrg    unsigned mtile_pr, mtile_ps;
1463e88f27b3Smrg
1464e88f27b3Smrg    if (level == 0) {
1465e88f27b3Smrg        surflevel->npix_x = surf->npix_x;
1466e88f27b3Smrg    } else {
1467e88f27b3Smrg        surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1468e88f27b3Smrg    }
1469e88f27b3Smrg    surflevel->npix_y = mip_minify(surf->npix_y, level);
1470e88f27b3Smrg    surflevel->npix_z = mip_minify(surf->npix_z, level);
1471e88f27b3Smrg
1472e88f27b3Smrg    if (level == 0 && surf->last_level > 0) {
1473e88f27b3Smrg        surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1474e88f27b3Smrg        surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1475e88f27b3Smrg        surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1476e88f27b3Smrg    } else {
1477e88f27b3Smrg        surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1478e88f27b3Smrg        surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1479e88f27b3Smrg        surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1480e88f27b3Smrg    }
1481e88f27b3Smrg
1482e88f27b3Smrg    if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
1483e88f27b3Smrg        !(surf->flags & RADEON_SURF_FMASK)) {
1484e88f27b3Smrg        if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
1485e88f27b3Smrg            surflevel->mode = RADEON_SURF_MODE_1D;
1486e88f27b3Smrg            return;
1487e88f27b3Smrg        }
1488e88f27b3Smrg    }
1489e88f27b3Smrg    surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
1490e88f27b3Smrg    surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
1491e88f27b3Smrg    surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
1492e88f27b3Smrg
1493e88f27b3Smrg    /* macro tile per row */
1494e88f27b3Smrg    mtile_pr = surflevel->nblk_x / xalign;
1495e88f27b3Smrg    /* macro tile per slice */
1496e88f27b3Smrg    mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
1497e88f27b3Smrg    surflevel->offset = offset;
1498e88f27b3Smrg    surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
1499e88f27b3Smrg    surflevel->slice_size = mtile_ps * mtileb * slice_pt;
1500e88f27b3Smrg
1501e88f27b3Smrg    surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1502e88f27b3Smrg}
1503e88f27b3Smrg
1504e88f27b3Smrgstatic int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1505e88f27b3Smrg                                          struct radeon_surface *surf,
1506e88f27b3Smrg                                          unsigned tile_mode,
1507e88f27b3Smrg                                          uint64_t offset, unsigned start_level)
1508e88f27b3Smrg{
1509e88f27b3Smrg    uint32_t xalign, yalign, zalign, slice_align;
1510e88f27b3Smrg    unsigned i;
1511e88f27b3Smrg
1512e88f27b3Smrg    /* compute alignment */
1513e88f27b3Smrg    if (!start_level) {
1514e88f27b3Smrg        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1515e88f27b3Smrg    }
1516e88f27b3Smrg    xalign = MAX2(8, 64 / surf->bpe);
1517e88f27b3Smrg    yalign = 1;
1518e88f27b3Smrg    zalign = 1;
1519e88f27b3Smrg    slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1520e88f27b3Smrg
1521e88f27b3Smrg    /* build mipmap tree */
1522e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
1523e88f27b3Smrg        surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1524e88f27b3Smrg        si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
1525e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
1526e88f27b3Smrg        offset = surf->bo_size;
1527aad13f10Swiz        if (i == 0) {
1528e88f27b3Smrg            offset = ALIGN(offset, surf->bo_alignment);
1529e88f27b3Smrg        }
1530e88f27b3Smrg        if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1531e88f27b3Smrg            surf->tiling_index[i] = tile_mode;
1532e88f27b3Smrg        }
1533e88f27b3Smrg    }
1534e88f27b3Smrg    return 0;
1535e88f27b3Smrg}
1536e88f27b3Smrg
1537e88f27b3Smrgstatic int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1538e88f27b3Smrg                              struct radeon_surface *surf,
1539e88f27b3Smrg                              struct radeon_surface_level *level,
1540e88f27b3Smrg                              unsigned bpe, unsigned tile_mode,
1541e88f27b3Smrg                              uint64_t offset, unsigned start_level)
1542e88f27b3Smrg{
1543e88f27b3Smrg    uint32_t xalign, yalign, zalign, slice_align;
1544e88f27b3Smrg    unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
1545e88f27b3Smrg    unsigned i;
1546e88f27b3Smrg
1547e88f27b3Smrg    /* compute alignment */
1548e88f27b3Smrg    xalign = 8;
1549e88f27b3Smrg    yalign = 8;
1550e88f27b3Smrg    zalign = 1;
1551e88f27b3Smrg    slice_align = surf_man->hw_info.group_bytes;
1552e88f27b3Smrg    if (surf->flags & RADEON_SURF_SCANOUT) {
1553e88f27b3Smrg        xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1554e88f27b3Smrg    }
1555e88f27b3Smrg
1556e88f27b3Smrg    if (start_level <= 1) {
1557e88f27b3Smrg        surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1558e88f27b3Smrg
1559e88f27b3Smrg        if (offset) {
1560e88f27b3Smrg            offset = ALIGN(offset, alignment);
1561e88f27b3Smrg        }
1562e88f27b3Smrg    }
1563e88f27b3Smrg
1564e88f27b3Smrg    /* build mipmap tree */
1565e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
1566e88f27b3Smrg        level[i].mode = RADEON_SURF_MODE_1D;
1567e88f27b3Smrg        si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1568e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
1569e88f27b3Smrg        offset = surf->bo_size;
1570aad13f10Swiz        if (i == 0) {
1571e88f27b3Smrg            offset = ALIGN(offset, alignment);
1572e88f27b3Smrg        }
1573e88f27b3Smrg        if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1574e88f27b3Smrg            if (surf->level == level) {
1575e88f27b3Smrg                surf->tiling_index[i] = tile_mode;
1576e88f27b3Smrg                /* it's ok because stencil is done after */
1577e88f27b3Smrg                surf->stencil_tiling_index[i] = tile_mode;
1578e88f27b3Smrg            } else {
1579e88f27b3Smrg                surf->stencil_tiling_index[i] = tile_mode;
1580e88f27b3Smrg            }
1581e88f27b3Smrg        }
1582e88f27b3Smrg    }
1583e88f27b3Smrg    return 0;
1584e88f27b3Smrg}
1585e88f27b3Smrg
1586e88f27b3Smrgstatic int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1587e88f27b3Smrg                                       struct radeon_surface *surf,
1588e88f27b3Smrg                                       unsigned tile_mode, unsigned stencil_tile_mode)
1589e88f27b3Smrg{
1590e88f27b3Smrg    int r;
1591e88f27b3Smrg
1592e88f27b3Smrg    r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
1593e88f27b3Smrg    if (r) {
1594e88f27b3Smrg        return r;
1595e88f27b3Smrg    }
1596e88f27b3Smrg
1597e88f27b3Smrg    if (surf->flags & RADEON_SURF_SBUFFER) {
1598e88f27b3Smrg        r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
1599e88f27b3Smrg        surf->stencil_offset = surf->stencil_level[0].offset;
1600e88f27b3Smrg    }
1601e88f27b3Smrg    return r;
1602e88f27b3Smrg}
1603e88f27b3Smrg
1604e88f27b3Smrgstatic int si_surface_init_2d(struct radeon_surface_manager *surf_man,
1605e88f27b3Smrg                              struct radeon_surface *surf,
1606e88f27b3Smrg                              struct radeon_surface_level *level,
1607e88f27b3Smrg                              unsigned bpe, unsigned tile_mode,
1608e88f27b3Smrg                              unsigned num_pipes, unsigned num_banks,
1609e88f27b3Smrg                              unsigned tile_split,
1610e88f27b3Smrg                              uint64_t offset,
1611e88f27b3Smrg                              unsigned start_level)
1612e88f27b3Smrg{
1613e88f27b3Smrg    uint64_t aligned_offset = offset;
1614e88f27b3Smrg    unsigned tilew, tileh, tileb;
1615e88f27b3Smrg    unsigned mtilew, mtileh, mtileb;
1616e88f27b3Smrg    unsigned slice_pt;
1617e88f27b3Smrg    unsigned i;
1618e88f27b3Smrg
1619e88f27b3Smrg    /* compute tile values */
1620e88f27b3Smrg    tilew = 8;
1621e88f27b3Smrg    tileh = 8;
1622e88f27b3Smrg    tileb = tilew * tileh * bpe * surf->nsamples;
1623e88f27b3Smrg    /* slices per tile */
1624e88f27b3Smrg    slice_pt = 1;
1625e88f27b3Smrg    if (tileb > tile_split && tile_split) {
1626e88f27b3Smrg        slice_pt = tileb / tile_split;
1627e88f27b3Smrg    }
1628e88f27b3Smrg    tileb = tileb / slice_pt;
1629e88f27b3Smrg
1630e88f27b3Smrg    /* macro tile width & height */
1631e88f27b3Smrg    mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
1632e88f27b3Smrg    mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
1633e88f27b3Smrg
1634e88f27b3Smrg    /* macro tile bytes */
1635e88f27b3Smrg    mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
1636e88f27b3Smrg
1637e88f27b3Smrg    if (start_level <= 1) {
1638e88f27b3Smrg        unsigned alignment = MAX2(256, mtileb);
1639e88f27b3Smrg        surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1640e88f27b3Smrg
1641e88f27b3Smrg        if (aligned_offset) {
1642e88f27b3Smrg            aligned_offset = ALIGN(aligned_offset, alignment);
1643e88f27b3Smrg        }
1644e88f27b3Smrg    }
1645e88f27b3Smrg
1646e88f27b3Smrg    /* build mipmap tree */
1647e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
1648e88f27b3Smrg        level[i].mode = RADEON_SURF_MODE_2D;
1649e88f27b3Smrg        si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
1650e88f27b3Smrg        if (level[i].mode == RADEON_SURF_MODE_1D) {
1651e88f27b3Smrg            switch (tile_mode) {
1652e88f27b3Smrg            case SI_TILE_MODE_COLOR_2D_8BPP:
1653e88f27b3Smrg            case SI_TILE_MODE_COLOR_2D_16BPP:
1654e88f27b3Smrg            case SI_TILE_MODE_COLOR_2D_32BPP:
1655e88f27b3Smrg            case SI_TILE_MODE_COLOR_2D_64BPP:
1656e88f27b3Smrg                tile_mode = SI_TILE_MODE_COLOR_1D;
1657e88f27b3Smrg                break;
1658e88f27b3Smrg            case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
1659e88f27b3Smrg            case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
1660e88f27b3Smrg                tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1661e88f27b3Smrg                break;
1662e88f27b3Smrg            case SI_TILE_MODE_DEPTH_STENCIL_2D:
1663e88f27b3Smrg                tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1664e88f27b3Smrg                break;
1665e88f27b3Smrg            default:
1666e88f27b3Smrg                return -EINVAL;
1667e88f27b3Smrg            }
1668e88f27b3Smrg            return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
1669e88f27b3Smrg        }
1670e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
1671e88f27b3Smrg        aligned_offset = offset = surf->bo_size;
1672aad13f10Swiz        if (i == 0) {
1673e88f27b3Smrg            aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
1674e88f27b3Smrg        }
1675e88f27b3Smrg        if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1676e88f27b3Smrg            if (surf->level == level) {
1677e88f27b3Smrg                surf->tiling_index[i] = tile_mode;
1678e88f27b3Smrg                /* it's ok because stencil is done after */
1679e88f27b3Smrg                surf->stencil_tiling_index[i] = tile_mode;
1680e88f27b3Smrg            } else {
1681e88f27b3Smrg                surf->stencil_tiling_index[i] = tile_mode;
1682e88f27b3Smrg            }
1683e88f27b3Smrg        }
1684e88f27b3Smrg    }
1685e88f27b3Smrg    return 0;
1686e88f27b3Smrg}
1687e88f27b3Smrg
1688e88f27b3Smrgstatic int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
1689e88f27b3Smrg                                       struct radeon_surface *surf,
1690e88f27b3Smrg                                       unsigned tile_mode, unsigned stencil_tile_mode)
1691e88f27b3Smrg{
1692e88f27b3Smrg    unsigned num_pipes, num_banks;
1693e88f27b3Smrg    uint32_t gb_tile_mode;
1694e88f27b3Smrg    int r;
1695e88f27b3Smrg
1696e88f27b3Smrg    /* retrieve tiling mode value */
1697e88f27b3Smrg    gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1698e88f27b3Smrg    si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
1699e88f27b3Smrg
1700e88f27b3Smrg    r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
1701e88f27b3Smrg    if (r) {
1702e88f27b3Smrg        return r;
1703e88f27b3Smrg    }
1704e88f27b3Smrg
1705e88f27b3Smrg    if (surf->flags & RADEON_SURF_SBUFFER) {
1706e88f27b3Smrg        r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0);
1707e88f27b3Smrg        surf->stencil_offset = surf->stencil_level[0].offset;
1708e88f27b3Smrg    }
1709e88f27b3Smrg    return r;
1710e88f27b3Smrg}
1711e88f27b3Smrg
1712e88f27b3Smrgstatic int si_surface_init(struct radeon_surface_manager *surf_man,
1713e88f27b3Smrg                           struct radeon_surface *surf)
1714e88f27b3Smrg{
1715e88f27b3Smrg    unsigned mode, tile_mode, stencil_tile_mode;
1716e88f27b3Smrg    int r;
1717e88f27b3Smrg
1718e88f27b3Smrg    /* MSAA surfaces support the 2D mode only. */
1719e88f27b3Smrg    if (surf->nsamples > 1) {
1720e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1721e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1722e88f27b3Smrg    }
1723e88f27b3Smrg
1724e88f27b3Smrg    /* tiling mode */
1725e88f27b3Smrg    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1726e88f27b3Smrg
1727e88f27b3Smrg    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1728e88f27b3Smrg        /* zbuffer only support 1D or 2D tiled surface */
1729e88f27b3Smrg        switch (mode) {
1730e88f27b3Smrg        case RADEON_SURF_MODE_1D:
1731e88f27b3Smrg        case RADEON_SURF_MODE_2D:
1732e88f27b3Smrg            break;
1733e88f27b3Smrg        default:
1734e88f27b3Smrg            mode = RADEON_SURF_MODE_1D;
1735e88f27b3Smrg            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1736e88f27b3Smrg            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1737e88f27b3Smrg            break;
1738e88f27b3Smrg        }
1739e88f27b3Smrg    }
1740e88f27b3Smrg
1741e88f27b3Smrg    r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1742e88f27b3Smrg    if (r) {
1743e88f27b3Smrg        return r;
1744e88f27b3Smrg    }
1745e88f27b3Smrg
1746e88f27b3Smrg    surf->stencil_offset = 0;
1747e88f27b3Smrg    surf->bo_alignment = 0;
1748e88f27b3Smrg
1749e88f27b3Smrg    /* check tiling mode */
1750e88f27b3Smrg    switch (mode) {
1751e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR:
1752e88f27b3Smrg        r = r6_surface_init_linear(surf_man, surf, 0, 0);
1753e88f27b3Smrg        break;
1754e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR_ALIGNED:
1755e88f27b3Smrg        r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
1756e88f27b3Smrg        break;
1757e88f27b3Smrg    case RADEON_SURF_MODE_1D:
1758e88f27b3Smrg        r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1759e88f27b3Smrg        break;
1760e88f27b3Smrg    case RADEON_SURF_MODE_2D:
1761e88f27b3Smrg        r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1762e88f27b3Smrg        break;
1763e88f27b3Smrg    default:
1764e88f27b3Smrg        return -EINVAL;
1765e88f27b3Smrg    }
1766e88f27b3Smrg    return r;
1767e88f27b3Smrg}
1768e88f27b3Smrg
1769e88f27b3Smrg/*
1770e88f27b3Smrg * depending on surface
1771e88f27b3Smrg */
1772e88f27b3Smrgstatic int si_surface_best(struct radeon_surface_manager *surf_man,
1773e88f27b3Smrg                           struct radeon_surface *surf)
1774e88f27b3Smrg{
1775e88f27b3Smrg    unsigned mode, tile_mode, stencil_tile_mode;
1776e88f27b3Smrg
1777e88f27b3Smrg    /* tiling mode */
1778e88f27b3Smrg    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1779e88f27b3Smrg
1780e88f27b3Smrg    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
1781e88f27b3Smrg        !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
1782e88f27b3Smrg        /* depth/stencil force 1d tiling for old mesa */
1783e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1784e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1785e88f27b3Smrg    }
1786e88f27b3Smrg
1787e88f27b3Smrg    return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1788e88f27b3Smrg}
1789e88f27b3Smrg
1790e88f27b3Smrg
1791e88f27b3Smrg/* ===========================================================================
1792e88f27b3Smrg * Sea Islands family
1793e88f27b3Smrg */
1794e88f27b3Smrg#define CIK__GB_TILE_MODE__PIPE_CONFIG(x)        (((x) >> 6) & 0x1f)
1795e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P2               0
1796e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16          4
1797e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16         5
1798e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32         6
1799e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32         7
1800e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16    8
1801e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16    9
1802e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16    10
1803e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16   11
1804e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16   12
1805e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32   13
1806e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32   14
1807e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16   16
1808e88f27b3Smrg#define     CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16  17
1809e88f27b3Smrg#define CIK__GB_TILE_MODE__TILE_SPLIT(x)         (((x) >> 11) & 0x7)
1810e88f27b3Smrg#define     CIK__TILE_SPLIT__64B                         0
1811e88f27b3Smrg#define     CIK__TILE_SPLIT__128B                        1
1812e88f27b3Smrg#define     CIK__TILE_SPLIT__256B                        2
1813e88f27b3Smrg#define     CIK__TILE_SPLIT__512B                        3
1814e88f27b3Smrg#define     CIK__TILE_SPLIT__1024B                       4
1815e88f27b3Smrg#define     CIK__TILE_SPLIT__2048B                       5
1816e88f27b3Smrg#define     CIK__TILE_SPLIT__4096B                       6
1817e88f27b3Smrg#define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x)         (((x) >> 25) & 0x3)
1818e88f27b3Smrg#define     CIK__SAMPLE_SPLIT__1                         0
1819e88f27b3Smrg#define     CIK__SAMPLE_SPLIT__2                         1
1820e88f27b3Smrg#define     CIK__SAMPLE_SPLIT__4                         2
1821e88f27b3Smrg#define     CIK__SAMPLE_SPLIT__8                         3
1822e88f27b3Smrg#define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x)        ((x) & 0x3)
1823e88f27b3Smrg#define     CIK__BANK_WIDTH__1                           0
1824e88f27b3Smrg#define     CIK__BANK_WIDTH__2                           1
1825e88f27b3Smrg#define     CIK__BANK_WIDTH__4                           2
1826e88f27b3Smrg#define     CIK__BANK_WIDTH__8                           3
1827e88f27b3Smrg#define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x)       (((x) >> 2) & 0x3)
1828e88f27b3Smrg#define     CIK__BANK_HEIGHT__1                          0
1829e88f27b3Smrg#define     CIK__BANK_HEIGHT__2                          1
1830e88f27b3Smrg#define     CIK__BANK_HEIGHT__4                          2
1831e88f27b3Smrg#define     CIK__BANK_HEIGHT__8                          3
1832e88f27b3Smrg#define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3)
1833e88f27b3Smrg#define     CIK__MACRO_TILE_ASPECT__1                    0
1834e88f27b3Smrg#define     CIK__MACRO_TILE_ASPECT__2                    1
1835e88f27b3Smrg#define     CIK__MACRO_TILE_ASPECT__4                    2
1836e88f27b3Smrg#define     CIK__MACRO_TILE_ASPECT__8                    3
1837e88f27b3Smrg#define CIK__GB_MACROTILE_MODE__NUM_BANKS(x)         (((x) >> 6) & 0x3)
1838e88f27b3Smrg#define     CIK__NUM_BANKS__2_BANK                       0
1839e88f27b3Smrg#define     CIK__NUM_BANKS__4_BANK                       1
1840e88f27b3Smrg#define     CIK__NUM_BANKS__8_BANK                       2
1841e88f27b3Smrg#define     CIK__NUM_BANKS__16_BANK                      3
1842e88f27b3Smrg
1843e88f27b3Smrg
1844e88f27b3Smrgstatic void cik_get_2d_params(struct radeon_surface_manager *surf_man,
1845e88f27b3Smrg                              unsigned bpe, unsigned nsamples, bool is_color,
1846e88f27b3Smrg                              unsigned tile_mode,
1847e88f27b3Smrg                              uint32_t *num_pipes,
1848e88f27b3Smrg                              uint32_t *tile_split_ptr,
1849e88f27b3Smrg                              uint32_t *num_banks,
1850e88f27b3Smrg                              uint32_t *macro_tile_aspect,
1851e88f27b3Smrg                              uint32_t *bank_w,
1852e88f27b3Smrg                              uint32_t *bank_h)
1853e88f27b3Smrg{
1854e88f27b3Smrg    uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1855e88f27b3Smrg    unsigned tileb_1x, tileb;
1856e88f27b3Smrg    unsigned gb_macrotile_mode;
1857e88f27b3Smrg    unsigned macrotile_index;
1858e88f27b3Smrg    unsigned tile_split, sample_split;
1859e88f27b3Smrg
1860e88f27b3Smrg    if (num_pipes) {
1861e88f27b3Smrg        switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1862e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P2:
1863e88f27b3Smrg        default:
1864e88f27b3Smrg            *num_pipes = 2;
1865e88f27b3Smrg            break;
1866e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1867e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1868e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1869e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1870e88f27b3Smrg            *num_pipes = 4;
1871e88f27b3Smrg            break;
1872e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1873e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1874e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1875e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1876e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1877e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1878e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1879e88f27b3Smrg            *num_pipes = 8;
1880e88f27b3Smrg            break;
1881e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16:
1882e88f27b3Smrg        case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16:
1883e88f27b3Smrg            *num_pipes = 16;
1884e88f27b3Smrg            break;
1885e88f27b3Smrg        }
1886e88f27b3Smrg    }
1887e88f27b3Smrg    switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1888e88f27b3Smrg    default:
1889e88f27b3Smrg    case CIK__TILE_SPLIT__64B:
1890e88f27b3Smrg        tile_split = 64;
1891e88f27b3Smrg        break;
1892e88f27b3Smrg    case CIK__TILE_SPLIT__128B:
1893e88f27b3Smrg        tile_split = 128;
1894e88f27b3Smrg        break;
1895e88f27b3Smrg    case CIK__TILE_SPLIT__256B:
1896e88f27b3Smrg        tile_split = 256;
1897e88f27b3Smrg        break;
1898e88f27b3Smrg    case CIK__TILE_SPLIT__512B:
1899e88f27b3Smrg        tile_split = 512;
1900e88f27b3Smrg        break;
1901e88f27b3Smrg    case CIK__TILE_SPLIT__1024B:
1902e88f27b3Smrg        tile_split = 1024;
1903e88f27b3Smrg        break;
1904e88f27b3Smrg    case CIK__TILE_SPLIT__2048B:
1905e88f27b3Smrg        tile_split = 2048;
1906e88f27b3Smrg        break;
1907e88f27b3Smrg    case CIK__TILE_SPLIT__4096B:
1908e88f27b3Smrg        tile_split = 4096;
1909e88f27b3Smrg        break;
1910e88f27b3Smrg    }
1911e88f27b3Smrg    switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) {
1912e88f27b3Smrg    default:
1913e88f27b3Smrg    case CIK__SAMPLE_SPLIT__1:
1914e88f27b3Smrg        sample_split = 1;
1915e88f27b3Smrg        break;
1916e88f27b3Smrg    case CIK__SAMPLE_SPLIT__2:
1917e88f27b3Smrg        sample_split = 1;
1918e88f27b3Smrg        break;
1919e88f27b3Smrg    case CIK__SAMPLE_SPLIT__4:
1920e88f27b3Smrg        sample_split = 4;
1921e88f27b3Smrg        break;
1922e88f27b3Smrg    case CIK__SAMPLE_SPLIT__8:
1923e88f27b3Smrg        sample_split = 8;
1924e88f27b3Smrg        break;
1925e88f27b3Smrg    }
1926e88f27b3Smrg
1927e88f27b3Smrg    /* Adjust the tile split. */
1928e88f27b3Smrg    tileb_1x = 8 * 8 * bpe;
1929e88f27b3Smrg    if (is_color) {
1930e88f27b3Smrg        tile_split = MAX2(256, sample_split * tileb_1x);
1931e88f27b3Smrg    }
1932e88f27b3Smrg    tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
1933e88f27b3Smrg
1934e88f27b3Smrg    /* Determine the macrotile index. */
1935e88f27b3Smrg    tileb = MIN2(tile_split, nsamples * tileb_1x);
1936e88f27b3Smrg
1937e88f27b3Smrg    for (macrotile_index = 0; tileb > 64; macrotile_index++) {
1938e88f27b3Smrg        tileb >>= 1;
1939e88f27b3Smrg    }
1940e88f27b3Smrg    gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index];
1941e88f27b3Smrg
1942e88f27b3Smrg    if (tile_split_ptr) {
1943e88f27b3Smrg        *tile_split_ptr = tile_split;
1944e88f27b3Smrg    }
1945e88f27b3Smrg    if (num_banks) {
1946e88f27b3Smrg        switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) {
1947e88f27b3Smrg        default:
1948e88f27b3Smrg        case CIK__NUM_BANKS__2_BANK:
1949e88f27b3Smrg            *num_banks = 2;
1950e88f27b3Smrg            break;
1951e88f27b3Smrg        case CIK__NUM_BANKS__4_BANK:
1952e88f27b3Smrg            *num_banks = 4;
1953e88f27b3Smrg            break;
1954e88f27b3Smrg        case CIK__NUM_BANKS__8_BANK:
1955e88f27b3Smrg            *num_banks = 8;
1956e88f27b3Smrg            break;
1957e88f27b3Smrg        case CIK__NUM_BANKS__16_BANK:
1958e88f27b3Smrg            *num_banks = 16;
1959e88f27b3Smrg            break;
1960e88f27b3Smrg        }
1961e88f27b3Smrg    }
1962e88f27b3Smrg    if (macro_tile_aspect) {
1963e88f27b3Smrg        switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) {
1964e88f27b3Smrg        default:
1965e88f27b3Smrg        case CIK__MACRO_TILE_ASPECT__1:
1966e88f27b3Smrg            *macro_tile_aspect = 1;
1967e88f27b3Smrg            break;
1968e88f27b3Smrg        case CIK__MACRO_TILE_ASPECT__2:
1969e88f27b3Smrg            *macro_tile_aspect = 2;
1970e88f27b3Smrg            break;
1971e88f27b3Smrg        case CIK__MACRO_TILE_ASPECT__4:
1972e88f27b3Smrg            *macro_tile_aspect = 4;
1973e88f27b3Smrg            break;
1974e88f27b3Smrg        case CIK__MACRO_TILE_ASPECT__8:
1975e88f27b3Smrg            *macro_tile_aspect = 8;
1976e88f27b3Smrg            break;
1977e88f27b3Smrg        }
1978e88f27b3Smrg    }
1979e88f27b3Smrg    if (bank_w) {
1980e88f27b3Smrg        switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) {
1981e88f27b3Smrg        default:
1982e88f27b3Smrg        case CIK__BANK_WIDTH__1:
1983e88f27b3Smrg            *bank_w = 1;
1984e88f27b3Smrg            break;
1985e88f27b3Smrg        case CIK__BANK_WIDTH__2:
1986e88f27b3Smrg            *bank_w = 2;
1987e88f27b3Smrg            break;
1988e88f27b3Smrg        case CIK__BANK_WIDTH__4:
1989e88f27b3Smrg            *bank_w = 4;
1990e88f27b3Smrg            break;
1991e88f27b3Smrg        case CIK__BANK_WIDTH__8:
1992e88f27b3Smrg            *bank_w = 8;
1993e88f27b3Smrg            break;
1994e88f27b3Smrg        }
1995e88f27b3Smrg    }
1996e88f27b3Smrg    if (bank_h) {
1997e88f27b3Smrg        switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) {
1998e88f27b3Smrg        default:
1999e88f27b3Smrg        case CIK__BANK_HEIGHT__1:
2000e88f27b3Smrg            *bank_h = 1;
2001e88f27b3Smrg            break;
2002e88f27b3Smrg        case CIK__BANK_HEIGHT__2:
2003e88f27b3Smrg            *bank_h = 2;
2004e88f27b3Smrg            break;
2005e88f27b3Smrg        case CIK__BANK_HEIGHT__4:
2006e88f27b3Smrg            *bank_h = 4;
2007e88f27b3Smrg            break;
2008e88f27b3Smrg        case CIK__BANK_HEIGHT__8:
2009e88f27b3Smrg            *bank_h = 8;
2010e88f27b3Smrg            break;
2011e88f27b3Smrg        }
2012e88f27b3Smrg    }
2013e88f27b3Smrg}
2014e88f27b3Smrg
2015e88f27b3Smrgstatic int cik_init_hw_info(struct radeon_surface_manager *surf_man)
2016e88f27b3Smrg{
2017e88f27b3Smrg    uint32_t tiling_config;
2018e88f27b3Smrg    drmVersionPtr version;
2019e88f27b3Smrg    int r;
2020e88f27b3Smrg
2021e88f27b3Smrg    r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
2022e88f27b3Smrg                         &tiling_config);
2023e88f27b3Smrg    if (r) {
2024e88f27b3Smrg        return r;
2025e88f27b3Smrg    }
2026e88f27b3Smrg
2027e88f27b3Smrg    surf_man->hw_info.allow_2d = 0;
2028e88f27b3Smrg    version = drmGetVersion(surf_man->fd);
2029e88f27b3Smrg    if (version && version->version_minor >= 35) {
2030e88f27b3Smrg        if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) &&
2031e88f27b3Smrg	    !radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_mode_array)) {
2032e88f27b3Smrg            surf_man->hw_info.allow_2d = 1;
2033e88f27b3Smrg        }
2034e88f27b3Smrg    }
2035e88f27b3Smrg    drmFreeVersion(version);
2036e88f27b3Smrg
2037e88f27b3Smrg    switch (tiling_config & 0xf) {
2038e88f27b3Smrg    case 0:
2039e88f27b3Smrg        surf_man->hw_info.num_pipes = 1;
2040e88f27b3Smrg        break;
2041e88f27b3Smrg    case 1:
2042e88f27b3Smrg        surf_man->hw_info.num_pipes = 2;
2043e88f27b3Smrg        break;
2044e88f27b3Smrg    case 2:
2045e88f27b3Smrg        surf_man->hw_info.num_pipes = 4;
2046e88f27b3Smrg        break;
2047e88f27b3Smrg    case 3:
2048e88f27b3Smrg        surf_man->hw_info.num_pipes = 8;
2049e88f27b3Smrg        break;
2050e88f27b3Smrg    default:
2051e88f27b3Smrg        surf_man->hw_info.num_pipes = 8;
2052e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
2053e88f27b3Smrg        break;
2054e88f27b3Smrg    }
2055e88f27b3Smrg
2056e88f27b3Smrg    switch ((tiling_config & 0xf0) >> 4) {
2057e88f27b3Smrg    case 0:
2058e88f27b3Smrg        surf_man->hw_info.num_banks = 4;
2059e88f27b3Smrg        break;
2060e88f27b3Smrg    case 1:
2061e88f27b3Smrg        surf_man->hw_info.num_banks = 8;
2062e88f27b3Smrg        break;
2063e88f27b3Smrg    case 2:
2064e88f27b3Smrg        surf_man->hw_info.num_banks = 16;
2065e88f27b3Smrg        break;
2066e88f27b3Smrg    default:
2067e88f27b3Smrg        surf_man->hw_info.num_banks = 8;
2068e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
2069e88f27b3Smrg        break;
2070e88f27b3Smrg    }
2071e88f27b3Smrg
2072e88f27b3Smrg    switch ((tiling_config & 0xf00) >> 8) {
2073e88f27b3Smrg    case 0:
2074e88f27b3Smrg        surf_man->hw_info.group_bytes = 256;
2075e88f27b3Smrg        break;
2076e88f27b3Smrg    case 1:
2077e88f27b3Smrg        surf_man->hw_info.group_bytes = 512;
2078e88f27b3Smrg        break;
2079e88f27b3Smrg    default:
2080e88f27b3Smrg        surf_man->hw_info.group_bytes = 256;
2081e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
2082e88f27b3Smrg        break;
2083e88f27b3Smrg    }
2084e88f27b3Smrg
2085e88f27b3Smrg    switch ((tiling_config & 0xf000) >> 12) {
2086e88f27b3Smrg    case 0:
2087e88f27b3Smrg        surf_man->hw_info.row_size = 1024;
2088e88f27b3Smrg        break;
2089e88f27b3Smrg    case 1:
2090e88f27b3Smrg        surf_man->hw_info.row_size = 2048;
2091e88f27b3Smrg        break;
2092e88f27b3Smrg    case 2:
2093e88f27b3Smrg        surf_man->hw_info.row_size = 4096;
2094e88f27b3Smrg        break;
2095e88f27b3Smrg    default:
2096e88f27b3Smrg        surf_man->hw_info.row_size = 4096;
2097e88f27b3Smrg        surf_man->hw_info.allow_2d = 0;
2098e88f27b3Smrg        break;
2099e88f27b3Smrg    }
2100e88f27b3Smrg    return 0;
2101e88f27b3Smrg}
2102e88f27b3Smrg
2103e88f27b3Smrgstatic int cik_surface_sanity(struct radeon_surface_manager *surf_man,
2104e88f27b3Smrg                              struct radeon_surface *surf,
2105e88f27b3Smrg                              unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
2106e88f27b3Smrg{
2107e88f27b3Smrg    /* check surface dimension */
2108e88f27b3Smrg    if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
2109e88f27b3Smrg        return -EINVAL;
2110e88f27b3Smrg    }
2111e88f27b3Smrg
2112e88f27b3Smrg    /* check mipmap last_level */
2113e88f27b3Smrg    if (surf->last_level > 15) {
2114e88f27b3Smrg        return -EINVAL;
2115e88f27b3Smrg    }
2116e88f27b3Smrg
2117e88f27b3Smrg    /* force 1d on kernel that can't do 2d */
2118e88f27b3Smrg    if (mode > RADEON_SURF_MODE_1D &&
2119e88f27b3Smrg        (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
2120e88f27b3Smrg        if (surf->nsamples > 1) {
2121e88f27b3Smrg            fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
2122e88f27b3Smrg            return -EFAULT;
2123e88f27b3Smrg        }
2124e88f27b3Smrg        mode = RADEON_SURF_MODE_1D;
2125e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2126e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(mode, MODE);
2127e88f27b3Smrg    }
2128e88f27b3Smrg
2129e88f27b3Smrg    if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
2130e88f27b3Smrg        return -EINVAL;
2131e88f27b3Smrg    }
2132e88f27b3Smrg
2133e88f27b3Smrg    if (!surf->tile_split) {
2134e88f27b3Smrg        /* default value */
2135e88f27b3Smrg        surf->mtilea = 1;
2136e88f27b3Smrg        surf->bankw = 1;
2137e88f27b3Smrg        surf->bankw = 1;
2138e88f27b3Smrg        surf->tile_split = 64;
2139e88f27b3Smrg        surf->stencil_tile_split = 64;
2140e88f27b3Smrg    }
2141e88f27b3Smrg
2142e88f27b3Smrg    switch (mode) {
2143e88f27b3Smrg    case RADEON_SURF_MODE_2D: {
2144e88f27b3Smrg        if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) {
2145e88f27b3Smrg            switch (surf->nsamples) {
2146e88f27b3Smrg            case 1:
2147e88f27b3Smrg                *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64;
2148e88f27b3Smrg                break;
2149e88f27b3Smrg            case 2:
2150e88f27b3Smrg            case 4:
2151e88f27b3Smrg                *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128;
2152e88f27b3Smrg                break;
2153e88f27b3Smrg            case 8:
2154e88f27b3Smrg                *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256;
2155e88f27b3Smrg                break;
2156e88f27b3Smrg            default:
2157e88f27b3Smrg                return -EINVAL;
2158e88f27b3Smrg            }
2159e88f27b3Smrg
2160e88f27b3Smrg            if (surf->flags & RADEON_SURF_SBUFFER) {
2161e88f27b3Smrg                *stencil_tile_mode = *tile_mode;
2162e88f27b3Smrg
2163e88f27b3Smrg                cik_get_2d_params(surf_man, 1, surf->nsamples, false,
2164e88f27b3Smrg                                  *stencil_tile_mode, NULL,
2165e88f27b3Smrg                                  &surf->stencil_tile_split,
2166e88f27b3Smrg                                  NULL, NULL, NULL, NULL);
2167e88f27b3Smrg            }
2168e88f27b3Smrg        } else if (surf->flags & RADEON_SURF_SCANOUT) {
2169e88f27b3Smrg            *tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT;
2170e88f27b3Smrg        } else {
2171e88f27b3Smrg            *tile_mode = CIK_TILE_MODE_COLOR_2D;
2172e88f27b3Smrg        }
2173e88f27b3Smrg
2174e88f27b3Smrg        /* retrieve tiling mode values */
2175e88f27b3Smrg        cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2176e88f27b3Smrg                          !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode,
2177e88f27b3Smrg                          NULL, &surf->tile_split, NULL, &surf->mtilea,
2178e88f27b3Smrg                          &surf->bankw, &surf->bankh);
2179e88f27b3Smrg        break;
2180e88f27b3Smrg    }
2181e88f27b3Smrg    case RADEON_SURF_MODE_1D:
2182e88f27b3Smrg        if (surf->flags & RADEON_SURF_SBUFFER) {
2183e88f27b3Smrg            *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2184e88f27b3Smrg        }
2185e88f27b3Smrg        if (surf->flags & RADEON_SURF_ZBUFFER) {
2186e88f27b3Smrg            *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2187e88f27b3Smrg        } else if (surf->flags & RADEON_SURF_SCANOUT) {
2188e88f27b3Smrg            *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2189e88f27b3Smrg        } else {
2190e88f27b3Smrg            *tile_mode = SI_TILE_MODE_COLOR_1D;
2191e88f27b3Smrg        }
2192e88f27b3Smrg        break;
2193e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR_ALIGNED:
2194e88f27b3Smrg    default:
2195e88f27b3Smrg        *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
2196e88f27b3Smrg    }
2197e88f27b3Smrg
2198e88f27b3Smrg    return 0;
2199e88f27b3Smrg}
2200e88f27b3Smrg
2201e88f27b3Smrgstatic int cik_surface_init_2d(struct radeon_surface_manager *surf_man,
2202e88f27b3Smrg                               struct radeon_surface *surf,
2203e88f27b3Smrg                               struct radeon_surface_level *level,
2204e88f27b3Smrg                               unsigned bpe, unsigned tile_mode,
2205e88f27b3Smrg                               unsigned tile_split,
2206e88f27b3Smrg                               unsigned num_pipes, unsigned num_banks,
2207e88f27b3Smrg                               uint64_t offset,
2208e88f27b3Smrg                               unsigned start_level)
2209e88f27b3Smrg{
2210e88f27b3Smrg    uint64_t aligned_offset = offset;
2211e88f27b3Smrg    unsigned tilew, tileh, tileb_1x, tileb;
2212e88f27b3Smrg    unsigned mtilew, mtileh, mtileb;
2213e88f27b3Smrg    unsigned slice_pt;
2214e88f27b3Smrg    unsigned i;
2215e88f27b3Smrg
2216e88f27b3Smrg    /* compute tile values */
2217e88f27b3Smrg    tilew = 8;
2218e88f27b3Smrg    tileh = 8;
2219e88f27b3Smrg    tileb_1x = tilew * tileh * bpe;
2220e88f27b3Smrg
2221e88f27b3Smrg    tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
2222e88f27b3Smrg
2223e88f27b3Smrg    tileb = surf->nsamples * tileb_1x;
2224e88f27b3Smrg
2225e88f27b3Smrg    /* slices per tile */
2226e88f27b3Smrg    slice_pt = 1;
2227e88f27b3Smrg    if (tileb > tile_split && tile_split) {
2228e88f27b3Smrg        slice_pt = tileb / tile_split;
2229e88f27b3Smrg        tileb = tileb / slice_pt;
2230e88f27b3Smrg    }
2231e88f27b3Smrg
2232e88f27b3Smrg    /* macro tile width & height */
2233e88f27b3Smrg    mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
2234e88f27b3Smrg    mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
2235e88f27b3Smrg
2236e88f27b3Smrg    /* macro tile bytes */
2237e88f27b3Smrg    mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
2238e88f27b3Smrg
2239e88f27b3Smrg    if (start_level <= 1) {
2240e88f27b3Smrg        unsigned alignment = MAX2(256, mtileb);
2241e88f27b3Smrg        surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
2242e88f27b3Smrg
2243e88f27b3Smrg        if (aligned_offset) {
2244e88f27b3Smrg            aligned_offset = ALIGN(aligned_offset, alignment);
2245e88f27b3Smrg        }
2246e88f27b3Smrg    }
2247e88f27b3Smrg
2248e88f27b3Smrg    /* build mipmap tree */
2249e88f27b3Smrg    for (i = start_level; i <= surf->last_level; i++) {
2250e88f27b3Smrg        level[i].mode = RADEON_SURF_MODE_2D;
2251e88f27b3Smrg        si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
2252e88f27b3Smrg        if (level[i].mode == RADEON_SURF_MODE_1D) {
2253e88f27b3Smrg            switch (tile_mode) {
2254e88f27b3Smrg            case CIK_TILE_MODE_COLOR_2D:
2255e88f27b3Smrg                tile_mode = SI_TILE_MODE_COLOR_1D;
2256e88f27b3Smrg                break;
2257e88f27b3Smrg            case CIK_TILE_MODE_COLOR_2D_SCANOUT:
2258e88f27b3Smrg                tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2259e88f27b3Smrg                break;
2260e88f27b3Smrg            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64:
2261e88f27b3Smrg            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128:
2262e88f27b3Smrg            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256:
2263e88f27b3Smrg            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512:
2264e88f27b3Smrg            case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE:
2265e88f27b3Smrg                tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2266e88f27b3Smrg                break;
2267e88f27b3Smrg            default:
2268e88f27b3Smrg                return -EINVAL;
2269e88f27b3Smrg            }
2270e88f27b3Smrg            return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
2271e88f27b3Smrg        }
2272e88f27b3Smrg        /* level0 and first mipmap need to have alignment */
2273e88f27b3Smrg        aligned_offset = offset = surf->bo_size;
2274e88f27b3Smrg        if (i == 0) {
2275e88f27b3Smrg            aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
2276e88f27b3Smrg        }
2277e88f27b3Smrg        if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
2278e88f27b3Smrg            if (surf->level == level) {
2279e88f27b3Smrg                surf->tiling_index[i] = tile_mode;
2280e88f27b3Smrg                /* it's ok because stencil is done after */
2281e88f27b3Smrg                surf->stencil_tiling_index[i] = tile_mode;
2282e88f27b3Smrg            } else {
2283e88f27b3Smrg                surf->stencil_tiling_index[i] = tile_mode;
2284e88f27b3Smrg            }
2285e88f27b3Smrg        }
2286e88f27b3Smrg    }
2287e88f27b3Smrg    return 0;
2288e88f27b3Smrg}
2289e88f27b3Smrg
2290e88f27b3Smrgstatic int cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
2291e88f27b3Smrg                                        struct radeon_surface *surf,
2292e88f27b3Smrg                                        unsigned tile_mode, unsigned stencil_tile_mode)
2293e88f27b3Smrg{
2294e88f27b3Smrg    int r;
2295e88f27b3Smrg    uint32_t num_pipes, num_banks;
2296e88f27b3Smrg
2297e88f27b3Smrg    cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2298e88f27b3Smrg                        !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode,
2299e88f27b3Smrg                        &num_pipes, NULL, &num_banks, NULL, NULL, NULL);
2300e88f27b3Smrg
2301e88f27b3Smrg    r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode,
2302e88f27b3Smrg                            surf->tile_split, num_pipes, num_banks, 0, 0);
2303e88f27b3Smrg    if (r) {
2304e88f27b3Smrg        return r;
2305e88f27b3Smrg    }
2306e88f27b3Smrg
2307e88f27b3Smrg    if (surf->flags & RADEON_SURF_SBUFFER) {
2308e88f27b3Smrg        r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode,
2309e88f27b3Smrg                                surf->stencil_tile_split, num_pipes, num_banks,
2310e88f27b3Smrg                                surf->bo_size, 0);
2311e88f27b3Smrg        surf->stencil_offset = surf->stencil_level[0].offset;
2312e88f27b3Smrg    }
2313e88f27b3Smrg    return r;
2314e88f27b3Smrg}
2315e88f27b3Smrg
2316e88f27b3Smrgstatic int cik_surface_init(struct radeon_surface_manager *surf_man,
2317e88f27b3Smrg                            struct radeon_surface *surf)
2318e88f27b3Smrg{
2319e88f27b3Smrg    unsigned mode, tile_mode, stencil_tile_mode;
2320e88f27b3Smrg    int r;
2321e88f27b3Smrg
2322e88f27b3Smrg    /* MSAA surfaces support the 2D mode only. */
2323e88f27b3Smrg    if (surf->nsamples > 1) {
2324e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2325e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
2326e88f27b3Smrg    }
2327e88f27b3Smrg
2328e88f27b3Smrg    /* tiling mode */
2329e88f27b3Smrg    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2330e88f27b3Smrg
2331e88f27b3Smrg    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
2332e88f27b3Smrg        /* zbuffer only support 1D or 2D tiled surface */
2333e88f27b3Smrg        switch (mode) {
2334e88f27b3Smrg        case RADEON_SURF_MODE_1D:
2335e88f27b3Smrg        case RADEON_SURF_MODE_2D:
2336e88f27b3Smrg            break;
2337e88f27b3Smrg        default:
2338e88f27b3Smrg            mode = RADEON_SURF_MODE_1D;
2339e88f27b3Smrg            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2340e88f27b3Smrg            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2341e88f27b3Smrg            break;
2342e88f27b3Smrg        }
2343e88f27b3Smrg    }
2344e88f27b3Smrg
2345e88f27b3Smrg    r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2346e88f27b3Smrg    if (r) {
2347e88f27b3Smrg        return r;
2348e88f27b3Smrg    }
2349e88f27b3Smrg
2350e88f27b3Smrg    surf->stencil_offset = 0;
2351e88f27b3Smrg    surf->bo_alignment = 0;
2352e88f27b3Smrg
2353e88f27b3Smrg    /* check tiling mode */
2354e88f27b3Smrg    switch (mode) {
2355e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR:
2356e88f27b3Smrg        r = r6_surface_init_linear(surf_man, surf, 0, 0);
2357e88f27b3Smrg        break;
2358e88f27b3Smrg    case RADEON_SURF_MODE_LINEAR_ALIGNED:
2359e88f27b3Smrg        r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
2360e88f27b3Smrg        break;
2361e88f27b3Smrg    case RADEON_SURF_MODE_1D:
2362e88f27b3Smrg        r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2363e88f27b3Smrg        break;
2364e88f27b3Smrg    case RADEON_SURF_MODE_2D:
2365e88f27b3Smrg        r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2366e88f27b3Smrg        break;
2367e88f27b3Smrg    default:
2368e88f27b3Smrg        return -EINVAL;
2369e88f27b3Smrg    }
2370e88f27b3Smrg    return r;
2371e88f27b3Smrg}
2372e88f27b3Smrg
2373e88f27b3Smrg/*
2374e88f27b3Smrg * depending on surface
2375e88f27b3Smrg */
2376e88f27b3Smrgstatic int cik_surface_best(struct radeon_surface_manager *surf_man,
2377e88f27b3Smrg                            struct radeon_surface *surf)
2378e88f27b3Smrg{
2379e88f27b3Smrg    unsigned mode, tile_mode, stencil_tile_mode;
2380e88f27b3Smrg
2381e88f27b3Smrg    /* tiling mode */
2382e88f27b3Smrg    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2383e88f27b3Smrg
2384e88f27b3Smrg    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
2385e88f27b3Smrg        !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
2386e88f27b3Smrg        /* depth/stencil force 1d tiling for old mesa */
2387e88f27b3Smrg        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2388e88f27b3Smrg        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2389e88f27b3Smrg    }
2390e88f27b3Smrg
2391e88f27b3Smrg    return cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2392e88f27b3Smrg}
2393e88f27b3Smrg
2394e88f27b3Smrg
2395e88f27b3Smrg/* ===========================================================================
2396e88f27b3Smrg * public API
2397e88f27b3Smrg */
2398e88f27b3Smrgstruct radeon_surface_manager *radeon_surface_manager_new(int fd)
2399e88f27b3Smrg{
2400e88f27b3Smrg    struct radeon_surface_manager *surf_man;
2401e88f27b3Smrg
2402e88f27b3Smrg    surf_man = calloc(1, sizeof(struct radeon_surface_manager));
2403e88f27b3Smrg    if (surf_man == NULL) {
2404e88f27b3Smrg        return NULL;
2405e88f27b3Smrg    }
2406e88f27b3Smrg    surf_man->fd = fd;
2407e88f27b3Smrg    if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
2408e88f27b3Smrg        goto out_err;
2409e88f27b3Smrg    }
2410e88f27b3Smrg    if (radeon_get_family(surf_man)) {
2411e88f27b3Smrg        goto out_err;
2412e88f27b3Smrg    }
2413e88f27b3Smrg
2414e88f27b3Smrg    if (surf_man->family <= CHIP_RV740) {
2415e88f27b3Smrg        if (r6_init_hw_info(surf_man)) {
2416e88f27b3Smrg            goto out_err;
2417e88f27b3Smrg        }
2418e88f27b3Smrg        surf_man->surface_init = &r6_surface_init;
2419e88f27b3Smrg        surf_man->surface_best = &r6_surface_best;
2420e88f27b3Smrg    } else if (surf_man->family <= CHIP_ARUBA) {
2421e88f27b3Smrg        if (eg_init_hw_info(surf_man)) {
2422e88f27b3Smrg            goto out_err;
2423e88f27b3Smrg        }
2424e88f27b3Smrg        surf_man->surface_init = &eg_surface_init;
2425e88f27b3Smrg        surf_man->surface_best = &eg_surface_best;
2426e88f27b3Smrg    } else if (surf_man->family < CHIP_BONAIRE) {
2427e88f27b3Smrg        if (si_init_hw_info(surf_man)) {
2428e88f27b3Smrg            goto out_err;
2429e88f27b3Smrg        }
2430e88f27b3Smrg        surf_man->surface_init = &si_surface_init;
2431e88f27b3Smrg        surf_man->surface_best = &si_surface_best;
2432e88f27b3Smrg    } else {
2433e88f27b3Smrg        if (cik_init_hw_info(surf_man)) {
2434e88f27b3Smrg            goto out_err;
2435e88f27b3Smrg        }
2436e88f27b3Smrg        surf_man->surface_init = &cik_surface_init;
2437e88f27b3Smrg        surf_man->surface_best = &cik_surface_best;
2438e88f27b3Smrg    }
2439e88f27b3Smrg
2440e88f27b3Smrg    return surf_man;
2441e88f27b3Smrgout_err:
2442e88f27b3Smrg    free(surf_man);
2443e88f27b3Smrg    return NULL;
2444e88f27b3Smrg}
2445e88f27b3Smrg
2446e88f27b3Smrgvoid radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
2447e88f27b3Smrg{
2448e88f27b3Smrg    free(surf_man);
2449e88f27b3Smrg}
2450e88f27b3Smrg
2451e88f27b3Smrgstatic int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
2452e88f27b3Smrg                                 struct radeon_surface *surf,
2453e88f27b3Smrg                                 unsigned type,
2454e88f27b3Smrg                                 unsigned mode)
2455e88f27b3Smrg{
2456e88f27b3Smrg    if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
2457e88f27b3Smrg        return -EINVAL;
2458e88f27b3Smrg    }
2459e88f27b3Smrg
2460e88f27b3Smrg    /* all dimension must be at least 1 ! */
2461e88f27b3Smrg    if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
2462e88f27b3Smrg        return -EINVAL;
2463e88f27b3Smrg    }
2464e88f27b3Smrg    if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
2465e88f27b3Smrg        return -EINVAL;
2466e88f27b3Smrg    }
2467e88f27b3Smrg    if (!surf->array_size) {
2468e88f27b3Smrg        return -EINVAL;
2469e88f27b3Smrg    }
2470e88f27b3Smrg    /* array size must be a power of 2 */
2471e88f27b3Smrg    surf->array_size = next_power_of_two(surf->array_size);
2472e88f27b3Smrg
2473e88f27b3Smrg    switch (surf->nsamples) {
2474e88f27b3Smrg    case 1:
2475e88f27b3Smrg    case 2:
2476e88f27b3Smrg    case 4:
2477e88f27b3Smrg    case 8:
2478e88f27b3Smrg        break;
2479e88f27b3Smrg    default:
2480e88f27b3Smrg        return -EINVAL;
2481e88f27b3Smrg    }
2482e88f27b3Smrg    /* check type */
2483e88f27b3Smrg    switch (type) {
2484e88f27b3Smrg    case RADEON_SURF_TYPE_1D:
2485e88f27b3Smrg        if (surf->npix_y > 1) {
2486e88f27b3Smrg            return -EINVAL;
2487e88f27b3Smrg        }
2488e88f27b3Smrg    case RADEON_SURF_TYPE_2D:
2489e88f27b3Smrg        if (surf->npix_z > 1) {
2490e88f27b3Smrg            return -EINVAL;
2491e88f27b3Smrg        }
2492e88f27b3Smrg        break;
2493e88f27b3Smrg    case RADEON_SURF_TYPE_CUBEMAP:
2494e88f27b3Smrg        if (surf->npix_z > 1) {
2495e88f27b3Smrg            return -EINVAL;
2496e88f27b3Smrg        }
2497e88f27b3Smrg        /* deal with cubemap as they were texture array */
2498e88f27b3Smrg        if (surf_man->family >= CHIP_RV770) {
2499e88f27b3Smrg            surf->array_size = 8;
2500e88f27b3Smrg        } else {
2501e88f27b3Smrg            surf->array_size = 6;
2502e88f27b3Smrg        }
2503e88f27b3Smrg        break;
2504e88f27b3Smrg    case RADEON_SURF_TYPE_3D:
2505e88f27b3Smrg        break;
2506e88f27b3Smrg    case RADEON_SURF_TYPE_1D_ARRAY:
2507e88f27b3Smrg        if (surf->npix_y > 1) {
2508e88f27b3Smrg            return -EINVAL;
2509e88f27b3Smrg        }
2510e88f27b3Smrg    case RADEON_SURF_TYPE_2D_ARRAY:
2511e88f27b3Smrg        break;
2512e88f27b3Smrg    default:
2513e88f27b3Smrg        return -EINVAL;
2514e88f27b3Smrg    }
2515e88f27b3Smrg    return 0;
2516e88f27b3Smrg}
2517e88f27b3Smrg
2518e88f27b3Smrgint radeon_surface_init(struct radeon_surface_manager *surf_man,
2519e88f27b3Smrg                        struct radeon_surface *surf)
2520e88f27b3Smrg{
2521e88f27b3Smrg    unsigned mode, type;
2522e88f27b3Smrg    int r;
2523e88f27b3Smrg
2524e88f27b3Smrg    type = RADEON_SURF_GET(surf->flags, TYPE);
2525e88f27b3Smrg    mode = RADEON_SURF_GET(surf->flags, MODE);
2526e88f27b3Smrg
2527e88f27b3Smrg    r = radeon_surface_sanity(surf_man, surf, type, mode);
2528e88f27b3Smrg    if (r) {
2529e88f27b3Smrg        return r;
2530e88f27b3Smrg    }
2531e88f27b3Smrg    return surf_man->surface_init(surf_man, surf);
2532e88f27b3Smrg}
2533e88f27b3Smrg
2534e88f27b3Smrgint radeon_surface_best(struct radeon_surface_manager *surf_man,
2535e88f27b3Smrg                        struct radeon_surface *surf)
2536e88f27b3Smrg{
2537e88f27b3Smrg    unsigned mode, type;
2538e88f27b3Smrg    int r;
2539e88f27b3Smrg
2540e88f27b3Smrg    type = RADEON_SURF_GET(surf->flags, TYPE);
2541e88f27b3Smrg    mode = RADEON_SURF_GET(surf->flags, MODE);
2542e88f27b3Smrg
2543e88f27b3Smrg    r = radeon_surface_sanity(surf_man, surf, type, mode);
2544e88f27b3Smrg    if (r) {
2545e88f27b3Smrg        return r;
2546e88f27b3Smrg    }
2547e88f27b3Smrg    return surf_man->surface_best(surf_man, surf);
2548e88f27b3Smrg}
2549