Statistics
| Branch: | Revision:

root / pflib.c @ ff5928d0

History | View | Annotate | Download (6.7 kB)

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
 * Contributions after 2012-01-13 are licensed under the terms of the
10
 * GNU GPL, version 2 or (at your option) any later version.
11
 */
12
#include "qemu-common.h"
13
#include "console.h"
14
#include "pflib.h"
15

    
16
typedef struct QemuPixel QemuPixel;
17

    
18
typedef void (*pf_convert)(QemuPfConv *conv,
19
                           void *dst, void *src, uint32_t cnt);
20
typedef void (*pf_convert_from)(PixelFormat *pf,
21
                                QemuPixel *dst, void *src, uint32_t cnt);
22
typedef void (*pf_convert_to)(PixelFormat *pf,
23
                              void *dst, QemuPixel *src, uint32_t cnt);
24

    
25
struct QemuPfConv {
26
    pf_convert        convert;
27
    PixelFormat       src;
28
    PixelFormat       dst;
29

    
30
    /* for copy_generic() */
31
    pf_convert_from   conv_from;
32
    pf_convert_to     conv_to;
33
    QemuPixel         *conv_buf;
34
    uint32_t          conv_cnt;
35
};
36

    
37
struct QemuPixel {
38
    uint8_t red;
39
    uint8_t green;
40
    uint8_t blue;
41
    uint8_t alpha;
42
};
43

    
44
/* ----------------------------------------------------------------------- */
45
/* PixelFormat -> QemuPixel conversions                                    */
46

    
47
static void conv_16_to_pixel(PixelFormat *pf,
48
                             QemuPixel *dst, void *src, uint32_t cnt)
