1 /**********************************************************
2 * Copyright 2009-2015 VMware, Inc. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 **********************************************************/
28 * SVGA buffer manager for Guest Memory Regions (GMRs).
30 * GMRs are used for pixel and vertex data upload/download to/from the virtual
31 * SVGA hardware. There is a limited number of GMRs available, and
32 * creating/destroying them is also a slow operation so we must suballocate
35 * This file implements a pipebuffer library's buffer manager, so that we can
36 * use pipepbuffer's suballocation, fencing, and debugging facilities with GMRs.
38 * @author Jose Fonseca <jfonseca@vmware.com>
44 #include "util/u_inlines.h"
45 #include "util/u_memory.h"
46 #include "pipebuffer/pb_buffer.h"
47 #include "pipebuffer/pb_bufmgr.h"
49 #include "svga_winsys.h"
51 #include "vmw_screen.h"
52 #include "vmw_buffer.h"
54 struct vmw_gmr_bufmgr
;
59 struct pb_buffer base
;
61 struct vmw_gmr_bufmgr
*mgr
;
63 struct vmw_region
*region
;
69 extern const struct pb_vtbl vmw_gmr_buffer_vtbl
;
72 static inline struct vmw_gmr_buffer
*
73 vmw_gmr_buffer(struct pb_buffer
*buf
)
76 assert(buf
->vtbl
== &vmw_gmr_buffer_vtbl
);
77 return (struct vmw_gmr_buffer
*)buf
;
83 struct pb_manager base
;
85 struct vmw_winsys_screen
*vws
;
89 static inline struct vmw_gmr_bufmgr
*
90 vmw_gmr_bufmgr(struct pb_manager
*mgr
)
93 return (struct vmw_gmr_bufmgr
*)mgr
;
98 vmw_gmr_buffer_destroy(struct pb_buffer
*_buf
)
100 struct vmw_gmr_buffer
*buf
= vmw_gmr_buffer(_buf
);
102 vmw_ioctl_region_unmap(buf
->region
);
104 vmw_ioctl_region_destroy(buf
->region
);
111 vmw_gmr_buffer_map(struct pb_buffer
*_buf
,
115 struct vmw_gmr_buffer
*buf
= vmw_gmr_buffer(_buf
);
119 buf
->map
= vmw_ioctl_region_map(buf
->region
);
125 if ((_buf
->usage
& VMW_BUFFER_USAGE_SYNC
) &&
126 !(flags
& PB_USAGE_UNSYNCHRONIZED
)) {
127 ret
= vmw_ioctl_syncforcpu(buf
->region
,
128 !!(flags
& PB_USAGE_DONTBLOCK
),
129 !(flags
& PB_USAGE_CPU_WRITE
),
140 vmw_gmr_buffer_unmap(struct pb_buffer
*_buf
)
142 struct vmw_gmr_buffer
*buf
= vmw_gmr_buffer(_buf
);
143 unsigned flags
= buf
->map_flags
;
145 if ((_buf
->usage
& VMW_BUFFER_USAGE_SYNC
) &&
146 !(flags
& PB_USAGE_UNSYNCHRONIZED
)) {
147 vmw_ioctl_releasefromcpu(buf
->region
,
148 !(flags
& PB_USAGE_CPU_WRITE
),
155 vmw_gmr_buffer_get_base_buffer(struct pb_buffer
*buf
,
156 struct pb_buffer
**base_buf
,
164 static enum pipe_error
165 vmw_gmr_buffer_validate( struct pb_buffer
*_buf
,
166 struct pb_validate
*vl
,
175 vmw_gmr_buffer_fence( struct pb_buffer
*_buf
,
176 struct pipe_fence_handle
*fence
)
178 /* We don't need to do anything, as the pipebuffer library
179 * will take care of delaying the destruction of fenced buffers */
183 const struct pb_vtbl vmw_gmr_buffer_vtbl
= {
184 vmw_gmr_buffer_destroy
,
186 vmw_gmr_buffer_unmap
,
187 vmw_gmr_buffer_validate
,
188 vmw_gmr_buffer_fence
,
189 vmw_gmr_buffer_get_base_buffer
193 static struct pb_buffer
*
194 vmw_gmr_bufmgr_create_buffer(struct pb_manager
*_mgr
,
196 const struct pb_desc
*pb_desc
)
198 struct vmw_gmr_bufmgr
*mgr
= vmw_gmr_bufmgr(_mgr
);
199 struct vmw_winsys_screen
*vws
= mgr
->vws
;
200 struct vmw_gmr_buffer
*buf
;
201 const struct vmw_buffer_desc
*desc
=
202 (const struct vmw_buffer_desc
*) pb_desc
;
204 buf
= CALLOC_STRUCT(vmw_gmr_buffer
);
208 pipe_reference_init(&buf
->base
.reference
, 1);
209 buf
->base
.alignment
= pb_desc
->alignment
;
210 buf
->base
.usage
= pb_desc
->usage
& ~VMW_BUFFER_USAGE_SHARED
;
211 buf
->base
.vtbl
= &vmw_gmr_buffer_vtbl
;
213 buf
->base
.size
= size
;
214 if ((pb_desc
->usage
& VMW_BUFFER_USAGE_SHARED
) && desc
->region
) {
215 buf
->region
= desc
->region
;
217 buf
->region
= vmw_ioctl_region_create(vws
, size
);
231 vmw_gmr_bufmgr_flush(struct pb_manager
*mgr
)
238 vmw_gmr_bufmgr_destroy(struct pb_manager
*_mgr
)
240 struct vmw_gmr_bufmgr
*mgr
= vmw_gmr_bufmgr(_mgr
);
246 vmw_gmr_bufmgr_create(struct vmw_winsys_screen
*vws
)
248 struct vmw_gmr_bufmgr
*mgr
;
250 mgr
= CALLOC_STRUCT(vmw_gmr_bufmgr
);
254 mgr
->base
.destroy
= vmw_gmr_bufmgr_destroy
;
255 mgr
->base
.create_buffer
= vmw_gmr_bufmgr_create_buffer
;
256 mgr
->base
.flush
= vmw_gmr_bufmgr_flush
;
265 vmw_gmr_bufmgr_region_ptr(struct pb_buffer
*buf
,
266 struct SVGAGuestPtr
*ptr
)
268 struct pb_buffer
*base_buf
;
270 struct vmw_gmr_buffer
*gmr_buf
;
272 pb_get_base_buffer( buf
, &base_buf
, &offset
);
274 gmr_buf
= vmw_gmr_buffer(base_buf
);
278 *ptr
= vmw_ioctl_region_ptr(gmr_buf
->region
);
280 ptr
->offset
+= offset
;
286 struct svga_winsys_buffer
{
287 struct pb_buffer
*pb_buf
;
288 struct debug_flush_buf
*fbuf
;
292 vmw_pb_buffer(struct svga_winsys_buffer
*buffer
)
295 return buffer
->pb_buf
;
298 struct svga_winsys_buffer
*
299 vmw_svga_winsys_buffer_wrap(struct pb_buffer
*buffer
)
301 struct svga_winsys_buffer
*buf
;
306 buf
= CALLOC_STRUCT(svga_winsys_buffer
);
308 pb_reference(&buffer
, NULL
);
312 buf
->pb_buf
= buffer
;
313 buf
->fbuf
= debug_flush_buf_create(TRUE
, VMW_DEBUG_FLUSH_STACK
);
317 struct debug_flush_buf
*
318 vmw_debug_flush_buf(struct svga_winsys_buffer
*buffer
)
326 vmw_svga_winsys_buffer_destroy(struct svga_winsys_screen
*sws
,
327 struct svga_winsys_buffer
*buf
)
329 struct pb_buffer
*pbuf
= vmw_pb_buffer(buf
);
331 pb_reference(&pbuf
, NULL
);
333 debug_flush_buf_reference(&buf
->fbuf
, NULL
);
339 vmw_svga_winsys_buffer_map(struct svga_winsys_screen
*sws
,
340 struct svga_winsys_buffer
*buf
,
346 if (flags
& PIPE_TRANSFER_UNSYNCHRONIZED
)
347 flags
&= ~PIPE_TRANSFER_DONTBLOCK
;
349 map
= pb_map(vmw_pb_buffer(buf
), flags
, NULL
);
353 debug_flush_map(buf
->fbuf
, flags
);
361 vmw_svga_winsys_buffer_unmap(struct svga_winsys_screen
*sws
,
362 struct svga_winsys_buffer
*buf
)
367 debug_flush_unmap(buf
->fbuf
);
370 pb_unmap(vmw_pb_buffer(buf
));