qemu/pflib.c
<<
>>
Prefs
   1/*
   2 * PixelFormat conversion library.
   3 *
   4 * Author: Gerd Hoffmann <kraxel@redhat.com>
   5 *
   6 * This work is licensed under the terms of the GNU GPL, version 2.  See
   7 * the COPYING file in the top-level directory.
   8 *
   9 */
  10#include "qemu-common.h"
  11#include "console.h"
  12#include "pflib.h"
  13
  14typedef struct QemuPixel QemuPixel;
  15
  16typedef void (*pf_convert)(QemuPfConv *conv,
  17                           void *dst, void *src, uint32_t cnt);
  18typedef void (*pf_convert_from)(PixelFormat *pf,
  19                                QemuPixel *dst, void *src, uint32_t cnt);
  20typedef void (*pf_convert_to)(PixelFormat *pf,
  21                              void *dst, QemuPixel *src, uint32_t cnt);
  22
  23struct QemuPfConv {
  24    pf_convert        convert;
  25    PixelFormat       src;
  26    PixelFormat       dst;
  27
  28    /* for copy_generic() */
  29    pf_convert_from   conv_from;
  30    pf_convert_to     conv_to;
  31    QemuPixel         *conv_buf;
  32    uint32_t          conv_cnt;
  33};
  34
  35struct QemuPixel {
  36    uint8_t red;
  37    uint8_t green;
  38    uint8_t blue;
  39    uint8_t alpha;
  40};
  41
  42/* ----------------------------------------------------------------------- */
  43/* PixelFormat -> QemuPixel conversions                                    */
  44
  45static void conv_16_to_pixel(PixelFormat *pf,
  46                             QemuPixel *dst, void *src, uint32_t cnt)
  47{
  48    uint16_t *src16 = src;
  49
  50    while (cnt > 0) {
  51        dst->red   = ((*src16 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
  52        dst->green = ((*src16 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
  53        dst->blue  = ((*src16 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
  54        dst->alpha = ((*src16 & pf->amask) >> pf->ashift) << (8 - pf->abits);
  55        dst++, src16++, cnt--;
  56    }
  57}
  58
  59/* assumes pf->{r,g,b,a}bits == 8 */
  60static void conv_32_to_pixel_fast(PixelFormat *pf,
  61                                  QemuPixel *dst, void *src, uint32_t cnt)
  62{
  63    uint32_t *src32 = src;
  64
  65    while (cnt > 0) {
  66        dst->red   = (*src32 & pf->rmask) >> pf->rshift;
  67        dst->green = (*src32 & pf->gmask) >> pf->gshift;
  68        dst->blue  = (*src32 & pf->bmask) >> pf->bshift;
  69        dst->alpha = (*src32 & pf->amask) >> pf->ashift;
  70        dst++, src32++, cnt--;
  71    }
  72}
  73
  74static void conv_32_to_pixel_generic(PixelFormat *pf,
  75                                     QemuPixel *dst, void *src, uint32_t cnt)
  76{
  77    uint32_t *src32 = src;
  78
  79    while (cnt > 0) {
  80        if (pf->rbits < 8) {
  81            dst->red   = ((*src32 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
  82        } else {
  83            dst->red   = ((*src32 & pf->rmask) >> pf->rshift) >> (pf->rbits - 8);
  84        }
  85        if (pf->gbits < 8) {
  86            dst->green = ((*src32 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
  87        } else {
  88            dst->green = ((*src32 & pf->gmask) >> pf->gshift) >> (pf->gbits - 8);
  89        }
  90        if (pf->bbits < 8) {
  91            dst->blue  = ((*src32 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
  92        } else {
  93            dst->blue  = ((*src32 & pf->bmask) >> pf->bshift) >> (pf->bbits - 8);
  94        }
  95        if (pf->abits < 8) {
  96            dst->alpha = ((*src32 & pf->amask) >> pf->ashift) << (8 - pf->abits);
  97        } else {
  98            dst->alpha = ((*src32 & pf->amask) >> pf->ashift) >> (pf->abits - 8);
  99        }
 100        dst++, src32++, cnt--;
 101    }
 102}
 103
 104/* ----------------------------------------------------------------------- */
 105/* QemuPixel -> PixelFormat conversions                                    */
 106
 107static void conv_pixel_to_16(PixelFormat *pf,
 108                             void *dst, QemuPixel *src, uint32_t cnt)
 109{
 110    uint16_t *dst16 = dst;
 111
 112    while (cnt > 0) {
 113        *dst16  = ((uint16_t)src->red   >> (8 - pf->rbits)) << pf->rshift;
 114        *dst16 |= ((uint16_t)src->green >> (8 - pf->gbits)) << pf->gshift;
 115        *dst16 |= ((uint16_t)src->blue  >> (8 - pf->bbits)) << pf->bshift;
 116        *dst16 |= ((uint16_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
 117        dst16++, src++, cnt--;
 118    }
 119}
 120
 121static void conv_pixel_to_32(PixelFormat *pf,
 122                             void *dst, QemuPixel *src, uint32_t cnt)
 123{
 124    uint32_t *dst32 = dst;
 125
 126    while (cnt > 0) {
 127        *dst32  = ((uint32_t)src->red   >> (8 - pf->rbits)) << pf->rshift;
 128        *dst32 |= ((uint32_t)src->green >> (8 - pf->gbits)) << pf->gshift;
 129        *dst32 |= ((uint32_t)src->blue  >> (8 - pf->bbits)) << pf->bshift;
 130        *dst32 |= ((uint32_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
 131        dst32++, src++, cnt--;
 132    }
 133}
 134
 135/* ----------------------------------------------------------------------- */
 136/* PixelFormat -> PixelFormat conversions                                  */
 137
 138static void convert_copy(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
 139{
 140    uint32_t bytes = cnt * conv->src.bytes_per_pixel;
 141    memcpy(dst, src, bytes);
 142}
 143
 144static void convert_generic(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
 145{
 146    if (conv->conv_cnt < cnt) {
 147        conv->conv_cnt = cnt;
 148        conv->conv_buf = qemu_realloc(conv->conv_buf, sizeof(QemuPixel) * conv->conv_cnt);
 149    }
 150    conv->conv_from(&conv->src, conv->conv_buf, src, cnt);
 151    conv->conv_to(&conv->dst, dst, conv->conv_buf, cnt);
 152}
 153
 154/* ----------------------------------------------------------------------- */
 155/* public interface                                                        */
 156
 157QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src)
 158{
 159    QemuPfConv *conv = qemu_mallocz(sizeof(QemuPfConv));
 160
 161    conv->src = *src;
 162    conv->dst = *dst;
 163
 164    if (memcmp(&conv->src, &conv->dst, sizeof(PixelFormat)) == 0) {
 165        /* formats identical, can simply copy */
 166        conv->convert = convert_copy;
 167    } else {
 168        /* generic two-step conversion: src -> QemuPixel -> dst  */
 169        switch (conv->src.bytes_per_pixel) {
 170        case 2:
 171            conv->conv_from = conv_16_to_pixel;
 172            break;
 173        case 4:
 174            if (conv->src.rbits == 8 && conv->src.gbits == 8 && conv->src.bbits == 8) {
 175                conv->conv_from = conv_32_to_pixel_fast;
 176            } else {
 177                conv->conv_from = conv_32_to_pixel_generic;
 178            }
 179            break;
 180        default:
 181            goto err;
 182        }
 183        switch (conv->dst.bytes_per_pixel) {
 184        case 2:
 185            conv->conv_to = conv_pixel_to_16;
 186            break;
 187        case 4:
 188            conv->conv_to = conv_pixel_to_32;
 189            break;
 190        default:
 191            goto err;
 192        }
 193        conv->convert = convert_generic;
 194    }
 195    return conv;
 196
 197err:
 198    qemu_free(conv);
 199    return NULL;
 200}
 201
 202void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
 203{
 204    conv->convert(conv, dst, src, cnt);
 205}
 206
 207void qemu_pf_conv_put(QemuPfConv *conv)
 208{
 209    if (conv) {
 210        qemu_free(conv->conv_buf);
 211        qemu_free(conv);
 212    }
 213}
 214