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 #include "util/u_debug.h"
29 #include "util/u_memory.h"
30 #include "pipe/p_defines.h"
31 #include "vmw_surface.h"
32 #include "vmw_screen.h"
33 #include "vmw_buffer.h"
34 #include "vmw_context.h"
35 #include "pipebuffer/pb_bufmgr.h"
38 vmw_svga_winsys_surface_init(struct svga_winsys_screen
*sws
,
39 struct svga_winsys_surface
*srf
,
40 unsigned surf_size
, SVGA3dSurfaceAllFlags flags
)
42 struct vmw_svga_winsys_surface
*vsrf
= vmw_svga_winsys_surface(srf
);
44 struct pb_buffer
*pb_buf
;
46 struct vmw_winsys_screen
*vws
= vsrf
->screen
;
47 pb_flags
= PIPE_TRANSFER_READ_WRITE
| PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
;
49 struct pb_manager
*provider
;
52 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vsrf
->buf
,
53 PIPE_TRANSFER_DONTBLOCK
| pb_flags
);
57 provider
= vws
->pools
.mob_fenced
;
58 memset(&desc
, 0, sizeof(desc
));
59 desc
.alignment
= 4096;
60 pb_buf
= provider
->create_buffer(provider
, vsrf
->size
, &desc
);
62 struct svga_winsys_buffer
*vbuf
=
63 vmw_svga_winsys_buffer_wrap(pb_buf
);
65 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vbuf
, pb_flags
);
68 vmw_svga_winsys_buffer_destroy(&vws
->base
, vsrf
->buf
);
72 vmw_svga_winsys_buffer_destroy(&vws
->base
, vbuf
);
76 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vsrf
->buf
, pb_flags
);
81 mtx_unlock(&vsrf
->mutex
);
85 if (flags
& SVGA3D_SURFACE_BIND_STREAM_OUTPUT
) {
86 memset(data
, 0, surf_size
+ sizeof(SVGA3dDXSOState
));
89 memset(data
, 0, surf_size
);
92 mtx_lock(&vsrf
->mutex
);
93 vmw_svga_winsys_buffer_unmap(&vsrf
->screen
->base
, vsrf
->buf
);
94 mtx_unlock(&vsrf
->mutex
);
100 vmw_svga_winsys_surface_map(struct svga_winsys_context
*swc
,
101 struct svga_winsys_surface
*srf
,
102 unsigned flags
, boolean
*retry
,
105 struct vmw_svga_winsys_surface
*vsrf
= vmw_svga_winsys_surface(srf
);
107 struct pb_buffer
*pb_buf
;
109 struct vmw_winsys_screen
*vws
= vsrf
->screen
;
113 assert((flags
& (PIPE_TRANSFER_READ
| PIPE_TRANSFER_WRITE
)) != 0);
114 mtx_lock(&vsrf
->mutex
);
116 if (vsrf
->mapcount
) {
117 /* Other mappers will get confused if we discard. */
118 flags
&= ~PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
;
121 vsrf
->rebind
= FALSE
;
124 * If we intend to read, there's no point discarding the
127 if (flags
& PIPE_TRANSFER_READ
|| vsrf
->shared
)
128 flags
&= ~PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
;
131 * Discard is a hint to a synchronized map.
133 if (flags
& PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
)
134 flags
&= ~PIPE_TRANSFER_UNSYNCHRONIZED
;
137 * The surface is allowed to be referenced on the command stream iff
138 * we're mapping unsynchronized or discard. This is an early check.
139 * We need to recheck after a failing discard map.
141 if (!(flags
& (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
|
142 PIPE_TRANSFER_UNSYNCHRONIZED
)) &&
143 p_atomic_read(&vsrf
->validated
)) {
148 pb_flags
= flags
& (PIPE_TRANSFER_READ_WRITE
| PIPE_TRANSFER_UNSYNCHRONIZED
|
149 PIPE_TRANSFER_PERSISTENT
);
151 if (flags
& PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
) {
152 struct pb_manager
*provider
;
156 * First, if possible, try to map existing storage with DONTBLOCK.
158 if (!p_atomic_read(&vsrf
->validated
)) {
159 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vsrf
->buf
,
160 PIPE_TRANSFER_DONTBLOCK
| pb_flags
);
166 * Attempt to get a new buffer.
168 provider
= vws
->pools
.mob_fenced
;
169 memset(&desc
, 0, sizeof(desc
));
170 desc
.alignment
= 4096;
171 pb_buf
= provider
->create_buffer(provider
, vsrf
->size
, &desc
);
172 if (pb_buf
!= NULL
) {
173 struct svga_winsys_buffer
*vbuf
=
174 vmw_svga_winsys_buffer_wrap(pb_buf
);
176 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vbuf
, pb_flags
);
180 * We've discarded data on this surface and thus
181 * it's data is no longer consider referenced.
183 vmw_swc_surface_clear_reference(swc
, vsrf
);
185 vmw_svga_winsys_buffer_destroy(&vws
->base
, vsrf
->buf
);
188 /* Rebind persistent maps immediately */
189 if (flags
& PIPE_TRANSFER_PERSISTENT
) {
191 vsrf
->rebind
= FALSE
;
195 vmw_svga_winsys_buffer_destroy(&vws
->base
, vbuf
);
198 * We couldn't get and map a new buffer for some reason.
199 * Fall through to an ordinary map.
200 * But tell pipe driver to flush now if already on validate list,
201 * Otherwise we'll overwrite previous contents.
203 if (!(flags
& PIPE_TRANSFER_UNSYNCHRONIZED
) &&
204 p_atomic_read(&vsrf
->validated
)) {
210 pb_flags
|= (flags
& PIPE_TRANSFER_DONTBLOCK
);
211 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vsrf
->buf
, pb_flags
);
218 vsrf
->map_mode
= flags
& (PIPE_TRANSFER_READ
| PIPE_TRANSFER_WRITE
);
220 mtx_unlock(&vsrf
->mutex
);
226 vmw_svga_winsys_surface_unmap(struct svga_winsys_context
*swc
,
227 struct svga_winsys_surface
*srf
,
230 struct vmw_svga_winsys_surface
*vsrf
= vmw_svga_winsys_surface(srf
);
231 mtx_lock(&vsrf
->mutex
);
232 if (--vsrf
->mapcount
== 0) {
233 *rebind
= vsrf
->rebind
;
234 vsrf
->rebind
= FALSE
;
238 vmw_svga_winsys_buffer_unmap(&vsrf
->screen
->base
, vsrf
->buf
);
239 mtx_unlock(&vsrf
->mutex
);
243 vmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface
**pdst
,
244 struct vmw_svga_winsys_surface
*src
)
246 struct pipe_reference
*src_ref
;
247 struct pipe_reference
*dst_ref
;
248 struct vmw_svga_winsys_surface
*dst
;
250 if(pdst
== NULL
|| *pdst
== src
)
255 src_ref
= src
? &src
->refcnt
: NULL
;
256 dst_ref
= dst
? &dst
->refcnt
: NULL
;
258 if (pipe_reference(dst_ref
, src_ref
)) {
260 vmw_svga_winsys_buffer_destroy(&dst
->screen
->base
, dst
->buf
);
261 vmw_ioctl_surface_destroy(dst
->screen
, dst
->sid
);
263 /* to detect dangling pointers */
264 assert(p_atomic_read(&dst
->validated
) == 0);
265 dst
->sid
= SVGA3D_INVALID_ID
;
267 mtx_destroy(&dst
->mutex
);