qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

qxl-logger.c (9334B)


      1 /*
      2  * qxl command logging -- for debug purposes
      3  *
      4  * Copyright (C) 2010 Red Hat, Inc.
      5  *
      6  * maintained by Gerd Hoffmann <kraxel@redhat.com>
      7  *
      8  * This program is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU General Public License as
     10  * published by the Free Software Foundation; either version 2 or
     11  * (at your option) version 3 of the License.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, see <http://www.gnu.org/licenses/>.
     20  */
     21 
     22 #include "qemu/osdep.h"
     23 #include "qemu/timer.h"
     24 #include "qxl.h"
     25 
     26 static const char *const qxl_type[] = {
     27     [ QXL_CMD_NOP ]     = "nop",
     28     [ QXL_CMD_DRAW ]    = "draw",
     29     [ QXL_CMD_UPDATE ]  = "update",
     30     [ QXL_CMD_CURSOR ]  = "cursor",
     31     [ QXL_CMD_MESSAGE ] = "message",
     32     [ QXL_CMD_SURFACE ] = "surface",
     33 };
     34 
     35 static const char *const qxl_draw_type[] = {
     36     [ QXL_DRAW_NOP         ] = "nop",
     37     [ QXL_DRAW_FILL        ] = "fill",
     38     [ QXL_DRAW_OPAQUE      ] = "opaque",
     39     [ QXL_DRAW_COPY        ] = "copy",
     40     [ QXL_COPY_BITS        ] = "copy-bits",
     41     [ QXL_DRAW_BLEND       ] = "blend",
     42     [ QXL_DRAW_BLACKNESS   ] = "blackness",
     43     [ QXL_DRAW_WHITENESS   ] = "whitemess",
     44     [ QXL_DRAW_INVERS      ] = "invers",
     45     [ QXL_DRAW_ROP3        ] = "rop3",
     46     [ QXL_DRAW_STROKE      ] = "stroke",
     47     [ QXL_DRAW_TEXT        ] = "text",
     48     [ QXL_DRAW_TRANSPARENT ] = "transparent",
     49     [ QXL_DRAW_ALPHA_BLEND ] = "alpha-blend",
     50 };
     51 
     52 static const char *const qxl_draw_effect[] = {
     53     [ QXL_EFFECT_BLEND            ] = "blend",
     54     [ QXL_EFFECT_OPAQUE           ] = "opaque",
     55     [ QXL_EFFECT_REVERT_ON_DUP    ] = "revert-on-dup",
     56     [ QXL_EFFECT_BLACKNESS_ON_DUP ] = "blackness-on-dup",
     57     [ QXL_EFFECT_WHITENESS_ON_DUP ] = "whiteness-on-dup",
     58     [ QXL_EFFECT_NOP_ON_DUP       ] = "nop-on-dup",
     59     [ QXL_EFFECT_NOP              ] = "nop",
     60     [ QXL_EFFECT_OPAQUE_BRUSH     ] = "opaque-brush",
     61 };
     62 
     63 static const char *const qxl_surface_cmd[] = {
     64    [ QXL_SURFACE_CMD_CREATE  ] = "create",
     65    [ QXL_SURFACE_CMD_DESTROY ] = "destroy",
     66 };
     67 
     68 static const char *const spice_surface_fmt[] = {
     69    [ SPICE_SURFACE_FMT_INVALID  ] = "invalid",
     70    [ SPICE_SURFACE_FMT_1_A      ] = "alpha/1",
     71    [ SPICE_SURFACE_FMT_8_A      ] = "alpha/8",
     72    [ SPICE_SURFACE_FMT_16_555   ] = "555/16",
     73    [ SPICE_SURFACE_FMT_16_565   ] = "565/16",
     74    [ SPICE_SURFACE_FMT_32_xRGB  ] = "xRGB/32",
     75    [ SPICE_SURFACE_FMT_32_ARGB  ] = "ARGB/32",
     76 };
     77 
     78 static const char *const qxl_cursor_cmd[] = {
     79    [ QXL_CURSOR_SET   ] = "set",
     80    [ QXL_CURSOR_MOVE  ] = "move",
     81    [ QXL_CURSOR_HIDE  ] = "hide",
     82    [ QXL_CURSOR_TRAIL ] = "trail",
     83 };
     84 
     85 static const char *const spice_cursor_type[] = {
     86    [ SPICE_CURSOR_TYPE_ALPHA   ] = "alpha",
     87    [ SPICE_CURSOR_TYPE_MONO    ] = "mono",
     88    [ SPICE_CURSOR_TYPE_COLOR4  ] = "color4",
     89    [ SPICE_CURSOR_TYPE_COLOR8  ] = "color8",
     90    [ SPICE_CURSOR_TYPE_COLOR16 ] = "color16",
     91    [ SPICE_CURSOR_TYPE_COLOR24 ] = "color24",
     92    [ SPICE_CURSOR_TYPE_COLOR32 ] = "color32",
     93 };
     94 
     95 static const char *qxl_v2n(const char *const n[], size_t l, int v)
     96 {
     97     if (v >= l || !n[v]) {
     98         return "???";
     99     }
    100     return n[v];
    101 }
    102 #define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value)
    103 
    104 static int qxl_log_image(PCIQXLDevice *qxl, QXLPHYSICAL addr, int group_id)
    105 {
    106     QXLImage *image;
    107     QXLImageDescriptor *desc;
    108 
    109     image = qxl_phys2virt(qxl, addr, group_id, sizeof(QXLImage));
    110     if (!image) {
    111         return 1;
    112     }
    113     desc = &image->descriptor;
    114     fprintf(stderr, " (id %" PRIx64 " type %d flags %d width %d height %d",
    115             desc->id, desc->type, desc->flags, desc->width, desc->height);
    116     switch (desc->type) {
    117     case SPICE_IMAGE_TYPE_BITMAP:
    118         fprintf(stderr, ", fmt %d flags %d x %d y %d stride %d"
    119                 " palette %" PRIx64 " data %" PRIx64,
    120                 image->bitmap.format, image->bitmap.flags,
    121                 image->bitmap.x, image->bitmap.y,
    122                 image->bitmap.stride,
    123                 image->bitmap.palette, image->bitmap.data);
    124         break;
    125     }
    126     fprintf(stderr, ")");
    127     return 0;
    128 }
    129 
    130 static void qxl_log_rect(QXLRect *rect)
    131 {
    132     fprintf(stderr, " %dx%d+%d+%d",
    133             rect->right - rect->left,
    134             rect->bottom - rect->top,
    135             rect->left, rect->top);
    136 }
    137 
    138 static int qxl_log_cmd_draw_copy(PCIQXLDevice *qxl, QXLCopy *copy,
    139                                  int group_id)
    140 {
    141     int ret;
    142 
    143     fprintf(stderr, " src %" PRIx64,
    144             copy->src_bitmap);
    145     ret = qxl_log_image(qxl, copy->src_bitmap, group_id);
    146     if (ret != 0) {
    147         return ret;
    148     }
    149     fprintf(stderr, " area");
    150     qxl_log_rect(&copy->src_area);
    151     fprintf(stderr, " rop %d", copy->rop_descriptor);
    152     return 0;
    153 }
    154 
    155 static int qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw, int group_id)
    156 {
    157     fprintf(stderr, ": surface_id %d type %s effect %s",
    158             draw->surface_id,
    159             qxl_name(qxl_draw_type, draw->type),
    160             qxl_name(qxl_draw_effect, draw->effect));
    161     switch (draw->type) {
    162     case QXL_DRAW_COPY:
    163         return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
    164     }
    165     return 0;
    166 }
    167 
    168 static int qxl_log_cmd_draw_compat(PCIQXLDevice *qxl, QXLCompatDrawable *draw,
    169                                    int group_id)
    170 {
    171     fprintf(stderr, ": type %s effect %s",
    172             qxl_name(qxl_draw_type, draw->type),
    173             qxl_name(qxl_draw_effect, draw->effect));
    174     if (draw->bitmap_offset) {
    175         fprintf(stderr, ": bitmap %d",
    176                 draw->bitmap_offset);
    177         qxl_log_rect(&draw->bitmap_area);
    178     }
    179     switch (draw->type) {
    180     case QXL_DRAW_COPY:
    181         return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
    182     }
    183     return 0;
    184 }
    185 
    186 static void qxl_log_cmd_surface(PCIQXLDevice *qxl, QXLSurfaceCmd *cmd)
    187 {
    188     fprintf(stderr, ": %s id %d",
    189             qxl_name(qxl_surface_cmd, cmd->type),
    190             cmd->surface_id);
    191     if (cmd->type == QXL_SURFACE_CMD_CREATE) {
    192         fprintf(stderr, " size %dx%d stride %d format %s (count %u, max %u)",
    193                 cmd->u.surface_create.width,
    194                 cmd->u.surface_create.height,
    195                 cmd->u.surface_create.stride,
    196                 qxl_name(spice_surface_fmt, cmd->u.surface_create.format),
    197                 qxl->guest_surfaces.count, qxl->guest_surfaces.max);
    198     }
    199     if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
    200         fprintf(stderr, " (count %u)", qxl->guest_surfaces.count);
    201     }
    202 }
    203 
    204 int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id)
    205 {
    206     QXLCursor *cursor;
    207 
    208     fprintf(stderr, ": %s",
    209             qxl_name(qxl_cursor_cmd, cmd->type));
    210     switch (cmd->type) {
    211     case QXL_CURSOR_SET:
    212         fprintf(stderr, " +%d+%d visible %s, shape @ 0x%" PRIx64,
    213                 cmd->u.set.position.x,
    214                 cmd->u.set.position.y,
    215                 cmd->u.set.visible ? "yes" : "no",
    216                 cmd->u.set.shape);
    217         cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id,
    218                                sizeof(QXLCursor));
    219         if (!cursor) {
    220             return 1;
    221         }
    222         fprintf(stderr, " type %s size %dx%d hot-spot +%d+%d"
    223                 " unique 0x%" PRIx64 " data-size %d",
    224                 qxl_name(spice_cursor_type, cursor->header.type),
    225                 cursor->header.width, cursor->header.height,
    226                 cursor->header.hot_spot_x, cursor->header.hot_spot_y,
    227                 cursor->header.unique, cursor->data_size);
    228         break;
    229     case QXL_CURSOR_MOVE:
    230         fprintf(stderr, " +%d+%d", cmd->u.position.x, cmd->u.position.y);
    231         break;
    232     }
    233     return 0;
    234 }
    235 
    236 int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext)
    237 {
    238     bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT;
    239     void *data;
    240     size_t datasz;
    241     int ret;
    242 
    243     if (!qxl->cmdlog) {
    244         return 0;
    245     }
    246     fprintf(stderr, "%" PRId64 " qxl-%d/%s:", qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
    247             qxl->id, ring);
    248     fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data,
    249             qxl_name(qxl_type, ext->cmd.type),
    250             compat ? "(compat)" : "");
    251 
    252     switch (ext->cmd.type) {
    253     case QXL_CMD_DRAW:
    254         datasz = compat ? sizeof(QXLCompatDrawable) : sizeof(QXLDrawable);
    255         break;
    256     case QXL_CMD_SURFACE:
    257         datasz = sizeof(QXLSurfaceCmd);
    258         break;
    259     case QXL_CMD_CURSOR:
    260         datasz = sizeof(QXLCursorCmd);
    261         break;
    262     default:
    263         goto out;
    264     }
    265     data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id, datasz);
    266     if (!data) {
    267         return 1;
    268     }
    269     switch (ext->cmd.type) {
    270     case QXL_CMD_DRAW:
    271         if (!compat) {
    272             ret = qxl_log_cmd_draw(qxl, data, ext->group_id);
    273         } else {
    274             ret = qxl_log_cmd_draw_compat(qxl, data, ext->group_id);
    275         }
    276         if (ret) {
    277             return ret;
    278         }
    279         break;
    280     case QXL_CMD_SURFACE:
    281         qxl_log_cmd_surface(qxl, data);
    282         break;
    283     case QXL_CMD_CURSOR:
    284         qxl_log_cmd_cursor(qxl, data, ext->group_id);
    285         break;
    286     }
    287 out:
    288     fprintf(stderr, "\n");
    289     return 0;
    290 }