217
}
218
219
static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,
220
- QXLDataChunk *chunk, uint32_t group_id)
220
+ QXLDataChunk *chunk, uint32_t group_id,
221
+ uint32_t chunk_data_size)
222
{
223
uint32_t max_chunks = 32;
224
size_t offset = 0;
226
QXLPHYSICAL next_chunk_phys = 0;
227
228
for (;;) {
228
- bytes = MIN(size - offset, chunk->data_size);
229
+ bytes = MIN(size - offset, chunk_data_size);
230
memcpy(dest + offset, chunk->data, bytes);
231
offset += bytes;
232
if (offset == size) {
233
return;
234
}
235
next_chunk_phys = chunk->next_chunk;
235
- /* fist time, only get the next chunk's data size */
236
chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
237
sizeof(QXLDataChunk));
238
if (!chunk) {
239
return;
240
}
241
- /* second time, check data size and get data */
241
+ chunk_data_size = chunk->data_size;
242
chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
243
- sizeof(QXLDataChunk) + chunk->data_size);
243
+ sizeof(QXLDataChunk) + chunk_data_size);
244
if (!chunk) {
245
return;
246
}
252
}
253
254
static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
255
- uint32_t group_id)
255
+ uint32_t group_id, uint32_t chunk_data_size)
256
{
257
QEMUCursor *c;
258
uint8_t *and_mask, *xor_mask;
272
case SPICE_CURSOR_TYPE_MONO:
273
/* Assume that the full cursor is available in a single chunk. */
274
size = 2 * cursor_get_mono_bpl(c) * c->height;
275
- if (size != cursor->data_size || cursor->chunk.data_size < size) {
275
+ if (size != cursor->data_size || chunk_data_size < size) {
276
qxl_set_guest_bug(qxl, "%s: bad monochrome cursor %ux%u"
277
" data_size %u chunk_size %u",
278
__func__, c->width, c->height,
279
- cursor->data_size, cursor->chunk.data_size);
279
+ cursor->data_size, chunk_data_size);
280
goto fail;
281
}
282
and_mask = cursor->chunk.data;
288
break;
289
case SPICE_CURSOR_TYPE_ALPHA:
290
size = sizeof(uint32_t) * c->width * c->height;
291
- qxl_unpack_chunks(c->data, size, qxl, &cursor->chunk, group_id);
291
+ qxl_unpack_chunks(c->data, size, qxl, &cursor->chunk, group_id,
292
+ chunk_data_size);
293
if (qxl->debug > 2) {
294
cursor_print_ascii_art(c, "qxl/alpha");
295
}
326
}
327
switch (cmd->type) {
328
case QXL_CURSOR_SET:
329
+ {
330
+ uint32_t chunk_data_size;
331
+
332
/* First read the QXLCursor to get QXLDataChunk::data_size ... */
333
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id,
334
sizeof(QXLCursor));
335
if (!cursor) {
336
return 1;
337
}
338
+ chunk_data_size = cursor->chunk.data_size;
339
/* Then read including the chunked data following QXLCursor. */
340
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id,
336
- sizeof(QXLCursor) + cursor->chunk.data_size);
341
+ sizeof(QXLCursor) + chunk_data_size);
342
if (!cursor) {
343
return 1;
344
}
340
- c = qxl_cursor(qxl, cursor, ext->group_id);
345
+ c = qxl_cursor(qxl, cursor, ext->group_id, chunk_data_size);
346
if (c == NULL) {
347
c = cursor_builtin_left_ptr();
348
}
356
qemu_mutex_unlock(&qxl->ssd.lock);
357
qemu_bh_schedule(qxl->ssd.cursor_bh);
358
break;
359
+ }
360
case QXL_CURSOR_MOVE:
361
qemu_mutex_lock(&qxl->ssd.lock);
362
qxl->ssd.mouse_x = cmd->u.position.x;