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 void qxl_log_image(PCIQXLDevice
*qxl
, QXLPHYSICAL addr
, int group_id
)
106 QXLImageDescriptor
*desc
;
108 image
= qxl_phys2virt(qxl
, addr
, group_id
);
109 desc
= &image
->descriptor
;
110 fprintf(stderr
, " (id %" PRIx64
" type %d flags %d width %d height %d",
111 desc
->id
, desc
->type
, desc
->flags
, desc
->width
, desc
->height
);
112 switch (desc
->type
) {
113 case SPICE_IMAGE_TYPE_BITMAP
:
114 fprintf(stderr
, ", fmt %d flags %d x %d y %d stride %d"
115 " palette %" PRIx64
" data %" PRIx64
,
116 image
->bitmap
.format
, image
->bitmap
.flags
,
117 image
->bitmap
.x
, image
->bitmap
.y
,
118 image
->bitmap
.stride
,
119 image
->bitmap
.palette
, image
->bitmap
.data
);
122 fprintf(stderr
, ")");
125 static void qxl_log_rect(QXLRect
*rect
)
127 fprintf(stderr
, " %dx%d+%d+%d",
128 rect
->right
- rect
->left
,
129 rect
->bottom
- rect
->top
,
130 rect
->left
, rect
->top
);
133 static void qxl_log_cmd_draw_copy(PCIQXLDevice
*qxl
, QXLCopy
*copy
, int group_id
)
135 fprintf(stderr
, " src %" PRIx64
,
137 qxl_log_image(qxl
, copy
->src_bitmap
, group_id
);
138 fprintf(stderr
, " area");
139 qxl_log_rect(©
->src_area
);
140 fprintf(stderr
, " rop %d", copy
->rop_descriptor
);
143 static void qxl_log_cmd_draw(PCIQXLDevice
*qxl
, QXLDrawable
*draw
, int group_id
)
145 fprintf(stderr
, ": surface_id %d type %s effect %s",
147 qxl_name(qxl_draw_type
, draw
->type
),
148 qxl_name(qxl_draw_effect
, draw
->effect
));
149 switch (draw
->type
) {
151 qxl_log_cmd_draw_copy(qxl
, &draw
->u
.copy
, group_id
);
156 static void qxl_log_cmd_draw_compat(PCIQXLDevice
*qxl
, QXLCompatDrawable
*draw
,
159 fprintf(stderr
, ": type %s effect %s",
160 qxl_name(qxl_draw_type
, draw
->type
),
161 qxl_name(qxl_draw_effect
, draw
->effect
));
162 if (draw
->bitmap_offset
) {
163 fprintf(stderr
, ": bitmap %d",
164 draw
->bitmap_offset
);
165 qxl_log_rect(&draw
->bitmap_area
);
167 switch (draw
->type
) {
169 qxl_log_cmd_draw_copy(qxl
, &draw
->u
.copy
, group_id
);
174 static void qxl_log_cmd_surface(PCIQXLDevice
*qxl
, QXLSurfaceCmd
*cmd
)
176 fprintf(stderr
, ": %s id %d",
177 qxl_name(qxl_surface_cmd
, cmd
->type
),
179 if (cmd
->type
== QXL_SURFACE_CMD_CREATE
) {
180 fprintf(stderr
, " size %dx%d stride %d format %s (count %d, max %d)",
181 cmd
->u
.surface_create
.width
,
182 cmd
->u
.surface_create
.height
,
183 cmd
->u
.surface_create
.stride
,
184 qxl_name(spice_surface_fmt
, cmd
->u
.surface_create
.format
),
185 qxl
->guest_surfaces
.count
, qxl
->guest_surfaces
.max
);
187 if (cmd
->type
== QXL_SURFACE_CMD_DESTROY
) {
188 fprintf(stderr
, " (count %d)", qxl
->guest_surfaces
.count
);
192 void qxl_log_cmd_cursor(PCIQXLDevice
*qxl
, QXLCursorCmd
*cmd
, int group_id
)
196 fprintf(stderr
, ": %s",
197 qxl_name(qxl_cursor_cmd
, cmd
->type
));
200 fprintf(stderr
, " +%d+%d visible %s, shape @ 0x%" PRIx64
,
201 cmd
->u
.set
.position
.x
,
202 cmd
->u
.set
.position
.y
,
203 cmd
->u
.set
.visible
? "yes" : "no",
205 cursor
= qxl_phys2virt(qxl
, cmd
->u
.set
.shape
, group_id
);
206 fprintf(stderr
, " type %s size %dx%d hot-spot +%d+%d"
207 " unique 0x%" PRIx64
" data-size %d",
208 qxl_name(spice_cursor_type
, cursor
->header
.type
),
209 cursor
->header
.width
, cursor
->header
.height
,
210 cursor
->header
.hot_spot_x
, cursor
->header
.hot_spot_y
,
211 cursor
->header
.unique
, cursor
->data_size
);
213 case QXL_CURSOR_MOVE
:
214 fprintf(stderr
, " +%d+%d", cmd
->u
.position
.x
, cmd
->u
.position
.y
);
219 void qxl_log_command(PCIQXLDevice
*qxl
, const char *ring
, QXLCommandExt
*ext
)
221 bool compat
= ext
->flags
& QXL_COMMAND_FLAG_COMPAT
;
227 fprintf(stderr
, "%ld qxl-%d/%s:", qemu_get_clock_ns(vm_clock
),
229 fprintf(stderr
, " cmd @ 0x%" PRIx64
" %s%s", ext
->cmd
.data
,
230 qxl_name(qxl_type
, ext
->cmd
.type
),
231 compat
? "(compat)" : "");
233 data
= qxl_phys2virt(qxl
, ext
->cmd
.data
, ext
->group_id
);
234 switch (ext
->cmd
.type
) {
237 qxl_log_cmd_draw(qxl
, data
, ext
->group_id
);
239 qxl_log_cmd_draw_compat(qxl
, data
, ext
->group_id
);
242 case QXL_CMD_SURFACE
:
243 qxl_log_cmd_surface(qxl
, data
);
246 qxl_log_cmd_cursor(qxl
, data
, ext
->group_id
);
249 fprintf(stderr
, "\n");