]>
Commit | Line | Data |
---|---|---|
a19cbfb3 GH |
1 | /* |
2 | * qxl command logging -- for debug purposes | |
3 | * | |
4 | * Copyright (C) 2010 Red Hat, Inc. | |
5 | * | |
6 | * maintained by Gerd Hoffmann <[email protected]> | |
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 | ||
1de7afc9 | 22 | #include "qemu/timer.h" |
47b43a1f | 23 | #include "qxl.h" |
a19cbfb3 GH |
24 | |
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", | |
32 | }; | |
33 | ||
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", | |
49 | }; | |
50 | ||
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", | |
60 | }; | |
61 | ||
62 | static const char *qxl_surface_cmd[] = { | |
63 | [ QXL_SURFACE_CMD_CREATE ] = "create", | |
64 | [ QXL_SURFACE_CMD_DESTROY ] = "destroy", | |
65 | }; | |
66 | ||
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", | |
75 | }; | |
76 | ||
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", | |
82 | }; | |
83 | ||
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", | |
92 | }; | |
93 | ||
94 | static const char *qxl_v2n(const char *n[], size_t l, int v) | |
95 | { | |
96 | if (v >= l || !n[v]) { | |
97 | return "???"; | |
98 | } | |
99 | return n[v]; | |
100 | } | |
101 | #define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value) | |
102 | ||
fae2afb1 | 103 | static int qxl_log_image(PCIQXLDevice *qxl, QXLPHYSICAL addr, int group_id) |
a19cbfb3 GH |
104 | { |
105 | QXLImage *image; | |
106 | QXLImageDescriptor *desc; | |
107 | ||
108 | image = qxl_phys2virt(qxl, addr, group_id); | |
fae2afb1 AL |
109 | if (!image) { |
110 | return 1; | |
111 | } | |
a19cbfb3 GH |
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); | |
123 | break; | |
124 | } | |
125 | fprintf(stderr, ")"); | |
fae2afb1 | 126 | return 0; |
a19cbfb3 GH |
127 | } |
128 | ||
129 | static void qxl_log_rect(QXLRect *rect) | |
130 | { | |
131 | fprintf(stderr, " %dx%d+%d+%d", | |
132 | rect->right - rect->left, | |
133 | rect->bottom - rect->top, | |
134 | rect->left, rect->top); | |
135 | } | |
136 | ||
fae2afb1 AL |
137 | static int qxl_log_cmd_draw_copy(PCIQXLDevice *qxl, QXLCopy *copy, |
138 | int group_id) | |
a19cbfb3 | 139 | { |
fae2afb1 AL |
140 | int ret; |
141 | ||
a19cbfb3 GH |
142 | fprintf(stderr, " src %" PRIx64, |
143 | copy->src_bitmap); | |
fae2afb1 AL |
144 | ret = qxl_log_image(qxl, copy->src_bitmap, group_id); |
145 | if (ret != 0) { | |
146 | return ret; | |
147 | } | |
a19cbfb3 GH |
148 | fprintf(stderr, " area"); |
149 | qxl_log_rect(©->src_area); | |
150 | fprintf(stderr, " rop %d", copy->rop_descriptor); | |
fae2afb1 | 151 | return 0; |
a19cbfb3 GH |
152 | } |
153 | ||
fae2afb1 | 154 | static int qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw, int group_id) |
a19cbfb3 GH |
155 | { |
156 | fprintf(stderr, ": surface_id %d type %s effect %s", | |
157 | draw->surface_id, | |
158 | qxl_name(qxl_draw_type, draw->type), | |
159 | qxl_name(qxl_draw_effect, draw->effect)); | |
160 | switch (draw->type) { | |
161 | case QXL_DRAW_COPY: | |
fae2afb1 | 162 | return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id); |
a19cbfb3 GH |
163 | break; |
164 | } | |
fae2afb1 | 165 | return 0; |
a19cbfb3 GH |
166 | } |
167 | ||
fae2afb1 AL |
168 | static int qxl_log_cmd_draw_compat(PCIQXLDevice *qxl, QXLCompatDrawable *draw, |
169 | int group_id) | |
a19cbfb3 GH |
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: | |
fae2afb1 | 181 | return qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id); |
a19cbfb3 GH |
182 | break; |
183 | } | |
fae2afb1 | 184 | return 0; |
a19cbfb3 GH |
185 | } |
186 | ||
187 | static void qxl_log_cmd_surface(PCIQXLDevice *qxl, QXLSurfaceCmd *cmd) | |
188 | { | |
189 | fprintf(stderr, ": %s id %d", | |
190 | qxl_name(qxl_surface_cmd, cmd->type), | |
191 | cmd->surface_id); | |
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); | |
199 | } | |
200 | if (cmd->type == QXL_SURFACE_CMD_DESTROY) { | |
201 | fprintf(stderr, " (count %d)", qxl->guest_surfaces.count); | |
202 | } | |
203 | } | |
204 | ||
fae2afb1 | 205 | int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id) |
a19cbfb3 GH |
206 | { |
207 | QXLCursor *cursor; | |
208 | ||
209 | fprintf(stderr, ": %s", | |
210 | qxl_name(qxl_cursor_cmd, cmd->type)); | |
211 | switch (cmd->type) { | |
212 | case QXL_CURSOR_SET: | |
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", | |
217 | cmd->u.set.shape); | |
218 | cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id); | |
fae2afb1 AL |
219 | if (!cursor) { |
220 | return 1; | |
221 | } | |
a19cbfb3 GH |
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 | } | |
fae2afb1 | 233 | return 0; |
a19cbfb3 GH |
234 | } |
235 | ||
fae2afb1 | 236 | int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext) |
a19cbfb3 GH |
237 | { |
238 | bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT; | |
239 | void *data; | |
fae2afb1 | 240 | int ret; |
a19cbfb3 GH |
241 | |
242 | if (!qxl->cmdlog) { | |
fae2afb1 | 243 | return 0; |
a19cbfb3 | 244 | } |
bc72ad67 | 245 | fprintf(stderr, "%" PRId64 " qxl-%d/%s:", qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), |
1f0ff2fb | 246 | qxl->id, ring); |
a19cbfb3 GH |
247 | fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data, |
248 | qxl_name(qxl_type, ext->cmd.type), | |
249 | compat ? "(compat)" : ""); | |
250 | ||
251 | data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); | |
fae2afb1 AL |
252 | if (!data) { |
253 | return 1; | |
254 | } | |
a19cbfb3 GH |
255 | switch (ext->cmd.type) { |
256 | case QXL_CMD_DRAW: | |
257 | if (!compat) { | |
fae2afb1 | 258 | ret = qxl_log_cmd_draw(qxl, data, ext->group_id); |
a19cbfb3 | 259 | } else { |
fae2afb1 AL |
260 | ret = qxl_log_cmd_draw_compat(qxl, data, ext->group_id); |
261 | } | |
262 | if (ret) { | |
263 | return ret; | |
a19cbfb3 GH |
264 | } |
265 | break; | |
266 | case QXL_CMD_SURFACE: | |
267 | qxl_log_cmd_surface(qxl, data); | |
268 | break; | |
269 | case QXL_CMD_CURSOR: | |
270 | qxl_log_cmd_cursor(qxl, data, ext->group_id); | |
271 | break; | |
272 | } | |
273 | fprintf(stderr, "\n"); | |
fae2afb1 | 274 | return 0; |
a19cbfb3 | 275 | } |