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 */
78 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
79 struct radeon_surface *surf);
80 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
81 struct radeon_surface *surf);
83 struct radeon_hw_info {
93 struct radeon_surface_manager {
96 struct radeon_hw_info hw_info;
98 hw_init_surface_t surface_init;
99 hw_best_surface_t surface_best;
103 static int radeon_get_value(int fd, unsigned req, uint32_t *value)
105 struct drm_radeon_info info = {};
110 info.value = (uintptr_t)value;
111 r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
112 sizeof(struct drm_radeon_info));
116 static int radeon_get_family(struct radeon_surface_manager *surf_man)
118 switch (surf_man->device_id) {
119 #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
120 #include "r600_pci_ids.h"
128 static unsigned next_power_of_two(unsigned x)
133 return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
136 static unsigned mip_minify(unsigned size, unsigned level)
140 val = MAX2(1, size >> level);
142 val = next_power_of_two(val);
146 static void surf_minify(struct radeon_surface *surf,
148 uint32_t xalign, uint32_t yalign, uint32_t zalign,
151 surf->level[level].npix_x = mip_minify(surf->npix_x, level);
152 surf->level[level].npix_y = mip_minify(surf->npix_y, level);
153 surf->level[level].npix_z = mip_minify(surf->npix_z, level);
154 surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
155 surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
156 surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
157 if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
158 if (surf->level[level].nblk_x < xalign || surf->level[level].nblk_y < yalign) {
159 surf->level[level].mode = RADEON_SURF_MODE_1D;
163 surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, xalign);
164 surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, yalign);
165 surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, zalign);
167 surf->level[level].offset = offset;
168 surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe;
169 surf->level[level].slice_size = surf->level[level].pitch_bytes * surf->level[level].nblk_y;
171 surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
174 /* ===========================================================================
177 static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
179 uint32_t tiling_config;
180 drmVersionPtr version;
183 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
189 surf_man->hw_info.allow_2d = 0;
190 version = drmGetVersion(surf_man->fd);
191 if (version && version->version_minor >= 14) {
192 surf_man->hw_info.allow_2d = 1;
195 switch ((tiling_config & 0xe) >> 1) {
197 surf_man->hw_info.num_pipes = 1;
200 surf_man->hw_info.num_pipes = 2;
203 surf_man->hw_info.num_pipes = 4;
206 surf_man->hw_info.num_pipes = 8;
209 surf_man->hw_info.num_pipes = 8;
210 surf_man->hw_info.allow_2d = 0;
214 switch ((tiling_config & 0x30) >> 4) {
216 surf_man->hw_info.num_banks = 4;
219 surf_man->hw_info.num_banks = 8;
222 surf_man->hw_info.num_banks = 8;
223 surf_man->hw_info.allow_2d = 0;
227 switch ((tiling_config & 0xc0) >> 6) {
229 surf_man->hw_info.group_bytes = 256;
232 surf_man->hw_info.group_bytes = 512;
235 surf_man->hw_info.group_bytes = 256;
236 surf_man->hw_info.allow_2d = 0;
242 static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
243 struct radeon_surface *surf,
244 uint64_t offset, unsigned start_level)
246 uint32_t xalign, yalign, zalign;
249 /* compute alignment */
251 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
253 /* the 32 alignment is for scanout, cb or db but to allow texture to be
254 * easily bound as such we force this alignment to all surface
256 xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
259 if (surf->flags & RADEON_SURF_SCANOUT) {
260 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
263 /* build mipmap tree */
264 for (i = start_level; i <= surf->last_level; i++) {
265 surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
266 surf_minify(surf, i, xalign, yalign, zalign, offset);
267 /* level0 and first mipmap need to have alignment */
268 offset = surf->bo_size;
270 offset = ALIGN(offset, surf->bo_alignment);
276 static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
277 struct radeon_surface *surf,
278 uint64_t offset, unsigned start_level)
280 uint32_t xalign, yalign, zalign;
283 /* compute alignment */
285 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
287 xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
291 /* build mipmap tree */
292 for (i = start_level; i <= surf->last_level; i++) {
293 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
294 surf_minify(surf, i, xalign, yalign, zalign, offset);
295 /* level0 and first mipmap need to have alignment */
296 offset = surf->bo_size;
298 offset = ALIGN(offset, surf->bo_alignment);
304 static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
305 struct radeon_surface *surf,
306 uint64_t offset, unsigned start_level)
308 uint32_t xalign, yalign, zalign, tilew;
311 /* compute alignment */
313 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
314 xalign = MAX2(tilew, xalign);
317 if (surf->flags & RADEON_SURF_SCANOUT) {
318 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
321 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
324 /* build mipmap tree */
325 for (i = start_level; i <= surf->last_level; i++) {
326 surf->level[i].mode = RADEON_SURF_MODE_1D;
327 surf_minify(surf, i, xalign, yalign, zalign, offset);
328 /* level0 and first mipmap need to have alignment */
329 offset = surf->bo_size;
331 offset = ALIGN(offset, surf->bo_alignment);
337 static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
338 struct radeon_surface *surf,
339 uint64_t offset, unsigned start_level)
341 uint32_t xalign, yalign, zalign, tilew;
344 /* compute alignment */
347 xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
348 (tilew * surf->bpe * surf->nsamples);
349 xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
350 yalign = tilew * surf_man->hw_info.num_pipes;
351 if (surf->flags & RADEON_SURF_SCANOUT) {
352 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
356 MAX2(surf_man->hw_info.num_pipes *
357 surf_man->hw_info.num_banks *
359 xalign * yalign * surf->nsamples * surf->bpe);
362 /* build mipmap tree */
363 for (i = start_level; i <= surf->last_level; i++) {
364 surf->level[i].mode = RADEON_SURF_MODE_2D;
365 surf_minify(surf, i, xalign, yalign, zalign, offset);
366 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
367 return r6_surface_init_1d(surf_man, surf, offset, i);
369 /* level0 and first mipmap need to have alignment */
370 offset = surf->bo_size;
372 offset = ALIGN(offset, surf->bo_alignment);
378 static int r6_surface_init(struct radeon_surface_manager *surf_man,
379 struct radeon_surface *surf)
385 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
387 /* always enable z & stencil together */
388 if (surf->flags & RADEON_SURF_ZBUFFER) {
389 surf->flags |= RADEON_SURF_SBUFFER;
391 if (surf->flags & RADEON_SURF_SBUFFER) {
392 surf->flags |= RADEON_SURF_ZBUFFER;
394 if (surf->flags & RADEON_SURF_ZBUFFER) {
395 /* zbuffer only support 1D or 2D tiled surface */
397 case RADEON_SURF_MODE_1D:
398 case RADEON_SURF_MODE_2D:
401 mode = RADEON_SURF_MODE_1D;
402 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
403 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
408 /* force 1d on kernel that can't do 2d */
409 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
410 mode = RADEON_SURF_MODE_1D;
411 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
412 surf->flags |= RADEON_SURF_SET(mode, MODE);
415 /* check surface dimension */
416 if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
420 /* check mipmap last_level */
421 if (surf->last_level > 14) {
425 /* check tiling mode */
427 case RADEON_SURF_MODE_LINEAR:
428 r = r6_surface_init_linear(surf_man, surf, 0, 0);
430 case RADEON_SURF_MODE_LINEAR_ALIGNED:
431 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
433 case RADEON_SURF_MODE_1D:
434 r = r6_surface_init_1d(surf_man, surf, 0, 0);
436 case RADEON_SURF_MODE_2D:
437 r = r6_surface_init_2d(surf_man, surf, 0, 0);
445 static int r6_surface_best(struct radeon_surface_manager *surf_man,
446 struct radeon_surface *surf)
448 /* no value to optimize for r6xx/r7xx */
453 /* ===========================================================================
456 static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
458 uint32_t tiling_config;
459 drmVersionPtr version;
462 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
468 surf_man->hw_info.allow_2d = 0;
469 version = drmGetVersion(surf_man->fd);
470 if (version && version->version_minor >= 16) {
471 surf_man->hw_info.allow_2d = 1;
474 switch (tiling_config & 0xf) {
476 surf_man->hw_info.num_pipes = 1;
479 surf_man->hw_info.num_pipes = 2;
482 surf_man->hw_info.num_pipes = 4;
485 surf_man->hw_info.num_pipes = 8;
488 surf_man->hw_info.num_pipes = 8;
489 surf_man->hw_info.allow_2d = 0;
493 switch ((tiling_config & 0xf0) >> 4) {
495 surf_man->hw_info.num_banks = 4;
498 surf_man->hw_info.num_banks = 8;
501 surf_man->hw_info.num_banks = 16;
504 surf_man->hw_info.num_banks = 8;
505 surf_man->hw_info.allow_2d = 0;
509 switch ((tiling_config & 0xf00) >> 8) {
511 surf_man->hw_info.group_bytes = 256;
514 surf_man->hw_info.group_bytes = 512;
517 surf_man->hw_info.group_bytes = 256;
518 surf_man->hw_info.allow_2d = 0;
522 switch ((tiling_config & 0xf000) >> 12) {
524 surf_man->hw_info.row_size = 1024;
527 surf_man->hw_info.row_size = 2048;
530 surf_man->hw_info.row_size = 4096;
533 surf_man->hw_info.row_size = 4096;
534 surf_man->hw_info.allow_2d = 0;
540 static void eg_surf_minify(struct radeon_surface *surf,
548 unsigned mtile_pr, mtile_ps;
550 surf->level[level].npix_x = mip_minify(surf->npix_x, level);
551 surf->level[level].npix_y = mip_minify(surf->npix_y, level);
552 surf->level[level].npix_z = mip_minify(surf->npix_z, level);
553 surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
554 surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
555 surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
556 if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
557 if (surf->level[level].nblk_x < mtilew || surf->level[level].nblk_y < mtileh) {
558 surf->level[level].mode = RADEON_SURF_MODE_1D;
562 surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, mtilew);
563 surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, mtileh);
564 surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, 1);
566 /* macro tile per row */
567 mtile_pr = surf->level[level].nblk_x / mtilew;
568 /* macro tile per slice */
569 mtile_ps = (mtile_pr * surf->level[level].nblk_y) / mtileh;
571 surf->level[level].offset = offset;
572 surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * slice_pt;
573 surf->level[level].slice_size = mtile_ps * mtileb * slice_pt;
575 surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
578 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
579 struct radeon_surface *surf,
580 uint64_t offset, unsigned start_level)
582 uint32_t xalign, yalign, zalign, tilew;
585 /* compute alignment */
587 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
588 if (surf->flags & RADEON_SURF_SBUFFER) {
589 xalign = surf_man->hw_info.group_bytes / (tilew * surf->nsamples);
591 xalign = MAX2(tilew, xalign);
594 if (surf->flags & RADEON_SURF_SCANOUT) {
595 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
598 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
601 /* build mipmap tree */
602 for (i = start_level; i <= surf->last_level; i++) {
603 surf->level[i].mode = RADEON_SURF_MODE_1D;
604 surf_minify(surf, i, xalign, yalign, zalign, offset);
605 /* level0 and first mipmap need to have alignment */
606 offset = surf->bo_size;
608 offset = ALIGN(offset, surf->bo_alignment);
612 if (surf->flags & RADEON_SURF_SBUFFER) {
613 surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
614 surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
620 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
621 struct radeon_surface *surf,
622 uint64_t offset, unsigned start_level)
624 unsigned tilew, tileh, tileb;
625 unsigned mtilew, mtileh, mtileb;
629 /* compute tile values */
632 tileb = tilew * tileh * surf->bpe * surf->nsamples;
633 /* slices per tile */
635 if (tileb > surf->tile_split) {
636 slice_pt = tileb / surf->tile_split;
638 tileb = tileb / slice_pt;
640 /* macro tile width & height */
641 mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
642 mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
643 /* macro tile bytes */
644 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
647 surf->bo_alignment = MAX2(256, mtileb);
650 /* build mipmap tree */
651 for (i = start_level; i <= surf->last_level; i++) {
652 surf->level[i].mode = RADEON_SURF_MODE_2D;
653 eg_surf_minify(surf, i, slice_pt, mtilew, mtileh, mtileb, offset);
654 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
655 return eg_surface_init_1d(surf_man, surf, offset, i);
657 /* level0 and first mipmap need to have alignment */
658 offset = surf->bo_size;
660 offset = ALIGN(offset, surf->bo_alignment);
664 if (surf->flags & RADEON_SURF_SBUFFER) {
665 surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
666 surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
672 static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
673 struct radeon_surface *surf,
678 /* check surface dimension */
679 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
683 /* check mipmap last_level */
684 if (surf->last_level > 15) {
688 /* force 1d on kernel that can't do 2d */
689 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
690 mode = RADEON_SURF_MODE_1D;
691 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
692 surf->flags |= RADEON_SURF_SET(mode, MODE);
695 /* check tile split */
696 if (mode == RADEON_SURF_MODE_2D) {
697 switch (surf->tile_split) {
709 switch (surf->mtilea) {
718 /* check aspect ratio */
719 if (surf_man->hw_info.num_banks < surf->mtilea) {
722 /* check bank width */
723 switch (surf->bankw) {
732 /* check bank height */
733 switch (surf->bankh) {
742 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
743 if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
751 static int eg_surface_init(struct radeon_surface_manager *surf_man,
752 struct radeon_surface *surf)
758 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
760 /* for some reason eg need to have room for stencil right after depth */
761 if (surf->flags & RADEON_SURF_ZBUFFER) {
762 surf->flags |= RADEON_SURF_SBUFFER;
764 if (surf->flags & RADEON_SURF_SBUFFER) {
765 surf->flags |= RADEON_SURF_ZBUFFER;
767 if (surf->flags & RADEON_SURF_ZBUFFER) {
768 /* zbuffer only support 1D or 2D tiled surface */
770 case RADEON_SURF_MODE_1D:
771 case RADEON_SURF_MODE_2D:
774 mode = RADEON_SURF_MODE_1D;
775 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
776 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
781 r = eg_surface_sanity(surf_man, surf, mode);
786 surf->stencil_offset = 0;
787 surf->stencil_tile_split = 0;
789 /* check tiling mode */
791 case RADEON_SURF_MODE_LINEAR:
792 r = r6_surface_init_linear(surf_man, surf, 0, 0);
794 case RADEON_SURF_MODE_LINEAR_ALIGNED:
795 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
797 case RADEON_SURF_MODE_1D:
798 r = eg_surface_init_1d(surf_man, surf, 0, 0);
800 case RADEON_SURF_MODE_2D:
801 r = eg_surface_init_2d(surf_man, surf, 0, 0);
809 static unsigned log2_int(unsigned x)
817 if ((unsigned)(1 << l) > x) {
824 /* compute best tile_split, bankw, bankh, mtilea
825 * depending on surface
827 static int eg_surface_best(struct radeon_surface_manager *surf_man,
828 struct radeon_surface *surf)
830 unsigned mode, tileb, h_over_w;
834 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
836 /* for some reason eg need to have room for stencil right after depth */
837 if (surf->flags & RADEON_SURF_ZBUFFER) {
838 surf->flags |= RADEON_SURF_SBUFFER;
841 /* set some default value to avoid sanity check choking on them */
842 surf->tile_split = 1024;
845 surf->mtilea = surf_man->hw_info.num_banks;
846 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
847 for (; surf->bankh <= 8; surf->bankh *= 2) {
848 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
852 if (surf->mtilea > 8) {
856 r = eg_surface_sanity(surf_man, surf, mode);
861 if (mode != RADEON_SURF_MODE_2D) {
862 /* nothing to do for non 2D tiled surface */
866 /* set tile split to row size, optimize latter for multi-sample surface
867 * tile split >= 256 for render buffer surface. Also depth surface want
868 * smaller value for optimal performances.
870 surf->tile_split = surf_man->hw_info.row_size;
871 surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
873 /* bankw or bankh greater than 1 increase alignment requirement, not
874 * sure if it's worth using smaller bankw & bankh to stick with 2D
875 * tiling on small surface rather than falling back to 1D tiling.
876 * Use recommanded value based on tile size for now.
878 * fmask buffer has different optimal value figure them out once we
881 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
882 /* assume 1 bytes for stencil, we optimize for stencil as stencil
883 * and depth shares surface values
885 tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
887 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
890 /* use bankw of 1 to minimize width alignment, might be interesting to
891 * increase it for large surface
906 /* double check the constraint */
907 for (; surf->bankh <= 8; surf->bankh *= 2) {
908 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
913 h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
914 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
915 surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
921 /* ===========================================================================
924 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
926 struct radeon_surface_manager *surf_man;
928 surf_man = calloc(1, sizeof(struct radeon_surface_manager));
929 if (surf_man == NULL) {
933 if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
936 if (radeon_get_family(surf_man)) {
940 if (surf_man->family <= CHIP_RV740) {
941 if (r6_init_hw_info(surf_man)) {
944 surf_man->surface_init = &r6_surface_init;
945 surf_man->surface_best = &r6_surface_best;
947 if (eg_init_hw_info(surf_man)) {
950 surf_man->surface_init = &eg_surface_init;
951 surf_man->surface_best = &eg_surface_best;
960 void radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
965 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
966 struct radeon_surface *surf,
970 if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
974 /* all dimension must be at least 1 ! */
975 if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
978 if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
981 if (!surf->array_size) {
984 /* array size must be a power of 2 */
985 surf->array_size = next_power_of_two(surf->array_size);
987 switch (surf->nsamples) {
998 case RADEON_SURF_TYPE_1D:
999 if (surf->npix_y > 1) {
1002 case RADEON_SURF_TYPE_2D:
1003 if (surf->npix_z > 1) {
1007 case RADEON_SURF_TYPE_CUBEMAP:
1008 if (surf->npix_z > 1) {
1011 /* deal with cubemap as they were texture array */
1012 if (surf_man->family >= CHIP_RV770) {
1013 surf->array_size = 8;
1015 surf->array_size = 6;
1018 case RADEON_SURF_TYPE_3D:
1020 case RADEON_SURF_TYPE_1D_ARRAY:
1021 if (surf->npix_y > 1) {
1024 case RADEON_SURF_TYPE_2D_ARRAY:
1032 int radeon_surface_init(struct radeon_surface_manager *surf_man,
1033 struct radeon_surface *surf)
1035 unsigned mode, type;
1038 type = RADEON_SURF_GET(surf->flags, TYPE);
1039 mode = RADEON_SURF_GET(surf->flags, MODE);
1041 r = radeon_surface_sanity(surf_man, surf, type, mode);
1045 return surf_man->surface_init(surf_man, surf);
1048 int radeon_surface_best(struct radeon_surface_manager *surf_man,
1049 struct radeon_surface *surf)
1051 unsigned mode, type;
1054 type = RADEON_SURF_GET(surf->flags, TYPE);
1055 mode = RADEON_SURF_GET(surf->flags, MODE);
1057 r = radeon_surface_sanity(surf_man, surf, type, mode);
1061 return surf_man->surface_best(surf_man, surf);