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