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