qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

qemu-pixman.c (8075B)


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