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_WRITE
| PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
;
49 struct pb_manager
*provider
;
52 mtx_lock(&vsrf
->mutex
);
53 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vsrf
->buf
, 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
);
69 vmw_svga_winsys_buffer_destroy(&vws
->base
, vsrf
->buf
);
73 vmw_svga_winsys_buffer_destroy(&vws
->base
, vbuf
);
78 /* Cannot create a buffer, just unlock */
83 mtx_unlock(&vsrf
->mutex
);
86 if (flags
& SVGA3D_SURFACE_BIND_STREAM_OUTPUT
) {
87 memset(data
, 0, surf_size
+ sizeof(SVGA3dDXSOState
));
90 memset(data
, 0, surf_size
);
94 mtx_lock(&vsrf
->mutex
);
95 vmw_svga_winsys_buffer_unmap(&vsrf
->screen
->base
, vsrf
->buf
);
97 mtx_unlock(&vsrf
->mutex
);
103 vmw_svga_winsys_surface_map(struct svga_winsys_context
*swc
,
104 struct svga_winsys_surface
*srf
,
105 unsigned flags
, boolean
*retry
,
108 struct vmw_svga_winsys_surface
*vsrf
= vmw_svga_winsys_surface(srf
);
110 struct pb_buffer
*pb_buf
;
112 struct vmw_winsys_screen
*vws
= vsrf
->screen
;
116 assert((flags
& (PIPE_TRANSFER_READ
| PIPE_TRANSFER_WRITE
)) != 0);
117 mtx_lock(&vsrf
->mutex
);
119 if (vsrf
->mapcount
) {
120 /* Other mappers will get confused if we discard. */
121 flags
&= ~PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
;
124 vsrf
->rebind
= FALSE
;
127 * If we intend to read, there's no point discarding the
130 if (flags
& PIPE_TRANSFER_READ
|| vsrf
->shared
)
131 flags
&= ~PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
;
134 * Discard is a hint to a synchronized map.
136 if (flags
& PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
)
137 flags
&= ~PIPE_TRANSFER_UNSYNCHRONIZED
;
140 * The surface is allowed to be referenced on the command stream iff
141 * we're mapping unsynchronized or discard. This is an early check.
142 * We need to recheck after a failing discard map.
144 if (!(flags
& (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
|
145 PIPE_TRANSFER_UNSYNCHRONIZED
)) &&
146 p_atomic_read(&vsrf
->validated
)) {
151 pb_flags
= flags
& (PIPE_TRANSFER_READ_WRITE
| PIPE_TRANSFER_UNSYNCHRONIZED
|
152 PIPE_TRANSFER_PERSISTENT
);
154 if (flags
& PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
) {
155 struct pb_manager
*provider
;
159 * First, if possible, try to map existing storage with DONTBLOCK.
161 if (!p_atomic_read(&vsrf
->validated
)) {
162 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vsrf
->buf
,
163 PIPE_TRANSFER_DONTBLOCK
| pb_flags
);
169 * Attempt to get a new buffer.
171 provider
= vws
->pools
.mob_fenced
;
172 memset(&desc
, 0, sizeof(desc
));
173 desc
.alignment
= 4096;
174 pb_buf
= provider
->create_buffer(provider
, vsrf
->size
, &desc
);
175 if (pb_buf
!= NULL
) {
176 struct svga_winsys_buffer
*vbuf
=
177 vmw_svga_winsys_buffer_wrap(pb_buf
);
179 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vbuf
, pb_flags
);
183 * We've discarded data on this surface and thus
184 * it's data is no longer consider referenced.
186 vmw_swc_surface_clear_reference(swc
, vsrf
);
188 vmw_svga_winsys_buffer_destroy(&vws
->base
, vsrf
->buf
);
191 /* Rebind persistent maps immediately */
192 if (flags
& PIPE_TRANSFER_PERSISTENT
) {
194 vsrf
->rebind
= FALSE
;
198 vmw_svga_winsys_buffer_destroy(&vws
->base
, vbuf
);
201 * We couldn't get and map a new buffer for some reason.
202 * Fall through to an ordinary map.
203 * But tell pipe driver to flush now if already on validate list,
204 * Otherwise we'll overwrite previous contents.
206 if (!(flags
& PIPE_TRANSFER_UNSYNCHRONIZED
) &&
207 p_atomic_read(&vsrf
->validated
)) {
213 pb_flags
|= (flags
& PIPE_TRANSFER_DONTBLOCK
);
214 data
= vmw_svga_winsys_buffer_map(&vws
->base
, vsrf
->buf
, pb_flags
);
221 vsrf
->map_mode
= flags
& (PIPE_TRANSFER_READ
| PIPE_TRANSFER_WRITE
);
223 mtx_unlock(&vsrf
->mutex
);
229 vmw_svga_winsys_surface_unmap(struct svga_winsys_context
*swc
,
230 struct svga_winsys_surface
*srf
,
233 struct vmw_svga_winsys_surface
*vsrf
= vmw_svga_winsys_surface(srf
);
234 mtx_lock(&vsrf
->mutex
);
235 if (--vsrf
->mapcount
== 0) {
236 *rebind
= vsrf
->rebind
;
237 vsrf
->rebind
= FALSE
;
241 vmw_svga_winsys_buffer_unmap(&vsrf
->screen
->base
, vsrf
->buf
);
242 mtx_unlock(&vsrf
->mutex
);
246 vmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface
**pdst
,
247 struct vmw_svga_winsys_surface
*src
)
249 struct pipe_reference
*src_ref
;
250 struct pipe_reference
*dst_ref
;
251 struct vmw_svga_winsys_surface
*dst
;
253 if(pdst
== NULL
|| *pdst
== src
)
258 src_ref
= src
? &src
->refcnt
: NULL
;
259 dst_ref
= dst
? &dst
->refcnt
: NULL
;
261 if (pipe_reference(dst_ref
, src_ref
)) {
263 vmw_svga_winsys_buffer_destroy(&dst
->screen
->base
, dst
->buf
);
264 vmw_ioctl_surface_destroy(dst
->screen
, dst
->sid
);
266 /* to detect dangling pointers */
267 assert(p_atomic_read(&dst
->validated
) == 0);
268 dst
->sid
= SVGA3D_INVALID_ID
;
270 mtx_destroy(&dst
->mutex
);