49
{
50
    uint16_t *src16 = src;
51

    
52
    while (cnt > 0) {
53
        dst->red   = ((*src16 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
54
        dst->green = ((*src16 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
55
        dst->blue  = ((*src16 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
56
        dst->alpha = ((*src16 & pf->amask) >> pf->ashift) << (8 - pf->abits);
57
        dst++, src16++, cnt--;
58
    }
59
}
60

    
61
/* assumes pf->{r,g,b,a}bits == 8 */
62
static void conv_32_to_pixel_fast(PixelFormat *pf,
63
                                  QemuPixel *dst, void *src, uint32_t cnt)
64
{
65
    uint32_t *src32 = src;
66

    
67
    while (cnt > 0) {
68
        dst->red   = (*src32 & pf->rmask) >> pf->rshift;
69
        dst->green = (*src32 & pf->gmask) >> pf->gshift;
70
        dst->blue  = (*src32 & pf->bmask) >> pf->bshift;
71
        dst->alpha = (*src32 & pf->amask) >> pf->ashift;
72
        dst++, src32++, cnt--;
73
    }
74
}
75

    
76
static void conv_32_to_pixel_generic(PixelFormat *pf,
77
                                     QemuPixel *dst, void *src, uint32_t cnt)
78
{
79
    uint32_t *src32 = src;
80

    
81
    while (cnt > 0) {
82
        if (pf->rbits < 8) {
83
            dst->red   = ((*src32 & pf->rmask) >> pf->rshift) << (8 - pf->rbits);
84
        } else {
85
            dst->red   = ((*src32 & pf->rmask) >> pf->rshift) >> (pf->rbits - 8);
86
        }
87
        if (pf->gbits < 8) {
88
            dst->green = ((*src32 & pf->gmask) >> pf->gshift) << (8 - pf->gbits);
89
        } else {
90
            dst->green = ((*src32 & pf->gmask) >> pf->gshift) >> (pf->gbits - 8);
91
        }
92
        if (pf->bbits < 8) {
93
            dst->blue  = ((*src32 & pf->bmask) >> pf->bshift) << (8 - pf->bbits);
94
        } else {
95
            dst->blue  = ((*src32 & pf->bmask) >> pf->bshift) >> (pf->bbits - 8);
96
        }
97
        if (pf->abits < 8) {
98
            dst->alpha = ((*src32 & pf->amask) >> pf->ashift) << (8 - pf->abits);
99
        } else {
100
            dst->alpha = ((*src32 & pf->amask) >> pf->ashift) >> (pf->abits - 8);
101
        }
102
        dst++, src32++, cnt--;
103
    }
104
}
105

    
106
/* ----------------------------------------------------------------------- */
107
/* QemuPixel -> PixelFormat conversions                                    */
108

    
109
static void conv_pixel_to_16(PixelFormat *pf,
110
                             void *dst, QemuPixel *src, uint32_t cnt)
111
{
112
    uint16_t *dst16 = dst;
113

    
114
    while (cnt > 0) {
115
        *dst16  = ((uint16_t)src->red   >> (8 - pf->rbits)) << pf->rshift;
116
        *dst16 |= ((uint16_t)src->green >> (8 - pf->gbits)) << pf->gshift;
117
        *dst16 |= ((uint16_t)src->blue  >> (8 - pf->bbits)) << pf->bshift;
118
        *dst16 |= ((uint16_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
119
        dst16++, src++, cnt--;
120
    }
121
}
122

    
123
static void conv_pixel_to_32(PixelFormat *pf,
124
                             void *dst, QemuPixel *src, uint32_t cnt)
125
{
126
    uint32_t *dst32 = dst;
127

    
128
    while (cnt > 0) {
129
        *dst32  = ((uint32_t)src->red   >> (8 - pf->rbits)) << pf->rshift;
130
        *dst32 |= ((uint32_t)src->green >> (8 - pf->gbits)) << pf->gshift;
131
        *dst32 |= ((uint32_t)src->blue  >> (8 - pf->bbits)) << pf->bshift;
132
        *dst32 |= ((uint32_t)src->alpha >> (8 - pf->abits)) << pf->ashift;
133
        dst32++, src++, cnt--;
134
    }
135
}
136

    
137
/* ----------------------------------------------------------------------- */
138
/* PixelFormat -> PixelFormat conversions                                  */
139

    
140
static void convert_copy(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
141
{
142
    uint32_t bytes = cnt * conv->src.bytes_per_pixel;
143
    memcpy(dst, src, bytes);
144
}
145

    
146
static void convert_generic(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
147
{
148
    if (conv->conv_cnt < cnt) {
149
        conv->conv_cnt = cnt;
150
        conv->conv_buf = g_realloc(conv->conv_buf, sizeof(QemuPixel) * conv->conv_cnt);
151
    }
152
    conv->conv_from(&conv->src, conv->conv_buf, src, cnt);
153
    conv->conv_to(&conv->dst, dst, conv->conv_buf, cnt);
154
}
155

    
156
/* ----------------------------------------------------------------------- */
157
/* public interface                                                        */
158

    
159
QemuPfConv *qemu_pf_conv_get(PixelFormat *dst, PixelFormat *src)
160
{
161
    QemuPfConv *conv = g_malloc0(sizeof(QemuPfConv));
162

    
163
    conv->src = *src;
164
    conv->dst = *dst;
165

    
166
    if (memcmp(&conv->src, &conv->dst, sizeof(PixelFormat)) == 0) {
167
        /* formats identical, can simply copy */
168
        conv->convert = convert_copy;
169
    } else {
170
        /* generic two-step conversion: src -> QemuPixel -> dst  */
171
        switch (conv->src.bytes_per_pixel) {
172
        case 2:
173
            conv->conv_from = conv_16_to_pixel;
174
            break;
175
        case 4:
176
            if (conv->src.rbits == 8 && conv->src.gbits == 8 && conv->src.bbits == 8) {
177
                conv->conv_from = conv_32_to_pixel_fast;
178
            } else {
179
                conv->conv_from = conv_32_to_pixel_generic;
180
            }
181
            break;
182
        default:
183
            goto err;
184
        }
185
        switch (conv->dst.bytes_per_pixel) {
186
        case 2:
187
            conv->conv_to = conv_pixel_to_16;
188
            break;
189
        case 4:
190
            conv->conv_to = conv_pixel_to_32;
191
            break;
192
        default:
193
            goto err;
194
        }
195
        conv->convert = convert_generic;
196
    }
197
    return conv;
198

    
199
err:
200
    g_free(conv);
201
    return NULL;
202
}
203

    
204
void qemu_pf_conv_run(QemuPfConv *conv, void *dst, void *src, uint32_t cnt)
205
{
206
    conv->convert(conv, dst, src, cnt);
207
}
208

    
209
void qemu_pf_conv_put(QemuPfConv *conv)
210
{
211
    if (conv) {
212
        g_free(conv->conv_buf);
213
        g_free(conv);
214
    }
215
}