2 * Copyright © 2011 Red Hat All Rights Reserved.
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:
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.
21 * The above copyright notice and this permission notice (including the
22 * next paragraph) shall be included in all copies or substantial portions
27 * Jérôme Glisse <jglisse@redhat.com>
34 #include <sys/ioctl.h>
37 #include "radeon_drm.h"
38 #include "radeon_surface.h"
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))
44 /* keep this private */
79 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
80 struct radeon_surface *surf);
81 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
82 struct radeon_surface *surf);
84 struct radeon_hw_info {
93 uint32_t tile_mode_array[32];
96 struct radeon_surface_manager {
99 struct radeon_hw_info hw_info;
101 hw_init_surface_t surface_init;
102 hw_best_surface_t surface_best;
106 static int radeon_get_value(int fd, unsigned req, uint32_t *value)
108 struct drm_radeon_info info = {};
113 info.value = (uintptr_t)value;
114 r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
115 sizeof(struct drm_radeon_info));
119 static int radeon_get_family(struct radeon_surface_manager *surf_man)
121 switch (surf_man->device_id) {
122 #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
123 #include "r600_pci_ids.h"
131 static unsigned next_power_of_two(unsigned x)
136 return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
139 static unsigned mip_minify(unsigned size, unsigned level)
143 val = MAX2(1, size >> level);
145 val = next_power_of_two(val);
149 static void surf_minify(struct radeon_surface *surf,
150 struct radeon_surface_level *surflevel,
151 unsigned bpe, unsigned level,
152 uint32_t xalign, uint32_t yalign, uint32_t zalign,
155 surflevel->npix_x = mip_minify(surf->npix_x, level);
156 surflevel->npix_y = mip_minify(surf->npix_y, level);
157 surflevel->npix_z = mip_minify(surf->npix_z, level);
158 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
159 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
160 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
161 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
162 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
163 surflevel->mode = RADEON_SURF_MODE_1D;
167 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
168 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
169 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
171 surflevel->offset = offset;
172 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
173 surflevel->slice_size = surflevel->pitch_bytes * surflevel->nblk_y;
175 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
178 /* ===========================================================================
181 static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
183 uint32_t tiling_config;
184 drmVersionPtr version;
187 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
193 surf_man->hw_info.allow_2d = 0;
194 version = drmGetVersion(surf_man->fd);
195 if (version && version->version_minor >= 14) {
196 surf_man->hw_info.allow_2d = 1;
198 drmFreeVersion(version);
200 switch ((tiling_config & 0xe) >> 1) {
202 surf_man->hw_info.num_pipes = 1;
205 surf_man->hw_info.num_pipes = 2;
208 surf_man->hw_info.num_pipes = 4;
211 surf_man->hw_info.num_pipes = 8;
214 surf_man->hw_info.num_pipes = 8;
215 surf_man->hw_info.allow_2d = 0;
219 switch ((tiling_config & 0x30) >> 4) {
221 surf_man->hw_info.num_banks = 4;
224 surf_man->hw_info.num_banks = 8;
227 surf_man->hw_info.num_banks = 8;
228 surf_man->hw_info.allow_2d = 0;
232 switch ((tiling_config & 0xc0) >> 6) {
234 surf_man->hw_info.group_bytes = 256;
237 surf_man->hw_info.group_bytes = 512;
240 surf_man->hw_info.group_bytes = 256;
241 surf_man->hw_info.allow_2d = 0;
247 static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
248 struct radeon_surface *surf,
249 uint64_t offset, unsigned start_level)
251 uint32_t xalign, yalign, zalign;
254 /* compute alignment */
256 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
258 /* the 32 alignment is for scanout, cb or db but to allow texture to be
259 * easily bound as such we force this alignment to all surface
261 xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
264 if (surf->flags & RADEON_SURF_SCANOUT) {
265 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
268 /* build mipmap tree */
269 for (i = start_level; i <= surf->last_level; i++) {
270 surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
271 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
272 /* level0 and first mipmap need to have alignment */
273 offset = surf->bo_size;
275 offset = ALIGN(offset, surf->bo_alignment);
281 static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
282 struct radeon_surface *surf,
283 uint64_t offset, unsigned start_level)
285 uint32_t xalign, yalign, zalign;
288 /* compute alignment */
290 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
292 xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
296 /* build mipmap tree */
297 for (i = start_level; i <= surf->last_level; i++) {
298 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
299 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
300 /* level0 and first mipmap need to have alignment */
301 offset = surf->bo_size;
303 offset = ALIGN(offset, surf->bo_alignment);
309 static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
310 struct radeon_surface *surf,
311 uint64_t offset, unsigned start_level)
313 uint32_t xalign, yalign, zalign, tilew;
316 /* compute alignment */
318 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
319 xalign = MAX2(tilew, xalign);
322 if (surf->flags & RADEON_SURF_SCANOUT) {
323 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
326 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
329 /* build mipmap tree */
330 for (i = start_level; i <= surf->last_level; i++) {
331 surf->level[i].mode = RADEON_SURF_MODE_1D;
332 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
333 /* level0 and first mipmap need to have alignment */
334 offset = surf->bo_size;
336 offset = ALIGN(offset, surf->bo_alignment);
342 static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
343 struct radeon_surface *surf,
344 uint64_t offset, unsigned start_level)
346 uint32_t xalign, yalign, zalign, tilew;
349 /* compute alignment */
352 xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
353 (tilew * surf->bpe * surf->nsamples);
354 xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
355 yalign = tilew * surf_man->hw_info.num_pipes;
356 if (surf->flags & RADEON_SURF_SCANOUT) {
357 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
361 MAX2(surf_man->hw_info.num_pipes *
362 surf_man->hw_info.num_banks *
363 surf->nsamples * surf->bpe * 64,
364 xalign * yalign * surf->nsamples * surf->bpe);
367 /* build mipmap tree */
368 for (i = start_level; i <= surf->last_level; i++) {
369 surf->level[i].mode = RADEON_SURF_MODE_2D;
370 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
371 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
372 return r6_surface_init_1d(surf_man, surf, offset, i);
374 /* level0 and first mipmap need to have alignment */
375 offset = surf->bo_size;
377 offset = ALIGN(offset, surf->bo_alignment);
383 static int r6_surface_init(struct radeon_surface_manager *surf_man,
384 struct radeon_surface *surf)
389 /* MSAA surfaces support the 2D mode only. */
390 if (surf->nsamples > 1) {
391 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
392 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
396 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
398 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
399 /* zbuffer only support 1D or 2D tiled surface */
401 case RADEON_SURF_MODE_1D:
402 case RADEON_SURF_MODE_2D:
405 mode = RADEON_SURF_MODE_1D;
406 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
407 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
412 /* force 1d on kernel that can't do 2d */
413 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
414 if (surf->nsamples > 1) {
415 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
418 mode = RADEON_SURF_MODE_1D;
419 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
420 surf->flags |= RADEON_SURF_SET(mode, MODE);
423 /* check surface dimension */
424 if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
428 /* check mipmap last_level */
429 if (surf->last_level > 14) {
433 /* check tiling mode */
435 case RADEON_SURF_MODE_LINEAR:
436 r = r6_surface_init_linear(surf_man, surf, 0, 0);
438 case RADEON_SURF_MODE_LINEAR_ALIGNED:
439 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
441 case RADEON_SURF_MODE_1D:
442 r = r6_surface_init_1d(surf_man, surf, 0, 0);
444 case RADEON_SURF_MODE_2D:
445 r = r6_surface_init_2d(surf_man, surf, 0, 0);
453 static int r6_surface_best(struct radeon_surface_manager *surf_man,
454 struct radeon_surface *surf)
456 /* no value to optimize for r6xx/r7xx */
461 /* ===========================================================================
464 static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
466 uint32_t tiling_config;
467 drmVersionPtr version;
470 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
476 surf_man->hw_info.allow_2d = 0;
477 version = drmGetVersion(surf_man->fd);
478 if (version && version->version_minor >= 16) {
479 surf_man->hw_info.allow_2d = 1;
481 drmFreeVersion(version);
483 switch (tiling_config & 0xf) {
485 surf_man->hw_info.num_pipes = 1;
488 surf_man->hw_info.num_pipes = 2;
491 surf_man->hw_info.num_pipes = 4;
494 surf_man->hw_info.num_pipes = 8;
497 surf_man->hw_info.num_pipes = 8;
498 surf_man->hw_info.allow_2d = 0;
502 switch ((tiling_config & 0xf0) >> 4) {
504 surf_man->hw_info.num_banks = 4;
507 surf_man->hw_info.num_banks = 8;
510 surf_man->hw_info.num_banks = 16;
513 surf_man->hw_info.num_banks = 8;
514 surf_man->hw_info.allow_2d = 0;
518 switch ((tiling_config & 0xf00) >> 8) {
520 surf_man->hw_info.group_bytes = 256;
523 surf_man->hw_info.group_bytes = 512;
526 surf_man->hw_info.group_bytes = 256;
527 surf_man->hw_info.allow_2d = 0;
531 switch ((tiling_config & 0xf000) >> 12) {
533 surf_man->hw_info.row_size = 1024;
536 surf_man->hw_info.row_size = 2048;
539 surf_man->hw_info.row_size = 4096;
542 surf_man->hw_info.row_size = 4096;
543 surf_man->hw_info.allow_2d = 0;
549 static void eg_surf_minify(struct radeon_surface *surf,
550 struct radeon_surface_level *surflevel,
559 unsigned mtile_pr, mtile_ps;
561 surflevel->npix_x = mip_minify(surf->npix_x, level);
562 surflevel->npix_y = mip_minify(surf->npix_y, level);
563 surflevel->npix_z = mip_minify(surf->npix_z, level);
564 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
565 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
566 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
567 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
568 if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
569 surflevel->mode = RADEON_SURF_MODE_1D;
573 surflevel->nblk_x = ALIGN(surflevel->nblk_x, mtilew);
574 surflevel->nblk_y = ALIGN(surflevel->nblk_y, mtileh);
575 surflevel->nblk_z = ALIGN(surflevel->nblk_z, 1);
577 /* macro tile per row */
578 mtile_pr = surflevel->nblk_x / mtilew;
579 /* macro tile per slice */
580 mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
582 surflevel->offset = offset;
583 surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
584 surflevel->slice_size = mtile_ps * mtileb * slice_pt;
586 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
589 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
590 struct radeon_surface *surf,
591 struct radeon_surface_level *level,
593 uint64_t offset, unsigned start_level)
595 uint32_t xalign, yalign, zalign, tilew;
598 /* compute alignment */
600 xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
601 xalign = MAX2(tilew, xalign);
604 if (surf->flags & RADEON_SURF_SCANOUT) {
605 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
609 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
610 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
613 offset = ALIGN(offset, alignment);
617 /* build mipmap tree */
618 for (i = start_level; i <= surf->last_level; i++) {
619 level[i].mode = RADEON_SURF_MODE_1D;
620 surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
621 /* level0 and first mipmap need to have alignment */
622 offset = surf->bo_size;
624 offset = ALIGN(offset, surf->bo_alignment);
630 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
631 struct radeon_surface *surf,
632 struct radeon_surface_level *level,
633 unsigned bpe, unsigned tile_split,
634 uint64_t offset, unsigned start_level)
636 unsigned tilew, tileh, tileb;
637 unsigned mtilew, mtileh, mtileb;
641 /* compute tile values */
644 tileb = tilew * tileh * bpe * surf->nsamples;
645 /* slices per tile */
647 if (tileb > tile_split) {
648 slice_pt = tileb / tile_split;
650 tileb = tileb / slice_pt;
652 /* macro tile width & height */
653 mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
654 mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
655 /* macro tile bytes */
656 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
659 unsigned alignment = MAX2(256, mtileb);
660 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
663 offset = ALIGN(offset, alignment);
667 /* build mipmap tree */
668 for (i = start_level; i <= surf->last_level; i++) {
669 level[i].mode = RADEON_SURF_MODE_2D;
670 eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
671 if (level[i].mode == RADEON_SURF_MODE_1D) {
672 return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
674 /* level0 and first mipmap need to have alignment */
675 offset = surf->bo_size;
677 offset = ALIGN(offset, surf->bo_alignment);
683 static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
684 struct radeon_surface *surf,
689 /* check surface dimension */
690 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
694 /* check mipmap last_level */
695 if (surf->last_level > 15) {
699 /* force 1d on kernel that can't do 2d */
700 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
701 if (surf->nsamples > 1) {
702 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
705 mode = RADEON_SURF_MODE_1D;
706 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
707 surf->flags |= RADEON_SURF_SET(mode, MODE);
710 /* check tile split */
711 if (mode == RADEON_SURF_MODE_2D) {
712 switch (surf->tile_split) {
724 switch (surf->mtilea) {
733 /* check aspect ratio */
734 if (surf_man->hw_info.num_banks < surf->mtilea) {
737 /* check bank width */
738 switch (surf->bankw) {
747 /* check bank height */
748 switch (surf->bankh) {
757 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
758 if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
766 static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
767 struct radeon_surface *surf)
769 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
770 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
771 /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
772 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
773 struct radeon_surface_level *stencil_level =
774 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
776 r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
780 if (is_depth_stencil) {
781 r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
783 surf->stencil_offset = stencil_level[0].offset;
788 static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
789 struct radeon_surface *surf)
791 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
792 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
793 /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
794 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
795 struct radeon_surface_level *stencil_level =
796 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
798 r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
799 surf->tile_split, 0, 0);
803 if (is_depth_stencil) {
804 r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
805 surf->stencil_tile_split, surf->bo_size, 0);
806 surf->stencil_offset = stencil_level[0].offset;
811 static int eg_surface_init(struct radeon_surface_manager *surf_man,
812 struct radeon_surface *surf)
817 /* MSAA surfaces support the 2D mode only. */
818 if (surf->nsamples > 1) {
819 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
820 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
824 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
826 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
827 /* zbuffer only support 1D or 2D tiled surface */
829 case RADEON_SURF_MODE_1D:
830 case RADEON_SURF_MODE_2D:
833 mode = RADEON_SURF_MODE_1D;
834 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
835 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
840 r = eg_surface_sanity(surf_man, surf, mode);
845 surf->stencil_offset = 0;
846 surf->bo_alignment = 0;
848 /* check tiling mode */
850 case RADEON_SURF_MODE_LINEAR:
851 r = r6_surface_init_linear(surf_man, surf, 0, 0);
853 case RADEON_SURF_MODE_LINEAR_ALIGNED:
854 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
856 case RADEON_SURF_MODE_1D:
857 r = eg_surface_init_1d_miptrees(surf_man, surf);
859 case RADEON_SURF_MODE_2D:
860 r = eg_surface_init_2d_miptrees(surf_man, surf);
868 static unsigned log2_int(unsigned x)
876 if ((unsigned)(1 << l) > x) {
883 /* compute best tile_split, bankw, bankh, mtilea
884 * depending on surface
886 static int eg_surface_best(struct radeon_surface_manager *surf_man,
887 struct radeon_surface *surf)
889 unsigned mode, tileb, h_over_w;
893 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
895 /* set some default value to avoid sanity check choking on them */
896 surf->tile_split = 1024;
899 surf->mtilea = surf_man->hw_info.num_banks;
900 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
901 for (; surf->bankh <= 8; surf->bankh *= 2) {
902 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
906 if (surf->mtilea > 8) {
910 r = eg_surface_sanity(surf_man, surf, mode);
915 if (mode != RADEON_SURF_MODE_2D) {
916 /* nothing to do for non 2D tiled surface */
920 /* Tweak TILE_SPLIT for performance here. */
921 if (surf->nsamples > 1) {
922 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
923 switch (surf->nsamples) {
925 surf->tile_split = 128;
928 surf->tile_split = 128;
931 surf->tile_split = 256;
933 case 16: /* cayman only */
934 surf->tile_split = 512;
937 fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
938 surf->nsamples, __LINE__);
941 surf->stencil_tile_split = 64;
943 /* tile split must be >= 256 for colorbuffer surfaces */
944 surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
945 if (surf->tile_split > 4096)
946 surf->tile_split = 4096;
949 /* set tile split to row size */
950 surf->tile_split = surf_man->hw_info.row_size;
951 surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
954 /* bankw or bankh greater than 1 increase alignment requirement, not
955 * sure if it's worth using smaller bankw & bankh to stick with 2D
956 * tiling on small surface rather than falling back to 1D tiling.
957 * Use recommanded value based on tile size for now.
959 * fmask buffer has different optimal value figure them out once we
962 if (surf->flags & RADEON_SURF_SBUFFER) {
963 /* assume 1 bytes for stencil, we optimize for stencil as stencil
964 * and depth shares surface values
966 tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
968 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
971 /* use bankw of 1 to minimize width alignment, might be interesting to
972 * increase it for large surface
987 /* double check the constraint */
988 for (; surf->bankh <= 8; surf->bankh *= 2) {
989 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
994 h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
995 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
996 surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
1002 /* ===========================================================================
1003 * Southern Islands family
1005 #define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
1006 #define SI__PIPE_CONFIG__ADDR_SURF_P2 0
1007 #define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
1008 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
1009 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
1010 #define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
1011 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
1012 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
1013 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
1014 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
1015 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
1016 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
1017 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
1018 #define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
1019 #define SI__TILE_SPLIT__64B 0
1020 #define SI__TILE_SPLIT__128B 1
1021 #define SI__TILE_SPLIT__256B 2
1022 #define SI__TILE_SPLIT__512B 3
1023 #define SI__TILE_SPLIT__1024B 4
1024 #define SI__TILE_SPLIT__2048B 5
1025 #define SI__TILE_SPLIT__4096B 6
1026 #define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3)
1027 #define SI__BANK_WIDTH__1 0
1028 #define SI__BANK_WIDTH__2 1
1029 #define SI__BANK_WIDTH__4 2
1030 #define SI__BANK_WIDTH__8 3
1031 #define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3)
1032 #define SI__BANK_HEIGHT__1 0
1033 #define SI__BANK_HEIGHT__2 1
1034 #define SI__BANK_HEIGHT__4 2
1035 #define SI__BANK_HEIGHT__8 3
1036 #define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3)
1037 #define SI__MACRO_TILE_ASPECT__1 0
1038 #define SI__MACRO_TILE_ASPECT__2 1
1039 #define SI__MACRO_TILE_ASPECT__4 2
1040 #define SI__MACRO_TILE_ASPECT__8 3
1041 #define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3)
1042 #define SI__NUM_BANKS__2_BANK 0
1043 #define SI__NUM_BANKS__4_BANK 1
1044 #define SI__NUM_BANKS__8_BANK 2
1045 #define SI__NUM_BANKS__16_BANK 3
1048 static void si_gb_tile_mode(uint32_t gb_tile_mode,
1049 unsigned *num_pipes,
1050 unsigned *num_banks,
1051 uint32_t *macro_tile_aspect,
1054 uint32_t *tile_split)
1057 switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1058 case SI__PIPE_CONFIG__ADDR_SURF_P2:
1062 case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1063 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1064 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1065 case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1068 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1069 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1070 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1071 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1072 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1073 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1074 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1080 switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
1082 case SI__NUM_BANKS__2_BANK:
1085 case SI__NUM_BANKS__4_BANK:
1088 case SI__NUM_BANKS__8_BANK:
1091 case SI__NUM_BANKS__16_BANK:
1096 if (macro_tile_aspect) {
1097 switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
1099 case SI__MACRO_TILE_ASPECT__1:
1100 *macro_tile_aspect = 1;
1102 case SI__MACRO_TILE_ASPECT__2:
1103 *macro_tile_aspect = 2;
1105 case SI__MACRO_TILE_ASPECT__4:
1106 *macro_tile_aspect = 4;
1108 case SI__MACRO_TILE_ASPECT__8:
1109 *macro_tile_aspect = 8;
1114 switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
1116 case SI__BANK_WIDTH__1:
1119 case SI__BANK_WIDTH__2:
1122 case SI__BANK_WIDTH__4:
1125 case SI__BANK_WIDTH__8:
1131 switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
1133 case SI__BANK_HEIGHT__1:
1136 case SI__BANK_HEIGHT__2:
1139 case SI__BANK_HEIGHT__4:
1142 case SI__BANK_HEIGHT__8:
1148 switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1150 case SI__TILE_SPLIT__64B:
1153 case SI__TILE_SPLIT__128B:
1156 case SI__TILE_SPLIT__256B:
1159 case SI__TILE_SPLIT__512B:
1162 case SI__TILE_SPLIT__1024B:
1165 case SI__TILE_SPLIT__2048B:
1168 case SI__TILE_SPLIT__4096B:
1175 static int si_init_hw_info(struct radeon_surface_manager *surf_man)
1177 uint32_t tiling_config;
1178 drmVersionPtr version;
1181 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
1187 surf_man->hw_info.allow_2d = 0;
1188 version = drmGetVersion(surf_man->fd);
1189 if (version && version->version_minor >= 33) {
1190 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
1191 surf_man->hw_info.allow_2d = 1;
1194 drmFreeVersion(version);
1196 switch (tiling_config & 0xf) {
1198 surf_man->hw_info.num_pipes = 1;
1201 surf_man->hw_info.num_pipes = 2;
1204 surf_man->hw_info.num_pipes = 4;
1207 surf_man->hw_info.num_pipes = 8;
1210 surf_man->hw_info.num_pipes = 8;
1211 surf_man->hw_info.allow_2d = 0;
1215 switch ((tiling_config & 0xf0) >> 4) {
1217 surf_man->hw_info.num_banks = 4;
1220 surf_man->hw_info.num_banks = 8;
1223 surf_man->hw_info.num_banks = 16;
1226 surf_man->hw_info.num_banks = 8;
1227 surf_man->hw_info.allow_2d = 0;
1231 switch ((tiling_config & 0xf00) >> 8) {
1233 surf_man->hw_info.group_bytes = 256;
1236 surf_man->hw_info.group_bytes = 512;
1239 surf_man->hw_info.group_bytes = 256;
1240 surf_man->hw_info.allow_2d = 0;
1244 switch ((tiling_config & 0xf000) >> 12) {
1246 surf_man->hw_info.row_size = 1024;
1249 surf_man->hw_info.row_size = 2048;
1252 surf_man->hw_info.row_size = 4096;
1255 surf_man->hw_info.row_size = 4096;
1256 surf_man->hw_info.allow_2d = 0;
1262 static int si_surface_sanity(struct radeon_surface_manager *surf_man,
1263 struct radeon_surface *surf,
1264 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
1266 uint32_t gb_tile_mode;
1268 /* check surface dimension */
1269 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
1273 /* check mipmap last_level */
1274 if (surf->last_level > 15) {
1278 /* force 1d on kernel that can't do 2d */
1279 if (mode > RADEON_SURF_MODE_1D &&
1280 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
1281 if (surf->nsamples > 1) {
1282 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
1285 mode = RADEON_SURF_MODE_1D;
1286 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1287 surf->flags |= RADEON_SURF_SET(mode, MODE);
1290 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
1294 if (!surf->tile_split) {
1299 surf->tile_split = 64;
1300 surf->stencil_tile_split = 64;
1304 case RADEON_SURF_MODE_2D:
1305 if (surf->flags & RADEON_SURF_SBUFFER) {
1306 switch (surf->nsamples) {
1308 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1311 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1314 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1317 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1322 /* retrieve tiling mode value */
1323 gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
1324 si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
1326 if (surf->flags & RADEON_SURF_ZBUFFER) {
1327 switch (surf->nsamples) {
1329 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1332 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1335 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1338 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1343 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1344 switch (surf->bpe) {
1346 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
1349 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
1355 switch (surf->bpe) {
1357 *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
1360 *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
1363 *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
1367 *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
1373 /* retrieve tiling mode value */
1374 gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
1375 si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
1377 case RADEON_SURF_MODE_1D:
1378 if (surf->flags & RADEON_SURF_SBUFFER) {
1379 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1381 if (surf->flags & RADEON_SURF_ZBUFFER) {
1382 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1383 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1384 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1386 *tile_mode = SI_TILE_MODE_COLOR_1D;
1389 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1391 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
1397 static void si_surf_minify(struct radeon_surface *surf,
1398 struct radeon_surface_level *surflevel,
1399 unsigned bpe, unsigned level,
1400 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1401 uint32_t slice_align, unsigned offset)
1403 surflevel->npix_x = mip_minify(surf->npix_x, level);
1404 surflevel->npix_y = mip_minify(surf->npix_y, level);
1405 surflevel->npix_z = mip_minify(surf->npix_z, level);
1407 if (level == 0 && surf->last_level > 0) {
1408 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1409 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1410 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1412 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1413 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1414 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1417 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1419 /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1420 * these are just guesses for the rules behind those
1422 if (level == 0 && surf->last_level == 0)
1423 /* Non-mipmap pitch padded to slice alignment */
1424 xalign = MAX2(xalign, slice_align / surf->bpe);
1426 /* Small rows evenly distributed across slice */
1427 xalign = MAX2(xalign, slice_align / surf->bpe / surflevel->nblk_y);
1429 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1430 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1432 surflevel->offset = offset;
1433 surflevel->pitch_bytes = surflevel->nblk_x * surf->bpe * surf->nsamples;
1434 surflevel->slice_size = ALIGN(surflevel->pitch_bytes * surflevel->nblk_y, slice_align);
1436 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1439 static void si_surf_minify_2d(struct radeon_surface *surf,
1440 struct radeon_surface_level *surflevel,
1441 unsigned bpe, unsigned level, unsigned slice_pt,
1442 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1443 unsigned mtileb, unsigned offset)
1445 unsigned mtile_pr, mtile_ps;
1447 surflevel->npix_x = mip_minify(surf->npix_x, level);
1448 surflevel->npix_y = mip_minify(surf->npix_y, level);
1449 surflevel->npix_z = mip_minify(surf->npix_z, level);
1451 if (level == 0 && surf->last_level > 0) {
1452 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1453 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1454 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1456 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1457 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1458 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1461 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
1462 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
1463 surflevel->mode = RADEON_SURF_MODE_1D;
1467 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1468 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1469 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1471 /* macro tile per row */
1472 mtile_pr = surflevel->nblk_x / xalign;
1473 /* macro tile per slice */
1474 mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
1475 surflevel->offset = offset;
1476 surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
1477 surflevel->slice_size = mtile_ps * mtileb * slice_pt;
1479 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1482 static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1483 struct radeon_surface *surf,
1485 uint64_t offset, unsigned start_level)
1487 uint32_t xalign, yalign, zalign, slice_align;
1490 /* compute alignment */
1492 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1494 xalign = MAX2(8, 64 / surf->bpe);
1497 slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1499 /* build mipmap tree */
1500 for (i = start_level; i <= surf->last_level; i++) {
1501 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1502 si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
1503 /* level0 and first mipmap need to have alignment */
1504 offset = surf->bo_size;
1506 offset = ALIGN(offset, surf->bo_alignment);
1508 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1509 surf->tiling_index[i] = tile_mode;
1515 static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1516 struct radeon_surface *surf,
1517 struct radeon_surface_level *level,
1518 unsigned bpe, unsigned tile_mode,
1519 uint64_t offset, unsigned start_level)
1521 uint32_t xalign, yalign, zalign, slice_align;
1524 /* compute alignment */
1528 slice_align = surf_man->hw_info.group_bytes;
1529 if (surf->flags & RADEON_SURF_SCANOUT) {
1530 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1534 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1537 offset = ALIGN(offset, surf->bo_alignment);
1541 /* build mipmap tree */
1542 for (i = start_level; i <= surf->last_level; i++) {
1543 level[i].mode = RADEON_SURF_MODE_1D;
1544 si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1545 /* level0 and first mipmap need to have alignment */
1546 offset = surf->bo_size;
1548 offset = ALIGN(offset, surf->bo_alignment);
1550 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1551 if (surf->level == level) {
1552 surf->tiling_index[i] = tile_mode;
1553 /* it's ok because stencil is done after */
1554 surf->stencil_tiling_index[i] = tile_mode;
1556 surf->stencil_tiling_index[i] = tile_mode;
1563 static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1564 struct radeon_surface *surf,
1565 unsigned tile_mode, unsigned stencil_tile_mode)
1569 r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
1574 if (surf->flags & RADEON_SURF_SBUFFER) {
1575 r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
1576 surf->stencil_offset = surf->stencil_level[0].offset;
1581 static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
1582 struct radeon_surface *surf,
1583 struct radeon_surface_level *level,
1584 unsigned bpe, unsigned tile_mode,
1585 unsigned num_pipes, unsigned num_banks,
1586 unsigned tile_split,
1588 unsigned start_level)
1590 unsigned tilew, tileh, tileb;
1591 unsigned mtilew, mtileh, mtileb;
1595 /* compute tile values */
1598 tileb = tilew * tileh * bpe * surf->nsamples;
1599 /* slices per tile */
1601 if (tileb > tile_split) {
1602 slice_pt = tileb / tile_split;
1604 tileb = tileb / slice_pt;
1606 /* macro tile width & height */
1607 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
1608 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
1610 /* macro tile bytes */
1611 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
1614 unsigned alignment = MAX2(256, mtileb);
1615 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1618 offset = ALIGN(offset, alignment);
1622 /* build mipmap tree */
1623 for (i = start_level; i <= surf->last_level; i++) {
1624 level[i].mode = RADEON_SURF_MODE_2D;
1625 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, offset);
1626 if (level[i].mode == RADEON_SURF_MODE_1D) {
1627 switch (tile_mode) {
1628 case SI_TILE_MODE_COLOR_2D_8BPP:
1629 case SI_TILE_MODE_COLOR_2D_16BPP:
1630 case SI_TILE_MODE_COLOR_2D_32BPP:
1631 case SI_TILE_MODE_COLOR_2D_64BPP:
1632 tile_mode = SI_TILE_MODE_COLOR_1D;
1634 case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
1635 case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
1636 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1638 case SI_TILE_MODE_DEPTH_STENCIL_2D:
1639 tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1644 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
1646 /* level0 and first mipmap need to have alignment */
1647 offset = surf->bo_size;
1649 offset = ALIGN(offset, surf->bo_alignment);
1651 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1652 if (surf->level == level) {
1653 surf->tiling_index[i] = tile_mode;
1654 /* it's ok because stencil is done after */
1655 surf->stencil_tiling_index[i] = tile_mode;
1657 surf->stencil_tiling_index[i] = tile_mode;
1664 static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
1665 struct radeon_surface *surf,
1666 unsigned tile_mode, unsigned stencil_tile_mode)
1668 unsigned num_pipes, num_banks;
1669 uint32_t gb_tile_mode;
1672 /* retrieve tiling mode value */
1673 gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1674 si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
1676 r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
1681 if (surf->flags & RADEON_SURF_SBUFFER) {
1682 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);
1683 surf->stencil_offset = surf->stencil_level[0].offset;
1688 static int si_surface_init(struct radeon_surface_manager *surf_man,
1689 struct radeon_surface *surf)
1691 unsigned mode, tile_mode, stencil_tile_mode;
1694 /* MSAA surfaces support the 2D mode only. */
1695 if (surf->nsamples > 1) {
1696 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1697 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1701 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1703 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1704 /* zbuffer only support 1D or 2D tiled surface */
1706 case RADEON_SURF_MODE_1D:
1707 case RADEON_SURF_MODE_2D:
1710 mode = RADEON_SURF_MODE_1D;
1711 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1712 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1717 r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1722 surf->stencil_offset = 0;
1723 surf->bo_alignment = 0;
1725 /* check tiling mode */
1727 case RADEON_SURF_MODE_LINEAR:
1728 r = r6_surface_init_linear(surf_man, surf, 0, 0);
1730 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1731 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
1733 case RADEON_SURF_MODE_1D:
1734 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1736 case RADEON_SURF_MODE_2D:
1737 r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1746 * depending on surface
1748 static int si_surface_best(struct radeon_surface_manager *surf_man,
1749 struct radeon_surface *surf)
1751 unsigned mode, tile_mode, stencil_tile_mode;
1754 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1756 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
1757 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
1758 /* depth/stencil force 1d tiling for old mesa */
1759 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1760 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1763 return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1767 /* ===========================================================================
1770 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
1772 struct radeon_surface_manager *surf_man;
1774 surf_man = calloc(1, sizeof(struct radeon_surface_manager));
1775 if (surf_man == NULL) {
1779 if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
1782 if (radeon_get_family(surf_man)) {
1786 if (surf_man->family <= CHIP_RV740) {
1787 if (r6_init_hw_info(surf_man)) {
1790 surf_man->surface_init = &r6_surface_init;
1791 surf_man->surface_best = &r6_surface_best;
1792 } else if (surf_man->family <= CHIP_ARUBA) {
1793 if (eg_init_hw_info(surf_man)) {
1796 surf_man->surface_init = &eg_surface_init;
1797 surf_man->surface_best = &eg_surface_best;
1799 if (si_init_hw_info(surf_man)) {
1802 surf_man->surface_init = &si_surface_init;
1803 surf_man->surface_best = &si_surface_best;
1812 void radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
1817 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
1818 struct radeon_surface *surf,
1822 if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
1826 /* all dimension must be at least 1 ! */
1827 if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
1830 if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
1833 if (!surf->array_size) {
1836 /* array size must be a power of 2 */
1837 surf->array_size = next_power_of_two(surf->array_size);
1839 switch (surf->nsamples) {
1850 case RADEON_SURF_TYPE_1D:
1851 if (surf->npix_y > 1) {
1854 case RADEON_SURF_TYPE_2D:
1855 if (surf->npix_z > 1) {
1859 case RADEON_SURF_TYPE_CUBEMAP:
1860 if (surf->npix_z > 1) {
1863 /* deal with cubemap as they were texture array */
1864 if (surf_man->family >= CHIP_RV770) {
1865 surf->array_size = 8;
1867 surf->array_size = 6;
1870 case RADEON_SURF_TYPE_3D:
1872 case RADEON_SURF_TYPE_1D_ARRAY:
1873 if (surf->npix_y > 1) {
1876 case RADEON_SURF_TYPE_2D_ARRAY:
1884 int radeon_surface_init(struct radeon_surface_manager *surf_man,
1885 struct radeon_surface *surf)
1887 unsigned mode, type;
1890 type = RADEON_SURF_GET(surf->flags, TYPE);
1891 mode = RADEON_SURF_GET(surf->flags, MODE);
1893 r = radeon_surface_sanity(surf_man, surf, type, mode);
1897 return surf_man->surface_init(surf_man, surf);
1900 int radeon_surface_best(struct radeon_surface_manager *surf_man,
1901 struct radeon_surface *surf)
1903 unsigned mode, type;
1906 type = RADEON_SURF_GET(surf->flags, TYPE);
1907 mode = RADEON_SURF_GET(surf->flags, MODE);
1909 r = radeon_surface_sanity(surf_man, surf, type, mode);
1913 return surf_man->surface_best(surf_man, surf);