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