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