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>
36 #include <sys/ioctl.h>
39 #include "radeon_drm.h"
40 #include "radeon_surface.h"
42 #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
43 #define MAX2(A, B) ((A) > (B) ? (A) : (B))
44 #define MIN2(A, B) ((A) < (B) ? (A) : (B))
46 /* keep this private */
86 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
87 struct radeon_surface *surf);
88 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
89 struct radeon_surface *surf);
91 struct radeon_hw_info {
100 uint32_t tile_mode_array[32];
102 uint32_t macrotile_mode_array[16];
105 struct radeon_surface_manager {
108 struct radeon_hw_info hw_info;
110 hw_init_surface_t surface_init;
111 hw_best_surface_t surface_best;
115 static int radeon_get_value(int fd, unsigned req, uint32_t *value)
117 struct drm_radeon_info info = {};
122 info.value = (uintptr_t)value;
123 r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
124 sizeof(struct drm_radeon_info));
128 static int radeon_get_family(struct radeon_surface_manager *surf_man)
130 switch (surf_man->device_id) {
131 #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
132 #include "r600_pci_ids.h"
140 static unsigned next_power_of_two(unsigned x)
145 return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
148 static unsigned mip_minify(unsigned size, unsigned level)
152 val = MAX2(1, size >> level);
154 val = next_power_of_two(val);
158 static void surf_minify(struct radeon_surface *surf,
159 struct radeon_surface_level *surflevel,
160 unsigned bpe, unsigned level,
161 uint32_t xalign, uint32_t yalign, uint32_t zalign,
164 surflevel->npix_x = mip_minify(surf->npix_x, level);
165 surflevel->npix_y = mip_minify(surf->npix_y, level);
166 surflevel->npix_z = mip_minify(surf->npix_z, level);
167 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
168 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
169 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
170 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
171 !(surf->flags & RADEON_SURF_FMASK)) {
172 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
173 surflevel->mode = RADEON_SURF_MODE_1D;
177 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
178 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
179 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
181 surflevel->offset = offset;
182 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
183 surflevel->slice_size = surflevel->pitch_bytes * surflevel->nblk_y;
185 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
188 /* ===========================================================================
191 static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
193 uint32_t tiling_config;
194 drmVersionPtr version;
197 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
203 surf_man->hw_info.allow_2d = 0;
204 version = drmGetVersion(surf_man->fd);
205 if (version && version->version_minor >= 14) {
206 surf_man->hw_info.allow_2d = 1;
208 drmFreeVersion(version);
210 switch ((tiling_config & 0xe) >> 1) {
212 surf_man->hw_info.num_pipes = 1;
215 surf_man->hw_info.num_pipes = 2;
218 surf_man->hw_info.num_pipes = 4;
221 surf_man->hw_info.num_pipes = 8;
224 surf_man->hw_info.num_pipes = 8;
225 surf_man->hw_info.allow_2d = 0;
229 switch ((tiling_config & 0x30) >> 4) {
231 surf_man->hw_info.num_banks = 4;
234 surf_man->hw_info.num_banks = 8;
237 surf_man->hw_info.num_banks = 8;
238 surf_man->hw_info.allow_2d = 0;
242 switch ((tiling_config & 0xc0) >> 6) {
244 surf_man->hw_info.group_bytes = 256;
247 surf_man->hw_info.group_bytes = 512;
250 surf_man->hw_info.group_bytes = 256;
251 surf_man->hw_info.allow_2d = 0;
257 static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
258 struct radeon_surface *surf,
259 uint64_t offset, unsigned start_level)
261 uint32_t xalign, yalign, zalign;
264 /* compute alignment */
266 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
268 /* the 32 alignment is for scanout, cb or db but to allow texture to be
269 * easily bound as such we force this alignment to all surface
271 xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
274 if (surf->flags & RADEON_SURF_SCANOUT) {
275 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
278 /* build mipmap tree */
279 for (i = start_level; i <= surf->last_level; i++) {
280 surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
281 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
282 /* level0 and first mipmap need to have alignment */
283 offset = surf->bo_size;
285 offset = ALIGN(offset, surf->bo_alignment);
291 static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
292 struct radeon_surface *surf,
293 uint64_t offset, unsigned start_level)
295 uint32_t xalign, yalign, zalign;
298 /* compute alignment */
300 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
302 xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
306 /* build mipmap tree */
307 for (i = start_level; i <= surf->last_level; i++) {
308 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
309 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
310 /* level0 and first mipmap need to have alignment */
311 offset = surf->bo_size;
313 offset = ALIGN(offset, surf->bo_alignment);
319 static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
320 struct radeon_surface *surf,
321 uint64_t offset, unsigned start_level)
323 uint32_t xalign, yalign, zalign, tilew;
326 /* compute alignment */
328 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
329 xalign = MAX2(tilew, xalign);
332 if (surf->flags & RADEON_SURF_SCANOUT) {
333 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
336 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
339 /* build mipmap tree */
340 for (i = start_level; i <= surf->last_level; i++) {
341 surf->level[i].mode = RADEON_SURF_MODE_1D;
342 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
343 /* level0 and first mipmap need to have alignment */
344 offset = surf->bo_size;
346 offset = ALIGN(offset, surf->bo_alignment);
352 static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
353 struct radeon_surface *surf,
354 uint64_t offset, unsigned start_level)
356 uint32_t xalign, yalign, zalign, tilew;
359 /* compute alignment */
362 xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
363 (tilew * surf->bpe * surf->nsamples);
364 xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
365 yalign = tilew * surf_man->hw_info.num_pipes;
366 if (surf->flags & RADEON_SURF_SCANOUT) {
367 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
371 MAX2(surf_man->hw_info.num_pipes *
372 surf_man->hw_info.num_banks *
373 surf->nsamples * surf->bpe * 64,
374 xalign * yalign * surf->nsamples * surf->bpe);
377 /* build mipmap tree */
378 for (i = start_level; i <= surf->last_level; i++) {
379 surf->level[i].mode = RADEON_SURF_MODE_2D;
380 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
381 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
382 return r6_surface_init_1d(surf_man, surf, offset, i);
384 /* level0 and first mipmap need to have alignment */
385 offset = surf->bo_size;
387 offset = ALIGN(offset, surf->bo_alignment);
393 static int r6_surface_init(struct radeon_surface_manager *surf_man,
394 struct radeon_surface *surf)
399 /* MSAA surfaces support the 2D mode only. */
400 if (surf->nsamples > 1) {
401 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
402 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
406 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
408 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
409 /* zbuffer only support 1D or 2D tiled surface */
411 case RADEON_SURF_MODE_1D:
412 case RADEON_SURF_MODE_2D:
415 mode = RADEON_SURF_MODE_1D;
416 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
417 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
422 /* force 1d on kernel that can't do 2d */
423 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
424 if (surf->nsamples > 1) {
425 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
428 mode = RADEON_SURF_MODE_1D;
429 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
430 surf->flags |= RADEON_SURF_SET(mode, MODE);
433 /* check surface dimension */
434 if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
438 /* check mipmap last_level */
439 if (surf->last_level > 14) {
443 /* check tiling mode */
445 case RADEON_SURF_MODE_LINEAR:
446 r = r6_surface_init_linear(surf_man, surf, 0, 0);
448 case RADEON_SURF_MODE_LINEAR_ALIGNED:
449 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
451 case RADEON_SURF_MODE_1D:
452 r = r6_surface_init_1d(surf_man, surf, 0, 0);
454 case RADEON_SURF_MODE_2D:
455 r = r6_surface_init_2d(surf_man, surf, 0, 0);
463 static int r6_surface_best(struct radeon_surface_manager *surf_man,
464 struct radeon_surface *surf)
466 /* no value to optimize for r6xx/r7xx */
471 /* ===========================================================================
474 static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
476 uint32_t tiling_config;
477 drmVersionPtr version;
480 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
486 surf_man->hw_info.allow_2d = 0;
487 version = drmGetVersion(surf_man->fd);
488 if (version && version->version_minor >= 16) {
489 surf_man->hw_info.allow_2d = 1;
491 drmFreeVersion(version);
493 switch (tiling_config & 0xf) {
495 surf_man->hw_info.num_pipes = 1;
498 surf_man->hw_info.num_pipes = 2;
501 surf_man->hw_info.num_pipes = 4;
504 surf_man->hw_info.num_pipes = 8;
507 surf_man->hw_info.num_pipes = 8;
508 surf_man->hw_info.allow_2d = 0;
512 switch ((tiling_config & 0xf0) >> 4) {
514 surf_man->hw_info.num_banks = 4;
517 surf_man->hw_info.num_banks = 8;
520 surf_man->hw_info.num_banks = 16;
523 surf_man->hw_info.num_banks = 8;
524 surf_man->hw_info.allow_2d = 0;
528 switch ((tiling_config & 0xf00) >> 8) {
530 surf_man->hw_info.group_bytes = 256;
533 surf_man->hw_info.group_bytes = 512;
536 surf_man->hw_info.group_bytes = 256;
537 surf_man->hw_info.allow_2d = 0;
541 switch ((tiling_config & 0xf000) >> 12) {
543 surf_man->hw_info.row_size = 1024;
546 surf_man->hw_info.row_size = 2048;
549 surf_man->hw_info.row_size = 4096;
552 surf_man->hw_info.row_size = 4096;
553 surf_man->hw_info.allow_2d = 0;
559 static void eg_surf_minify(struct radeon_surface *surf,
560 struct radeon_surface_level *surflevel,
569 unsigned mtile_pr, mtile_ps;
571 surflevel->npix_x = mip_minify(surf->npix_x, level);
572 surflevel->npix_y = mip_minify(surf->npix_y, level);
573 surflevel->npix_z = mip_minify(surf->npix_z, level);
574 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
575 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
576 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
577 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
578 !(surf->flags & RADEON_SURF_FMASK)) {
579 if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
580 surflevel->mode = RADEON_SURF_MODE_1D;
584 surflevel->nblk_x = ALIGN(surflevel->nblk_x, mtilew);
585 surflevel->nblk_y = ALIGN(surflevel->nblk_y, mtileh);
586 surflevel->nblk_z = ALIGN(surflevel->nblk_z, 1);
588 /* macro tile per row */
589 mtile_pr = surflevel->nblk_x / mtilew;
590 /* macro tile per slice */
591 mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
593 surflevel->offset = offset;
594 surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
595 surflevel->slice_size = mtile_ps * mtileb * slice_pt;
597 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
600 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
601 struct radeon_surface *surf,
602 struct radeon_surface_level *level,
604 uint64_t offset, unsigned start_level)
606 uint32_t xalign, yalign, zalign, tilew;
609 /* compute alignment */
611 xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
612 xalign = MAX2(tilew, xalign);
615 if (surf->flags & RADEON_SURF_SCANOUT) {
616 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
620 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
621 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
624 offset = ALIGN(offset, alignment);
628 /* build mipmap tree */
629 for (i = start_level; i <= surf->last_level; i++) {
630 level[i].mode = RADEON_SURF_MODE_1D;
631 surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
632 /* level0 and first mipmap need to have alignment */
633 offset = surf->bo_size;
635 offset = ALIGN(offset, surf->bo_alignment);
641 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
642 struct radeon_surface *surf,
643 struct radeon_surface_level *level,
644 unsigned bpe, unsigned tile_split,
645 uint64_t offset, unsigned start_level)
647 unsigned tilew, tileh, tileb;
648 unsigned mtilew, mtileh, mtileb;
652 /* compute tile values */
655 tileb = tilew * tileh * bpe * surf->nsamples;
656 /* slices per tile */
658 if (tileb > tile_split) {
659 slice_pt = tileb / tile_split;
661 tileb = tileb / slice_pt;
663 /* macro tile width & height */
664 mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
665 mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
666 /* macro tile bytes */
667 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
670 unsigned alignment = MAX2(256, mtileb);
671 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
674 offset = ALIGN(offset, alignment);
678 /* build mipmap tree */
679 for (i = start_level; i <= surf->last_level; i++) {
680 level[i].mode = RADEON_SURF_MODE_2D;
681 eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
682 if (level[i].mode == RADEON_SURF_MODE_1D) {
683 return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
685 /* level0 and first mipmap need to have alignment */
686 offset = surf->bo_size;
688 offset = ALIGN(offset, surf->bo_alignment);
694 static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
695 struct radeon_surface *surf,
700 /* check surface dimension */
701 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
705 /* check mipmap last_level */
706 if (surf->last_level > 15) {
710 /* force 1d on kernel that can't do 2d */
711 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
712 if (surf->nsamples > 1) {
713 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
716 mode = RADEON_SURF_MODE_1D;
717 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
718 surf->flags |= RADEON_SURF_SET(mode, MODE);
721 /* check tile split */
722 if (mode == RADEON_SURF_MODE_2D) {
723 switch (surf->tile_split) {
735 switch (surf->mtilea) {
744 /* check aspect ratio */
745 if (surf_man->hw_info.num_banks < surf->mtilea) {
748 /* check bank width */
749 switch (surf->bankw) {
758 /* check bank height */
759 switch (surf->bankh) {
768 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
769 if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
777 static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
778 struct radeon_surface *surf)
780 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
781 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
782 /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
783 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
784 struct radeon_surface_level *stencil_level =
785 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
787 r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
791 if (is_depth_stencil) {
792 r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
794 surf->stencil_offset = stencil_level[0].offset;
799 static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
800 struct radeon_surface *surf)
802 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
803 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
804 /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
805 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
806 struct radeon_surface_level *stencil_level =
807 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
809 r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
810 surf->tile_split, 0, 0);
814 if (is_depth_stencil) {
815 r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
816 surf->stencil_tile_split, surf->bo_size, 0);
817 surf->stencil_offset = stencil_level[0].offset;
822 static int eg_surface_init(struct radeon_surface_manager *surf_man,
823 struct radeon_surface *surf)
828 /* MSAA surfaces support the 2D mode only. */
829 if (surf->nsamples > 1) {
830 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
831 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
835 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
837 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
838 /* zbuffer only support 1D or 2D tiled surface */
840 case RADEON_SURF_MODE_1D:
841 case RADEON_SURF_MODE_2D:
844 mode = RADEON_SURF_MODE_1D;
845 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
846 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
851 r = eg_surface_sanity(surf_man, surf, mode);
856 surf->stencil_offset = 0;
857 surf->bo_alignment = 0;
859 /* check tiling mode */
861 case RADEON_SURF_MODE_LINEAR:
862 r = r6_surface_init_linear(surf_man, surf, 0, 0);
864 case RADEON_SURF_MODE_LINEAR_ALIGNED:
865 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
867 case RADEON_SURF_MODE_1D:
868 r = eg_surface_init_1d_miptrees(surf_man, surf);
870 case RADEON_SURF_MODE_2D:
871 r = eg_surface_init_2d_miptrees(surf_man, surf);
879 static unsigned log2_int(unsigned x)
887 if ((unsigned)(1 << l) > x) {
894 /* compute best tile_split, bankw, bankh, mtilea
895 * depending on surface
897 static int eg_surface_best(struct radeon_surface_manager *surf_man,
898 struct radeon_surface *surf)
900 unsigned mode, tileb, h_over_w;
904 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
906 /* set some default value to avoid sanity check choking on them */
907 surf->tile_split = 1024;
910 surf->mtilea = surf_man->hw_info.num_banks;
911 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
912 for (; surf->bankh <= 8; surf->bankh *= 2) {
913 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
917 if (surf->mtilea > 8) {
921 r = eg_surface_sanity(surf_man, surf, mode);
926 if (mode != RADEON_SURF_MODE_2D) {
927 /* nothing to do for non 2D tiled surface */
931 /* Tweak TILE_SPLIT for performance here. */
932 if (surf->nsamples > 1) {
933 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
934 switch (surf->nsamples) {
936 surf->tile_split = 128;
939 surf->tile_split = 128;
942 surf->tile_split = 256;
944 case 16: /* cayman only */
945 surf->tile_split = 512;
948 fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
949 surf->nsamples, __LINE__);
952 surf->stencil_tile_split = 64;
954 /* tile split must be >= 256 for colorbuffer surfaces */
955 surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
956 if (surf->tile_split > 4096)
957 surf->tile_split = 4096;
960 /* set tile split to row size */
961 surf->tile_split = surf_man->hw_info.row_size;
962 surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
965 /* bankw or bankh greater than 1 increase alignment requirement, not
966 * sure if it's worth using smaller bankw & bankh to stick with 2D
967 * tiling on small surface rather than falling back to 1D tiling.
968 * Use recommanded value based on tile size for now.
970 * fmask buffer has different optimal value figure them out once we
973 if (surf->flags & RADEON_SURF_SBUFFER) {
974 /* assume 1 bytes for stencil, we optimize for stencil as stencil
975 * and depth shares surface values
977 tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
979 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
982 /* use bankw of 1 to minimize width alignment, might be interesting to
983 * increase it for large surface
998 /* double check the constraint */
999 for (; surf->bankh <= 8; surf->bankh *= 2) {
1000 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
1005 h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
1006 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
1007 surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
1013 /* ===========================================================================
1014 * Southern Islands family
1016 #define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
1017 #define SI__PIPE_CONFIG__ADDR_SURF_P2 0
1018 #define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
1019 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
1020 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
1021 #define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
1022 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
1023 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
1024 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
1025 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
1026 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
1027 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
1028 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
1029 #define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
1030 #define SI__TILE_SPLIT__64B 0
1031 #define SI__TILE_SPLIT__128B 1
1032 #define SI__TILE_SPLIT__256B 2
1033 #define SI__TILE_SPLIT__512B 3
1034 #define SI__TILE_SPLIT__1024B 4
1035 #define SI__TILE_SPLIT__2048B 5
1036 #define SI__TILE_SPLIT__4096B 6
1037 #define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3)
1038 #define SI__BANK_WIDTH__1 0
1039 #define SI__BANK_WIDTH__2 1
1040 #define SI__BANK_WIDTH__4 2
1041 #define SI__BANK_WIDTH__8 3
1042 #define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3)
1043 #define SI__BANK_HEIGHT__1 0
1044 #define SI__BANK_HEIGHT__2 1
1045 #define SI__BANK_HEIGHT__4 2
1046 #define SI__BANK_HEIGHT__8 3
1047 #define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3)
1048 #define SI__MACRO_TILE_ASPECT__1 0
1049 #define SI__MACRO_TILE_ASPECT__2 1
1050 #define SI__MACRO_TILE_ASPECT__4 2
1051 #define SI__MACRO_TILE_ASPECT__8 3
1052 #define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3)
1053 #define SI__NUM_BANKS__2_BANK 0
1054 #define SI__NUM_BANKS__4_BANK 1
1055 #define SI__NUM_BANKS__8_BANK 2
1056 #define SI__NUM_BANKS__16_BANK 3
1059 static void si_gb_tile_mode(uint32_t gb_tile_mode,
1060 unsigned *num_pipes,
1061 unsigned *num_banks,
1062 uint32_t *macro_tile_aspect,
1065 uint32_t *tile_split)
1068 switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1069 case SI__PIPE_CONFIG__ADDR_SURF_P2:
1073 case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1074 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1075 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1076 case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1079 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1080 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1081 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1082 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1083 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1084 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1085 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1091 switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
1093 case SI__NUM_BANKS__2_BANK:
1096 case SI__NUM_BANKS__4_BANK:
1099 case SI__NUM_BANKS__8_BANK:
1102 case SI__NUM_BANKS__16_BANK:
1107 if (macro_tile_aspect) {
1108 switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
1110 case SI__MACRO_TILE_ASPECT__1:
1111 *macro_tile_aspect = 1;
1113 case SI__MACRO_TILE_ASPECT__2:
1114 *macro_tile_aspect = 2;
1116 case SI__MACRO_TILE_ASPECT__4:
1117 *macro_tile_aspect = 4;
1119 case SI__MACRO_TILE_ASPECT__8:
1120 *macro_tile_aspect = 8;
1125 switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
1127 case SI__BANK_WIDTH__1:
1130 case SI__BANK_WIDTH__2:
1133 case SI__BANK_WIDTH__4:
1136 case SI__BANK_WIDTH__8:
1142 switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
1144 case SI__BANK_HEIGHT__1:
1147 case SI__BANK_HEIGHT__2:
1150 case SI__BANK_HEIGHT__4:
1153 case SI__BANK_HEIGHT__8:
1159 switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1161 case SI__TILE_SPLIT__64B:
1164 case SI__TILE_SPLIT__128B:
1167 case SI__TILE_SPLIT__256B:
1170 case SI__TILE_SPLIT__512B:
1173 case SI__TILE_SPLIT__1024B:
1176 case SI__TILE_SPLIT__2048B:
1179 case SI__TILE_SPLIT__4096B:
1186 static int si_init_hw_info(struct radeon_surface_manager *surf_man)
1188 uint32_t tiling_config;
1189 drmVersionPtr version;
1192 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
1198 surf_man->hw_info.allow_2d = 0;
1199 version = drmGetVersion(surf_man->fd);
1200 if (version && version->version_minor >= 33) {
1201 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
1202 surf_man->hw_info.allow_2d = 1;
1205 drmFreeVersion(version);
1207 switch (tiling_config & 0xf) {
1209 surf_man->hw_info.num_pipes = 1;
1212 surf_man->hw_info.num_pipes = 2;
1215 surf_man->hw_info.num_pipes = 4;
1218 surf_man->hw_info.num_pipes = 8;
1221 surf_man->hw_info.num_pipes = 8;
1222 surf_man->hw_info.allow_2d = 0;
1226 switch ((tiling_config & 0xf0) >> 4) {
1228 surf_man->hw_info.num_banks = 4;
1231 surf_man->hw_info.num_banks = 8;
1234 surf_man->hw_info.num_banks = 16;
1237 surf_man->hw_info.num_banks = 8;
1238 surf_man->hw_info.allow_2d = 0;
1242 switch ((tiling_config & 0xf00) >> 8) {
1244 surf_man->hw_info.group_bytes = 256;
1247 surf_man->hw_info.group_bytes = 512;
1250 surf_man->hw_info.group_bytes = 256;
1251 surf_man->hw_info.allow_2d = 0;
1255 switch ((tiling_config & 0xf000) >> 12) {
1257 surf_man->hw_info.row_size = 1024;
1260 surf_man->hw_info.row_size = 2048;
1263 surf_man->hw_info.row_size = 4096;
1266 surf_man->hw_info.row_size = 4096;
1267 surf_man->hw_info.allow_2d = 0;
1273 static int si_surface_sanity(struct radeon_surface_manager *surf_man,
1274 struct radeon_surface *surf,
1275 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
1277 uint32_t gb_tile_mode;
1279 /* check surface dimension */
1280 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
1284 /* check mipmap last_level */
1285 if (surf->last_level > 15) {
1289 /* force 1d on kernel that can't do 2d */
1290 if (mode > RADEON_SURF_MODE_1D &&
1291 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
1292 if (surf->nsamples > 1) {
1293 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
1296 mode = RADEON_SURF_MODE_1D;
1297 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1298 surf->flags |= RADEON_SURF_SET(mode, MODE);
1301 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
1305 if (!surf->tile_split) {
1310 surf->tile_split = 64;
1311 surf->stencil_tile_split = 64;
1315 case RADEON_SURF_MODE_2D:
1316 if (surf->flags & RADEON_SURF_SBUFFER) {
1317 switch (surf->nsamples) {
1319 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1322 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1325 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1328 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1333 /* retrieve tiling mode value */
1334 gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
1335 si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
1337 if (surf->flags & RADEON_SURF_ZBUFFER) {
1338 switch (surf->nsamples) {
1340 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1343 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1346 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1349 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1354 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1355 switch (surf->bpe) {
1357 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
1360 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
1366 switch (surf->bpe) {
1368 *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
1371 *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
1374 *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
1378 *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
1384 /* retrieve tiling mode value */
1385 gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
1386 si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
1388 case RADEON_SURF_MODE_1D:
1389 if (surf->flags & RADEON_SURF_SBUFFER) {
1390 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1392 if (surf->flags & RADEON_SURF_ZBUFFER) {
1393 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1394 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1395 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1397 *tile_mode = SI_TILE_MODE_COLOR_1D;
1400 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1402 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
1408 static void si_surf_minify(struct radeon_surface *surf,
1409 struct radeon_surface_level *surflevel,
1410 unsigned bpe, unsigned level,
1411 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1412 uint32_t slice_align, unsigned offset)
1415 surflevel->npix_x = surf->npix_x;
1417 surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1419 surflevel->npix_y = mip_minify(surf->npix_y, level);
1420 surflevel->npix_z = mip_minify(surf->npix_z, level);
1422 if (level == 0 && surf->last_level > 0) {
1423 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1424 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1425 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1427 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1428 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1429 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1432 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1434 /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1435 * these are just guesses for the rules behind those
1437 if (level == 0 && surf->last_level == 0)
1438 /* Non-mipmap pitch padded to slice alignment */
1439 /* Using just bpe here breaks stencil blitting; surf->bpe works. */
1440 xalign = MAX2(xalign, slice_align / surf->bpe);
1441 else if (surflevel->mode == RADEON_SURF_MODE_LINEAR_ALIGNED)
1442 /* Small rows evenly distributed across slice */
1443 xalign = MAX2(xalign, slice_align / bpe / surflevel->nblk_y);
1445 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1446 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1448 surflevel->offset = offset;
1449 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
1450 surflevel->slice_size = ALIGN(surflevel->pitch_bytes * surflevel->nblk_y, slice_align);
1452 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1455 static void si_surf_minify_2d(struct radeon_surface *surf,
1456 struct radeon_surface_level *surflevel,
1457 unsigned bpe, unsigned level, unsigned slice_pt,
1458 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1459 unsigned mtileb, unsigned offset)
1461 unsigned mtile_pr, mtile_ps;
1464 surflevel->npix_x = surf->npix_x;
1466 surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1468 surflevel->npix_y = mip_minify(surf->npix_y, level);
1469 surflevel->npix_z = mip_minify(surf->npix_z, level);
1471 if (level == 0 && surf->last_level > 0) {
1472 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1473 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1474 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1476 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1477 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1478 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1481 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
1482 !(surf->flags & RADEON_SURF_FMASK)) {
1483 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
1484 surflevel->mode = RADEON_SURF_MODE_1D;
1488 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1489 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1490 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1492 /* macro tile per row */
1493 mtile_pr = surflevel->nblk_x / xalign;
1494 /* macro tile per slice */
1495 mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
1496 surflevel->offset = offset;
1497 surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
1498 surflevel->slice_size = mtile_ps * mtileb * slice_pt;
1500 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1503 static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1504 struct radeon_surface *surf,
1506 uint64_t offset, unsigned start_level)
1508 uint32_t xalign, yalign, zalign, slice_align;
1511 /* compute alignment */
1513 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1515 xalign = MAX2(8, 64 / surf->bpe);
1518 slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1520 /* build mipmap tree */
1521 for (i = start_level; i <= surf->last_level; i++) {
1522 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1523 si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
1524 /* level0 and first mipmap need to have alignment */
1525 offset = surf->bo_size;
1527 offset = ALIGN(offset, surf->bo_alignment);
1529 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1530 surf->tiling_index[i] = tile_mode;
1536 static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1537 struct radeon_surface *surf,
1538 struct radeon_surface_level *level,
1539 unsigned bpe, unsigned tile_mode,
1540 uint64_t offset, unsigned start_level)
1542 uint32_t xalign, yalign, zalign, slice_align;
1543 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
1546 /* compute alignment */
1550 slice_align = surf_man->hw_info.group_bytes;
1551 if (surf->flags & RADEON_SURF_SCANOUT) {
1552 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1555 if (start_level <= 1) {
1556 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1559 offset = ALIGN(offset, alignment);
1563 /* build mipmap tree */
1564 for (i = start_level; i <= surf->last_level; i++) {
1565 level[i].mode = RADEON_SURF_MODE_1D;
1566 si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1567 /* level0 and first mipmap need to have alignment */
1568 offset = surf->bo_size;
1570 offset = ALIGN(offset, alignment);
1572 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1573 if (surf->level == level) {
1574 surf->tiling_index[i] = tile_mode;
1575 /* it's ok because stencil is done after */
1576 surf->stencil_tiling_index[i] = tile_mode;
1578 surf->stencil_tiling_index[i] = tile_mode;
1585 static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1586 struct radeon_surface *surf,
1587 unsigned tile_mode, unsigned stencil_tile_mode)
1591 r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
1596 if (surf->flags & RADEON_SURF_SBUFFER) {
1597 r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
1598 surf->stencil_offset = surf->stencil_level[0].offset;
1603 static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
1604 struct radeon_surface *surf,
1605 struct radeon_surface_level *level,
1606 unsigned bpe, unsigned tile_mode,
1607 unsigned num_pipes, unsigned num_banks,
1608 unsigned tile_split,
1610 unsigned start_level)
1612 uint64_t aligned_offset = offset;
1613 unsigned tilew, tileh, tileb;
1614 unsigned mtilew, mtileh, mtileb;
1618 /* compute tile values */
1621 tileb = tilew * tileh * bpe * surf->nsamples;
1622 /* slices per tile */
1624 if (tileb > tile_split) {
1625 slice_pt = tileb / tile_split;
1627 tileb = tileb / slice_pt;
1629 /* macro tile width & height */
1630 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
1631 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
1633 /* macro tile bytes */
1634 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
1636 if (start_level <= 1) {
1637 unsigned alignment = MAX2(256, mtileb);
1638 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1640 if (aligned_offset) {
1641 aligned_offset = ALIGN(aligned_offset, alignment);
1645 /* build mipmap tree */
1646 for (i = start_level; i <= surf->last_level; i++) {
1647 level[i].mode = RADEON_SURF_MODE_2D;
1648 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
1649 if (level[i].mode == RADEON_SURF_MODE_1D) {
1650 switch (tile_mode) {
1651 case SI_TILE_MODE_COLOR_2D_8BPP:
1652 case SI_TILE_MODE_COLOR_2D_16BPP:
1653 case SI_TILE_MODE_COLOR_2D_32BPP:
1654 case SI_TILE_MODE_COLOR_2D_64BPP:
1655 tile_mode = SI_TILE_MODE_COLOR_1D;
1657 case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
1658 case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
1659 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1661 case SI_TILE_MODE_DEPTH_STENCIL_2D:
1662 tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1667 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
1669 /* level0 and first mipmap need to have alignment */
1670 aligned_offset = surf->bo_size;
1672 aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
1674 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1675 if (surf->level == level) {
1676 surf->tiling_index[i] = tile_mode;
1677 /* it's ok because stencil is done after */
1678 surf->stencil_tiling_index[i] = tile_mode;
1680 surf->stencil_tiling_index[i] = tile_mode;
1687 static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
1688 struct radeon_surface *surf,
1689 unsigned tile_mode, unsigned stencil_tile_mode)
1691 unsigned num_pipes, num_banks;
1692 uint32_t gb_tile_mode;
1695 /* retrieve tiling mode value */
1696 gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1697 si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
1699 r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
1704 if (surf->flags & RADEON_SURF_SBUFFER) {
1705 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);
1706 surf->stencil_offset = surf->stencil_level[0].offset;
1711 static int si_surface_init(struct radeon_surface_manager *surf_man,
1712 struct radeon_surface *surf)
1714 unsigned mode, tile_mode, stencil_tile_mode;
1717 /* MSAA surfaces support the 2D mode only. */
1718 if (surf->nsamples > 1) {
1719 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1720 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1724 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1726 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1727 /* zbuffer only support 1D or 2D tiled surface */
1729 case RADEON_SURF_MODE_1D:
1730 case RADEON_SURF_MODE_2D:
1733 mode = RADEON_SURF_MODE_1D;
1734 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1735 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1740 r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1745 surf->stencil_offset = 0;
1746 surf->bo_alignment = 0;
1748 /* check tiling mode */
1750 case RADEON_SURF_MODE_LINEAR:
1751 r = r6_surface_init_linear(surf_man, surf, 0, 0);
1753 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1754 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
1756 case RADEON_SURF_MODE_1D:
1757 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1759 case RADEON_SURF_MODE_2D:
1760 r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1769 * depending on surface
1771 static int si_surface_best(struct radeon_surface_manager *surf_man,
1772 struct radeon_surface *surf)
1774 unsigned mode, tile_mode, stencil_tile_mode;
1777 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1779 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
1780 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
1781 /* depth/stencil force 1d tiling for old mesa */
1782 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1783 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1786 return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1790 /* ===========================================================================
1791 * Sea Islands family
1793 #define CIK__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
1794 #define CIK__PIPE_CONFIG__ADDR_SURF_P2 0
1795 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
1796 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
1797 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
1798 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
1799 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
1800 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
1801 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
1802 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
1803 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
1804 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
1805 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
1806 #define CIK__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
1807 #define CIK__TILE_SPLIT__64B 0
1808 #define CIK__TILE_SPLIT__128B 1
1809 #define CIK__TILE_SPLIT__256B 2
1810 #define CIK__TILE_SPLIT__512B 3
1811 #define CIK__TILE_SPLIT__1024B 4
1812 #define CIK__TILE_SPLIT__2048B 5
1813 #define CIK__TILE_SPLIT__4096B 6
1814 #define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x) (((x) >> 25) & 0x3)
1815 #define CIK__SAMPLE_SPLIT__1 0
1816 #define CIK__SAMPLE_SPLIT__2 1
1817 #define CIK__SAMPLE_SPLIT__4 2
1818 #define CIK__SAMPLE_SPLIT__8 3
1819 #define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x) ((x) & 0x3)
1820 #define CIK__BANK_WIDTH__1 0
1821 #define CIK__BANK_WIDTH__2 1
1822 #define CIK__BANK_WIDTH__4 2
1823 #define CIK__BANK_WIDTH__8 3
1824 #define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x) (((x) >> 2) & 0x3)
1825 #define CIK__BANK_HEIGHT__1 0
1826 #define CIK__BANK_HEIGHT__2 1
1827 #define CIK__BANK_HEIGHT__4 2
1828 #define CIK__BANK_HEIGHT__8 3
1829 #define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3)
1830 #define CIK__MACRO_TILE_ASPECT__1 0
1831 #define CIK__MACRO_TILE_ASPECT__2 1
1832 #define CIK__MACRO_TILE_ASPECT__4 2
1833 #define CIK__MACRO_TILE_ASPECT__8 3
1834 #define CIK__GB_MACROTILE_MODE__NUM_BANKS(x) (((x) >> 6) & 0x3)
1835 #define CIK__NUM_BANKS__2_BANK 0
1836 #define CIK__NUM_BANKS__4_BANK 1
1837 #define CIK__NUM_BANKS__8_BANK 2
1838 #define CIK__NUM_BANKS__16_BANK 3
1841 static void cik_get_2d_params(struct radeon_surface_manager *surf_man,
1842 unsigned bpe, unsigned nsamples, bool is_color,
1844 uint32_t *num_pipes,
1845 uint32_t *tile_split_ptr,
1846 uint32_t *num_banks,
1847 uint32_t *macro_tile_aspect,
1851 uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1852 unsigned tileb_1x, tileb;
1853 unsigned gb_macrotile_mode;
1854 unsigned macrotile_index;
1855 unsigned tile_split, sample_split;
1858 switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1859 case CIK__PIPE_CONFIG__ADDR_SURF_P2:
1863 case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1864 case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1865 case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1866 case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1869 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1870 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1871 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1872 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1873 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1874 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1875 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1880 switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1882 case CIK__TILE_SPLIT__64B:
1885 case CIK__TILE_SPLIT__128B:
1888 case CIK__TILE_SPLIT__256B:
1891 case CIK__TILE_SPLIT__512B:
1894 case CIK__TILE_SPLIT__1024B:
1897 case CIK__TILE_SPLIT__2048B:
1900 case CIK__TILE_SPLIT__4096B:
1904 switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) {
1906 case CIK__SAMPLE_SPLIT__1:
1909 case CIK__SAMPLE_SPLIT__2:
1912 case CIK__SAMPLE_SPLIT__4:
1915 case CIK__SAMPLE_SPLIT__8:
1920 /* Adjust the tile split. */
1921 tileb_1x = 8 * 8 * bpe;
1923 tile_split = MAX2(256, sample_split * tileb_1x);
1925 tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
1927 /* Determine the macrotile index. */
1928 tileb = MIN2(tile_split, nsamples * tileb_1x);
1930 for (macrotile_index = 0; tileb > 64; macrotile_index++) {
1933 gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index];
1935 if (tile_split_ptr) {
1936 *tile_split_ptr = tile_split;
1939 switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) {
1941 case CIK__NUM_BANKS__2_BANK:
1944 case CIK__NUM_BANKS__4_BANK:
1947 case CIK__NUM_BANKS__8_BANK:
1950 case CIK__NUM_BANKS__16_BANK:
1955 if (macro_tile_aspect) {
1956 switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) {
1958 case CIK__MACRO_TILE_ASPECT__1:
1959 *macro_tile_aspect = 1;
1961 case CIK__MACRO_TILE_ASPECT__2:
1962 *macro_tile_aspect = 2;
1964 case CIK__MACRO_TILE_ASPECT__4:
1965 *macro_tile_aspect = 4;
1967 case CIK__MACRO_TILE_ASPECT__8:
1968 *macro_tile_aspect = 8;
1973 switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) {
1975 case CIK__BANK_WIDTH__1:
1978 case CIK__BANK_WIDTH__2:
1981 case CIK__BANK_WIDTH__4:
1984 case CIK__BANK_WIDTH__8:
1990 switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) {
1992 case CIK__BANK_HEIGHT__1:
1995 case CIK__BANK_HEIGHT__2:
1998 case CIK__BANK_HEIGHT__4:
2001 case CIK__BANK_HEIGHT__8:
2008 static int cik_init_hw_info(struct radeon_surface_manager *surf_man)
2010 uint32_t tiling_config;
2011 drmVersionPtr version;
2014 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
2020 surf_man->hw_info.allow_2d = 0;
2021 version = drmGetVersion(surf_man->fd);
2022 if (version && version->version_minor >= 35) {
2023 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) &&
2024 !radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_mode_array)) {
2025 surf_man->hw_info.allow_2d = 1;
2028 drmFreeVersion(version);
2030 switch (tiling_config & 0xf) {
2032 surf_man->hw_info.num_pipes = 1;
2035 surf_man->hw_info.num_pipes = 2;
2038 surf_man->hw_info.num_pipes = 4;
2041 surf_man->hw_info.num_pipes = 8;
2044 surf_man->hw_info.num_pipes = 8;
2045 surf_man->hw_info.allow_2d = 0;
2049 switch ((tiling_config & 0xf0) >> 4) {
2051 surf_man->hw_info.num_banks = 4;
2054 surf_man->hw_info.num_banks = 8;
2057 surf_man->hw_info.num_banks = 16;
2060 surf_man->hw_info.num_banks = 8;
2061 surf_man->hw_info.allow_2d = 0;
2065 switch ((tiling_config & 0xf00) >> 8) {
2067 surf_man->hw_info.group_bytes = 256;
2070 surf_man->hw_info.group_bytes = 512;
2073 surf_man->hw_info.group_bytes = 256;
2074 surf_man->hw_info.allow_2d = 0;
2078 switch ((tiling_config & 0xf000) >> 12) {
2080 surf_man->hw_info.row_size = 1024;
2083 surf_man->hw_info.row_size = 2048;
2086 surf_man->hw_info.row_size = 4096;
2089 surf_man->hw_info.row_size = 4096;
2090 surf_man->hw_info.allow_2d = 0;
2096 static int cik_surface_sanity(struct radeon_surface_manager *surf_man,
2097 struct radeon_surface *surf,
2098 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
2100 /* check surface dimension */
2101 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
2105 /* check mipmap last_level */
2106 if (surf->last_level > 15) {
2110 /* force 1d on kernel that can't do 2d */
2111 if (mode > RADEON_SURF_MODE_1D &&
2112 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
2113 if (surf->nsamples > 1) {
2114 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
2117 mode = RADEON_SURF_MODE_1D;
2118 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2119 surf->flags |= RADEON_SURF_SET(mode, MODE);
2122 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
2126 if (!surf->tile_split) {
2131 surf->tile_split = 64;
2132 surf->stencil_tile_split = 64;
2136 case RADEON_SURF_MODE_2D: {
2137 if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) {
2138 switch (surf->nsamples) {
2140 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64;
2144 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128;
2147 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256;
2153 if (surf->flags & RADEON_SURF_SBUFFER) {
2154 *stencil_tile_mode = *tile_mode;
2156 cik_get_2d_params(surf_man, 1, surf->nsamples, false,
2157 *stencil_tile_mode, NULL,
2158 &surf->stencil_tile_split,
2159 NULL, NULL, NULL, NULL);
2161 } else if (surf->flags & RADEON_SURF_SCANOUT) {
2162 *tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT;
2164 *tile_mode = CIK_TILE_MODE_COLOR_2D;
2167 /* retrieve tiling mode values */
2168 cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2169 !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode,
2170 NULL, &surf->tile_split, NULL, &surf->mtilea,
2171 &surf->bankw, &surf->bankh);
2174 case RADEON_SURF_MODE_1D:
2175 if (surf->flags & RADEON_SURF_SBUFFER) {
2176 *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2178 if (surf->flags & RADEON_SURF_ZBUFFER) {
2179 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2180 } else if (surf->flags & RADEON_SURF_SCANOUT) {
2181 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2183 *tile_mode = SI_TILE_MODE_COLOR_1D;
2186 case RADEON_SURF_MODE_LINEAR_ALIGNED:
2188 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
2194 static int cik_surface_init_2d(struct radeon_surface_manager *surf_man,
2195 struct radeon_surface *surf,
2196 struct radeon_surface_level *level,
2197 unsigned bpe, unsigned tile_mode,
2198 unsigned tile_split,
2199 unsigned num_pipes, unsigned num_banks,
2201 unsigned start_level)
2203 uint64_t aligned_offset = offset;
2204 unsigned tilew, tileh, tileb_1x, tileb;
2205 unsigned mtilew, mtileh, mtileb;
2209 /* compute tile values */
2212 tileb_1x = tilew * tileh * bpe;
2214 tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
2216 tileb = surf->nsamples * tileb_1x;
2218 /* slices per tile */
2220 if (tileb > tile_split) {
2221 slice_pt = tileb / tile_split;
2222 tileb = tileb / slice_pt;
2225 /* macro tile width & height */
2226 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
2227 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
2229 /* macro tile bytes */
2230 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
2232 if (start_level <= 1) {
2233 unsigned alignment = MAX2(256, mtileb);
2234 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
2236 if (aligned_offset) {
2237 aligned_offset = ALIGN(aligned_offset, alignment);
2241 /* build mipmap tree */
2242 for (i = start_level; i <= surf->last_level; i++) {
2243 level[i].mode = RADEON_SURF_MODE_2D;
2244 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
2245 if (level[i].mode == RADEON_SURF_MODE_1D) {
2246 switch (tile_mode) {
2247 case CIK_TILE_MODE_COLOR_2D:
2248 tile_mode = SI_TILE_MODE_COLOR_1D;
2250 case CIK_TILE_MODE_COLOR_2D_SCANOUT:
2251 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2253 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64:
2254 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128:
2255 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256:
2256 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512:
2257 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE:
2258 tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2263 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
2265 /* level0 and first mipmap need to have alignment */
2266 aligned_offset = offset = surf->bo_size;
2268 aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
2270 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
2271 if (surf->level == level) {
2272 surf->tiling_index[i] = tile_mode;
2273 /* it's ok because stencil is done after */
2274 surf->stencil_tiling_index[i] = tile_mode;
2276 surf->stencil_tiling_index[i] = tile_mode;
2283 static int cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
2284 struct radeon_surface *surf,
2285 unsigned tile_mode, unsigned stencil_tile_mode)
2288 uint32_t num_pipes, num_banks;
2290 cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2291 !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode,
2292 &num_pipes, NULL, &num_banks, NULL, NULL, NULL);
2294 r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode,
2295 surf->tile_split, num_pipes, num_banks, 0, 0);
2300 if (surf->flags & RADEON_SURF_SBUFFER) {
2301 r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode,
2302 surf->stencil_tile_split, num_pipes, num_banks,
2304 surf->stencil_offset = surf->stencil_level[0].offset;
2309 static int cik_surface_init(struct radeon_surface_manager *surf_man,
2310 struct radeon_surface *surf)
2312 unsigned mode, tile_mode, stencil_tile_mode;
2315 /* MSAA surfaces support the 2D mode only. */
2316 if (surf->nsamples > 1) {
2317 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2318 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
2322 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2324 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
2325 /* zbuffer only support 1D or 2D tiled surface */
2327 case RADEON_SURF_MODE_1D:
2328 case RADEON_SURF_MODE_2D:
2331 mode = RADEON_SURF_MODE_1D;
2332 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2333 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2338 r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2343 surf->stencil_offset = 0;
2344 surf->bo_alignment = 0;
2346 /* check tiling mode */
2348 case RADEON_SURF_MODE_LINEAR:
2349 r = r6_surface_init_linear(surf_man, surf, 0, 0);
2351 case RADEON_SURF_MODE_LINEAR_ALIGNED:
2352 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
2354 case RADEON_SURF_MODE_1D:
2355 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2357 case RADEON_SURF_MODE_2D:
2358 r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2367 * depending on surface
2369 static int cik_surface_best(struct radeon_surface_manager *surf_man,
2370 struct radeon_surface *surf)
2372 unsigned mode, tile_mode, stencil_tile_mode;
2375 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2377 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
2378 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
2379 /* depth/stencil force 1d tiling for old mesa */
2380 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2381 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2384 return cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2388 /* ===========================================================================
2391 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
2393 struct radeon_surface_manager *surf_man;
2395 surf_man = calloc(1, sizeof(struct radeon_surface_manager));
2396 if (surf_man == NULL) {
2400 if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
2403 if (radeon_get_family(surf_man)) {
2407 if (surf_man->family <= CHIP_RV740) {
2408 if (r6_init_hw_info(surf_man)) {
2411 surf_man->surface_init = &r6_surface_init;
2412 surf_man->surface_best = &r6_surface_best;
2413 } else if (surf_man->family <= CHIP_ARUBA) {
2414 if (eg_init_hw_info(surf_man)) {
2417 surf_man->surface_init = &eg_surface_init;
2418 surf_man->surface_best = &eg_surface_best;
2419 } else if (surf_man->family < CHIP_BONAIRE) {
2420 if (si_init_hw_info(surf_man)) {
2423 surf_man->surface_init = &si_surface_init;
2424 surf_man->surface_best = &si_surface_best;
2426 if (cik_init_hw_info(surf_man)) {
2429 surf_man->surface_init = &cik_surface_init;
2430 surf_man->surface_best = &cik_surface_best;
2439 void radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
2444 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
2445 struct radeon_surface *surf,
2449 if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
2453 /* all dimension must be at least 1 ! */
2454 if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
2457 if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
2460 if (!surf->array_size) {
2463 /* array size must be a power of 2 */
2464 surf->array_size = next_power_of_two(surf->array_size);
2466 switch (surf->nsamples) {
2477 case RADEON_SURF_TYPE_1D:
2478 if (surf->npix_y > 1) {
2481 case RADEON_SURF_TYPE_2D:
2482 if (surf->npix_z > 1) {
2486 case RADEON_SURF_TYPE_CUBEMAP:
2487 if (surf->npix_z > 1) {
2490 /* deal with cubemap as they were texture array */
2491 if (surf_man->family >= CHIP_RV770) {
2492 surf->array_size = 8;
2494 surf->array_size = 6;
2497 case RADEON_SURF_TYPE_3D:
2499 case RADEON_SURF_TYPE_1D_ARRAY:
2500 if (surf->npix_y > 1) {
2503 case RADEON_SURF_TYPE_2D_ARRAY:
2511 int radeon_surface_init(struct radeon_surface_manager *surf_man,
2512 struct radeon_surface *surf)
2514 unsigned mode, type;
2517 type = RADEON_SURF_GET(surf->flags, TYPE);
2518 mode = RADEON_SURF_GET(surf->flags, MODE);
2520 r = radeon_surface_sanity(surf_man, surf, type, mode);
2524 return surf_man->surface_init(surf_man, surf);
2527 int radeon_surface_best(struct radeon_surface_manager *surf_man,
2528 struct radeon_surface *surf)
2530 unsigned mode, type;
2533 type = RADEON_SURF_GET(surf->flags, TYPE);
2534 mode = RADEON_SURF_GET(surf->flags, MODE);
2536 r = radeon_surface_sanity(surf_man, surf, type, mode);
2540 return surf_man->surface_best(surf_man, surf);