3 #include "radeon_drm.h"
4 #include "radeon_bo_gem.h"
5 #include "radeon_cs_gem.h"
6 #include "radeon_buffer.h"
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"
14 #include "radeon_winsys.h"
15 struct radeon_drm_bufmgr;
17 struct radeon_drm_buffer {
18 struct pb_buffer base;
19 struct radeon_drm_bufmgr *mgr;
26 struct radeon_drm_buffer *next, *prev;
29 extern const struct pb_vtbl radeon_drm_buffer_vtbl;
32 static INLINE struct radeon_drm_buffer *
33 radeon_drm_buffer(struct pb_buffer *buf)
36 assert(buf->vtbl == &radeon_drm_buffer_vtbl);
37 return (struct radeon_drm_buffer *)buf;
40 struct radeon_drm_bufmgr {
41 struct pb_manager base;
42 struct radeon_libdrm_winsys *rws;
43 struct radeon_drm_buffer buffer_map_list;
46 static INLINE struct radeon_drm_bufmgr *
47 radeon_drm_bufmgr(struct pb_manager *mgr)
50 return (struct radeon_drm_bufmgr *)mgr;
54 radeon_drm_buffer_destroy(struct pb_buffer *_buf)
56 struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
58 if (buf->bo->ptr != NULL) {
59 remove_from_list(buf);
60 radeon_bo_unmap(buf->bo);
63 radeon_bo_unref(buf->bo);
69 radeon_drm_buffer_map(struct pb_buffer *_buf,
72 struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
75 if (flags & PIPE_TRANSFER_DONTBLOCK) {
76 if ((_buf->base.usage & PIPE_BIND_VERTEX_BUFFER) ||
77 (_buf->base.usage & PIPE_BIND_INDEX_BUFFER))
78 if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs))
82 if (buf->bo->ptr != NULL)
85 if (flags & PIPE_TRANSFER_DONTBLOCK) {
87 if (radeon_bo_is_busy(buf->bo, &domain))
91 if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
92 buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
95 if (flags & PIPE_TRANSFER_WRITE) {
99 if (radeon_bo_map(buf->bo, write)) {
102 insert_at_tail(&buf->mgr->buffer_map_list, buf);
107 radeon_drm_buffer_unmap(struct pb_buffer *_buf)
113 radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf,
114 struct pb_buffer **base_buf,
122 static enum pipe_error
123 radeon_drm_buffer_validate(struct pb_buffer *_buf,
124 struct pb_validate *vl,
132 radeon_drm_buffer_fence(struct pb_buffer *buf,
133 struct pipe_fence_handle *fence)
137 const struct pb_vtbl radeon_drm_buffer_vtbl = {
138 radeon_drm_buffer_destroy,
139 radeon_drm_buffer_map,
140 radeon_drm_buffer_unmap,
141 radeon_drm_buffer_validate,
142 radeon_drm_buffer_fence,
143 radeon_drm_buffer_get_base_buffer,
147 static uint32_t radeon_domain_from_usage(unsigned usage)
151 if (usage & PIPE_BIND_RENDER_TARGET) {
152 domain |= RADEON_GEM_DOMAIN_VRAM;
154 if (usage & PIPE_BIND_DEPTH_STENCIL) {
155 domain |= RADEON_GEM_DOMAIN_VRAM;
157 if (usage & PIPE_BIND_SAMPLER_VIEW) {
158 domain |= RADEON_GEM_DOMAIN_VRAM;
160 /* also need BIND_BLIT_SOURCE/DESTINATION ? */
161 if (usage & PIPE_BIND_VERTEX_BUFFER) {
162 domain |= RADEON_GEM_DOMAIN_GTT;
164 if (usage & PIPE_BIND_INDEX_BUFFER) {
165 domain |= RADEON_GEM_DOMAIN_GTT;
171 struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
174 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
175 struct radeon_libdrm_winsys *rws = mgr->rws;
176 struct radeon_drm_buffer *buf;
177 struct radeon_bo *bo;
179 bo = radeon_bo_open(rws->bom, handle, 0,
184 buf = CALLOC_STRUCT(radeon_drm_buffer);
190 make_empty_list(buf);
192 pipe_reference_init(&buf->base.base.reference, 1);
193 buf->base.base.alignment = 0;
194 buf->base.base.usage = PIPE_BIND_SAMPLER_VIEW;
195 buf->base.base.size = 0;
196 buf->base.vtbl = &radeon_drm_buffer_vtbl;
204 static struct pb_buffer *
205 radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr,
207 const struct pb_desc *desc)
209 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
210 struct radeon_libdrm_winsys *rws = mgr->rws;
211 struct radeon_drm_buffer *buf;
214 buf = CALLOC_STRUCT(radeon_drm_buffer);
218 pipe_reference_init(&buf->base.base.reference, 1);
219 buf->base.base.alignment = desc->alignment;
220 buf->base.base.usage = desc->usage;
221 buf->base.base.size = size;
222 buf->base.vtbl = &radeon_drm_buffer_vtbl;
225 make_empty_list(buf);
226 domain = radeon_domain_from_usage(desc->usage);
227 buf->bo = radeon_bo_open(rws->bom, 0, size,
228 desc->alignment, domain, 0);
241 radeon_drm_bufmgr_flush(struct pb_manager *mgr)
247 radeon_drm_bufmgr_destroy(struct pb_manager *_mgr)
249 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
254 radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws)
256 struct radeon_drm_bufmgr *mgr;
258 mgr = CALLOC_STRUCT(radeon_drm_bufmgr);
262 mgr->base.destroy = radeon_drm_bufmgr_destroy;
263 mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer;
264 mgr->base.flush = radeon_drm_bufmgr_flush;
267 make_empty_list(&mgr->buffer_map_list);
271 static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
273 struct radeon_drm_buffer *buf;
274 if (_buf->vtbl == &radeon_drm_buffer_vtbl) {
275 buf = radeon_drm_buffer(_buf);
277 struct pb_buffer *base_buf;
279 pb_get_base_buffer(_buf, &base_buf, &offset);
281 buf = radeon_drm_buffer(base_buf);
286 boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
287 struct winsys_handle *whandle)
290 struct drm_gem_flink flink;
291 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
292 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
294 fd = buf->mgr->rws->fd;
295 flink.handle = buf->bo->handle;
297 retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
303 buf->flink = flink.name;
305 whandle->handle = buf->flink;
306 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
307 whandle->handle = buf->bo->handle;
312 void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
313 enum r300_buffer_tiling *microtiled,
314 enum r300_buffer_tiling *macrotiled)
316 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
317 uint32_t flags = 0, pitch;
319 radeon_bo_get_tiling(buf->bo, &flags, &pitch);
321 *microtiled = R300_BUFFER_LINEAR;
322 *macrotiled = R300_BUFFER_LINEAR;
323 if (flags & RADEON_BO_FLAGS_MICRO_TILE)
324 *microtiled = R300_BUFFER_TILED;
326 if (flags & RADEON_BO_FLAGS_MACRO_TILE)
327 *macrotiled = R300_BUFFER_TILED;
330 void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
331 enum r300_buffer_tiling microtiled,
332 enum r300_buffer_tiling macrotiled,
335 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
336 uint32_t flags = 0, old_flags, old_pitch;
337 if (microtiled == R300_BUFFER_TILED)
338 flags |= RADEON_BO_FLAGS_MICRO_TILE;
339 /* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */
340 #ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE
341 else if (microtiled == R300_BUFFER_SQUARETILED)
342 flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE;
344 if (macrotiled == R300_BUFFER_TILED)
345 flags |= RADEON_BO_FLAGS_MACRO_TILE;
347 radeon_bo_get_tiling(buf->bo, &old_flags, &old_pitch);
349 if (flags != old_flags || pitch != old_pitch) {
350 /* Tiling determines how DRM treats the buffer data.
351 * We must flush CS when changing it if the buffer is referenced. */
352 if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
353 buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
356 radeon_bo_set_tiling(buf->bo, flags, pitch);
360 boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf,
361 uint32_t rd, uint32_t wd)
363 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
364 radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo,
369 void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf,
370 uint32_t rd, uint32_t wd,
373 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
376 retval = radeon_cs_write_reloc(buf->mgr->rws->cs,
377 buf->bo, rd, wd, flags);
379 debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n",
384 boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf)
386 struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
389 return (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs) ||
390 radeon_bo_is_busy(buf->bo, &domain));
394 void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
396 struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
397 struct radeon_drm_buffer *rpb, *t_rpb;
399 foreach_s(rpb, t_rpb, &mgr->buffer_map_list) {
400 radeon_bo_unmap(rpb->bo);
402 remove_from_list(rpb);
405 make_empty_list(&mgr->buffer_map_list);