Add support for YVYU and VYUY
[android/external-libkmsxx.git] / libkmstest / conv.cpp
1 #include <drm_fourcc.h>
2 #include <stdexcept>
4 #include "kms++.h"
5 #include "color.h"
7 namespace kms
8 {
9 static RGB read_rgb(const DumbFramebuffer& fb, int x, int y)
10 {
11         uint32_t *pc = (uint32_t *)(fb.map(0) + fb.stride(0) * y);
13         uint32_t c = pc[x];
15         return RGB((c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff);
16 }
18 static YUV read_rgb_as_yuv(const DumbFramebuffer& fb, int x, int y)
19 {
20         RGB rgb = read_rgb(fb, x, y);
21         return YUV(rgb);
22 }
24 static void fb_rgb_to_packed_yuv(DumbFramebuffer& dst_fb, const DumbFramebuffer& src_fb)
25 {
26         unsigned w = src_fb.width();
27         unsigned h = src_fb.height();
29         uint8_t *dst = dst_fb.map(0);
31         for (unsigned y = 0; y < h; ++y) {
32                 for (unsigned x = 0; x < w; x += 2) {
33                         YUV yuv1 = read_rgb_as_yuv(src_fb, x + 0, y);
34                         YUV yuv2 = read_rgb_as_yuv(src_fb, x + 1, y);
36                         switch (dst_fb.format()) {
37                         case PixelFormat::UYVY:
38                                 dst[x * 2 + 0] = (yuv1.u + yuv2.u) / 2;
39                                 dst[x * 2 + 1] = yuv1.y;
40                                 dst[x * 2 + 2] = (yuv1.v + yuv2.v) / 2;
41                                 dst[x * 2 + 3] = yuv2.y;
42                                 break;
43                         case PixelFormat::YUYV:
44                                 dst[x * 2 + 0] = yuv1.y;
45                                 dst[x * 2 + 1] = (yuv1.u + yuv2.u) / 2;
46                                 dst[x * 2 + 2] = yuv2.y;
47                                 dst[x * 2 + 3] = (yuv1.v + yuv2.v) / 2;
48                                 break;
50                         default:
51                                 throw std::invalid_argument("fo");
52                         }
53                 }
55                 dst += dst_fb.stride(0);
56         }
57 }
59 static void fb_rgb_to_semiplanar_yuv(DumbFramebuffer& dst_fb, const DumbFramebuffer& src_fb)
60 {
61         unsigned w = src_fb.width();
62         unsigned h = src_fb.height();
64         uint8_t *dst_y = dst_fb.map(0);
65         uint8_t *dst_uv = dst_fb.map(1);
67         for (unsigned y = 0; y < h; ++y) {
68                 for (unsigned x = 0; x < w; ++x) {
69                         YUV yuv = read_rgb_as_yuv(src_fb, x, y);
70                         dst_y[x] = yuv.y;
71                 }
73                 dst_y += dst_fb.stride(0);
74         }
76         for (unsigned y = 0; y < h; y += 2) {
77                 for (unsigned x = 0; x < w; x += 2) {
78                         YUV yuv00 = read_rgb_as_yuv(src_fb, x + 0, y + 0);
79                         YUV yuv01 = read_rgb_as_yuv(src_fb, x + 1, y + 0);
80                         YUV yuv10 = read_rgb_as_yuv(src_fb, x + 0, y + 1);
81                         YUV yuv11 = read_rgb_as_yuv(src_fb, x + 1, y + 1);
83                         unsigned u = (yuv00.u + yuv01.u + yuv10.u + yuv11.u) / 4;
84                         unsigned v = (yuv00.v + yuv01.v + yuv10.v + yuv11.v) / 4;
86                         dst_uv[x + 0] = u;
87                         dst_uv[x + 1] = v;
88                 }
90                 dst_uv += dst_fb.stride(1);
91         }
92 }
94 static void fb_rgb_to_rgb565(DumbFramebuffer& dst_fb, const DumbFramebuffer& src_fb)
95 {
96         unsigned w = src_fb.width();
97         unsigned h = src_fb.height();
99         uint8_t *dst = dst_fb.map(0);
101         for (unsigned y = 0; y < h; ++y) {
102                 for (unsigned x = 0; x < w; ++x) {
103                         RGB rgb = read_rgb(src_fb, x, y);
105                         unsigned r = rgb.r * 32 / 256;
106                         unsigned g = rgb.g * 64 / 256;
107                         unsigned b = rgb.b * 32 / 256;
109                         ((uint16_t *)dst)[x] = (r << 11) | (g << 5) | (b << 0);
110                 }
112                 dst += dst_fb.stride(0);
113         }
116 void color_convert(DumbFramebuffer& dst, const DumbFramebuffer &src)
118         switch (dst.format()) {
119         case PixelFormat::NV12:
120         case PixelFormat::NV21:
121                 fb_rgb_to_semiplanar_yuv(dst, src);
122                 break;
124         case PixelFormat::YUYV:
125         case PixelFormat::UYVY:
126                 fb_rgb_to_packed_yuv(dst, src);
127                 break;
129         case PixelFormat::RGB565:
130                 fb_rgb_to_rgb565(dst, src);
131                 break;
133         default:
134                 throw std::invalid_argument("fo");
135         }