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 */
80 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
81 struct radeon_surface *surf);
82 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
83 struct radeon_surface *surf);
85 struct radeon_hw_info {
94 uint32_t tile_mode_array[32];
97 struct radeon_surface_manager {
100 struct radeon_hw_info hw_info;
102 hw_init_surface_t surface_init;
103 hw_best_surface_t surface_best;
107 static int radeon_get_value(int fd, unsigned req, uint32_t *value)
109 struct drm_radeon_info info = {};
114 info.value = (uintptr_t)value;
115 r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
116 sizeof(struct drm_radeon_info));
120 static int radeon_get_family(struct radeon_surface_manager *surf_man)
122 switch (surf_man->device_id) {
123 #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
124 #include "r600_pci_ids.h"
132 static unsigned next_power_of_two(unsigned x)
137 return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
140 static unsigned mip_minify(unsigned size, unsigned level)
144 val = MAX2(1, size >> level);
146 val = next_power_of_two(val);
150 static void surf_minify(struct radeon_surface *surf,
151 struct radeon_surface_level *surflevel,
152 unsigned bpe, unsigned level,
153 uint32_t xalign, uint32_t yalign, uint32_t zalign,
156 surflevel->npix_x = mip_minify(surf->npix_x, level);
157 surflevel->npix_y = mip_minify(surf->npix_y, level);
158 surflevel->npix_z = mip_minify(surf->npix_z, level);
159 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
160 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
161 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
162 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
163 !(surf->flags & RADEON_SURF_FMASK)) {
164 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
165 surflevel->mode = RADEON_SURF_MODE_1D;
169 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
170 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
171 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
173 surflevel->offset = offset;
174 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
175 surflevel->slice_size = surflevel->pitch_bytes * surflevel->nblk_y;
177 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
180 /* ===========================================================================
183 static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
185 uint32_t tiling_config;
186 drmVersionPtr version;
189 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
195 surf_man->hw_info.allow_2d = 0;
196 version = drmGetVersion(surf_man->fd);
197 if (version && version->version_minor >= 14) {
198 surf_man->hw_info.allow_2d = 1;
200 drmFreeVersion(version);
202 switch ((tiling_config & 0xe) >> 1) {
204 surf_man->hw_info.num_pipes = 1;
207 surf_man->hw_info.num_pipes = 2;
210 surf_man->hw_info.num_pipes = 4;
213 surf_man->hw_info.num_pipes = 8;
216 surf_man->hw_info.num_pipes = 8;
217 surf_man->hw_info.allow_2d = 0;
221 switch ((tiling_config & 0x30) >> 4) {
223 surf_man->hw_info.num_banks = 4;
226 surf_man->hw_info.num_banks = 8;
229 surf_man->hw_info.num_banks = 8;
230 surf_man->hw_info.allow_2d = 0;
234 switch ((tiling_config & 0xc0) >> 6) {
236 surf_man->hw_info.group_bytes = 256;
239 surf_man->hw_info.group_bytes = 512;
242 surf_man->hw_info.group_bytes = 256;
243 surf_man->hw_info.allow_2d = 0;
249 static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
250 struct radeon_surface *surf,
251 uint64_t offset, unsigned start_level)
253 uint32_t xalign, yalign, zalign;
256 /* compute alignment */
258 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
260 /* the 32 alignment is for scanout, cb or db but to allow texture to be
261 * easily bound as such we force this alignment to all surface
263 xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
266 if (surf->flags & RADEON_SURF_SCANOUT) {
267 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
270 /* build mipmap tree */
271 for (i = start_level; i <= surf->last_level; i++) {
272 surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
273 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
274 /* level0 and first mipmap need to have alignment */
275 offset = surf->bo_size;
277 offset = ALIGN(offset, surf->bo_alignment);
283 static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
284 struct radeon_surface *surf,
285 uint64_t offset, unsigned start_level)
287 uint32_t xalign, yalign, zalign;
290 /* compute alignment */
292 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
294 xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
298 /* build mipmap tree */
299 for (i = start_level; i <= surf->last_level; i++) {
300 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
301 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
302 /* level0 and first mipmap need to have alignment */
303 offset = surf->bo_size;
305 offset = ALIGN(offset, surf->bo_alignment);
311 static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
312 struct radeon_surface *surf,
313 uint64_t offset, unsigned start_level)
315 uint32_t xalign, yalign, zalign, tilew;
318 /* compute alignment */
320 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
321 xalign = MAX2(tilew, xalign);
324 if (surf->flags & RADEON_SURF_SCANOUT) {
325 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
328 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
331 /* build mipmap tree */
332 for (i = start_level; i <= surf->last_level; i++) {
333 surf->level[i].mode = RADEON_SURF_MODE_1D;
334 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
335 /* level0 and first mipmap need to have alignment */
336 offset = surf->bo_size;
338 offset = ALIGN(offset, surf->bo_alignment);
344 static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
345 struct radeon_surface *surf,
346 uint64_t offset, unsigned start_level)
348 uint32_t xalign, yalign, zalign, tilew;
351 /* compute alignment */
354 xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
355 (tilew * surf->bpe * surf->nsamples);
356 xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
357 yalign = tilew * surf_man->hw_info.num_pipes;
358 if (surf->flags & RADEON_SURF_SCANOUT) {
359 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
363 MAX2(surf_man->hw_info.num_pipes *
364 surf_man->hw_info.num_banks *
365 surf->nsamples * surf->bpe * 64,
366 xalign * yalign * surf->nsamples * surf->bpe);
369 /* build mipmap tree */
370 for (i = start_level; i <= surf->last_level; i++) {
371 surf->level[i].mode = RADEON_SURF_MODE_2D;
372 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
373 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
374 return r6_surface_init_1d(surf_man, surf, offset, i);
376 /* level0 and first mipmap need to have alignment */
377 offset = surf->bo_size;
379 offset = ALIGN(offset, surf->bo_alignment);
385 static int r6_surface_init(struct radeon_surface_manager *surf_man,
386 struct radeon_surface *surf)
391 /* MSAA surfaces support the 2D mode only. */
392 if (surf->nsamples > 1) {
393 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
394 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
398 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
400 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
401 /* zbuffer only support 1D or 2D tiled surface */
403 case RADEON_SURF_MODE_1D:
404 case RADEON_SURF_MODE_2D:
407 mode = RADEON_SURF_MODE_1D;
408 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
409 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
414 /* force 1d on kernel that can't do 2d */
415 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
416 if (surf->nsamples > 1) {
417 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
420 mode = RADEON_SURF_MODE_1D;
421 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
422 surf->flags |= RADEON_SURF_SET(mode, MODE);
425 /* check surface dimension */
426 if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
430 /* check mipmap last_level */
431 if (surf->last_level > 14) {
435 /* check tiling mode */
437 case RADEON_SURF_MODE_LINEAR:
438 r = r6_surface_init_linear(surf_man, surf, 0, 0);
440 case RADEON_SURF_MODE_LINEAR_ALIGNED:
441 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
443 case RADEON_SURF_MODE_1D:
444 r = r6_surface_init_1d(surf_man, surf, 0, 0);
446 case RADEON_SURF_MODE_2D:
447 r = r6_surface_init_2d(surf_man, surf, 0, 0);
455 static int r6_surface_best(struct radeon_surface_manager *surf_man,
456 struct radeon_surface *surf)
458 /* no value to optimize for r6xx/r7xx */
463 /* ===========================================================================
466 static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
468 uint32_t tiling_config;
469 drmVersionPtr version;
472 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
478 surf_man->hw_info.allow_2d = 0;
479 version = drmGetVersion(surf_man->fd);
480 if (version && version->version_minor >= 16) {
481 surf_man->hw_info.allow_2d = 1;
483 drmFreeVersion(version);
485 switch (tiling_config & 0xf) {
487 surf_man->hw_info.num_pipes = 1;
490 surf_man->hw_info.num_pipes = 2;
493 surf_man->hw_info.num_pipes = 4;
496 surf_man->hw_info.num_pipes = 8;
499 surf_man->hw_info.num_pipes = 8;
500 surf_man->hw_info.allow_2d = 0;
504 switch ((tiling_config & 0xf0) >> 4) {
506 surf_man->hw_info.num_banks = 4;
509 surf_man->hw_info.num_banks = 8;
512 surf_man->hw_info.num_banks = 16;
515 surf_man->hw_info.num_banks = 8;
516 surf_man->hw_info.allow_2d = 0;
520 switch ((tiling_config & 0xf00) >> 8) {
522 surf_man->hw_info.group_bytes = 256;
525 surf_man->hw_info.group_bytes = 512;
528 surf_man->hw_info.group_bytes = 256;
529 surf_man->hw_info.allow_2d = 0;
533 switch ((tiling_config & 0xf000) >> 12) {
535 surf_man->hw_info.row_size = 1024;
538 surf_man->hw_info.row_size = 2048;
541 surf_man->hw_info.row_size = 4096;
544 surf_man->hw_info.row_size = 4096;
545 surf_man->hw_info.allow_2d = 0;
551 static void eg_surf_minify(struct radeon_surface *surf,
552 struct radeon_surface_level *surflevel,
561 unsigned mtile_pr, mtile_ps;
563 surflevel->npix_x = mip_minify(surf->npix_x, level);
564 surflevel->npix_y = mip_minify(surf->npix_y, level);
565 surflevel->npix_z = mip_minify(surf->npix_z, level);
566 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
567 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
568 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
569 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
570 !(surf->flags & RADEON_SURF_FMASK)) {
571 if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
572 surflevel->mode = RADEON_SURF_MODE_1D;
576 surflevel->nblk_x = ALIGN(surflevel->nblk_x, mtilew);
577 surflevel->nblk_y = ALIGN(surflevel->nblk_y, mtileh);
578 surflevel->nblk_z = ALIGN(surflevel->nblk_z, 1);
580 /* macro tile per row */
581 mtile_pr = surflevel->nblk_x / mtilew;
582 /* macro tile per slice */
583 mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
585 surflevel->offset = offset;
586 surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
587 surflevel->slice_size = mtile_ps * mtileb * slice_pt;
589 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
592 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
593 struct radeon_surface *surf,
594 struct radeon_surface_level *level,
596 uint64_t offset, unsigned start_level)
598 uint32_t xalign, yalign, zalign, tilew;
601 /* compute alignment */
603 xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
604 xalign = MAX2(tilew, xalign);
607 if (surf->flags & RADEON_SURF_SCANOUT) {
608 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
612 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
613 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
616 offset = ALIGN(offset, alignment);
620 /* build mipmap tree */
621 for (i = start_level; i <= surf->last_level; i++) {
622 level[i].mode = RADEON_SURF_MODE_1D;
623 surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
624 /* level0 and first mipmap need to have alignment */
625 offset = surf->bo_size;
627 offset = ALIGN(offset, surf->bo_alignment);
633 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
634 struct radeon_surface *surf,
635 struct radeon_surface_level *level,
636 unsigned bpe, unsigned tile_split,
637 uint64_t offset, unsigned start_level)
639 unsigned tilew, tileh, tileb;
640 unsigned mtilew, mtileh, mtileb;
644 /* compute tile values */
647 tileb = tilew * tileh * bpe * surf->nsamples;
648 /* slices per tile */
650 if (tileb > tile_split) {
651 slice_pt = tileb / tile_split;
653 tileb = tileb / slice_pt;
655 /* macro tile width & height */
656 mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
657 mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
658 /* macro tile bytes */
659 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
662 unsigned alignment = MAX2(256, mtileb);
663 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
666 offset = ALIGN(offset, alignment);
670 /* build mipmap tree */
671 for (i = start_level; i <= surf->last_level; i++) {
672 level[i].mode = RADEON_SURF_MODE_2D;
673 eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
674 if (level[i].mode == RADEON_SURF_MODE_1D) {
675 return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
677 /* level0 and first mipmap need to have alignment */
678 offset = surf->bo_size;
680 offset = ALIGN(offset, surf->bo_alignment);
686 static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
687 struct radeon_surface *surf,
692 /* check surface dimension */
693 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
697 /* check mipmap last_level */
698 if (surf->last_level > 15) {
702 /* force 1d on kernel that can't do 2d */
703 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
704 if (surf->nsamples > 1) {
705 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
708 mode = RADEON_SURF_MODE_1D;
709 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
710 surf->flags |= RADEON_SURF_SET(mode, MODE);
713 /* check tile split */
714 if (mode == RADEON_SURF_MODE_2D) {
715 switch (surf->tile_split) {
727 switch (surf->mtilea) {
736 /* check aspect ratio */
737 if (surf_man->hw_info.num_banks < surf->mtilea) {
740 /* check bank width */
741 switch (surf->bankw) {
750 /* check bank height */
751 switch (surf->bankh) {
760 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
761 if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
769 static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
770 struct radeon_surface *surf)
772 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
773 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
774 /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
775 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
776 struct radeon_surface_level *stencil_level =
777 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
779 r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
783 if (is_depth_stencil) {
784 r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
786 surf->stencil_offset = stencil_level[0].offset;
791 static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
792 struct radeon_surface *surf)
794 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
795 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
796 /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
797 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
798 struct radeon_surface_level *stencil_level =
799 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
801 r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
802 surf->tile_split, 0, 0);
806 if (is_depth_stencil) {
807 r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
808 surf->stencil_tile_split, surf->bo_size, 0);
809 surf->stencil_offset = stencil_level[0].offset;
814 static int eg_surface_init(struct radeon_surface_manager *surf_man,
815 struct radeon_surface *surf)
820 /* MSAA surfaces support the 2D mode only. */
821 if (surf->nsamples > 1) {
822 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
823 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
827 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
829 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
830 /* zbuffer only support 1D or 2D tiled surface */
832 case RADEON_SURF_MODE_1D:
833 case RADEON_SURF_MODE_2D:
836 mode = RADEON_SURF_MODE_1D;
837 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
838 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
843 r = eg_surface_sanity(surf_man, surf, mode);
848 surf->stencil_offset = 0;
849 surf->bo_alignment = 0;
851 /* check tiling mode */
853 case RADEON_SURF_MODE_LINEAR:
854 r = r6_surface_init_linear(surf_man, surf, 0, 0);
856 case RADEON_SURF_MODE_LINEAR_ALIGNED:
857 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
859 case RADEON_SURF_MODE_1D:
860 r = eg_surface_init_1d_miptrees(surf_man, surf);
862 case RADEON_SURF_MODE_2D:
863 r = eg_surface_init_2d_miptrees(surf_man, surf);
871 static unsigned log2_int(unsigned x)
879 if ((unsigned)(1 << l) > x) {
886 /* compute best tile_split, bankw, bankh, mtilea
887 * depending on surface
889 static int eg_surface_best(struct radeon_surface_manager *surf_man,
890 struct radeon_surface *surf)
892 unsigned mode, tileb, h_over_w;
896 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
898 /* set some default value to avoid sanity check choking on them */
899 surf->tile_split = 1024;
902 surf->mtilea = surf_man->hw_info.num_banks;
903 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
904 for (; surf->bankh <= 8; surf->bankh *= 2) {
905 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
909 if (surf->mtilea > 8) {
913 r = eg_surface_sanity(surf_man, surf, mode);
918 if (mode != RADEON_SURF_MODE_2D) {
919 /* nothing to do for non 2D tiled surface */
923 /* Tweak TILE_SPLIT for performance here. */
924 if (surf->nsamples > 1) {
925 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
926 switch (surf->nsamples) {
928 surf->tile_split = 128;
931 surf->tile_split = 128;
934 surf->tile_split = 256;
936 case 16: /* cayman only */
937 surf->tile_split = 512;
940 fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
941 surf->nsamples, __LINE__);
944 surf->stencil_tile_split = 64;
946 /* tile split must be >= 256 for colorbuffer surfaces */
947 surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
948 if (surf->tile_split > 4096)
949 surf->tile_split = 4096;
952 /* set tile split to row size */
953 surf->tile_split = surf_man->hw_info.row_size;
954 surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
957 /* bankw or bankh greater than 1 increase alignment requirement, not
958 * sure if it's worth using smaller bankw & bankh to stick with 2D
959 * tiling on small surface rather than falling back to 1D tiling.
960 * Use recommanded value based on tile size for now.
962 * fmask buffer has different optimal value figure them out once we
965 if (surf->flags & RADEON_SURF_SBUFFER) {
966 /* assume 1 bytes for stencil, we optimize for stencil as stencil
967 * and depth shares surface values
969 tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
971 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
974 /* use bankw of 1 to minimize width alignment, might be interesting to
975 * increase it for large surface
990 /* double check the constraint */
991 for (; surf->bankh <= 8; surf->bankh *= 2) {
992 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
997 h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
998 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
999 surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
1005 /* ===========================================================================
1006 * Southern Islands family
1008 #define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
1009 #define SI__PIPE_CONFIG__ADDR_SURF_P2 0
1010 #define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
1011 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
1012 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
1013 #define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
1014 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
1015 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
1016 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
1017 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
1018 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
1019 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
1020 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
1021 #define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
1022 #define SI__TILE_SPLIT__64B 0
1023 #define SI__TILE_SPLIT__128B 1
1024 #define SI__TILE_SPLIT__256B 2
1025 #define SI__TILE_SPLIT__512B 3
1026 #define SI__TILE_SPLIT__1024B 4
1027 #define SI__TILE_SPLIT__2048B 5
1028 #define SI__TILE_SPLIT__4096B 6
1029 #define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3)
1030 #define SI__BANK_WIDTH__1 0
1031 #define SI__BANK_WIDTH__2 1
1032 #define SI__BANK_WIDTH__4 2
1033 #define SI__BANK_WIDTH__8 3
1034 #define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3)
1035 #define SI__BANK_HEIGHT__1 0
1036 #define SI__BANK_HEIGHT__2 1
1037 #define SI__BANK_HEIGHT__4 2
1038 #define SI__BANK_HEIGHT__8 3
1039 #define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3)
1040 #define SI__MACRO_TILE_ASPECT__1 0
1041 #define SI__MACRO_TILE_ASPECT__2 1
1042 #define SI__MACRO_TILE_ASPECT__4 2
1043 #define SI__MACRO_TILE_ASPECT__8 3
1044 #define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3)
1045 #define SI__NUM_BANKS__2_BANK 0
1046 #define SI__NUM_BANKS__4_BANK 1
1047 #define SI__NUM_BANKS__8_BANK 2
1048 #define SI__NUM_BANKS__16_BANK 3
1051 static void si_gb_tile_mode(uint32_t gb_tile_mode,
1052 unsigned *num_pipes,
1053 unsigned *num_banks,
1054 uint32_t *macro_tile_aspect,
1057 uint32_t *tile_split)
1060 switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1061 case SI__PIPE_CONFIG__ADDR_SURF_P2:
1065 case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1066 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1067 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1068 case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1071 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1072 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1073 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1074 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1075 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1076 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1077 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1083 switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
1085 case SI__NUM_BANKS__2_BANK:
1088 case SI__NUM_BANKS__4_BANK:
1091 case SI__NUM_BANKS__8_BANK:
1094 case SI__NUM_BANKS__16_BANK:
1099 if (macro_tile_aspect) {
1100 switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
1102 case SI__MACRO_TILE_ASPECT__1:
1103 *macro_tile_aspect = 1;
1105 case SI__MACRO_TILE_ASPECT__2:
1106 *macro_tile_aspect = 2;
1108 case SI__MACRO_TILE_ASPECT__4:
1109 *macro_tile_aspect = 4;
1111 case SI__MACRO_TILE_ASPECT__8:
1112 *macro_tile_aspect = 8;
1117 switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
1119 case SI__BANK_WIDTH__1:
1122 case SI__BANK_WIDTH__2:
1125 case SI__BANK_WIDTH__4:
1128 case SI__BANK_WIDTH__8:
1134 switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
1136 case SI__BANK_HEIGHT__1:
1139 case SI__BANK_HEIGHT__2:
1142 case SI__BANK_HEIGHT__4:
1145 case SI__BANK_HEIGHT__8:
1151 switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1153 case SI__TILE_SPLIT__64B:
1156 case SI__TILE_SPLIT__128B:
1159 case SI__TILE_SPLIT__256B:
1162 case SI__TILE_SPLIT__512B:
1165 case SI__TILE_SPLIT__1024B:
1168 case SI__TILE_SPLIT__2048B:
1171 case SI__TILE_SPLIT__4096B:
1178 static int si_init_hw_info(struct radeon_surface_manager *surf_man)
1180 uint32_t tiling_config;
1181 drmVersionPtr version;
1184 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
1190 surf_man->hw_info.allow_2d = 0;
1191 version = drmGetVersion(surf_man->fd);
1192 if (version && version->version_minor >= 33) {
1193 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
1194 surf_man->hw_info.allow_2d = 1;
1197 drmFreeVersion(version);
1199 switch (tiling_config & 0xf) {
1201 surf_man->hw_info.num_pipes = 1;
1204 surf_man->hw_info.num_pipes = 2;
1207 surf_man->hw_info.num_pipes = 4;
1210 surf_man->hw_info.num_pipes = 8;
1213 surf_man->hw_info.num_pipes = 8;
1214 surf_man->hw_info.allow_2d = 0;
1218 switch ((tiling_config & 0xf0) >> 4) {
1220 surf_man->hw_info.num_banks = 4;
1223 surf_man->hw_info.num_banks = 8;
1226 surf_man->hw_info.num_banks = 16;
1229 surf_man->hw_info.num_banks = 8;
1230 surf_man->hw_info.allow_2d = 0;
1234 switch ((tiling_config & 0xf00) >> 8) {
1236 surf_man->hw_info.group_bytes = 256;
1239 surf_man->hw_info.group_bytes = 512;
1242 surf_man->hw_info.group_bytes = 256;
1243 surf_man->hw_info.allow_2d = 0;
1247 switch ((tiling_config & 0xf000) >> 12) {
1249 surf_man->hw_info.row_size = 1024;
1252 surf_man->hw_info.row_size = 2048;
1255 surf_man->hw_info.row_size = 4096;
1258 surf_man->hw_info.row_size = 4096;
1259 surf_man->hw_info.allow_2d = 0;
1265 static int si_surface_sanity(struct radeon_surface_manager *surf_man,
1266 struct radeon_surface *surf,
1267 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
1269 uint32_t gb_tile_mode;
1271 /* check surface dimension */
1272 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
1276 /* check mipmap last_level */
1277 if (surf->last_level > 15) {
1281 /* force 1d on kernel that can't do 2d */
1282 if (mode > RADEON_SURF_MODE_1D &&
1283 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
1284 if (surf->nsamples > 1) {
1285 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
1288 mode = RADEON_SURF_MODE_1D;
1289 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1290 surf->flags |= RADEON_SURF_SET(mode, MODE);
1293 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
1297 if (!surf->tile_split) {
1302 surf->tile_split = 64;
1303 surf->stencil_tile_split = 64;
1307 case RADEON_SURF_MODE_2D:
1308 if (surf->flags & RADEON_SURF_SBUFFER) {
1309 switch (surf->nsamples) {
1311 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1314 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1317 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1320 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1325 /* retrieve tiling mode value */
1326 gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
1327 si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
1329 if (surf->flags & RADEON_SURF_ZBUFFER) {
1330 switch (surf->nsamples) {
1332 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1335 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1338 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1341 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1346 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1347 switch (surf->bpe) {
1349 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
1352 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
1358 switch (surf->bpe) {
1360 *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
1363 *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
1366 *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
1370 *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
1376 /* retrieve tiling mode value */
1377 gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
1378 si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
1380 case RADEON_SURF_MODE_1D:
1381 if (surf->flags & RADEON_SURF_SBUFFER) {
1382 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1384 if (surf->flags & RADEON_SURF_ZBUFFER) {
1385 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1386 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1387 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1389 *tile_mode = SI_TILE_MODE_COLOR_1D;
1392 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1394 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
1400 static void si_surf_minify(struct radeon_surface *surf,
1401 struct radeon_surface_level *surflevel,
1402 unsigned bpe, unsigned level,
1403 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1404 uint32_t slice_align, unsigned offset)
1406 surflevel->npix_x = mip_minify(surf->npix_x, level);
1407 surflevel->npix_y = mip_minify(surf->npix_y, level);
1408 surflevel->npix_z = mip_minify(surf->npix_z, level);
1410 if (level == 0 && surf->last_level > 0) {
1411 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1412 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1413 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1415 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1416 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1417 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1420 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1422 /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1423 * these are just guesses for the rules behind those
1425 if (level == 0 && surf->last_level == 0)
1426 /* Non-mipmap pitch padded to slice alignment */
1427 xalign = MAX2(xalign, slice_align / surf->bpe);
1429 /* Small rows evenly distributed across slice */
1430 xalign = MAX2(xalign, slice_align / surf->bpe / surflevel->nblk_y);
1432 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1433 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1435 surflevel->offset = offset;
1436 surflevel->pitch_bytes = surflevel->nblk_x * surf->bpe * surf->nsamples;
1437 surflevel->slice_size = ALIGN(surflevel->pitch_bytes * surflevel->nblk_y, slice_align);
1439 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1442 static void si_surf_minify_2d(struct radeon_surface *surf,
1443 struct radeon_surface_level *surflevel,
1444 unsigned bpe, unsigned level, unsigned slice_pt,
1445 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1446 unsigned mtileb, unsigned offset)
1448 unsigned mtile_pr, mtile_ps;
1450 surflevel->npix_x = mip_minify(surf->npix_x, level);
1451 surflevel->npix_y = mip_minify(surf->npix_y, level);
1452 surflevel->npix_z = mip_minify(surf->npix_z, level);
1454 if (level == 0 && surf->last_level > 0) {
1455 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1456 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1457 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1459 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1460 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1461 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1464 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
1465 !(surf->flags & RADEON_SURF_FMASK)) {
1466 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
1467 surflevel->mode = RADEON_SURF_MODE_1D;
1471 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1472 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1473 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1475 /* macro tile per row */
1476 mtile_pr = surflevel->nblk_x / xalign;
1477 /* macro tile per slice */
1478 mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
1479 surflevel->offset = offset;
1480 surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
1481 surflevel->slice_size = mtile_ps * mtileb * slice_pt;
1483 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1486 static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1487 struct radeon_surface *surf,
1489 uint64_t offset, unsigned start_level)
1491 uint32_t xalign, yalign, zalign, slice_align;
1494 /* compute alignment */
1496 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1498 xalign = MAX2(8, 64 / surf->bpe);
1501 slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1503 /* build mipmap tree */
1504 for (i = start_level; i <= surf->last_level; i++) {
1505 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1506 si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
1507 /* level0 and first mipmap need to have alignment */
1508 offset = surf->bo_size;
1510 offset = ALIGN(offset, surf->bo_alignment);
1512 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1513 surf->tiling_index[i] = tile_mode;
1519 static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1520 struct radeon_surface *surf,
1521 struct radeon_surface_level *level,
1522 unsigned bpe, unsigned tile_mode,
1523 uint64_t offset, unsigned start_level)
1525 uint32_t xalign, yalign, zalign, slice_align;
1528 /* compute alignment */
1532 slice_align = surf_man->hw_info.group_bytes;
1533 if (surf->flags & RADEON_SURF_SCANOUT) {
1534 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1538 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1541 offset = ALIGN(offset, surf->bo_alignment);
1545 /* build mipmap tree */
1546 for (i = start_level; i <= surf->last_level; i++) {
1547 level[i].mode = RADEON_SURF_MODE_1D;
1548 si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1549 /* level0 and first mipmap need to have alignment */
1550 offset = surf->bo_size;
1552 offset = ALIGN(offset, surf->bo_alignment);
1554 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1555 if (surf->level == level) {
1556 surf->tiling_index[i] = tile_mode;
1557 /* it's ok because stencil is done after */
1558 surf->stencil_tiling_index[i] = tile_mode;
1560 surf->stencil_tiling_index[i] = tile_mode;
1567 static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1568 struct radeon_surface *surf,
1569 unsigned tile_mode, unsigned stencil_tile_mode)
1573 r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
1578 if (surf->flags & RADEON_SURF_SBUFFER) {
1579 r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
1580 surf->stencil_offset = surf->stencil_level[0].offset;
1585 static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
1586 struct radeon_surface *surf,
1587 struct radeon_surface_level *level,
1588 unsigned bpe, unsigned tile_mode,
1589 unsigned num_pipes, unsigned num_banks,
1590 unsigned tile_split,
1592 unsigned start_level)
1594 unsigned tilew, tileh, tileb;
1595 unsigned mtilew, mtileh, mtileb;
1599 /* compute tile values */
1602 tileb = tilew * tileh * bpe * surf->nsamples;
1603 /* slices per tile */
1605 if (tileb > tile_split) {
1606 slice_pt = tileb / tile_split;
1608 tileb = tileb / slice_pt;
1610 /* macro tile width & height */
1611 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
1612 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
1614 /* macro tile bytes */
1615 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
1618 unsigned alignment = MAX2(256, mtileb);
1619 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1622 offset = ALIGN(offset, alignment);
1626 /* build mipmap tree */
1627 for (i = start_level; i <= surf->last_level; i++) {
1628 level[i].mode = RADEON_SURF_MODE_2D;
1629 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, offset);
1630 if (level[i].mode == RADEON_SURF_MODE_1D) {
1631 switch (tile_mode) {
1632 case SI_TILE_MODE_COLOR_2D_8BPP:
1633 case SI_TILE_MODE_COLOR_2D_16BPP:
1634 case SI_TILE_MODE_COLOR_2D_32BPP:
1635 case SI_TILE_MODE_COLOR_2D_64BPP:
1636 tile_mode = SI_TILE_MODE_COLOR_1D;
1638 case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
1639 case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
1640 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1642 case SI_TILE_MODE_DEPTH_STENCIL_2D:
1643 tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1648 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
1650 /* level0 and first mipmap need to have alignment */
1651 offset = surf->bo_size;
1653 offset = ALIGN(offset, surf->bo_alignment);
1655 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1656 if (surf->level == level) {
1657 surf->tiling_index[i] = tile_mode;
1658 /* it's ok because stencil is done after */
1659 surf->stencil_tiling_index[i] = tile_mode;
1661 surf->stencil_tiling_index[i] = tile_mode;
1668 static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
1669 struct radeon_surface *surf,
1670 unsigned tile_mode, unsigned stencil_tile_mode)
1672 unsigned num_pipes, num_banks;
1673 uint32_t gb_tile_mode;
1676 /* retrieve tiling mode value */
1677 gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1678 si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
1680 r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
1685 if (surf->flags & RADEON_SURF_SBUFFER) {
1686 r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0);
1687 surf->stencil_offset = surf->stencil_level[0].offset;
1692 static int si_surface_init(struct radeon_surface_manager *surf_man,
1693 struct radeon_surface *surf)
1695 unsigned mode, tile_mode, stencil_tile_mode;
1698 /* MSAA surfaces support the 2D mode only. */
1699 if (surf->nsamples > 1) {
1700 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1701 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1705 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1707 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1708 /* zbuffer only support 1D or 2D tiled surface */
1710 case RADEON_SURF_MODE_1D:
1711 case RADEON_SURF_MODE_2D:
1714 mode = RADEON_SURF_MODE_1D;
1715 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1716 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1721 r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1726 surf->stencil_offset = 0;
1727 surf->bo_alignment = 0;
1729 /* check tiling mode */
1731 case RADEON_SURF_MODE_LINEAR:
1732 r = r6_surface_init_linear(surf_man, surf, 0, 0);
1734 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1735 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
1737 case RADEON_SURF_MODE_1D:
1738 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1740 case RADEON_SURF_MODE_2D:
1741 r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1750 * depending on surface
1752 static int si_surface_best(struct radeon_surface_manager *surf_man,
1753 struct radeon_surface *surf)
1755 unsigned mode, tile_mode, stencil_tile_mode;
1758 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1760 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
1761 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
1762 /* depth/stencil force 1d tiling for old mesa */
1763 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1764 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1767 return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1771 /* ===========================================================================
1774 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
1776 struct radeon_surface_manager *surf_man;
1778 surf_man = calloc(1, sizeof(struct radeon_surface_manager));
1779 if (surf_man == NULL) {
1783 if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
1786 if (radeon_get_family(surf_man)) {
1790 if (surf_man->family <= CHIP_RV740) {
1791 if (r6_init_hw_info(surf_man)) {
1794 surf_man->surface_init = &r6_surface_init;
1795 surf_man->surface_best = &r6_surface_best;
1796 } else if (surf_man->family <= CHIP_ARUBA) {
1797 if (eg_init_hw_info(surf_man)) {
1800 surf_man->surface_init = &eg_surface_init;
1801 surf_man->surface_best = &eg_surface_best;
1803 if (si_init_hw_info(surf_man)) {
1806 surf_man->surface_init = &si_surface_init;
1807 surf_man->surface_best = &si_surface_best;
1816 void radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
1821 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
1822 struct radeon_surface *surf,
1826 if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
1830 /* all dimension must be at least 1 ! */
1831 if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
1834 if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
1837 if (!surf->array_size) {
1840 /* array size must be a power of 2 */
1841 surf->array_size = next_power_of_two(surf->array_size);
1843 switch (surf->nsamples) {
1854 case RADEON_SURF_TYPE_1D:
1855 if (surf->npix_y > 1) {
1858 case RADEON_SURF_TYPE_2D:
1859 if (surf->npix_z > 1) {
1863 case RADEON_SURF_TYPE_CUBEMAP:
1864 if (surf->npix_z > 1) {
1867 /* deal with cubemap as they were texture array */
1868 if (surf_man->family >= CHIP_RV770) {
1869 surf->array_size = 8;
1871 surf->array_size = 6;
1874 case RADEON_SURF_TYPE_3D:
1876 case RADEON_SURF_TYPE_1D_ARRAY:
1877 if (surf->npix_y > 1) {
1880 case RADEON_SURF_TYPE_2D_ARRAY:
1888 int radeon_surface_init(struct radeon_surface_manager *surf_man,
1889 struct radeon_surface *surf)
1891 unsigned mode, type;
1894 type = RADEON_SURF_GET(surf->flags, TYPE);
1895 mode = RADEON_SURF_GET(surf->flags, MODE);
1897 r = radeon_surface_sanity(surf_man, surf, type, mode);
1901 return surf_man->surface_init(surf_man, surf);
1904 int radeon_surface_best(struct radeon_surface_manager *surf_man,
1905 struct radeon_surface *surf)
1907 unsigned mode, type;
1910 type = RADEON_SURF_GET(surf->flags, TYPE);
1911 mode = RADEON_SURF_GET(surf->flags, MODE);
1913 r = radeon_surface_sanity(surf_man, surf, type, mode);
1917 return surf_man->surface_best(surf_man, surf);