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 */
83 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
84 struct radeon_surface *surf);
85 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
86 struct radeon_surface *surf);
88 struct radeon_hw_info {
97 uint32_t tile_mode_array[32];
100 struct radeon_surface_manager {
103 struct radeon_hw_info hw_info;
105 hw_init_surface_t surface_init;
106 hw_best_surface_t surface_best;
110 static int radeon_get_value(int fd, unsigned req, uint32_t *value)
112 struct drm_radeon_info info = {};
117 info.value = (uintptr_t)value;
118 r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
119 sizeof(struct drm_radeon_info));
123 static int radeon_get_family(struct radeon_surface_manager *surf_man)
125 switch (surf_man->device_id) {
126 #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
127 #include "r600_pci_ids.h"
135 static unsigned next_power_of_two(unsigned x)
140 return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
143 static unsigned mip_minify(unsigned size, unsigned level)
147 val = MAX2(1, size >> level);
149 val = next_power_of_two(val);
153 static void surf_minify(struct radeon_surface *surf,
154 struct radeon_surface_level *surflevel,
155 unsigned bpe, unsigned level,
156 uint32_t xalign, uint32_t yalign, uint32_t zalign,
159 surflevel->npix_x = mip_minify(surf->npix_x, level);
160 surflevel->npix_y = mip_minify(surf->npix_y, level);
161 surflevel->npix_z = mip_minify(surf->npix_z, level);
162 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
163 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
164 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
165 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
166 !(surf->flags & RADEON_SURF_FMASK)) {
167 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
168 surflevel->mode = RADEON_SURF_MODE_1D;
172 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
173 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
174 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
176 surflevel->offset = offset;
177 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
178 surflevel->slice_size = surflevel->pitch_bytes * surflevel->nblk_y;
180 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
183 /* ===========================================================================
186 static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
188 uint32_t tiling_config;
189 drmVersionPtr version;
192 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
198 surf_man->hw_info.allow_2d = 0;
199 version = drmGetVersion(surf_man->fd);
200 if (version && version->version_minor >= 14) {
201 surf_man->hw_info.allow_2d = 1;
203 drmFreeVersion(version);
205 switch ((tiling_config & 0xe) >> 1) {
207 surf_man->hw_info.num_pipes = 1;
210 surf_man->hw_info.num_pipes = 2;
213 surf_man->hw_info.num_pipes = 4;
216 surf_man->hw_info.num_pipes = 8;
219 surf_man->hw_info.num_pipes = 8;
220 surf_man->hw_info.allow_2d = 0;
224 switch ((tiling_config & 0x30) >> 4) {
226 surf_man->hw_info.num_banks = 4;
229 surf_man->hw_info.num_banks = 8;
232 surf_man->hw_info.num_banks = 8;
233 surf_man->hw_info.allow_2d = 0;
237 switch ((tiling_config & 0xc0) >> 6) {
239 surf_man->hw_info.group_bytes = 256;
242 surf_man->hw_info.group_bytes = 512;
245 surf_man->hw_info.group_bytes = 256;
246 surf_man->hw_info.allow_2d = 0;
252 static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
253 struct radeon_surface *surf,
254 uint64_t offset, unsigned start_level)
256 uint32_t xalign, yalign, zalign;
259 /* compute alignment */
261 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
263 /* the 32 alignment is for scanout, cb or db but to allow texture to be
264 * easily bound as such we force this alignment to all surface
266 xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
269 if (surf->flags & RADEON_SURF_SCANOUT) {
270 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
273 /* build mipmap tree */
274 for (i = start_level; i <= surf->last_level; i++) {
275 surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
276 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
277 /* level0 and first mipmap need to have alignment */
278 offset = surf->bo_size;
280 offset = ALIGN(offset, surf->bo_alignment);
286 static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
287 struct radeon_surface *surf,
288 uint64_t offset, unsigned start_level)
290 uint32_t xalign, yalign, zalign;
293 /* compute alignment */
295 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
297 xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
301 /* build mipmap tree */
302 for (i = start_level; i <= surf->last_level; i++) {
303 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
304 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
305 /* level0 and first mipmap need to have alignment */
306 offset = surf->bo_size;
308 offset = ALIGN(offset, surf->bo_alignment);
314 static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
315 struct radeon_surface *surf,
316 uint64_t offset, unsigned start_level)
318 uint32_t xalign, yalign, zalign, tilew;
321 /* compute alignment */
323 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
324 xalign = MAX2(tilew, xalign);
327 if (surf->flags & RADEON_SURF_SCANOUT) {
328 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
331 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
334 /* build mipmap tree */
335 for (i = start_level; i <= surf->last_level; i++) {
336 surf->level[i].mode = RADEON_SURF_MODE_1D;
337 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
338 /* level0 and first mipmap need to have alignment */
339 offset = surf->bo_size;
341 offset = ALIGN(offset, surf->bo_alignment);
347 static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
348 struct radeon_surface *surf,
349 uint64_t offset, unsigned start_level)
351 uint32_t xalign, yalign, zalign, tilew;
354 /* compute alignment */
357 xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
358 (tilew * surf->bpe * surf->nsamples);
359 xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
360 yalign = tilew * surf_man->hw_info.num_pipes;
361 if (surf->flags & RADEON_SURF_SCANOUT) {
362 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
366 MAX2(surf_man->hw_info.num_pipes *
367 surf_man->hw_info.num_banks *
368 surf->nsamples * surf->bpe * 64,
369 xalign * yalign * surf->nsamples * surf->bpe);
372 /* build mipmap tree */
373 for (i = start_level; i <= surf->last_level; i++) {
374 surf->level[i].mode = RADEON_SURF_MODE_2D;
375 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
376 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
377 return r6_surface_init_1d(surf_man, surf, offset, i);
379 /* level0 and first mipmap need to have alignment */
380 offset = surf->bo_size;
382 offset = ALIGN(offset, surf->bo_alignment);
388 static int r6_surface_init(struct radeon_surface_manager *surf_man,
389 struct radeon_surface *surf)
394 /* MSAA surfaces support the 2D mode only. */
395 if (surf->nsamples > 1) {
396 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
397 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
401 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
403 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
404 /* zbuffer only support 1D or 2D tiled surface */
406 case RADEON_SURF_MODE_1D:
407 case RADEON_SURF_MODE_2D:
410 mode = RADEON_SURF_MODE_1D;
411 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
412 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
417 /* force 1d on kernel that can't do 2d */
418 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
419 if (surf->nsamples > 1) {
420 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
423 mode = RADEON_SURF_MODE_1D;
424 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
425 surf->flags |= RADEON_SURF_SET(mode, MODE);
428 /* check surface dimension */
429 if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
433 /* check mipmap last_level */
434 if (surf->last_level > 14) {
438 /* check tiling mode */
440 case RADEON_SURF_MODE_LINEAR:
441 r = r6_surface_init_linear(surf_man, surf, 0, 0);
443 case RADEON_SURF_MODE_LINEAR_ALIGNED:
444 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
446 case RADEON_SURF_MODE_1D:
447 r = r6_surface_init_1d(surf_man, surf, 0, 0);
449 case RADEON_SURF_MODE_2D:
450 r = r6_surface_init_2d(surf_man, surf, 0, 0);
458 static int r6_surface_best(struct radeon_surface_manager *surf_man,
459 struct radeon_surface *surf)
461 /* no value to optimize for r6xx/r7xx */
466 /* ===========================================================================
469 static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
471 uint32_t tiling_config;
472 drmVersionPtr version;
475 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
481 surf_man->hw_info.allow_2d = 0;
482 version = drmGetVersion(surf_man->fd);
483 if (version && version->version_minor >= 16) {
484 surf_man->hw_info.allow_2d = 1;
486 drmFreeVersion(version);
488 switch (tiling_config & 0xf) {
490 surf_man->hw_info.num_pipes = 1;
493 surf_man->hw_info.num_pipes = 2;
496 surf_man->hw_info.num_pipes = 4;
499 surf_man->hw_info.num_pipes = 8;
502 surf_man->hw_info.num_pipes = 8;
503 surf_man->hw_info.allow_2d = 0;
507 switch ((tiling_config & 0xf0) >> 4) {
509 surf_man->hw_info.num_banks = 4;
512 surf_man->hw_info.num_banks = 8;
515 surf_man->hw_info.num_banks = 16;
518 surf_man->hw_info.num_banks = 8;
519 surf_man->hw_info.allow_2d = 0;
523 switch ((tiling_config & 0xf00) >> 8) {
525 surf_man->hw_info.group_bytes = 256;
528 surf_man->hw_info.group_bytes = 512;
531 surf_man->hw_info.group_bytes = 256;
532 surf_man->hw_info.allow_2d = 0;
536 switch ((tiling_config & 0xf000) >> 12) {
538 surf_man->hw_info.row_size = 1024;
541 surf_man->hw_info.row_size = 2048;
544 surf_man->hw_info.row_size = 4096;
547 surf_man->hw_info.row_size = 4096;
548 surf_man->hw_info.allow_2d = 0;
554 static void eg_surf_minify(struct radeon_surface *surf,
555 struct radeon_surface_level *surflevel,
564 unsigned mtile_pr, mtile_ps;
566 surflevel->npix_x = mip_minify(surf->npix_x, level);
567 surflevel->npix_y = mip_minify(surf->npix_y, level);
568 surflevel->npix_z = mip_minify(surf->npix_z, level);
569 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
570 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
571 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
572 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
573 !(surf->flags & RADEON_SURF_FMASK)) {
574 if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
575 surflevel->mode = RADEON_SURF_MODE_1D;
579 surflevel->nblk_x = ALIGN(surflevel->nblk_x, mtilew);
580 surflevel->nblk_y = ALIGN(surflevel->nblk_y, mtileh);
581 surflevel->nblk_z = ALIGN(surflevel->nblk_z, 1);
583 /* macro tile per row */
584 mtile_pr = surflevel->nblk_x / mtilew;
585 /* macro tile per slice */
586 mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
588 surflevel->offset = offset;
589 surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
590 surflevel->slice_size = mtile_ps * mtileb * slice_pt;
592 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
595 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
596 struct radeon_surface *surf,
597 struct radeon_surface_level *level,
599 uint64_t offset, unsigned start_level)
601 uint32_t xalign, yalign, zalign, tilew;
604 /* compute alignment */
606 xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
607 xalign = MAX2(tilew, xalign);
610 if (surf->flags & RADEON_SURF_SCANOUT) {
611 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
615 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
616 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
619 offset = ALIGN(offset, alignment);
623 /* build mipmap tree */
624 for (i = start_level; i <= surf->last_level; i++) {
625 level[i].mode = RADEON_SURF_MODE_1D;
626 surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
627 /* level0 and first mipmap need to have alignment */
628 offset = surf->bo_size;
630 offset = ALIGN(offset, surf->bo_alignment);
636 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
637 struct radeon_surface *surf,
638 struct radeon_surface_level *level,
639 unsigned bpe, unsigned tile_split,
640 uint64_t offset, unsigned start_level)
642 unsigned tilew, tileh, tileb;
643 unsigned mtilew, mtileh, mtileb;
647 /* compute tile values */
650 tileb = tilew * tileh * bpe * surf->nsamples;
651 /* slices per tile */
653 if (tileb > tile_split) {
654 slice_pt = tileb / tile_split;
656 tileb = tileb / slice_pt;
658 /* macro tile width & height */
659 mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
660 mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
661 /* macro tile bytes */
662 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
665 unsigned alignment = MAX2(256, mtileb);
666 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
669 offset = ALIGN(offset, alignment);
673 /* build mipmap tree */
674 for (i = start_level; i <= surf->last_level; i++) {
675 level[i].mode = RADEON_SURF_MODE_2D;
676 eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
677 if (level[i].mode == RADEON_SURF_MODE_1D) {
678 return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
680 /* level0 and first mipmap need to have alignment */
681 offset = surf->bo_size;
683 offset = ALIGN(offset, surf->bo_alignment);
689 static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
690 struct radeon_surface *surf,
695 /* check surface dimension */
696 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
700 /* check mipmap last_level */
701 if (surf->last_level > 15) {
705 /* force 1d on kernel that can't do 2d */
706 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
707 if (surf->nsamples > 1) {
708 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
711 mode = RADEON_SURF_MODE_1D;
712 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
713 surf->flags |= RADEON_SURF_SET(mode, MODE);
716 /* check tile split */
717 if (mode == RADEON_SURF_MODE_2D) {
718 switch (surf->tile_split) {
730 switch (surf->mtilea) {
739 /* check aspect ratio */
740 if (surf_man->hw_info.num_banks < surf->mtilea) {
743 /* check bank width */
744 switch (surf->bankw) {
753 /* check bank height */
754 switch (surf->bankh) {
763 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
764 if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
772 static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
773 struct radeon_surface *surf)
775 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
776 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
777 /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
778 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
779 struct radeon_surface_level *stencil_level =
780 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
782 r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
786 if (is_depth_stencil) {
787 r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
789 surf->stencil_offset = stencil_level[0].offset;
794 static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
795 struct radeon_surface *surf)
797 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
798 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
799 /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
800 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
801 struct radeon_surface_level *stencil_level =
802 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
804 r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
805 surf->tile_split, 0, 0);
809 if (is_depth_stencil) {
810 r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
811 surf->stencil_tile_split, surf->bo_size, 0);
812 surf->stencil_offset = stencil_level[0].offset;
817 static int eg_surface_init(struct radeon_surface_manager *surf_man,
818 struct radeon_surface *surf)
823 /* MSAA surfaces support the 2D mode only. */
824 if (surf->nsamples > 1) {
825 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
826 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
830 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
832 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
833 /* zbuffer only support 1D or 2D tiled surface */
835 case RADEON_SURF_MODE_1D:
836 case RADEON_SURF_MODE_2D:
839 mode = RADEON_SURF_MODE_1D;
840 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
841 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
846 r = eg_surface_sanity(surf_man, surf, mode);
851 surf->stencil_offset = 0;
852 surf->bo_alignment = 0;
854 /* check tiling mode */
856 case RADEON_SURF_MODE_LINEAR:
857 r = r6_surface_init_linear(surf_man, surf, 0, 0);
859 case RADEON_SURF_MODE_LINEAR_ALIGNED:
860 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
862 case RADEON_SURF_MODE_1D:
863 r = eg_surface_init_1d_miptrees(surf_man, surf);
865 case RADEON_SURF_MODE_2D:
866 r = eg_surface_init_2d_miptrees(surf_man, surf);
874 static unsigned log2_int(unsigned x)
882 if ((unsigned)(1 << l) > x) {
889 /* compute best tile_split, bankw, bankh, mtilea
890 * depending on surface
892 static int eg_surface_best(struct radeon_surface_manager *surf_man,
893 struct radeon_surface *surf)
895 unsigned mode, tileb, h_over_w;
899 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
901 /* set some default value to avoid sanity check choking on them */
902 surf->tile_split = 1024;
905 surf->mtilea = surf_man->hw_info.num_banks;
906 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
907 for (; surf->bankh <= 8; surf->bankh *= 2) {
908 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
912 if (surf->mtilea > 8) {
916 r = eg_surface_sanity(surf_man, surf, mode);
921 if (mode != RADEON_SURF_MODE_2D) {
922 /* nothing to do for non 2D tiled surface */
926 /* Tweak TILE_SPLIT for performance here. */
927 if (surf->nsamples > 1) {
928 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
929 switch (surf->nsamples) {
931 surf->tile_split = 128;
934 surf->tile_split = 128;
937 surf->tile_split = 256;
939 case 16: /* cayman only */
940 surf->tile_split = 512;
943 fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
944 surf->nsamples, __LINE__);
947 surf->stencil_tile_split = 64;
949 /* tile split must be >= 256 for colorbuffer surfaces */
950 surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
951 if (surf->tile_split > 4096)
952 surf->tile_split = 4096;
955 /* set tile split to row size */
956 surf->tile_split = surf_man->hw_info.row_size;
957 surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
960 /* bankw or bankh greater than 1 increase alignment requirement, not
961 * sure if it's worth using smaller bankw & bankh to stick with 2D
962 * tiling on small surface rather than falling back to 1D tiling.
963 * Use recommanded value based on tile size for now.
965 * fmask buffer has different optimal value figure them out once we
968 if (surf->flags & RADEON_SURF_SBUFFER) {
969 /* assume 1 bytes for stencil, we optimize for stencil as stencil
970 * and depth shares surface values
972 tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
974 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
977 /* use bankw of 1 to minimize width alignment, might be interesting to
978 * increase it for large surface
993 /* double check the constraint */
994 for (; surf->bankh <= 8; surf->bankh *= 2) {
995 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
1000 h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
1001 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
1002 surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
1008 /* ===========================================================================
1009 * Southern Islands family
1011 #define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
1012 #define SI__PIPE_CONFIG__ADDR_SURF_P2 0
1013 #define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
1014 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
1015 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
1016 #define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
1017 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
1018 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
1019 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
1020 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
1021 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
1022 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
1023 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
1024 #define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
1025 #define SI__TILE_SPLIT__64B 0
1026 #define SI__TILE_SPLIT__128B 1
1027 #define SI__TILE_SPLIT__256B 2
1028 #define SI__TILE_SPLIT__512B 3
1029 #define SI__TILE_SPLIT__1024B 4
1030 #define SI__TILE_SPLIT__2048B 5
1031 #define SI__TILE_SPLIT__4096B 6
1032 #define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3)
1033 #define SI__BANK_WIDTH__1 0
1034 #define SI__BANK_WIDTH__2 1
1035 #define SI__BANK_WIDTH__4 2
1036 #define SI__BANK_WIDTH__8 3
1037 #define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3)
1038 #define SI__BANK_HEIGHT__1 0
1039 #define SI__BANK_HEIGHT__2 1
1040 #define SI__BANK_HEIGHT__4 2
1041 #define SI__BANK_HEIGHT__8 3
1042 #define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3)
1043 #define SI__MACRO_TILE_ASPECT__1 0
1044 #define SI__MACRO_TILE_ASPECT__2 1
1045 #define SI__MACRO_TILE_ASPECT__4 2
1046 #define SI__MACRO_TILE_ASPECT__8 3
1047 #define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3)
1048 #define SI__NUM_BANKS__2_BANK 0
1049 #define SI__NUM_BANKS__4_BANK 1
1050 #define SI__NUM_BANKS__8_BANK 2
1051 #define SI__NUM_BANKS__16_BANK 3
1054 static void si_gb_tile_mode(uint32_t gb_tile_mode,
1055 unsigned *num_pipes,
1056 unsigned *num_banks,
1057 uint32_t *macro_tile_aspect,
1060 uint32_t *tile_split)
1063 switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1064 case SI__PIPE_CONFIG__ADDR_SURF_P2:
1068 case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1069 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1070 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1071 case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1074 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1075 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1076 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1077 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1078 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1079 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1080 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1086 switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
1088 case SI__NUM_BANKS__2_BANK:
1091 case SI__NUM_BANKS__4_BANK:
1094 case SI__NUM_BANKS__8_BANK:
1097 case SI__NUM_BANKS__16_BANK:
1102 if (macro_tile_aspect) {
1103 switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
1105 case SI__MACRO_TILE_ASPECT__1:
1106 *macro_tile_aspect = 1;
1108 case SI__MACRO_TILE_ASPECT__2:
1109 *macro_tile_aspect = 2;
1111 case SI__MACRO_TILE_ASPECT__4:
1112 *macro_tile_aspect = 4;
1114 case SI__MACRO_TILE_ASPECT__8:
1115 *macro_tile_aspect = 8;
1120 switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
1122 case SI__BANK_WIDTH__1:
1125 case SI__BANK_WIDTH__2:
1128 case SI__BANK_WIDTH__4:
1131 case SI__BANK_WIDTH__8:
1137 switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
1139 case SI__BANK_HEIGHT__1:
1142 case SI__BANK_HEIGHT__2:
1145 case SI__BANK_HEIGHT__4:
1148 case SI__BANK_HEIGHT__8:
1154 switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1156 case SI__TILE_SPLIT__64B:
1159 case SI__TILE_SPLIT__128B:
1162 case SI__TILE_SPLIT__256B:
1165 case SI__TILE_SPLIT__512B:
1168 case SI__TILE_SPLIT__1024B:
1171 case SI__TILE_SPLIT__2048B:
1174 case SI__TILE_SPLIT__4096B:
1181 static int si_init_hw_info(struct radeon_surface_manager *surf_man)
1183 uint32_t tiling_config;
1184 drmVersionPtr version;
1187 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
1193 surf_man->hw_info.allow_2d = 0;
1194 version = drmGetVersion(surf_man->fd);
1195 if (version && version->version_minor >= 33) {
1196 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
1197 surf_man->hw_info.allow_2d = 1;
1200 drmFreeVersion(version);
1202 switch (tiling_config & 0xf) {
1204 surf_man->hw_info.num_pipes = 1;
1207 surf_man->hw_info.num_pipes = 2;
1210 surf_man->hw_info.num_pipes = 4;
1213 surf_man->hw_info.num_pipes = 8;
1216 surf_man->hw_info.num_pipes = 8;
1217 surf_man->hw_info.allow_2d = 0;
1221 switch ((tiling_config & 0xf0) >> 4) {
1223 surf_man->hw_info.num_banks = 4;
1226 surf_man->hw_info.num_banks = 8;
1229 surf_man->hw_info.num_banks = 16;
1232 surf_man->hw_info.num_banks = 8;
1233 surf_man->hw_info.allow_2d = 0;
1237 switch ((tiling_config & 0xf00) >> 8) {
1239 surf_man->hw_info.group_bytes = 256;
1242 surf_man->hw_info.group_bytes = 512;
1245 surf_man->hw_info.group_bytes = 256;
1246 surf_man->hw_info.allow_2d = 0;
1250 switch ((tiling_config & 0xf000) >> 12) {
1252 surf_man->hw_info.row_size = 1024;
1255 surf_man->hw_info.row_size = 2048;
1258 surf_man->hw_info.row_size = 4096;
1261 surf_man->hw_info.row_size = 4096;
1262 surf_man->hw_info.allow_2d = 0;
1268 static int si_surface_sanity(struct radeon_surface_manager *surf_man,
1269 struct radeon_surface *surf,
1270 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
1272 uint32_t gb_tile_mode;
1274 /* check surface dimension */
1275 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
1279 /* check mipmap last_level */
1280 if (surf->last_level > 15) {
1284 /* force 1d on kernel that can't do 2d */
1285 if (mode > RADEON_SURF_MODE_1D &&
1286 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
1287 if (surf->nsamples > 1) {
1288 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
1291 mode = RADEON_SURF_MODE_1D;
1292 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1293 surf->flags |= RADEON_SURF_SET(mode, MODE);
1296 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
1300 if (!surf->tile_split) {
1305 surf->tile_split = 64;
1306 surf->stencil_tile_split = 64;
1310 case RADEON_SURF_MODE_2D:
1311 if (surf->flags & RADEON_SURF_SBUFFER) {
1312 switch (surf->nsamples) {
1314 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1317 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1320 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1323 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1328 /* retrieve tiling mode value */
1329 gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
1330 si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
1332 if (surf->flags & RADEON_SURF_ZBUFFER) {
1333 switch (surf->nsamples) {
1335 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1338 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1341 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1344 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1349 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1350 switch (surf->bpe) {
1352 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
1355 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
1361 switch (surf->bpe) {
1363 *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
1366 *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
1369 *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
1373 *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
1379 /* retrieve tiling mode value */
1380 gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
1381 si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
1383 case RADEON_SURF_MODE_1D:
1384 if (surf->flags & RADEON_SURF_SBUFFER) {
1385 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1387 if (surf->flags & RADEON_SURF_ZBUFFER) {
1388 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1389 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1390 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1392 *tile_mode = SI_TILE_MODE_COLOR_1D;
1395 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1397 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
1403 static void si_surf_minify(struct radeon_surface *surf,
1404 struct radeon_surface_level *surflevel,
1405 unsigned bpe, unsigned level,
1406 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1407 uint32_t slice_align, unsigned offset)
1409 surflevel->npix_x = mip_minify(surf->npix_x, level);
1410 surflevel->npix_y = mip_minify(surf->npix_y, level);
1411 surflevel->npix_z = mip_minify(surf->npix_z, level);
1413 if (level == 0 && surf->last_level > 0) {
1414 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1415 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1416 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1418 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1419 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1420 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1423 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1425 /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1426 * these are just guesses for the rules behind those
1428 if (level == 0 && surf->last_level == 0)
1429 /* Non-mipmap pitch padded to slice alignment */
1430 xalign = MAX2(xalign, slice_align / surf->bpe);
1432 /* Small rows evenly distributed across slice */
1433 xalign = MAX2(xalign, slice_align / surf->bpe / surflevel->nblk_y);
1435 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1436 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1438 surflevel->offset = offset;
1439 surflevel->pitch_bytes = surflevel->nblk_x * surf->bpe * surf->nsamples;
1440 surflevel->slice_size = ALIGN(surflevel->pitch_bytes * surflevel->nblk_y, slice_align);
1442 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1445 static void si_surf_minify_2d(struct radeon_surface *surf,
1446 struct radeon_surface_level *surflevel,
1447 unsigned bpe, unsigned level, unsigned slice_pt,
1448 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1449 unsigned mtileb, unsigned offset)
1451 unsigned mtile_pr, mtile_ps;
1453 surflevel->npix_x = mip_minify(surf->npix_x, level);
1454 surflevel->npix_y = mip_minify(surf->npix_y, level);
1455 surflevel->npix_z = mip_minify(surf->npix_z, level);
1457 if (level == 0 && surf->last_level > 0) {
1458 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1459 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1460 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1462 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1463 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1464 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1467 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
1468 !(surf->flags & RADEON_SURF_FMASK)) {
1469 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
1470 surflevel->mode = RADEON_SURF_MODE_1D;
1474 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1475 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1476 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1478 /* macro tile per row */
1479 mtile_pr = surflevel->nblk_x / xalign;
1480 /* macro tile per slice */
1481 mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
1482 surflevel->offset = offset;
1483 surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
1484 surflevel->slice_size = mtile_ps * mtileb * slice_pt;
1486 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1489 static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1490 struct radeon_surface *surf,
1492 uint64_t offset, unsigned start_level)
1494 uint32_t xalign, yalign, zalign, slice_align;
1497 /* compute alignment */
1499 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1501 xalign = MAX2(8, 64 / surf->bpe);
1504 slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1506 /* build mipmap tree */
1507 for (i = start_level; i <= surf->last_level; i++) {
1508 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1509 si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
1510 /* level0 and first mipmap need to have alignment */
1511 offset = surf->bo_size;
1513 offset = ALIGN(offset, surf->bo_alignment);
1515 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1516 surf->tiling_index[i] = tile_mode;
1522 static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1523 struct radeon_surface *surf,
1524 struct radeon_surface_level *level,
1525 unsigned bpe, unsigned tile_mode,
1526 uint64_t offset, unsigned start_level)
1528 uint32_t xalign, yalign, zalign, slice_align;
1531 /* compute alignment */
1535 slice_align = surf_man->hw_info.group_bytes;
1536 if (surf->flags & RADEON_SURF_SCANOUT) {
1537 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1541 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1544 offset = ALIGN(offset, surf->bo_alignment);
1548 /* build mipmap tree */
1549 for (i = start_level; i <= surf->last_level; i++) {
1550 level[i].mode = RADEON_SURF_MODE_1D;
1551 si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1552 /* level0 and first mipmap need to have alignment */
1553 offset = surf->bo_size;
1555 offset = ALIGN(offset, surf->bo_alignment);
1557 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1558 if (surf->level == level) {
1559 surf->tiling_index[i] = tile_mode;
1560 /* it's ok because stencil is done after */
1561 surf->stencil_tiling_index[i] = tile_mode;
1563 surf->stencil_tiling_index[i] = tile_mode;
1570 static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1571 struct radeon_surface *surf,
1572 unsigned tile_mode, unsigned stencil_tile_mode)
1576 r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
1581 if (surf->flags & RADEON_SURF_SBUFFER) {
1582 r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
1583 surf->stencil_offset = surf->stencil_level[0].offset;
1588 static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
1589 struct radeon_surface *surf,
1590 struct radeon_surface_level *level,
1591 unsigned bpe, unsigned tile_mode,
1592 unsigned num_pipes, unsigned num_banks,
1593 unsigned tile_split,
1595 unsigned start_level)
1597 unsigned tilew, tileh, tileb;
1598 unsigned mtilew, mtileh, mtileb;
1602 /* compute tile values */
1605 tileb = tilew * tileh * bpe * surf->nsamples;
1606 /* slices per tile */
1608 if (tileb > tile_split) {
1609 slice_pt = tileb / tile_split;
1611 tileb = tileb / slice_pt;
1613 /* macro tile width & height */
1614 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
1615 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
1617 /* macro tile bytes */
1618 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
1621 unsigned alignment = MAX2(256, mtileb);
1622 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1625 offset = ALIGN(offset, alignment);
1629 /* build mipmap tree */
1630 for (i = start_level; i <= surf->last_level; i++) {
1631 level[i].mode = RADEON_SURF_MODE_2D;
1632 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, offset);
1633 if (level[i].mode == RADEON_SURF_MODE_1D) {
1634 switch (tile_mode) {
1635 case SI_TILE_MODE_COLOR_2D_8BPP:
1636 case SI_TILE_MODE_COLOR_2D_16BPP:
1637 case SI_TILE_MODE_COLOR_2D_32BPP:
1638 case SI_TILE_MODE_COLOR_2D_64BPP:
1639 tile_mode = SI_TILE_MODE_COLOR_1D;
1641 case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
1642 case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
1643 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1645 case SI_TILE_MODE_DEPTH_STENCIL_2D:
1646 tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1651 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
1653 /* level0 and first mipmap need to have alignment */
1654 offset = surf->bo_size;
1656 offset = ALIGN(offset, surf->bo_alignment);
1658 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1659 if (surf->level == level) {
1660 surf->tiling_index[i] = tile_mode;
1661 /* it's ok because stencil is done after */
1662 surf->stencil_tiling_index[i] = tile_mode;
1664 surf->stencil_tiling_index[i] = tile_mode;
1671 static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
1672 struct radeon_surface *surf,
1673 unsigned tile_mode, unsigned stencil_tile_mode)
1675 unsigned num_pipes, num_banks;
1676 uint32_t gb_tile_mode;
1679 /* retrieve tiling mode value */
1680 gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1681 si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
1683 r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
1688 if (surf->flags & RADEON_SURF_SBUFFER) {
1689 r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0);
1690 surf->stencil_offset = surf->stencil_level[0].offset;
1695 static int si_surface_init(struct radeon_surface_manager *surf_man,
1696 struct radeon_surface *surf)
1698 unsigned mode, tile_mode, stencil_tile_mode;
1701 /* MSAA surfaces support the 2D mode only. */
1702 if (surf->nsamples > 1) {
1703 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1704 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1708 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1710 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1711 /* zbuffer only support 1D or 2D tiled surface */
1713 case RADEON_SURF_MODE_1D:
1714 case RADEON_SURF_MODE_2D:
1717 mode = RADEON_SURF_MODE_1D;
1718 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1719 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1724 r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1729 surf->stencil_offset = 0;
1730 surf->bo_alignment = 0;
1732 /* check tiling mode */
1734 case RADEON_SURF_MODE_LINEAR:
1735 r = r6_surface_init_linear(surf_man, surf, 0, 0);
1737 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1738 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
1740 case RADEON_SURF_MODE_1D:
1741 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1743 case RADEON_SURF_MODE_2D:
1744 r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1753 * depending on surface
1755 static int si_surface_best(struct radeon_surface_manager *surf_man,
1756 struct radeon_surface *surf)
1758 unsigned mode, tile_mode, stencil_tile_mode;
1761 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1763 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
1764 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
1765 /* depth/stencil force 1d tiling for old mesa */
1766 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1767 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1770 return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1774 /* ===========================================================================
1777 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
1779 struct radeon_surface_manager *surf_man;
1781 surf_man = calloc(1, sizeof(struct radeon_surface_manager));
1782 if (surf_man == NULL) {
1786 if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
1789 if (radeon_get_family(surf_man)) {
1793 if (surf_man->family <= CHIP_RV740) {
1794 if (r6_init_hw_info(surf_man)) {
1797 surf_man->surface_init = &r6_surface_init;
1798 surf_man->surface_best = &r6_surface_best;
1799 } else if (surf_man->family <= CHIP_ARUBA) {
1800 if (eg_init_hw_info(surf_man)) {
1803 surf_man->surface_init = &eg_surface_init;
1804 surf_man->surface_best = &eg_surface_best;
1806 if (si_init_hw_info(surf_man)) {
1809 surf_man->surface_init = &si_surface_init;
1810 surf_man->surface_best = &si_surface_best;
1819 void radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
1824 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
1825 struct radeon_surface *surf,
1829 if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
1833 /* all dimension must be at least 1 ! */
1834 if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
1837 if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
1840 if (!surf->array_size) {
1843 /* array size must be a power of 2 */
1844 surf->array_size = next_power_of_two(surf->array_size);
1846 switch (surf->nsamples) {
1857 case RADEON_SURF_TYPE_1D:
1858 if (surf->npix_y > 1) {
1861 case RADEON_SURF_TYPE_2D:
1862 if (surf->npix_z > 1) {
1866 case RADEON_SURF_TYPE_CUBEMAP:
1867 if (surf->npix_z > 1) {
1870 /* deal with cubemap as they were texture array */
1871 if (surf_man->family >= CHIP_RV770) {
1872 surf->array_size = 8;
1874 surf->array_size = 6;
1877 case RADEON_SURF_TYPE_3D:
1879 case RADEON_SURF_TYPE_1D_ARRAY:
1880 if (surf->npix_y > 1) {
1883 case RADEON_SURF_TYPE_2D_ARRAY:
1891 int radeon_surface_init(struct radeon_surface_manager *surf_man,
1892 struct radeon_surface *surf)
1894 unsigned mode, type;
1897 type = RADEON_SURF_GET(surf->flags, TYPE);
1898 mode = RADEON_SURF_GET(surf->flags, MODE);
1900 r = radeon_surface_sanity(surf_man, surf, type, mode);
1904 return surf_man->surface_init(surf_man, surf);
1907 int radeon_surface_best(struct radeon_surface_manager *surf_man,
1908 struct radeon_surface *surf)
1910 unsigned mode, type;
1913 type = RADEON_SURF_GET(surf->flags, TYPE);
1914 mode = RADEON_SURF_GET(surf->flags, MODE);
1916 r = radeon_surface_sanity(surf_man, surf, type, mode);
1920 return surf_man->surface_best(surf_man, surf);