root / ui / spice-display.c @ 0e326109
History | View | Annotate | Download (11.6 kB)
1 | a3e22260 | Gerd Hoffmann | /*
|
---|---|---|---|
2 | a3e22260 | Gerd Hoffmann | * Copyright (C) 2010 Red Hat, Inc.
|
3 | a3e22260 | Gerd Hoffmann | *
|
4 | a3e22260 | Gerd Hoffmann | * This program is free software; you can redistribute it and/or
|
5 | a3e22260 | Gerd Hoffmann | * modify it under the terms of the GNU General Public License as
|
6 | a3e22260 | Gerd Hoffmann | * published by the Free Software Foundation; either version 2 or
|
7 | a3e22260 | Gerd Hoffmann | * (at your option) version 3 of the License.
|
8 | a3e22260 | Gerd Hoffmann | *
|
9 | a3e22260 | Gerd Hoffmann | * This program is distributed in the hope that it will be useful,
|
10 | a3e22260 | Gerd Hoffmann | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11 | a3e22260 | Gerd Hoffmann | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12 | a3e22260 | Gerd Hoffmann | * GNU General Public License for more details.
|
13 | a3e22260 | Gerd Hoffmann | *
|
14 | a3e22260 | Gerd Hoffmann | * You should have received a copy of the GNU General Public License
|
15 | a3e22260 | Gerd Hoffmann | * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
16 | a3e22260 | Gerd Hoffmann | */
|
17 | a3e22260 | Gerd Hoffmann | |
18 | a3e22260 | Gerd Hoffmann | #include <pthread.h> |
19 | a3e22260 | Gerd Hoffmann | |
20 | a3e22260 | Gerd Hoffmann | #include "qemu-common.h" |
21 | a3e22260 | Gerd Hoffmann | #include "qemu-spice.h" |
22 | a3e22260 | Gerd Hoffmann | #include "qemu-timer.h" |
23 | a3e22260 | Gerd Hoffmann | #include "qemu-queue.h" |
24 | a3e22260 | Gerd Hoffmann | #include "monitor.h" |
25 | a3e22260 | Gerd Hoffmann | #include "console.h" |
26 | a3e22260 | Gerd Hoffmann | #include "sysemu.h" |
27 | a3e22260 | Gerd Hoffmann | |
28 | a3e22260 | Gerd Hoffmann | #include "spice-display.h" |
29 | a3e22260 | Gerd Hoffmann | |
30 | a3e22260 | Gerd Hoffmann | static int debug = 0; |
31 | a3e22260 | Gerd Hoffmann | |
32 | 2c80e423 | Stefan Weil | static void GCC_FMT_ATTR(2, 3) dprint(int level, const char *fmt, ...) |
33 | a3e22260 | Gerd Hoffmann | { |
34 | a3e22260 | Gerd Hoffmann | va_list args; |
35 | a3e22260 | Gerd Hoffmann | |
36 | a3e22260 | Gerd Hoffmann | if (level <= debug) {
|
37 | a3e22260 | Gerd Hoffmann | va_start(args, fmt); |
38 | a3e22260 | Gerd Hoffmann | vfprintf(stderr, fmt, args); |
39 | a3e22260 | Gerd Hoffmann | va_end(args); |
40 | a3e22260 | Gerd Hoffmann | } |
41 | a3e22260 | Gerd Hoffmann | } |
42 | a3e22260 | Gerd Hoffmann | |
43 | a3e22260 | Gerd Hoffmann | int qemu_spice_rect_is_empty(const QXLRect* r) |
44 | a3e22260 | Gerd Hoffmann | { |
45 | a3e22260 | Gerd Hoffmann | return r->top == r->bottom || r->left == r->right;
|
46 | a3e22260 | Gerd Hoffmann | } |
47 | a3e22260 | Gerd Hoffmann | |
48 | a3e22260 | Gerd Hoffmann | void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) |
49 | a3e22260 | Gerd Hoffmann | { |
50 | a3e22260 | Gerd Hoffmann | if (qemu_spice_rect_is_empty(r)) {
|
51 | a3e22260 | Gerd Hoffmann | return;
|
52 | a3e22260 | Gerd Hoffmann | } |
53 | a3e22260 | Gerd Hoffmann | |
54 | a3e22260 | Gerd Hoffmann | if (qemu_spice_rect_is_empty(dest)) {
|
55 | a3e22260 | Gerd Hoffmann | *dest = *r; |
56 | a3e22260 | Gerd Hoffmann | return;
|
57 | a3e22260 | Gerd Hoffmann | } |
58 | a3e22260 | Gerd Hoffmann | |
59 | a3e22260 | Gerd Hoffmann | dest->top = MIN(dest->top, r->top); |
60 | a3e22260 | Gerd Hoffmann | dest->left = MIN(dest->left, r->left); |
61 | a3e22260 | Gerd Hoffmann | dest->bottom = MAX(dest->bottom, r->bottom); |
62 | a3e22260 | Gerd Hoffmann | dest->right = MAX(dest->right, r->right); |
63 | a3e22260 | Gerd Hoffmann | } |
64 | a3e22260 | Gerd Hoffmann | |
65 | a3e22260 | Gerd Hoffmann | /*
|
66 | a3e22260 | Gerd Hoffmann | * Called from spice server thread context (via interface_get_command).
|
67 | 7466bc49 | Gerd Hoffmann | *
|
68 | 7466bc49 | Gerd Hoffmann | * We must aquire the global qemu mutex here to make sure the
|
69 | 7466bc49 | Gerd Hoffmann | * DisplayState (+DisplaySurface) we are accessing doesn't change
|
70 | 7466bc49 | Gerd Hoffmann | * underneath us.
|
71 | a3e22260 | Gerd Hoffmann | */
|
72 | a3e22260 | Gerd Hoffmann | SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) |
73 | a3e22260 | Gerd Hoffmann | { |
74 | a3e22260 | Gerd Hoffmann | SimpleSpiceUpdate *update; |
75 | a3e22260 | Gerd Hoffmann | QXLDrawable *drawable; |
76 | a3e22260 | Gerd Hoffmann | QXLImage *image; |
77 | a3e22260 | Gerd Hoffmann | QXLCommand *cmd; |
78 | a3e22260 | Gerd Hoffmann | uint8_t *src, *dst; |
79 | a3e22260 | Gerd Hoffmann | int by, bw, bh;
|
80 | a3e22260 | Gerd Hoffmann | |
81 | 7466bc49 | Gerd Hoffmann | qemu_mutex_lock_iothread(); |
82 | a3e22260 | Gerd Hoffmann | if (qemu_spice_rect_is_empty(&ssd->dirty)) {
|
83 | 7466bc49 | Gerd Hoffmann | qemu_mutex_unlock_iothread(); |
84 | a3e22260 | Gerd Hoffmann | return NULL; |
85 | a3e22260 | Gerd Hoffmann | }; |
86 | a3e22260 | Gerd Hoffmann | |
87 | a3e22260 | Gerd Hoffmann | dprint(2, "%s: lr %d -> %d, tb -> %d -> %d\n", __FUNCTION__, |
88 | a3e22260 | Gerd Hoffmann | ssd->dirty.left, ssd->dirty.right, |
89 | a3e22260 | Gerd Hoffmann | ssd->dirty.top, ssd->dirty.bottom); |
90 | a3e22260 | Gerd Hoffmann | |
91 | a3e22260 | Gerd Hoffmann | update = qemu_mallocz(sizeof(*update));
|
92 | a3e22260 | Gerd Hoffmann | drawable = &update->drawable; |
93 | a3e22260 | Gerd Hoffmann | image = &update->image; |
94 | a3e22260 | Gerd Hoffmann | cmd = &update->ext.cmd; |
95 | a3e22260 | Gerd Hoffmann | |
96 | a3e22260 | Gerd Hoffmann | bw = ssd->dirty.right - ssd->dirty.left; |
97 | a3e22260 | Gerd Hoffmann | bh = ssd->dirty.bottom - ssd->dirty.top; |
98 | a3e22260 | Gerd Hoffmann | update->bitmap = qemu_malloc(bw * bh * 4);
|
99 | a3e22260 | Gerd Hoffmann | |
100 | a3e22260 | Gerd Hoffmann | drawable->bbox = ssd->dirty; |
101 | a3e22260 | Gerd Hoffmann | drawable->clip.type = SPICE_CLIP_TYPE_NONE; |
102 | a3e22260 | Gerd Hoffmann | drawable->effect = QXL_EFFECT_OPAQUE; |
103 | a3e22260 | Gerd Hoffmann | drawable->release_info.id = (intptr_t)update; |
104 | a3e22260 | Gerd Hoffmann | drawable->type = QXL_DRAW_COPY; |
105 | a3e22260 | Gerd Hoffmann | drawable->surfaces_dest[0] = -1; |
106 | a3e22260 | Gerd Hoffmann | drawable->surfaces_dest[1] = -1; |
107 | a3e22260 | Gerd Hoffmann | drawable->surfaces_dest[2] = -1; |
108 | a3e22260 | Gerd Hoffmann | |
109 | a3e22260 | Gerd Hoffmann | drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; |
110 | a3e22260 | Gerd Hoffmann | drawable->u.copy.src_bitmap = (intptr_t)image; |
111 | a3e22260 | Gerd Hoffmann | drawable->u.copy.src_area.right = bw; |
112 | a3e22260 | Gerd Hoffmann | drawable->u.copy.src_area.bottom = bh; |
113 | a3e22260 | Gerd Hoffmann | |
114 | a3e22260 | Gerd Hoffmann | QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, ssd->unique++); |
115 | a3e22260 | Gerd Hoffmann | image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP; |
116 | a3e22260 | Gerd Hoffmann | image->bitmap.flags = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN; |
117 | a3e22260 | Gerd Hoffmann | image->bitmap.stride = bw * 4;
|
118 | a3e22260 | Gerd Hoffmann | image->descriptor.width = image->bitmap.x = bw; |
119 | a3e22260 | Gerd Hoffmann | image->descriptor.height = image->bitmap.y = bh; |
120 | a3e22260 | Gerd Hoffmann | image->bitmap.data = (intptr_t)(update->bitmap); |
121 | a3e22260 | Gerd Hoffmann | image->bitmap.palette = 0;
|
122 | a3e22260 | Gerd Hoffmann | image->bitmap.format = SPICE_BITMAP_FMT_32BIT; |
123 | a3e22260 | Gerd Hoffmann | |
124 | a3e22260 | Gerd Hoffmann | if (ssd->conv == NULL) { |
125 | a3e22260 | Gerd Hoffmann | PixelFormat dst = qemu_default_pixelformat(32);
|
126 | a3e22260 | Gerd Hoffmann | ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf); |
127 | a3e22260 | Gerd Hoffmann | assert(ssd->conv); |
128 | a3e22260 | Gerd Hoffmann | } |
129 | a3e22260 | Gerd Hoffmann | |
130 | a3e22260 | Gerd Hoffmann | src = ds_get_data(ssd->ds) + |
131 | a3e22260 | Gerd Hoffmann | ssd->dirty.top * ds_get_linesize(ssd->ds) + |
132 | a3e22260 | Gerd Hoffmann | ssd->dirty.left * ds_get_bytes_per_pixel(ssd->ds); |
133 | a3e22260 | Gerd Hoffmann | dst = update->bitmap; |
134 | a3e22260 | Gerd Hoffmann | for (by = 0; by < bh; by++) { |
135 | a3e22260 | Gerd Hoffmann | qemu_pf_conv_run(ssd->conv, dst, src, bw); |
136 | a3e22260 | Gerd Hoffmann | src += ds_get_linesize(ssd->ds); |
137 | a3e22260 | Gerd Hoffmann | dst += image->bitmap.stride; |
138 | a3e22260 | Gerd Hoffmann | } |
139 | a3e22260 | Gerd Hoffmann | |
140 | a3e22260 | Gerd Hoffmann | cmd->type = QXL_CMD_DRAW; |
141 | a3e22260 | Gerd Hoffmann | cmd->data = (intptr_t)drawable; |
142 | a3e22260 | Gerd Hoffmann | |
143 | a3e22260 | Gerd Hoffmann | memset(&ssd->dirty, 0, sizeof(ssd->dirty)); |
144 | 7466bc49 | Gerd Hoffmann | qemu_mutex_unlock_iothread(); |
145 | a3e22260 | Gerd Hoffmann | return update;
|
146 | a3e22260 | Gerd Hoffmann | } |
147 | a3e22260 | Gerd Hoffmann | |
148 | a3e22260 | Gerd Hoffmann | /*
|
149 | a3e22260 | Gerd Hoffmann | * Called from spice server thread context (via interface_release_ressource)
|
150 | a3e22260 | Gerd Hoffmann | * We do *not* hold the global qemu mutex here, so extra care is needed
|
151 | a3e22260 | Gerd Hoffmann | * when calling qemu functions. Qemu interfaces used:
|
152 | a3e22260 | Gerd Hoffmann | * - qemu_free (underlying glibc free is re-entrant).
|
153 | a3e22260 | Gerd Hoffmann | */
|
154 | a3e22260 | Gerd Hoffmann | void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update)
|
155 | a3e22260 | Gerd Hoffmann | { |
156 | a3e22260 | Gerd Hoffmann | qemu_free(update->bitmap); |
157 | a3e22260 | Gerd Hoffmann | qemu_free(update); |
158 | a3e22260 | Gerd Hoffmann | } |
159 | a3e22260 | Gerd Hoffmann | |
160 | a3e22260 | Gerd Hoffmann | void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
|
161 | a3e22260 | Gerd Hoffmann | { |
162 | a3e22260 | Gerd Hoffmann | QXLDevMemSlot memslot; |
163 | a3e22260 | Gerd Hoffmann | |
164 | a3e22260 | Gerd Hoffmann | dprint(1, "%s:\n", __FUNCTION__); |
165 | a3e22260 | Gerd Hoffmann | |
166 | a3e22260 | Gerd Hoffmann | memset(&memslot, 0, sizeof(memslot)); |
167 | a3e22260 | Gerd Hoffmann | memslot.slot_group_id = MEMSLOT_GROUP_HOST; |
168 | a3e22260 | Gerd Hoffmann | memslot.virt_end = ~0;
|
169 | a3e22260 | Gerd Hoffmann | ssd->worker->add_memslot(ssd->worker, &memslot); |
170 | a3e22260 | Gerd Hoffmann | } |
171 | a3e22260 | Gerd Hoffmann | |
172 | a3e22260 | Gerd Hoffmann | void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
|
173 | a3e22260 | Gerd Hoffmann | { |
174 | a3e22260 | Gerd Hoffmann | QXLDevSurfaceCreate surface; |
175 | a3e22260 | Gerd Hoffmann | |
176 | a3e22260 | Gerd Hoffmann | dprint(1, "%s: %dx%d\n", __FUNCTION__, |
177 | a3e22260 | Gerd Hoffmann | ds_get_width(ssd->ds), ds_get_height(ssd->ds)); |
178 | a3e22260 | Gerd Hoffmann | |
179 | a3e22260 | Gerd Hoffmann | surface.format = SPICE_SURFACE_FMT_32_xRGB; |
180 | a3e22260 | Gerd Hoffmann | surface.width = ds_get_width(ssd->ds); |
181 | a3e22260 | Gerd Hoffmann | surface.height = ds_get_height(ssd->ds); |
182 | a3e22260 | Gerd Hoffmann | surface.stride = -surface.width * 4;
|
183 | 869564a9 | Gerd Hoffmann | surface.mouse_mode = true;
|
184 | a3e22260 | Gerd Hoffmann | surface.flags = 0;
|
185 | a3e22260 | Gerd Hoffmann | surface.type = 0;
|
186 | a3e22260 | Gerd Hoffmann | surface.mem = (intptr_t)ssd->buf; |
187 | a3e22260 | Gerd Hoffmann | surface.group_id = MEMSLOT_GROUP_HOST; |
188 | 7466bc49 | Gerd Hoffmann | |
189 | 7466bc49 | Gerd Hoffmann | qemu_mutex_unlock_iothread(); |
190 | a3e22260 | Gerd Hoffmann | ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
|
191 | 7466bc49 | Gerd Hoffmann | qemu_mutex_lock_iothread(); |
192 | a3e22260 | Gerd Hoffmann | } |
193 | a3e22260 | Gerd Hoffmann | |
194 | a3e22260 | Gerd Hoffmann | void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
|
195 | a3e22260 | Gerd Hoffmann | { |
196 | a3e22260 | Gerd Hoffmann | dprint(1, "%s:\n", __FUNCTION__); |
197 | a3e22260 | Gerd Hoffmann | |
198 | 7466bc49 | Gerd Hoffmann | qemu_mutex_unlock_iothread(); |
199 | a3e22260 | Gerd Hoffmann | ssd->worker->destroy_primary_surface(ssd->worker, 0);
|
200 | 7466bc49 | Gerd Hoffmann | qemu_mutex_lock_iothread(); |
201 | a3e22260 | Gerd Hoffmann | } |
202 | a3e22260 | Gerd Hoffmann | |
203 | a3e22260 | Gerd Hoffmann | void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) |
204 | a3e22260 | Gerd Hoffmann | { |
205 | a3e22260 | Gerd Hoffmann | SimpleSpiceDisplay *ssd = opaque; |
206 | a3e22260 | Gerd Hoffmann | |
207 | a3e22260 | Gerd Hoffmann | if (running) {
|
208 | a3e22260 | Gerd Hoffmann | ssd->worker->start(ssd->worker); |
209 | a3e22260 | Gerd Hoffmann | } else {
|
210 | 7466bc49 | Gerd Hoffmann | qemu_mutex_unlock_iothread(); |
211 | a3e22260 | Gerd Hoffmann | ssd->worker->stop(ssd->worker); |
212 | 7466bc49 | Gerd Hoffmann | qemu_mutex_lock_iothread(); |
213 | a3e22260 | Gerd Hoffmann | } |
214 | a3e22260 | Gerd Hoffmann | ssd->running = running; |
215 | a3e22260 | Gerd Hoffmann | } |
216 | a3e22260 | Gerd Hoffmann | |
217 | a3e22260 | Gerd Hoffmann | /* display listener callbacks */
|
218 | a3e22260 | Gerd Hoffmann | |
219 | a3e22260 | Gerd Hoffmann | void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
|
220 | a3e22260 | Gerd Hoffmann | int x, int y, int w, int h) |
221 | a3e22260 | Gerd Hoffmann | { |
222 | a3e22260 | Gerd Hoffmann | QXLRect update_area; |
223 | a3e22260 | Gerd Hoffmann | |
224 | a3e22260 | Gerd Hoffmann | dprint(2, "%s: x %d y %d w %d h %d\n", __FUNCTION__, x, y, w, h); |
225 | a3e22260 | Gerd Hoffmann | update_area.left = x, |
226 | a3e22260 | Gerd Hoffmann | update_area.right = x + w; |
227 | a3e22260 | Gerd Hoffmann | update_area.top = y; |
228 | a3e22260 | Gerd Hoffmann | update_area.bottom = y + h; |
229 | a3e22260 | Gerd Hoffmann | |
230 | a3e22260 | Gerd Hoffmann | if (qemu_spice_rect_is_empty(&ssd->dirty)) {
|
231 | a3e22260 | Gerd Hoffmann | ssd->notify++; |
232 | a3e22260 | Gerd Hoffmann | } |
233 | a3e22260 | Gerd Hoffmann | qemu_spice_rect_union(&ssd->dirty, &update_area); |
234 | a3e22260 | Gerd Hoffmann | } |
235 | a3e22260 | Gerd Hoffmann | |
236 | a3e22260 | Gerd Hoffmann | void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
|
237 | a3e22260 | Gerd Hoffmann | { |
238 | a3e22260 | Gerd Hoffmann | dprint(1, "%s:\n", __FUNCTION__); |
239 | a3e22260 | Gerd Hoffmann | |
240 | a3e22260 | Gerd Hoffmann | memset(&ssd->dirty, 0, sizeof(ssd->dirty)); |
241 | a3e22260 | Gerd Hoffmann | qemu_pf_conv_put(ssd->conv); |
242 | a3e22260 | Gerd Hoffmann | ssd->conv = NULL;
|
243 | a3e22260 | Gerd Hoffmann | |
244 | a3e22260 | Gerd Hoffmann | qemu_spice_destroy_host_primary(ssd); |
245 | a3e22260 | Gerd Hoffmann | qemu_spice_create_host_primary(ssd); |
246 | a3e22260 | Gerd Hoffmann | |
247 | a3e22260 | Gerd Hoffmann | memset(&ssd->dirty, 0, sizeof(ssd->dirty)); |
248 | a3e22260 | Gerd Hoffmann | ssd->notify++; |
249 | a3e22260 | Gerd Hoffmann | } |
250 | a3e22260 | Gerd Hoffmann | |
251 | a3e22260 | Gerd Hoffmann | void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
|
252 | a3e22260 | Gerd Hoffmann | { |
253 | a3e22260 | Gerd Hoffmann | dprint(3, "%s:\n", __FUNCTION__); |
254 | a3e22260 | Gerd Hoffmann | vga_hw_update(); |
255 | a3e22260 | Gerd Hoffmann | if (ssd->notify) {
|
256 | a3e22260 | Gerd Hoffmann | ssd->notify = 0;
|
257 | a3e22260 | Gerd Hoffmann | ssd->worker->wakeup(ssd->worker); |
258 | a3e22260 | Gerd Hoffmann | dprint(2, "%s: notify\n", __FUNCTION__); |
259 | a3e22260 | Gerd Hoffmann | } |
260 | a3e22260 | Gerd Hoffmann | } |
261 | a3e22260 | Gerd Hoffmann | |
262 | a3e22260 | Gerd Hoffmann | /* spice display interface callbacks */
|
263 | a3e22260 | Gerd Hoffmann | |
264 | a3e22260 | Gerd Hoffmann | static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) |
265 | a3e22260 | Gerd Hoffmann | { |
266 | a3e22260 | Gerd Hoffmann | SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); |
267 | a3e22260 | Gerd Hoffmann | |
268 | a3e22260 | Gerd Hoffmann | dprint(1, "%s:\n", __FUNCTION__); |
269 | a3e22260 | Gerd Hoffmann | ssd->worker = qxl_worker; |
270 | a3e22260 | Gerd Hoffmann | } |
271 | a3e22260 | Gerd Hoffmann | |
272 | a3e22260 | Gerd Hoffmann | static void interface_set_compression_level(QXLInstance *sin, int level) |
273 | a3e22260 | Gerd Hoffmann | { |
274 | a3e22260 | Gerd Hoffmann | dprint(1, "%s:\n", __FUNCTION__); |
275 | a3e22260 | Gerd Hoffmann | /* nothing to do */
|
276 | a3e22260 | Gerd Hoffmann | } |
277 | a3e22260 | Gerd Hoffmann | |
278 | a3e22260 | Gerd Hoffmann | static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time) |
279 | a3e22260 | Gerd Hoffmann | { |
280 | a3e22260 | Gerd Hoffmann | dprint(3, "%s:\n", __FUNCTION__); |
281 | a3e22260 | Gerd Hoffmann | /* nothing to do */
|
282 | a3e22260 | Gerd Hoffmann | } |
283 | a3e22260 | Gerd Hoffmann | |
284 | a3e22260 | Gerd Hoffmann | static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) |
285 | a3e22260 | Gerd Hoffmann | { |
286 | a3e22260 | Gerd Hoffmann | SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); |
287 | a3e22260 | Gerd Hoffmann | |
288 | a3e22260 | Gerd Hoffmann | info->memslot_gen_bits = MEMSLOT_GENERATION_BITS; |
289 | a3e22260 | Gerd Hoffmann | info->memslot_id_bits = MEMSLOT_SLOT_BITS; |
290 | a3e22260 | Gerd Hoffmann | info->num_memslots = NUM_MEMSLOTS; |
291 | a3e22260 | Gerd Hoffmann | info->num_memslots_groups = NUM_MEMSLOTS_GROUPS; |
292 | a3e22260 | Gerd Hoffmann | info->internal_groupslot_id = 0;
|
293 | a3e22260 | Gerd Hoffmann | info->qxl_ram_size = ssd->bufsize; |
294 | a3e22260 | Gerd Hoffmann | info->n_surfaces = NUM_SURFACES; |
295 | a3e22260 | Gerd Hoffmann | } |
296 | a3e22260 | Gerd Hoffmann | |
297 | a3e22260 | Gerd Hoffmann | static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) |
298 | a3e22260 | Gerd Hoffmann | { |
299 | a3e22260 | Gerd Hoffmann | SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); |
300 | a3e22260 | Gerd Hoffmann | SimpleSpiceUpdate *update; |
301 | a3e22260 | Gerd Hoffmann | |
302 | a3e22260 | Gerd Hoffmann | dprint(3, "%s:\n", __FUNCTION__); |
303 | a3e22260 | Gerd Hoffmann | update = qemu_spice_create_update(ssd); |
304 | a3e22260 | Gerd Hoffmann | if (update == NULL) { |
305 | a3e22260 | Gerd Hoffmann | return false; |
306 | a3e22260 | Gerd Hoffmann | } |
307 | a3e22260 | Gerd Hoffmann | *ext = update->ext; |
308 | a3e22260 | Gerd Hoffmann | return true; |
309 | a3e22260 | Gerd Hoffmann | } |
310 | a3e22260 | Gerd Hoffmann | |
311 | a3e22260 | Gerd Hoffmann | static int interface_req_cmd_notification(QXLInstance *sin) |
312 | a3e22260 | Gerd Hoffmann | { |
313 | a3e22260 | Gerd Hoffmann | dprint(1, "%s:\n", __FUNCTION__); |
314 | a3e22260 | Gerd Hoffmann | return 1; |
315 | a3e22260 | Gerd Hoffmann | } |
316 | a3e22260 | Gerd Hoffmann | |
317 | a3e22260 | Gerd Hoffmann | static void interface_release_resource(QXLInstance *sin, |
318 | a3e22260 | Gerd Hoffmann | struct QXLReleaseInfoExt ext)
|
319 | a3e22260 | Gerd Hoffmann | { |
320 | a3e22260 | Gerd Hoffmann | SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); |
321 | a3e22260 | Gerd Hoffmann | uintptr_t id; |
322 | a3e22260 | Gerd Hoffmann | |
323 | a3e22260 | Gerd Hoffmann | dprint(2, "%s:\n", __FUNCTION__); |
324 | a3e22260 | Gerd Hoffmann | id = ext.info->id; |
325 | a3e22260 | Gerd Hoffmann | qemu_spice_destroy_update(ssd, (void*)id);
|
326 | a3e22260 | Gerd Hoffmann | } |
327 | a3e22260 | Gerd Hoffmann | |
328 | a3e22260 | Gerd Hoffmann | static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext) |
329 | a3e22260 | Gerd Hoffmann | { |
330 | a3e22260 | Gerd Hoffmann | dprint(3, "%s:\n", __FUNCTION__); |
331 | a3e22260 | Gerd Hoffmann | return false; |
332 | a3e22260 | Gerd Hoffmann | } |
333 | a3e22260 | Gerd Hoffmann | |
334 | a3e22260 | Gerd Hoffmann | static int interface_req_cursor_notification(QXLInstance *sin) |
335 | a3e22260 | Gerd Hoffmann | { |
336 | a3e22260 | Gerd Hoffmann | dprint(1, "%s:\n", __FUNCTION__); |
337 | a3e22260 | Gerd Hoffmann | return 1; |
338 | a3e22260 | Gerd Hoffmann | } |
339 | a3e22260 | Gerd Hoffmann | |
340 | a3e22260 | Gerd Hoffmann | static void interface_notify_update(QXLInstance *sin, uint32_t update_id) |
341 | a3e22260 | Gerd Hoffmann | { |
342 | a3e22260 | Gerd Hoffmann | fprintf(stderr, "%s: abort()\n", __FUNCTION__);
|
343 | a3e22260 | Gerd Hoffmann | abort(); |
344 | a3e22260 | Gerd Hoffmann | } |
345 | a3e22260 | Gerd Hoffmann | |
346 | a3e22260 | Gerd Hoffmann | static int interface_flush_resources(QXLInstance *sin) |
347 | a3e22260 | Gerd Hoffmann | { |
348 | a3e22260 | Gerd Hoffmann | fprintf(stderr, "%s: abort()\n", __FUNCTION__);
|
349 | a3e22260 | Gerd Hoffmann | abort(); |
350 | a3e22260 | Gerd Hoffmann | return 0; |
351 | a3e22260 | Gerd Hoffmann | } |
352 | a3e22260 | Gerd Hoffmann | |
353 | a3e22260 | Gerd Hoffmann | static const QXLInterface dpy_interface = { |
354 | a3e22260 | Gerd Hoffmann | .base.type = SPICE_INTERFACE_QXL, |
355 | a3e22260 | Gerd Hoffmann | .base.description = "qemu simple display",
|
356 | a3e22260 | Gerd Hoffmann | .base.major_version = SPICE_INTERFACE_QXL_MAJOR, |
357 | a3e22260 | Gerd Hoffmann | .base.minor_version = SPICE_INTERFACE_QXL_MINOR, |
358 | a3e22260 | Gerd Hoffmann | |
359 | a3e22260 | Gerd Hoffmann | .attache_worker = interface_attach_worker, |
360 | a3e22260 | Gerd Hoffmann | .set_compression_level = interface_set_compression_level, |
361 | a3e22260 | Gerd Hoffmann | .set_mm_time = interface_set_mm_time, |
362 | a3e22260 | Gerd Hoffmann | .get_init_info = interface_get_init_info, |
363 | a3e22260 | Gerd Hoffmann | |
364 | a3e22260 | Gerd Hoffmann | /* the callbacks below are called from spice server thread context */
|
365 | a3e22260 | Gerd Hoffmann | .get_command = interface_get_command, |
366 | a3e22260 | Gerd Hoffmann | .req_cmd_notification = interface_req_cmd_notification, |
367 | a3e22260 | Gerd Hoffmann | .release_resource = interface_release_resource, |
368 | a3e22260 | Gerd Hoffmann | .get_cursor_command = interface_get_cursor_command, |
369 | a3e22260 | Gerd Hoffmann | .req_cursor_notification = interface_req_cursor_notification, |
370 | a3e22260 | Gerd Hoffmann | .notify_update = interface_notify_update, |
371 | a3e22260 | Gerd Hoffmann | .flush_resources = interface_flush_resources, |
372 | a3e22260 | Gerd Hoffmann | }; |
373 | a3e22260 | Gerd Hoffmann | |
374 | a3e22260 | Gerd Hoffmann | static SimpleSpiceDisplay sdpy;
|
375 | a3e22260 | Gerd Hoffmann | |
376 | a3e22260 | Gerd Hoffmann | static void display_update(struct DisplayState *ds, int x, int y, int w, int h) |
377 | a3e22260 | Gerd Hoffmann | { |
378 | a3e22260 | Gerd Hoffmann | qemu_spice_display_update(&sdpy, x, y, w, h); |
379 | a3e22260 | Gerd Hoffmann | } |
380 | a3e22260 | Gerd Hoffmann | |
381 | a3e22260 | Gerd Hoffmann | static void display_resize(struct DisplayState *ds) |
382 | a3e22260 | Gerd Hoffmann | { |
383 | a3e22260 | Gerd Hoffmann | qemu_spice_display_resize(&sdpy); |
384 | a3e22260 | Gerd Hoffmann | } |
385 | a3e22260 | Gerd Hoffmann | |
386 | a3e22260 | Gerd Hoffmann | static void display_refresh(struct DisplayState *ds) |
387 | a3e22260 | Gerd Hoffmann | { |
388 | a3e22260 | Gerd Hoffmann | qemu_spice_display_refresh(&sdpy); |
389 | a3e22260 | Gerd Hoffmann | } |
390 | a3e22260 | Gerd Hoffmann | |
391 | a3e22260 | Gerd Hoffmann | static DisplayChangeListener display_listener = {
|
392 | a3e22260 | Gerd Hoffmann | .dpy_update = display_update, |
393 | a3e22260 | Gerd Hoffmann | .dpy_resize = display_resize, |
394 | a3e22260 | Gerd Hoffmann | .dpy_refresh = display_refresh, |
395 | a3e22260 | Gerd Hoffmann | }; |
396 | a3e22260 | Gerd Hoffmann | |
397 | a3e22260 | Gerd Hoffmann | void qemu_spice_display_init(DisplayState *ds)
|
398 | a3e22260 | Gerd Hoffmann | { |
399 | a3e22260 | Gerd Hoffmann | assert(sdpy.ds == NULL);
|
400 | a3e22260 | Gerd Hoffmann | sdpy.ds = ds; |
401 | a3e22260 | Gerd Hoffmann | sdpy.bufsize = (16 * 1024 * 1024); |
402 | a3e22260 | Gerd Hoffmann | sdpy.buf = qemu_malloc(sdpy.bufsize); |
403 | a3e22260 | Gerd Hoffmann | register_displaychangelistener(ds, &display_listener); |
404 | a3e22260 | Gerd Hoffmann | |
405 | a3e22260 | Gerd Hoffmann | sdpy.qxl.base.sif = &dpy_interface.base; |
406 | a3e22260 | Gerd Hoffmann | qemu_spice_add_interface(&sdpy.qxl.base); |
407 | a3e22260 | Gerd Hoffmann | assert(sdpy.worker); |
408 | a3e22260 | Gerd Hoffmann | |
409 | a3e22260 | Gerd Hoffmann | qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy); |
410 | a3e22260 | Gerd Hoffmann | qemu_spice_create_host_memslot(&sdpy); |
411 | a3e22260 | Gerd Hoffmann | qemu_spice_create_host_primary(&sdpy); |
412 | a3e22260 | Gerd Hoffmann | } |