2 * qxl command logging -- for debug purposes
4 * Copyright (C) 2010 Red Hat, Inc.
6 * maintained by Gerd Hoffmann <kraxel@redhat.com>
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.
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.
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/>.
22 #include "qemu/timer.h"
25 static const char *qxl_type
[] = {
26 [ QXL_CMD_NOP
] = "nop",
27 [ QXL_CMD_DRAW
] = "draw",
28 [ QXL_CMD_UPDATE
] = "update",
29 [ QXL_CMD_CURSOR
] = "cursor",
30 [ QXL_CMD_MESSAGE
] = "message",
31 [ QXL_CMD_SURFACE
] = "surface",
34 static const char *qxl_draw_type
[] = {
35 [ QXL_DRAW_NOP
] = "nop",
36 [ QXL_DRAW_FILL
] = "fill",
37 [ QXL_DRAW_OPAQUE
] = "opaque",
38 [ QXL_DRAW_COPY
] = "copy",
39 [ QXL_COPY_BITS
] = "copy-bits",
40 [ QXL_DRAW_BLEND
] = "blend",
41 [ QXL_DRAW_BLACKNESS
] = "blackness",
42 [ QXL_DRAW_WHITENESS
] = "whitemess",
43 [ QXL_DRAW_INVERS
] = "invers",
44 [ QXL_DRAW_ROP3
] = "rop3",
45 [ QXL_DRAW_STROKE
] = "stroke",
46 [ QXL_DRAW_TEXT
] = "text",
47 [ QXL_DRAW_TRANSPARENT
] = "transparent",
48 [ QXL_DRAW_ALPHA_BLEND
] = "alpha-blend",
51 static const char *qxl_draw_effect
[] = {
52 [ QXL_EFFECT_BLEND
] = "blend",
53 [ QXL_EFFECT_OPAQUE
] = "opaque",
54 [ QXL_EFFECT_REVERT_ON_DUP
] = "revert-on-dup",
55 [ QXL_EFFECT_BLACKNESS_ON_DUP
] = "blackness-on-dup",
56 [ QXL_EFFECT_WHITENESS_ON_DUP
] = "whiteness-on-dup",
57 [ QXL_EFFECT_NOP_ON_DUP
] = "nop-on-dup",
58 [ QXL_EFFECT_NOP
] = "nop",
59 [ QXL_EFFECT_OPAQUE_BRUSH
] = "opaque-brush",
62 static const char *qxl_surface_cmd
[] = {
63 [ QXL_SURFACE_CMD_CREATE
] = "create",
64 [ QXL_SURFACE_CMD_DESTROY
] = "destroy",
67 static const char *spice_surface_fmt
[] = {
68 [ SPICE_SURFACE_FMT_INVALID
] = "invalid",
69 [ SPICE_SURFACE_FMT_1_A
] = "alpha/1",
70 [ SPICE_SURFACE_FMT_8_A
] = "alpha/8",
71 [ SPICE_SURFACE_FMT_16_555
] = "555/16",
72 [ SPICE_SURFACE_FMT_16_565
] = "565/16",
73 [ SPICE_SURFACE_FMT_32_xRGB
] = "xRGB/32",
74 [ SPICE_SURFACE_FMT_32_ARGB
] = "ARGB/32",
77 static const char *qxl_cursor_cmd
[] = {
78 [ QXL_CURSOR_SET
] = "set",
79 [ QXL_CURSOR_MOVE
] = "move",
80 [ QXL_CURSOR_HIDE
] = "hide",
81 [ QXL_CURSOR_TRAIL
] = "trail",
84 static const char *spice_cursor_type
[] = {
85 [ SPICE_CURSOR_TYPE_ALPHA
] = "alpha",
86 [ SPICE_CURSOR_TYPE_MONO
] = "mono",
87 [ SPICE_CURSOR_TYPE_COLOR4
] = "color4",
88 [ SPICE_CURSOR_TYPE_COLOR8
] = "color8",
89 [ SPICE_CURSOR_TYPE_COLOR16
] = "color16",
90 [ SPICE_CURSOR_TYPE_COLOR24
] = "color24",
91 [ SPICE_CURSOR_TYPE_COLOR32
] = "color32",
94 static const char *qxl_v2n(const char *n
[], size_t l
, int v
)
96 if (v
>= l
|| !n
[v
]) {
101 #define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value)
103 static int qxl_log_image(PCIQXLDevice
*qxl
, QXLPHYSICAL addr
, int group_id
)
106 QXLImageDescriptor
*desc
;
108 image
= qxl_phys2virt(qxl
, addr
, group_id
);
112 desc
= &image
->descriptor
;
113 fprintf(stderr
, " (id %" PRIx64
" type %d flags %d width %d height %d",
114 desc
->id
, desc
->type
, desc
->flags
, desc
->width
, desc
->height
);
115 switch (desc
->type
) {
116 case SPICE_IMAGE_TYPE_BITMAP
:
117 fprintf(stderr
, ", fmt %d flags %d x %d y %d stride %d"
118 " palette %" PRIx64
" data %" PRIx64
,
119 image
->bitmap
.format
, image
->bitmap
.flags
,
120 image
->bitmap
.x
, image
->bitmap
.y
,
121 image
->bitmap
.stride
,
122 image
->bitmap
.palette
, image
->bitmap
.data
);
125 fprintf(stderr
, ")");
129 static void qxl_log_rect(QXLRect
*rect
)
131 fprintf(stderr
, " %dx%d+%d+%d",
132 rect
->right
- rect
->left
,
133 rect
->bottom
- rect
->top
,
134 rect
->left
, rect
->top
);
137 static int qxl_log_cmd_draw_copy(PCIQXLDevice
*qxl
, QXLCopy
*copy
,
142 fprintf(stderr
, " src %" PRIx64
,
144 ret
= qxl_log_image(qxl
, copy
->src_bitmap
, group_id
);
148 fprintf(stderr
, " area");
149 qxl_log_rect(©
->src_area
);
150 fprintf(stderr
, " rop %d", copy
->rop_descriptor
);
154 static int qxl_log_cmd_draw(PCIQXLDevice
*qxl
, QXLDrawable
*draw
, int group_id
)
156 fprintf(stderr
, ": surface_id %d type %s effect %s",
158 qxl_name(qxl_draw_type
, draw
->type
),
159 qxl_name(qxl_draw_effect
, draw
->effect
));
160 switch (draw
->type
) {
162 return qxl_log_cmd_draw_copy(qxl
, &draw
->u
.copy
, group_id
);
168 static int qxl_log_cmd_draw_compat(PCIQXLDevice
*qxl
, QXLCompatDrawable
*draw
,
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
);
179 switch (draw
->type
) {
181 return qxl_log_cmd_draw_copy(qxl
, &draw
->u
.copy
, group_id
);
187 static void qxl_log_cmd_surface(PCIQXLDevice
*qxl
, QXLSurfaceCmd
*cmd
)
189 fprintf(stderr
, ": %s id %d",
190 qxl_name(qxl_surface_cmd
, cmd
->type
),
192 if (cmd
->type
== QXL_SURFACE_CMD_CREATE
) {
193 fprintf(stderr
, " size %dx%d stride %d format %s (count %d, max %d)",
194 cmd
->u
.surface_create
.width
,
195 cmd
->u
.surface_create
.height
,
196 cmd
->u
.surface_create
.stride
,
197 qxl_name(spice_surface_fmt
, cmd
->u
.surface_create
.format
),
198 qxl
->guest_surfaces
.count
, qxl
->guest_surfaces
.max
);
200 if (cmd
->type
== QXL_SURFACE_CMD_DESTROY
) {
201 fprintf(stderr
, " (count %d)", qxl
->guest_surfaces
.count
);
205 int qxl_log_cmd_cursor(PCIQXLDevice
*qxl
, QXLCursorCmd
*cmd
, int group_id
)
209 fprintf(stderr
, ": %s",
210 qxl_name(qxl_cursor_cmd
, cmd
->type
));
213 fprintf(stderr
, " +%d+%d visible %s, shape @ 0x%" PRIx64
,
214 cmd
->u
.set
.position
.x
,
215 cmd
->u
.set
.position
.y
,
216 cmd
->u
.set
.visible
? "yes" : "no",
218 cursor
= qxl_phys2virt(qxl
, cmd
->u
.set
.shape
, group_id
);
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
);
229 case QXL_CURSOR_MOVE
:
230 fprintf(stderr
, " +%d+%d", cmd
->u
.position
.x
, cmd
->u
.position
.y
);
236 int qxl_log_command(PCIQXLDevice
*qxl
, const char *ring
, QXLCommandExt
*ext
)
238 bool compat
= ext
->flags
& QXL_COMMAND_FLAG_COMPAT
;
245 fprintf(stderr
, "%" PRId64
" qxl-%d/%s:", qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
),
247 fprintf(stderr
, " cmd @ 0x%" PRIx64
" %s%s", ext
->cmd
.data
,
248 qxl_name(qxl_type
, ext
->cmd
.type
),
249 compat
? "(compat)" : "");
251 data
= qxl_phys2virt(qxl
, ext
->cmd
.data
, ext
->group_id
);
255 switch (ext
->cmd
.type
) {
258 ret
= qxl_log_cmd_draw(qxl
, data
, ext
->group_id
);
260 ret
= qxl_log_cmd_draw_compat(qxl
, data
, ext
->group_id
);
266 case QXL_CMD_SURFACE
:
267 qxl_log_cmd_surface(qxl
, data
);
270 qxl_log_cmd_cursor(qxl
, data
, ext
->group_id
);
273 fprintf(stderr
, "\n");