OSDN Git Service

radeon: fix tile_split of 128-bit surface formats with 8x MSAA
[android-x86/external-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_LAST,
76 };
77
78 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
79                                  struct radeon_surface *surf);
80 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
81                                  struct radeon_surface *surf);
82
83 struct radeon_hw_info {
84     /* apply to r6, eg */
85     uint32_t                    group_bytes;
86     uint32_t                    num_banks;
87     uint32_t                    num_pipes;
88     /* apply to eg */
89     uint32_t                    row_size;
90     unsigned                    allow_2d;
91 };
92
93 struct radeon_surface_manager {
94     int                         fd;
95     uint32_t                    device_id;
96     struct radeon_hw_info       hw_info;
97     unsigned                    family;
98     hw_init_surface_t           surface_init;
99     hw_best_surface_t           surface_best;
100 };
101
102 /* helper */
103 static int radeon_get_value(int fd, unsigned req, uint32_t *value)
104 {
105     struct drm_radeon_info info = {};
106     int r;
107
108     *value = 0;
109     info.request = req;
110     info.value = (uintptr_t)value;
111     r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
112                             sizeof(struct drm_radeon_info));
113     return r;
114 }
115
116 static int radeon_get_family(struct radeon_surface_manager *surf_man)
117 {
118     switch (surf_man->device_id) {
119 #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
120 #include "r600_pci_ids.h"
121 #undef CHIPSET
122     default:
123         return -EINVAL;
124     }
125     return 0;
126 }
127
128 static unsigned next_power_of_two(unsigned x)
129 {
130    if (x <= 1)
131        return 1;
132
133    return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
134 }
135
136 static unsigned mip_minify(unsigned size, unsigned level)
137 {
138     unsigned val;
139
140     val = MAX2(1, size >> level);
141     if (level > 0)
142         val = next_power_of_two(val);
143     return val;
144 }
145
146 static void surf_minify(struct radeon_surface *surf,
147                         struct radeon_surface_level *surflevel,
148                         unsigned bpe, unsigned level,
149                         uint32_t xalign, uint32_t yalign, uint32_t zalign,
150                         unsigned offset)
151 {
152     surflevel->npix_x = mip_minify(surf->npix_x, level);
153     surflevel->npix_y = mip_minify(surf->npix_y, level);
154     surflevel->npix_z = mip_minify(surf->npix_z, level);
155     surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
156     surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
157     surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
158     if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
159         if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
160             surflevel->mode = RADEON_SURF_MODE_1D;
161             return;
162         }
163     }
164     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
165     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
166     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
167
168     surflevel->offset = offset;
169     surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
170     surflevel->slice_size = surflevel->pitch_bytes * surflevel->nblk_y;
171
172     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
173 }
174
175 /* ===========================================================================
176  * r600/r700 family
177  */
178 static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
179 {
180     uint32_t tiling_config;
181     drmVersionPtr version;
182     int r;
183
184     r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
185                          &tiling_config);
186     if (r) {
187         return r;
188     }
189
190     surf_man->hw_info.allow_2d = 0;
191     version = drmGetVersion(surf_man->fd);
192     if (version && version->version_minor >= 14) {
193         surf_man->hw_info.allow_2d = 1;
194     }
195     drmFreeVersion(version);
196
197     switch ((tiling_config & 0xe) >> 1) {
198     case 0:
199         surf_man->hw_info.num_pipes = 1;
200         break;
201     case 1:
202         surf_man->hw_info.num_pipes = 2;
203         break;
204     case 2:
205         surf_man->hw_info.num_pipes = 4;
206         break;
207     case 3:
208         surf_man->hw_info.num_pipes = 8;
209         break;
210     default:
211         surf_man->hw_info.num_pipes = 8;
212         surf_man->hw_info.allow_2d = 0;
213         break;
214     }
215
216     switch ((tiling_config & 0x30) >> 4) {
217     case 0:
218         surf_man->hw_info.num_banks = 4;
219         break;
220     case 1:
221         surf_man->hw_info.num_banks = 8;
222         break;
223     default:
224         surf_man->hw_info.num_banks = 8;
225         surf_man->hw_info.allow_2d = 0;
226         break;
227     }
228
229     switch ((tiling_config & 0xc0) >> 6) {
230     case 0:
231         surf_man->hw_info.group_bytes = 256;
232         break;
233     case 1:
234         surf_man->hw_info.group_bytes = 512;
235         break;
236     default:
237         surf_man->hw_info.group_bytes = 256;
238         surf_man->hw_info.allow_2d = 0;
239         break;
240     }
241     return 0;
242 }
243
244 static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
245                                   struct radeon_surface *surf,
246                                   uint64_t offset, unsigned start_level)
247 {
248     uint32_t xalign, yalign, zalign;
249     unsigned i;
250
251     /* compute alignment */
252     if (!start_level) {
253         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
254     }
255     /* the 32 alignment is for scanout, cb or db but to allow texture to be
256      * easily bound as such we force this alignment to all surface
257      */
258     xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
259     yalign = 1;
260     zalign = 1;
261     if (surf->flags & RADEON_SURF_SCANOUT) {
262         xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
263     }
264
265     /* build mipmap tree */
266     for (i = start_level; i <= surf->last_level; i++) {
267         surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
268         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
269         /* level0 and first mipmap need to have alignment */
270         offset = surf->bo_size;
271         if ((i == 0)) {
272             offset = ALIGN(offset, surf->bo_alignment);
273         }
274     }
275     return 0;
276 }
277
278 static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
279                                           struct radeon_surface *surf,
280                                           uint64_t offset, unsigned start_level)
281 {
282     uint32_t xalign, yalign, zalign;
283     unsigned i;
284
285     /* compute alignment */
286     if (!start_level) {
287         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
288     }
289     xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
290     yalign = 1;
291     zalign = 1;
292
293     /* build mipmap tree */
294     for (i = start_level; i <= surf->last_level; i++) {
295         surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
296         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
297         /* level0 and first mipmap need to have alignment */
298         offset = surf->bo_size;
299         if ((i == 0)) {
300             offset = ALIGN(offset, surf->bo_alignment);
301         }
302     }
303     return 0;
304 }
305
306 static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
307                               struct radeon_surface *surf,
308                               uint64_t offset, unsigned start_level)
309 {
310     uint32_t xalign, yalign, zalign, tilew;
311     unsigned i;
312
313     /* compute alignment */
314     tilew = 8;
315     xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
316     xalign = MAX2(tilew, xalign);
317     yalign = tilew;
318     zalign = 1;
319     if (surf->flags & RADEON_SURF_SCANOUT) {
320         xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
321     }
322     if (!start_level) {
323         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
324     }
325
326     /* build mipmap tree */
327     for (i = start_level; i <= surf->last_level; i++) {
328         surf->level[i].mode = RADEON_SURF_MODE_1D;
329         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
330         /* level0 and first mipmap need to have alignment */
331         offset = surf->bo_size;
332         if ((i == 0)) {
333             offset = ALIGN(offset, surf->bo_alignment);
334         }
335     }
336     return 0;
337 }
338
339 static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
340                               struct radeon_surface *surf,
341                               uint64_t offset, unsigned start_level)
342 {
343     uint32_t xalign, yalign, zalign, tilew;
344     unsigned i;
345
346     /* compute alignment */
347     tilew = 8;
348     zalign = 1;
349     xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
350              (tilew * surf->bpe * surf->nsamples);
351     xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
352     yalign = tilew * surf_man->hw_info.num_pipes;
353     if (surf->flags & RADEON_SURF_SCANOUT) {
354         xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
355     }
356     if (!start_level) {
357         surf->bo_alignment =
358             MAX2(surf_man->hw_info.num_pipes *
359                  surf_man->hw_info.num_banks *
360                  surf->nsamples * surf->bpe * 64,
361                  xalign * yalign * surf->nsamples * surf->bpe);
362     }
363
364     /* build mipmap tree */
365     for (i = start_level; i <= surf->last_level; i++) {
366         surf->level[i].mode = RADEON_SURF_MODE_2D;
367         surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
368         if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
369             return r6_surface_init_1d(surf_man, surf, offset, i);
370         }
371         /* level0 and first mipmap need to have alignment */
372         offset = surf->bo_size;
373         if ((i == 0)) {
374             offset = ALIGN(offset, surf->bo_alignment);
375         }
376     }
377     return 0;
378 }
379
380 static int r6_surface_init(struct radeon_surface_manager *surf_man,
381                            struct radeon_surface *surf)
382 {
383     unsigned mode;
384     int r;
385
386     /* MSAA surfaces support the 2D mode only. */
387     if (surf->nsamples > 1) {
388         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
389         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
390     }
391
392     /* tiling mode */
393     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
394
395     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
396         /* zbuffer only support 1D or 2D tiled surface */
397         switch (mode) {
398         case RADEON_SURF_MODE_1D:
399         case RADEON_SURF_MODE_2D:
400             break;
401         default:
402             mode = RADEON_SURF_MODE_1D;
403             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
404             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
405             break;
406         }
407     }
408
409     /* force 1d on kernel that can't do 2d */
410     if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
411         if (surf->nsamples > 1) {
412             fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
413             return -EFAULT;
414         }
415         mode = RADEON_SURF_MODE_1D;
416         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
417         surf->flags |= RADEON_SURF_SET(mode, MODE);
418     }
419
420     /* check surface dimension */
421     if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
422         return -EINVAL;
423     }
424
425     /* check mipmap last_level */
426     if (surf->last_level > 14) {
427         return -EINVAL;
428     }
429
430     /* check tiling mode */
431     switch (mode) {
432     case RADEON_SURF_MODE_LINEAR:
433         r = r6_surface_init_linear(surf_man, surf, 0, 0);
434         break;
435     case RADEON_SURF_MODE_LINEAR_ALIGNED:
436         r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
437         break;
438     case RADEON_SURF_MODE_1D:
439         r = r6_surface_init_1d(surf_man, surf, 0, 0);
440         break;
441     case RADEON_SURF_MODE_2D:
442         r = r6_surface_init_2d(surf_man, surf, 0, 0);
443         break;
444     default:
445         return -EINVAL;
446     }
447     return r;
448 }
449
450 static int r6_surface_best(struct radeon_surface_manager *surf_man,
451                            struct radeon_surface *surf)
452 {
453     /* no value to optimize for r6xx/r7xx */
454     return 0;
455 }
456
457
458 /* ===========================================================================
459  * evergreen family
460  */
461 static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
462 {
463     uint32_t tiling_config;
464     drmVersionPtr version;
465     int r;
466
467     r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
468                          &tiling_config);
469     if (r) {
470         return r;
471     }
472
473     surf_man->hw_info.allow_2d = 0;
474     version = drmGetVersion(surf_man->fd);
475     if (version && version->version_minor >= 16) {
476         surf_man->hw_info.allow_2d = 1;
477     }
478     drmFreeVersion(version);
479
480     switch (tiling_config & 0xf) {
481     case 0:
482         surf_man->hw_info.num_pipes = 1;
483         break;
484     case 1:
485         surf_man->hw_info.num_pipes = 2;
486         break;
487     case 2:
488         surf_man->hw_info.num_pipes = 4;
489         break;
490     case 3:
491         surf_man->hw_info.num_pipes = 8;
492         break;
493     default:
494         surf_man->hw_info.num_pipes = 8;
495         surf_man->hw_info.allow_2d = 0;
496         break;
497     }
498
499     switch ((tiling_config & 0xf0) >> 4) {
500     case 0:
501         surf_man->hw_info.num_banks = 4;
502         break;
503     case 1:
504         surf_man->hw_info.num_banks = 8;
505         break;
506     case 2:
507         surf_man->hw_info.num_banks = 16;
508         break;
509     default:
510         surf_man->hw_info.num_banks = 8;
511         surf_man->hw_info.allow_2d = 0;
512         break;
513     }
514
515     switch ((tiling_config & 0xf00) >> 8) {
516     case 0:
517         surf_man->hw_info.group_bytes = 256;
518         break;
519     case 1:
520         surf_man->hw_info.group_bytes = 512;
521         break;
522     default:
523         surf_man->hw_info.group_bytes = 256;
524         surf_man->hw_info.allow_2d = 0;
525         break;
526     }
527
528     switch ((tiling_config & 0xf000) >> 12) {
529     case 0:
530         surf_man->hw_info.row_size = 1024;
531         break;
532     case 1:
533         surf_man->hw_info.row_size = 2048;
534         break;
535     case 2:
536         surf_man->hw_info.row_size = 4096;
537         break;
538     default:
539         surf_man->hw_info.row_size = 4096;
540         surf_man->hw_info.allow_2d = 0;
541         break;
542     }
543     return 0;
544 }
545
546 static void eg_surf_minify(struct radeon_surface *surf,
547                            struct radeon_surface_level *surflevel,
548                            unsigned bpe,
549                            unsigned level,
550                            unsigned slice_pt,
551                            unsigned mtilew,
552                            unsigned mtileh,
553                            unsigned mtileb,
554                            unsigned offset)
555 {
556     unsigned mtile_pr, mtile_ps;
557
558     surflevel->npix_x = mip_minify(surf->npix_x, level);
559     surflevel->npix_y = mip_minify(surf->npix_y, level);
560     surflevel->npix_z = mip_minify(surf->npix_z, level);
561     surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
562     surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
563     surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
564     if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
565         if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
566             surflevel->mode = RADEON_SURF_MODE_1D;
567             return;
568         }
569     }
570     surflevel->nblk_x  = ALIGN(surflevel->nblk_x, mtilew);
571     surflevel->nblk_y  = ALIGN(surflevel->nblk_y, mtileh);
572     surflevel->nblk_z  = ALIGN(surflevel->nblk_z, 1);
573
574     /* macro tile per row */
575     mtile_pr = surflevel->nblk_x / mtilew;
576     /* macro tile per slice */
577     mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
578
579     surflevel->offset = offset;
580     surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
581     surflevel->slice_size = mtile_ps * mtileb * slice_pt;
582
583     surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
584 }
585
586 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
587                               struct radeon_surface *surf,
588                               struct radeon_surface_level *level,
589                               unsigned bpe,
590                               uint64_t offset, unsigned start_level)
591 {
592     uint32_t xalign, yalign, zalign, tilew;
593     unsigned i;
594
595     /* compute alignment */
596     tilew = 8;
597     xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
598     xalign = MAX2(tilew, xalign);
599     yalign = tilew;
600     zalign = 1;
601     if (surf->flags & RADEON_SURF_SCANOUT) {
602         xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
603     }
604
605     if (!start_level) {
606         unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
607         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
608
609         if (offset) {
610             offset = ALIGN(offset, alignment);
611         }
612     }
613
614     /* build mipmap tree */
615     for (i = start_level; i <= surf->last_level; i++) {
616         level[i].mode = RADEON_SURF_MODE_1D;
617         surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
618         /* level0 and first mipmap need to have alignment */
619         offset = surf->bo_size;
620         if ((i == 0)) {
621             offset = ALIGN(offset, surf->bo_alignment);
622         }
623     }
624     return 0;
625 }
626
627 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
628                               struct radeon_surface *surf,
629                               struct radeon_surface_level *level,
630                               unsigned bpe, unsigned tile_split,
631                               uint64_t offset, unsigned start_level)
632 {
633     unsigned tilew, tileh, tileb;
634     unsigned mtilew, mtileh, mtileb;
635     unsigned slice_pt;
636     unsigned i;
637
638     /* compute tile values */
639     tilew = 8;
640     tileh = 8;
641     tileb = tilew * tileh * bpe * surf->nsamples;
642     /* slices per tile */
643     slice_pt = 1;
644     if (tileb > tile_split) {
645         slice_pt = tileb / tile_split;
646     }
647     tileb = tileb / slice_pt;
648
649     /* macro tile width & height */
650     mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
651     mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
652     /* macro tile bytes */
653     mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
654
655     if (!start_level) {
656         unsigned alignment = MAX2(256, mtileb);
657         surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
658
659         if (offset) {
660             offset = ALIGN(offset, alignment);
661         }
662     }
663
664     /* build mipmap tree */
665     for (i = start_level; i <= surf->last_level; i++) {
666         level[i].mode = RADEON_SURF_MODE_2D;
667         eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
668         if (level[i].mode == RADEON_SURF_MODE_1D) {
669             return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
670         }
671         /* level0 and first mipmap need to have alignment */
672         offset = surf->bo_size;
673         if ((i == 0)) {
674             offset = ALIGN(offset, surf->bo_alignment);
675         }
676     }
677     return 0;
678 }
679
680 static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
681                              struct radeon_surface *surf,
682                              unsigned mode)
683 {
684     unsigned tileb;
685
686     /* check surface dimension */
687     if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
688         return -EINVAL;
689     }
690
691     /* check mipmap last_level */
692     if (surf->last_level > 15) {
693         return -EINVAL;
694     }
695
696     /* force 1d on kernel that can't do 2d */
697     if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
698         if (surf->nsamples > 1) {
699             fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
700             return -EFAULT;
701         }
702         mode = RADEON_SURF_MODE_1D;
703         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
704         surf->flags |= RADEON_SURF_SET(mode, MODE);
705     }
706
707     /* check tile split */
708     if (mode == RADEON_SURF_MODE_2D) {
709         switch (surf->tile_split) {
710         case 64:
711         case 128:
712         case 256:
713         case 512:
714         case 1024:
715         case 2048:
716         case 4096:
717             break;
718         default:
719             return -EINVAL;
720         }
721         switch (surf->mtilea) {
722         case 1:
723         case 2:
724         case 4:
725         case 8:
726             break;
727         default:
728             return -EINVAL;
729         }
730         /* check aspect ratio */
731         if (surf_man->hw_info.num_banks < surf->mtilea) {
732             return -EINVAL;
733         }
734         /* check bank width */
735         switch (surf->bankw) {
736         case 1:
737         case 2:
738         case 4:
739         case 8:
740             break;
741         default:
742             return -EINVAL;
743         }
744         /* check bank height */
745         switch (surf->bankh) {
746         case 1:
747         case 2:
748         case 4:
749         case 8:
750             break;
751         default:
752             return -EINVAL;
753         }
754         tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
755         if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
756             return -EINVAL;
757         }
758     }
759
760     return 0;
761 }
762
763 static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
764                                        struct radeon_surface *surf)
765 {
766     unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
767     int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
768     /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
769     struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
770     struct radeon_surface_level *stencil_level =
771         (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
772
773     r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
774     if (r)
775         return r;
776
777     if (is_depth_stencil) {
778         r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
779                                surf->bo_size, 0);
780         surf->stencil_offset = stencil_level[0].offset;
781     }
782     return r;
783 }
784
785 static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
786                                        struct radeon_surface *surf)
787 {
788     unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
789     int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
790     /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
791     struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
792     struct radeon_surface_level *stencil_level =
793         (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
794
795     r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
796                            surf->tile_split, 0, 0);
797     if (r)
798         return r;
799
800     if (is_depth_stencil) {
801         r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
802                                surf->stencil_tile_split, surf->bo_size, 0);
803         surf->stencil_offset = stencil_level[0].offset;
804     }
805     return r;
806 }
807
808 static int eg_surface_init(struct radeon_surface_manager *surf_man,
809                            struct radeon_surface *surf)
810 {
811     unsigned mode;
812     int r;
813
814     /* MSAA surfaces support the 2D mode only. */
815     if (surf->nsamples > 1) {
816         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
817         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
818     }
819
820     /* tiling mode */
821     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
822
823     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
824         /* zbuffer only support 1D or 2D tiled surface */
825         switch (mode) {
826         case RADEON_SURF_MODE_1D:
827         case RADEON_SURF_MODE_2D:
828             break;
829         default:
830             mode = RADEON_SURF_MODE_1D;
831             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
832             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
833             break;
834         }
835     }
836
837     r = eg_surface_sanity(surf_man, surf, mode);
838     if (r) {
839         return r;
840     }
841
842     surf->stencil_offset = 0;
843     surf->bo_alignment = 0;
844
845     /* check tiling mode */
846     switch (mode) {
847     case RADEON_SURF_MODE_LINEAR:
848         r = r6_surface_init_linear(surf_man, surf, 0, 0);
849         break;
850     case RADEON_SURF_MODE_LINEAR_ALIGNED:
851         r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
852         break;
853     case RADEON_SURF_MODE_1D:
854         r = eg_surface_init_1d_miptrees(surf_man, surf);
855         break;
856     case RADEON_SURF_MODE_2D:
857         r = eg_surface_init_2d_miptrees(surf_man, surf);
858         break;
859     default:
860         return -EINVAL;
861     }
862     return r;
863 }
864
865 static unsigned log2_int(unsigned x)
866 {
867     unsigned l;
868
869     if (x < 2) {
870         return 0;
871     }
872     for (l = 2; ; l++) {
873         if ((unsigned)(1 << l) > x) {
874             return l - 1;
875         }
876     }
877     return 0;
878 }
879
880 /* compute best tile_split, bankw, bankh, mtilea
881  * depending on surface
882  */
883 static int eg_surface_best(struct radeon_surface_manager *surf_man,
884                            struct radeon_surface *surf)
885 {
886     unsigned mode, tileb, h_over_w;
887     int r;
888
889     /* tiling mode */
890     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
891
892     /* set some default value to avoid sanity check choking on them */
893     surf->tile_split = 1024;
894     surf->bankw = 1;
895     surf->bankh = 1;
896     surf->mtilea = surf_man->hw_info.num_banks;
897     tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
898     for (; surf->bankh <= 8; surf->bankh *= 2) {
899         if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
900             break;
901         }
902     }
903     if (surf->mtilea > 8) {
904         surf->mtilea = 8;
905     }
906
907     r = eg_surface_sanity(surf_man, surf, mode);
908     if (r) {
909         return r;
910     }
911
912     if (mode != RADEON_SURF_MODE_2D) {
913         /* nothing to do for non 2D tiled surface */
914         return 0;
915     }
916
917     /* Tweak TILE_SPLIT for performance here. */
918     if (surf->nsamples > 1) {
919         if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
920             switch (surf->nsamples) {
921             case 2:
922                 surf->tile_split = 128;
923                 break;
924             case 4:
925                 surf->tile_split = 128;
926                 break;
927             case 8:
928                 surf->tile_split = 256;
929                 break;
930             case 16: /* cayman only */
931                 surf->tile_split = 512;
932                 break;
933             default:
934                 fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
935                         surf->nsamples, __LINE__);
936                 return -EINVAL;
937             }
938             surf->stencil_tile_split = 64;
939         } else {
940             /* tile split must be >= 256 for colorbuffer surfaces */
941             surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
942             if (surf->tile_split > 4096)
943                 surf->tile_split = 4096;
944         }
945     } else {
946         /* set tile split to row size */
947         surf->tile_split = surf_man->hw_info.row_size;
948         surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
949     }
950
951     /* bankw or bankh greater than 1 increase alignment requirement, not
952      * sure if it's worth using smaller bankw & bankh to stick with 2D
953      * tiling on small surface rather than falling back to 1D tiling.
954      * Use recommanded value based on tile size for now.
955      *
956      * fmask buffer has different optimal value figure them out once we
957      * use it.
958      */
959     if (surf->flags & RADEON_SURF_SBUFFER) {
960         /* assume 1 bytes for stencil, we optimize for stencil as stencil
961          * and depth shares surface values
962          */
963         tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
964     } else {
965         tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
966     }
967
968     /* use bankw of 1 to minimize width alignment, might be interesting to
969      * increase it for large surface
970      */
971     surf->bankw = 1;
972     switch (tileb) {
973     case 64:
974         surf->bankh = 4;
975         break;
976     case 128:
977     case 256:
978         surf->bankh = 2;
979         break;
980     default:
981         surf->bankh = 1;
982         break;
983     }
984     /* double check the constraint */
985     for (; surf->bankh <= 8; surf->bankh *= 2) {
986         if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
987             break;
988         }
989     }
990
991     h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
992                 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
993     surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
994
995     return 0;
996 }
997
998
999 /* ===========================================================================
1000  * Southern Islands family
1001  */
1002
1003 static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
1004                                           unsigned level,
1005                                           uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
1006                                           unsigned offset)
1007 {
1008     surf->level[level].npix_x = mip_minify(surf->npix_x, level);
1009     surf->level[level].npix_y = mip_minify(surf->npix_y, level);
1010     surf->level[level].npix_z = mip_minify(surf->npix_z, level);
1011
1012     if (level == 0 && surf->last_level > 0) {
1013         surf->level[level].nblk_x = (next_power_of_two(surf->level[level].npix_x) + surf->blk_w - 1) / surf->blk_w;
1014         surf->level[level].nblk_y = (next_power_of_two(surf->level[level].npix_y) + surf->blk_h - 1) / surf->blk_h;
1015         surf->level[level].nblk_z = (next_power_of_two(surf->level[level].npix_z) + surf->blk_d - 1) / surf->blk_d;
1016     } else {
1017         surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
1018         surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
1019         surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
1020     }
1021
1022     /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1023      * these are just guesses for the rules behind those
1024      */
1025     if (level == 0 && surf->last_level == 0)
1026         /* Non-mipmap pitch padded to slice alignment */
1027         xalign = MAX2(xalign, slice_align / surf->bpe);
1028     else
1029         /* Small rows evenly distributed across slice */
1030         xalign = MAX2(xalign, slice_align / surf->bpe / surf->level[level].npix_y);
1031
1032     surf->level[level].nblk_x  = ALIGN(surf->level[level].nblk_x, xalign);
1033     surf->level[level].nblk_y  = ALIGN(surf->level[level].nblk_y, yalign);
1034     surf->level[level].nblk_z  = ALIGN(surf->level[level].nblk_z, zalign);
1035
1036     surf->level[level].offset = offset;
1037     surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * surf->nsamples;
1038     surf->level[level].slice_size = ALIGN(surf->level[level].pitch_bytes * surf->level[level].nblk_y, slice_align);
1039
1040     surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
1041 }
1042
1043 static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1044                                           struct radeon_surface *surf,
1045                                           uint64_t offset, unsigned start_level)
1046 {
1047     uint32_t xalign, yalign, zalign, slice_align;
1048     unsigned i;
1049
1050     /* compute alignment */
1051     if (!start_level) {
1052         surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1053     }
1054     xalign = MAX2(8, 64 / surf->bpe);
1055     yalign = 1;
1056     zalign = 1;
1057     slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1058
1059     /* build mipmap tree */
1060     for (i = start_level; i <= surf->last_level; i++) {
1061         surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1062         si_surf_minify_linear_aligned(surf, i, xalign, yalign, zalign, slice_align, offset);
1063         /* level0 and first mipmap need to have alignment */
1064         offset = surf->bo_size;
1065         if ((i == 0)) {
1066             offset = ALIGN(offset, surf->bo_alignment);
1067         }
1068     }
1069     return 0;
1070 }
1071
1072 static int si_surface_init(struct radeon_surface_manager *surf_man,
1073                            struct radeon_surface *surf)
1074 {
1075     unsigned mode;
1076     int r;
1077
1078     /* MSAA surfaces support the 2D mode only. */
1079     if (surf->nsamples > 1) {
1080         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1081         surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1082     }
1083
1084     /* tiling mode */
1085     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1086
1087     if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1088         /* zbuffer only support 1D or 2D tiled surface */
1089         switch (mode) {
1090         case RADEON_SURF_MODE_1D:
1091         case RADEON_SURF_MODE_2D:
1092             break;
1093         default:
1094             mode = RADEON_SURF_MODE_1D;
1095             surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1096             surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1097             break;
1098         }
1099     }
1100
1101     r = eg_surface_sanity(surf_man, surf, mode);
1102     if (r) {
1103         return r;
1104     }
1105
1106     surf->stencil_offset = 0;
1107     surf->bo_alignment = 0;
1108
1109     /* check tiling mode */
1110     switch (mode) {
1111     case RADEON_SURF_MODE_LINEAR:
1112         r = r6_surface_init_linear(surf_man, surf, 0, 0);
1113         break;
1114     case RADEON_SURF_MODE_LINEAR_ALIGNED:
1115         r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
1116         break;
1117     case RADEON_SURF_MODE_1D:
1118         r = eg_surface_init_1d_miptrees(surf_man, surf);
1119         break;
1120     case RADEON_SURF_MODE_2D:
1121         r = eg_surface_init_2d_miptrees(surf_man, surf);
1122         break;
1123     default:
1124         return -EINVAL;
1125     }
1126     return r;
1127 }
1128
1129 /* ===========================================================================
1130  * public API
1131  */
1132 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
1133 {
1134     struct radeon_surface_manager *surf_man;
1135
1136     surf_man = calloc(1, sizeof(struct radeon_surface_manager));
1137     if (surf_man == NULL) {
1138         return NULL;
1139     }
1140     surf_man->fd = fd;
1141     if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
1142         goto out_err;
1143     }
1144     if (radeon_get_family(surf_man)) {
1145         goto out_err;
1146     }
1147
1148     if (surf_man->family <= CHIP_RV740) {
1149         if (r6_init_hw_info(surf_man)) {
1150             goto out_err;
1151         }
1152         surf_man->surface_init = &r6_surface_init;
1153         surf_man->surface_best = &r6_surface_best;
1154     } else {
1155         if (eg_init_hw_info(surf_man)) {
1156             goto out_err;
1157         }
1158         if (surf_man->family <= CHIP_ARUBA) {
1159             surf_man->surface_init = &eg_surface_init;
1160         } else {
1161             surf_man->surface_init = &si_surface_init;
1162         }
1163         surf_man->surface_best = &eg_surface_best;
1164     }
1165
1166     return surf_man;
1167 out_err:
1168     free(surf_man);
1169     return NULL;
1170 }
1171
1172 void radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
1173 {
1174     free(surf_man);
1175 }
1176
1177 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
1178                                  struct radeon_surface *surf,
1179                                  unsigned type,
1180                                  unsigned mode)
1181 {
1182     if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
1183         return -EINVAL;
1184     }
1185
1186     /* all dimension must be at least 1 ! */
1187     if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
1188         return -EINVAL;
1189     }
1190     if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
1191         return -EINVAL;
1192     }
1193     if (!surf->array_size) {
1194         return -EINVAL;
1195     }
1196     /* array size must be a power of 2 */
1197     surf->array_size = next_power_of_two(surf->array_size);
1198
1199     switch (surf->nsamples) {
1200     case 1:
1201     case 2:
1202     case 4:
1203     case 8:
1204         break;
1205     default:
1206         return -EINVAL;
1207     }
1208     /* check type */
1209     switch (type) {
1210     case RADEON_SURF_TYPE_1D:
1211         if (surf->npix_y > 1) {
1212             return -EINVAL;
1213         }
1214     case RADEON_SURF_TYPE_2D:
1215         if (surf->npix_z > 1) {
1216             return -EINVAL;
1217         }
1218         break;
1219     case RADEON_SURF_TYPE_CUBEMAP:
1220         if (surf->npix_z > 1) {
1221             return -EINVAL;
1222         }
1223         /* deal with cubemap as they were texture array */
1224         if (surf_man->family >= CHIP_RV770) {
1225             surf->array_size = 8;
1226         } else {
1227             surf->array_size = 6;
1228         }
1229         break;
1230     case RADEON_SURF_TYPE_3D:
1231         break;
1232     case RADEON_SURF_TYPE_1D_ARRAY:
1233         if (surf->npix_y > 1) {
1234             return -EINVAL;
1235         }
1236     case RADEON_SURF_TYPE_2D_ARRAY:
1237         break;
1238     default:
1239         return -EINVAL;
1240     }
1241     return 0;
1242 }
1243
1244 int radeon_surface_init(struct radeon_surface_manager *surf_man,
1245                         struct radeon_surface *surf)
1246 {
1247     unsigned mode, type;
1248     int r;
1249
1250     type = RADEON_SURF_GET(surf->flags, TYPE);
1251     mode = RADEON_SURF_GET(surf->flags, MODE);
1252
1253     r = radeon_surface_sanity(surf_man, surf, type, mode);
1254     if (r) {
1255         return r;
1256     }
1257     return surf_man->surface_init(surf_man, surf);
1258 }
1259
1260 int radeon_surface_best(struct radeon_surface_manager *surf_man,
1261                         struct radeon_surface *surf)
1262 {
1263     unsigned mode, type;
1264     int r;
1265
1266     type = RADEON_SURF_GET(surf->flags, TYPE);
1267     mode = RADEON_SURF_GET(surf->flags, MODE);
1268
1269     r = radeon_surface_sanity(surf_man, surf, type, mode);
1270     if (r) {
1271         return r;
1272     }
1273     return surf_man->surface_best(surf_man, surf);
1274 }