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_BUFFER_USAGE_DONTBLOCK
) {
76 if ((_buf
->base
.usage
& PIPE_BUFFER_USAGE_VERTEX
) ||
77 (_buf
->base
.usage
& PIPE_BUFFER_USAGE_INDEX
))
78 if (radeon_bo_is_referenced_by_cs(buf
->bo
, buf
->mgr
->rws
->cs
))
82 if (buf
->bo
->ptr
!= NULL
)
85 if (flags
& PIPE_BUFFER_USAGE_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_BUFFER_USAGE_CPU_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_BUFFER_USAGE_GPU_WRITE
) {
152 domain
|= RADEON_GEM_DOMAIN_VRAM
;
154 if (usage
& PIPE_BUFFER_USAGE_PIXEL
) {
155 domain
|= RADEON_GEM_DOMAIN_VRAM
;
157 if (usage
& PIPE_BUFFER_USAGE_VERTEX
) {
158 domain
|= RADEON_GEM_DOMAIN_GTT
;
160 if (usage
& PIPE_BUFFER_USAGE_INDEX
) {
161 domain
|= RADEON_GEM_DOMAIN_GTT
;
167 struct pb_buffer
*radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
*_mgr
,
170 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
171 struct radeon_libdrm_winsys
*rws
= mgr
->rws
;
172 struct radeon_drm_buffer
*buf
;
173 struct radeon_bo
*bo
;
175 bo
= radeon_bo_open(rws
->bom
, handle
, 0,
180 buf
= CALLOC_STRUCT(radeon_drm_buffer
);
186 make_empty_list(buf
);
188 pipe_reference_init(&buf
->base
.base
.reference
, 1);
189 buf
->base
.base
.alignment
= 0;
190 buf
->base
.base
.usage
= PIPE_BUFFER_USAGE_PIXEL
;
191 buf
->base
.base
.size
= 0;
192 buf
->base
.vtbl
= &radeon_drm_buffer_vtbl
;
200 static struct pb_buffer
*
201 radeon_drm_bufmgr_create_buffer(struct pb_manager
*_mgr
,
203 const struct pb_desc
*desc
)
205 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
206 struct radeon_libdrm_winsys
*rws
= mgr
->rws
;
207 struct radeon_drm_buffer
*buf
;
210 buf
= CALLOC_STRUCT(radeon_drm_buffer
);
214 pipe_reference_init(&buf
->base
.base
.reference
, 1);
215 buf
->base
.base
.alignment
= desc
->alignment
;
216 buf
->base
.base
.usage
= desc
->usage
;
217 buf
->base
.base
.size
= size
;
218 buf
->base
.vtbl
= &radeon_drm_buffer_vtbl
;
221 make_empty_list(buf
);
222 domain
= radeon_domain_from_usage(desc
->usage
);
223 buf
->bo
= radeon_bo_open(rws
->bom
, 0, size
,
224 desc
->alignment
, domain
, 0);
237 radeon_drm_bufmgr_flush(struct pb_manager
*mgr
)
243 radeon_drm_bufmgr_destroy(struct pb_manager
*_mgr
)
245 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
250 radeon_drm_bufmgr_create(struct radeon_libdrm_winsys
*rws
)
252 struct radeon_drm_bufmgr
*mgr
;
254 mgr
= CALLOC_STRUCT(radeon_drm_bufmgr
);
258 mgr
->base
.destroy
= radeon_drm_bufmgr_destroy
;
259 mgr
->base
.create_buffer
= radeon_drm_bufmgr_create_buffer
;
260 mgr
->base
.flush
= radeon_drm_bufmgr_flush
;
263 make_empty_list(&mgr
->buffer_map_list
);
267 static struct radeon_drm_buffer
*get_drm_buffer(struct pb_buffer
*_buf
)
269 struct radeon_drm_buffer
*buf
;
270 if (_buf
->vtbl
== &radeon_drm_buffer_vtbl
) {
271 buf
= radeon_drm_buffer(_buf
);
273 struct pb_buffer
*base_buf
;
275 pb_get_base_buffer(_buf
, &base_buf
, &offset
);
277 buf
= radeon_drm_buffer(base_buf
);
282 boolean
radeon_drm_bufmgr_get_handle(struct pb_buffer
*_buf
,
283 struct winsys_handle
*whandle
)
286 struct drm_gem_flink flink
;
287 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
288 if (whandle
->type
== DRM_API_HANDLE_TYPE_SHARED
) {
290 fd
= buf
->mgr
->rws
->fd
;
291 flink
.handle
= buf
->bo
->handle
;
293 retval
= ioctl(fd
, DRM_IOCTL_GEM_FLINK
, &flink
);
299 buf
->flink
= flink
.name
;
301 whandle
->handle
= buf
->flink
;
302 } else if (whandle
->type
== DRM_API_HANDLE_TYPE_KMS
) {
303 whandle
->handle
= buf
->bo
->handle
;
308 void radeon_drm_bufmgr_get_tiling(struct pb_buffer
*_buf
,
309 enum r300_buffer_tiling
*microtiled
,
310 enum r300_buffer_tiling
*macrotiled
)
312 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
313 uint32_t flags
= 0, pitch
;
315 radeon_bo_get_tiling(buf
->bo
, &flags
, &pitch
);
317 *microtiled
= R300_BUFFER_LINEAR
;
318 *macrotiled
= R300_BUFFER_LINEAR
;
319 if (flags
& RADEON_BO_FLAGS_MICRO_TILE
)
320 *microtiled
= R300_BUFFER_TILED
;
322 if (flags
& RADEON_BO_FLAGS_MACRO_TILE
)
323 *macrotiled
= R300_BUFFER_TILED
;
326 void radeon_drm_bufmgr_set_tiling(struct pb_buffer
*_buf
,
327 enum r300_buffer_tiling microtiled
,
328 enum r300_buffer_tiling macrotiled
,
331 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
332 uint32_t flags
= 0, old_flags
, old_pitch
;
333 if (microtiled
== R300_BUFFER_TILED
)
334 flags
|= RADEON_BO_FLAGS_MICRO_TILE
;
335 /* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */
336 #ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE
337 else if (microtiled
== R300_BUFFER_SQUARETILED
)
338 flags
|= RADEON_BO_FLAGS_MICRO_TILE_SQUARE
;
340 if (macrotiled
== R300_BUFFER_TILED
)
341 flags
|= RADEON_BO_FLAGS_MACRO_TILE
;
343 radeon_bo_get_tiling(buf
->bo
, &old_flags
, &old_pitch
);
345 if (flags
!= old_flags
|| pitch
!= old_pitch
) {
346 /* Tiling determines how DRM treats the buffer data.
347 * We must flush CS when changing it if the buffer is referenced. */
348 if (radeon_bo_is_referenced_by_cs(buf
->bo
, buf
->mgr
->rws
->cs
)) {
349 buf
->mgr
->rws
->flush_cb(buf
->mgr
->rws
->flush_data
);
352 radeon_bo_set_tiling(buf
->bo
, flags
, pitch
);
356 boolean
radeon_drm_bufmgr_add_buffer(struct pb_buffer
*_buf
,
357 uint32_t rd
, uint32_t wd
)
359 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
360 radeon_cs_space_add_persistent_bo(buf
->mgr
->rws
->cs
, buf
->bo
,
365 void radeon_drm_bufmgr_write_reloc(struct pb_buffer
*_buf
,
366 uint32_t rd
, uint32_t wd
,
369 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
372 retval
= radeon_cs_write_reloc(buf
->mgr
->rws
->cs
,
373 buf
->bo
, rd
, wd
, flags
);
375 debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n",
380 boolean
radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer
*_buf
)
382 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
385 return (radeon_bo_is_referenced_by_cs(buf
->bo
, buf
->mgr
->rws
->cs
) ||
386 radeon_bo_is_busy(buf
->bo
, &domain
));
390 void radeon_drm_bufmgr_flush_maps(struct pb_manager
*_mgr
)
392 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
393 struct radeon_drm_buffer
*rpb
, *t_rpb
;
395 foreach_s(rpb
, t_rpb
, &mgr
->buffer_map_list
) {
396 radeon_bo_unmap(rpb
->bo
);
398 remove_from_list(rpb
);
401 make_empty_list(&mgr
->buffer_map_list
);