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