Commit 5ac88aa7 authored by Gerd Hoffmann's avatar Gerd Hoffmann Committed by Alexander Larsson
Browse files

Properly parse QXLImage to the new-world SpiceImage

SpiceImage now replaces RedImage and has all image types in it.
All image data are now chunked (and as such not copied when demarshalling).
parent 26c1a076
This diff is collapsed.
......@@ -33,7 +33,6 @@ typedef struct _SpicePaletteCache SpicePaletteCache;
typedef struct _SpiceGlzDecoder SpiceGlzDecoder;
typedef struct _SpiceJpegDecoder SpiceJpegDecoder;
typedef struct _SpiceZlibDecoder SpiceZlibDecoder;
typedef struct _SpiceVirtMapping SpiceVirtMapping;
typedef struct _SpiceCanvas SpiceCanvas;
typedef struct {
......@@ -120,16 +119,6 @@ struct _SpiceZlibDecoder {
SpiceZlibDecoderOps *ops;
};
typedef struct {
void *(*get_virt)(SpiceVirtMapping *mapping, unsigned long addr, uint32_t add_size);
void (*validate_virt)(SpiceVirtMapping *mapping, unsigned long virt,
unsigned long from_addr, uint32_t add_size);
} SpiceVirtMappingOps;
struct _SpiceVirtMapping {
SpiceVirtMappingOps *ops;
};
typedef struct {
void (*draw_fill)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill);
void (*draw_copy)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy);
......
......@@ -806,9 +806,6 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
, SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
)
{
GLCanvas *canvas;
......@@ -835,9 +832,6 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
, glz_decoder
, jpeg_decoder
, zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, virt_mapping
#endif
);
if (!init_ok) {
goto error_2;
......
......@@ -32,9 +32,6 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
, SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
);
void gl_canvas_set_textures_lost(SpiceCanvas *canvas, int textures_lost);
void gl_canvas_init();
......
......@@ -1173,9 +1173,6 @@ static SpiceCanvas *canvas_create_common(pixman_image_t *image,
, SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
)
{
SwCanvas *canvas;
......@@ -1202,9 +1199,6 @@ static SpiceCanvas *canvas_create_common(pixman_image_t *image,
, glz_decoder
, jpeg_decoder
, zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, virt_mapping
#endif
);
canvas->private_data = NULL;
canvas->private_data_size = 0;
......@@ -1225,9 +1219,6 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format
, SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
)
{
pixman_image_t *image;
......@@ -1246,9 +1237,6 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format
, glz_decoder
, jpeg_decoder
, zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, virt_mapping
#endif
);
}
......@@ -1264,9 +1252,6 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format,
, SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
)
{
pixman_image_t *image;
......@@ -1285,9 +1270,6 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format,
, glz_decoder
, jpeg_decoder
, zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, virt_mapping
#endif
);
}
......
......@@ -37,9 +37,6 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format
, SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
);
SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint8_t *data, size_t stride
......@@ -53,9 +50,6 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint
, SpiceGlzDecoder *glz_decoder
, SpiceJpegDecoder *jpeg_decoder
, SpiceZlibDecoder *zlib_decoder
#ifndef SW_CANVAS_NO_CHUNKS
, SpiceVirtMapping *virt_mapping
#endif
);
......
......@@ -93,7 +93,7 @@ def write_read_primitive(writer, start, container, name, scope):
writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size"))
writer.error_check("pos + %s > message_end" % m.member_type.get_fixed_nw_size())
var = "%s__value" % (name)
var = "%s__value" % (name.replace(".", "_"))
if not scope.variable_defined(var):
scope.variable_def(m.member_type.c_type(), var)
writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type()))
......@@ -112,7 +112,7 @@ def write_read_primitive_item(writer, item, scope):
assert(item.type.is_primitive())
writer.assign("pos", item.get_position())
writer.error_check("pos + %s > message_end" % item.type.get_fixed_nw_size())
var = "%s__value" % (item.subprefix)
var = "%s__value" % (item.subprefix.replace(".", "_"))
scope.variable_def(item.type.c_type(), var)
writer.assign(var, "read_%s(pos)" % (item.type.primitive_type()))
return var
......
......@@ -811,14 +811,31 @@ class ContainerType(Type):
return str(fixed)
def lookup_member(self, name):
dot = name.find('.')
rest = None
if dot >= 0:
rest = name[dot+1:]
name = name[:dot]
member = None
if self.members_by_name.has_key(name):
return self.members_by_name[name]
for m in self.members:
if m.is_switch():
member = m.lookup_case_member(name)
if member:
return member
raise Exception, "No member called %s found" % name
member = self.members_by_name[name]
else:
for m in self.members:
if m.is_switch():
member = m.lookup_case_member(name)
if member != None:
break
if member != None:
break
if member == None:
raise Exception, "No member called %s found" % name
if rest != None:
return member.member_type.lookup_member(rest)
return member
class StructType(ContainerType):
def __init__(self, name, members, attribute_list):
......
......@@ -95,7 +95,7 @@ def SPICE_BNF():
switchCase = Group(Group(OneOrMore(default_.setParseAction(replaceWith(None)) + colon | case_.suppress() + identifier + colon)) + variableDef) \
.setParseAction(lambda toks: ptypes.SwitchCase(toks[0][0], toks[0][1]))
switchBody = Group(switch_ + lparen + identifier + rparen + lbrace + Group(OneOrMore(switchCase)) + rbrace + identifier + attributes - semi) \
switchBody = Group(switch_ + lparen + delimitedList(identifier,delim='.', combine=True) + rparen + lbrace + Group(OneOrMore(switchCase)) + rbrace + identifier + attributes - semi) \
.setParseAction(lambda toks: ptypes.Switch(toks[0][1], toks[0][2], toks[0][3], toks[0][4]))
messageBody = structBody = Group(lbrace + ZeroOrMore(variableDef | switchBody) + rbrace)
structSpec = Group(struct_ + identifier + structBody + attributes).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3]))
......
......@@ -17,6 +17,7 @@
*/
#include <stdbool.h>
#include <inttypes.h>
#include "red_common.h"
#include "red_memslots.h"
#include "red_parse_qxl.h"
......@@ -99,7 +100,6 @@ static size_t red_get_data_chunks_ptr(RedMemSlotInfo *slots, int group_id,
return data_size;
}
#if 0
static size_t red_get_data_chunks(RedMemSlotInfo *slots, int group_id,
RedDataChunk *red, SPICE_ADDRESS addr)
{
......@@ -109,7 +109,6 @@ static size_t red_get_data_chunks(RedMemSlotInfo *slots, int group_id,
qxl = (QXLDataChunk*)get_virt(slots, addr, sizeof(*qxl), group_id);
return red_get_data_chunks_ptr(slots, group_id, memslot_id, red, qxl);
}
#endif
static void red_put_data_chunks(RedDataChunk *red)
{
......@@ -255,6 +254,151 @@ static SpiceClipRects *red_get_clip_rects(RedMemSlotInfo *slots, int group_id,
return red;
}
static SpiceChunks *red_get_image_data_flat(RedMemSlotInfo *slots, int group_id,
SPICE_ADDRESS addr, size_t size)
{
SpiceChunks *data;
data = spice_chunks_new(1);
data->data_size = size;
data->chunk[0].data = (void*)get_virt(slots, addr, size, group_id);
data->chunk[0].len = size;
return data;
}
static SpiceChunks *red_get_image_data_chunked(RedMemSlotInfo *slots, int group_id,
RedDataChunk *head)
{
SpiceChunks *data;
RedDataChunk *chunk;
int i;
for (i = 0, chunk = head; chunk != NULL; chunk = chunk->next_chunk) {
i++;
}
data = spice_chunks_new(i);
data->data_size = 0;
for (i = 0, chunk = head;
chunk != NULL && i < data->num_chunks;
chunk = chunk->next_chunk, i++) {
data->chunk[i].data = chunk->data;
data->chunk[i].len = chunk->data_size;
data->data_size += chunk->data_size;
}
ASSERT(i == data->num_chunks);
return data;
}
static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id,
SPICE_ADDRESS addr)
{
RedDataChunk chunks;
QXLImage *qxl;
SpiceImage *red;
size_t bitmap_size, size;
uint8_t qxl_flags;
if (addr == 0) {
return NULL;
}
qxl = (QXLImage *)get_virt(slots, addr, sizeof(*qxl), group_id);
red = spice_new0(SpiceImage, 1);
red->descriptor.id = qxl->descriptor.id;
red->descriptor.type = qxl->descriptor.type;
red->descriptor.flags = 0;
if (qxl->descriptor.flags & QXL_IMAGE_HIGH_BITS_SET) {
red->descriptor.flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET;
}
if (qxl->descriptor.flags & QXL_IMAGE_CACHE) {
red->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME;
}
red->descriptor.width = qxl->descriptor.width;
red->descriptor.height = qxl->descriptor.height;
switch (red->descriptor.type) {
case SPICE_IMAGE_TYPE_BITMAP:
red->u.bitmap.format = qxl->bitmap.format;
qxl_flags = qxl->bitmap.flags;
if (qxl_flags & QXL_BITMAP_TOP_DOWN) {
red->u.bitmap.flags = SPICE_BITMAP_FLAGS_TOP_DOWN;
}
red->u.bitmap.x = qxl->bitmap.x;
red->u.bitmap.y = qxl->bitmap.y;
red->u.bitmap.stride = qxl->bitmap.stride;
if (qxl->bitmap.palette) {
QXLPalette *qp;
SpicePalette *rp;
int i, num_ents;
qp = (QXLPalette *)get_virt(slots, qxl->bitmap.palette,
sizeof(*qp), group_id);
num_ents = qp->num_ents;
validate_virt(slots, (intptr_t)qp->ents,
get_memslot_id(slots, qxl->bitmap.palette),
num_ents * sizeof(qp->ents[0]), group_id);
rp = spice_malloc_n_m(num_ents, sizeof(rp->ents[0]), sizeof(*rp));
rp->unique = qp->unique;
rp->num_ents = num_ents;
for (i = 0; i < num_ents; i++) {
rp->ents[i] = qp->ents[i];
}
red->u.bitmap.palette = rp;
red->u.bitmap.palette_id = rp->unique;
}
bitmap_size = red->u.bitmap.y * abs(red->u.bitmap.stride);
if (qxl_flags & QXL_BITMAP_DIRECT) {
red->u.bitmap.data = red_get_image_data_flat(slots, group_id,
qxl->bitmap.data,
bitmap_size);
} else {
size = red_get_data_chunks(slots, group_id,
&chunks, qxl->bitmap.data);
ASSERT(size == bitmap_size);
red->u.bitmap.data = red_get_image_data_chunked(slots, group_id,
&chunks);
red_put_data_chunks(&chunks);
}
if (qxl_flags & QXL_BITMAP_UNSTABLE) {
red->u.bitmap.data->flags |= SPICE_CHUNKS_FLAGS_UNSTABLE;
}
break;
case SPICE_IMAGE_TYPE_SURFACE:
red->u.surface.surface_id = qxl->surface_image.surface_id;
break;
case SPICE_IMAGE_TYPE_QUIC:
red->u.quic.data_size = qxl->quic.data_size;
size = red_get_data_chunks_ptr(slots, group_id,
get_memslot_id(slots, addr),
&chunks, (QXLDataChunk *)qxl->quic.data);
ASSERT(size == red->u.quic.data_size);
red->u.quic.data = red_get_image_data_chunked(slots, group_id,
&chunks);
red_put_data_chunks(&chunks);
break;
default:
red_error("%s: unknown type %d", __FUNCTION__, red->descriptor.type);
abort();
}
return red;
}
void red_put_image(SpiceImage *red)
{
if (red == NULL)
return;
switch (red->descriptor.type) {
case SPICE_IMAGE_TYPE_BITMAP:
if (red->u.bitmap.palette) {
free(red->u.bitmap.palette);
}
spice_chunks_destroy(red->u.bitmap.data);
break;
}
free(red);
}
static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id,
SpiceBrush *red, QXLBrush *qxl)
{
......@@ -264,18 +408,32 @@ static void red_get_brush_ptr(RedMemSlotInfo *slots, int group_id,
red->u.color = qxl->u.color;
break;
case SPICE_BRUSH_TYPE_PATTERN:
red->u.pattern.pat = qxl->u.pattern.pat;
red->u.pattern.pat = red_get_image(slots, group_id, qxl->u.pattern.pat);
red_get_point_ptr(&red->u.pattern.pos, &qxl->u.pattern.pos);
break;
}
}
static void red_put_brush(SpiceBrush *red)
{
switch (red->type) {
case SPICE_BRUSH_TYPE_PATTERN:
red_put_image(red->u.pattern.pat);
break;
}
}
static void red_get_qmask_ptr(RedMemSlotInfo *slots, int group_id,
SpiceQMask *red, QXLQMask *qxl)
{
red->flags = qxl->flags;
red_get_point_ptr(&red->pos, &qxl->pos);
red->bitmap = qxl->bitmap;
red->bitmap = red_get_image(slots, group_id, qxl->bitmap);
}
static void red_put_qmask(SpiceQMask *red)
{
red_put_image(red->bitmap);
}
static void red_get_fill_ptr(RedMemSlotInfo *slots, int group_id,
......@@ -286,10 +444,16 @@ static void red_get_fill_ptr(RedMemSlotInfo *slots, int group_id,
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
}
static void red_put_fill(SpiceFill *red)
{
red_put_brush(&red->brush);
red_put_qmask(&red->mask);
}
static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id,
SpiceOpaque *red, QXLOpaque *qxl)
{
red->src_bitmap = qxl->src_bitmap;
red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap);
red_get_rect_ptr(&red->src_area, &qxl->src_area);
red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
red->rop_descriptor = qxl->rop_descriptor;
......@@ -297,41 +461,65 @@ static void red_get_opaque_ptr(RedMemSlotInfo *slots, int group_id,
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
}
static void red_put_opaque(SpiceOpaque *red)
{
red_put_image(red->src_bitmap);
red_put_brush(&red->brush);
red_put_qmask(&red->mask);
}
static void red_get_copy_ptr(RedMemSlotInfo *slots, int group_id,
SpiceCopy *red, QXLCopy *qxl)
{
red->src_bitmap = qxl->src_bitmap;
red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap);
red_get_rect_ptr(&red->src_area, &qxl->src_area);
red->rop_descriptor = qxl->rop_descriptor;
red->scale_mode = qxl->scale_mode;
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
}
static void red_put_copy(SpiceCopy *red)
{
red_put_image(red->src_bitmap);
red_put_qmask(&red->mask);
}
static void red_get_blend_ptr(RedMemSlotInfo *slots, int group_id,
SpiceBlend *red, QXLBlend *qxl)
{
red->src_bitmap = qxl->src_bitmap;
red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap);
red_get_rect_ptr(&red->src_area, &qxl->src_area);
red->rop_descriptor = qxl->rop_descriptor;
red->scale_mode = qxl->scale_mode;
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
}
static void red_put_blend(SpiceBlend *red)
{
red_put_image(red->src_bitmap);
red_put_qmask(&red->mask);
}
static void red_get_transparent_ptr(RedMemSlotInfo *slots, int group_id,
SpiceTransparent *red, QXLTransparent *qxl)
{
red->src_bitmap = qxl->src_bitmap;
red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap);
red_get_rect_ptr(&red->src_area, &qxl->src_area);
red->src_color = qxl->src_color;
red->true_color = qxl->true_color;
}
static void red_put_transparent(SpiceTransparent *red)
{
red_put_image(red->src_bitmap);
}
static void red_get_alpha_blend_ptr(RedMemSlotInfo *slots, int group_id,
SpiceAlphaBlnd *red, QXLAlphaBlnd *qxl)
{
red->alpha_flags = qxl->alpha_flags;
red->alpha = qxl->alpha;
red->src_bitmap = qxl->src_bitmap;
red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap);
red_get_rect_ptr(&red->src_area, &qxl->src_area);
}
......@@ -339,14 +527,19 @@ static void red_get_alpha_blend_ptr_compat(RedMemSlotInfo *slots, int group_id,
SpiceAlphaBlnd *red, QXLCompatAlphaBlnd *qxl)
{
red->alpha = qxl->alpha;
red->src_bitmap = qxl->src_bitmap;
red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap);
red_get_rect_ptr(&red->src_area, &qxl->src_area);
}
static void red_put_alpha_blend(SpiceAlphaBlnd *red)
{
red_put_image(red->src_bitmap);
}
static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
SpiceRop3 *red, QXLRop3 *qxl)
{
red->src_bitmap = qxl->src_bitmap;
red->src_bitmap = red_get_image(slots, group_id, qxl->src_bitmap);
red_get_rect_ptr(&red->src_area, &qxl->src_area);
red_get_brush_ptr(slots, group_id, &red->brush, &qxl->brush);
red->rop3 = qxl->rop3;
......@@ -354,6 +547,13 @@ static void red_get_rop3_ptr(RedMemSlotInfo *slots, int group_id,
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
}
static void red_put_rop3(SpiceRop3 *red)
{
red_put_image(red->src_bitmap);
red_put_brush(&red->brush);
red_put_qmask(&red->mask);
}
static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id,
SpiceStroke *red, QXLStroke *qxl)
{
......@@ -371,8 +571,9 @@ static void red_get_stroke_ptr(RedMemSlotInfo *slots, int group_id,
red->back_mode = qxl->back_mode;
}
static void red_put_stroke_ptr(SpiceStroke *red)
static void red_put_stroke(SpiceStroke *red)
{
red_put_brush(&red->brush);
free(red->path);
}
......@@ -465,6 +666,8 @@ static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id,
static void red_put_text_ptr(SpiceText *red)
{
free(red->str);
red_put_brush(&red->fore_brush);
red_put_brush(&red->back_brush);
}
static void red_get_whiteness_ptr(RedMemSlotInfo *slots, int group_id,
......@@ -473,18 +676,33 @@ static void red_get_whiteness_ptr(RedMemSlotInfo *slots, int group_id,
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
}
static void red_put_whiteness(SpiceWhiteness *red)
{
red_put_qmask(&red->mask);
}
static void red_get_blackness_ptr(RedMemSlotInfo *slots, int group_id,
SpiceBlackness *red, QXLBlackness *qxl)
{
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
}
static void red_put_blackness(SpiceWhiteness *red)
{
red_put_qmask(&red->mask);
}
static void red_get_invers_ptr(RedMemSlotInfo *slots, int group_id,
SpiceInvers *red, QXLInvers *qxl)
{
red_get_qmask_ptr(slots, group_id, &red->mask, &qxl->mask);
}
static void red_put_invers(SpiceWhiteness *red)
{
red_put_qmask(&red->mask);
}
static void red_get_clip_ptr(RedMemSlotInfo *slots, int group_id,
SpiceClip *red, QXLClip *qxl)
{
......@@ -573,7 +791,7 @@ void red_get_drawable(RedMemSlotInfo *slots, int group_id,
red_get_whiteness_ptr(slots, group_id, &red->u.whiteness, &qxl->u.whiteness);
break;
default:
red_error("unknown type");
red_error("%s: unknown type %d", __FUNCTION__, red->type);
break;
};
}
......@@ -637,7 +855,7 @@ void red_get_compat_drawable(RedMemSlotInfo *slots, int group_id,
red_get_whiteness_ptr(slots, group_id, &red->u.whiteness, &qxl->u.whiteness);
break;
default:
red_error("unknown type");
red_error("%s: unknown type %d", __FUNCTION__, red->type);
break;
};
}
......@@ -646,12 +864,42 @@ void red_put_drawable(RedDrawable *red)
{
red_put_clip(&red->clip);