qemu-pixman.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*
  2. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  3. * See the COPYING file in the top-level directory.
  4. */
  5. #include "qemu/osdep.h"
  6. #include "qapi/error.h"
  7. #include "ui/console.h"
  8. #include "qemu/memfd.h"
  9. #include "standard-headers/drm/drm_fourcc.h"
  10. #include "trace.h"
  11. PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format)
  12. {
  13. PixelFormat pf;
  14. uint8_t bpp;
  15. bpp = pf.bits_per_pixel = PIXMAN_FORMAT_BPP(format);
  16. pf.bytes_per_pixel = PIXMAN_FORMAT_BPP(format) / 8;
  17. pf.depth = PIXMAN_FORMAT_DEPTH(format);
  18. pf.abits = PIXMAN_FORMAT_A(format);
  19. pf.rbits = PIXMAN_FORMAT_R(format);
  20. pf.gbits = PIXMAN_FORMAT_G(format);
  21. pf.bbits = PIXMAN_FORMAT_B(format);
  22. switch (PIXMAN_FORMAT_TYPE(format)) {
  23. case PIXMAN_TYPE_ARGB:
  24. pf.ashift = pf.bbits + pf.gbits + pf.rbits;
  25. pf.rshift = pf.bbits + pf.gbits;
  26. pf.gshift = pf.bbits;
  27. pf.bshift = 0;
  28. break;
  29. case PIXMAN_TYPE_ABGR:
  30. pf.ashift = pf.rbits + pf.gbits + pf.bbits;
  31. pf.bshift = pf.rbits + pf.gbits;
  32. pf.gshift = pf.rbits;
  33. pf.rshift = 0;
  34. break;
  35. case PIXMAN_TYPE_BGRA:
  36. pf.bshift = bpp - pf.bbits;
  37. pf.gshift = bpp - (pf.bbits + pf.gbits);
  38. pf.rshift = bpp - (pf.bbits + pf.gbits + pf.rbits);
  39. pf.ashift = 0;
  40. break;
  41. case PIXMAN_TYPE_RGBA:
  42. pf.rshift = bpp - pf.rbits;
  43. pf.gshift = bpp - (pf.rbits + pf.gbits);
  44. pf.bshift = bpp - (pf.rbits + pf.gbits + pf.bbits);
  45. pf.ashift = 0;
  46. break;
  47. default:
  48. g_assert_not_reached();
  49. }
  50. pf.amax = (1 << pf.abits) - 1;
  51. pf.rmax = (1 << pf.rbits) - 1;
  52. pf.gmax = (1 << pf.gbits) - 1;
  53. pf.bmax = (1 << pf.bbits) - 1;
  54. pf.amask = pf.amax << pf.ashift;
  55. pf.rmask = pf.rmax << pf.rshift;
  56. pf.gmask = pf.gmax << pf.gshift;
  57. pf.bmask = pf.bmax << pf.bshift;
  58. return pf;
  59. }
  60. pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian)
  61. {
  62. if (native_endian) {
  63. switch (bpp) {
  64. case 15:
  65. return PIXMAN_x1r5g5b5;
  66. case 16:
  67. return PIXMAN_r5g6b5;
  68. case 24:
  69. return PIXMAN_r8g8b8;
  70. case 32:
  71. return PIXMAN_x8r8g8b8;
  72. }
  73. } else {
  74. switch (bpp) {
  75. case 24:
  76. return PIXMAN_b8g8r8;
  77. case 32:
  78. return PIXMAN_b8g8r8x8;
  79. break;
  80. }
  81. }
  82. return 0;
  83. }
  84. /* Note: drm is little endian, pixman is native endian */
  85. static const struct {
  86. uint32_t drm_format;
  87. pixman_format_code_t pixman_format;
  88. } drm_format_pixman_map[] = {
  89. { DRM_FORMAT_RGB888, PIXMAN_LE_r8g8b8 },
  90. { DRM_FORMAT_ARGB8888, PIXMAN_LE_a8r8g8b8 },
  91. { DRM_FORMAT_XRGB8888, PIXMAN_LE_x8r8g8b8 },
  92. { DRM_FORMAT_XBGR8888, PIXMAN_LE_x8b8g8r8 },
  93. { DRM_FORMAT_ABGR8888, PIXMAN_LE_a8b8g8r8 },
  94. };
  95. pixman_format_code_t qemu_drm_format_to_pixman(uint32_t drm_format)
  96. {
  97. int i;
  98. for (i = 0; i < ARRAY_SIZE(drm_format_pixman_map); i++) {
  99. if (drm_format == drm_format_pixman_map[i].drm_format) {
  100. return drm_format_pixman_map[i].pixman_format;
  101. }
  102. }
  103. return 0;
  104. }
  105. uint32_t qemu_pixman_to_drm_format(pixman_format_code_t pixman_format)
  106. {
  107. int i;
  108. for (i = 0; i < ARRAY_SIZE(drm_format_pixman_map); i++) {
  109. if (pixman_format == drm_format_pixman_map[i].pixman_format) {
  110. return drm_format_pixman_map[i].drm_format;
  111. }
  112. }
  113. return 0;
  114. }
  115. int qemu_pixman_get_type(int rshift, int gshift, int bshift)
  116. {
  117. int type = PIXMAN_TYPE_OTHER;
  118. if (rshift > gshift && gshift > bshift) {
  119. if (bshift == 0) {
  120. type = PIXMAN_TYPE_ARGB;
  121. } else {
  122. type = PIXMAN_TYPE_RGBA;
  123. }
  124. } else if (rshift < gshift && gshift < bshift) {
  125. if (rshift == 0) {
  126. type = PIXMAN_TYPE_ABGR;
  127. } else {
  128. type = PIXMAN_TYPE_BGRA;
  129. }
  130. }
  131. return type;
  132. }
  133. #ifdef CONFIG_PIXMAN
  134. pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf)
  135. {
  136. pixman_format_code_t format;
  137. int type;
  138. type = qemu_pixman_get_type(pf->rshift, pf->gshift, pf->bshift);
  139. format = PIXMAN_FORMAT(pf->bits_per_pixel, type,
  140. pf->abits, pf->rbits, pf->gbits, pf->bbits);
  141. if (!pixman_format_supported_source(format)) {
  142. return 0;
  143. }
  144. return format;
  145. }
  146. #endif
  147. /*
  148. * Return true for known-good pixman conversions.
  149. *
  150. * UIs using pixman for format conversion can hook this into
  151. * DisplayChangeListenerOps->dpy_gfx_check_format
  152. */
  153. bool qemu_pixman_check_format(DisplayChangeListener *dcl,
  154. pixman_format_code_t format)
  155. {
  156. switch (format) {
  157. /* 32 bpp */
  158. case PIXMAN_x8r8g8b8:
  159. case PIXMAN_a8r8g8b8:
  160. case PIXMAN_b8g8r8x8:
  161. case PIXMAN_b8g8r8a8:
  162. /* 24 bpp */
  163. case PIXMAN_r8g8b8:
  164. case PIXMAN_b8g8r8:
  165. /* 16 bpp */
  166. case PIXMAN_x1r5g5b5:
  167. case PIXMAN_r5g6b5:
  168. return true;
  169. default:
  170. return false;
  171. }
  172. }
  173. #ifdef CONFIG_PIXMAN
  174. pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format,
  175. int width)
  176. {
  177. pixman_image_t *image = pixman_image_create_bits(format, width, 1, NULL, 0);
  178. assert(image != NULL);
  179. return image;
  180. }
  181. /* fill linebuf from framebuffer */
  182. void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb,
  183. int width, int x, int y)
  184. {
  185. pixman_image_composite(PIXMAN_OP_SRC, fb, NULL, linebuf,
  186. x, y, 0, 0, 0, 0, width, 1);
  187. }
  188. pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format,
  189. pixman_image_t *image)
  190. {
  191. return pixman_image_create_bits(format,
  192. pixman_image_get_width(image),
  193. pixman_image_get_height(image),
  194. NULL,
  195. pixman_image_get_stride(image));
  196. }
  197. #endif
  198. void qemu_pixman_image_unref(pixman_image_t *image)
  199. {
  200. if (image == NULL) {
  201. return;
  202. }
  203. pixman_image_unref(image);
  204. }
  205. #ifdef CONFIG_PIXMAN
  206. pixman_image_t *qemu_pixman_glyph_from_vgafont(int height, const uint8_t *font,
  207. unsigned int ch)
  208. {
  209. pixman_image_t *glyph;
  210. uint8_t *data;
  211. bool bit;
  212. int x, y;
  213. glyph = pixman_image_create_bits(PIXMAN_a8, 8, height,
  214. NULL, 0);
  215. data = (uint8_t *)pixman_image_get_data(glyph);
  216. font += height * ch;
  217. for (y = 0; y < height; y++, font++) {
  218. for (x = 0; x < 8; x++, data++) {
  219. bit = (*font) & (1 << (7-x));
  220. *data = bit ? 0xff : 0x00;
  221. }
  222. }
  223. return glyph;
  224. }
  225. void qemu_pixman_glyph_render(pixman_image_t *glyph,
  226. pixman_image_t *surface,
  227. pixman_color_t *fgcol,
  228. pixman_color_t *bgcol,
  229. int x, int y, int cw, int ch)
  230. {
  231. pixman_image_t *ifg = pixman_image_create_solid_fill(fgcol);
  232. pixman_image_t *ibg = pixman_image_create_solid_fill(bgcol);
  233. pixman_image_composite(PIXMAN_OP_SRC, ibg, NULL, surface,
  234. 0, 0, 0, 0,
  235. cw * x, ch * y,
  236. cw, ch);
  237. pixman_image_composite(PIXMAN_OP_OVER, ifg, glyph, surface,
  238. 0, 0, 0, 0,
  239. cw * x, ch * y,
  240. cw, ch);
  241. pixman_image_unref(ifg);
  242. pixman_image_unref(ibg);
  243. }
  244. #endif /* CONFIG_PIXMAN */
  245. static void *
  246. qemu_pixman_shareable_alloc(const char *name, size_t size,
  247. qemu_pixman_shareable *handle,
  248. Error **errp)
  249. {
  250. #ifdef WIN32
  251. return qemu_win32_map_alloc(size, handle, errp);
  252. #else
  253. return qemu_memfd_alloc(name, size, 0, handle, errp);
  254. #endif
  255. }
  256. static void
  257. qemu_pixman_shareable_free(qemu_pixman_shareable handle,
  258. void *ptr, size_t size)
  259. {
  260. #ifdef WIN32
  261. qemu_win32_map_free(ptr, handle, &error_warn);
  262. #else
  263. qemu_memfd_free(ptr, size, handle);
  264. #endif
  265. }
  266. static void
  267. qemu_pixman_shared_image_destroy(pixman_image_t *image, void *data)
  268. {
  269. qemu_pixman_shareable handle = PTR_TO_SHAREABLE(data);
  270. void *ptr = pixman_image_get_data(image);
  271. size_t size = pixman_image_get_height(image) * pixman_image_get_stride(image);
  272. qemu_pixman_shareable_free(handle, ptr, size);
  273. }
  274. bool
  275. qemu_pixman_image_new_shareable(pixman_image_t **image,
  276. qemu_pixman_shareable *handle,
  277. const char *name,
  278. pixman_format_code_t format,
  279. int width,
  280. int height,
  281. int rowstride_bytes,
  282. Error **errp)
  283. {
  284. ERRP_GUARD();
  285. size_t size = height * rowstride_bytes;
  286. void *bits = NULL;
  287. g_return_val_if_fail(image != NULL, false);
  288. g_return_val_if_fail(handle != NULL, false);
  289. bits = qemu_pixman_shareable_alloc(name, size, handle, errp);
  290. if (!bits) {
  291. return false;
  292. }
  293. *image = pixman_image_create_bits(format, width, height, bits, rowstride_bytes);
  294. if (!*image) {
  295. error_setg(errp, "Failed to allocate image");
  296. qemu_pixman_shareable_free(*handle, bits, size);
  297. return false;
  298. }
  299. pixman_image_set_destroy_function(*image,
  300. qemu_pixman_shared_image_destroy,
  301. SHAREABLE_TO_PTR(*handle));
  302. return true;
  303. }