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
;
28 struct radeon_drm_buffer
*next
, *prev
;
31 extern const struct pb_vtbl radeon_drm_buffer_vtbl
;
34 static INLINE
struct radeon_drm_buffer
*
35 radeon_drm_buffer(struct pb_buffer
*buf
)
38 assert(buf
->vtbl
== &radeon_drm_buffer_vtbl
);
39 return (struct radeon_drm_buffer
*)buf
;
42 struct radeon_drm_bufmgr
{
43 struct pb_manager base
;
44 struct radeon_libdrm_winsys
*rws
;
45 struct radeon_drm_buffer buffer_map_list
;
48 static INLINE
struct radeon_drm_bufmgr
*
49 radeon_drm_bufmgr(struct pb_manager
*mgr
)
52 return (struct radeon_drm_bufmgr
*)mgr
;
56 radeon_drm_buffer_destroy(struct pb_buffer
*_buf
)
58 struct radeon_drm_buffer
*buf
= radeon_drm_buffer(_buf
);
60 if (buf
->bo
->ptr
!= NULL
) {
61 remove_from_list(buf
);
62 radeon_bo_unmap(buf
->bo
);
65 radeon_bo_unref(buf
->bo
);
71 radeon_drm_buffer_map(struct pb_buffer
*_buf
,
74 struct radeon_drm_buffer
*buf
= radeon_drm_buffer(_buf
);
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
))
84 if (buf
->bo
->ptr
!= NULL
)
87 if (flags
& PIPE_TRANSFER_DONTBLOCK
) {
89 if (radeon_bo_is_busy(buf
->bo
, &domain
))
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
);
97 if (flags
& PIPE_TRANSFER_WRITE
) {
101 if (radeon_bo_map(buf
->bo
, write
)) {
104 insert_at_tail(&buf
->mgr
->buffer_map_list
, buf
);
109 radeon_drm_buffer_unmap(struct pb_buffer
*_buf
)
115 radeon_drm_buffer_get_base_buffer(struct pb_buffer
*buf
,
116 struct pb_buffer
**base_buf
,
124 static enum pipe_error
125 radeon_drm_buffer_validate(struct pb_buffer
*_buf
,
126 struct pb_validate
*vl
,
134 radeon_drm_buffer_fence(struct pb_buffer
*buf
,
135 struct pipe_fence_handle
*fence
)
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
,
148 struct pb_buffer
*radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
*_mgr
,
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
;
156 bo
= radeon_bo_open(rws
->bom
, handle
, 0,
161 buf
= CALLOC_STRUCT(radeon_drm_buffer
);
167 make_empty_list(buf
);
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
;
181 static struct pb_buffer
*
182 radeon_drm_bufmgr_create_buffer(struct pb_manager
*_mgr
,
184 const struct pb_desc
*desc
)
186 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
187 struct radeon_libdrm_winsys
*rws
= mgr
->rws
;
188 struct radeon_drm_buffer
*buf
;
191 buf
= CALLOC_STRUCT(radeon_drm_buffer
);
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
;
202 make_empty_list(buf
);
205 (desc
->usage
& RADEON_USAGE_DOMAIN_GTT
? RADEON_GEM_DOMAIN_GTT
: 0) |
206 (desc
->usage
& RADEON_USAGE_DOMAIN_VRAM
? RADEON_GEM_DOMAIN_VRAM
: 0);
208 buf
->bo
= radeon_bo_open(rws
->bom
, 0, size
,
209 desc
->alignment
, domain
, 0);
222 radeon_drm_bufmgr_flush(struct pb_manager
*mgr
)
228 radeon_drm_bufmgr_destroy(struct pb_manager
*_mgr
)
230 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
235 radeon_drm_bufmgr_create(struct radeon_libdrm_winsys
*rws
)
237 struct radeon_drm_bufmgr
*mgr
;
239 mgr
= CALLOC_STRUCT(radeon_drm_bufmgr
);
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
;
248 make_empty_list(&mgr
->buffer_map_list
);
252 static struct radeon_drm_buffer
*get_drm_buffer(struct pb_buffer
*_buf
)
254 struct radeon_drm_buffer
*buf
;
255 if (_buf
->vtbl
== &radeon_drm_buffer_vtbl
) {
256 buf
= radeon_drm_buffer(_buf
);
258 struct pb_buffer
*base_buf
;
260 pb_get_base_buffer(_buf
, &base_buf
, &offset
);
262 buf
= radeon_drm_buffer(base_buf
);
267 boolean
radeon_drm_bufmgr_get_handle(struct pb_buffer
*_buf
,
268 struct winsys_handle
*whandle
)
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
) {
275 fd
= buf
->mgr
->rws
->fd
;
276 flink
.handle
= buf
->bo
->handle
;
278 retval
= ioctl(fd
, DRM_IOCTL_GEM_FLINK
, &flink
);
284 buf
->flink
= flink
.name
;
286 whandle
->handle
= buf
->flink
;
287 } else if (whandle
->type
== DRM_API_HANDLE_TYPE_KMS
) {
288 whandle
->handle
= buf
->bo
->handle
;
293 void radeon_drm_bufmgr_get_tiling(struct pb_buffer
*_buf
,
294 enum r300_buffer_tiling
*microtiled
,
295 enum r300_buffer_tiling
*macrotiled
)
297 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
298 uint32_t flags
= 0, pitch
;
300 radeon_bo_get_tiling(buf
->bo
, &flags
, &pitch
);
302 buf
->tileflags
= flags
;
305 *microtiled
= R300_BUFFER_LINEAR
;
306 *macrotiled
= R300_BUFFER_LINEAR
;
307 if (flags
& RADEON_BO_FLAGS_MICRO_TILE
)
308 *microtiled
= R300_BUFFER_TILED
;
310 if (flags
& RADEON_BO_FLAGS_MACRO_TILE
)
311 *macrotiled
= R300_BUFFER_TILED
;
314 void radeon_drm_bufmgr_set_tiling(struct pb_buffer
*_buf
,
315 enum r300_buffer_tiling microtiled
,
316 enum r300_buffer_tiling macrotiled
,
319 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
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
;
328 if (macrotiled
== R300_BUFFER_TILED
)
329 flags
|= RADEON_BO_FLAGS_MACRO_TILE
;
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
);
338 radeon_bo_set_tiling(buf
->bo
, flags
, pitch
);
342 static uint32_t gem_domain(enum r300_buffer_domain dom
)
346 if (dom
& R300_DOMAIN_GTT
)
347 res
|= RADEON_GEM_DOMAIN_GTT
;
348 if (dom
& R300_DOMAIN_VRAM
)
349 res
|= RADEON_GEM_DOMAIN_VRAM
;
353 boolean
radeon_drm_bufmgr_add_buffer(struct pb_buffer
*_buf
,
354 enum r300_buffer_domain rd
,
355 enum r300_buffer_domain wd
)
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
);
361 radeon_cs_space_add_persistent_bo(buf
->mgr
->rws
->cs
, buf
->bo
,
366 void radeon_drm_bufmgr_write_reloc(struct pb_buffer
*_buf
,
367 enum r300_buffer_domain rd
,
368 enum r300_buffer_domain wd
,
371 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
373 uint32_t gem_rd
= gem_domain(rd
);
374 uint32_t gem_wd
= gem_domain(wd
);
376 retval
= radeon_cs_write_reloc(buf
->mgr
->rws
->cs
,
377 buf
->bo
, gem_rd
, gem_wd
, flags
);
379 debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n",
380 buf
, gem_rd
, gem_wd
, flags
);
384 boolean
radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer
*_buf
,
385 enum r300_reference_domain domain
)
387 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
390 if (domain
& R300_REF_CS
) {
391 if (radeon_bo_is_referenced_by_cs(buf
->bo
, buf
->mgr
->rws
->cs
)) {
396 if (domain
& R300_REF_HW
) {
397 if (radeon_bo_is_busy(buf
->bo
, &tmp
)) {
406 void radeon_drm_bufmgr_flush_maps(struct pb_manager
*_mgr
)
408 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
409 struct radeon_drm_buffer
*rpb
, *t_rpb
;
411 foreach_s(rpb
, t_rpb
, &mgr
->buffer_map_list
) {
412 radeon_bo_unmap(rpb
->bo
);
414 remove_from_list(rpb
);
417 make_empty_list(&mgr
->buffer_map_list
);
420 void radeon_drm_bufmgr_wait(struct pb_buffer
*_buf
)
422 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
424 radeon_bo_wait(buf
->bo
);