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
,
149 static uint32_t radeon_domain_from_usage(unsigned usage
)
153 if (usage
& PIPE_BIND_RENDER_TARGET
) {
154 domain
|= RADEON_GEM_DOMAIN_VRAM
;
156 if (usage
& PIPE_BIND_DEPTH_STENCIL
) {
157 domain
|= RADEON_GEM_DOMAIN_VRAM
;
159 if (usage
& PIPE_BIND_SAMPLER_VIEW
) {
160 domain
|= RADEON_GEM_DOMAIN_VRAM
;
162 /* also need BIND_BLIT_SOURCE/DESTINATION ? */
163 if (usage
& PIPE_BIND_VERTEX_BUFFER
) {
164 domain
|= RADEON_GEM_DOMAIN_GTT
;
166 if (usage
& PIPE_BIND_INDEX_BUFFER
) {
167 domain
|= RADEON_GEM_DOMAIN_GTT
;
173 struct pb_buffer
*radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
*_mgr
,
176 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
177 struct radeon_libdrm_winsys
*rws
= mgr
->rws
;
178 struct radeon_drm_buffer
*buf
;
179 struct radeon_bo
*bo
;
181 bo
= radeon_bo_open(rws
->bom
, handle
, 0,
186 buf
= CALLOC_STRUCT(radeon_drm_buffer
);
192 make_empty_list(buf
);
194 pipe_reference_init(&buf
->base
.base
.reference
, 1);
195 buf
->base
.base
.alignment
= 0;
196 buf
->base
.base
.usage
= PIPE_BIND_SAMPLER_VIEW
;
197 buf
->base
.base
.size
= 0;
198 buf
->base
.vtbl
= &radeon_drm_buffer_vtbl
;
206 static struct pb_buffer
*
207 radeon_drm_bufmgr_create_buffer(struct pb_manager
*_mgr
,
209 const struct pb_desc
*desc
)
211 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
212 struct radeon_libdrm_winsys
*rws
= mgr
->rws
;
213 struct radeon_drm_buffer
*buf
;
216 buf
= CALLOC_STRUCT(radeon_drm_buffer
);
220 pipe_reference_init(&buf
->base
.base
.reference
, 1);
221 buf
->base
.base
.alignment
= desc
->alignment
;
222 buf
->base
.base
.usage
= desc
->usage
;
223 buf
->base
.base
.size
= size
;
224 buf
->base
.vtbl
= &radeon_drm_buffer_vtbl
;
227 make_empty_list(buf
);
228 domain
= radeon_domain_from_usage(desc
->usage
);
229 buf
->bo
= radeon_bo_open(rws
->bom
, 0, size
,
230 desc
->alignment
, domain
, 0);
243 radeon_drm_bufmgr_flush(struct pb_manager
*mgr
)
249 radeon_drm_bufmgr_destroy(struct pb_manager
*_mgr
)
251 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
256 radeon_drm_bufmgr_create(struct radeon_libdrm_winsys
*rws
)
258 struct radeon_drm_bufmgr
*mgr
;
260 mgr
= CALLOC_STRUCT(radeon_drm_bufmgr
);
264 mgr
->base
.destroy
= radeon_drm_bufmgr_destroy
;
265 mgr
->base
.create_buffer
= radeon_drm_bufmgr_create_buffer
;
266 mgr
->base
.flush
= radeon_drm_bufmgr_flush
;
269 make_empty_list(&mgr
->buffer_map_list
);
273 static struct radeon_drm_buffer
*get_drm_buffer(struct pb_buffer
*_buf
)
275 struct radeon_drm_buffer
*buf
;
276 if (_buf
->vtbl
== &radeon_drm_buffer_vtbl
) {
277 buf
= radeon_drm_buffer(_buf
);
279 struct pb_buffer
*base_buf
;
281 pb_get_base_buffer(_buf
, &base_buf
, &offset
);
283 buf
= radeon_drm_buffer(base_buf
);
288 boolean
radeon_drm_bufmgr_get_handle(struct pb_buffer
*_buf
,
289 struct winsys_handle
*whandle
)
292 struct drm_gem_flink flink
;
293 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
294 if (whandle
->type
== DRM_API_HANDLE_TYPE_SHARED
) {
296 fd
= buf
->mgr
->rws
->fd
;
297 flink
.handle
= buf
->bo
->handle
;
299 retval
= ioctl(fd
, DRM_IOCTL_GEM_FLINK
, &flink
);
305 buf
->flink
= flink
.name
;
307 whandle
->handle
= buf
->flink
;
308 } else if (whandle
->type
== DRM_API_HANDLE_TYPE_KMS
) {
309 whandle
->handle
= buf
->bo
->handle
;
314 void radeon_drm_bufmgr_get_tiling(struct pb_buffer
*_buf
,
315 enum r300_buffer_tiling
*microtiled
,
316 enum r300_buffer_tiling
*macrotiled
)
318 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
319 uint32_t flags
= 0, pitch
;
321 radeon_bo_get_tiling(buf
->bo
, &flags
, &pitch
);
323 buf
->tileflags
= flags
;
326 *microtiled
= R300_BUFFER_LINEAR
;
327 *macrotiled
= R300_BUFFER_LINEAR
;
328 if (flags
& RADEON_BO_FLAGS_MICRO_TILE
)
329 *microtiled
= R300_BUFFER_TILED
;
331 if (flags
& RADEON_BO_FLAGS_MACRO_TILE
)
332 *macrotiled
= R300_BUFFER_TILED
;
335 void radeon_drm_bufmgr_set_tiling(struct pb_buffer
*_buf
,
336 enum r300_buffer_tiling microtiled
,
337 enum r300_buffer_tiling macrotiled
,
340 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
342 if (microtiled
== R300_BUFFER_TILED
)
343 flags
|= RADEON_BO_FLAGS_MICRO_TILE
;
344 /* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */
345 #ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE
346 else if (microtiled
== R300_BUFFER_SQUARETILED
)
347 flags
|= RADEON_BO_FLAGS_MICRO_TILE_SQUARE
;
349 if (macrotiled
== R300_BUFFER_TILED
)
350 flags
|= RADEON_BO_FLAGS_MACRO_TILE
;
352 if (flags
!= buf
->tileflags
|| pitch
!= buf
->pitch
) {
353 /* Tiling determines how DRM treats the buffer data.
354 * We must flush CS when changing it if the buffer is referenced. */
355 if (radeon_bo_is_referenced_by_cs(buf
->bo
, buf
->mgr
->rws
->cs
)) {
356 buf
->mgr
->rws
->flush_cb(buf
->mgr
->rws
->flush_data
);
359 radeon_bo_set_tiling(buf
->bo
, flags
, pitch
);
363 boolean
radeon_drm_bufmgr_add_buffer(struct pb_buffer
*_buf
,
364 uint32_t rd
, uint32_t wd
)
366 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
367 radeon_cs_space_add_persistent_bo(buf
->mgr
->rws
->cs
, buf
->bo
,
372 void radeon_drm_bufmgr_write_reloc(struct pb_buffer
*_buf
,
373 uint32_t rd
, uint32_t wd
,
376 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
379 retval
= radeon_cs_write_reloc(buf
->mgr
->rws
->cs
,
380 buf
->bo
, rd
, wd
, flags
);
382 debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n",
387 boolean
radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer
*_buf
,
388 enum r300_reference_domain domain
)
390 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
393 if (domain
& R300_REF_CS
) {
394 if (radeon_bo_is_referenced_by_cs(buf
->bo
, buf
->mgr
->rws
->cs
)) {
399 if (domain
& R300_REF_HW
) {
400 if (radeon_bo_is_busy(buf
->bo
, &tmp
)) {
409 void radeon_drm_bufmgr_flush_maps(struct pb_manager
*_mgr
)
411 struct radeon_drm_bufmgr
*mgr
= radeon_drm_bufmgr(_mgr
);
412 struct radeon_drm_buffer
*rpb
, *t_rpb
;
414 foreach_s(rpb
, t_rpb
, &mgr
->buffer_map_list
) {
415 radeon_bo_unmap(rpb
->bo
);
417 remove_from_list(rpb
);
420 make_empty_list(&mgr
->buffer_map_list
);
423 void radeon_drm_bufmgr_wait(struct pb_buffer
*_buf
)
425 struct radeon_drm_buffer
*buf
= get_drm_buffer(_buf
);
427 radeon_bo_wait(buf
->bo
);