r300g: use r300_buffer_domain everywhere
[mesa.git] / src / gallium / winsys / radeon / drm / 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 uint32_t tileflags;
26 uint32_t pitch;
27
28 struct radeon_drm_buffer *next, *prev;
29 };
30
31 extern const struct pb_vtbl radeon_drm_buffer_vtbl;
32
33
34 static INLINE struct radeon_drm_buffer *
35 radeon_drm_buffer(struct pb_buffer *buf)
36 {
37 assert(buf);
38 assert(buf->vtbl == &radeon_drm_buffer_vtbl);
39 return (struct radeon_drm_buffer *)buf;
40 }
41
42 struct radeon_drm_bufmgr {
43 struct pb_manager base;
44 struct radeon_libdrm_winsys *rws;
45 struct radeon_drm_buffer buffer_map_list;
46 };
47
48 static INLINE struct radeon_drm_bufmgr *
49 radeon_drm_bufmgr(struct pb_manager *mgr)
50 {
51 assert(mgr);
52 return (struct radeon_drm_bufmgr *)mgr;
53 }
54
55 static void
56 radeon_drm_buffer_destroy(struct pb_buffer *_buf)
57 {
58 struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
59
60 if (buf->bo->ptr != NULL) {
61 remove_from_list(buf);
62 radeon_bo_unmap(buf->bo);
63 buf->bo->ptr = NULL;
64 }
65 radeon_bo_unref(buf->bo);
66
67 FREE(buf);
68 }
69
70 static void *
71 radeon_drm_buffer_map(struct pb_buffer *_buf,
72 unsigned flags)
73 {
74 struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
75 int write = 0;
76
77 if (flags & PIPE_TRANSFER_DONTBLOCK) {
78 if ((_buf->base.usage & PIPE_BIND_VERTEX_BUFFER) ||
79 (_buf->base.usage & PIPE_BIND_INDEX_BUFFER))
80 if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs))
81 return NULL;
82 }
83
84 if (buf->bo->ptr != NULL)
85 return buf->bo->ptr;
86
87 if (flags & PIPE_TRANSFER_DONTBLOCK) {
88 uint32_t domain;
89 if (radeon_bo_is_busy(buf->bo, &domain))
90 return NULL;
91 }
92
93 if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
94 buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
95 }
96
97 if (flags & PIPE_TRANSFER_WRITE) {
98 write = 1;
99 }
100
101 if (radeon_bo_map(buf->bo, write)) {
102 return NULL;
103 }
104 insert_at_tail(&buf->mgr->buffer_map_list, buf);
105 return buf->bo->ptr;
106 }
107
108 static void
109 radeon_drm_buffer_unmap(struct pb_buffer *_buf)
110 {
111 (void)_buf;
112 }
113
114 static void
115 radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf,
116 struct pb_buffer **base_buf,
117 unsigned *offset)
118 {
119 *base_buf = buf;
120 *offset = 0;
121 }
122
123
124 static enum pipe_error
125 radeon_drm_buffer_validate(struct pb_buffer *_buf,
126 struct pb_validate *vl,
127 unsigned flags)
128 {
129 /* Always pinned */
130 return PIPE_OK;
131 }
132
133 static void
134 radeon_drm_buffer_fence(struct pb_buffer *buf,
135 struct pipe_fence_handle *fence)
136 {
137 }
138
139 const struct pb_vtbl radeon_drm_buffer_vtbl = {
140 radeon_drm_buffer_destroy,
141 radeon_drm_buffer_map,
142 radeon_drm_buffer_unmap,
143 radeon_drm_buffer_validate,
144 radeon_drm_buffer_fence,
145 radeon_drm_buffer_get_base_buffer,
146 };
147
148 struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
149 uint32_t handle)
150 {
151 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
152 struct radeon_libdrm_winsys *rws = mgr->rws;
153 struct radeon_drm_buffer *buf;
154 struct radeon_bo *bo;
155
156 bo = radeon_bo_open(rws->bom, handle, 0,
157 0, 0, 0);
158 if (bo == NULL)
159 return NULL;
160
161 buf = CALLOC_STRUCT(radeon_drm_buffer);
162 if (!buf) {
163 radeon_bo_unref(bo);
164 return NULL;
165 }
166
167 make_empty_list(buf);
168
169 pipe_reference_init(&buf->base.base.reference, 1);
170 buf->base.base.alignment = 0;
171 buf->base.base.usage = PIPE_BIND_SAMPLER_VIEW;
172 buf->base.base.size = 0;
173 buf->base.vtbl = &radeon_drm_buffer_vtbl;
174 buf->mgr = mgr;
175
176 buf->bo = bo;
177
178 return &buf->base;
179 }
180
181 static struct pb_buffer *
182 radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr,
183 pb_size size,
184 const struct pb_desc *desc)
185 {
186 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
187 struct radeon_libdrm_winsys *rws = mgr->rws;
188 struct radeon_drm_buffer *buf;
189 uint32_t domain;
190
191 buf = CALLOC_STRUCT(radeon_drm_buffer);
192 if (!buf)
193 goto error1;
194
195 pipe_reference_init(&buf->base.base.reference, 1);
196 buf->base.base.alignment = desc->alignment;
197 buf->base.base.usage = desc->usage;
198 buf->base.base.size = size;
199 buf->base.vtbl = &radeon_drm_buffer_vtbl;
200 buf->mgr = mgr;
201
202 make_empty_list(buf);
203
204 domain =
205 (desc->usage & RADEON_USAGE_DOMAIN_GTT ? RADEON_GEM_DOMAIN_GTT : 0) |
206 (desc->usage & RADEON_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0);
207
208 buf->bo = radeon_bo_open(rws->bom, 0, size,
209 desc->alignment, domain, 0);
210 if (buf->bo == NULL)
211 goto error2;
212
213 return &buf->base;
214
215 error2:
216 FREE(buf);
217 error1:
218 return NULL;
219 }
220
221 static void
222 radeon_drm_bufmgr_flush(struct pb_manager *mgr)
223 {
224 /* NOP */
225 }
226
227 static void
228 radeon_drm_bufmgr_destroy(struct pb_manager *_mgr)
229 {
230 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
231 FREE(mgr);
232 }
233
234 struct pb_manager *
235 radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws)
236 {
237 struct radeon_drm_bufmgr *mgr;
238
239 mgr = CALLOC_STRUCT(radeon_drm_bufmgr);
240 if (!mgr)
241 return NULL;
242
243 mgr->base.destroy = radeon_drm_bufmgr_destroy;
244 mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer;
245 mgr->base.flush = radeon_drm_bufmgr_flush;
246
247 mgr->rws = rws;
248 make_empty_list(&mgr->buffer_map_list);
249 return &mgr->base;
250 }
251
252 static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
253 {
254 struct radeon_drm_buffer *buf;
255 if (_buf->vtbl == &radeon_drm_buffer_vtbl) {
256 buf = radeon_drm_buffer(_buf);
257 } else {
258 struct pb_buffer *base_buf;
259 pb_size offset;
260 pb_get_base_buffer(_buf, &base_buf, &offset);
261
262 buf = radeon_drm_buffer(base_buf);
263 }
264 return buf;
265 }
266
267 boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
268 struct winsys_handle *whandle)
269 {
270 int retval, fd;
271 struct drm_gem_flink flink;
272 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
273 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
274 if (!buf->flinked) {
275 fd = buf->mgr->rws->fd;
276 flink.handle = buf->bo->handle;
277
278 retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
279 if (retval) {
280 return FALSE;
281 }
282
283 buf->flinked = TRUE;
284 buf->flink = flink.name;
285 }
286 whandle->handle = buf->flink;
287 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
288 whandle->handle = buf->bo->handle;
289 }
290 return TRUE;
291 }
292
293 void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
294 enum r300_buffer_tiling *microtiled,
295 enum r300_buffer_tiling *macrotiled)
296 {
297 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
298 uint32_t flags = 0, pitch;
299
300 radeon_bo_get_tiling(buf->bo, &flags, &pitch);
301
302 buf->tileflags = flags;
303 buf->pitch = pitch;
304
305 *microtiled = R300_BUFFER_LINEAR;
306 *macrotiled = R300_BUFFER_LINEAR;
307 if (flags & RADEON_BO_FLAGS_MICRO_TILE)
308 *microtiled = R300_BUFFER_TILED;
309
310 if (flags & RADEON_BO_FLAGS_MACRO_TILE)
311 *macrotiled = R300_BUFFER_TILED;
312 }
313
314 void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
315 enum r300_buffer_tiling microtiled,
316 enum r300_buffer_tiling macrotiled,
317 uint32_t pitch)
318 {
319 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
320 uint32_t flags = 0;
321 if (microtiled == R300_BUFFER_TILED)
322 flags |= RADEON_BO_FLAGS_MICRO_TILE;
323 /* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */
324 #ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE
325 else if (microtiled == R300_BUFFER_SQUARETILED)
326 flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE;
327 #endif
328 if (macrotiled == R300_BUFFER_TILED)
329 flags |= RADEON_BO_FLAGS_MACRO_TILE;
330
331 if (flags != buf->tileflags || pitch != buf->pitch) {
332 /* Tiling determines how DRM treats the buffer data.
333 * We must flush CS when changing it if the buffer is referenced. */
334 if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
335 buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
336 }
337
338 radeon_bo_set_tiling(buf->bo, flags, pitch);
339 }
340 }
341
342 static uint32_t gem_domain(enum r300_buffer_domain dom)
343 {
344 uint32_t res = 0;
345
346 if (dom & R300_DOMAIN_GTT)
347 res |= RADEON_GEM_DOMAIN_GTT;
348 if (dom & R300_DOMAIN_VRAM)
349 res |= RADEON_GEM_DOMAIN_VRAM;
350 return res;
351 }
352
353 boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf,
354 enum r300_buffer_domain rd,
355 enum r300_buffer_domain wd)
356 {
357 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
358 uint32_t gem_rd = gem_domain(rd);
359 uint32_t gem_wd = gem_domain(wd);
360
361 radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo,
362 gem_rd, gem_wd);
363 return TRUE;
364 }
365
366 void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf,
367 enum r300_buffer_domain rd,
368 enum r300_buffer_domain wd,
369 uint32_t flags)
370 {
371 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
372 int retval;
373 uint32_t gem_rd = gem_domain(rd);
374 uint32_t gem_wd = gem_domain(wd);
375
376 retval = radeon_cs_write_reloc(buf->mgr->rws->cs,
377 buf->bo, gem_rd, gem_wd, flags);
378 if (retval) {
379 debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n",
380 buf, gem_rd, gem_wd, flags);
381 }
382 }
383
384 boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
385 enum r300_reference_domain domain)
386 {
387 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
388 uint32_t tmp;
389
390 if (domain & R300_REF_CS) {
391 if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
392 return TRUE;
393 }
394 }
395
396 if (domain & R300_REF_HW) {
397 if (radeon_bo_is_busy(buf->bo, &tmp)) {
398 return TRUE;
399 }
400 }
401
402 return FALSE;
403 }
404
405
406 void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
407 {
408 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
409 struct radeon_drm_buffer *rpb, *t_rpb;
410
411 foreach_s(rpb, t_rpb, &mgr->buffer_map_list) {
412 radeon_bo_unmap(rpb->bo);
413 rpb->bo->ptr = NULL;
414 remove_from_list(rpb);
415 }
416
417 make_empty_list(&mgr->buffer_map_list);
418 }
419
420 void radeon_drm_bufmgr_wait(struct pb_buffer *_buf)
421 {
422 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
423
424 radeon_bo_wait(buf->bo);
425 }