qxl-logger.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * qxl command logging -- for debug purposes
  3. *
  4. * Copyright (C) 2010 Red Hat, Inc.
  5. *
  6. * maintained by Gerd Hoffmann <kraxel@redhat.com>
  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. #include "qemu-timer.h"
  22. #include "qxl.h"
  23. static const char *qxl_type[] = {
  24. [ QXL_CMD_NOP ] = "nop",
  25. [ QXL_CMD_DRAW ] = "draw",
  26. [ QXL_CMD_UPDATE ] = "update",
  27. [ QXL_CMD_CURSOR ] = "cursor",
  28. [ QXL_CMD_MESSAGE ] = "message",
  29. [ QXL_CMD_SURFACE ] = "surface",
  30. };
  31. static const char *qxl_draw_type[] = {
  32. [ QXL_DRAW_NOP ] = "nop",
  33. [ QXL_DRAW_FILL ] = "fill",
  34. [ QXL_DRAW_OPAQUE ] = "opaque",
  35. [ QXL_DRAW_COPY ] = "copy",
  36. [ QXL_COPY_BITS ] = "copy-bits",
  37. [ QXL_DRAW_BLEND ] = "blend",
  38. [ QXL_DRAW_BLACKNESS ] = "blackness",
  39. [ QXL_DRAW_WHITENESS ] = "whitemess",
  40. [ QXL_DRAW_INVERS ] = "invers",
  41. [ QXL_DRAW_ROP3 ] = "rop3",
  42. [ QXL_DRAW_STROKE ] = "stroke",
  43. [ QXL_DRAW_TEXT ] = "text",
  44. [ QXL_DRAW_TRANSPARENT ] = "transparent",
  45. [ QXL_DRAW_ALPHA_BLEND ] = "alpha-blend",
  46. };
  47. static const char *qxl_draw_effect[] = {
  48. [ QXL_EFFECT_BLEND ] = "blend",
  49. [ QXL_EFFECT_OPAQUE ] = "opaque",
  50. [ QXL_EFFECT_REVERT_ON_DUP ] = "revert-on-dup",
  51. [ QXL_EFFECT_BLACKNESS_ON_DUP ] = "blackness-on-dup",
  52. [ QXL_EFFECT_WHITENESS_ON_DUP ] = "whiteness-on-dup",
  53. [ QXL_EFFECT_NOP_ON_DUP ] = "nop-on-dup",
  54. [ QXL_EFFECT_NOP ] = "nop",
  55. [ QXL_EFFECT_OPAQUE_BRUSH ] = "opaque-brush",
  56. };
  57. static const char *qxl_surface_cmd[] = {
  58. [ QXL_SURFACE_CMD_CREATE ] = "create",
  59. [ QXL_SURFACE_CMD_DESTROY ] = "destroy",
  60. };
  61. static const char *spice_surface_fmt[] = {
  62. [ SPICE_SURFACE_FMT_INVALID ] = "invalid",
  63. [ SPICE_SURFACE_FMT_1_A ] = "alpha/1",
  64. [ SPICE_SURFACE_FMT_8_A ] = "alpha/8",
  65. [ SPICE_SURFACE_FMT_16_555 ] = "555/16",
  66. [ SPICE_SURFACE_FMT_16_565 ] = "565/16",
  67. [ SPICE_SURFACE_FMT_32_xRGB ] = "xRGB/32",
  68. [ SPICE_SURFACE_FMT_32_ARGB ] = "ARGB/32",
  69. };
  70. static const char *qxl_cursor_cmd[] = {
  71. [ QXL_CURSOR_SET ] = "set",
  72. [ QXL_CURSOR_MOVE ] = "move",
  73. [ QXL_CURSOR_HIDE ] = "hide",
  74. [ QXL_CURSOR_TRAIL ] = "trail",
  75. };
  76. static const char *spice_cursor_type[] = {
  77. [ SPICE_CURSOR_TYPE_ALPHA ] = "alpha",
  78. [ SPICE_CURSOR_TYPE_MONO ] = "mono",
  79. [ SPICE_CURSOR_TYPE_COLOR4 ] = "color4",
  80. [ SPICE_CURSOR_TYPE_COLOR8 ] = "color8",
  81. [ SPICE_CURSOR_TYPE_COLOR16 ] = "color16",
  82. [ SPICE_CURSOR_TYPE_COLOR24 ] = "color24",
  83. [ SPICE_CURSOR_TYPE_COLOR32 ] = "color32",
  84. };
  85. static const char *qxl_v2n(const char *n[], size_t l, int v)
  86. {
  87. if (v >= l || !n[v]) {
  88. return "???";
  89. }
  90. return n[v];
  91. }
  92. #define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value)
  93. static void qxl_log_image(PCIQXLDevice *qxl, QXLPHYSICAL addr, int group_id)
  94. {
  95. QXLImage *image;
  96. QXLImageDescriptor *desc;
  97. image = qxl_phys2virt(qxl, addr, group_id);
  98. desc = &image->descriptor;
  99. fprintf(stderr, " (id %" PRIx64 " type %d flags %d width %d height %d",
  100. desc->id, desc->type, desc->flags, desc->width, desc->height);
  101. switch (desc->type) {
  102. case SPICE_IMAGE_TYPE_BITMAP:
  103. fprintf(stderr, ", fmt %d flags %d x %d y %d stride %d"
  104. " palette %" PRIx64 " data %" PRIx64,
  105. image->bitmap.format, image->bitmap.flags,
  106. image->bitmap.x, image->bitmap.y,
  107. image->bitmap.stride,
  108. image->bitmap.palette, image->bitmap.data);
  109. break;
  110. }
  111. fprintf(stderr, ")");
  112. }
  113. static void qxl_log_rect(QXLRect *rect)
  114. {
  115. fprintf(stderr, " %dx%d+%d+%d",
  116. rect->right - rect->left,
  117. rect->bottom - rect->top,
  118. rect->left, rect->top);
  119. }
  120. static void qxl_log_cmd_draw_copy(PCIQXLDevice *qxl, QXLCopy *copy, int group_id)
  121. {
  122. fprintf(stderr, " src %" PRIx64,
  123. copy->src_bitmap);
  124. qxl_log_image(qxl, copy->src_bitmap, group_id);
  125. fprintf(stderr, " area");
  126. qxl_log_rect(&copy->src_area);
  127. fprintf(stderr, " rop %d", copy->rop_descriptor);
  128. }
  129. static void qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw, int group_id)
  130. {
  131. fprintf(stderr, ": surface_id %d type %s effect %s",
  132. draw->surface_id,
  133. qxl_name(qxl_draw_type, draw->type),
  134. qxl_name(qxl_draw_effect, draw->effect));
  135. switch (draw->type) {
  136. case QXL_DRAW_COPY:
  137. qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
  138. break;
  139. }
  140. }
  141. static void qxl_log_cmd_draw_compat(PCIQXLDevice *qxl, QXLCompatDrawable *draw,
  142. int group_id)
  143. {
  144. fprintf(stderr, ": type %s effect %s",
  145. qxl_name(qxl_draw_type, draw->type),
  146. qxl_name(qxl_draw_effect, draw->effect));
  147. if (draw->bitmap_offset) {
  148. fprintf(stderr, ": bitmap %d",
  149. draw->bitmap_offset);
  150. qxl_log_rect(&draw->bitmap_area);
  151. }
  152. switch (draw->type) {
  153. case QXL_DRAW_COPY:
  154. qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
  155. break;
  156. }
  157. }
  158. static void qxl_log_cmd_surface(PCIQXLDevice *qxl, QXLSurfaceCmd *cmd)
  159. {
  160. fprintf(stderr, ": %s id %d",
  161. qxl_name(qxl_surface_cmd, cmd->type),
  162. cmd->surface_id);
  163. if (cmd->type == QXL_SURFACE_CMD_CREATE) {
  164. fprintf(stderr, " size %dx%d stride %d format %s (count %d, max %d)",
  165. cmd->u.surface_create.width,
  166. cmd->u.surface_create.height,
  167. cmd->u.surface_create.stride,
  168. qxl_name(spice_surface_fmt, cmd->u.surface_create.format),
  169. qxl->guest_surfaces.count, qxl->guest_surfaces.max);
  170. }
  171. if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
  172. fprintf(stderr, " (count %d)", qxl->guest_surfaces.count);
  173. }
  174. }
  175. void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id)
  176. {
  177. QXLCursor *cursor;
  178. fprintf(stderr, ": %s",
  179. qxl_name(qxl_cursor_cmd, cmd->type));
  180. switch (cmd->type) {
  181. case QXL_CURSOR_SET:
  182. fprintf(stderr, " +%d+%d visible %s, shape @ 0x%" PRIx64,
  183. cmd->u.set.position.x,
  184. cmd->u.set.position.y,
  185. cmd->u.set.visible ? "yes" : "no",
  186. cmd->u.set.shape);
  187. cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id);
  188. fprintf(stderr, " type %s size %dx%d hot-spot +%d+%d"
  189. " unique 0x%" PRIx64 " data-size %d",
  190. qxl_name(spice_cursor_type, cursor->header.type),
  191. cursor->header.width, cursor->header.height,
  192. cursor->header.hot_spot_x, cursor->header.hot_spot_y,
  193. cursor->header.unique, cursor->data_size);
  194. break;
  195. case QXL_CURSOR_MOVE:
  196. fprintf(stderr, " +%d+%d", cmd->u.position.x, cmd->u.position.y);
  197. break;
  198. }
  199. }
  200. void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext)
  201. {
  202. bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT;
  203. void *data;
  204. if (!qxl->cmdlog) {
  205. return;
  206. }
  207. fprintf(stderr, "%ld qxl-%d/%s:", qemu_get_clock_ns(vm_clock),
  208. qxl->id, ring);
  209. fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data,
  210. qxl_name(qxl_type, ext->cmd.type),
  211. compat ? "(compat)" : "");
  212. data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
  213. switch (ext->cmd.type) {
  214. case QXL_CMD_DRAW:
  215. if (!compat) {
  216. qxl_log_cmd_draw(qxl, data, ext->group_id);
  217. } else {
  218. qxl_log_cmd_draw_compat(qxl, data, ext->group_id);
  219. }
  220. break;
  221. case QXL_CMD_SURFACE:
  222. qxl_log_cmd_surface(qxl, data);
  223. break;
  224. case QXL_CMD_CURSOR:
  225. qxl_log_cmd_cursor(qxl, data, ext->group_id);
  226. break;
  227. }
  228. fprintf(stderr, "\n");
  229. }