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/osdep.h"
23 #include "qemu/timer.h"
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",
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",
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",
63 static const char *const qxl_surface_cmd
[] = {
64 [ QXL_SURFACE_CMD_CREATE
] = "create",
65 [ QXL_SURFACE_CMD_DESTROY
] = "destroy",
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",
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",
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",
95 static const char *qxl_v2n(const char *const n
[], size_t l
, int v
)
97 if (v
>= l
|| !n
[v
]) {
102 #define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value)
104 static int qxl_log_image(PCIQXLDevice
*qxl
, QXLPHYSICAL addr
, int group_id
)
107 QXLImageDescriptor
*desc
;
109 image
= qxl_phys2virt(qxl
, addr
, group_id
);
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
);
126 fprintf(stderr
, ")");
130 static void qxl_log_rect(QXLRect
*rect
)
132 fprintf(stderr
, " %dx%d+%d+%d",
133 rect
->right
- rect
->left
,
134 rect
->bottom
- rect
->top
,
135 rect
->left
, rect
->top
);
138 static int qxl_log_cmd_draw_copy(PCIQXLDevice
*qxl
, QXLCopy
*copy
,
143 fprintf(stderr
, " src %" PRIx64
,
145 ret
= qxl_log_image(qxl
, copy
->src_bitmap
, group_id
);
149 fprintf(stderr
, " area");
150 qxl_log_rect(©
->src_area
);
151 fprintf(stderr
, " rop %d", copy
->rop_descriptor
);
155 static int qxl_log_cmd_draw(PCIQXLDevice
*qxl
, QXLDrawable
*draw
, int group_id
)
157 fprintf(stderr
, ": surface_id %d type %s effect %s",
159 qxl_name(qxl_draw_type
, draw
->type
),
160 qxl_name(qxl_draw_effect
, draw
->effect
));
161 switch (draw
->type
) {
163 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
);
186 static void qxl_log_cmd_surface(PCIQXLDevice
*qxl
, QXLSurfaceCmd
*cmd
)
188 fprintf(stderr
, ": %s id %d",
189 qxl_name(qxl_surface_cmd
, cmd
->type
),
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
);
199 if (cmd
->type
== QXL_SURFACE_CMD_DESTROY
) {
200 fprintf(stderr
, " (count %u)", qxl
->guest_surfaces
.count
);
204 int qxl_log_cmd_cursor(PCIQXLDevice
*qxl
, QXLCursorCmd
*cmd
, int group_id
)
208 fprintf(stderr
, ": %s",
209 qxl_name(qxl_cursor_cmd
, cmd
->type
));
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",
217 cursor
= qxl_phys2virt(qxl
, cmd
->u
.set
.shape
, group_id
);
221 fprintf(stderr
, " type %s size %dx%d hot-spot +%d+%d"
222 " unique 0x%" PRIx64
" data-size %d",
223 qxl_name(spice_cursor_type
, cursor
->header
.type
),
224 cursor
->header
.width
, cursor
->header
.height
,
225 cursor
->header
.hot_spot_x
, cursor
->header
.hot_spot_y
,
226 cursor
->header
.unique
, cursor
->data_size
);
228 case QXL_CURSOR_MOVE
:
229 fprintf(stderr
, " +%d+%d", cmd
->u
.position
.x
, cmd
->u
.position
.y
);
235 int qxl_log_command(PCIQXLDevice
*qxl
, const char *ring
, QXLCommandExt
*ext
)
237 bool compat
= ext
->flags
& QXL_COMMAND_FLAG_COMPAT
;
244 fprintf(stderr
, "%" PRId64
" qxl-%d/%s:", qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
),
246 fprintf(stderr
, " cmd @ 0x%" PRIx64
" %s%s", ext
->cmd
.data
,
247 qxl_name(qxl_type
, ext
->cmd
.type
),
248 compat
? "(compat)" : "");
250 data
= qxl_phys2virt(qxl
, ext
->cmd
.data
, ext
->group_id
);
254 switch (ext
->cmd
.type
) {
257 ret
= qxl_log_cmd_draw(qxl
, data
, ext
->group_id
);
259 ret
= qxl_log_cmd_draw_compat(qxl
, data
, ext
->group_id
);
265 case QXL_CMD_SURFACE
:
266 qxl_log_cmd_surface(qxl
, data
);
269 qxl_log_cmd_cursor(qxl
, data
, ext
->group_id
);
272 fprintf(stderr
, "\n");