a74064c460ab99e3ffad7d1ccc588b7fc909cdc5
[platform/upstream/libdrm.git] / radeon / radeon_surface.c
1 /*
2  * Copyright © 2011 Red Hat All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
14  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
16  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * The above copyright notice and this permission notice (including the
22  * next paragraph) shall be included in all copies or substantial portions
23  * of the Software.
24  */
25 /*
26  * Authors:
27  *      Jérôme Glisse <jglisse@redhat.com>
28  */
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/mman.h>
34 #include <sys/ioctl.h>
35 #include "drm.h"
36 #include "xf86drm.h"
37 #include "radeon_drm.h"
38 #include "radeon_surface.h"
39
40 #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
41 #define MAX2(A, B)              ((A) > (B) ? (A) : (B))
42 #define MIN2(A, B)              ((A) < (B) ? (A) : (B))
43
44 /* keep this private */
45 enum radeon_family {
46     CHIP_UNKNOWN,
47     CHIP_R600,
48     CHIP_RV610,
49     CHIP_RV630,
50     CHIP_RV670,
51     CHIP_RV620,
52     CHIP_RV635,
53     CHIP_RS780,
54     CHIP_RS880,
55     CHIP_RV770,
56     CHIP_RV730,
57     CHIP_RV710,
58     CHIP_RV740,
59     CHIP_CEDAR,
60     CHIP_REDWOOD,
61     CHIP_JUNIPER,
62     CHIP_CYPRESS,
63     CHIP_HEMLOCK,
64     CHIP_PALM,
65     CHIP_SUMO,
66     CHIP_SUMO2,
67     CHIP_BARTS,
68     CHIP_TURKS,
69     CHIP_CAICOS,
70     CHIP_CAYMAN,
71     CHIP_ARUBA,
72     CHIP_TAHITI,
73     CHIP_PITCAIRN,
74     CHIP_VERDE,
75     CHIP_OLAND,
76     CHIP_HAINAN,
77     CHIP_LAST,
78 };
79
80 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
81                                  struct radeon_surface *surf);
82 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
83                                  struct radeon_surface *surf);
84
85 struct radeon_hw_info {
86     /* apply to r6, eg */
87     uint32_t                        group_bytes;
88     uint32_t                        num_banks;
89     uint32_t                        num_pipes;
90     /* apply to eg */
91     uint32_t                        row_size;
92     unsigned                        allow_2d;
93     /* apply to si */
94     uint32_t                        tile_mode_array[32];
95 };
96
97 struct radeon_surface_manager {
98     int                         fd;
99     uint32_t                    device_id;
100     struct radeon_hw_info       hw_info;
101     unsigned                    family;
102     hw_init_surface_t           surface_init;
103     hw_best_surface_t           surface_best;
104 };
105
106 /* helper */
107 static int radeon_get_value(int fd, unsigned req, uint32_t *value)
108 {
109     struct drm_radeon_info info = {};
110     int r;
111
112     *value = 0;
113     info.request = req;
114     info.value = (uintptr_t)value;
115     r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
116                             sizeof(struct drm_radeon_info));
117     return r;
118 }
119
120 static int radeon_get_family(struct radeon_surface_manager *surf_man)
121 {
122     switch (surf_man->device_id) {
123 #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
124 #include "r600_pci_ids.h"
125 #undef CHIPSET
126     default:
127         return -EINVAL;
128     }
129     return 0;
130 }
131
132 static unsigned next_power_of_two(unsigned x)
133 {
134    if (x <= 1)
135        return 1;
136
137    return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
138 }
139
140 static unsigned mip_minify(unsigned size, unsigned level)
141 {
142     unsigned val;
143
144     val = MAX2(1, size >> level);
145     if (level > 0)
146         val = next_power_of_two(val);
147     return val;
148 }
149
150 static void surf_minify(struct radeon_surface *surf,
151                         struct radeon_surface_level *surflevel,
152                         unsigned bpe, unsigned level,
153                         uint32_t xalign, uint32_t yalign, uint32_t zalign,
154                         unsigned offset)
155 {
156     surflevel->npix_x = mip_minify(surf->npix_x, level);
157     surflevel->npix_y = mip_minify(surf->npix_y, level);
158     surflevel->npix_z = mip_minify(surf->npix_z, level);
159     surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
160     surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
161     surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
162     if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
163         !(surf->flags & RADEON_SURF_FMASK)) {
164         if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
165             surflevel->mode = RADEON_SURF_MODE_1D;
166             return;
167         }
168     }
169     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
170     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
171     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
172
173     surflevel->offset = offset;
174     surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
175     surflevel->slice_size = surflevel->pitch_bytes * surflevel->nblk_y;
176
177     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
178 }
179
180 /* ===========================================================================
181  * r600/r700 family
182  */
183 static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
184 {
185     uint32_t tiling_config;
186     drmVersionPtr version;
187     int r;
188
189     r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
190                          &tiling_config);
191     if (r) {
192         return r;
193     }
194
195     surf_man->hw_info.allow_2d = 0;
196     version = drmGetVersion(surf_man->fd);
197     if (version && version->version_minor >= 14) {
198         surf_man->hw_info.allow_2d = 1;
199     }
200     drmFreeVersion(version);
201
202     switch ((tiling_config & 0xe) >> 1) {
203     case 0:
204         surf_man->hw_info.num_pipes = 1;
205         break;
206     case 1:
207         surf_man->hw_info.num_pipes = 2;
208         break;
209     case 2:
210         surf_man->hw_info.num_pipes = 4;
211         break;
212     case 3:
213         surf_man->hw_info.num_pipes = 8;
214         break;
215     default:
216         surf_man->hw_info.num_pipes = 8;
217         surf_man->hw_info.allow_2d = 0;
218         break;
219     }
220
221     switch ((tiling_config & 0x30) >> 4) {
222     case 0:
223         surf_man->hw_info.num_banks = 4;
224         break;
225     case 1:
226         surf_man->hw_info.num_banks = 8;
227         break;
228     default:
229         surf_man->hw_info.num_banks = 8;
230         surf_man->hw_info.allow_2d = 0;
231         break;
232     }
233
234     switch ((tiling_config & 0xc0) >> 6) {
235     case 0:
236         surf_man->hw_info.group_bytes = 256;
237         break;
238     case 1:
239         surf_man->hw_info.group_bytes = 512;
240         break;
241     default:
242         surf_man->hw_info.group_bytes = 256;
243         surf_man->hw_info.allow_2d = 0;
244         break;
245     }
246     return 0;
247 }
248
249 static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
250                                   struct radeon_surface *surf,
251                                   uint64_t offset, unsigned start_level)
252 {
253     uint32_t xalign, yalign, zalign;
254     unsigned i;
255
256     /* compute alignment */
257     if (!start_level) {
258         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
259     }
260     /* the 32 alignment is for scanout, cb or db but to allow texture to be
261      * easily bound as such we force this alignment to all surface
262      */
263     xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
264     yalign = 1;
265     zalign = 1;
266     if (surf->flags & RADEON_SURF_SCANOUT) {
267         xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
268     }
269
270     /* build mipmap tree */
271     for (i = start_level; i <= surf->last_level; i++) {
272         surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
273         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
274         /* level0 and first mipmap need to have alignment */
275         offset = surf->bo_size;
276         if ((i == 0)) {
277             offset = ALIGN(offset, surf->bo_alignment);
278         }
279     }
280     return 0;
281 }
282
283 static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
284                                           struct radeon_surface *surf,
285                                           uint64_t offset, unsigned start_level)
286 {
287     uint32_t xalign, yalign, zalign;
288     unsigned i;
289
290     /* compute alignment */
291     if (!start_level) {
292         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
293     }
294     xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
295     yalign = 1;
296     zalign = 1;
297
298     /* build mipmap tree */
299     for (i = start_level; i <= surf->last_level; i++) {
300         surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
301         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
302         /* level0 and first mipmap need to have alignment */
303         offset = surf->bo_size;
304         if ((i == 0)) {
305             offset = ALIGN(offset, surf->bo_alignment);
306         }
307     }
308     return 0;
309 }
310
311 static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
312                               struct radeon_surface *surf,
313                               uint64_t offset, unsigned start_level)
314 {
315     uint32_t xalign, yalign, zalign, tilew;
316     unsigned i;
317
318     /* compute alignment */
319     tilew = 8;
320     xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
321     xalign = MAX2(tilew, xalign);
322     yalign = tilew;
323     zalign = 1;
324     if (surf->flags & RADEON_SURF_SCANOUT) {
325         xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
326     }
327     if (!start_level) {
328         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
329     }
330
331     /* build mipmap tree */
332     for (i = start_level; i <= surf->last_level; i++) {
333         surf->level[i].mode = RADEON_SURF_MODE_1D;
334         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
335         /* level0 and first mipmap need to have alignment */
336         offset = surf->bo_size;
337         if ((i == 0)) {
338             offset = ALIGN(offset, surf->bo_alignment);
339         }
340     }
341     return 0;
342 }
343
344 static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
345                               struct radeon_surface *surf,
346                               uint64_t offset, unsigned start_level)
347 {
348     uint32_t xalign, yalign, zalign, tilew;
349     unsigned i;
350
351     /* compute alignment */
352     tilew = 8;
353     zalign = 1;
354     xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
355              (tilew * surf->bpe * surf->nsamples);
356     xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
357     yalign = tilew * surf_man->hw_info.num_pipes;
358     if (surf->flags & RADEON_SURF_SCANOUT) {
359         xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
360     }
361     if (!start_level) {
362         surf->bo_alignment =
363             MAX2(surf_man->hw_info.num_pipes *
364                  surf_man->hw_info.num_banks *
365                  surf->nsamples * surf->bpe * 64,
366                  xalign * yalign * surf->nsamples * surf->bpe);
367     }
368
369     /* build mipmap tree */
370     for (i = start_level; i <= surf->last_level; i++) {
371         surf->level[i].mode = RADEON_SURF_MODE_2D;
372         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
373         if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
374             return r6_surface_init_1d(surf_man, surf, offset, i);
375         }
376         /* level0 and first mipmap need to have alignment */
377         offset = surf->bo_size;
378         if ((i == 0)) {
379             offset = ALIGN(offset, surf->bo_alignment);
380         }
381     }
382     return 0;
383 }
384
385 static int r6_surface_init(struct radeon_surface_manager *surf_man,
386                            struct radeon_surface *surf)
387 {
388     unsigned mode;
389     int r;
390
391     /* MSAA surfaces support the 2D mode only. */
392     if (surf->nsamples > 1) {
393         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
394         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
395     }
396
397     /* tiling mode */
398     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
399
400     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
401         /* zbuffer only support 1D or 2D tiled surface */
402         switch (mode) {
403         case RADEON_SURF_MODE_1D:
404         case RADEON_SURF_MODE_2D:
405             break;
406         default:
407             mode = RADEON_SURF_MODE_1D;
408             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
409             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
410             break;
411         }
412     }
413
414     /* force 1d on kernel that can't do 2d */
415     if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
416         if (surf->nsamples > 1) {
417             fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
418             return -EFAULT;
419         }
420         mode = RADEON_SURF_MODE_1D;
421         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
422         surf->flags |= RADEON_SURF_SET(mode, MODE);
423     }
424
425     /* check surface dimension */
426     if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
427         return -EINVAL;
428     }
429
430     /* check mipmap last_level */
431     if (surf->last_level > 14) {
432         return -EINVAL;
433     }
434
435     /* check tiling mode */
436     switch (mode) {
437     case RADEON_SURF_MODE_LINEAR:
438         r = r6_surface_init_linear(surf_man, surf, 0, 0);
439         break;
440     case RADEON_SURF_MODE_LINEAR_ALIGNED:
441         r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
442         break;
443     case RADEON_SURF_MODE_1D:
444         r = r6_surface_init_1d(surf_man, surf, 0, 0);
445         break;
446     case RADEON_SURF_MODE_2D:
447         r = r6_surface_init_2d(surf_man, surf, 0, 0);
448         break;
449     default:
450         return -EINVAL;
451     }
452     return r;
453 }
454
455 static int r6_surface_best(struct radeon_surface_manager *surf_man,
456                            struct radeon_surface *surf)
457 {
458     /* no value to optimize for r6xx/r7xx */
459     return 0;
460 }
461
462
463 /* ===========================================================================
464  * evergreen family
465  */
466 static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
467 {
468     uint32_t tiling_config;
469     drmVersionPtr version;
470     int r;
471
472     r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
473                          &tiling_config);
474     if (r) {
475         return r;
476     }
477
478     surf_man->hw_info.allow_2d = 0;
479     version = drmGetVersion(surf_man->fd);
480     if (version && version->version_minor >= 16) {
481         surf_man->hw_info.allow_2d = 1;
482     }
483     drmFreeVersion(version);
484
485     switch (tiling_config & 0xf) {
486     case 0:
487         surf_man->hw_info.num_pipes = 1;
488         break;
489     case 1:
490         surf_man->hw_info.num_pipes = 2;
491         break;
492     case 2:
493         surf_man->hw_info.num_pipes = 4;
494         break;
495     case 3:
496         surf_man->hw_info.num_pipes = 8;
497         break;
498     default:
499         surf_man->hw_info.num_pipes = 8;
500         surf_man->hw_info.allow_2d = 0;
501         break;
502     }
503
504     switch ((tiling_config & 0xf0) >> 4) {
505     case 0:
506         surf_man->hw_info.num_banks = 4;
507         break;
508     case 1:
509         surf_man->hw_info.num_banks = 8;
510         break;
511     case 2:
512         surf_man->hw_info.num_banks = 16;
513         break;
514     default:
515         surf_man->hw_info.num_banks = 8;
516         surf_man->hw_info.allow_2d = 0;
517         break;
518     }
519
520     switch ((tiling_config & 0xf00) >> 8) {
521     case 0:
522         surf_man->hw_info.group_bytes = 256;
523         break;
524     case 1:
525         surf_man->hw_info.group_bytes = 512;
526         break;
527     default:
528         surf_man->hw_info.group_bytes = 256;
529         surf_man->hw_info.allow_2d = 0;
530         break;
531     }
532
533     switch ((tiling_config & 0xf000) >> 12) {
534     case 0:
535         surf_man->hw_info.row_size = 1024;
536         break;
537     case 1:
538         surf_man->hw_info.row_size = 2048;
539         break;
540     case 2:
541         surf_man->hw_info.row_size = 4096;
542         break;
543     default:
544         surf_man->hw_info.row_size = 4096;
545         surf_man->hw_info.allow_2d = 0;
546         break;
547     }
548     return 0;
549 }
550
551 static void eg_surf_minify(struct radeon_surface *surf,
552                            struct radeon_surface_level *surflevel,
553                            unsigned bpe,
554                            unsigned level,
555                            unsigned slice_pt,
556                            unsigned mtilew,
557                            unsigned mtileh,
558                            unsigned mtileb,
559                            unsigned offset)
560 {
561     unsigned mtile_pr, mtile_ps;
562
563     surflevel->npix_x = mip_minify(surf->npix_x, level);
564     surflevel->npix_y = mip_minify(surf->npix_y, level);
565     surflevel->npix_z = mip_minify(surf->npix_z, level);
566     surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
567     surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
568     surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
569     if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
570         !(surf->flags & RADEON_SURF_FMASK)) {
571         if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
572             surflevel->mode = RADEON_SURF_MODE_1D;
573             return;
574         }
575     }
576     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, mtilew);
577     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, mtileh);
578     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, 1);
579
580     /* macro tile per row */
581     mtile_pr = surflevel->nblk_x / mtilew;
582     /* macro tile per slice */
583     mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
584
585     surflevel->offset = offset;
586     surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
587     surflevel->slice_size = mtile_ps * mtileb * slice_pt;
588
589     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
590 }
591
592 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
593                               struct radeon_surface *surf,
594                               struct radeon_surface_level *level,
595                               unsigned bpe,
596                               uint64_t offset, unsigned start_level)
597 {
598     uint32_t xalign, yalign, zalign, tilew;
599     unsigned i;
600
601     /* compute alignment */
602     tilew = 8;
603     xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
604     xalign = MAX2(tilew, xalign);
605     yalign = tilew;
606     zalign = 1;
607     if (surf->flags & RADEON_SURF_SCANOUT) {
608         xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
609     }
610
611     if (!start_level) {
612         unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
613         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
614
615         if (offset) {
616             offset = ALIGN(offset, alignment);
617         }
618     }
619
620     /* build mipmap tree */
621     for (i = start_level; i <= surf->last_level; i++) {
622         level[i].mode = RADEON_SURF_MODE_1D;
623         surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
624         /* level0 and first mipmap need to have alignment */
625         offset = surf->bo_size;
626         if ((i == 0)) {
627             offset = ALIGN(offset, surf->bo_alignment);
628         }
629     }
630     return 0;
631 }
632
633 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
634                               struct radeon_surface *surf,
635                               struct radeon_surface_level *level,
636                               unsigned bpe, unsigned tile_split,
637                               uint64_t offset, unsigned start_level)
638 {
639     unsigned tilew, tileh, tileb;
640     unsigned mtilew, mtileh, mtileb;
641     unsigned slice_pt;
642     unsigned i;
643
644     /* compute tile values */
645     tilew = 8;
646     tileh = 8;
647     tileb = tilew * tileh * bpe * surf->nsamples;
648     /* slices per tile */
649     slice_pt = 1;
650     if (tileb > tile_split) {
651         slice_pt = tileb / tile_split;
652     }
653     tileb = tileb / slice_pt;
654
655     /* macro tile width & height */
656     mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
657     mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
658     /* macro tile bytes */
659     mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
660
661     if (!start_level) {
662         unsigned alignment = MAX2(256, mtileb);
663         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
664
665         if (offset) {
666             offset = ALIGN(offset, alignment);
667         }
668     }
669
670     /* build mipmap tree */
671     for (i = start_level; i <= surf->last_level; i++) {
672         level[i].mode = RADEON_SURF_MODE_2D;
673         eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
674         if (level[i].mode == RADEON_SURF_MODE_1D) {
675             return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
676         }
677         /* level0 and first mipmap need to have alignment */
678         offset = surf->bo_size;
679         if ((i == 0)) {
680             offset = ALIGN(offset, surf->bo_alignment);
681         }
682     }
683     return 0;
684 }
685
686 static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
687                              struct radeon_surface *surf,
688                              unsigned mode)
689 {
690     unsigned tileb;
691
692     /* check surface dimension */
693     if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
694         return -EINVAL;
695     }
696
697     /* check mipmap last_level */
698     if (surf->last_level > 15) {
699         return -EINVAL;
700     }
701
702     /* force 1d on kernel that can't do 2d */
703     if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
704         if (surf->nsamples > 1) {
705             fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
706             return -EFAULT;
707         }
708         mode = RADEON_SURF_MODE_1D;
709         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
710         surf->flags |= RADEON_SURF_SET(mode, MODE);
711     }
712
713     /* check tile split */
714     if (mode == RADEON_SURF_MODE_2D) {
715         switch (surf->tile_split) {
716         case 64:
717         case 128:
718         case 256:
719         case 512:
720         case 1024:
721         case 2048:
722         case 4096:
723             break;
724         default:
725             return -EINVAL;
726         }
727         switch (surf->mtilea) {
728         case 1:
729         case 2:
730         case 4:
731         case 8:
732             break;
733         default:
734             return -EINVAL;
735         }
736         /* check aspect ratio */
737         if (surf_man->hw_info.num_banks < surf->mtilea) {
738             return -EINVAL;
739         }
740         /* check bank width */
741         switch (surf->bankw) {
742         case 1:
743         case 2:
744         case 4:
745         case 8:
746             break;
747         default:
748             return -EINVAL;
749         }
750         /* check bank height */
751         switch (surf->bankh) {
752         case 1:
753         case 2:
754         case 4:
755         case 8:
756             break;
757         default:
758             return -EINVAL;
759         }
760         tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
761         if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
762             return -EINVAL;
763         }
764     }
765
766     return 0;
767 }
768
769 static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
770                                        struct radeon_surface *surf)
771 {
772     unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
773     int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
774     /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
775     struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
776     struct radeon_surface_level *stencil_level =
777         (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
778
779     r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
780     if (r)
781         return r;
782
783     if (is_depth_stencil) {
784         r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
785                                surf->bo_size, 0);
786         surf->stencil_offset = stencil_level[0].offset;
787     }
788     return r;
789 }
790
791 static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
792                                        struct radeon_surface *surf)
793 {
794     unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
795     int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
796     /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
797     struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
798     struct radeon_surface_level *stencil_level =
799         (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
800
801     r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
802                            surf->tile_split, 0, 0);
803     if (r)
804         return r;
805
806     if (is_depth_stencil) {
807         r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
808                                surf->stencil_tile_split, surf->bo_size, 0);
809         surf->stencil_offset = stencil_level[0].offset;
810     }
811     return r;
812 }
813
814 static int eg_surface_init(struct radeon_surface_manager *surf_man,
815                            struct radeon_surface *surf)
816 {
817     unsigned mode;
818     int r;
819
820     /* MSAA surfaces support the 2D mode only. */
821     if (surf->nsamples > 1) {
822         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
823         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
824     }
825
826     /* tiling mode */
827     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
828
829     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
830         /* zbuffer only support 1D or 2D tiled surface */
831         switch (mode) {
832         case RADEON_SURF_MODE_1D:
833         case RADEON_SURF_MODE_2D:
834             break;
835         default:
836             mode = RADEON_SURF_MODE_1D;
837             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
838             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
839             break;
840         }
841     }
842
843     r = eg_surface_sanity(surf_man, surf, mode);
844     if (r) {
845         return r;
846     }
847
848     surf->stencil_offset = 0;
849     surf->bo_alignment = 0;
850
851     /* check tiling mode */
852     switch (mode) {
853     case RADEON_SURF_MODE_LINEAR:
854         r = r6_surface_init_linear(surf_man, surf, 0, 0);
855         break;
856     case RADEON_SURF_MODE_LINEAR_ALIGNED:
857         r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
858         break;
859     case RADEON_SURF_MODE_1D:
860         r = eg_surface_init_1d_miptrees(surf_man, surf);
861         break;
862     case RADEON_SURF_MODE_2D:
863         r = eg_surface_init_2d_miptrees(surf_man, surf);
864         break;
865     default:
866         return -EINVAL;
867     }
868     return r;
869 }
870
871 static unsigned log2_int(unsigned x)
872 {
873     unsigned l;
874
875     if (x < 2) {
876         return 0;
877     }
878     for (l = 2; ; l++) {
879         if ((unsigned)(1 << l) > x) {
880             return l - 1;
881         }
882     }
883     return 0;
884 }
885
886 /* compute best tile_split, bankw, bankh, mtilea
887  * depending on surface
888  */
889 static int eg_surface_best(struct radeon_surface_manager *surf_man,
890                            struct radeon_surface *surf)
891 {
892     unsigned mode, tileb, h_over_w;
893     int r;
894
895     /* tiling mode */
896     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
897
898     /* set some default value to avoid sanity check choking on them */
899     surf->tile_split = 1024;
900     surf->bankw = 1;
901     surf->bankh = 1;
902     surf->mtilea = surf_man->hw_info.num_banks;
903     tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
904     for (; surf->bankh <= 8; surf->bankh *= 2) {
905         if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
906             break;
907         }
908     }
909     if (surf->mtilea > 8) {
910         surf->mtilea = 8;
911     }
912
913     r = eg_surface_sanity(surf_man, surf, mode);
914     if (r) {
915         return r;
916     }
917
918     if (mode != RADEON_SURF_MODE_2D) {
919         /* nothing to do for non 2D tiled surface */
920         return 0;
921     }
922
923     /* Tweak TILE_SPLIT for performance here. */
924     if (surf->nsamples > 1) {
925         if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
926             switch (surf->nsamples) {
927             case 2:
928                 surf->tile_split = 128;
929                 break;
930             case 4:
931                 surf->tile_split = 128;
932                 break;
933             case 8:
934                 surf->tile_split = 256;
935                 break;
936             case 16: /* cayman only */
937                 surf->tile_split = 512;
938                 break;
939             default:
940                 fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
941                         surf->nsamples, __LINE__);
942                 return -EINVAL;
943             }
944             surf->stencil_tile_split = 64;
945         } else {
946             /* tile split must be >= 256 for colorbuffer surfaces */
947             surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
948             if (surf->tile_split > 4096)
949                 surf->tile_split = 4096;
950         }
951     } else {
952         /* set tile split to row size */
953         surf->tile_split = surf_man->hw_info.row_size;
954         surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
955     }
956
957     /* bankw or bankh greater than 1 increase alignment requirement, not
958      * sure if it's worth using smaller bankw & bankh to stick with 2D
959      * tiling on small surface rather than falling back to 1D tiling.
960      * Use recommanded value based on tile size for now.
961      *
962      * fmask buffer has different optimal value figure them out once we
963      * use it.
964      */
965     if (surf->flags & RADEON_SURF_SBUFFER) {
966         /* assume 1 bytes for stencil, we optimize for stencil as stencil
967          * and depth shares surface values
968          */
969         tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
970     } else {
971         tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
972     }
973
974     /* use bankw of 1 to minimize width alignment, might be interesting to
975      * increase it for large surface
976      */
977     surf->bankw = 1;
978     switch (tileb) {
979     case 64:
980         surf->bankh = 4;
981         break;
982     case 128:
983     case 256:
984         surf->bankh = 2;
985         break;
986     default:
987         surf->bankh = 1;
988         break;
989     }
990     /* double check the constraint */
991     for (; surf->bankh <= 8; surf->bankh *= 2) {
992         if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
993             break;
994         }
995     }
996
997     h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
998                 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
999     surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
1000
1001     return 0;
1002 }
1003
1004
1005 /* ===========================================================================
1006  * Southern Islands family
1007  */
1008 #define SI__GB_TILE_MODE__PIPE_CONFIG(x)        (((x) >> 6) & 0x1f)
1009 #define     SI__PIPE_CONFIG__ADDR_SURF_P2               0
1010 #define     SI__PIPE_CONFIG__ADDR_SURF_P4_8x16          4
1011 #define     SI__PIPE_CONFIG__ADDR_SURF_P4_16x16         5
1012 #define     SI__PIPE_CONFIG__ADDR_SURF_P4_16x32         6
1013 #define     SI__PIPE_CONFIG__ADDR_SURF_P4_32x32         7
1014 #define     SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16    8
1015 #define     SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16    9
1016 #define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16    10
1017 #define     SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16   11
1018 #define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16   12
1019 #define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32   13
1020 #define     SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32   14
1021 #define SI__GB_TILE_MODE__TILE_SPLIT(x)         (((x) >> 11) & 0x7)
1022 #define     SI__TILE_SPLIT__64B                         0
1023 #define     SI__TILE_SPLIT__128B                        1
1024 #define     SI__TILE_SPLIT__256B                        2
1025 #define     SI__TILE_SPLIT__512B                        3
1026 #define     SI__TILE_SPLIT__1024B                       4
1027 #define     SI__TILE_SPLIT__2048B                       5
1028 #define     SI__TILE_SPLIT__4096B                       6
1029 #define SI__GB_TILE_MODE__BANK_WIDTH(x)         (((x) >> 14) & 0x3)
1030 #define     SI__BANK_WIDTH__1                           0
1031 #define     SI__BANK_WIDTH__2                           1
1032 #define     SI__BANK_WIDTH__4                           2
1033 #define     SI__BANK_WIDTH__8                           3
1034 #define SI__GB_TILE_MODE__BANK_HEIGHT(x)        (((x) >> 16) & 0x3)
1035 #define     SI__BANK_HEIGHT__1                          0
1036 #define     SI__BANK_HEIGHT__2                          1
1037 #define     SI__BANK_HEIGHT__4                          2
1038 #define     SI__BANK_HEIGHT__8                          3
1039 #define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x)  (((x) >> 18) & 0x3)
1040 #define     SI__MACRO_TILE_ASPECT__1                    0
1041 #define     SI__MACRO_TILE_ASPECT__2                    1
1042 #define     SI__MACRO_TILE_ASPECT__4                    2
1043 #define     SI__MACRO_TILE_ASPECT__8                    3
1044 #define SI__GB_TILE_MODE__NUM_BANKS(x)          (((x) >> 20) & 0x3)
1045 #define     SI__NUM_BANKS__2_BANK                       0
1046 #define     SI__NUM_BANKS__4_BANK                       1
1047 #define     SI__NUM_BANKS__8_BANK                       2
1048 #define     SI__NUM_BANKS__16_BANK                      3
1049
1050
1051 static void si_gb_tile_mode(uint32_t gb_tile_mode,
1052                             unsigned *num_pipes,
1053                             unsigned *num_banks,
1054                             uint32_t *macro_tile_aspect,
1055                             uint32_t *bank_w,
1056                             uint32_t *bank_h,
1057                             uint32_t *tile_split)
1058 {
1059     if (num_pipes) {
1060         switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1061         case SI__PIPE_CONFIG__ADDR_SURF_P2:
1062         default:
1063             *num_pipes = 2;
1064             break;
1065         case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1066         case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1067         case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1068         case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1069             *num_pipes = 4;
1070             break;
1071         case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1072         case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1073         case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1074         case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1075         case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1076         case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1077         case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1078             *num_pipes = 8;
1079             break;
1080         }
1081     }
1082     if (num_banks) {
1083         switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
1084         default:
1085         case SI__NUM_BANKS__2_BANK:
1086             *num_banks = 2;
1087             break;
1088         case SI__NUM_BANKS__4_BANK:
1089             *num_banks = 4;
1090             break;
1091         case SI__NUM_BANKS__8_BANK:
1092             *num_banks = 8;
1093             break;
1094         case SI__NUM_BANKS__16_BANK:
1095             *num_banks = 16;
1096             break;
1097         }
1098     }
1099     if (macro_tile_aspect) {
1100         switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
1101         default:
1102         case SI__MACRO_TILE_ASPECT__1:
1103             *macro_tile_aspect = 1;
1104             break;
1105         case SI__MACRO_TILE_ASPECT__2:
1106             *macro_tile_aspect = 2;
1107             break;
1108         case SI__MACRO_TILE_ASPECT__4:
1109             *macro_tile_aspect = 4;
1110             break;
1111         case SI__MACRO_TILE_ASPECT__8:
1112             *macro_tile_aspect = 8;
1113             break;
1114         }
1115     }
1116     if (bank_w) {
1117         switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
1118         default:
1119         case SI__BANK_WIDTH__1:
1120             *bank_w = 1;
1121             break;
1122         case SI__BANK_WIDTH__2:
1123             *bank_w = 2;
1124             break;
1125         case SI__BANK_WIDTH__4:
1126             *bank_w = 4;
1127             break;
1128         case SI__BANK_WIDTH__8:
1129             *bank_w = 8;
1130             break;
1131         }
1132     }
1133     if (bank_h) {
1134         switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
1135         default:
1136         case SI__BANK_HEIGHT__1:
1137             *bank_h = 1;
1138             break;
1139         case SI__BANK_HEIGHT__2:
1140             *bank_h = 2;
1141             break;
1142         case SI__BANK_HEIGHT__4:
1143             *bank_h = 4;
1144             break;
1145         case SI__BANK_HEIGHT__8:
1146             *bank_h = 8;
1147             break;
1148         }
1149     }
1150     if (tile_split) {
1151         switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1152         default:
1153         case SI__TILE_SPLIT__64B:
1154             *tile_split = 64;
1155             break;
1156         case SI__TILE_SPLIT__128B:
1157             *tile_split = 128;
1158             break;
1159         case SI__TILE_SPLIT__256B:
1160             *tile_split = 256;
1161             break;
1162         case SI__TILE_SPLIT__512B:
1163             *tile_split = 512;
1164             break;
1165         case SI__TILE_SPLIT__1024B:
1166             *tile_split = 1024;
1167             break;
1168         case SI__TILE_SPLIT__2048B:
1169             *tile_split = 2048;
1170             break;
1171         case SI__TILE_SPLIT__4096B:
1172             *tile_split = 4096;
1173             break;
1174         }
1175     }
1176 }
1177
1178 static int si_init_hw_info(struct radeon_surface_manager *surf_man)
1179 {
1180     uint32_t tiling_config;
1181     drmVersionPtr version;
1182     int r;
1183
1184     r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
1185                          &tiling_config);
1186     if (r) {
1187         return r;
1188     }
1189
1190     surf_man->hw_info.allow_2d = 0;
1191     version = drmGetVersion(surf_man->fd);
1192     if (version && version->version_minor >= 33) {
1193         if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
1194             surf_man->hw_info.allow_2d = 1;
1195         }
1196     }
1197     drmFreeVersion(version);
1198
1199     switch (tiling_config & 0xf) {
1200     case 0:
1201         surf_man->hw_info.num_pipes = 1;
1202         break;
1203     case 1:
1204         surf_man->hw_info.num_pipes = 2;
1205         break;
1206     case 2:
1207         surf_man->hw_info.num_pipes = 4;
1208         break;
1209     case 3:
1210         surf_man->hw_info.num_pipes = 8;
1211         break;
1212     default:
1213         surf_man->hw_info.num_pipes = 8;
1214         surf_man->hw_info.allow_2d = 0;
1215         break;
1216     }
1217
1218     switch ((tiling_config & 0xf0) >> 4) {
1219     case 0:
1220         surf_man->hw_info.num_banks = 4;
1221         break;
1222     case 1:
1223         surf_man->hw_info.num_banks = 8;
1224         break;
1225     case 2:
1226         surf_man->hw_info.num_banks = 16;
1227         break;
1228     default:
1229         surf_man->hw_info.num_banks = 8;
1230         surf_man->hw_info.allow_2d = 0;
1231         break;
1232     }
1233
1234     switch ((tiling_config & 0xf00) >> 8) {
1235     case 0:
1236         surf_man->hw_info.group_bytes = 256;
1237         break;
1238     case 1:
1239         surf_man->hw_info.group_bytes = 512;
1240         break;
1241     default:
1242         surf_man->hw_info.group_bytes = 256;
1243         surf_man->hw_info.allow_2d = 0;
1244         break;
1245     }
1246
1247     switch ((tiling_config & 0xf000) >> 12) {
1248     case 0:
1249         surf_man->hw_info.row_size = 1024;
1250         break;
1251     case 1:
1252         surf_man->hw_info.row_size = 2048;
1253         break;
1254     case 2:
1255         surf_man->hw_info.row_size = 4096;
1256         break;
1257     default:
1258         surf_man->hw_info.row_size = 4096;
1259         surf_man->hw_info.allow_2d = 0;
1260         break;
1261     }
1262     return 0;
1263 }
1264
1265 static int si_surface_sanity(struct radeon_surface_manager *surf_man,
1266                              struct radeon_surface *surf,
1267                              unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
1268 {
1269     uint32_t gb_tile_mode;
1270
1271     /* check surface dimension */
1272     if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
1273         return -EINVAL;
1274     }
1275
1276     /* check mipmap last_level */
1277     if (surf->last_level > 15) {
1278         return -EINVAL;
1279     }
1280
1281     /* force 1d on kernel that can't do 2d */
1282     if (mode > RADEON_SURF_MODE_1D &&
1283         (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
1284         if (surf->nsamples > 1) {
1285             fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
1286             return -EFAULT;
1287         }
1288         mode = RADEON_SURF_MODE_1D;
1289         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1290         surf->flags |= RADEON_SURF_SET(mode, MODE);
1291     }
1292
1293     if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
1294         return -EINVAL;
1295     }
1296
1297     if (!surf->tile_split) {
1298         /* default value */
1299         surf->mtilea = 1;
1300         surf->bankw = 1;
1301         surf->bankw = 1;
1302         surf->tile_split = 64;
1303         surf->stencil_tile_split = 64;
1304     }
1305
1306     switch (mode) {
1307     case RADEON_SURF_MODE_2D:
1308         if (surf->flags & RADEON_SURF_SBUFFER) {
1309             switch (surf->nsamples) {
1310             case 1:
1311                 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1312                 break;
1313             case 2:
1314                 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1315                 break;
1316             case 4:
1317                 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1318                 break;
1319             case 8:
1320                 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1321                 break;
1322             default:
1323                 return -EINVAL;
1324             }
1325             /* retrieve tiling mode value */
1326             gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
1327             si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
1328         }
1329         if (surf->flags & RADEON_SURF_ZBUFFER) {
1330             switch (surf->nsamples) {
1331             case 1:
1332                 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1333                 break;
1334             case 2:
1335                 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1336                 break;
1337             case 4:
1338                 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1339                 break;
1340             case 8:
1341                 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1342                 break;
1343             default:
1344                 return -EINVAL;
1345             }
1346         } else if (surf->flags & RADEON_SURF_SCANOUT) {
1347             switch (surf->bpe) {
1348             case 2:
1349                 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
1350                 break;
1351             case 4:
1352                 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
1353                 break;
1354             default:
1355                 return -EINVAL;
1356             }
1357         } else {
1358             switch (surf->bpe) {
1359             case 1:
1360                 *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
1361                 break;
1362             case 2:
1363                 *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
1364                 break;
1365             case 4:
1366                 *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
1367                 break;
1368             case 8:
1369             case 16:
1370                 *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
1371                 break;
1372             default:
1373                 return -EINVAL;
1374             }
1375         }
1376         /* retrieve tiling mode value */
1377         gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
1378         si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
1379         break;
1380     case RADEON_SURF_MODE_1D:
1381         if (surf->flags & RADEON_SURF_SBUFFER) {
1382             *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1383         }
1384         if (surf->flags & RADEON_SURF_ZBUFFER) {
1385             *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1386         } else if (surf->flags & RADEON_SURF_SCANOUT) {
1387             *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1388         } else {
1389             *tile_mode = SI_TILE_MODE_COLOR_1D;
1390         }
1391         break;
1392     case RADEON_SURF_MODE_LINEAR_ALIGNED:
1393     default:
1394         *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
1395     }
1396
1397     return 0;
1398 }
1399
1400 static void si_surf_minify(struct radeon_surface *surf,
1401                            struct radeon_surface_level *surflevel,
1402                            unsigned bpe, unsigned level,
1403                            uint32_t xalign, uint32_t yalign, uint32_t zalign,
1404                            uint32_t slice_align, unsigned offset)
1405 {
1406     surflevel->npix_x = mip_minify(surf->npix_x, level);
1407     surflevel->npix_y = mip_minify(surf->npix_y, level);
1408     surflevel->npix_z = mip_minify(surf->npix_z, level);
1409
1410     if (level == 0 && surf->last_level > 0) {
1411         surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1412         surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1413         surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1414     } else {
1415         surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1416         surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1417         surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1418     }
1419
1420     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
1421
1422     /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1423      * these are just guesses for the rules behind those
1424      */
1425     if (level == 0 && surf->last_level == 0)
1426         /* Non-mipmap pitch padded to slice alignment */
1427         xalign = MAX2(xalign, slice_align / surf->bpe);
1428     else
1429         /* Small rows evenly distributed across slice */
1430         xalign = MAX2(xalign, slice_align / surf->bpe / surflevel->nblk_y);
1431
1432     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
1433     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
1434
1435     surflevel->offset = offset;
1436     surflevel->pitch_bytes = surflevel->nblk_x * surf->bpe * surf->nsamples;
1437     surflevel->slice_size = ALIGN(surflevel->pitch_bytes * surflevel->nblk_y, slice_align);
1438
1439     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1440 }
1441
1442 static void si_surf_minify_2d(struct radeon_surface *surf,
1443                               struct radeon_surface_level *surflevel,
1444                               unsigned bpe, unsigned level, unsigned slice_pt,
1445                               uint32_t xalign, uint32_t yalign, uint32_t zalign,
1446                               unsigned mtileb, unsigned offset)
1447 {
1448     unsigned mtile_pr, mtile_ps;
1449
1450     surflevel->npix_x = mip_minify(surf->npix_x, level);
1451     surflevel->npix_y = mip_minify(surf->npix_y, level);
1452     surflevel->npix_z = mip_minify(surf->npix_z, level);
1453
1454     if (level == 0 && surf->last_level > 0) {
1455         surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1456         surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1457         surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1458     } else {
1459         surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1460         surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1461         surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1462     }
1463
1464     if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
1465         !(surf->flags & RADEON_SURF_FMASK)) {
1466         if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
1467             surflevel->mode = RADEON_SURF_MODE_1D;
1468             return;
1469         }
1470     }
1471     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
1472     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
1473     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
1474
1475     /* macro tile per row */
1476     mtile_pr = surflevel->nblk_x / xalign;
1477     /* macro tile per slice */
1478     mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
1479     surflevel->offset = offset;
1480     surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
1481     surflevel->slice_size = mtile_ps * mtileb * slice_pt;
1482
1483     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1484 }
1485
1486 static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1487                                           struct radeon_surface *surf,
1488                                           unsigned tile_mode,
1489                                           uint64_t offset, unsigned start_level)
1490 {
1491     uint32_t xalign, yalign, zalign, slice_align;
1492     unsigned i;
1493
1494     /* compute alignment */
1495     if (!start_level) {
1496         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1497     }
1498     xalign = MAX2(8, 64 / surf->bpe);
1499     yalign = 1;
1500     zalign = 1;
1501     slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1502
1503     /* build mipmap tree */
1504     for (i = start_level; i <= surf->last_level; i++) {
1505         surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1506         si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
1507         /* level0 and first mipmap need to have alignment */
1508         offset = surf->bo_size;
1509         if ((i == 0)) {
1510             offset = ALIGN(offset, surf->bo_alignment);
1511         }
1512         if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1513             surf->tiling_index[i] = tile_mode;
1514         }
1515     }
1516     return 0;
1517 }
1518
1519 static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1520                               struct radeon_surface *surf,
1521                               struct radeon_surface_level *level,
1522                               unsigned bpe, unsigned tile_mode,
1523                               uint64_t offset, unsigned start_level)
1524 {
1525     uint32_t xalign, yalign, zalign, slice_align;
1526     unsigned i;
1527
1528     /* compute alignment */
1529     xalign = 8;
1530     yalign = 8;
1531     zalign = 1;
1532     slice_align = surf_man->hw_info.group_bytes;
1533     if (surf->flags & RADEON_SURF_SCANOUT) {
1534         xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1535     }
1536
1537     if (!start_level) {
1538         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1539
1540         if (offset) {
1541             offset = ALIGN(offset, surf->bo_alignment);
1542         }
1543     }
1544
1545     /* build mipmap tree */
1546     for (i = start_level; i <= surf->last_level; i++) {
1547         level[i].mode = RADEON_SURF_MODE_1D;
1548         si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1549         /* level0 and first mipmap need to have alignment */
1550         offset = surf->bo_size;
1551         if ((i == 0)) {
1552             offset = ALIGN(offset, surf->bo_alignment);
1553         }
1554         if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1555             if (surf->level == level) {
1556                 surf->tiling_index[i] = tile_mode;
1557                 /* it's ok because stencil is done after */
1558                 surf->stencil_tiling_index[i] = tile_mode;
1559             } else {
1560                 surf->stencil_tiling_index[i] = tile_mode;
1561             }
1562         }
1563     }
1564     return 0;
1565 }
1566
1567 static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1568                                        struct radeon_surface *surf,
1569                                        unsigned tile_mode, unsigned stencil_tile_mode)
1570 {
1571     int r;
1572
1573     r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
1574     if (r) {
1575         return r;
1576     }
1577
1578     if (surf->flags & RADEON_SURF_SBUFFER) {
1579         r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
1580         surf->stencil_offset = surf->stencil_level[0].offset;
1581     }
1582     return r;
1583 }
1584
1585 static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
1586                               struct radeon_surface *surf,
1587                               struct radeon_surface_level *level,
1588                               unsigned bpe, unsigned tile_mode,
1589                               unsigned num_pipes, unsigned num_banks,
1590                               unsigned tile_split,
1591                               uint64_t offset,
1592                               unsigned start_level)
1593 {
1594     unsigned tilew, tileh, tileb;
1595     unsigned mtilew, mtileh, mtileb;
1596     unsigned slice_pt;
1597     unsigned i;
1598
1599     /* compute tile values */
1600     tilew = 8;
1601     tileh = 8;
1602     tileb = tilew * tileh * bpe * surf->nsamples;
1603     /* slices per tile */
1604     slice_pt = 1;
1605     if (tileb > tile_split) {
1606         slice_pt = tileb / tile_split;
1607     }
1608     tileb = tileb / slice_pt;
1609
1610     /* macro tile width & height */
1611     mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
1612     mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
1613
1614     /* macro tile bytes */
1615     mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
1616
1617     if (!start_level) {
1618         unsigned alignment = MAX2(256, mtileb);
1619         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1620
1621         if (offset) {
1622             offset = ALIGN(offset, alignment);
1623         }
1624     }
1625
1626     /* build mipmap tree */
1627     for (i = start_level; i <= surf->last_level; i++) {
1628         level[i].mode = RADEON_SURF_MODE_2D;
1629         si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, offset);
1630         if (level[i].mode == RADEON_SURF_MODE_1D) {
1631             switch (tile_mode) {
1632             case SI_TILE_MODE_COLOR_2D_8BPP:
1633             case SI_TILE_MODE_COLOR_2D_16BPP:
1634             case SI_TILE_MODE_COLOR_2D_32BPP:
1635             case SI_TILE_MODE_COLOR_2D_64BPP:
1636                 tile_mode = SI_TILE_MODE_COLOR_1D;
1637                 break;
1638             case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
1639             case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
1640                 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1641                 break;
1642             case SI_TILE_MODE_DEPTH_STENCIL_2D:
1643                 tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1644                 break;
1645             default:
1646                 return -EINVAL;
1647             }
1648             return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
1649         }
1650         /* level0 and first mipmap need to have alignment */
1651         offset = surf->bo_size;
1652         if ((i == 0)) {
1653             offset = ALIGN(offset, surf->bo_alignment);
1654         }
1655         if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1656             if (surf->level == level) {
1657                 surf->tiling_index[i] = tile_mode;
1658                 /* it's ok because stencil is done after */
1659                 surf->stencil_tiling_index[i] = tile_mode;
1660             } else {
1661                 surf->stencil_tiling_index[i] = tile_mode;
1662             }
1663         }
1664     }
1665     return 0;
1666 }
1667
1668 static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
1669                                        struct radeon_surface *surf,
1670                                        unsigned tile_mode, unsigned stencil_tile_mode)
1671 {
1672     unsigned num_pipes, num_banks;
1673     uint32_t gb_tile_mode;
1674     int r;
1675
1676     /* retrieve tiling mode value */
1677     gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1678     si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
1679
1680     r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
1681     if (r) {
1682         return r;
1683     }
1684
1685     if (surf->flags & RADEON_SURF_SBUFFER) {
1686         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);
1687         surf->stencil_offset = surf->stencil_level[0].offset;
1688     }
1689     return r;
1690 }
1691
1692 static int si_surface_init(struct radeon_surface_manager *surf_man,
1693                            struct radeon_surface *surf)
1694 {
1695     unsigned mode, tile_mode, stencil_tile_mode;
1696     int r;
1697
1698     /* MSAA surfaces support the 2D mode only. */
1699     if (surf->nsamples > 1) {
1700         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1701         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1702     }
1703
1704     /* tiling mode */
1705     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1706
1707     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1708         /* zbuffer only support 1D or 2D tiled surface */
1709         switch (mode) {
1710         case RADEON_SURF_MODE_1D:
1711         case RADEON_SURF_MODE_2D:
1712             break;
1713         default:
1714             mode = RADEON_SURF_MODE_1D;
1715             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1716             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1717             break;
1718         }
1719     }
1720
1721     r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1722     if (r) {
1723         return r;
1724     }
1725
1726     surf->stencil_offset = 0;
1727     surf->bo_alignment = 0;
1728
1729     /* check tiling mode */
1730     switch (mode) {
1731     case RADEON_SURF_MODE_LINEAR:
1732         r = r6_surface_init_linear(surf_man, surf, 0, 0);
1733         break;
1734     case RADEON_SURF_MODE_LINEAR_ALIGNED:
1735         r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
1736         break;
1737     case RADEON_SURF_MODE_1D:
1738         r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1739         break;
1740     case RADEON_SURF_MODE_2D:
1741         r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1742         break;
1743     default:
1744         return -EINVAL;
1745     }
1746     return r;
1747 }
1748
1749 /*
1750  * depending on surface
1751  */
1752 static int si_surface_best(struct radeon_surface_manager *surf_man,
1753                            struct radeon_surface *surf)
1754 {
1755     unsigned mode, tile_mode, stencil_tile_mode;
1756
1757     /* tiling mode */
1758     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1759
1760     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
1761         !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
1762         /* depth/stencil force 1d tiling for old mesa */
1763         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1764         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1765     }
1766
1767     return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1768 }
1769
1770
1771 /* ===========================================================================
1772  * public API
1773  */
1774 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
1775 {
1776     struct radeon_surface_manager *surf_man;
1777
1778     surf_man = calloc(1, sizeof(struct radeon_surface_manager));
1779     if (surf_man == NULL) {
1780         return NULL;
1781     }
1782     surf_man->fd = fd;
1783     if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
1784         goto out_err;
1785     }
1786     if (radeon_get_family(surf_man)) {
1787         goto out_err;
1788     }
1789
1790     if (surf_man->family <= CHIP_RV740) {
1791         if (r6_init_hw_info(surf_man)) {
1792             goto out_err;
1793         }
1794         surf_man->surface_init = &r6_surface_init;
1795         surf_man->surface_best = &r6_surface_best;
1796     } else if (surf_man->family <= CHIP_ARUBA) {
1797         if (eg_init_hw_info(surf_man)) {
1798             goto out_err;
1799         }
1800         surf_man->surface_init = &eg_surface_init;
1801         surf_man->surface_best = &eg_surface_best;
1802     } else {
1803         if (si_init_hw_info(surf_man)) {
1804             goto out_err;
1805         }
1806         surf_man->surface_init = &si_surface_init;
1807         surf_man->surface_best = &si_surface_best;
1808     }
1809
1810     return surf_man;
1811 out_err:
1812     free(surf_man);
1813     return NULL;
1814 }
1815
1816 void radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
1817 {
1818     free(surf_man);
1819 }
1820
1821 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
1822                                  struct radeon_surface *surf,
1823                                  unsigned type,
1824                                  unsigned mode)
1825 {
1826     if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
1827         return -EINVAL;
1828     }
1829
1830     /* all dimension must be at least 1 ! */
1831     if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
1832         return -EINVAL;
1833     }
1834     if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
1835         return -EINVAL;
1836     }
1837     if (!surf->array_size) {
1838         return -EINVAL;
1839     }
1840     /* array size must be a power of 2 */
1841     surf->array_size = next_power_of_two(surf->array_size);
1842
1843     switch (surf->nsamples) {
1844     case 1:
1845     case 2:
1846     case 4:
1847     case 8:
1848         break;
1849     default:
1850         return -EINVAL;
1851     }
1852     /* check type */
1853     switch (type) {
1854     case RADEON_SURF_TYPE_1D:
1855         if (surf->npix_y > 1) {
1856             return -EINVAL;
1857         }
1858     case RADEON_SURF_TYPE_2D:
1859         if (surf->npix_z > 1) {
1860             return -EINVAL;
1861         }
1862         break;
1863     case RADEON_SURF_TYPE_CUBEMAP:
1864         if (surf->npix_z > 1) {
1865             return -EINVAL;
1866         }
1867         /* deal with cubemap as they were texture array */
1868         if (surf_man->family >= CHIP_RV770) {
1869             surf->array_size = 8;
1870         } else {
1871             surf->array_size = 6;
1872         }
1873         break;
1874     case RADEON_SURF_TYPE_3D:
1875         break;
1876     case RADEON_SURF_TYPE_1D_ARRAY:
1877         if (surf->npix_y > 1) {
1878             return -EINVAL;
1879         }
1880     case RADEON_SURF_TYPE_2D_ARRAY:
1881         break;
1882     default:
1883         return -EINVAL;
1884     }
1885     return 0;
1886 }
1887
1888 int radeon_surface_init(struct radeon_surface_manager *surf_man,
1889                         struct radeon_surface *surf)
1890 {
1891     unsigned mode, type;
1892     int r;
1893
1894     type = RADEON_SURF_GET(surf->flags, TYPE);
1895     mode = RADEON_SURF_GET(surf->flags, MODE);
1896
1897     r = radeon_surface_sanity(surf_man, surf, type, mode);
1898     if (r) {
1899         return r;
1900     }
1901     return surf_man->surface_init(surf_man, surf);
1902 }
1903
1904 int radeon_surface_best(struct radeon_surface_manager *surf_man,
1905                         struct radeon_surface *surf)
1906 {
1907     unsigned mode, type;
1908     int r;
1909
1910     type = RADEON_SURF_GET(surf->flags, TYPE);
1911     mode = RADEON_SURF_GET(surf->flags, MODE);
1912
1913     r = radeon_surface_sanity(surf_man, surf, type, mode);
1914     if (r) {
1915         return r;
1916     }
1917     return surf_man->surface_best(surf_man, surf);
1918 }