1 /**********************************************************
2 * Copyright 2009 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 * This file implements the SVGA interface into this winsys, defined
29 * in drivers/svga/svga_winsys.h.
31 * @author Keith Whitwell
32 * @author Jose Fonseca
37 #include "svga3d_caps.h"
39 #include "util/u_inlines.h"
40 #include "util/u_math.h"
41 #include "util/u_memory.h"
42 #include "pipebuffer/pb_buffer.h"
43 #include "pipebuffer/pb_bufmgr.h"
44 #include "svga_winsys.h"
45 #include "vmw_context.h"
46 #include "vmw_screen.h"
47 #include "vmw_surface.h"
48 #include "vmw_buffer.h"
49 #include "vmw_fence.h"
50 #include "vmw_shader.h"
51 #include "svga3d_surfacedefs.h"
54 * Try to get a surface backing buffer from the cache
55 * if it's this size or smaller.
57 #define VMW_TRY_CACHED_SIZE (2*1024*1024)
59 static struct svga_winsys_buffer
*
60 vmw_svga_winsys_buffer_create(struct svga_winsys_screen
*sws
,
65 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
66 struct vmw_buffer_desc desc
;
67 struct pb_manager
*provider
;
68 struct pb_buffer
*buffer
;
70 memset(&desc
, 0, sizeof desc
);
71 desc
.pb_desc
.alignment
= alignment
;
72 desc
.pb_desc
.usage
= usage
;
74 if (usage
== SVGA_BUFFER_USAGE_PINNED
) {
75 if (vws
->pools
.query_fenced
== NULL
&& !vmw_query_pools_init(vws
))
77 provider
= vws
->pools
.query_fenced
;
78 } else if (usage
== SVGA_BUFFER_USAGE_SHADER
) {
79 provider
= vws
->pools
.mob_shader_slab_fenced
;
81 provider
= vws
->pools
.gmr_fenced
;
84 buffer
= provider
->create_buffer(provider
, size
, &desc
.pb_desc
);
86 if(!buffer
&& provider
== vws
->pools
.gmr_fenced
) {
89 provider
= vws
->pools
.gmr_slab_fenced
;
90 buffer
= provider
->create_buffer(provider
, size
, &desc
.pb_desc
);
96 return vmw_svga_winsys_buffer_wrap(buffer
);
101 vmw_svga_winsys_fence_reference(struct svga_winsys_screen
*sws
,
102 struct pipe_fence_handle
**pdst
,
103 struct pipe_fence_handle
*src
)
105 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
107 vmw_fence_reference(vws
, pdst
, src
);
112 vmw_svga_winsys_fence_signalled(struct svga_winsys_screen
*sws
,
113 struct pipe_fence_handle
*fence
,
116 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
118 return vmw_fence_signalled(vws
, fence
, flag
);
123 vmw_svga_winsys_fence_finish(struct svga_winsys_screen
*sws
,
124 struct pipe_fence_handle
*fence
,
127 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
129 return vmw_fence_finish(vws
, fence
, flag
);
134 static struct svga_winsys_surface
*
135 vmw_svga_winsys_surface_create(struct svga_winsys_screen
*sws
,
136 SVGA3dSurfaceFlags flags
,
137 SVGA3dSurfaceFormat format
,
142 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
143 struct vmw_svga_winsys_surface
*surface
;
144 struct vmw_buffer_desc desc
;
145 struct pb_manager
*provider
= vws
->pools
.mob_fenced
;
146 uint32_t buffer_size
;
149 memset(&desc
, 0, sizeof(desc
));
150 surface
= CALLOC_STRUCT(vmw_svga_winsys_surface
);
154 pipe_reference_init(&surface
->refcnt
, 1);
155 p_atomic_set(&surface
->validated
, 0);
156 surface
->screen
= vws
;
157 pipe_mutex_init(surface
->mutex
);
160 * Used for the backing buffer GB surfaces, and to approximate
161 * when to flush on non-GB hosts.
163 buffer_size
= svga3dsurface_get_serialized_size(format
, size
, numMipLevels
, (numFaces
== 6));
164 if (sws
->have_gb_objects
) {
165 SVGAGuestPtr ptr
= {0,0};
168 * If the backing buffer size is small enough, try to allocate a
169 * buffer out of the buffer cache. Otherwise, let the kernel allocate
170 * a suitable buffer for us.
172 if (buffer_size
< VMW_TRY_CACHED_SIZE
) {
173 struct pb_buffer
*pb_buf
;
175 surface
->size
= buffer_size
;
176 desc
.pb_desc
.alignment
= 4096;
177 desc
.pb_desc
.usage
= 0;
178 pb_buf
= provider
->create_buffer(provider
, buffer_size
, &desc
.pb_desc
);
179 surface
->buf
= vmw_svga_winsys_buffer_wrap(pb_buf
);
180 if (surface
->buf
&& !vmw_gmr_bufmgr_region_ptr(pb_buf
, &ptr
))
184 surface
->sid
= vmw_ioctl_gb_surface_create(vws
,
186 numFaces
, numMipLevels
,
188 surface
->buf
? NULL
:
191 if (surface
->sid
== SVGA3D_INVALID_ID
&& surface
->buf
) {
194 * Kernel refused to allocate a surface for us.
195 * Perhaps something was wrong with our buffer?
196 * This is really a guard against future new size requirements
197 * on the backing buffers.
199 vmw_svga_winsys_buffer_destroy(sws
, surface
->buf
);
201 surface
->sid
= vmw_ioctl_gb_surface_create(vws
,
203 numFaces
, numMipLevels
,
206 if (surface
->sid
== SVGA3D_INVALID_ID
)
211 * If the kernel created the buffer for us, wrap it into a
212 * vmw_svga_winsys_buffer.
214 if (surface
->buf
== NULL
) {
215 struct pb_buffer
*pb_buf
;
217 surface
->size
= vmw_region_size(desc
.region
);
218 desc
.pb_desc
.alignment
= 4096;
219 desc
.pb_desc
.usage
= VMW_BUFFER_USAGE_SHARED
;
220 pb_buf
= provider
->create_buffer(provider
, surface
->size
,
222 surface
->buf
= vmw_svga_winsys_buffer_wrap(pb_buf
);
223 if (surface
->buf
== NULL
) {
224 vmw_ioctl_region_destroy(desc
.region
);
225 vmw_ioctl_surface_destroy(vws
, surface
->sid
);
230 surface
->sid
= vmw_ioctl_surface_create(vws
,
232 numFaces
, numMipLevels
);
233 if(surface
->sid
== SVGA3D_INVALID_ID
)
236 /* Best estimate for surface size, used for early flushing. */
237 surface
->size
= buffer_size
;
241 return svga_winsys_surface(surface
);
245 vmw_svga_winsys_buffer_destroy(sws
, surface
->buf
);
254 vmw_svga_winsys_surface_is_flushed(struct svga_winsys_screen
*sws
,
255 struct svga_winsys_surface
*surface
)
257 struct vmw_svga_winsys_surface
*vsurf
= vmw_svga_winsys_surface(surface
);
258 return (p_atomic_read(&vsurf
->validated
) == 0);
263 vmw_svga_winsys_surface_ref(struct svga_winsys_screen
*sws
,
264 struct svga_winsys_surface
**pDst
,
265 struct svga_winsys_surface
*src
)
267 struct vmw_svga_winsys_surface
*d_vsurf
= vmw_svga_winsys_surface(*pDst
);
268 struct vmw_svga_winsys_surface
*s_vsurf
= vmw_svga_winsys_surface(src
);
270 vmw_svga_winsys_surface_reference(&d_vsurf
, s_vsurf
);
271 *pDst
= svga_winsys_surface(d_vsurf
);
276 vmw_svga_winsys_destroy(struct svga_winsys_screen
*sws
)
278 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
280 vmw_winsys_destroy(vws
);
284 static SVGA3dHardwareVersion
285 vmw_svga_winsys_get_hw_version(struct svga_winsys_screen
*sws
)
287 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
289 if (sws
->have_gb_objects
)
290 return SVGA3D_HWVERSION_WS8_B1
;
292 return (SVGA3dHardwareVersion
) vws
->ioctl
.hwversion
;
297 vmw_svga_winsys_get_cap(struct svga_winsys_screen
*sws
,
298 SVGA3dDevCapIndex index
,
299 SVGA3dDevCapResult
*result
)
301 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
303 if (index
> vws
->ioctl
.num_cap_3d
|| !vws
->ioctl
.cap_3d
[index
].has_cap
)
306 *result
= vws
->ioctl
.cap_3d
[index
].result
;
310 static struct svga_winsys_gb_shader
*
311 vmw_svga_winsys_shader_create(struct svga_winsys_screen
*sws
,
312 SVGA3dShaderType type
,
313 const uint32
*bytecode
,
316 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
317 struct vmw_svga_winsys_shader
*shader
;
320 shader
= CALLOC_STRUCT(vmw_svga_winsys_shader
);
324 pipe_reference_init(&shader
->refcnt
, 1);
325 p_atomic_set(&shader
->validated
, 0);
326 shader
->screen
= vws
;
327 shader
->buf
= vmw_svga_winsys_buffer_create(sws
, 64,
328 SVGA_BUFFER_USAGE_SHADER
,
333 code
= vmw_svga_winsys_buffer_map(sws
, shader
->buf
, PIPE_TRANSFER_WRITE
);
337 memcpy(code
, bytecode
, bytecodeLen
);
338 vmw_svga_winsys_buffer_unmap(sws
, shader
->buf
);
340 shader
->shid
= vmw_ioctl_shader_create(vws
, type
, bytecodeLen
);
341 if(shader
->shid
== SVGA3D_INVALID_ID
)
344 return svga_winsys_shader(shader
);
347 vmw_svga_winsys_buffer_destroy(sws
, shader
->buf
);
355 vmw_svga_winsys_shader_destroy(struct svga_winsys_screen
*sws
,
356 struct svga_winsys_gb_shader
*shader
)
358 struct vmw_svga_winsys_shader
*d_shader
=
359 vmw_svga_winsys_shader(shader
);
361 vmw_svga_winsys_shader_reference(&d_shader
, NULL
);
365 vmw_winsys_screen_init_svga(struct vmw_winsys_screen
*vws
)
367 vws
->base
.destroy
= vmw_svga_winsys_destroy
;
368 vws
->base
.get_hw_version
= vmw_svga_winsys_get_hw_version
;
369 vws
->base
.get_cap
= vmw_svga_winsys_get_cap
;
370 vws
->base
.context_create
= vmw_svga_winsys_context_create
;
371 vws
->base
.surface_create
= vmw_svga_winsys_surface_create
;
372 vws
->base
.surface_is_flushed
= vmw_svga_winsys_surface_is_flushed
;
373 vws
->base
.surface_reference
= vmw_svga_winsys_surface_ref
;
374 vws
->base
.buffer_create
= vmw_svga_winsys_buffer_create
;
375 vws
->base
.buffer_map
= vmw_svga_winsys_buffer_map
;
376 vws
->base
.buffer_unmap
= vmw_svga_winsys_buffer_unmap
;
377 vws
->base
.buffer_destroy
= vmw_svga_winsys_buffer_destroy
;
378 vws
->base
.fence_reference
= vmw_svga_winsys_fence_reference
;
379 vws
->base
.fence_signalled
= vmw_svga_winsys_fence_signalled
;
380 vws
->base
.shader_create
= vmw_svga_winsys_shader_create
;
381 vws
->base
.shader_destroy
= vmw_svga_winsys_shader_destroy
;
382 vws
->base
.fence_finish
= vmw_svga_winsys_fence_finish
;