qemu-pixman.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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 "ui/console.h"
  7. #include "standard-headers/drm/drm_fourcc.h"
  8. PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format)
  9. {
  10. PixelFormat pf;
  11. uint8_t bpp;
  12. bpp = pf.bits_per_pixel = PIXMAN_FORMAT_BPP(format);
  13. pf.bytes_per_pixel = PIXMAN_FORMAT_BPP(format) / 8;
  14. pf.depth = PIXMAN_FORMAT_DEPTH(format);
  15. pf.abits = PIXMAN_FORMAT_A(format);
  16. pf.rbits = PIXMAN_FORMAT_R(format);
  17. pf.gbits = PIXMAN_FORMAT_G(format);
  18. pf.bbits = PIXMAN_FORMAT_B(format);
  19. switch (PIXMAN_FORMAT_TYPE(format)) {
  20. case PIXMAN_TYPE_ARGB:
  21. pf.ashift = pf.bbits + pf.gbits + pf.rbits;
  22. pf.rshift = pf.bbits + pf.gbits;
  23. pf.gshift = pf.bbits;
  24. pf.bshift = 0;
  25. break;
  26. case PIXMAN_TYPE_ABGR:
  27. pf.ashift = pf.rbits + pf.gbits + pf.bbits;
  28. pf.bshift = pf.rbits + pf.gbits;
  29. pf.gshift = pf.rbits;
  30. pf.rshift = 0;
  31. break;
  32. case PIXMAN_TYPE_BGRA:
  33. pf.bshift = bpp - pf.bbits;
  34. pf.gshift = bpp - (pf.bbits + pf.gbits);
  35. pf.rshift = bpp - (pf.bbits + pf.gbits + pf.rbits);
  36. pf.ashift = 0;
  37. break;
  38. case PIXMAN_TYPE_RGBA:
  39. pf.rshift = bpp - pf.rbits;
  40. pf.gshift = bpp - (pf.rbits + pf.gbits);
  41. pf.bshift = bpp - (pf.rbits + pf.gbits + pf.bbits);
  42. pf.ashift = 0;
  43. break;
  44. default:
  45. g_assert_not_reached();
  46. break;
  47. }
  48. pf.amax = (1 << pf.abits) - 1;
  49. pf.rmax = (1 << pf.rbits) - 1;
  50. pf.gmax = (1 << pf.gbits) - 1;
  51. pf.bmax = (1 << pf.bbits) - 1;
  52. pf.amask = pf.amax << pf.ashift;
  53. pf.rmask = pf.rmax << pf.rshift;
  54. pf.gmask = pf.gmax << pf.gshift;
  55. pf.bmask = pf.bmax << pf.bshift;
  56. return pf;
  57. }
  58. pixman_format_code_t qemu_default_pixman_format(int bpp, bool native_endian)
  59. {
  60. if (native_endian) {
  61. switch (bpp) {
  62. case 15:
  63. return PIXMAN_x1r5g5b5;
  64. case 16:
  65. return PIXMAN_r5g6b5;
  66. case 24:
  67. return PIXMAN_r8g8b8;
  68. case 32:
  69. return PIXMAN_x8r8g8b8;
  70. }
  71. } else {
  72. switch (bpp) {
  73. case 24:
  74. return PIXMAN_b8g8r8;
  75. case 32:
  76. return PIXMAN_b8g8r8x8;
  77. break;
  78. }
  79. }
  80. return 0;
  81. }
  82. /* Note: drm is little endian, pixman is native endian */
  83. static const struct {
  84. uint32_t drm_format;
  85. pixman_format_code_t pixman_format;
  86. } drm_format_pixman_map[] = {
  87. { DRM_FORMAT_RGB888, PIXMAN_LE_r8g8b8 },
  88. { DRM_FORMAT_ARGB8888, PIXMAN_LE_a8r8g8b8 },
  89. { DRM_FORMAT_XRGB8888, PIXMAN_LE_x8r8g8b8 }
  90. };
  91. pixman_format_code_t qemu_drm_format_to_pixman(uint32_t drm_format)
  92. {
  93. int i;
  94. for (i = 0; i < ARRAY_SIZE(drm_format_pixman_map); i++) {
  95. if (drm_format == drm_format_pixman_map[i].drm_format) {
  96. return drm_format_pixman_map[i].pixman_format;
  97. }
  98. }
  99. return 0;
  100. }
  101. uint32_t qemu_pixman_to_drm_format(pixman_format_code_t pixman_format)
  102. {
  103. int i;
  104. for (i = 0; i < ARRAY_SIZE(drm_format_pixman_map); i++) {
  105. if (pixman_format == drm_format_pixman_map[i].pixman_format) {
  106. return drm_format_pixman_map[i].drm_format;
  107. }
  108. }
  109. return 0;
  110. }
  111. int qemu_pixman_get_type(int rshift, int gshift, int bshift)
  112. {
  113. int type = PIXMAN_TYPE_OTHER;
  114. if (rshift > gshift && gshift > bshift) {
  115. if (bshift == 0) {
  116. type = PIXMAN_TYPE_ARGB;
  117. } else {
  118. type = PIXMAN_TYPE_RGBA;
  119. }
  120. } else if (rshift < gshift && gshift < bshift) {
  121. if (rshift == 0) {
  122. type = PIXMAN_TYPE_ABGR;
  123. } else {
  124. type = PIXMAN_TYPE_BGRA;
  125. }
  126. }
  127. return type;
  128. }
  129. pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf)
  130. {
  131. pixman_format_code_t format;
  132. int type;
  133. type = qemu_pixman_get_type(pf->rshift, pf->gshift, pf->bshift);
  134. format = PIXMAN_FORMAT(pf->bits_per_pixel, type,
  135. pf->abits, pf->rbits, pf->gbits, pf->bbits);
  136. if (!pixman_format_supported_source(format)) {
  137. return 0;
  138. }
  139. return format;
  140. }
  141. /*
  142. * Return true for known-good pixman conversions.
  143. *
  144. * UIs using pixman for format conversion can hook this into
  145. * DisplayChangeListenerOps->dpy_gfx_check_format
  146. */
  147. bool qemu_pixman_check_format(DisplayChangeListener *dcl,
  148. pixman_format_code_t format)
  149. {
  150. switch (format) {
  151. /* 32 bpp */
  152. case PIXMAN_x8r8g8b8:
  153. case PIXMAN_a8r8g8b8:
  154. case PIXMAN_b8g8r8x8:
  155. case PIXMAN_b8g8r8a8:
  156. /* 24 bpp */
  157. case PIXMAN_r8g8b8:
  158. case PIXMAN_b8g8r8:
  159. /* 16 bpp */
  160. case PIXMAN_x1r5g5b5:
  161. case PIXMAN_r5g6b5:
  162. return true;
  163. default:
  164. return false;
  165. }
  166. }
  167. pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format,
  168. int width)
  169. {
  170. pixman_image_t *image = pixman_image_create_bits(format, width, 1, NULL, 0);
  171. assert(image != NULL);
  172. return image;
  173. }
  174. /* fill linebuf from framebuffer */
  175. void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb,
  176. int width, int x, int y)
  177. {
  178. pixman_image_composite(PIXMAN_OP_SRC, fb, NULL, linebuf,
  179. x, y, 0, 0, 0, 0, width, 1);
  180. }
  181. /* copy linebuf to framebuffer */
  182. void qemu_pixman_linebuf_copy(pixman_image_t *fb, int width, int x, int y,
  183. pixman_image_t *linebuf)
  184. {
  185. pixman_image_composite(PIXMAN_OP_SRC, linebuf, NULL, fb,
  186. 0, 0, 0, 0, x, y, 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. void qemu_pixman_image_unref(pixman_image_t *image)
  198. {
  199. if (image == NULL) {
  200. return;
  201. }
  202. pixman_image_unref(image);
  203. }
  204. pixman_color_t qemu_pixman_color(PixelFormat *pf, uint32_t color)
  205. {
  206. pixman_color_t c;
  207. c.red = ((color & pf->rmask) >> pf->rshift) << (16 - pf->rbits);
  208. c.green = ((color & pf->gmask) >> pf->gshift) << (16 - pf->gbits);
  209. c.blue = ((color & pf->bmask) >> pf->bshift) << (16 - pf->bbits);
  210. c.alpha = ((color & pf->amask) >> pf->ashift) << (16 - pf->abits);
  211. return c;
  212. }
  213. pixman_image_t *qemu_pixman_glyph_from_vgafont(int height, const uint8_t *font,
  214. unsigned int ch)
  215. {
  216. pixman_image_t *glyph;
  217. uint8_t *data;
  218. bool bit;
  219. int x, y;
  220. glyph = pixman_image_create_bits(PIXMAN_a8, 8, height,
  221. NULL, 0);
  222. data = (uint8_t *)pixman_image_get_data(glyph);
  223. font += height * ch;
  224. for (y = 0; y < height; y++, font++) {
  225. for (x = 0; x < 8; x++, data++) {
  226. bit = (*font) & (1 << (7-x));
  227. *data = bit ? 0xff : 0x00;
  228. }
  229. }
  230. return glyph;
  231. }
  232. void qemu_pixman_glyph_render(pixman_image_t *glyph,
  233. pixman_image_t *surface,
  234. pixman_color_t *fgcol,
  235. pixman_color_t *bgcol,
  236. int x, int y, int cw, int ch)
  237. {
  238. pixman_image_t *ifg = pixman_image_create_solid_fill(fgcol);
  239. pixman_image_t *ibg = pixman_image_create_solid_fill(bgcol);
  240. pixman_image_composite(PIXMAN_OP_SRC, ibg, NULL, surface,
  241. 0, 0, 0, 0,
  242. cw * x, ch * y,
  243. cw, ch);
  244. pixman_image_composite(PIXMAN_OP_OVER, ifg, glyph, surface,
  245. 0, 0, 0, 0,
  246. cw * x, ch * y,
  247. cw, ch);
  248. pixman_image_unref(ifg);
  249. pixman_image_unref(ibg);
  250. }