1 /*
2 * Copyright © 2011 Red Hat All Rights Reserved.
3 *
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:
11 *
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.
20 *
21 * The above copyright notice and this permission notice (including the
22 * next paragraph) shall be included in all copies or substantial portions
23 * of the Software.
24 */
25 /*
26 * Authors:
27 * Jérôme Glisse <jglisse@redhat.com>
28 */
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 #include <stdbool.h>
33 #include <assert.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/ioctl.h>
39 #include "drm.h"
40 #include "libdrm_macros.h"
41 #include "xf86drm.h"
42 #include "radeon_drm.h"
43 #include "radeon_surface.h"
44
45 #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
46 #define MAX2(A, B) ((A) > (B) ? (A) : (B))
47 #define MIN2(A, B) ((A) < (B) ? (A) : (B))
48
49 /* keep this private */
50 enum radeon_family {
51 CHIP_UNKNOWN,
52 CHIP_R600,
53 CHIP_RV610,
54 CHIP_RV630,
55 CHIP_RV670,
56 CHIP_RV620,
57 CHIP_RV635,
58 CHIP_RS780,
59 CHIP_RS880,
60 CHIP_RV770,
61 CHIP_RV730,
62 CHIP_RV710,
63 CHIP_RV740,
64 CHIP_CEDAR,
65 CHIP_REDWOOD,
66 CHIP_JUNIPER,
67 CHIP_CYPRESS,
68 CHIP_HEMLOCK,
69 CHIP_PALM,
70 CHIP_SUMO,
71 CHIP_SUMO2,
72 CHIP_BARTS,
73 CHIP_TURKS,
74 CHIP_CAICOS,
75 CHIP_CAYMAN,
76 CHIP_ARUBA,
77 CHIP_TAHITI,
78 CHIP_PITCAIRN,
79 CHIP_VERDE,
80 CHIP_OLAND,
81 CHIP_HAINAN,
82 CHIP_BONAIRE,
83 CHIP_KAVERI,
84 CHIP_KABINI,
85 CHIP_HAWAII,
86 CHIP_MULLINS,
87 CHIP_LAST,
88 };
89
90 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
91 struct radeon_surface *surf);
92 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
93 struct radeon_surface *surf);
94
95 struct radeon_hw_info {
96 /* apply to r6, eg */
97 uint32_t group_bytes;
98 uint32_t num_banks;
99 uint32_t num_pipes;
100 /* apply to eg */
101 uint32_t row_size;
102 unsigned allow_2d;
103 /* apply to si */
104 uint32_t tile_mode_array[32];
105 /* apply to cik */
106 uint32_t macrotile_mode_array[16];
107 };
108
109 struct radeon_surface_manager {
110 int fd;
111 uint32_t device_id;
112 struct radeon_hw_info hw_info;
113 unsigned family;
114 hw_init_surface_t surface_init;
115 hw_best_surface_t surface_best;
116 };
117
118 /* helper */
radeon_get_value(int fd,unsigned req,uint32_t * value)119 static int radeon_get_value(int fd, unsigned req, uint32_t *value)
120 {
121 struct drm_radeon_info info = {};
122 int r;
123
124 *value = 0;
125 info.request = req;
126 info.value = (uintptr_t)value;
127 r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
128 sizeof(struct drm_radeon_info));
129 return r;
130 }
131
radeon_get_family(struct radeon_surface_manager * surf_man)132 static int radeon_get_family(struct radeon_surface_manager *surf_man)
133 {
134 switch (surf_man->device_id) {
135 #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
136 #include "r600_pci_ids.h"
137 #undef CHIPSET
138 default:
139 return -EINVAL;
140 }
141 return 0;
142 }
143
next_power_of_two(unsigned x)144 static unsigned next_power_of_two(unsigned x)
145 {
146 if (x <= 1)
147 return 1;
148
149 return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
150 }
151
mip_minify(unsigned size,unsigned level)152 static unsigned mip_minify(unsigned size, unsigned level)
153 {
154 unsigned val;
155
156 val = MAX2(1, size >> level);
157 if (level > 0)
158 val = next_power_of_two(val);
159 return val;
160 }
161
surf_minify(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,uint32_t xalign,uint32_t yalign,uint32_t zalign,uint64_t offset)162 static void surf_minify(struct radeon_surface *surf,
163 struct radeon_surface_level *surflevel,
164 unsigned bpe, unsigned level,
165 uint32_t xalign, uint32_t yalign, uint32_t zalign,
166 uint64_t offset)
167 {
168 surflevel->npix_x = mip_minify(surf->npix_x, level);
169 surflevel->npix_y = mip_minify(surf->npix_y, level);
170 surflevel->npix_z = mip_minify(surf->npix_z, level);
171 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
172 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
173 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
174 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
175 !(surf->flags & RADEON_SURF_FMASK)) {
176 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
177 surflevel->mode = RADEON_SURF_MODE_1D;
178 return;
179 }
180 }
181 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
182 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
183 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
184
185 surflevel->offset = offset;
186 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
187 surflevel->slice_size = (uint64_t)surflevel->pitch_bytes * surflevel->nblk_y;
188
189 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
190 }
191
192 /* ===========================================================================
193 * r600/r700 family
194 */
r6_init_hw_info(struct radeon_surface_manager * surf_man)195 static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
196 {
197 uint32_t tiling_config;
198 drmVersionPtr version;
199 int r;
200
201 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
202 &tiling_config);
203 if (r) {
204 return r;
205 }
206
207 surf_man->hw_info.allow_2d = 0;
208 version = drmGetVersion(surf_man->fd);
209 if (version && version->version_minor >= 14) {
210 surf_man->hw_info.allow_2d = 1;
211 }
212 drmFreeVersion(version);
213
214 switch ((tiling_config & 0xe) >> 1) {
215 case 0:
216 surf_man->hw_info.num_pipes = 1;
217 break;
218 case 1:
219 surf_man->hw_info.num_pipes = 2;
220 break;
221 case 2:
222 surf_man->hw_info.num_pipes = 4;
223 break;
224 case 3:
225 surf_man->hw_info.num_pipes = 8;
226 break;
227 default:
228 surf_man->hw_info.num_pipes = 8;
229 surf_man->hw_info.allow_2d = 0;
230 break;
231 }
232
233 switch ((tiling_config & 0x30) >> 4) {
234 case 0:
235 surf_man->hw_info.num_banks = 4;
236 break;
237 case 1:
238 surf_man->hw_info.num_banks = 8;
239 break;
240 default:
241 surf_man->hw_info.num_banks = 8;
242 surf_man->hw_info.allow_2d = 0;
243 break;
244 }
245
246 switch ((tiling_config & 0xc0) >> 6) {
247 case 0:
248 surf_man->hw_info.group_bytes = 256;
249 break;
250 case 1:
251 surf_man->hw_info.group_bytes = 512;
252 break;
253 default:
254 surf_man->hw_info.group_bytes = 256;
255 surf_man->hw_info.allow_2d = 0;
256 break;
257 }
258 return 0;
259 }
260
r6_surface_init_linear(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)261 static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
262 struct radeon_surface *surf,
263 uint64_t offset, unsigned start_level)
264 {
265 uint32_t xalign, yalign, zalign;
266 unsigned i;
267
268 /* compute alignment */
269 if (!start_level) {
270 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
271 }
272 /* the 32 alignment is for scanout, cb or db but to allow texture to be
273 * easily bound as such we force this alignment to all surface
274 */
275 xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
276 yalign = 1;
277 zalign = 1;
278 if (surf->flags & RADEON_SURF_SCANOUT) {
279 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
280 }
281
282 /* build mipmap tree */
283 for (i = start_level; i <= surf->last_level; i++) {
284 surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
285 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
286 /* level0 and first mipmap need to have alignment */
287 offset = surf->bo_size;
288 if (i == 0) {
289 offset = ALIGN(offset, surf->bo_alignment);
290 }
291 }
292 return 0;
293 }
294
r6_surface_init_linear_aligned(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)295 static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
296 struct radeon_surface *surf,
297 uint64_t offset, unsigned start_level)
298 {
299 uint32_t xalign, yalign, zalign;
300 unsigned i;
301
302 /* compute alignment */
303 if (!start_level) {
304 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
305 }
306 xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
307 yalign = 1;
308 zalign = 1;
309
310 /* build mipmap tree */
311 for (i = start_level; i <= surf->last_level; i++) {
312 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
313 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
314 /* level0 and first mipmap need to have alignment */
315 offset = surf->bo_size;
316 if (i == 0) {
317 offset = ALIGN(offset, surf->bo_alignment);
318 }
319 }
320 return 0;
321 }
322
r6_surface_init_1d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)323 static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
324 struct radeon_surface *surf,
325 uint64_t offset, unsigned start_level)
326 {
327 uint32_t xalign, yalign, zalign, tilew;
328 unsigned i;
329
330 /* compute alignment */
331 tilew = 8;
332 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
333 xalign = MAX2(tilew, xalign);
334 yalign = tilew;
335 zalign = 1;
336 if (surf->flags & RADEON_SURF_SCANOUT) {
337 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
338 }
339 if (!start_level) {
340 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
341 }
342
343 /* build mipmap tree */
344 for (i = start_level; i <= surf->last_level; i++) {
345 surf->level[i].mode = RADEON_SURF_MODE_1D;
346 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
347 /* level0 and first mipmap need to have alignment */
348 offset = surf->bo_size;
349 if (i == 0) {
350 offset = ALIGN(offset, surf->bo_alignment);
351 }
352 }
353 return 0;
354 }
355
r6_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)356 static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
357 struct radeon_surface *surf,
358 uint64_t offset, unsigned start_level)
359 {
360 uint32_t xalign, yalign, zalign, tilew;
361 unsigned i;
362
363 /* compute alignment */
364 tilew = 8;
365 zalign = 1;
366 xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
367 (tilew * surf->bpe * surf->nsamples);
368 xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
369 if (surf->flags & RADEON_SURF_FMASK)
370 xalign = MAX2(128, xalign);
371 yalign = tilew * surf_man->hw_info.num_pipes;
372 if (surf->flags & RADEON_SURF_SCANOUT) {
373 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
374 }
375 if (!start_level) {
376 surf->bo_alignment =
377 MAX2(surf_man->hw_info.num_pipes *
378 surf_man->hw_info.num_banks *
379 surf->nsamples * surf->bpe * 64,
380 xalign * yalign * surf->nsamples * surf->bpe);
381 }
382
383 /* build mipmap tree */
384 for (i = start_level; i <= surf->last_level; i++) {
385 surf->level[i].mode = RADEON_SURF_MODE_2D;
386 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
387 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
388 return r6_surface_init_1d(surf_man, surf, offset, i);
389 }
390 /* level0 and first mipmap need to have alignment */
391 offset = surf->bo_size;
392 if (i == 0) {
393 offset = ALIGN(offset, surf->bo_alignment);
394 }
395 }
396 return 0;
397 }
398
r6_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)399 static int r6_surface_init(struct radeon_surface_manager *surf_man,
400 struct radeon_surface *surf)
401 {
402 unsigned mode;
403 int r;
404
405 /* MSAA surfaces support the 2D mode only. */
406 if (surf->nsamples > 1) {
407 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
408 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
409 }
410
411 /* tiling mode */
412 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
413
414 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
415 /* zbuffer only support 1D or 2D tiled surface */
416 switch (mode) {
417 case RADEON_SURF_MODE_1D:
418 case RADEON_SURF_MODE_2D:
419 break;
420 default:
421 mode = RADEON_SURF_MODE_1D;
422 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
423 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
424 break;
425 }
426 }
427
428 /* force 1d on kernel that can't do 2d */
429 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
430 if (surf->nsamples > 1) {
431 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
432 return -EFAULT;
433 }
434 mode = RADEON_SURF_MODE_1D;
435 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
436 surf->flags |= RADEON_SURF_SET(mode, MODE);
437 }
438
439 /* check surface dimension */
440 if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
441 return -EINVAL;
442 }
443
444 /* check mipmap last_level */
445 if (surf->last_level > 14) {
446 return -EINVAL;
447 }
448
449 /* check tiling mode */
450 switch (mode) {
451 case RADEON_SURF_MODE_LINEAR:
452 r = r6_surface_init_linear(surf_man, surf, 0, 0);
453 break;
454 case RADEON_SURF_MODE_LINEAR_ALIGNED:
455 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
456 break;
457 case RADEON_SURF_MODE_1D:
458 r = r6_surface_init_1d(surf_man, surf, 0, 0);
459 break;
460 case RADEON_SURF_MODE_2D:
461 r = r6_surface_init_2d(surf_man, surf, 0, 0);
462 break;
463 default:
464 return -EINVAL;
465 }
466 return r;
467 }
468
r6_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)469 static int r6_surface_best(struct radeon_surface_manager *surf_man,
470 struct radeon_surface *surf)
471 {
472 /* no value to optimize for r6xx/r7xx */
473 return 0;
474 }
475
476
477 /* ===========================================================================
478 * evergreen family
479 */
eg_init_hw_info(struct radeon_surface_manager * surf_man)480 static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
481 {
482 uint32_t tiling_config;
483 drmVersionPtr version;
484 int r;
485
486 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
487 &tiling_config);
488 if (r) {
489 return r;
490 }
491
492 surf_man->hw_info.allow_2d = 0;
493 version = drmGetVersion(surf_man->fd);
494 if (version && version->version_minor >= 16) {
495 surf_man->hw_info.allow_2d = 1;
496 }
497 drmFreeVersion(version);
498
499 switch (tiling_config & 0xf) {
500 case 0:
501 surf_man->hw_info.num_pipes = 1;
502 break;
503 case 1:
504 surf_man->hw_info.num_pipes = 2;
505 break;
506 case 2:
507 surf_man->hw_info.num_pipes = 4;
508 break;
509 case 3:
510 surf_man->hw_info.num_pipes = 8;
511 break;
512 default:
513 surf_man->hw_info.num_pipes = 8;
514 surf_man->hw_info.allow_2d = 0;
515 break;
516 }
517
518 switch ((tiling_config & 0xf0) >> 4) {
519 case 0:
520 surf_man->hw_info.num_banks = 4;
521 break;
522 case 1:
523 surf_man->hw_info.num_banks = 8;
524 break;
525 case 2:
526 surf_man->hw_info.num_banks = 16;
527 break;
528 default:
529 surf_man->hw_info.num_banks = 8;
530 surf_man->hw_info.allow_2d = 0;
531 break;
532 }
533
534 switch ((tiling_config & 0xf00) >> 8) {
535 case 0:
536 surf_man->hw_info.group_bytes = 256;
537 break;
538 case 1:
539 surf_man->hw_info.group_bytes = 512;
540 break;
541 default:
542 surf_man->hw_info.group_bytes = 256;
543 surf_man->hw_info.allow_2d = 0;
544 break;
545 }
546
547 switch ((tiling_config & 0xf000) >> 12) {
548 case 0:
549 surf_man->hw_info.row_size = 1024;
550 break;
551 case 1:
552 surf_man->hw_info.row_size = 2048;
553 break;
554 case 2:
555 surf_man->hw_info.row_size = 4096;
556 break;
557 default:
558 surf_man->hw_info.row_size = 4096;
559 surf_man->hw_info.allow_2d = 0;
560 break;
561 }
562 return 0;
563 }
564
eg_surf_minify(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,unsigned slice_pt,unsigned mtilew,unsigned mtileh,unsigned mtileb,uint64_t offset)565 static void eg_surf_minify(struct radeon_surface *surf,
566 struct radeon_surface_level *surflevel,
567 unsigned bpe,
568 unsigned level,
569 unsigned slice_pt,
570 unsigned mtilew,
571 unsigned mtileh,
572 unsigned mtileb,
573 uint64_t offset)
574 {
575 unsigned mtile_pr, mtile_ps;
576
577 surflevel->npix_x = mip_minify(surf->npix_x, level);
578 surflevel->npix_y = mip_minify(surf->npix_y, level);
579 surflevel->npix_z = mip_minify(surf->npix_z, level);
580 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
581 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
582 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
583 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
584 !(surf->flags & RADEON_SURF_FMASK)) {
585 if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
586 surflevel->mode = RADEON_SURF_MODE_1D;
587 return;
588 }
589 }
590 surflevel->nblk_x = ALIGN(surflevel->nblk_x, mtilew);
591 surflevel->nblk_y = ALIGN(surflevel->nblk_y, mtileh);
592 surflevel->nblk_z = ALIGN(surflevel->nblk_z, 1);
593
594 /* macro tile per row */
595 mtile_pr = surflevel->nblk_x / mtilew;
596 /* macro tile per slice */
597 mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
598
599 surflevel->offset = offset;
600 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
601 surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt;
602
603 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
604 }
605
eg_surface_init_1d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,uint64_t offset,unsigned start_level)606 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
607 struct radeon_surface *surf,
608 struct radeon_surface_level *level,
609 unsigned bpe,
610 uint64_t offset, unsigned start_level)
611 {
612 uint32_t xalign, yalign, zalign, tilew;
613 unsigned i;
614
615 /* compute alignment */
616 tilew = 8;
617 xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
618 xalign = MAX2(tilew, xalign);
619 yalign = tilew;
620 zalign = 1;
621 if (surf->flags & RADEON_SURF_SCANOUT) {
622 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
623 }
624
625 if (!start_level) {
626 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
627 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
628
629 if (offset) {
630 offset = ALIGN(offset, alignment);
631 }
632 }
633
634 /* build mipmap tree */
635 for (i = start_level; i <= surf->last_level; i++) {
636 level[i].mode = RADEON_SURF_MODE_1D;
637 surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
638 /* level0 and first mipmap need to have alignment */
639 offset = surf->bo_size;
640 if (i == 0) {
641 offset = ALIGN(offset, surf->bo_alignment);
642 }
643 }
644 return 0;
645 }
646
eg_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_split,uint64_t offset,unsigned start_level)647 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
648 struct radeon_surface *surf,
649 struct radeon_surface_level *level,
650 unsigned bpe, unsigned tile_split,
651 uint64_t offset, unsigned start_level)
652 {
653 unsigned tilew, tileh, tileb;
654 unsigned mtilew, mtileh, mtileb;
655 unsigned slice_pt;
656 unsigned i;
657
658 /* compute tile values */
659 tilew = 8;
660 tileh = 8;
661 tileb = tilew * tileh * bpe * surf->nsamples;
662 /* slices per tile */
663 slice_pt = 1;
664 if (tileb > tile_split && tile_split) {
665 slice_pt = tileb / tile_split;
666 }
667 tileb = tileb / slice_pt;
668
669 /* macro tile width & height */
670 mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
671 mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
672 /* macro tile bytes */
673 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
674
675 if (!start_level) {
676 unsigned alignment = MAX2(256, mtileb);
677 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
678
679 if (offset) {
680 offset = ALIGN(offset, alignment);
681 }
682 }
683
684 /* build mipmap tree */
685 for (i = start_level; i <= surf->last_level; i++) {
686 level[i].mode = RADEON_SURF_MODE_2D;
687 eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
688 if (level[i].mode == RADEON_SURF_MODE_1D) {
689 return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
690 }
691 /* level0 and first mipmap need to have alignment */
692 offset = surf->bo_size;
693 if (i == 0) {
694 offset = ALIGN(offset, surf->bo_alignment);
695 }
696 }
697 return 0;
698 }
699
eg_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned mode)700 static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
701 struct radeon_surface *surf,
702 unsigned mode)
703 {
704 unsigned tileb;
705
706 /* check surface dimension */
707 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
708 return -EINVAL;
709 }
710
711 /* check mipmap last_level */
712 if (surf->last_level > 15) {
713 return -EINVAL;
714 }
715
716 /* force 1d on kernel that can't do 2d */
717 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
718 if (surf->nsamples > 1) {
719 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
720 return -EFAULT;
721 }
722 mode = RADEON_SURF_MODE_1D;
723 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
724 surf->flags |= RADEON_SURF_SET(mode, MODE);
725 }
726
727 /* check tile split */
728 if (mode == RADEON_SURF_MODE_2D) {
729 switch (surf->tile_split) {
730 case 64:
731 case 128:
732 case 256:
733 case 512:
734 case 1024:
735 case 2048:
736 case 4096:
737 break;
738 default:
739 return -EINVAL;
740 }
741 switch (surf->mtilea) {
742 case 1:
743 case 2:
744 case 4:
745 case 8:
746 break;
747 default:
748 return -EINVAL;
749 }
750 /* check aspect ratio */
751 if (surf_man->hw_info.num_banks < surf->mtilea) {
752 return -EINVAL;
753 }
754 /* check bank width */
755 switch (surf->bankw) {
756 case 1:
757 case 2:
758 case 4:
759 case 8:
760 break;
761 default:
762 return -EINVAL;
763 }
764 /* check bank height */
765 switch (surf->bankh) {
766 case 1:
767 case 2:
768 case 4:
769 case 8:
770 break;
771 default:
772 return -EINVAL;
773 }
774 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
775 if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
776 return -EINVAL;
777 }
778 }
779
780 return 0;
781 }
782
eg_surface_init_1d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)783 static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
784 struct radeon_surface *surf)
785 {
786 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
787 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
788 /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */
789 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
790 struct radeon_surface_level *stencil_level =
791 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
792
793 r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
794 if (r)
795 return r;
796
797 if (is_depth_stencil) {
798 r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
799 surf->bo_size, 0);
800 surf->stencil_offset = stencil_level[0].offset;
801 }
802 return r;
803 }
804
eg_surface_init_2d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)805 static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
806 struct radeon_surface *surf)
807 {
808 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
809 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
810 /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */
811 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
812 struct radeon_surface_level *stencil_level =
813 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
814
815 r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
816 surf->tile_split, 0, 0);
817 if (r)
818 return r;
819
820 if (is_depth_stencil) {
821 r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
822 surf->stencil_tile_split, surf->bo_size, 0);
823 surf->stencil_offset = stencil_level[0].offset;
824 }
825 return r;
826 }
827
eg_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)828 static int eg_surface_init(struct radeon_surface_manager *surf_man,
829 struct radeon_surface *surf)
830 {
831 unsigned mode;
832 int r;
833
834 /* MSAA surfaces support the 2D mode only. */
835 if (surf->nsamples > 1) {
836 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
837 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
838 }
839
840 /* tiling mode */
841 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
842
843 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
844 /* zbuffer only support 1D or 2D tiled surface */
845 switch (mode) {
846 case RADEON_SURF_MODE_1D:
847 case RADEON_SURF_MODE_2D:
848 break;
849 default:
850 mode = RADEON_SURF_MODE_1D;
851 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
852 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
853 break;
854 }
855 }
856
857 r = eg_surface_sanity(surf_man, surf, mode);
858 if (r) {
859 return r;
860 }
861
862 surf->stencil_offset = 0;
863 surf->bo_alignment = 0;
864
865 /* check tiling mode */
866 switch (mode) {
867 case RADEON_SURF_MODE_LINEAR:
868 r = r6_surface_init_linear(surf_man, surf, 0, 0);
869 break;
870 case RADEON_SURF_MODE_LINEAR_ALIGNED:
871 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
872 break;
873 case RADEON_SURF_MODE_1D:
874 r = eg_surface_init_1d_miptrees(surf_man, surf);
875 break;
876 case RADEON_SURF_MODE_2D:
877 r = eg_surface_init_2d_miptrees(surf_man, surf);
878 break;
879 default:
880 return -EINVAL;
881 }
882 return r;
883 }
884
log2_int(unsigned x)885 static unsigned log2_int(unsigned x)
886 {
887 unsigned l;
888
889 if (x < 2) {
890 return 0;
891 }
892 for (l = 2; ; l++) {
893 if ((unsigned)(1 << l) > x) {
894 return l - 1;
895 }
896 }
897 return 0;
898 }
899
900 /* compute best tile_split, bankw, bankh, mtilea
901 * depending on surface
902 */
eg_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)903 static int eg_surface_best(struct radeon_surface_manager *surf_man,
904 struct radeon_surface *surf)
905 {
906 unsigned mode, tileb, h_over_w;
907 int r;
908
909 /* tiling mode */
910 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
911
912 /* set some default value to avoid sanity check choking on them */
913 surf->tile_split = 1024;
914 surf->bankw = 1;
915 surf->bankh = 1;
916 surf->mtilea = surf_man->hw_info.num_banks;
917 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
918 for (; surf->bankh <= 8; surf->bankh *= 2) {
919 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
920 break;
921 }
922 }
923 if (surf->mtilea > 8) {
924 surf->mtilea = 8;
925 }
926
927 r = eg_surface_sanity(surf_man, surf, mode);
928 if (r) {
929 return r;
930 }
931
932 if (mode != RADEON_SURF_MODE_2D) {
933 /* nothing to do for non 2D tiled surface */
934 return 0;
935 }
936
937 /* Tweak TILE_SPLIT for performance here. */
938 if (surf->nsamples > 1) {
939 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
940 switch (surf->nsamples) {
941 case 2:
942 surf->tile_split = 128;
943 break;
944 case 4:
945 surf->tile_split = 128;
946 break;
947 case 8:
948 surf->tile_split = 256;
949 break;
950 case 16: /* cayman only */
951 surf->tile_split = 512;
952 break;
953 default:
954 fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
955 surf->nsamples, __LINE__);
956 return -EINVAL;
957 }
958 surf->stencil_tile_split = 64;
959 } else {
960 /* tile split must be >= 256 for colorbuffer surfaces */
961 surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
962 if (surf->tile_split > 4096)
963 surf->tile_split = 4096;
964 }
965 } else {
966 /* set tile split to row size */
967 surf->tile_split = surf_man->hw_info.row_size;
968 surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
969 }
970
971 /* bankw or bankh greater than 1 increase alignment requirement, not
972 * sure if it's worth using smaller bankw & bankh to stick with 2D
973 * tiling on small surface rather than falling back to 1D tiling.
974 * Use recommanded value based on tile size for now.
975 *
976 * fmask buffer has different optimal value figure them out once we
977 * use it.
978 */
979 if (surf->flags & RADEON_SURF_SBUFFER) {
980 /* assume 1 bytes for stencil, we optimize for stencil as stencil
981 * and depth shares surface values
982 */
983 tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
984 } else {
985 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
986 }
987
988 /* use bankw of 1 to minimize width alignment, might be interesting to
989 * increase it for large surface
990 */
991 surf->bankw = 1;
992 switch (tileb) {
993 case 64:
994 surf->bankh = 4;
995 break;
996 case 128:
997 case 256:
998 surf->bankh = 2;
999 break;
1000 default:
1001 surf->bankh = 1;
1002 break;
1003 }
1004 /* double check the constraint */
1005 for (; surf->bankh <= 8; surf->bankh *= 2) {
1006 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
1007 break;
1008 }
1009 }
1010
1011 h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
1012 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
1013 surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
1014
1015 return 0;
1016 }
1017
1018
1019 /* ===========================================================================
1020 * Southern Islands family
1021 */
1022 #define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
1023 #define SI__PIPE_CONFIG__ADDR_SURF_P2 0
1024 #define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
1025 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
1026 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
1027 #define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
1028 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
1029 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
1030 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
1031 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
1032 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
1033 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
1034 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
1035 #define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
1036 #define SI__TILE_SPLIT__64B 0
1037 #define SI__TILE_SPLIT__128B 1
1038 #define SI__TILE_SPLIT__256B 2
1039 #define SI__TILE_SPLIT__512B 3
1040 #define SI__TILE_SPLIT__1024B 4
1041 #define SI__TILE_SPLIT__2048B 5
1042 #define SI__TILE_SPLIT__4096B 6
1043 #define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3)
1044 #define SI__BANK_WIDTH__1 0
1045 #define SI__BANK_WIDTH__2 1
1046 #define SI__BANK_WIDTH__4 2
1047 #define SI__BANK_WIDTH__8 3
1048 #define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3)
1049 #define SI__BANK_HEIGHT__1 0
1050 #define SI__BANK_HEIGHT__2 1
1051 #define SI__BANK_HEIGHT__4 2
1052 #define SI__BANK_HEIGHT__8 3
1053 #define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3)
1054 #define SI__MACRO_TILE_ASPECT__1 0
1055 #define SI__MACRO_TILE_ASPECT__2 1
1056 #define SI__MACRO_TILE_ASPECT__4 2
1057 #define SI__MACRO_TILE_ASPECT__8 3
1058 #define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3)
1059 #define SI__NUM_BANKS__2_BANK 0
1060 #define SI__NUM_BANKS__4_BANK 1
1061 #define SI__NUM_BANKS__8_BANK 2
1062 #define SI__NUM_BANKS__16_BANK 3
1063
1064
si_gb_tile_mode(uint32_t gb_tile_mode,unsigned * num_pipes,unsigned * num_banks,uint32_t * macro_tile_aspect,uint32_t * bank_w,uint32_t * bank_h,uint32_t * tile_split)1065 static void si_gb_tile_mode(uint32_t gb_tile_mode,
1066 unsigned *num_pipes,
1067 unsigned *num_banks,
1068 uint32_t *macro_tile_aspect,
1069 uint32_t *bank_w,
1070 uint32_t *bank_h,
1071 uint32_t *tile_split)
1072 {
1073 if (num_pipes) {
1074 switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1075 case SI__PIPE_CONFIG__ADDR_SURF_P2:
1076 default:
1077 *num_pipes = 2;
1078 break;
1079 case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1080 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1081 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1082 case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1083 *num_pipes = 4;
1084 break;
1085 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1086 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1087 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1088 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1089 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1090 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1091 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1092 *num_pipes = 8;
1093 break;
1094 }
1095 }
1096 if (num_banks) {
1097 switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
1098 default:
1099 case SI__NUM_BANKS__2_BANK:
1100 *num_banks = 2;
1101 break;
1102 case SI__NUM_BANKS__4_BANK:
1103 *num_banks = 4;
1104 break;
1105 case SI__NUM_BANKS__8_BANK:
1106 *num_banks = 8;
1107 break;
1108 case SI__NUM_BANKS__16_BANK:
1109 *num_banks = 16;
1110 break;
1111 }
1112 }
1113 if (macro_tile_aspect) {
1114 switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
1115 default:
1116 case SI__MACRO_TILE_ASPECT__1:
1117 *macro_tile_aspect = 1;
1118 break;
1119 case SI__MACRO_TILE_ASPECT__2:
1120 *macro_tile_aspect = 2;
1121 break;
1122 case SI__MACRO_TILE_ASPECT__4:
1123 *macro_tile_aspect = 4;
1124 break;
1125 case SI__MACRO_TILE_ASPECT__8:
1126 *macro_tile_aspect = 8;
1127 break;
1128 }
1129 }
1130 if (bank_w) {
1131 switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
1132 default:
1133 case SI__BANK_WIDTH__1:
1134 *bank_w = 1;
1135 break;
1136 case SI__BANK_WIDTH__2:
1137 *bank_w = 2;
1138 break;
1139 case SI__BANK_WIDTH__4:
1140 *bank_w = 4;
1141 break;
1142 case SI__BANK_WIDTH__8:
1143 *bank_w = 8;
1144 break;
1145 }
1146 }
1147 if (bank_h) {
1148 switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
1149 default:
1150 case SI__BANK_HEIGHT__1:
1151 *bank_h = 1;
1152 break;
1153 case SI__BANK_HEIGHT__2:
1154 *bank_h = 2;
1155 break;
1156 case SI__BANK_HEIGHT__4:
1157 *bank_h = 4;
1158 break;
1159 case SI__BANK_HEIGHT__8:
1160 *bank_h = 8;
1161 break;
1162 }
1163 }
1164 if (tile_split) {
1165 switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1166 default:
1167 case SI__TILE_SPLIT__64B:
1168 *tile_split = 64;
1169 break;
1170 case SI__TILE_SPLIT__128B:
1171 *tile_split = 128;
1172 break;
1173 case SI__TILE_SPLIT__256B:
1174 *tile_split = 256;
1175 break;
1176 case SI__TILE_SPLIT__512B:
1177 *tile_split = 512;
1178 break;
1179 case SI__TILE_SPLIT__1024B:
1180 *tile_split = 1024;
1181 break;
1182 case SI__TILE_SPLIT__2048B:
1183 *tile_split = 2048;
1184 break;
1185 case SI__TILE_SPLIT__4096B:
1186 *tile_split = 4096;
1187 break;
1188 }
1189 }
1190 }
1191
si_init_hw_info(struct radeon_surface_manager * surf_man)1192 static int si_init_hw_info(struct radeon_surface_manager *surf_man)
1193 {
1194 uint32_t tiling_config;
1195 drmVersionPtr version;
1196 int r;
1197
1198 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
1199 &tiling_config);
1200 if (r) {
1201 return r;
1202 }
1203
1204 surf_man->hw_info.allow_2d = 0;
1205 version = drmGetVersion(surf_man->fd);
1206 if (version && version->version_minor >= 33) {
1207 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
1208 surf_man->hw_info.allow_2d = 1;
1209 }
1210 }
1211 drmFreeVersion(version);
1212
1213 switch (tiling_config & 0xf) {
1214 case 0:
1215 surf_man->hw_info.num_pipes = 1;
1216 break;
1217 case 1:
1218 surf_man->hw_info.num_pipes = 2;
1219 break;
1220 case 2:
1221 surf_man->hw_info.num_pipes = 4;
1222 break;
1223 case 3:
1224 surf_man->hw_info.num_pipes = 8;
1225 break;
1226 default:
1227 surf_man->hw_info.num_pipes = 8;
1228 surf_man->hw_info.allow_2d = 0;
1229 break;
1230 }
1231
1232 switch ((tiling_config & 0xf0) >> 4) {
1233 case 0:
1234 surf_man->hw_info.num_banks = 4;
1235 break;
1236 case 1:
1237 surf_man->hw_info.num_banks = 8;
1238 break;
1239 case 2:
1240 surf_man->hw_info.num_banks = 16;
1241 break;
1242 default:
1243 surf_man->hw_info.num_banks = 8;
1244 surf_man->hw_info.allow_2d = 0;
1245 break;
1246 }
1247
1248 switch ((tiling_config & 0xf00) >> 8) {
1249 case 0:
1250 surf_man->hw_info.group_bytes = 256;
1251 break;
1252 case 1:
1253 surf_man->hw_info.group_bytes = 512;
1254 break;
1255 default:
1256 surf_man->hw_info.group_bytes = 256;
1257 surf_man->hw_info.allow_2d = 0;
1258 break;
1259 }
1260
1261 switch ((tiling_config & 0xf000) >> 12) {
1262 case 0:
1263 surf_man->hw_info.row_size = 1024;
1264 break;
1265 case 1:
1266 surf_man->hw_info.row_size = 2048;
1267 break;
1268 case 2:
1269 surf_man->hw_info.row_size = 4096;
1270 break;
1271 default:
1272 surf_man->hw_info.row_size = 4096;
1273 surf_man->hw_info.allow_2d = 0;
1274 break;
1275 }
1276 return 0;
1277 }
1278
si_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned mode,unsigned * tile_mode,unsigned * stencil_tile_mode)1279 static int si_surface_sanity(struct radeon_surface_manager *surf_man,
1280 struct radeon_surface *surf,
1281 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
1282 {
1283 uint32_t gb_tile_mode;
1284
1285 /* check surface dimension */
1286 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
1287 return -EINVAL;
1288 }
1289
1290 /* check mipmap last_level */
1291 if (surf->last_level > 15) {
1292 return -EINVAL;
1293 }
1294
1295 /* force 1d on kernel that can't do 2d */
1296 if (mode > RADEON_SURF_MODE_1D &&
1297 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
1298 if (surf->nsamples > 1) {
1299 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
1300 return -EFAULT;
1301 }
1302 mode = RADEON_SURF_MODE_1D;
1303 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1304 surf->flags |= RADEON_SURF_SET(mode, MODE);
1305 }
1306
1307 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
1308 return -EINVAL;
1309 }
1310
1311 if (!surf->tile_split) {
1312 /* default value */
1313 surf->mtilea = 1;
1314 surf->bankw = 1;
1315 surf->bankh = 1;
1316 surf->tile_split = 64;
1317 surf->stencil_tile_split = 64;
1318 }
1319
1320 switch (mode) {
1321 case RADEON_SURF_MODE_2D:
1322 if (surf->flags & RADEON_SURF_SBUFFER) {
1323 switch (surf->nsamples) {
1324 case 1:
1325 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1326 break;
1327 case 2:
1328 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1329 break;
1330 case 4:
1331 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1332 break;
1333 case 8:
1334 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1335 break;
1336 default:
1337 return -EINVAL;
1338 }
1339 /* retrieve tiling mode value */
1340 gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
1341 si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
1342 }
1343 if (surf->flags & RADEON_SURF_ZBUFFER) {
1344 switch (surf->nsamples) {
1345 case 1:
1346 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1347 break;
1348 case 2:
1349 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1350 break;
1351 case 4:
1352 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1353 break;
1354 case 8:
1355 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1356 break;
1357 default:
1358 return -EINVAL;
1359 }
1360 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1361 switch (surf->bpe) {
1362 case 2:
1363 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
1364 break;
1365 case 4:
1366 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
1367 break;
1368 default:
1369 return -EINVAL;
1370 }
1371 } else {
1372 switch (surf->bpe) {
1373 case 1:
1374 *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
1375 break;
1376 case 2:
1377 *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
1378 break;
1379 case 4:
1380 *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
1381 break;
1382 case 8:
1383 case 16:
1384 *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
1385 break;
1386 default:
1387 return -EINVAL;
1388 }
1389 }
1390 /* retrieve tiling mode value */
1391 gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
1392 si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
1393 break;
1394 case RADEON_SURF_MODE_1D:
1395 if (surf->flags & RADEON_SURF_SBUFFER) {
1396 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1397 }
1398 if (surf->flags & RADEON_SURF_ZBUFFER) {
1399 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1400 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1401 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1402 } else {
1403 *tile_mode = SI_TILE_MODE_COLOR_1D;
1404 }
1405 break;
1406 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1407 default:
1408 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
1409 }
1410
1411 return 0;
1412 }
1413
si_surf_minify(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,uint32_t xalign,uint32_t yalign,uint32_t zalign,uint32_t slice_align,uint64_t offset)1414 static void si_surf_minify(struct radeon_surface *surf,
1415 struct radeon_surface_level *surflevel,
1416 unsigned bpe, unsigned level,
1417 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1418 uint32_t slice_align, uint64_t offset)
1419 {
1420 if (level == 0) {
1421 surflevel->npix_x = surf->npix_x;
1422 } else {
1423 surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1424 }
1425 surflevel->npix_y = mip_minify(surf->npix_y, level);
1426 surflevel->npix_z = mip_minify(surf->npix_z, level);
1427
1428 if (level == 0 && surf->last_level > 0) {
1429 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1430 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1431 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1432 } else {
1433 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1434 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1435 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1436 }
1437
1438 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1439
1440 /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1441 * these are just guesses for the rules behind those
1442 */
1443 if (level == 0 && surf->last_level == 0)
1444 /* Non-mipmap pitch padded to slice alignment */
1445 /* Using just bpe here breaks stencil blitting; surf->bpe works. */
1446 xalign = MAX2(xalign, slice_align / surf->bpe);
1447 else if (surflevel->mode == RADEON_SURF_MODE_LINEAR_ALIGNED)
1448 /* Small rows evenly distributed across slice */
1449 xalign = MAX2(xalign, slice_align / bpe / surflevel->nblk_y);
1450
1451 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1452 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1453
1454 surflevel->offset = offset;
1455 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
1456 surflevel->slice_size = ALIGN((uint64_t)surflevel->pitch_bytes * surflevel->nblk_y,
1457 (uint64_t)slice_align);
1458
1459 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1460 }
1461
si_surf_minify_2d(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,unsigned slice_pt,uint32_t xalign,uint32_t yalign,uint32_t zalign,unsigned mtileb,uint64_t offset)1462 static void si_surf_minify_2d(struct radeon_surface *surf,
1463 struct radeon_surface_level *surflevel,
1464 unsigned bpe, unsigned level, unsigned slice_pt,
1465 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1466 unsigned mtileb, uint64_t offset)
1467 {
1468 unsigned mtile_pr, mtile_ps;
1469
1470 if (level == 0) {
1471 surflevel->npix_x = surf->npix_x;
1472 } else {
1473 surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1474 }
1475 surflevel->npix_y = mip_minify(surf->npix_y, level);
1476 surflevel->npix_z = mip_minify(surf->npix_z, level);
1477
1478 if (level == 0 && surf->last_level > 0) {
1479 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1480 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1481 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1482 } else {
1483 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1484 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1485 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1486 }
1487
1488 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
1489 !(surf->flags & RADEON_SURF_FMASK)) {
1490 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
1491 surflevel->mode = RADEON_SURF_MODE_1D;
1492 return;
1493 }
1494 }
1495 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1496 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1497 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1498
1499 /* macro tile per row */
1500 mtile_pr = surflevel->nblk_x / xalign;
1501 /* macro tile per slice */
1502 mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
1503 surflevel->offset = offset;
1504 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
1505 surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt;
1506
1507 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1508 }
1509
si_surface_init_linear_aligned(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,uint64_t offset,unsigned start_level)1510 static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1511 struct radeon_surface *surf,
1512 unsigned tile_mode,
1513 uint64_t offset, unsigned start_level)
1514 {
1515 uint32_t xalign, yalign, zalign, slice_align;
1516 unsigned i;
1517
1518 /* compute alignment */
1519 if (!start_level) {
1520 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1521 }
1522 xalign = MAX2(8, 64 / surf->bpe);
1523 yalign = 1;
1524 zalign = 1;
1525 slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1526
1527 /* build mipmap tree */
1528 for (i = start_level; i <= surf->last_level; i++) {
1529 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1530 si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
1531 /* level0 and first mipmap need to have alignment */
1532 offset = surf->bo_size;
1533 if (i == 0) {
1534 offset = ALIGN(offset, surf->bo_alignment);
1535 }
1536 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1537 surf->tiling_index[i] = tile_mode;
1538 }
1539 }
1540 return 0;
1541 }
1542
si_surface_init_1d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_mode,uint64_t offset,unsigned start_level)1543 static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1544 struct radeon_surface *surf,
1545 struct radeon_surface_level *level,
1546 unsigned bpe, unsigned tile_mode,
1547 uint64_t offset, unsigned start_level)
1548 {
1549 uint32_t xalign, yalign, zalign, slice_align;
1550 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
1551 unsigned i;
1552
1553 /* compute alignment */
1554 xalign = 8;
1555 yalign = 8;
1556 zalign = 1;
1557 slice_align = surf_man->hw_info.group_bytes;
1558 if (surf->flags & RADEON_SURF_SCANOUT) {
1559 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1560 }
1561
1562 if (start_level <= 1) {
1563 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1564
1565 if (offset) {
1566 offset = ALIGN(offset, alignment);
1567 }
1568 }
1569
1570 /* build mipmap tree */
1571 for (i = start_level; i <= surf->last_level; i++) {
1572 level[i].mode = RADEON_SURF_MODE_1D;
1573 si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1574 /* level0 and first mipmap need to have alignment */
1575 offset = surf->bo_size;
1576 if (i == 0) {
1577 offset = ALIGN(offset, alignment);
1578 }
1579 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1580 if (surf->level == level) {
1581 surf->tiling_index[i] = tile_mode;
1582 /* it's ok because stencil is done after */
1583 surf->stencil_tiling_index[i] = tile_mode;
1584 } else {
1585 surf->stencil_tiling_index[i] = tile_mode;
1586 }
1587 }
1588 }
1589 return 0;
1590 }
1591
si_surface_init_1d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,unsigned stencil_tile_mode)1592 static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1593 struct radeon_surface *surf,
1594 unsigned tile_mode, unsigned stencil_tile_mode)
1595 {
1596 int r;
1597
1598 r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
1599 if (r) {
1600 return r;
1601 }
1602
1603 if (surf->flags & RADEON_SURF_SBUFFER) {
1604 r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
1605 surf->stencil_offset = surf->stencil_level[0].offset;
1606 }
1607 return r;
1608 }
1609
si_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_mode,unsigned num_pipes,unsigned num_banks,unsigned tile_split,uint64_t offset,unsigned start_level)1610 static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
1611 struct radeon_surface *surf,
1612 struct radeon_surface_level *level,
1613 unsigned bpe, unsigned tile_mode,
1614 unsigned num_pipes, unsigned num_banks,
1615 unsigned tile_split,
1616 uint64_t offset,
1617 unsigned start_level)
1618 {
1619 uint64_t aligned_offset = offset;
1620 unsigned tilew, tileh, tileb;
1621 unsigned mtilew, mtileh, mtileb;
1622 unsigned slice_pt;
1623 unsigned i;
1624
1625 /* compute tile values */
1626 tilew = 8;
1627 tileh = 8;
1628 tileb = tilew * tileh * bpe * surf->nsamples;
1629 /* slices per tile */
1630 slice_pt = 1;
1631 if (tileb > tile_split && tile_split) {
1632 slice_pt = tileb / tile_split;
1633 }
1634 tileb = tileb / slice_pt;
1635
1636 /* macro tile width & height */
1637 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
1638 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
1639
1640 /* macro tile bytes */
1641 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
1642
1643 if (start_level <= 1) {
1644 unsigned alignment = MAX2(256, mtileb);
1645 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1646
1647 if (aligned_offset) {
1648 aligned_offset = ALIGN(aligned_offset, alignment);
1649 }
1650 }
1651
1652 /* build mipmap tree */
1653 for (i = start_level; i <= surf->last_level; i++) {
1654 level[i].mode = RADEON_SURF_MODE_2D;
1655 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
1656 if (level[i].mode == RADEON_SURF_MODE_1D) {
1657 switch (tile_mode) {
1658 case SI_TILE_MODE_COLOR_2D_8BPP:
1659 case SI_TILE_MODE_COLOR_2D_16BPP:
1660 case SI_TILE_MODE_COLOR_2D_32BPP:
1661 case SI_TILE_MODE_COLOR_2D_64BPP:
1662 tile_mode = SI_TILE_MODE_COLOR_1D;
1663 break;
1664 case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
1665 case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
1666 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1667 break;
1668 case SI_TILE_MODE_DEPTH_STENCIL_2D:
1669 tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1670 break;
1671 default:
1672 return -EINVAL;
1673 }
1674 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
1675 }
1676 /* level0 and first mipmap need to have alignment */
1677 aligned_offset = offset = surf->bo_size;
1678 if (i == 0) {
1679 aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
1680 }
1681 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1682 if (surf->level == level) {
1683 surf->tiling_index[i] = tile_mode;
1684 /* it's ok because stencil is done after */
1685 surf->stencil_tiling_index[i] = tile_mode;
1686 } else {
1687 surf->stencil_tiling_index[i] = tile_mode;
1688 }
1689 }
1690 }
1691 return 0;
1692 }
1693
si_surface_init_2d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,unsigned stencil_tile_mode)1694 static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
1695 struct radeon_surface *surf,
1696 unsigned tile_mode, unsigned stencil_tile_mode)
1697 {
1698 unsigned num_pipes, num_banks;
1699 uint32_t gb_tile_mode;
1700 int r;
1701
1702 /* retrieve tiling mode value */
1703 gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1704 si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
1705
1706 r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
1707 if (r) {
1708 return r;
1709 }
1710
1711 if (surf->flags & RADEON_SURF_SBUFFER) {
1712 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);
1713 surf->stencil_offset = surf->stencil_level[0].offset;
1714 }
1715 return r;
1716 }
1717
si_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)1718 static int si_surface_init(struct radeon_surface_manager *surf_man,
1719 struct radeon_surface *surf)
1720 {
1721 unsigned mode, tile_mode, stencil_tile_mode;
1722 int r;
1723
1724 /* MSAA surfaces support the 2D mode only. */
1725 if (surf->nsamples > 1) {
1726 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1727 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1728 }
1729
1730 /* tiling mode */
1731 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1732
1733 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1734 /* zbuffer only support 1D or 2D tiled surface */
1735 switch (mode) {
1736 case RADEON_SURF_MODE_1D:
1737 case RADEON_SURF_MODE_2D:
1738 break;
1739 default:
1740 mode = RADEON_SURF_MODE_1D;
1741 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1742 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1743 break;
1744 }
1745 }
1746
1747 r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1748 if (r) {
1749 return r;
1750 }
1751
1752 surf->stencil_offset = 0;
1753 surf->bo_alignment = 0;
1754
1755 /* check tiling mode */
1756 switch (mode) {
1757 case RADEON_SURF_MODE_LINEAR:
1758 r = r6_surface_init_linear(surf_man, surf, 0, 0);
1759 break;
1760 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1761 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
1762 break;
1763 case RADEON_SURF_MODE_1D:
1764 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1765 break;
1766 case RADEON_SURF_MODE_2D:
1767 r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1768 break;
1769 default:
1770 return -EINVAL;
1771 }
1772 return r;
1773 }
1774
1775 /*
1776 * depending on surface
1777 */
si_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)1778 static int si_surface_best(struct radeon_surface_manager *surf_man,
1779 struct radeon_surface *surf)
1780 {
1781 unsigned mode, tile_mode, stencil_tile_mode;
1782
1783 /* tiling mode */
1784 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1785
1786 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
1787 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
1788 /* depth/stencil force 1d tiling for old mesa */
1789 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1790 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1791 }
1792
1793 return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1794 }
1795
1796
1797 /* ===========================================================================
1798 * Sea Islands family
1799 */
1800 #define CIK__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
1801 #define CIK__PIPE_CONFIG__ADDR_SURF_P2 0
1802 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
1803 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
1804 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
1805 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
1806 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
1807 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
1808 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
1809 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
1810 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
1811 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
1812 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
1813 #define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16 16
1814 #define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16 17
1815 #define CIK__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
1816 #define CIK__TILE_SPLIT__64B 0
1817 #define CIK__TILE_SPLIT__128B 1
1818 #define CIK__TILE_SPLIT__256B 2
1819 #define CIK__TILE_SPLIT__512B 3
1820 #define CIK__TILE_SPLIT__1024B 4
1821 #define CIK__TILE_SPLIT__2048B 5
1822 #define CIK__TILE_SPLIT__4096B 6
1823 #define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x) (((x) >> 25) & 0x3)
1824 #define CIK__SAMPLE_SPLIT__1 0
1825 #define CIK__SAMPLE_SPLIT__2 1
1826 #define CIK__SAMPLE_SPLIT__4 2
1827 #define CIK__SAMPLE_SPLIT__8 3
1828 #define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x) ((x) & 0x3)
1829 #define CIK__BANK_WIDTH__1 0
1830 #define CIK__BANK_WIDTH__2 1
1831 #define CIK__BANK_WIDTH__4 2
1832 #define CIK__BANK_WIDTH__8 3
1833 #define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x) (((x) >> 2) & 0x3)
1834 #define CIK__BANK_HEIGHT__1 0
1835 #define CIK__BANK_HEIGHT__2 1
1836 #define CIK__BANK_HEIGHT__4 2
1837 #define CIK__BANK_HEIGHT__8 3
1838 #define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3)
1839 #define CIK__MACRO_TILE_ASPECT__1 0
1840 #define CIK__MACRO_TILE_ASPECT__2 1
1841 #define CIK__MACRO_TILE_ASPECT__4 2
1842 #define CIK__MACRO_TILE_ASPECT__8 3
1843 #define CIK__GB_MACROTILE_MODE__NUM_BANKS(x) (((x) >> 6) & 0x3)
1844 #define CIK__NUM_BANKS__2_BANK 0
1845 #define CIK__NUM_BANKS__4_BANK 1
1846 #define CIK__NUM_BANKS__8_BANK 2
1847 #define CIK__NUM_BANKS__16_BANK 3
1848
1849
cik_get_2d_params(struct radeon_surface_manager * surf_man,unsigned bpe,unsigned nsamples,bool is_color,unsigned tile_mode,uint32_t * num_pipes,uint32_t * tile_split_ptr,uint32_t * num_banks,uint32_t * macro_tile_aspect,uint32_t * bank_w,uint32_t * bank_h)1850 static void cik_get_2d_params(struct radeon_surface_manager *surf_man,
1851 unsigned bpe, unsigned nsamples, bool is_color,
1852 unsigned tile_mode,
1853 uint32_t *num_pipes,
1854 uint32_t *tile_split_ptr,
1855 uint32_t *num_banks,
1856 uint32_t *macro_tile_aspect,
1857 uint32_t *bank_w,
1858 uint32_t *bank_h)
1859 {
1860 uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1861 unsigned tileb_1x, tileb;
1862 unsigned gb_macrotile_mode;
1863 unsigned macrotile_index;
1864 unsigned tile_split, sample_split;
1865
1866 if (num_pipes) {
1867 switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1868 case CIK__PIPE_CONFIG__ADDR_SURF_P2:
1869 default:
1870 *num_pipes = 2;
1871 break;
1872 case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1873 case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1874 case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1875 case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1876 *num_pipes = 4;
1877 break;
1878 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1879 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1880 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1881 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1882 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1883 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1884 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1885 *num_pipes = 8;
1886 break;
1887 case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16:
1888 case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16:
1889 *num_pipes = 16;
1890 break;
1891 }
1892 }
1893 switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1894 default:
1895 case CIK__TILE_SPLIT__64B:
1896 tile_split = 64;
1897 break;
1898 case CIK__TILE_SPLIT__128B:
1899 tile_split = 128;
1900 break;
1901 case CIK__TILE_SPLIT__256B:
1902 tile_split = 256;
1903 break;
1904 case CIK__TILE_SPLIT__512B:
1905 tile_split = 512;
1906 break;
1907 case CIK__TILE_SPLIT__1024B:
1908 tile_split = 1024;
1909 break;
1910 case CIK__TILE_SPLIT__2048B:
1911 tile_split = 2048;
1912 break;
1913 case CIK__TILE_SPLIT__4096B:
1914 tile_split = 4096;
1915 break;
1916 }
1917 switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) {
1918 default:
1919 case CIK__SAMPLE_SPLIT__1:
1920 sample_split = 1;
1921 break;
1922 case CIK__SAMPLE_SPLIT__2:
1923 sample_split = 2;
1924 break;
1925 case CIK__SAMPLE_SPLIT__4:
1926 sample_split = 4;
1927 break;
1928 case CIK__SAMPLE_SPLIT__8:
1929 sample_split = 8;
1930 break;
1931 }
1932
1933 /* Adjust the tile split. */
1934 tileb_1x = 8 * 8 * bpe;
1935 if (is_color) {
1936 tile_split = MAX2(256, sample_split * tileb_1x);
1937 }
1938 tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
1939
1940 /* Determine the macrotile index. */
1941 tileb = MIN2(tile_split, nsamples * tileb_1x);
1942
1943 for (macrotile_index = 0; tileb > 64; macrotile_index++) {
1944 tileb >>= 1;
1945 }
1946 gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index];
1947
1948 if (tile_split_ptr) {
1949 *tile_split_ptr = tile_split;
1950 }
1951 if (num_banks) {
1952 switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) {
1953 default:
1954 case CIK__NUM_BANKS__2_BANK:
1955 *num_banks = 2;
1956 break;
1957 case CIK__NUM_BANKS__4_BANK:
1958 *num_banks = 4;
1959 break;
1960 case CIK__NUM_BANKS__8_BANK:
1961 *num_banks = 8;
1962 break;
1963 case CIK__NUM_BANKS__16_BANK:
1964 *num_banks = 16;
1965 break;
1966 }
1967 }
1968 if (macro_tile_aspect) {
1969 switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) {
1970 default:
1971 case CIK__MACRO_TILE_ASPECT__1:
1972 *macro_tile_aspect = 1;
1973 break;
1974 case CIK__MACRO_TILE_ASPECT__2:
1975 *macro_tile_aspect = 2;
1976 break;
1977 case CIK__MACRO_TILE_ASPECT__4:
1978 *macro_tile_aspect = 4;
1979 break;
1980 case CIK__MACRO_TILE_ASPECT__8:
1981 *macro_tile_aspect = 8;
1982 break;
1983 }
1984 }
1985 if (bank_w) {
1986 switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) {
1987 default:
1988 case CIK__BANK_WIDTH__1:
1989 *bank_w = 1;
1990 break;
1991 case CIK__BANK_WIDTH__2:
1992 *bank_w = 2;
1993 break;
1994 case CIK__BANK_WIDTH__4:
1995 *bank_w = 4;
1996 break;
1997 case CIK__BANK_WIDTH__8:
1998 *bank_w = 8;
1999 break;
2000 }
2001 }
2002 if (bank_h) {
2003 switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) {
2004 default:
2005 case CIK__BANK_HEIGHT__1:
2006 *bank_h = 1;
2007 break;
2008 case CIK__BANK_HEIGHT__2:
2009 *bank_h = 2;
2010 break;
2011 case CIK__BANK_HEIGHT__4:
2012 *bank_h = 4;
2013 break;
2014 case CIK__BANK_HEIGHT__8:
2015 *bank_h = 8;
2016 break;
2017 }
2018 }
2019 }
2020
cik_init_hw_info(struct radeon_surface_manager * surf_man)2021 static int cik_init_hw_info(struct radeon_surface_manager *surf_man)
2022 {
2023 uint32_t tiling_config;
2024 drmVersionPtr version;
2025 int r;
2026
2027 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
2028 &tiling_config);
2029 if (r) {
2030 return r;
2031 }
2032
2033 surf_man->hw_info.allow_2d = 0;
2034 version = drmGetVersion(surf_man->fd);
2035 if (version && version->version_minor >= 35) {
2036 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) &&
2037 !radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_mode_array)) {
2038 surf_man->hw_info.allow_2d = 1;
2039 }
2040 }
2041 drmFreeVersion(version);
2042
2043 switch (tiling_config & 0xf) {
2044 case 0:
2045 surf_man->hw_info.num_pipes = 1;
2046 break;
2047 case 1:
2048 surf_man->hw_info.num_pipes = 2;
2049 break;
2050 case 2:
2051 surf_man->hw_info.num_pipes = 4;
2052 break;
2053 case 3:
2054 surf_man->hw_info.num_pipes = 8;
2055 break;
2056 default:
2057 surf_man->hw_info.num_pipes = 8;
2058 surf_man->hw_info.allow_2d = 0;
2059 break;
2060 }
2061
2062 switch ((tiling_config & 0xf0) >> 4) {
2063 case 0:
2064 surf_man->hw_info.num_banks = 4;
2065 break;
2066 case 1:
2067 surf_man->hw_info.num_banks = 8;
2068 break;
2069 case 2:
2070 surf_man->hw_info.num_banks = 16;
2071 break;
2072 default:
2073 surf_man->hw_info.num_banks = 8;
2074 surf_man->hw_info.allow_2d = 0;
2075 break;
2076 }
2077
2078 switch ((tiling_config & 0xf00) >> 8) {
2079 case 0:
2080 surf_man->hw_info.group_bytes = 256;
2081 break;
2082 case 1:
2083 surf_man->hw_info.group_bytes = 512;
2084 break;
2085 default:
2086 surf_man->hw_info.group_bytes = 256;
2087 surf_man->hw_info.allow_2d = 0;
2088 break;
2089 }
2090
2091 switch ((tiling_config & 0xf000) >> 12) {
2092 case 0:
2093 surf_man->hw_info.row_size = 1024;
2094 break;
2095 case 1:
2096 surf_man->hw_info.row_size = 2048;
2097 break;
2098 case 2:
2099 surf_man->hw_info.row_size = 4096;
2100 break;
2101 default:
2102 surf_man->hw_info.row_size = 4096;
2103 surf_man->hw_info.allow_2d = 0;
2104 break;
2105 }
2106 return 0;
2107 }
2108
cik_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned mode,unsigned * tile_mode,unsigned * stencil_tile_mode)2109 static int cik_surface_sanity(struct radeon_surface_manager *surf_man,
2110 struct radeon_surface *surf,
2111 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
2112 {
2113 /* check surface dimension */
2114 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
2115 return -EINVAL;
2116 }
2117
2118 /* check mipmap last_level */
2119 if (surf->last_level > 15) {
2120 return -EINVAL;
2121 }
2122
2123 /* force 1d on kernel that can't do 2d */
2124 if (mode > RADEON_SURF_MODE_1D &&
2125 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
2126 if (surf->nsamples > 1) {
2127 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
2128 return -EFAULT;
2129 }
2130 mode = RADEON_SURF_MODE_1D;
2131 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2132 surf->flags |= RADEON_SURF_SET(mode, MODE);
2133 }
2134
2135 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
2136 return -EINVAL;
2137 }
2138
2139 if (!surf->tile_split) {
2140 /* default value */
2141 surf->mtilea = 1;
2142 surf->bankw = 1;
2143 surf->bankh = 1;
2144 surf->tile_split = 64;
2145 surf->stencil_tile_split = 64;
2146 }
2147
2148 switch (mode) {
2149 case RADEON_SURF_MODE_2D: {
2150 if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) {
2151 switch (surf->nsamples) {
2152 case 1:
2153 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64;
2154 break;
2155 case 2:
2156 case 4:
2157 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128;
2158 break;
2159 case 8:
2160 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256;
2161 break;
2162 default:
2163 return -EINVAL;
2164 }
2165
2166 if (surf->flags & RADEON_SURF_SBUFFER) {
2167 *stencil_tile_mode = *tile_mode;
2168
2169 cik_get_2d_params(surf_man, 1, surf->nsamples, false,
2170 *stencil_tile_mode, NULL,
2171 &surf->stencil_tile_split,
2172 NULL, NULL, NULL, NULL);
2173 }
2174 } else if (surf->flags & RADEON_SURF_SCANOUT) {
2175 *tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT;
2176 } else {
2177 *tile_mode = CIK_TILE_MODE_COLOR_2D;
2178 }
2179
2180 /* retrieve tiling mode values */
2181 cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2182 !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode,
2183 NULL, &surf->tile_split, NULL, &surf->mtilea,
2184 &surf->bankw, &surf->bankh);
2185 break;
2186 }
2187 case RADEON_SURF_MODE_1D:
2188 if (surf->flags & RADEON_SURF_SBUFFER) {
2189 *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2190 }
2191 if (surf->flags & RADEON_SURF_ZBUFFER) {
2192 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2193 } else if (surf->flags & RADEON_SURF_SCANOUT) {
2194 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2195 } else {
2196 *tile_mode = SI_TILE_MODE_COLOR_1D;
2197 }
2198 break;
2199 case RADEON_SURF_MODE_LINEAR_ALIGNED:
2200 default:
2201 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
2202 }
2203
2204 return 0;
2205 }
2206
cik_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_mode,unsigned tile_split,unsigned num_pipes,unsigned num_banks,uint64_t offset,unsigned start_level)2207 static int cik_surface_init_2d(struct radeon_surface_manager *surf_man,
2208 struct radeon_surface *surf,
2209 struct radeon_surface_level *level,
2210 unsigned bpe, unsigned tile_mode,
2211 unsigned tile_split,
2212 unsigned num_pipes, unsigned num_banks,
2213 uint64_t offset,
2214 unsigned start_level)
2215 {
2216 uint64_t aligned_offset = offset;
2217 unsigned tilew, tileh, tileb_1x, tileb;
2218 unsigned mtilew, mtileh, mtileb;
2219 unsigned slice_pt;
2220 unsigned i;
2221
2222 /* compute tile values */
2223 tilew = 8;
2224 tileh = 8;
2225 tileb_1x = tilew * tileh * bpe;
2226
2227 tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
2228
2229 tileb = surf->nsamples * tileb_1x;
2230
2231 /* slices per tile */
2232 slice_pt = 1;
2233 if (tileb > tile_split && tile_split) {
2234 slice_pt = tileb / tile_split;
2235 tileb = tileb / slice_pt;
2236 }
2237
2238 /* macro tile width & height */
2239 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
2240 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
2241
2242 /* macro tile bytes */
2243 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
2244
2245 if (start_level <= 1) {
2246 unsigned alignment = MAX2(256, mtileb);
2247 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
2248
2249 if (aligned_offset) {
2250 aligned_offset = ALIGN(aligned_offset, alignment);
2251 }
2252 }
2253
2254 /* build mipmap tree */
2255 for (i = start_level; i <= surf->last_level; i++) {
2256 level[i].mode = RADEON_SURF_MODE_2D;
2257 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
2258 if (level[i].mode == RADEON_SURF_MODE_1D) {
2259 switch (tile_mode) {
2260 case CIK_TILE_MODE_COLOR_2D:
2261 tile_mode = SI_TILE_MODE_COLOR_1D;
2262 break;
2263 case CIK_TILE_MODE_COLOR_2D_SCANOUT:
2264 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2265 break;
2266 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64:
2267 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128:
2268 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256:
2269 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512:
2270 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE:
2271 tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2272 break;
2273 default:
2274 return -EINVAL;
2275 }
2276 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
2277 }
2278 /* level0 and first mipmap need to have alignment */
2279 aligned_offset = offset = surf->bo_size;
2280 if (i == 0) {
2281 aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
2282 }
2283 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
2284 if (surf->level == level) {
2285 surf->tiling_index[i] = tile_mode;
2286 /* it's ok because stencil is done after */
2287 surf->stencil_tiling_index[i] = tile_mode;
2288 } else {
2289 surf->stencil_tiling_index[i] = tile_mode;
2290 }
2291 }
2292 }
2293 return 0;
2294 }
2295
cik_surface_init_2d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,unsigned stencil_tile_mode)2296 static int cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
2297 struct radeon_surface *surf,
2298 unsigned tile_mode, unsigned stencil_tile_mode)
2299 {
2300 int r;
2301 uint32_t num_pipes, num_banks;
2302
2303 cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2304 !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode,
2305 &num_pipes, NULL, &num_banks, NULL, NULL, NULL);
2306
2307 r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode,
2308 surf->tile_split, num_pipes, num_banks, 0, 0);
2309 if (r) {
2310 return r;
2311 }
2312
2313 if (surf->flags & RADEON_SURF_SBUFFER) {
2314 r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode,
2315 surf->stencil_tile_split, num_pipes, num_banks,
2316 surf->bo_size, 0);
2317 surf->stencil_offset = surf->stencil_level[0].offset;
2318 }
2319 return r;
2320 }
2321
cik_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2322 static int cik_surface_init(struct radeon_surface_manager *surf_man,
2323 struct radeon_surface *surf)
2324 {
2325 unsigned mode, tile_mode, stencil_tile_mode;
2326 int r;
2327
2328 /* MSAA surfaces support the 2D mode only. */
2329 if (surf->nsamples > 1) {
2330 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2331 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
2332 }
2333
2334 /* tiling mode */
2335 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2336
2337 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
2338 /* zbuffer only support 1D or 2D tiled surface */
2339 switch (mode) {
2340 case RADEON_SURF_MODE_1D:
2341 case RADEON_SURF_MODE_2D:
2342 break;
2343 default:
2344 mode = RADEON_SURF_MODE_1D;
2345 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2346 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2347 break;
2348 }
2349 }
2350
2351 r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2352 if (r) {
2353 return r;
2354 }
2355
2356 surf->stencil_offset = 0;
2357 surf->bo_alignment = 0;
2358
2359 /* check tiling mode */
2360 switch (mode) {
2361 case RADEON_SURF_MODE_LINEAR:
2362 r = r6_surface_init_linear(surf_man, surf, 0, 0);
2363 break;
2364 case RADEON_SURF_MODE_LINEAR_ALIGNED:
2365 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
2366 break;
2367 case RADEON_SURF_MODE_1D:
2368 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2369 break;
2370 case RADEON_SURF_MODE_2D:
2371 r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2372 break;
2373 default:
2374 return -EINVAL;
2375 }
2376 return r;
2377 }
2378
2379 /*
2380 * depending on surface
2381 */
cik_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2382 static int cik_surface_best(struct radeon_surface_manager *surf_man,
2383 struct radeon_surface *surf)
2384 {
2385 unsigned mode, tile_mode, stencil_tile_mode;
2386
2387 /* tiling mode */
2388 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2389
2390 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
2391 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
2392 /* depth/stencil force 1d tiling for old mesa */
2393 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2394 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2395 }
2396
2397 return cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2398 }
2399
2400
2401 /* ===========================================================================
2402 * public API
2403 */
2404 struct radeon_surface_manager *
radeon_surface_manager_new(int fd)2405 radeon_surface_manager_new(int fd)
2406 {
2407 struct radeon_surface_manager *surf_man;
2408
2409 surf_man = calloc(1, sizeof(struct radeon_surface_manager));
2410 if (surf_man == NULL) {
2411 return NULL;
2412 }
2413 surf_man->fd = fd;
2414 if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
2415 goto out_err;
2416 }
2417 if (radeon_get_family(surf_man)) {
2418 goto out_err;
2419 }
2420
2421 if (surf_man->family <= CHIP_RV740) {
2422 if (r6_init_hw_info(surf_man)) {
2423 goto out_err;
2424 }
2425 surf_man->surface_init = &r6_surface_init;
2426 surf_man->surface_best = &r6_surface_best;
2427 } else if (surf_man->family <= CHIP_ARUBA) {
2428 if (eg_init_hw_info(surf_man)) {
2429 goto out_err;
2430 }
2431 surf_man->surface_init = &eg_surface_init;
2432 surf_man->surface_best = &eg_surface_best;
2433 } else if (surf_man->family < CHIP_BONAIRE) {
2434 if (si_init_hw_info(surf_man)) {
2435 goto out_err;
2436 }
2437 surf_man->surface_init = &si_surface_init;
2438 surf_man->surface_best = &si_surface_best;
2439 } else {
2440 if (cik_init_hw_info(surf_man)) {
2441 goto out_err;
2442 }
2443 surf_man->surface_init = &cik_surface_init;
2444 surf_man->surface_best = &cik_surface_best;
2445 }
2446
2447 return surf_man;
2448 out_err:
2449 free(surf_man);
2450 return NULL;
2451 }
2452
2453 void
radeon_surface_manager_free(struct radeon_surface_manager * surf_man)2454 radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
2455 {
2456 free(surf_man);
2457 }
2458
radeon_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned type,unsigned mode)2459 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
2460 struct radeon_surface *surf,
2461 unsigned type,
2462 unsigned mode)
2463 {
2464 if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
2465 return -EINVAL;
2466 }
2467
2468 /* all dimension must be at least 1 ! */
2469 if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
2470 return -EINVAL;
2471 }
2472 if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
2473 return -EINVAL;
2474 }
2475 if (!surf->array_size) {
2476 return -EINVAL;
2477 }
2478 /* array size must be a power of 2 */
2479 surf->array_size = next_power_of_two(surf->array_size);
2480
2481 switch (surf->nsamples) {
2482 case 1:
2483 case 2:
2484 case 4:
2485 case 8:
2486 break;
2487 default:
2488 return -EINVAL;
2489 }
2490 /* check type */
2491 switch (type) {
2492 case RADEON_SURF_TYPE_1D:
2493 if (surf->npix_y > 1) {
2494 return -EINVAL;
2495 }
2496 case RADEON_SURF_TYPE_2D:
2497 if (surf->npix_z > 1) {
2498 return -EINVAL;
2499 }
2500 break;
2501 case RADEON_SURF_TYPE_CUBEMAP:
2502 if (surf->npix_z > 1) {
2503 return -EINVAL;
2504 }
2505 /* deal with cubemap as they were texture array */
2506 if (surf_man->family >= CHIP_RV770) {
2507 surf->array_size = 8;
2508 } else {
2509 surf->array_size = 6;
2510 }
2511 break;
2512 case RADEON_SURF_TYPE_3D:
2513 break;
2514 case RADEON_SURF_TYPE_1D_ARRAY:
2515 if (surf->npix_y > 1) {
2516 return -EINVAL;
2517 }
2518 case RADEON_SURF_TYPE_2D_ARRAY:
2519 break;
2520 default:
2521 return -EINVAL;
2522 }
2523 return 0;
2524 }
2525
2526 int
radeon_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2527 radeon_surface_init(struct radeon_surface_manager *surf_man,
2528 struct radeon_surface *surf)
2529 {
2530 unsigned mode, type;
2531 int r;
2532
2533 type = RADEON_SURF_GET(surf->flags, TYPE);
2534 mode = RADEON_SURF_GET(surf->flags, MODE);
2535
2536 r = radeon_surface_sanity(surf_man, surf, type, mode);
2537 if (r) {
2538 return r;
2539 }
2540 return surf_man->surface_init(surf_man, surf);
2541 }
2542
2543 int
radeon_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2544 radeon_surface_best(struct radeon_surface_manager *surf_man,
2545 struct radeon_surface *surf)
2546 {
2547 unsigned mode, type;
2548 int r;
2549
2550 type = RADEON_SURF_GET(surf->flags, TYPE);
2551 mode = RADEON_SURF_GET(surf->flags, MODE);
2552
2553 r = radeon_surface_sanity(surf_man, surf, type, mode);
2554 if (r) {
2555 return r;
2556 }
2557 return surf_man->surface_best(surf_man, surf);
2558 }
2559