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.
10 #include "qemu-common.h"
14 typedef struct QemuPixel QemuPixel
;
16 typedef void (*pf_convert
)(QemuPfConv
*conv
,
17 void *dst
, void *src
, uint32_t cnt
);
18 typedef void (*pf_convert_from
)(PixelFormat
*pf
,
19 QemuPixel
*dst
, void *src
, uint32_t cnt
);
20 typedef void (*pf_convert_to
)(PixelFormat
*pf
,
21 void *dst
, QemuPixel
*src
, uint32_t cnt
);
28 /* for copy_generic() */
29 pf_convert_from conv_from
;
30 pf_convert_to conv_to
;
42 /* ----------------------------------------------------------------------- */
43 /* PixelFormat -> QemuPixel conversions */
45 static void conv_16_to_pixel(PixelFormat
*pf
,
46 QemuPixel
*dst
, void *src
, uint32_t cnt
)
48 uint16_t *src16
= src
;
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
--;
59 /* assumes pf->{r,g,b,a}bits == 8 */
60 static void conv_32_to_pixel_fast(PixelFormat
*pf
,
61 QemuPixel
*dst
, void *src
, uint32_t cnt
)
63 uint32_t *src32
= src
;
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
--;
74 static void conv_32_to_pixel_generic(PixelFormat
*pf
,
75 QemuPixel
*dst
, void *src
, uint32_t cnt
)
77 uint32_t *src32
= src
;
81 dst
->red
= ((*src32
& pf
->rmask
) >> pf
->rshift
) << (8 - pf
->rbits
);
83 dst
->red
= ((*src32
& pf
->rmask
) >> pf
->rshift
) >> (pf
->rbits
- 8);
86 dst
->green
= ((*src32
& pf
->gmask
) >> pf
->gshift
) << (8 - pf
->gbits
);
88 dst
->green
= ((*src32
& pf
->gmask
) >> pf
->gshift
) >> (pf
->gbits
- 8);
91 dst
->blue
= ((*src32
& pf
->bmask
) >> pf
->bshift
) << (8 - pf
->bbits
);
93 dst
->blue
= ((*src32
& pf
->bmask
) >> pf
->bshift
) >> (pf
->bbits
- 8);
96 dst
->alpha
= ((*src32
& pf
->amask
) >> pf
->ashift
) << (8 - pf
->abits
);
98 dst
->alpha
= ((*src32
& pf
->amask
) >> pf
->ashift
) >> (pf
->abits
- 8);
100 dst
++, src32
++, cnt
--;
104 /* ----------------------------------------------------------------------- */
105 /* QemuPixel -> PixelFormat conversions */
107 static void conv_pixel_to_16(PixelFormat
*pf
,
108 void *dst
, QemuPixel
*src
, uint32_t cnt
)
110 uint16_t *dst16
= dst
;
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
--;
121 static void conv_pixel_to_32(PixelFormat
*pf
,
122 void *dst
, QemuPixel
*src
, uint32_t cnt
)
124 uint32_t *dst32
= dst
;
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
--;
135 /* ----------------------------------------------------------------------- */
136 /* PixelFormat -> PixelFormat conversions */
138 static void convert_copy(QemuPfConv
*conv
, void *dst
, void *src
, uint32_t cnt
)
140 uint32_t bytes
= cnt
* conv
->src
.bytes_per_pixel
;
141 memcpy(dst
, src
, bytes
);
144 static void convert_generic(QemuPfConv
*conv
, void *dst
, void *src
, uint32_t cnt
)
146 if (conv
->conv_cnt
< cnt
) {
147 conv
->conv_cnt
= cnt
;
148 conv
->conv_buf
= g_realloc(conv
->conv_buf
, sizeof(QemuPixel
) * conv
->conv_cnt
);
150 conv
->conv_from(&conv
->src
, conv
->conv_buf
, src
, cnt
);
151 conv
->conv_to(&conv
->dst
, dst
, conv
->conv_buf
, cnt
);
154 /* ----------------------------------------------------------------------- */
155 /* public interface */
157 QemuPfConv
*qemu_pf_conv_get(PixelFormat
*dst
, PixelFormat
*src
)
159 QemuPfConv
*conv
= g_malloc0(sizeof(QemuPfConv
));
164 if (memcmp(&conv
->src
, &conv
->dst
, sizeof(PixelFormat
)) == 0) {
165 /* formats identical, can simply copy */
166 conv
->convert
= convert_copy
;
168 /* generic two-step conversion: src -> QemuPixel -> dst */
169 switch (conv
->src
.bytes_per_pixel
) {
171 conv
->conv_from
= conv_16_to_pixel
;
174 if (conv
->src
.rbits
== 8 && conv
->src
.gbits
== 8 && conv
->src
.bbits
== 8) {
175 conv
->conv_from
= conv_32_to_pixel_fast
;
177 conv
->conv_from
= conv_32_to_pixel_generic
;
183 switch (conv
->dst
.bytes_per_pixel
) {
185 conv
->conv_to
= conv_pixel_to_16
;
188 conv
->conv_to
= conv_pixel_to_32
;
193 conv
->convert
= convert_generic
;
202 void qemu_pf_conv_run(QemuPfConv
*conv
, void *dst
, void *src
, uint32_t cnt
)
204 conv
->convert(conv
, dst
, src
, cnt
);
207 void qemu_pf_conv_put(QemuPfConv
*conv
)
210 g_free(conv
->conv_buf
);