aboutsummaryrefslogtreecommitdiffstats
path: root/radeon
diff options
context:
space:
mode:
authorJerome Glisse2011-12-09 20:07:15 -0600
committerJerome Glisse2012-02-01 16:11:29 -0600
commitc51f7f0e460dcadb9f1a56ecf1615810877c33c8 (patch)
tree25cfc7eba38eefb4da051ac59529b4808dec0683 /radeon
parent151cdcfe685ee280a4344dfc40e6087d74a5590f (diff)
downloadlibdrm-c51f7f0e460dcadb9f1a56ecf1615810877c33c8.tar.gz
libdrm-c51f7f0e460dcadb9f1a56ecf1615810877c33c8.tar.xz
libdrm-c51f7f0e460dcadb9f1a56ecf1615810877c33c8.zip
radeon: add surface allocator helper v10
The surface allocator is able to build complete miptree when allocating surface for r600/r700/evergreen/northern islands GPU family. It also compute bo size and alignment for render buffer, depth buffer and scanout buffer. v2 fix r6xx/r7xx 2D tiling width align computation v3 add tile split support and fix 1d texture alignment v4 rework to more properly support compressed format, split surface pixel size and surface element size in separate fields v5 support texture array (still issue on r6xx) v6 split surface value computation and mipmap tree building, rework eg and newer computation v7 add a check for tile split and 2d tiled v8 initialize mode value before testing it in all case, reenable 2D macro tile mode on r6xx for cubemap and array. Fix cubemap to force array size to the number of face. v9 fix handling of stencil buffer on evergreen v10 on evergreen depth buffer need to have enough room for a stencil buffer just after depth one Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Diffstat (limited to 'radeon')
-rw-r--r--radeon/Makefile.am2
-rw-r--r--radeon/r600_pci_ids.h271
-rw-r--r--radeon/radeon_surface.c995
-rw-r--r--radeon/radeon_surface.h114
4 files changed, 1382 insertions, 0 deletions
diff --git a/radeon/Makefile.am b/radeon/Makefile.am
index dc94b5f3..e64aff4b 100644
--- a/radeon/Makefile.am
+++ b/radeon/Makefile.am
@@ -40,6 +40,7 @@ libdrm_radeon_la_SOURCES = \
40 radeon_cs_space.c \ 40 radeon_cs_space.c \
41 radeon_bo.c \ 41 radeon_bo.c \
42 radeon_cs.c \ 42 radeon_cs.c \
43 radeon_surface.c \
43 bof.c \ 44 bof.c \
44 bof.h 45 bof.h
45 46
@@ -47,6 +48,7 @@ libdrm_radeonincludedir = ${includedir}/libdrm
47libdrm_radeoninclude_HEADERS = \ 48libdrm_radeoninclude_HEADERS = \
48 radeon_bo.h \ 49 radeon_bo.h \
49 radeon_cs.h \ 50 radeon_cs.h \
51 radeon_surface.h \
50 radeon_bo_gem.h \ 52 radeon_bo_gem.h \
51 radeon_cs_gem.h \ 53 radeon_cs_gem.h \
52 radeon_bo_int.h \ 54 radeon_bo_int.h \
diff --git a/radeon/r600_pci_ids.h b/radeon/r600_pci_ids.h
new file mode 100644
index 00000000..0ffb741d
--- /dev/null
+++ b/radeon/r600_pci_ids.h
@@ -0,0 +1,271 @@
1CHIPSET(0x9400, R600_9400, R600)
2CHIPSET(0x9401, R600_9401, R600)
3CHIPSET(0x9402, R600_9402, R600)
4CHIPSET(0x9403, R600_9403, R600)
5CHIPSET(0x9405, R600_9405, R600)
6CHIPSET(0x940A, R600_940A, R600)
7CHIPSET(0x940B, R600_940B, R600)
8CHIPSET(0x940F, R600_940F, R600)
9
10CHIPSET(0x94C0, RV610_94C0, RV610)
11CHIPSET(0x94C1, RV610_94C1, RV610)
12CHIPSET(0x94C3, RV610_94C3, RV610)
13CHIPSET(0x94C4, RV610_94C4, RV610)
14CHIPSET(0x94C5, RV610_94C5, RV610)
15CHIPSET(0x94C6, RV610_94C6, RV610)
16CHIPSET(0x94C7, RV610_94C7, RV610)
17CHIPSET(0x94C8, RV610_94C8, RV610)
18CHIPSET(0x94C9, RV610_94C9, RV610)
19CHIPSET(0x94CB, RV610_94CB, RV610)
20CHIPSET(0x94CC, RV610_94CC, RV610)
21CHIPSET(0x94CD, RV610_94CD, RV610)
22
23CHIPSET(0x9580, RV630_9580, RV630)
24CHIPSET(0x9581, RV630_9581, RV630)
25CHIPSET(0x9583, RV630_9583, RV630)
26CHIPSET(0x9586, RV630_9586, RV630)
27CHIPSET(0x9587, RV630_9587, RV630)
28CHIPSET(0x9588, RV630_9588, RV630)
29CHIPSET(0x9589, RV630_9589, RV630)
30CHIPSET(0x958A, RV630_958A, RV630)
31CHIPSET(0x958B, RV630_958B, RV630)
32CHIPSET(0x958C, RV630_958C, RV630)
33CHIPSET(0x958D, RV630_958D, RV630)
34CHIPSET(0x958E, RV630_958E, RV630)
35CHIPSET(0x958F, RV630_958F, RV630)
36
37CHIPSET(0x9500, RV670_9500, RV670)
38CHIPSET(0x9501, RV670_9501, RV670)
39CHIPSET(0x9504, RV670_9504, RV670)
40CHIPSET(0x9505, RV670_9505, RV670)
41CHIPSET(0x9506, RV670_9506, RV670)
42CHIPSET(0x9507, RV670_9507, RV670)
43CHIPSET(0x9508, RV670_9508, RV670)
44CHIPSET(0x9509, RV670_9509, RV670)
45CHIPSET(0x950F, RV670_950F, RV670)
46CHIPSET(0x9511, RV670_9511, RV670)
47CHIPSET(0x9515, RV670_9515, RV670)
48CHIPSET(0x9517, RV670_9517, RV670)
49CHIPSET(0x9519, RV670_9519, RV670)
50
51CHIPSET(0x95C0, RV620_95C0, RV620)
52CHIPSET(0x95C2, RV620_95C2, RV620)
53CHIPSET(0x95C4, RV620_95C4, RV620)
54CHIPSET(0x95C5, RV620_95C5, RV620)
55CHIPSET(0x95C6, RV620_95C6, RV620)
56CHIPSET(0x95C7, RV620_95C7, RV620)
57CHIPSET(0x95C9, RV620_95C9, RV620)
58CHIPSET(0x95CC, RV620_95CC, RV620)
59CHIPSET(0x95CD, RV620_95CD, RV620)
60CHIPSET(0x95CE, RV620_95CE, RV620)
61CHIPSET(0x95CF, RV620_95CF, RV620)
62
63CHIPSET(0x9590, RV635_9590, RV635)
64CHIPSET(0x9591, RV635_9591, RV635)
65CHIPSET(0x9593, RV635_9593, RV635)
66CHIPSET(0x9595, RV635_9595, RV635)
67CHIPSET(0x9596, RV635_9596, RV635)
68CHIPSET(0x9597, RV635_9597, RV635)
69CHIPSET(0x9598, RV635_9598, RV635)
70CHIPSET(0x9599, RV635_9599, RV635)
71CHIPSET(0x959B, RV635_959B, RV635)
72
73CHIPSET(0x9610, RS780_9610, RS780)
74CHIPSET(0x9611, RS780_9611, RS780)
75CHIPSET(0x9612, RS780_9612, RS780)
76CHIPSET(0x9613, RS780_9613, RS780)
77CHIPSET(0x9614, RS780_9614, RS780)
78CHIPSET(0x9615, RS780_9615, RS780)
79CHIPSET(0x9616, RS780_9616, RS780)
80
81CHIPSET(0x9710, RS880_9710, RS880)
82CHIPSET(0x9711, RS880_9711, RS880)
83CHIPSET(0x9712, RS880_9712, RS880)
84CHIPSET(0x9713, RS880_9713, RS880)
85CHIPSET(0x9714, RS880_9714, RS880)
86CHIPSET(0x9715, RS880_9715, RS880)
87
88CHIPSET(0x9440, RV770_9440, RV770)
89CHIPSET(0x9441, RV770_9441, RV770)
90CHIPSET(0x9442, RV770_9442, RV770)
91CHIPSET(0x9443, RV770_9443, RV770)
92CHIPSET(0x9444, RV770_9444, RV770)
93CHIPSET(0x9446, RV770_9446, RV770)
94CHIPSET(0x944A, RV770_944A, RV770)
95CHIPSET(0x944B, RV770_944B, RV770)
96CHIPSET(0x944C, RV770_944C, RV770)
97CHIPSET(0x944E, RV770_944E, RV770)
98CHIPSET(0x9450, RV770_9450, RV770)
99CHIPSET(0x9452, RV770_9452, RV770)
100CHIPSET(0x9456, RV770_9456, RV770)
101CHIPSET(0x945A, RV770_945A, RV770)
102CHIPSET(0x945B, RV770_945B, RV770)
103CHIPSET(0x945E, RV770_945E, RV770)
104CHIPSET(0x9460, RV790_9460, RV770)
105CHIPSET(0x9462, RV790_9462, RV770)
106CHIPSET(0x946A, RV770_946A, RV770)
107CHIPSET(0x946B, RV770_946B, RV770)
108CHIPSET(0x947A, RV770_947A, RV770)
109CHIPSET(0x947B, RV770_947B, RV770)
110
111CHIPSET(0x9480, RV730_9480, RV730)
112CHIPSET(0x9487, RV730_9487, RV730)
113CHIPSET(0x9488, RV730_9488, RV730)
114CHIPSET(0x9489, RV730_9489, RV730)
115CHIPSET(0x948A, RV730_948A, RV730)
116CHIPSET(0x948F, RV730_948F, RV730)
117CHIPSET(0x9490, RV730_9490, RV730)
118CHIPSET(0x9491, RV730_9491, RV730)
119CHIPSET(0x9495, RV730_9495, RV730)
120CHIPSET(0x9498, RV730_9498, RV730)
121CHIPSET(0x949C, RV730_949C, RV730)
122CHIPSET(0x949E, RV730_949E, RV730)
123CHIPSET(0x949F, RV730_949F, RV730)
124
125CHIPSET(0x9540, RV710_9540, RV710)
126CHIPSET(0x9541, RV710_9541, RV710)
127CHIPSET(0x9542, RV710_9542, RV710)
128CHIPSET(0x954E, RV710_954E, RV710)
129CHIPSET(0x954F, RV710_954F, RV710)
130CHIPSET(0x9552, RV710_9552, RV710)
131CHIPSET(0x9553, RV710_9553, RV710)
132CHIPSET(0x9555, RV710_9555, RV710)
133CHIPSET(0x9557, RV710_9557, RV710)
134CHIPSET(0x955F, RV710_955F, RV710)
135
136CHIPSET(0x94A0, RV740_94A0, RV740)
137CHIPSET(0x94A1, RV740_94A1, RV740)
138CHIPSET(0x94A3, RV740_94A3, RV740)
139CHIPSET(0x94B1, RV740_94B1, RV740)
140CHIPSET(0x94B3, RV740_94B3, RV740)
141CHIPSET(0x94B4, RV740_94B4, RV740)
142CHIPSET(0x94B5, RV740_94B5, RV740)
143CHIPSET(0x94B9, RV740_94B9, RV740)
144
145CHIPSET(0x68E0, CEDAR_68E0, CEDAR)
146CHIPSET(0x68E1, CEDAR_68E1, CEDAR)
147CHIPSET(0x68E4, CEDAR_68E4, CEDAR)
148CHIPSET(0x68E5, CEDAR_68E5, CEDAR)
149CHIPSET(0x68E8, CEDAR_68E8, CEDAR)
150CHIPSET(0x68E9, CEDAR_68E9, CEDAR)
151CHIPSET(0x68F1, CEDAR_68F1, CEDAR)
152CHIPSET(0x68F2, CEDAR_68F2, CEDAR)
153CHIPSET(0x68F8, CEDAR_68F8, CEDAR)
154CHIPSET(0x68F9, CEDAR_68F9, CEDAR)
155CHIPSET(0x68FE, CEDAR_68FE, CEDAR)
156
157CHIPSET(0x68C0, REDWOOD_68C0, REDWOOD)
158CHIPSET(0x68C1, REDWOOD_68C1, REDWOOD)
159CHIPSET(0x68C8, REDWOOD_68C8, REDWOOD)
160CHIPSET(0x68C9, REDWOOD_68C9, REDWOOD)
161CHIPSET(0x68D8, REDWOOD_68D8, REDWOOD)
162CHIPSET(0x68D9, REDWOOD_68D9, REDWOOD)
163CHIPSET(0x68DA, REDWOOD_68DA, REDWOOD)
164CHIPSET(0x68DE, REDWOOD_68DE, REDWOOD)
165
166CHIPSET(0x68A0, JUNIPER_68A0, JUNIPER)
167CHIPSET(0x68A1, JUNIPER_68A1, JUNIPER)
168CHIPSET(0x68A8, JUNIPER_68A8, JUNIPER)
169CHIPSET(0x68A9, JUNIPER_68A9, JUNIPER)
170CHIPSET(0x68B0, JUNIPER_68B0, JUNIPER)
171CHIPSET(0x68B8, JUNIPER_68B8, JUNIPER)
172CHIPSET(0x68B9, JUNIPER_68B9, JUNIPER)
173CHIPSET(0x68BA, JUNIPER_68BA, JUNIPER)
174CHIPSET(0x68BE, JUNIPER_68BE, JUNIPER)
175CHIPSET(0x68BF, JUNIPER_68BF, JUNIPER)
176
177CHIPSET(0x6880, CYPRESS_6880, CYPRESS)
178CHIPSET(0x6888, CYPRESS_6888, CYPRESS)
179CHIPSET(0x6889, CYPRESS_6889, CYPRESS)
180CHIPSET(0x688A, CYPRESS_688A, CYPRESS)
181CHIPSET(0x6898, CYPRESS_6898, CYPRESS)
182CHIPSET(0x6899, CYPRESS_6899, CYPRESS)
183CHIPSET(0x689B, CYPRESS_689B, CYPRESS)
184CHIPSET(0x689E, CYPRESS_689E, CYPRESS)
185
186CHIPSET(0x689C, HEMLOCK_689C, HEMLOCK)
187CHIPSET(0x689D, HEMLOCK_689D, HEMLOCK)
188
189CHIPSET(0x9802, PALM_9802, PALM)
190CHIPSET(0x9803, PALM_9803, PALM)
191CHIPSET(0x9804, PALM_9804, PALM)
192CHIPSET(0x9805, PALM_9805, PALM)
193CHIPSET(0x9806, PALM_9806, PALM)
194CHIPSET(0x9807, PALM_9807, PALM)
195
196CHIPSET(0x9640, SUMO_9640, SUMO)
197CHIPSET(0x9641, SUMO_9641, SUMO)
198CHIPSET(0x9642, SUMO2_9642, SUMO2)
199CHIPSET(0x9643, SUMO2_9643, SUMO2)
200CHIPSET(0x9644, SUMO2_9644, SUMO2)
201CHIPSET(0x9645, SUMO2_9645, SUMO2)
202CHIPSET(0x9647, SUMO_9647, SUMO)
203CHIPSET(0x9648, SUMO_9648, SUMO)
204CHIPSET(0x964a, SUMO_964A, SUMO)
205CHIPSET(0x964e, SUMO_964E, SUMO)
206CHIPSET(0x964f, SUMO_964F, SUMO)
207
208CHIPSET(0x6700, CAYMAN_6700, CAYMAN)
209CHIPSET(0x6701, CAYMAN_6701, CAYMAN)
210CHIPSET(0x6702, CAYMAN_6702, CAYMAN)
211CHIPSET(0x6703, CAYMAN_6703, CAYMAN)
212CHIPSET(0x6704, CAYMAN_6704, CAYMAN)
213CHIPSET(0x6705, CAYMAN_6705, CAYMAN)
214CHIPSET(0x6706, CAYMAN_6706, CAYMAN)
215CHIPSET(0x6707, CAYMAN_6707, CAYMAN)
216CHIPSET(0x6708, CAYMAN_6708, CAYMAN)
217CHIPSET(0x6709, CAYMAN_6709, CAYMAN)
218CHIPSET(0x6718, CAYMAN_6718, CAYMAN)
219CHIPSET(0x6719, CAYMAN_6719, CAYMAN)
220CHIPSET(0x671C, CAYMAN_671C, CAYMAN)
221CHIPSET(0x671D, CAYMAN_671D, CAYMAN)
222CHIPSET(0x671F, CAYMAN_671F, CAYMAN)
223
224CHIPSET(0x6720, BARTS_6720, BARTS)
225CHIPSET(0x6721, BARTS_6721, BARTS)
226CHIPSET(0x6722, BARTS_6722, BARTS)
227CHIPSET(0x6723, BARTS_6723, BARTS)
228CHIPSET(0x6724, BARTS_6724, BARTS)
229CHIPSET(0x6725, BARTS_6725, BARTS)
230CHIPSET(0x6726, BARTS_6726, BARTS)
231CHIPSET(0x6727, BARTS_6727, BARTS)
232CHIPSET(0x6728, BARTS_6728, BARTS)
233CHIPSET(0x6729, BARTS_6729, BARTS)
234CHIPSET(0x6738, BARTS_6738, BARTS)
235CHIPSET(0x6739, BARTS_6739, BARTS)
236CHIPSET(0x673E, BARTS_673E, BARTS)
237CHIPSET(0x6740, TURKS_6740, TURKS)
238CHIPSET(0x6741, TURKS_6741, TURKS)
239CHIPSET(0x6742, TURKS_6742, TURKS)
240CHIPSET(0x6743, TURKS_6743, TURKS)
241CHIPSET(0x6744, TURKS_6744, TURKS)
242CHIPSET(0x6745, TURKS_6745, TURKS)
243CHIPSET(0x6746, TURKS_6746, TURKS)
244CHIPSET(0x6747, TURKS_6747, TURKS)
245CHIPSET(0x6748, TURKS_6748, TURKS)
246CHIPSET(0x6749, TURKS_6749, TURKS)
247CHIPSET(0x6750, TURKS_6750, TURKS)
248CHIPSET(0x6758, TURKS_6758, TURKS)
249CHIPSET(0x6759, TURKS_6759, TURKS)
250CHIPSET(0x675F, TURKS_675F, TURKS)
251CHIPSET(0x6840, TURKS_6840, TURKS)
252CHIPSET(0x6841, TURKS_6841, TURKS)
253CHIPSET(0x6842, TURKS_6842, TURKS)
254CHIPSET(0x6843, TURKS_6843, TURKS)
255CHIPSET(0x6849, TURKS_6849, TURKS)
256CHIPSET(0x6850, TURKS_6850, TURKS)
257CHIPSET(0x6858, TURKS_6858, TURKS)
258CHIPSET(0x6859, TURKS_6859, TURKS)
259
260CHIPSET(0x6760, CAICOS_6760, CAICOS)
261CHIPSET(0x6761, CAICOS_6761, CAICOS)
262CHIPSET(0x6762, CAICOS_6762, CAICOS)
263CHIPSET(0x6763, CAICOS_6763, CAICOS)
264CHIPSET(0x6764, CAICOS_6764, CAICOS)
265CHIPSET(0x6765, CAICOS_6765, CAICOS)
266CHIPSET(0x6766, CAICOS_6766, CAICOS)
267CHIPSET(0x6767, CAICOS_6767, CAICOS)
268CHIPSET(0x6768, CAICOS_6768, CAICOS)
269CHIPSET(0x6770, CAICOS_6770, CAICOS)
270CHIPSET(0x6778, CAICOS_6778, CAICOS)
271CHIPSET(0x6779, CAICOS_6779, CAICOS)
diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
new file mode 100644
index 00000000..0f01e2ed
--- /dev/null
+++ b/radeon/radeon_surface.c
@@ -0,0 +1,995 @@
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#include <errno.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <sys/mman.h>
34#include <sys/ioctl.h>
35#include "drm.h"
36#include "xf86drm.h"
37#include "radeon_drm.h"
38#include "radeon_surface.h"
39
40#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
41#define MAX2(A, B) ((A) > (B) ? (A) : (B))
42#define MIN2(A, B) ((A) < (B) ? (A) : (B))
43
44/* keep this private */
45enum radeon_family {
46 CHIP_UNKNOWN,
47 CHIP_R600,
48 CHIP_RV610,
49 CHIP_RV630,
50 CHIP_RV670,
51 CHIP_RV620,
52 CHIP_RV635,
53 CHIP_RS780,
54 CHIP_RS880,
55 CHIP_RV770,
56 CHIP_RV730,
57 CHIP_RV710,
58 CHIP_RV740,
59 CHIP_CEDAR,
60 CHIP_REDWOOD,
61 CHIP_JUNIPER,
62 CHIP_CYPRESS,
63 CHIP_HEMLOCK,
64 CHIP_PALM,
65 CHIP_SUMO,
66 CHIP_SUMO2,
67 CHIP_BARTS,
68 CHIP_TURKS,
69 CHIP_CAICOS,
70 CHIP_CAYMAN,
71 CHIP_LAST,
72};
73
74typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
75 struct radeon_surface *surf);
76typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
77 struct radeon_surface *surf);
78
79struct radeon_hw_info {
80 /* apply to r6, eg */
81 uint32_t group_bytes;
82 uint32_t num_banks;
83 uint32_t num_pipes;
84 /* apply to eg */
85 uint32_t row_size;
86 unsigned allow_2d;
87};
88
89struct radeon_surface_manager {
90 int fd;
91 uint32_t device_id;
92 struct radeon_hw_info hw_info;
93 unsigned family;
94 hw_init_surface_t surface_init;
95 hw_best_surface_t surface_best;
96};
97
98/* helper */
99static int radeon_get_value(int fd, unsigned req, uint32_t *value)
100{
101 struct drm_radeon_info info = {};
102 int r;
103
104 *value = 0;
105 info.request = req;
106 info.value = (uintptr_t)value;
107 r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
108 sizeof(struct drm_radeon_info));
109 return r;
110}
111
112static int radeon_get_family(struct radeon_surface_manager *surf_man)
113{
114 switch (surf_man->device_id) {
115#define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
116#include "r600_pci_ids.h"
117#undef CHIPSET
118 default:
119 return -EINVAL;
120 }
121 return 0;
122}
123
124static unsigned next_power_of_two(unsigned x)
125{
126 if (x <= 1)
127 return 1;
128
129 return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
130}
131
132static unsigned mip_minify(unsigned size, unsigned level)
133{
134 unsigned val;
135
136 val = MAX2(1, size >> level);
137 if (level > 0)
138 val = next_power_of_two(val);
139 return val;
140}
141
142static void surf_minify(struct radeon_surface *surf,
143 unsigned level,
144 uint32_t xalign, uint32_t yalign, uint32_t zalign,
145 unsigned offset)
146{
147 surf->level[level].nblk_x = mip_minify(surf->nblk_x, level);
148 surf->level[level].nblk_y = mip_minify(surf->nblk_y, level);
149 surf->level[level].nblk_z = mip_minify(surf->nblk_z, level);
150 surf->level[level].npix_x = mip_minify(surf->npix_x, level);
151 surf->level[level].npix_y = mip_minify(surf->npix_y, level);
152 surf->level[level].npix_z = mip_minify(surf->npix_z, level);
153 if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
154 if (surf->level[level].nblk_x < xalign || surf->level[level].nblk_y < yalign) {
155 surf->level[level].mode = RADEON_SURF_MODE_1D;
156 return;
157 }
158 }
159 surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, xalign);
160 surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, yalign);
161 surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, zalign);
162
163 surf->level[level].offset = offset;
164 surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe;
165 surf->level[level].slice_size = surf->level[level].pitch_bytes * surf->level[level].nblk_y;
166
167 surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
168}
169
170/* ===========================================================================
171 * r600/r700 family
172 */
173static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
174{
175 uint32_t tiling_config;
176 int r;
177
178 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
179 &tiling_config);
180 if (r) {
181 return r;
182 }
183
184 switch ((tiling_config & 0xe) >> 1) {
185 case 0:
186 surf_man->hw_info.num_pipes = 1;
187 break;
188 case 1:
189 surf_man->hw_info.num_pipes = 2;
190 break;
191 case 2:
192 surf_man->hw_info.num_pipes = 4;
193 break;
194 case 3:
195 surf_man->hw_info.num_pipes = 8;
196 break;
197 default:
198 return -EINVAL;
199 }
200
201 switch ((tiling_config & 0x30) >> 4) {
202 case 0:
203 surf_man->hw_info.num_banks = 4;
204 break;
205 case 1:
206 surf_man->hw_info.num_banks = 8;
207 break;
208 default:
209 return -EINVAL;
210 }
211
212 switch ((tiling_config & 0xc0) >> 6) {
213 case 0:
214 surf_man->hw_info.group_bytes = 256;
215 break;
216 case 1:
217 surf_man->hw_info.group_bytes = 512;
218 break;
219 default:
220 return -EINVAL;
221 }
222 return 0;
223}
224
225static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
226 struct radeon_surface *surf,
227 uint64_t offset, unsigned start_level)
228{
229 uint32_t xalign, yalign, zalign;
230 unsigned i;
231
232 /* compute alignment */
233 if (!start_level) {
234 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
235 }
236 /* the 32 alignment is for scanout, cb or db but to allow texture to be
237 * easily bound as such we force this alignment to all surface
238 */
239 xalign = MAX2(32, surf_man->hw_info.group_bytes / surf->bpe);
240 yalign = 1;
241 zalign = 1;
242
243 /* build mipmap tree */
244 for (i = start_level; i <= surf->last_level; i++) {
245 surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
246 surf_minify(surf, i, xalign, yalign, zalign, offset);
247 /* level0 and first mipmap need to have alignment */
248 offset = surf->bo_size;
249 if ((i == 0)) {
250 offset = ALIGN(offset, surf->bo_alignment);
251 }
252 }
253 return 0;
254}
255
256static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
257 struct radeon_surface *surf,
258 uint64_t offset, unsigned start_level)
259{
260 uint32_t xalign, yalign, zalign;
261 unsigned i;
262
263 /* compute alignment */
264 if (!start_level) {
265 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
266 }
267 xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
268 yalign = 1;
269 zalign = 1;
270
271 /* build mipmap tree */
272 for (i = start_level; i <= surf->last_level; i++) {
273 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
274 surf_minify(surf, i, xalign, yalign, zalign, offset);
275 /* level0 and first mipmap need to have alignment */
276 offset = surf->bo_size;
277 if ((i == 0)) {
278 offset = ALIGN(offset, surf->bo_alignment);
279 }
280 }
281 return 0;
282}
283
284static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
285 struct radeon_surface *surf,
286 uint64_t offset, unsigned start_level)
287{
288 uint32_t xalign, yalign, zalign, tilew;
289 unsigned i;
290
291 /* compute alignment */
292 tilew = 8;
293 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
294 xalign = MAX2(tilew, xalign);
295 yalign = tilew;
296 zalign = 1;
297 if (!start_level) {
298 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
299 }
300
301 /* build mipmap tree */
302 for (i = start_level; i <= surf->last_level; i++) {
303 surf->level[i].mode = RADEON_SURF_MODE_1D;
304 surf_minify(surf, i, xalign, yalign, zalign, offset);
305 /* level0 and first mipmap need to have alignment */
306 offset = surf->bo_size;
307 if ((i == 0)) {
308 offset = ALIGN(offset, surf->bo_alignment);
309 }
310 }
311 return 0;
312}
313
314static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
315 struct radeon_surface *surf,
316 uint64_t offset, unsigned start_level)
317{
318 uint32_t xalign, yalign, zalign, tilew;
319 unsigned i;
320
321 /* compute alignment */
322 tilew = 8;
323 zalign = 1;
324 xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
325 (tilew * surf->bpe * surf->nsamples);
326 xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
327 yalign = tilew * surf_man->hw_info.num_pipes;
328 if (!start_level) {
329 surf->bo_alignment =
330 MAX2(surf_man->hw_info.num_pipes *
331 surf_man->hw_info.num_banks *
332 surf->bpe * 64,
333 xalign * yalign * surf->nsamples * surf->bpe);
334 }
335
336 /* build mipmap tree */
337 for (i = start_level; i <= surf->last_level; i++) {
338 surf->level[i].mode = RADEON_SURF_MODE_2D;
339 surf_minify(surf, i, xalign, yalign, zalign, offset);
340 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
341 return r6_surface_init_1d(surf_man, surf, offset, i);
342 }
343 /* level0 and first mipmap need to have alignment */
344 offset = surf->bo_size;
345 if ((i == 0)) {
346 offset = ALIGN(offset, surf->bo_alignment);
347 }
348 }
349 return 0;
350}
351
352static int r6_surface_init(struct radeon_surface_manager *surf_man,
353 struct radeon_surface *surf)
354{
355 unsigned mode;
356 int r;
357
358 /* tiling mode */
359 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
360
361 /* check surface dimension */
362 if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
363 return -EINVAL;
364 }
365
366 /* check mipmap last_level */
367 if (surf->last_level > 14) {
368 return -EINVAL;
369 }
370
371 /* check tiling mode */
372 switch (mode) {
373 case RADEON_SURF_MODE_LINEAR:
374 r = r6_surface_init_linear(surf_man, surf, 0, 0);
375 break;
376 case RADEON_SURF_MODE_LINEAR_ALIGNED:
377 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
378 break;
379 case RADEON_SURF_MODE_1D:
380 r = r6_surface_init_1d(surf_man, surf, 0, 0);
381 break;
382 case RADEON_SURF_MODE_2D:
383 r = r6_surface_init_2d(surf_man, surf, 0, 0);
384 break;
385 default:
386 return -EINVAL;
387 }
388 return r;
389}
390
391static int r6_surface_best(struct radeon_surface_manager *surf_man,
392 struct radeon_surface *surf)
393{
394 /* no value to optimize for r6xx/r7xx */
395 return 0;
396}
397
398
399/* ===========================================================================
400 * evergreen family
401 */
402static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
403{
404 uint32_t tiling_config;
405 drmVersionPtr version;
406 int r;
407
408 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
409 &tiling_config);
410 if (r) {
411 return r;
412 }
413
414 surf_man->hw_info.allow_2d = 0;
415 version = drmGetVersion(surf_man->fd);
416 if (version && version->version_minor >= 14) {
417 surf_man->hw_info.allow_2d = 1;
418 }
419
420 switch (tiling_config & 0xf) {
421 case 0:
422 surf_man->hw_info.num_pipes = 1;
423 break;
424 case 1:
425 surf_man->hw_info.num_pipes = 2;
426 break;
427 case 2:
428 surf_man->hw_info.num_pipes = 4;
429 break;
430 case 3:
431 surf_man->hw_info.num_pipes = 8;
432 break;
433 default:
434 return -EINVAL;
435 }
436
437 switch ((tiling_config & 0xf0) >> 4) {
438 case 0:
439 surf_man->hw_info.num_banks = 4;
440 break;
441 case 1:
442 surf_man->hw_info.num_banks = 8;
443 break;
444 case 2:
445 surf_man->hw_info.num_banks = 16;
446 break;
447 default:
448 return -EINVAL;
449 }
450
451 switch ((tiling_config & 0xf00) >> 8) {
452 case 0:
453 surf_man->hw_info.group_bytes = 256;
454 break;
455 case 1:
456 surf_man->hw_info.group_bytes = 512;
457 break;
458 default:
459 return -EINVAL;
460 }
461
462 switch ((tiling_config & 0xf000) >> 12) {
463 case 0:
464 surf_man->hw_info.row_size = 1024;
465 break;
466 case 1:
467 surf_man->hw_info.row_size = 2048;
468 break;
469 case 2:
470 surf_man->hw_info.row_size = 4096;
471 break;
472 default:
473 return -EINVAL;
474 }
475 return 0;
476}
477
478static void eg_surf_minify(struct radeon_surface *surf,
479 unsigned level,
480 unsigned slice_pt,
481 unsigned mtilew,
482 unsigned mtileh,
483 unsigned mtileb,
484 unsigned offset)
485{
486 unsigned mtile_pr, mtile_ps;
487
488 surf->level[level].nblk_x = mip_minify(surf->nblk_x, level);
489 surf->level[level].nblk_y = mip_minify(surf->nblk_y, level);
490 surf->level[level].nblk_z = mip_minify(surf->nblk_z, level);
491 surf->level[level].npix_x = mip_minify(surf->npix_x, level);
492 surf->level[level].npix_y = mip_minify(surf->npix_y, level);
493 surf->level[level].npix_z = mip_minify(surf->npix_z, level);
494 if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
495 if (surf->level[level].nblk_x < mtilew || surf->level[level].nblk_y < mtileh) {
496 surf->level[level].mode = RADEON_SURF_MODE_1D;
497 return;
498 }
499 }
500 surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, mtilew);
501 surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, mtileh);
502 surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, 1);
503
504 /* macro tile per row */
505 mtile_pr = surf->level[level].nblk_x / mtilew;
506 /* macro tile per slice */
507 mtile_ps = (mtile_pr * surf->level[level].nblk_y) / mtileh;
508
509 surf->level[level].offset = offset;
510 surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * slice_pt;
511 surf->level[level].slice_size = mtile_ps * mtileb * slice_pt;
512
513 surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
514}
515
516static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
517 struct radeon_surface *surf,
518 uint64_t offset, unsigned start_level)
519{
520 uint32_t xalign, yalign, zalign, tilew;
521 unsigned i;
522
523 /* compute alignment */
524 tilew = 8;
525 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
526 if (surf->flags & RADEON_SURF_SBUFFER) {
527 surf->stencil_offset = 0;
528 surf->stencil_tile_split = 0;
529 xalign = surf_man->hw_info.group_bytes / (tilew * surf->nsamples);
530 }
531 xalign = MAX2(tilew, xalign);
532 yalign = tilew;
533 zalign = 1;
534 if (!start_level) {
535 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
536 }
537
538 /* build mipmap tree */
539 for (i = start_level; i <= surf->last_level; i++) {
540 surf->level[i].mode = RADEON_SURF_MODE_1D;
541 surf_minify(surf, i, xalign, yalign, zalign, offset);
542 /* level0 and first mipmap need to have alignment */
543 offset = surf->bo_size;
544 if ((i == 0)) {
545 offset = ALIGN(offset, surf->bo_alignment);
546 }
547 }
548
549 if (surf->flags & RADEON_SURF_SBUFFER) {
550 surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
551 surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
552 }
553
554 return 0;
555}
556
557static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
558 struct radeon_surface *surf,
559 uint64_t offset, unsigned start_level)
560{
561 unsigned tilew, tileh, tileb;
562 unsigned mtilew, mtileh, mtileb;
563 unsigned slice_pt;
564 unsigned i;
565
566 surf->stencil_offset = 0;
567 /* compute tile values */
568 tilew = 8;
569 tileh = 8;
570 tileb = tilew * tileh * surf->bpe * surf->nsamples;
571 /* slices per tile */
572 slice_pt = 1;
573 if (tileb > surf->tile_split) {
574 slice_pt = tileb / surf->tile_split;
575 }
576 tileb = tileb / slice_pt;
577
578 /* macro tile width & height */
579 mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
580 mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
581 /* macro tile bytes */
582 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
583
584 /* check if surface is big enought */
585 if (surf->nblk_x < mtilew || surf->nblk_y < mtileh) {
586 surf->level[start_level].mode = RADEON_SURF_MODE_1D;
587 return eg_surface_init_1d(surf_man, surf, offset, start_level);
588 }
589
590 if (!start_level) {
591 surf->bo_alignment = MAX2(256, mtileb);
592 }
593
594 /* build mipmap tree */
595 for (i = start_level; i <= surf->last_level; i++) {
596 surf->level[i].mode = RADEON_SURF_MODE_2D;
597 eg_surf_minify(surf, i, slice_pt, mtilew, mtileh, mtileb, offset);
598 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
599 return r6_surface_init_1d(surf_man, surf, offset, i);
600 }
601 /* level0 and first mipmap need to have alignment */
602 offset = surf->bo_size;
603 if ((i == 0)) {
604 offset = ALIGN(offset, surf->bo_alignment);
605 }
606 }
607
608 if (surf->flags & RADEON_SURF_SBUFFER) {
609 surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
610 surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
611 }
612
613 return 0;
614}
615
616static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
617 struct radeon_surface *surf,
618 unsigned mode)
619{
620 unsigned tileb;
621
622 /* check surface dimension */
623 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
624 return -EINVAL;
625 }
626
627 /* check mipmap last_level */
628 if (surf->last_level > 15) {
629 return -EINVAL;
630 }
631
632 /* check tile split */
633 switch (surf->tile_split) {
634 case 0:
635 if (mode == RADEON_SURF_MODE_2D) {
636 return -EINVAL;
637 }
638 case 64:
639 case 128:
640 case 256:
641 case 512:
642 case 1024:
643 case 2048:
644 case 4096:
645 break;
646 default:
647 return -EINVAL;
648 }
649 switch (surf->mtilea) {
650 case 0:
651 case 1:
652 case 2:
653 case 4:
654 case 8:
655 break;
656 default:
657 return -EINVAL;
658 }
659 /* check aspect ratio */
660 if (surf_man->hw_info.num_banks < surf->mtilea) {
661 return -EINVAL;
662 }
663 /* check bank width */
664 switch (surf->bankw) {
665 case 0:
666 case 1:
667 case 2:
668 case 4:
669 case 8:
670 break;
671 default:
672 return -EINVAL;
673 }
674 /* check bank height */
675 switch (surf->bankh) {
676 case 0:
677 case 1:
678 case 2:
679 case 4:
680 case 8:
681 break;
682 default:
683 return -EINVAL;
684 }
685 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
686 if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
687 if (mode == RADEON_SURF_MODE_2D) {
688 return -EINVAL;
689 }
690 }
691
692 /* force 1d on kernel that can't do 2d */
693 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
694 mode = RADEON_SURF_MODE_1D;
695 }
696
697 return 0;
698}
699
700static int eg_surface_init(struct radeon_surface_manager *surf_man,
701 struct radeon_surface *surf)
702{
703 unsigned mode;
704 int r;
705
706 /* tiling mode */
707 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
708
709 /* for some reason eg need to have room for stencil right after depth */
710 if (surf->flags & RADEON_SURF_ZBUFFER) {
711 surf->flags |= RADEON_SURF_SBUFFER;
712 }
713
714 r = eg_surface_sanity(surf_man, surf, mode);
715 if (r) {
716 return r;
717 }
718
719 /* check tiling mode */
720 switch (mode) {
721 case RADEON_SURF_MODE_LINEAR:
722 r = r6_surface_init_linear(surf_man, surf, 0, 0);
723 break;
724 case RADEON_SURF_MODE_LINEAR_ALIGNED:
725 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
726 break;
727 case RADEON_SURF_MODE_1D:
728 r = eg_surface_init_1d(surf_man, surf, 0, 0);
729 break;
730 case RADEON_SURF_MODE_2D:
731 r = eg_surface_init_2d(surf_man, surf, 0, 0);
732 break;
733 default:
734 return -EINVAL;
735 }
736 return r;
737}
738
739static unsigned log2_int(unsigned x)
740{
741 unsigned l;
742
743 if (x < 2) {
744 return 0;
745 }
746 for (l = 2; ; l++) {
747 if ((unsigned)(1 << l) > x) {
748 return l - 1;
749 }
750 }
751 return 0;
752}
753
754/* compute best tile_split, bankw, bankh, mtilea
755 * depending on surface
756 */
757static int eg_surface_best(struct radeon_surface_manager *surf_man,
758 struct radeon_surface *surf)
759{
760 unsigned mode, tileb, h_over_w;
761 int r;
762
763 /* tiling mode */
764 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
765
766 /* for some reason eg need to have room for stencil right after depth */
767 if (surf->flags & RADEON_SURF_ZBUFFER) {
768 surf->flags |= RADEON_SURF_SBUFFER;
769 }
770
771 /* set some default value to avoid sanity check choking on them */
772 surf->tile_split = 1024;
773 surf->bankw = 1;
774 surf->bankh = 1;
775 surf->mtilea = surf_man->hw_info.num_banks;
776 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
777 for (; surf->bankh <= 8; surf->bankh *= 2) {
778 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
779 break;
780 }
781 }
782 if (surf->mtilea > 8) {
783 surf->mtilea = 8;
784 }
785
786 r = eg_surface_sanity(surf_man, surf, mode);
787 if (r) {
788 return r;
789 }
790
791 if (mode != RADEON_SURF_MODE_2D) {
792 /* nothing to do for non 2D tiled surface */
793 return 0;
794 }
795
796 /* set tile split to row size, optimize latter for multi-sample surface
797 * tile split >= 256 for render buffer surface. Also depth surface want
798 * smaller value for optimal performances.
799 */
800 surf->tile_split = surf_man->hw_info.row_size;
801 surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
802
803 /* bankw or bankh greater than 1 increase alignment requirement, not
804 * sure if it's worth using smaller bankw & bankh to stick with 2D
805 * tiling on small surface rather than falling back to 1D tiling.
806 * Use recommanded value based on tile size for now.
807 *
808 * fmask buffer has different optimal value figure them out once we
809 * use it.
810 */
811 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
812 /* assume 1 bytes for stencil, we optimize for stencil as stencil
813 * and depth shares surface values
814 */
815 tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
816 } else {
817 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
818 }
819
820 /* use bankw of 1 to minimize width alignment, might be interesting to
821 * increase it for large surface
822 */
823 surf->bankw = 1;
824 switch (tileb) {
825 case 64:
826 surf->bankh = 4;
827 break;
828 case 128:
829 case 256:
830 surf->bankh = 2;
831 break;
832 default:
833 surf->bankh = 1;
834 break;
835 }
836 /* double check the constraint */
837 for (; surf->bankh <= 8; surf->bankh *= 2) {
838 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
839 break;
840 }
841 }
842
843 h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
844 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
845 surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
846
847 return 0;
848}
849
850
851/* ===========================================================================
852 * public API
853 */
854struct radeon_surface_manager *radeon_surface_manager_new(int fd)
855{
856 struct radeon_surface_manager *surf_man;
857
858 surf_man = calloc(1, sizeof(struct radeon_surface_manager));
859 if (surf_man == NULL) {
860 return NULL;
861 }
862 surf_man->fd = fd;
863 if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
864 goto out_err;
865 }
866 if (radeon_get_family(surf_man)) {
867 goto out_err;
868 }
869
870 if (surf_man->family <= CHIP_RV740) {
871 if (r6_init_hw_info(surf_man)) {
872 goto out_err;
873 }
874 surf_man->surface_init = &r6_surface_init;
875 surf_man->surface_best = &r6_surface_best;
876 } else {
877 if (eg_init_hw_info(surf_man)) {
878 goto out_err;
879 }
880 surf_man->surface_init = &eg_surface_init;
881 surf_man->surface_best = &eg_surface_best;
882 }
883
884 return surf_man;
885out_err:
886 free(surf_man);
887 return NULL;
888}
889
890void radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
891{
892 free(surf_man);
893}
894
895static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
896 struct radeon_surface *surf,
897 unsigned type,
898 unsigned mode)
899{
900 if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
901 return -EINVAL;
902 }
903
904 /* all dimension must be at least 1 ! */
905 if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
906 return -EINVAL;
907 }
908 if (!surf->nblk_x || !surf->nblk_y || !surf->nblk_z) {
909 return -EINVAL;
910 }
911 if (surf->npix_x < surf->nblk_x || surf->npix_y < surf->nblk_y || surf->npix_z < surf->nblk_z) {
912 return -EINVAL;
913 }
914 if (!surf->array_size) {
915 return -EINVAL;
916 }
917 /* array size must be a power of 2 */
918 surf->array_size = next_power_of_two(surf->array_size);
919
920 switch (surf->nsamples) {
921 case 1:
922 case 2:
923 case 4:
924 case 8:
925 break;
926 default:
927 return -EINVAL;
928 }
929 /* check type */
930 switch (type) {
931 case RADEON_SURF_TYPE_1D:
932 if (surf->npix_y > 1) {
933 return -EINVAL;
934 }
935 case RADEON_SURF_TYPE_2D:
936 if (surf->npix_z > 1) {
937 return -EINVAL;
938 }
939 break;
940 case RADEON_SURF_TYPE_CUBEMAP:
941 if (surf->npix_z > 1) {
942 return -EINVAL;
943 }
944 /* deal with cubemap as they were texture array */
945 if (surf_man->family >= CHIP_RV770) {
946 surf->array_size = 8;
947 } else {
948 surf->array_size = 6;
949 }
950 break;
951 case RADEON_SURF_TYPE_3D:
952 break;
953 case RADEON_SURF_TYPE_1D_ARRAY:
954 if (surf->npix_y > 1) {
955 return -EINVAL;
956 }
957 case RADEON_SURF_TYPE_2D_ARRAY:
958 break;
959 default:
960 return -EINVAL;
961 }
962 return 0;
963}
964
965int radeon_surface_init(struct radeon_surface_manager *surf_man,
966 struct radeon_surface *surf)
967{
968 unsigned mode, type;
969 int r;
970
971 type = RADEON_SURF_GET(surf->flags, TYPE);
972 mode = RADEON_SURF_GET(surf->flags, MODE);
973
974 r = radeon_surface_sanity(surf_man, surf, type, mode);
975 if (r) {
976 return r;
977 }
978 return surf_man->surface_init(surf_man, surf);
979}
980
981int radeon_surface_best(struct radeon_surface_manager *surf_man,
982 struct radeon_surface *surf)
983{
984 unsigned mode, type;
985 int r;
986
987 type = RADEON_SURF_GET(surf->flags, TYPE);
988 mode = RADEON_SURF_GET(surf->flags, MODE);
989
990 r = radeon_surface_sanity(surf_man, surf, type, mode);
991 if (r) {
992 return r;
993 }
994 return surf_man->surface_best(surf_man, surf);
995}
diff --git a/radeon/radeon_surface.h b/radeon/radeon_surface.h
new file mode 100644
index 00000000..3e5fbedc
--- /dev/null
+++ b/radeon/radeon_surface.h
@@ -0,0 +1,114 @@
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#ifndef RADEON_SURFACE_H
30#define RADEON_SURFACE_H
31
32/* Note :
33 *
34 * For texture array, the n layer are stored one after the other within each
35 * mipmap level. 0 value for field than can be hint is always valid.
36 */
37
38#define RADEON_SURF_MAX_LEVEL 32
39
40#define RADEON_SURF_TYPE_MASK 0xFF
41#define RADEON_SURF_TYPE_SHIFT 0
42#define RADEON_SURF_TYPE_1D 0
43#define RADEON_SURF_TYPE_2D 1
44#define RADEON_SURF_TYPE_3D 2
45#define RADEON_SURF_TYPE_CUBEMAP 3
46#define RADEON_SURF_TYPE_1D_ARRAY 4
47#define RADEON_SURF_TYPE_2D_ARRAY 5
48#define RADEON_SURF_MODE_MASK 0xFF
49#define RADEON_SURF_MODE_SHIFT 8
50#define RADEON_SURF_MODE_LINEAR 0
51#define RADEON_SURF_MODE_LINEAR_ALIGNED 1
52#define RADEON_SURF_MODE_1D 2
53#define RADEON_SURF_MODE_2D 3
54#define RADEON_SURF_SCANOUT (1 << 16)
55#define RADEON_SURF_ZBUFFER (1 << 17)
56#define RADEON_SURF_SBUFFER (1 << 18)
57
58#define RADEON_SURF_GET(v, field) (((v) >> RADEON_SURF_ ## field ## _SHIFT) & RADEON_SURF_ ## field ## _MASK)
59#define RADEON_SURF_SET(v, field) (((v) & RADEON_SURF_ ## field ## _MASK) << RADEON_SURF_ ## field ## _SHIFT)
60#define RADEON_SURF_CLR(v, field) ((v) & ~(RADEON_SURF_ ## field ## _MASK << RADEON_SURF_ ## field ## _SHIFT))
61
62/* first field up to mode need to match r6 struct so that we can reuse
63 * same function for linear & linear aligned
64 */
65struct radeon_surface_level {
66 uint64_t offset;
67 uint64_t slice_size;
68 uint32_t npix_x;
69 uint32_t npix_y;
70 uint32_t npix_z;
71 uint32_t nblk_x;
72 uint32_t nblk_y;
73 uint32_t nblk_z;
74 uint32_t pitch_bytes;
75 uint32_t mode;
76};
77
78struct radeon_surface {
79 uint32_t npix_x;
80 uint32_t npix_y;
81 uint32_t npix_z;
82 uint32_t nblk_x;
83 uint32_t nblk_y;
84 uint32_t nblk_z;
85 uint32_t array_size;
86 uint32_t last_level;
87 uint32_t bpe;
88 uint32_t nsamples;
89 uint32_t flags;
90 /* Following is updated/fill by the allocator. It's allowed to
91 * set some of the value but they are use as hint and can be
92 * overridden (things lile bankw/bankh on evergreen for
93 * instance).
94 */
95 uint64_t bo_size;
96 uint64_t bo_alignment;
97 /* apply to eg */
98 uint32_t bankw;
99 uint32_t bankh;
100 uint32_t mtilea;
101 uint32_t tile_split;
102 uint32_t stencil_tile_split;
103 uint64_t stencil_offset;
104 struct radeon_surface_level level[RADEON_SURF_MAX_LEVEL];
105};
106
107struct radeon_surface_manager *radeon_surface_manager_new(int fd);
108void radeon_surface_manager_free(struct radeon_surface_manager *surf_man);
109int radeon_surface_init(struct radeon_surface_manager *surf_man,
110 struct radeon_surface *surf);
111int radeon_surface_best(struct radeon_surface_manager *surf_man,
112 struct radeon_surface *surf);
113
114#endif