Merge branch '7.8' into master
[mesa.git] / src / gallium / winsys / drm / radeon / core / radeon_drm_buffer.c
1
2 #include <sys/ioctl.h>
3 #include "radeon_drm.h"
4 #include "radeon_bo_gem.h"
5 #include "radeon_cs_gem.h"
6 #include "radeon_buffer.h"
7
8 #include "util/u_inlines.h"
9 #include "util/u_memory.h"
10 #include "util/u_simple_list.h"
11 #include "pipebuffer/pb_buffer.h"
12 #include "pipebuffer/pb_bufmgr.h"
13
14 #include "radeon_winsys.h"
15 struct radeon_drm_bufmgr;
16
17 struct radeon_drm_buffer {
18 struct pb_buffer base;
19 struct radeon_drm_bufmgr *mgr;
20
21 struct radeon_bo *bo;
22
23 boolean flinked;
24 uint32_t flink;
25
26 boolean mapped;
27 struct radeon_drm_buffer *next, *prev;
28 };
29
30 extern const struct pb_vtbl radeon_drm_buffer_vtbl;
31
32
33 static INLINE struct radeon_drm_buffer *
34 radeon_drm_buffer(struct pb_buffer *buf)
35 {
36 assert(buf);
37 assert(buf->vtbl == &radeon_drm_buffer_vtbl);
38 return (struct radeon_drm_buffer *)buf;
39 }
40
41 struct radeon_drm_bufmgr {
42 struct pb_manager base;
43 struct radeon_libdrm_winsys *rws;
44 struct radeon_drm_buffer buffer_map_list;
45 };
46
47 static INLINE struct radeon_drm_bufmgr *
48 radeon_drm_bufmgr(struct pb_manager *mgr)
49 {
50 assert(mgr);
51 return (struct radeon_drm_bufmgr *)mgr;
52 }
53
54 static void
55 radeon_drm_buffer_destroy(struct pb_buffer *_buf)
56 {
57 struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
58
59 if (buf->mapped) {
60 remove_from_list(buf);
61 radeon_bo_unmap(buf->bo);
62 buf->mapped = false;
63 }
64 radeon_bo_unref(buf->bo);
65
66 FREE(buf);
67 }
68
69 static void *
70 radeon_drm_buffer_map(struct pb_buffer *_buf,
71 unsigned flags)
72 {
73 struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
74 int write;
75
76 if (buf->mapped)
77 return buf->bo->ptr;
78
79 if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) {
80 uint32_t domain;
81
82 if (radeon_bo_is_busy(buf->bo, &domain))
83 return NULL;
84 }
85
86
87 if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
88 buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
89 }
90
91 if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) {
92 write = 1;
93 }
94
95 if (radeon_bo_map(buf->bo, write)) {
96 return NULL;
97 }
98 buf->mapped = true;
99 insert_at_tail(&buf->mgr->buffer_map_list, buf);
100 return buf->bo->ptr;
101 }
102
103 static void
104 radeon_drm_buffer_unmap(struct pb_buffer *_buf)
105 {
106 (void)_buf;
107 }
108
109 static void
110 radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf,
111 struct pb_buffer **base_buf,
112 unsigned *offset)
113 {
114 *base_buf = buf;
115 *offset = 0;
116 }
117
118
119 static enum pipe_error
120 radeon_drm_buffer_validate(struct pb_buffer *_buf,
121 struct pb_validate *vl,
122 unsigned flags)
123 {
124 /* Always pinned */
125 return PIPE_OK;
126 }
127
128 static void
129 radeon_drm_buffer_fence(struct pb_buffer *buf,
130 struct pipe_fence_handle *fence)
131 {
132 }
133
134 const struct pb_vtbl radeon_drm_buffer_vtbl = {
135 radeon_drm_buffer_destroy,
136 radeon_drm_buffer_map,
137 radeon_drm_buffer_unmap,
138 radeon_drm_buffer_validate,
139 radeon_drm_buffer_fence,
140 radeon_drm_buffer_get_base_buffer,
141 };
142
143
144 static uint32_t radeon_domain_from_usage(unsigned usage)
145 {
146 uint32_t domain = 0;
147
148 if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) {
149 domain |= RADEON_GEM_DOMAIN_VRAM;
150 }
151 if (usage & PIPE_BUFFER_USAGE_PIXEL) {
152 domain |= RADEON_GEM_DOMAIN_VRAM;
153 }
154 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
155 domain |= RADEON_GEM_DOMAIN_GTT;
156 }
157 if (usage & PIPE_BUFFER_USAGE_INDEX) {
158 domain |= RADEON_GEM_DOMAIN_GTT;
159 }
160
161 return domain;
162 }
163
164 struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
165 uint32_t handle)
166 {
167 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
168 struct radeon_libdrm_winsys *rws = mgr->rws;
169 struct radeon_drm_buffer *buf;
170 struct radeon_bo *bo;
171
172 bo = radeon_bo_open(rws->bom, handle, 0,
173 0, 0, 0);
174 if (bo == NULL)
175 return NULL;
176
177 buf = CALLOC_STRUCT(radeon_drm_buffer);
178 if (!buf) {
179 radeon_bo_unref(bo);
180 return NULL;
181 }
182
183 make_empty_list(buf);
184
185 pipe_reference_init(&buf->base.base.reference, 1);
186 buf->base.base.alignment = 0;
187 buf->base.base.usage = PIPE_BUFFER_USAGE_PIXEL;
188 buf->base.base.size = 0;
189 buf->base.vtbl = &radeon_drm_buffer_vtbl;
190 buf->mgr = mgr;
191
192 buf->bo = bo;
193
194 return &buf->base;
195 }
196
197 static struct pb_buffer *
198 radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr,
199 pb_size size,
200 const struct pb_desc *desc)
201 {
202 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
203 struct radeon_libdrm_winsys *rws = mgr->rws;
204 struct radeon_drm_buffer *buf;
205 uint32_t domain;
206
207 buf = CALLOC_STRUCT(radeon_drm_buffer);
208 if (!buf)
209 goto error1;
210
211 pipe_reference_init(&buf->base.base.reference, 1);
212 buf->base.base.alignment = desc->alignment;
213 buf->base.base.usage = desc->usage;
214 buf->base.base.size = size;
215 buf->base.vtbl = &radeon_drm_buffer_vtbl;
216 buf->mgr = mgr;
217
218 make_empty_list(buf);
219 domain = radeon_domain_from_usage(desc->usage);
220 buf->bo = radeon_bo_open(rws->bom, 0, size,
221 desc->alignment, domain, 0);
222 if (buf->bo == NULL)
223 goto error2;
224
225 return &buf->base;
226
227 error2:
228 FREE(buf);
229 error1:
230 return NULL;
231 }
232
233 static void
234 radeon_drm_bufmgr_flush(struct pb_manager *mgr)
235 {
236 /* NOP */
237 }
238
239 static void
240 radeon_drm_bufmgr_destroy(struct pb_manager *_mgr)
241 {
242 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
243 FREE(mgr);
244 }
245
246 struct pb_manager *
247 radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws)
248 {
249 struct radeon_drm_bufmgr *mgr;
250
251 mgr = CALLOC_STRUCT(radeon_drm_bufmgr);
252 if (!mgr)
253 return NULL;
254
255 mgr->base.destroy = radeon_drm_bufmgr_destroy;
256 mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer;
257 mgr->base.flush = radeon_drm_bufmgr_flush;
258
259 mgr->rws = rws;
260 make_empty_list(&mgr->buffer_map_list);
261 return &mgr->base;
262 }
263
264 static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
265 {
266 struct radeon_drm_buffer *buf;
267 if (_buf->vtbl == &radeon_drm_buffer_vtbl) {
268 buf = radeon_drm_buffer(_buf);
269 } else {
270 struct pb_buffer *base_buf;
271 pb_size offset;
272 pb_get_base_buffer(_buf, &base_buf, &offset);
273
274 buf = radeon_drm_buffer(base_buf);
275 }
276 return buf;
277 }
278
279 boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
280 struct winsys_handle *whandle)
281 {
282 int retval, fd;
283 struct drm_gem_flink flink;
284 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
285 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
286 if (!buf->flinked) {
287 fd = buf->mgr->rws->fd;
288 flink.handle = buf->bo->handle;
289
290 retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
291 if (retval) {
292 return false;
293 }
294
295 buf->flinked = TRUE;
296 buf->flink = flink.name;
297 }
298 whandle->handle = buf->flink;
299 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
300 whandle->handle = buf->bo->handle;
301 }
302 return TRUE;
303 }
304
305
306 void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf, boolean microtiled, boolean macrotiled, uint32_t pitch)
307 {
308 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
309 uint32_t flags = 0;
310
311 if (microtiled)
312 flags |= RADEON_BO_FLAGS_MICRO_TILE;
313 if (macrotiled)
314 flags |= RADEON_BO_FLAGS_MACRO_TILE;
315
316 radeon_bo_set_tiling(buf->bo, flags, pitch);
317
318 }
319
320 boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf,
321 uint32_t rd, uint32_t wd)
322 {
323 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
324 radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo,
325 rd, wd);
326 return true;
327 }
328
329 void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf,
330 uint32_t rd, uint32_t wd,
331 uint32_t flags)
332 {
333 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
334 int retval;
335
336 retval = radeon_cs_write_reloc(buf->mgr->rws->cs,
337 buf->bo, rd, wd, flags);
338 if (retval) {
339 debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n",
340 buf, rd, wd, flags);
341 }
342 }
343
344 boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf)
345 {
346 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
347 uint32_t domain;
348
349 return (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs) ||
350 radeon_bo_is_busy(buf->bo, &domain));
351 }
352
353
354 void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
355 {
356 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
357 struct radeon_drm_buffer *rpb, *t_rpb;
358
359 foreach_s(rpb, t_rpb, &mgr->buffer_map_list) {
360 rpb->mapped = 0;
361 radeon_bo_unmap(rpb->bo);
362 remove_from_list(rpb);
363 }
364
365 make_empty_list(&mgr->buffer_map_list);
366
367
368 }