summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/canvas_base.c21
-rw-r--r--common/gdi_canvas.c13
-rw-r--r--common/gl_canvas.c12
-rw-r--r--python_modules/demarshal.py51
-rw-r--r--server/red_parse_qxl.c9
-rw-r--r--server/red_worker.c7
-rw-r--r--spice.proto2
-rw-r--r--spice1.proto4
8 files changed, 58 insertions, 61 deletions
diff --git a/common/canvas_base.c b/common/canvas_base.c
index 53d13f25..a0429a6a 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -3062,7 +3062,6 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
stroke_fill_spans,
stroke_fill_rects
};
- SpicePathSeg *seg;
StrokeLines lines;
unsigned int i;
int dashed;
@@ -3165,24 +3164,22 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
CANVAS_ERROR("invalid brush type");
}
- seg = (SpicePathSeg*)stroke->path->segments;
-
stroke_lines_init(&lines);
for (i = 0; i < stroke->path->num_segments; i++) {
- uint32_t flags = seg->flags;
- SpicePointFix* point = seg->points;
- SpicePointFix* end_point = point + seg->count;
- ASSERT(point < end_point);
- seg = (SpicePathSeg*)end_point;
+ SpicePathSeg *seg = stroke->path->segments[i];
+ SpicePointFix* point, *end_point;
+
+ point = seg->points;
+ end_point = point + seg->count;
- if (flags & SPICE_PATH_BEGIN) {
+ if (seg->flags & SPICE_PATH_BEGIN) {
stroke_lines_draw(&lines, (lineGC *)&gc, dashed);
stroke_lines_append_fix(&lines, point);
point++;
}
- if (flags & SPICE_PATH_BEZIER) {
+ if (seg->flags & SPICE_PATH_BEZIER) {
ASSERT((point - end_point) % 3 == 0);
for (; point + 2 < end_point; point += 3) {
stroke_lines_append_bezier(&lines,
@@ -3196,8 +3193,8 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
stroke_lines_append_fix(&lines, point);
}
}
- if (flags & SPICE_PATH_END) {
- if (flags & SPICE_PATH_CLOSE) {
+ if (seg->flags & SPICE_PATH_END) {
+ if (seg->flags & SPICE_PATH_CLOSE) {
stroke_lines_append(&lines,
lines.points[0].x, lines.points[0].y);
}
diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c
index e3489941..9c520024 100644
--- a/common/gdi_canvas.c
+++ b/common/gdi_canvas.c
@@ -310,17 +310,14 @@ uint32_t raster_ops[] = {
static void set_path(GdiCanvas *canvas, SpicePath *s)
{
- SpicePathSeg* seg = (SpicePathSeg*)s->segments;
unsigned int i;
for (i = 0; i < s->num_segments; i++) {
- uint32_t flags = seg->flags;
+ SpicePathSeg* seg = s->segments[0];
SpicePointFix* point = seg->points;
SpicePointFix* end_point = point + seg->count;
- ASSERT(point < end_point);
- seg = (SpicePathSeg*)end_point;
- if (flags & SPICE_PATH_BEGIN) {
+ if (seg->flags & SPICE_PATH_BEGIN) {
BeginPath(canvas->dc);
if (!MoveToEx(canvas->dc, (int)fix_to_double(point->x), (int)fix_to_double(point->y),
NULL)) {
@@ -330,7 +327,7 @@ static void set_path(GdiCanvas *canvas, SpicePath *s)
point++;
}
- if (flags & SPICE_PATH_BEZIER) {
+ if (seg->flags & SPICE_PATH_BEZIER) {
ASSERT((point - end_point) % 3 == 0);
for (; point + 2 < end_point; point += 3) {
POINT points[3];
@@ -355,9 +352,9 @@ static void set_path(GdiCanvas *canvas, SpicePath *s)
}
}
- if (flags & SPICE_PATH_END) {
+ if (seg->flags & SPICE_PATH_END) {
- if (flags & SPICE_PATH_CLOSE) {
+ if (seg->flags & SPICE_PATH_CLOSE) {
if (!CloseFigure(canvas->dc)) {
CANVAS_ERROR("CloseFigure failed");
}
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
index 3e02a25e..f0e10dd7 100644
--- a/common/gl_canvas.c
+++ b/common/gl_canvas.c
@@ -115,20 +115,18 @@ static GLCPath get_path(GLCanvas *canvas, SpicePath *s)
{
GLCPath path = glc_path_create(canvas->glc);
int i;
- SpicePathSeg* seg = (SpicePathSeg*)s->segments;
for (i = 0; i < s->num_segments; i++) {
- uint32_t flags = seg->flags;
+ SpicePathSeg* seg = s->segments[i];
SpicePointFix* point = seg->points;
SpicePointFix* end_point = point + seg->count;
- seg = (SpicePathSeg*)end_point;
- if (flags & SPICE_PATH_BEGIN) {
+ if (seg->flags & SPICE_PATH_BEGIN) {
glc_path_move_to(path, fix_to_double(point->x), fix_to_double(point->y));
point++;
}
- if (flags & SPICE_PATH_BEZIER) {
+ if (seg->flags & SPICE_PATH_BEZIER) {
ASSERT((point - end_point) % 3 == 0);
for (; point + 2 < end_point; point += 3) {
glc_path_curve_to(path,
@@ -141,8 +139,8 @@ static GLCPath get_path(GLCanvas *canvas, SpicePath *s)
glc_path_line_to(path, fix_to_double(point->x), fix_to_double(point->y));
}
}
- if (flags & SPICE_PATH_END) {
- if (flags & SPICE_PATH_CLOSE) {
+ if (seg->flags & SPICE_PATH_END) {
+ if (seg->flags & SPICE_PATH_CLOSE) {
glc_path_close(path);
}
}
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 606b926c..bd7660df 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -47,13 +47,16 @@ def write_parser_helpers(writer):
swap = "SPICE_BYTESWAP%d" % size
if size == 8:
writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
+ writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = val" % (type))
else:
writer.macro("read_%s" % type, "ptr", "((%s_t)%s(*((%s_t *)(ptr)))" % (type, swap, utype))
+ writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = %s((%s_t)val)" % (utype, swap, utype))
writer.writeln("#else")
for size in [8, 16, 32, 64]:
for sign in ["", "u"]:
type = "%sint%d" % (sign, size)
writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
+ writer.macro("write_%s" % type, "ptr, val", "(*((%s_t *)(ptr))) = val" % type)
writer.writeln("#endif")
for size in [8, 16, 32, 64]:
@@ -96,6 +99,15 @@ def write_read_primitive(writer, start, container, name, scope):
writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type()))
return var
+def write_write_primitive(writer, start, container, name, val):
+ m = container.lookup_member(name)
+ assert(m.is_primitive())
+ writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size"))
+
+ var = "%s__value" % (name)
+ writer.statement("write_%s(pos, %s)" % (m.member_type.primitive_type(), val))
+ return var
+
def write_read_primitive_item(writer, item, scope):
assert(item.type.is_primitive())
writer.assign("pos", item.get_position())
@@ -280,6 +292,9 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
element_type = array.element_type
if array.is_bytes_length():
nelements = "%s__nbytes" %(item.prefix)
+ real_nelements = "%s__nelements" %(item.prefix)
+ if not parent_scope.variable_defined(real_nelements):
+ parent_scope.variable_def("uint32_t", real_nelements)
else:
nelements = "%s__nelements" %(item.prefix)
if not parent_scope.variable_defined(nelements):
@@ -315,6 +330,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
is_byte_size = True
v = write_read_primitive(writer, start, container, array.size[1], scope)
writer.assign(nelements, v)
+ writer.assign(real_nelements, 0)
elif array.is_cstring_length():
writer.todo("cstring array size type not handled yet")
else:
@@ -389,6 +405,8 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
with writer.index(no_block = is_byte_size) as index:
with writer.while_loop("%s < %s" % (start2, start2_end) ) if is_byte_size else writer.for_loop(index, nelements) as scope:
+ if is_byte_size:
+ writer.increment(real_nelements, 1)
write_validate_item(writer, container, element_item, scope, parent_scope, start2,
want_element_nw_size, want_mem_size, want_extra_size)
@@ -405,6 +423,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
writer.increment(start2, start_increment)
if is_byte_size:
writer.error_check("%s != %s" % (start2, start2_end))
+ write_write_primitive(writer, start, container, array.size[1], real_nelements)
def write_validate_struct_item(writer, container, item, scope, parent_scope, start,
want_nw_size, want_mem_size, want_extra_size):
@@ -613,11 +632,9 @@ class SubDemarshallingDestination(DemarshallingDestination):
def get_ref(self, member):
return self.parent_dest.get_ref(self.member) + "." + member
-def read_array_len(writer, prefix, array, dest, scope, handles_bytes = False):
- if array.is_bytes_length():
- nelements = "%s__nbytes" % prefix
- else:
- nelements = "%s__nelements" % prefix
+# Note: during parsing, byte_size types have been converted to count during validation
+def read_array_len(writer, prefix, array, dest, scope):
+ nelements = "%s__nelements" % prefix
if dest.is_toplevel():
return nelements # Already there for toplevel, need not recalculate
element_type = array.element_type
@@ -645,9 +662,7 @@ def read_array_len(writer, prefix, array, dest, scope, handles_bytes = False):
else:
writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v))
elif array.is_bytes_length():
- if not handles_bytes:
- raise NotImplementedError("handling of bytes() not supported here yet")
- writer.assign(nelements, array.size[1])
+ writer.assign(nelements, dest.get_ref(array.size[2]))
else:
raise NotImplementedError("TODO array size type not handled yet")
return nelements
@@ -758,24 +773,16 @@ def write_array_parser(writer, nelements, array, dest, scope):
writer.increment("in", nelements)
writer.increment("end", nelements)
else:
- if is_byte_size:
- real_nelements = nelements[:-len("nbytes")] + "nelements"
- scope.variable_def("uint8_t *", "array_end")
- scope.variable_def("uint32_t", real_nelements)
- writer.assign("array_end", "end + %s" % nelements)
- writer.assign(real_nelements, 0)
if array.has_attr("ptr_array"):
scope.variable_def("void **", "ptr_array")
scope.variable_def("int", "ptr_array_index")
writer.assign("ptr_array_index", 0)
writer.assign("ptr_array", "(void **)end")
writer.increment("end", "sizeof(void *) * %s" % nelements)
- with writer.index(no_block = is_byte_size) as index:
- with writer.while_loop("end < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope:
+ with writer.index() as index:
+ with writer.for_loop(index, nelements) as array_scope:
if array.has_attr("ptr_array"):
writer.statement("ptr_array[ptr_array_index++] = end")
- if is_byte_size:
- writer.increment(real_nelements, 1)
if element_type.is_primitive():
writer.statement("*(%s *)end = consume_%s(&in)" % (element_type.c_type(), element_type.primitive_type()))
writer.increment("end", element_type.sizeof())
@@ -786,8 +793,6 @@ def write_array_parser(writer, nelements, array, dest, scope):
if array.has_attr("ptr_array"):
writer.comment("Align ptr_array element to 4 bytes").newline()
writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)")
- if is_byte_size:
- writer.assign(dest.get_ref(array.size[2]), real_nelements)
def write_parse_pointer(writer, t, at_end, dest, member_name, scope):
as_c_ptr = t.has_attr("c_ptr")
@@ -831,14 +836,14 @@ def write_member_parser(writer, container, member, dest, scope):
writer.increment("end", t.sizeof())
else:
if member.has_attr("bytes_count"):
- scope.variable_def("uint32_t", member.name);
- dest_var = member.name
+ print member.attributes["bytes_count"]
+ dest_var = dest.get_ref(member.attributes["bytes_count"][0])
else:
dest_var = dest.get_ref(member.name)
writer.assign(dest_var, "consume_%s(&in)" % (t.primitive_type()))
#TODO validate e.g. flags and enums
elif t.is_array():
- nelements = read_array_len(writer, member.name, t, dest, scope, handles_bytes = True)
+ nelements = read_array_len(writer, member.name, t, dest, scope)
if member.has_attr("as_ptr") and t.element_type.is_fixed_nw_size():
writer.comment("use array as pointer").newline()
writer.assign(dest.get_ref(member.name), "(%s *)in" % t.element_type.c_type())
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index d38cad7b..56f17dc8 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -153,7 +153,7 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id,
bool free_data;
QXLPath *qxl;
SpicePath *red;
- size_t size, mem_size, mem_size2, dsize;
+ size_t size, mem_size, mem_size2, dsize, segment_size;
int n_segments;
int i;
uint32_t count;
@@ -173,7 +173,8 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id,
while (start < end) {
n_segments++;
count = start->count;
- mem_size += sizeof(SpicePathSeg) + count * sizeof(SpicePointFix);
+ segment_size = sizeof(SpicePathSeg) + count * sizeof(SpicePointFix);
+ mem_size += sizeof(SpicePathSeg *) + SPICE_ALIGN(segment_size, 4);
start = (QXLPathSeg*)(&start->points[count]);
}
@@ -182,11 +183,11 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id,
start = (QXLPathSeg*)data;
end = (QXLPathSeg*)(data + size);
- seg = (SpicePathSeg*)red->segments;
+ seg = (SpicePathSeg*)&red->segments[n_segments];
n_segments = 0;
mem_size2 = sizeof(*red);
while (start < end) {
- n_segments++;
+ red->segments[n_segments++] = seg;
count = start->count;
/* Protect against overflow in size calculations before
diff --git a/server/red_worker.c b/server/red_worker.c
index ff0a049e..255a46e7 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -2296,9 +2296,10 @@ static int is_equal_path(RedWorker *worker, SpicePath *path1, SpicePath *path2)
if (path1->num_segments != path2->num_segments)
return FALSE;
- seg1 = (SpicePathSeg*)&path1->segments[0];
- seg2 = (SpicePathSeg*)&path2->segments[0];
for (i = 0; i < path1->num_segments; i++) {
+ seg1 = path1->segments[i];
+ seg2 = path2->segments[i];
+
if (seg1->flags != seg2->flags ||
seg1->count != seg2->count) {
return FALSE;
@@ -2309,8 +2310,6 @@ static int is_equal_path(RedWorker *worker, SpicePath *path1, SpicePath *path2)
return FALSE;
}
}
- seg1 = (SpicePathSeg*)(&seg1->points[seg1->count]);
- seg2 = (SpicePathSeg*)(&seg2->points[seg2->count]);
}
return TRUE;
diff --git a/spice.proto b/spice.proto
index 8df12387..e4376300 100644
--- a/spice.proto
+++ b/spice.proto
@@ -393,7 +393,7 @@ struct PathSegment {
struct Path {
uint32 num_segments;
- PathSegment segments[num_segments] @end;
+ PathSegment segments[num_segments] @ptr_array;
};
struct Clip {
diff --git a/spice1.proto b/spice1.proto
index 982f6668..b49371ad 100644
--- a/spice1.proto
+++ b/spice1.proto
@@ -374,8 +374,8 @@ struct PathSegment {
} @ctype(SpicePathSeg);
struct Path {
- uint32 segments_size @bytes_count;
- PathSegment segments[bytes(segments_size, num_segments)] @end;
+ uint32 segments_size @bytes_count(num_segments);
+ PathSegment segments[bytes(segments_size, num_segments)] @ptr_array;
};
struct Clip {