2 * PixelFormat conversion library.
4 * Author: Gerd Hoffmann <kraxel@redhat.com>
6 * This work is licensed under the terms of the GNU GPL, version 2. See
7 * the COPYING file in the top-level directory.
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.
12 #include "qemu-common.h"
16 typedef struct QemuPixel QemuPixel
;
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
);
30 /* for copy_generic() */
31 pf_convert_from conv_from
;
32 pf_convert_to conv_to
;
44 /* ----------------------------------------------------------------------- */
45 /* PixelFormat -> QemuPixel conversions */
47 static void conv_16_to_pixel(PixelFormat
*pf
,
48 QemuPixel
*dst
, void *src
, uint32_t cnt
)
50 uint16_t *src16
= src
;
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
--;
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
)
65 uint32_t *src32
= src
;
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
--;
76 static void conv_32_to_pixel_generic(PixelFormat
*pf
,
77 QemuPixel
*dst
, void *src
, uint32_t cnt
)
79 uint32_t *src32
= src
;
83 dst
->red
= ((*src32
& pf
->rmask
) >> pf
->rshift
) << (8 - pf
->rbits
);
85 dst
->red
= ((*src32
& pf
->rmask
) >> pf
->rshift
) >> (pf
->rbits
- 8);
88 dst
->green
= ((*src32
& pf
->gmask
) >> pf
->gshift
) << (8 - pf
->gbits
);
90 dst
->green
= ((*src32
& pf
->gmask
) >> pf
->gshift
) >> (pf
->gbits
- 8);
93 dst
->blue
= ((*src32
& pf
->bmask
) >> pf
->bshift
) << (8 - pf
->bbits
);
95 dst
->blue
= ((*src32
& pf
->bmask
) >> pf
->bshift
) >> (pf
->bbits
- 8);
98 dst
->alpha
= ((*src32
& pf
->amask
) >> pf
->ashift
) << (8 - pf
->abits
);
100 dst
->alpha
= ((*src32
& pf
->amask
) >> pf
->ashift
) >> (pf
->abits
- 8);
102 dst
++, src32
++, cnt
--;
106 /* ----------------------------------------------------------------------- */
107 /* QemuPixel -> PixelFormat conversions */
109 static void conv_pixel_to_16(PixelFormat
*pf
,
110 void *dst
, QemuPixel
*src
, uint32_t cnt
)
112 uint16_t *dst16
= dst
;
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
--;
123 static void conv_pixel_to_32(PixelFormat
*pf
,
124 void *dst
, QemuPixel
*src
, uint32_t cnt
)
126 uint32_t *dst32
= dst
;
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
--;
137 /* ----------------------------------------------------------------------- */
138 /* PixelFormat -> PixelFormat conversions */
140 static void convert_copy(QemuPfConv
*conv
, void *dst
, void *src
, uint32_t cnt
)
142 uint32_t bytes
= cnt
* conv
->src
.bytes_per_pixel
;
143 memcpy(dst
, src
, bytes
);
146 static void convert_generic(QemuPfConv
*conv
, void *dst
, void *src
, uint32_t cnt
)
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
);
152 conv
->conv_from(&conv
->src
, conv
->conv_buf
, src
, cnt
);
153 conv
->conv_to(&conv
->dst
, dst
, conv
->conv_buf
, cnt
);
156 /* ----------------------------------------------------------------------- */
157 /* public interface */
159 QemuPfConv
*qemu_pf_conv_get(PixelFormat
*dst
, PixelFormat
*src
)
161 QemuPfConv
*conv
= g_malloc0(sizeof(QemuPfConv
));
166 if (memcmp(&conv
->src
, &conv
->dst
, sizeof(PixelFormat
)) == 0) {
167 /* formats identical, can simply copy */
168 conv
->convert
= convert_copy
;
170 /* generic two-step conversion: src -> QemuPixel -> dst */
171 switch (conv
->src
.bytes_per_pixel
) {
173 conv
->conv_from
= conv_16_to_pixel
;
176 if (conv
->src
.rbits
== 8 && conv
->src
.gbits
== 8 && conv
->src
.bbits
== 8) {
177 conv
->conv_from
= conv_32_to_pixel_fast
;
179 conv
->conv_from
= conv_32_to_pixel_generic
;
185 switch (conv
->dst
.bytes_per_pixel
) {
187 conv
->conv_to
= conv_pixel_to_16
;
190 conv
->conv_to
= conv_pixel_to_32
;
195 conv
->convert
= convert_generic
;
204 void qemu_pf_conv_run(QemuPfConv
*conv
, void *dst
, void *src
, uint32_t cnt
)
206 conv
->convert(conv
, dst
, src
, cnt
);
209 void qemu_pf_conv_put(QemuPfConv
*conv
)
212 g_free(conv
->conv_buf
);