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 **********************************************************/
29 #include "util/u_debug.h"
30 #include "util/u_memory.h"
31 #include "util/u_debug_stack.h"
32 #include "pipebuffer/pb_buffer.h"
33 #include "pipebuffer/pb_validate.h"
35 #include "svga_winsys.h"
36 #include "vmw_context.h"
37 #include "vmw_screen.h"
38 #include "vmw_buffer.h"
39 #include "vmw_surface.h"
40 #include "vmw_fence.h"
42 #define VMW_COMMAND_SIZE (64*1024)
43 #define VMW_SURFACE_RELOCS (1024)
45 #define VMW_MUST_FLUSH_STACK 8
47 struct vmw_svga_winsys_context
49 struct svga_winsys_context base
;
51 struct vmw_winsys_screen
*vws
;
55 struct debug_stack_frame must_flush_stack
[VMW_MUST_FLUSH_STACK
];
59 uint8_t buffer
[VMW_COMMAND_SIZE
];
66 struct vmw_svga_winsys_surface
*handles
[VMW_SURFACE_RELOCS
];
73 struct pb_validate
*validate
;
79 static INLINE
struct vmw_svga_winsys_context
*
80 vmw_svga_winsys_context(struct svga_winsys_context
*swc
)
83 return (struct vmw_svga_winsys_context
*)swc
;
87 static enum pipe_error
88 vmw_swc_flush(struct svga_winsys_context
*swc
,
89 struct pipe_fence_handle
**pfence
)
91 struct vmw_svga_winsys_context
*vswc
= vmw_svga_winsys_context(swc
);
92 struct pipe_fence_handle
*fence
= NULL
;
96 ret
= pb_validate_validate(vswc
->validate
);
97 assert(ret
== PIPE_OK
);
100 if (vswc
->command
.used
)
101 vmw_ioctl_command(vswc
->vws
,
102 vswc
->command
.buffer
,
106 fence
= vmw_pipe_fence(vswc
->last_fence
);
108 pb_validate_fence(vswc
->validate
, fence
);
111 vswc
->command
.used
= 0;
112 vswc
->command
.reserved
= 0;
114 for(i
= 0; i
< vswc
->surface
.used
+ vswc
->surface
.staged
; ++i
) {
115 struct vmw_svga_winsys_surface
*vsurf
=
116 vswc
->surface
.handles
[i
];
117 p_atomic_dec(&vsurf
->validated
);
118 vmw_svga_winsys_surface_reference(&vswc
->surface
.handles
[i
], NULL
);
121 vswc
->surface
.used
= 0;
122 vswc
->surface
.reserved
= 0;
125 vswc
->must_flush
= FALSE
;
136 vmw_swc_reserve(struct svga_winsys_context
*swc
,
137 uint32_t nr_bytes
, uint32_t nr_relocs
)
139 struct vmw_svga_winsys_context
*vswc
= vmw_svga_winsys_context(swc
);
142 /* Check if somebody forgot to check the previous failure */
143 if(vswc
->must_flush
) {
144 debug_printf("Forgot to flush:\n");
145 debug_backtrace_dump(vswc
->must_flush_stack
, VMW_MUST_FLUSH_STACK
);
146 assert(!vswc
->must_flush
);
150 assert(nr_bytes
<= vswc
->command
.size
);
151 if(nr_bytes
> vswc
->command
.size
)
154 if(vswc
->command
.used
+ nr_bytes
> vswc
->command
.size
||
155 vswc
->surface
.used
+ nr_relocs
> vswc
->surface
.size
) {
157 vswc
->must_flush
= TRUE
;
158 debug_backtrace_capture(vswc
->must_flush_stack
, 1,
159 VMW_MUST_FLUSH_STACK
);
164 assert(vswc
->command
.used
+ nr_bytes
<= vswc
->command
.size
);
165 assert(vswc
->surface
.used
+ nr_relocs
<= vswc
->surface
.size
);
167 vswc
->command
.reserved
= nr_bytes
;
168 vswc
->surface
.reserved
= nr_relocs
;
169 vswc
->surface
.staged
= 0;
171 return vswc
->command
.buffer
+ vswc
->command
.used
;
176 vmw_swc_surface_relocation(struct svga_winsys_context
*swc
,
178 struct svga_winsys_surface
*surface
,
181 struct vmw_svga_winsys_context
*vswc
= vmw_svga_winsys_context(swc
);
182 struct vmw_svga_winsys_surface
*vsurf
;
185 *where
= SVGA3D_INVALID_ID
;
189 assert(vswc
->surface
.staged
< vswc
->surface
.reserved
);
191 vsurf
= vmw_svga_winsys_surface(surface
);
195 vmw_svga_winsys_surface_reference(&vswc
->surface
.handles
[vswc
->surface
.used
+ vswc
->surface
.staged
], vsurf
);
196 p_atomic_inc(&vsurf
->validated
);
197 ++vswc
->surface
.staged
;
202 vmw_swc_region_relocation(struct svga_winsys_context
*swc
,
203 struct SVGAGuestPtr
*where
,
204 struct svga_winsys_buffer
*buffer
,
208 struct vmw_svga_winsys_context
*vswc
= vmw_svga_winsys_context(swc
);
209 struct SVGAGuestPtr ptr
;
210 struct pb_buffer
*buf
= vmw_pb_buffer(buffer
);
213 if(!vmw_gmr_bufmgr_region_ptr(buf
, &ptr
))
216 ptr
.offset
+= offset
;
220 ret
= pb_validate_add_buffer(vswc
->validate
, buf
, flags
);
221 /* TODO: Update pipebuffer to reserve buffers and not fail here */
222 assert(ret
== PIPE_OK
);
227 vmw_swc_commit(struct svga_winsys_context
*swc
)
229 struct vmw_svga_winsys_context
*vswc
= vmw_svga_winsys_context(swc
);
231 assert(vswc
->command
.reserved
);
232 assert(vswc
->command
.used
+ vswc
->command
.reserved
<= vswc
->command
.size
);
233 vswc
->command
.used
+= vswc
->command
.reserved
;
234 vswc
->command
.reserved
= 0;
236 assert(vswc
->surface
.staged
<= vswc
->surface
.reserved
);
237 assert(vswc
->surface
.used
+ vswc
->surface
.staged
<= vswc
->surface
.size
);
238 vswc
->surface
.used
+= vswc
->surface
.staged
;
239 vswc
->surface
.staged
= 0;
240 vswc
->surface
.reserved
= 0;
245 vmw_swc_destroy(struct svga_winsys_context
*swc
)
247 struct vmw_svga_winsys_context
*vswc
= vmw_svga_winsys_context(swc
);
249 for(i
= 0; i
< vswc
->surface
.used
; ++i
) {
250 p_atomic_dec(&vswc
->surface
.handles
[i
]->validated
);
251 vmw_svga_winsys_surface_reference(&vswc
->surface
.handles
[i
], NULL
);
253 pb_validate_destroy(vswc
->validate
);
254 vmw_ioctl_context_destroy(vswc
->vws
, swc
->cid
);
259 struct svga_winsys_context
*
260 vmw_svga_winsys_context_create(struct svga_winsys_screen
*sws
)
262 struct vmw_winsys_screen
*vws
= vmw_winsys_screen(sws
);
263 struct vmw_svga_winsys_context
*vswc
;
265 vswc
= CALLOC_STRUCT(vmw_svga_winsys_context
);
269 vswc
->base
.destroy
= vmw_swc_destroy
;
270 vswc
->base
.reserve
= vmw_swc_reserve
;
271 vswc
->base
.surface_relocation
= vmw_swc_surface_relocation
;
272 vswc
->base
.region_relocation
= vmw_swc_region_relocation
;
273 vswc
->base
.commit
= vmw_swc_commit
;
274 vswc
->base
.flush
= vmw_swc_flush
;
276 vswc
->base
.cid
= vmw_ioctl_context_create(vws
);
280 vswc
->command
.size
= VMW_COMMAND_SIZE
;
281 vswc
->surface
.size
= VMW_SURFACE_RELOCS
;
283 vswc
->validate
= pb_validate_create();
284 if(!vswc
->validate
) {
293 struct pipe_context
*
294 vmw_svga_context_create(struct pipe_screen
*screen
)
296 return svga_context_create(screen
);