2 * Copyright 2010 Dave Airlie
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include <util/u_inlines.h>
27 #include <util/u_memory.h>
28 #include <util/u_double_list.h>
29 #include <pipebuffer/pb_buffer.h>
30 #include <pipebuffer/pb_bufmgr.h>
31 #include "r600_priv.h"
37 struct radeon_bo_pbmgr
*mgr
;
38 struct list_head maplist
;
41 extern const struct pb_vtbl radeon_bo_pb_vtbl
;
43 static INLINE
struct radeon_bo_pb
*radeon_bo_pb(struct pb_buffer
*buf
)
46 assert(buf
->vtbl
== &radeon_bo_pb_vtbl
);
47 return (struct radeon_bo_pb
*)buf
;
50 struct radeon_bo_pbmgr
{
52 struct radeon
*radeon
;
53 struct list_head buffer_map_list
;
56 static INLINE
struct radeon_bo_pbmgr
*radeon_bo_pbmgr(struct pb_manager
*mgr
)
59 return (struct radeon_bo_pbmgr
*)mgr
;
62 static void radeon_bo_pb_destroy(struct pb_buffer
*_buf
)
64 struct radeon_bo_pb
*buf
= radeon_bo_pb(_buf
);
66 /* If this buffer is on the list of buffers to unmap,
67 * do the unmapping now.
69 if (!LIST_IS_EMPTY(&buf
->maplist
))
70 radeon_bo_unmap(buf
->mgr
->radeon
, buf
->bo
);
72 LIST_DEL(&buf
->maplist
);
73 radeon_bo_reference(buf
->mgr
->radeon
, &buf
->bo
, NULL
);
78 radeon_bo_pb_map_internal(struct pb_buffer
*_buf
,
79 unsigned flags
, void *ctx
)
81 struct radeon_bo_pb
*buf
= radeon_bo_pb(_buf
);
82 struct pipe_context
*pctx
= ctx
;
84 if (flags
& PB_USAGE_UNSYNCHRONIZED
) {
85 if (radeon_bo_map(buf
->mgr
->radeon
, buf
->bo
)) {
88 LIST_DELINIT(&buf
->maplist
);
92 if (p_atomic_read(&buf
->bo
->reference
.count
) > 1) {
93 if (flags
& PB_USAGE_DONTBLOCK
) {
97 pctx
->flush(pctx
, 0, NULL
);
101 if (flags
& PB_USAGE_DONTBLOCK
) {
103 if (radeon_bo_busy(buf
->mgr
->radeon
, buf
->bo
, &domain
))
105 if (radeon_bo_map(buf
->mgr
->radeon
, buf
->bo
)) {
111 if (radeon_bo_map(buf
->mgr
->radeon
, buf
->bo
)) {
114 if (radeon_bo_wait(buf
->mgr
->radeon
, buf
->bo
)) {
115 radeon_bo_unmap(buf
->mgr
->radeon
, buf
->bo
);
119 LIST_DELINIT(&buf
->maplist
);
120 return buf
->bo
->data
;
123 static void radeon_bo_pb_unmap_internal(struct pb_buffer
*_buf
)
125 struct radeon_bo_pb
*buf
= radeon_bo_pb(_buf
);
126 LIST_ADDTAIL(&buf
->maplist
, &buf
->mgr
->buffer_map_list
);
130 radeon_bo_pb_get_base_buffer(struct pb_buffer
*buf
,
131 struct pb_buffer
**base_buf
,
138 static enum pipe_error
139 radeon_bo_pb_validate(struct pb_buffer
*_buf
,
140 struct pb_validate
*vl
,
148 radeon_bo_pb_fence(struct pb_buffer
*buf
,
149 struct pipe_fence_handle
*fence
)
153 const struct pb_vtbl radeon_bo_pb_vtbl
= {
154 radeon_bo_pb_destroy
,
155 radeon_bo_pb_map_internal
,
156 radeon_bo_pb_unmap_internal
,
157 radeon_bo_pb_validate
,
159 radeon_bo_pb_get_base_buffer
,
163 radeon_bo_pb_create_buffer_from_handle(struct pb_manager
*_mgr
,
166 struct radeon_bo_pbmgr
*mgr
= radeon_bo_pbmgr(_mgr
);
167 struct radeon
*radeon
= mgr
->radeon
;
168 struct radeon_bo_pb
*bo
;
169 struct radeon_bo
*hw_bo
;
171 hw_bo
= radeon_bo(radeon
, handle
, 0, 0);
175 bo
= CALLOC_STRUCT(radeon_bo_pb
);
177 radeon_bo_reference(radeon
, &hw_bo
, NULL
);
181 LIST_INITHEAD(&bo
->maplist
);
182 pipe_reference_init(&bo
->b
.base
.reference
, 1);
183 bo
->b
.base
.alignment
= 0;
184 bo
->b
.base
.usage
= PB_USAGE_GPU_WRITE
| PB_USAGE_GPU_READ
;
185 bo
->b
.base
.size
= hw_bo
->size
;
186 bo
->b
.vtbl
= &radeon_bo_pb_vtbl
;
194 static struct pb_buffer
*
195 radeon_bo_pb_create_buffer(struct pb_manager
*_mgr
,
197 const struct pb_desc
*desc
)
199 struct radeon_bo_pbmgr
*mgr
= radeon_bo_pbmgr(_mgr
);
200 struct radeon
*radeon
= mgr
->radeon
;
201 struct radeon_bo_pb
*bo
;
203 bo
= CALLOC_STRUCT(radeon_bo_pb
);
207 pipe_reference_init(&bo
->b
.base
.reference
, 1);
208 bo
->b
.base
.alignment
= desc
->alignment
;
209 bo
->b
.base
.usage
= desc
->usage
;
210 bo
->b
.base
.size
= size
;
211 bo
->b
.vtbl
= &radeon_bo_pb_vtbl
;
214 LIST_INITHEAD(&bo
->maplist
);
216 bo
->bo
= radeon_bo(radeon
, 0, size
, desc
->alignment
);
228 radeon_bo_pbmgr_flush(struct pb_manager
*mgr
)
234 radeon_bo_pbmgr_destroy(struct pb_manager
*_mgr
)
236 struct radeon_bo_pbmgr
*mgr
= radeon_bo_pbmgr(_mgr
);
240 struct pb_manager
*radeon_bo_pbmgr_create(struct radeon
*radeon
)
242 struct radeon_bo_pbmgr
*mgr
;
244 mgr
= CALLOC_STRUCT(radeon_bo_pbmgr
);
248 mgr
->b
.destroy
= radeon_bo_pbmgr_destroy
;
249 mgr
->b
.create_buffer
= radeon_bo_pb_create_buffer
;
250 mgr
->b
.flush
= radeon_bo_pbmgr_flush
;
252 mgr
->radeon
= radeon
;
253 LIST_INITHEAD(&mgr
->buffer_map_list
);
257 void radeon_bo_pbmgr_flush_maps(struct pb_manager
*_mgr
)
259 struct radeon_bo_pbmgr
*mgr
= radeon_bo_pbmgr(_mgr
);
260 struct radeon_bo_pb
*rpb
= NULL
;
261 struct radeon_bo_pb
*t_rpb
;
263 LIST_FOR_EACH_ENTRY_SAFE(rpb
, t_rpb
, &mgr
->buffer_map_list
, maplist
) {
264 radeon_bo_unmap(mgr
->radeon
, rpb
->bo
);
265 LIST_DELINIT(&rpb
->maplist
);
268 LIST_INITHEAD(&mgr
->buffer_map_list
);
271 struct radeon_bo
*radeon_bo_pb_get_bo(struct pb_buffer
*_buf
)
273 struct radeon_bo_pb
*buf
;
274 if (_buf
->vtbl
== &radeon_bo_pb_vtbl
) {
275 buf
= radeon_bo_pb(_buf
);
278 struct pb_buffer
*base_buf
;
280 pb_get_base_buffer(_buf
, &base_buf
, &offset
);
281 if (base_buf
->vtbl
== &radeon_bo_pb_vtbl
) {
282 buf
= radeon_bo_pb(base_buf
);