Hi<br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Nov 14, 2012 at 9:36 PM, Alon Levy <span dir="ltr"><<a href="mailto:alevy@redhat.com" target="_blank">alevy@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
This is a second attempt at recording commands received from the qxl<br>
device. The visitor allows more code to be shared between the device to<br>
spice struct verifier and copier and the logger.<br></blockquote><div><br>I missed the first version somehow.<br> <br>So a bit of context could be helpful :) Here we are changing the code that read cursor cmds from qxl memory into RedCursorCmd *red<br>
</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
---<br>
Does this look doable? it's the beginning of a second try at recording qxl<br>
traffic for debugging and development.<br></blockquote><div><br>Yeah, we really want that.<br> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

 server/red_parse_qxl.c | 142 ++++++++++++++++++++++++++++++++++++-------------<br>
 1 file changed, 104 insertions(+), 38 deletions(-)<br>
<br>
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c<br>
index 82463e1..298a334 100644<br>
--- a/server/red_parse_qxl.c<br>
+++ b/server/red_parse_qxl.c<br>
@@ -1251,8 +1251,88 @@ void red_put_surface_cmd(RedSurfaceCmd *red)<br>
     /* nothing yet */<br>
 }<br>
<br>
-static int red_get_cursor(RedMemSlotInfo *slots, int group_id,<br>
-                          SpiceCursor *red, QXLPHYSICAL addr)<br>
+typedef struct CursorCmdVisitor {<br>
+    RedMemSlotInfo *slots;<br>
+    int group_id;<br>
+    void *opaque;<br></blockquote><div><br>Instead of opaque pointer we could have each visitor implementation derive from that base visitor, but this isn't incompatible anyway, a matter of taste perhaps.<br><br></div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+    void (*visit_cursor_cmd)(void *opaque, QXLCursorCmd *qxl);<br></blockquote><div><br>And opaque could be "self" instead :)<br> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+    void (*visit_cursor_set_1)(void *opaque, QXLPoint16 *position, uint8_t visible);<br>
+    void (*visit_cursor_set_2)(void *opaque, QXLCursorHeader *header,<br>
+                               uint32_t data_size, bool free_data, size_t size,<br>
+                               uint8_t *data);<br>
+    void (*visit_cursor_move)(void *opaque, QXLPoint16 *position);<br>
+    void (*visit_cursor_trail)(void *opaque, uint16_t length, uint16_t frequency);<br>
+} CursorCmdVisitor;<br>
+<br>
+static void red_put_cursor(SpiceCursor *red)<br>
+{<br>
+    free(red->data);<br>
+}<br>
<br></blockquote><div>this function could go bellow, since it isn't used by CursorCmdVisitor. Actually it could even be removed perhaps...<br> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+static void copy_visit_cursor_cmd(void *opaque, QXLCursorCmd *qxl)<br>
+{<br>
+    RedCursorCmd *cmd = opaque;<br>
+<br>
+    cmd->release_info     = &qxl->release_info;<br>
+    cmd->type = qxl->type;<br>
+}<br>
+<br>
+void copy_visit_cursor_set_1(void *opaque, QXLPoint16 *position, uint8_t visible)<br>
+{<br>
+    RedCursorCmd *red = opaque;<br>
+<br>
+    red_get_point16_ptr(&red->u.set.position, position);<br>
+    red->u.set.visible  = visible;<br>
+}<br>
+<br>
+static void copy_visit_cursor_set_2(void *opaque, QXLCursorHeader *header,<br>
+                                    uint32_t data_size, bool free_data, size_t size,<br>
+                                    uint8_t *data)<br>
+{<br>
+    RedCursorCmd *cmd = opaque;<br>
+    SpiceCursor *red = &cmd->u.set.shape;<br>
+<br>
+    red->header.unique     = header->unique;<br>
+    red->header.type       = header->type;<br>
+    red->header.width      = header->width;<br>
+    red->header.height     = header->height;<br>
+    red->header.hot_spot_x = header->hot_spot_x;<br>
+    red->header.hot_spot_y = header->hot_spot_y;<br>
+<br>
+    red->flags = 0;<br>
+    red->data_size = data_size;<br>
+    if (free_data) {<br>
+        red->data = data;<br>
+    } else {<br>
+        red->data = spice_malloc(size);<br>
+        memcpy(red->data, data, size);<br>
+    }<br>
+}<br>
+<br>
+void copy_visit_cursor_move(void *opaque, QXLPoint16 *position)<br>
+{<br>
+    RedCursorCmd *red = opaque;<br>
+<br>
+    red_get_point16_ptr(&red->u.position, position);<br>
+}<br>
+<br>
+void copy_visit_cursor_trail(void *opaque, uint16_t length, uint16_t frequency)<br>
+{<br>
+    RedCursorCmd *red = opaque;<br>
+<br>
+    red->u.trail.length    = length;<br>
+    red->u.trail.frequency = frequency;<br>
+}<br>
+<br>
+CursorCmdVisitor copy_cursor_visitor = {<br>
+    .visit_cursor_cmd = copy_visit_cursor_cmd,<br>
+    .visit_cursor_set_1 = copy_visit_cursor_set_1,<br>
+    .visit_cursor_set_2 = copy_visit_cursor_set_2,<br>
+    .visit_cursor_move = copy_visit_cursor_move,<br>
+    .visit_cursor_trail = copy_visit_cursor_trail,<br>
+};<br>
+<br>
+static int visit_cursor_cmd_set(CursorCmdVisitor *v, QXLPHYSICAL addr)<br>
 {<br>
     QXLCursor *qxl;<br>
     RedDataChunk chunks;<br>
@@ -1261,69 +1341,55 @@ static int red_get_cursor(RedMemSlotInfo *slots, int group_id,<br>
     bool free_data;<br>
     int error;<br>
<br>
-    qxl = (QXLCursor *)get_virt(slots, addr, sizeof(*qxl), group_id, &error);<br>
+    qxl = (QXLCursor *)get_virt(v->slots, addr, sizeof(*qxl), v->group_id, &error);<br>
     if (error) {<br>
         return 1;<br>
     }<br>
<br>
-    red->header.unique     = qxl->header.unique;<br>
-    red->header.type       = qxl->header.type;<br>
-    red->header.width      = qxl->header.width;<br>
-    red->header.height     = qxl->header.height;<br>
-    red->header.hot_spot_x = qxl->header.hot_spot_x;<br>
-    red->header.hot_spot_y = qxl->header.hot_spot_y;<br>
-<br>
-    red->flags = 0;<br>
-    red->data_size = qxl->data_size;<br>
-    size = red_get_data_chunks_ptr(slots, group_id,<br>
-                                   get_memslot_id(slots, addr),<br>
+    size = red_get_data_chunks_ptr(v->slots, v->group_id,<br>
+                                   get_memslot_id(v->slots, addr),<br>
                                    &chunks, &qxl->chunk);<br>
     data = red_linearize_chunk(&chunks, size, &free_data);<br>
     red_put_data_chunks(&chunks);<br>
-    if (free_data) {<br>
-        red->data = data;<br>
-    } else {<br>
-        red->data = spice_malloc(size);<br>
-        memcpy(red->data, data, size);<br>
-    }<br>
+    v->visit_cursor_set_2(v->opaque, &qxl->header, qxl->data_size,<br>
+                          free_data, size, data);<br>
     return 0;<br>
 }<br>
<br>
-static void red_put_cursor(SpiceCursor *red)<br>
-{<br>
-    free(red->data);<br>
-}<br>
-<br>
-int red_get_cursor_cmd(RedMemSlotInfo *slots, int group_id,<br>
-                       RedCursorCmd *red, QXLPHYSICAL addr)<br>
+int visit_cursor_cmd(CursorCmdVisitor *v, QXLPHYSICAL addr)<br>
 {<br>
     QXLCursorCmd *qxl;<br>
     int error;<br>
<br>
-    qxl = (QXLCursorCmd *)get_virt(slots, addr, sizeof(*qxl), group_id, &error);<br>
+    qxl = (QXLCursorCmd *)get_virt(v->slots, addr, sizeof(*qxl), v->group_id, &error);<br>
     if (error) {<br>
         return error;<br>
     }<br>
-    red->release_info     = &qxl->release_info;<br>
-<br>
-    red->type = qxl->type;<br>
-    switch (red->type) {<br>
+    v->visit_cursor_cmd(v->opaque, qxl);<br>
+    switch (qxl->type) {<br>
     case QXL_CURSOR_SET:<br>
-        red_get_point16_ptr(&red->u.set.position, &qxl->u.set.position);<br>
-        red->u.set.visible  = qxl->u.set.visible;<br>
-        error = red_get_cursor(slots, group_id,  &red->u.set.shape, qxl->u.set.shape);<br>
+        v->visit_cursor_set_1(v->opaque, &qxl->u.set.position, qxl->u.set.visible);<br>
+        error = visit_cursor_cmd_set(v, qxl->u.set.shape);<br></blockquote><div><br>Is there a valid reason why set_1 and set_2 are splitted? Looks to me that it could be the same function eventually? And merge back visit_cursor_cmd_set in it's caller.<br>
<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
         break;<br>
     case QXL_CURSOR_MOVE:<br>
-        red_get_point16_ptr(&red->u.position, &qxl->u.position);<br>
+        v->visit_cursor_move(v->opaque, &qxl->u.position);<br>
         break;<br>
     case QXL_CURSOR_TRAIL:<br>
-        red->u.trail.length    = qxl->u.trail.length;<br>
-        red->u.trail.frequency = qxl->u.trail.frequency;<br>
+        v->visit_cursor_trail(v->opaque, qxl->u.trail.length, qxl->u.trail.frequency);<br>
         break;<br>
     }<br>
     return error;<br>
 }<br>
<br>
+int red_get_cursor_cmd(RedMemSlotInfo *slots, int group_id,<br>
+                       RedCursorCmd *red, QXLPHYSICAL addr)<br>
+{<br>
+    copy_cursor_visitor.slots = slots;<br>
+    copy_cursor_visitor.group_id = group_id;<br>
+    copy_cursor_visitor.opaque = red;<br>
+    return visit_cursor_cmd(&copy_cursor_visitor, addr);<br>
+}<br>
+<br>
 void red_put_cursor_cmd(RedCursorCmd *red)<br>
 {<br>
     switch (red->type) {<br>
<span class=""><font color="#888888">--<br>
1.8.0<br>
<br>
_______________________________________________<br>
Spice-devel mailing list<br>
<a href="mailto:Spice-devel@lists.freedesktop.org">Spice-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/spice-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/spice-devel</a><br>
</font></span></blockquote></div><br>Otherwise, looks "fine". I suppose you want to take similar approach for other commands? It would be nice to see some bits of the curosr logger visitor as an example of where this is going. Do you have a wip branch?<br>
<br>cheers<br><br>-- <br>Marc-André Lureau<br>
</div>