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
,
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
);