move test.h to libkmstest
[android/external-libkmsxx.git] / libkmstest / conv.cpp
1 #include <drm_fourcc.h>
2 #include <stdexcept>
4 #include "framebuffer.h"
5 #include "color.h"
6 #include "conv.h"
8 namespace kms
9 {
10 static RGB read_rgb(const Framebuffer& fb, int x, int y)
11 {
12         uint32_t *pc = (uint32_t *)(fb.map(0) + fb.stride(0) * y);
14         uint32_t c = pc[x];
16         return RGB((c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff);
17 }
19 static YUV read_rgb_as_yuv(const Framebuffer& fb, int x, int y)
20 {
21         RGB rgb = read_rgb(fb, x, y);
22         return YUV(rgb);
23 }
25 static void fb_rgb_to_packed_yuv(Framebuffer& dst_fb, const Framebuffer& src_fb)
26 {
27         unsigned w = src_fb.width();
28         unsigned h = src_fb.height();
30         uint8_t *dst = dst_fb.map(0);
32         for (unsigned y = 0; y < h; ++y) {
33                 for (unsigned x = 0; x < w; x += 2) {
34                         YUV yuv1 = read_rgb_as_yuv(src_fb, x + 0, y);
35                         YUV yuv2 = read_rgb_as_yuv(src_fb, x + 1, y);
37                         switch (dst_fb.format()) {
38                         case DRM_FORMAT_UYVY:
39                                 dst[x * 2 + 0] = (yuv1.u + yuv2.u) / 2;
40                                 dst[x * 2 + 1] = yuv1.y;
41                                 dst[x * 2 + 2] = (yuv1.v + yuv2.v) / 2;
42                                 dst[x * 2 + 3] = yuv2.y;
43                                 break;
44                         case DRM_FORMAT_YUYV:
45                                 dst[x * 2 + 0] = yuv1.y;
46                                 dst[x * 2 + 1] = (yuv1.u + yuv2.u) / 2;
47                                 dst[x * 2 + 2] = yuv2.y;
48                                 dst[x * 2 + 3] = (yuv1.v + yuv2.v) / 2;
49                                 break;
51                         default:
52                                 throw std::invalid_argument("fo");
53                         }
54                 }
56                 dst += dst_fb.stride(0);
57         }
58 }
60 static void fb_rgb_to_semiplanar_yuv(Framebuffer& dst_fb, const Framebuffer& src_fb)
61 {
62         unsigned w = src_fb.width();
63         unsigned h = src_fb.height();
65         uint8_t *dst_y = dst_fb.map(0);
66         uint8_t *dst_uv = dst_fb.map(1);
68         for (unsigned y = 0; y < h; ++y) {
69                 for (unsigned x = 0; x < w; ++x) {
70                         YUV yuv = read_rgb_as_yuv(src_fb, x, y);
71                         dst_y[x] = yuv.y;
72                 }
74                 dst_y += dst_fb.stride(0);
75         }
77         for (unsigned y = 0; y < h; y += 2) {
78                 for (unsigned x = 0; x < w; x += 2) {
79                         YUV yuv00 = read_rgb_as_yuv(src_fb, x + 0, y + 0);
80                         YUV yuv01 = read_rgb_as_yuv(src_fb, x + 1, y + 0);
81                         YUV yuv10 = read_rgb_as_yuv(src_fb, x + 0, y + 1);
82                         YUV yuv11 = read_rgb_as_yuv(src_fb, x + 1, y + 1);
84                         unsigned u = (yuv00.u + yuv01.u + yuv10.u + yuv11.u) / 4;
85                         unsigned v = (yuv00.v + yuv01.v + yuv10.v + yuv11.v) / 4;
87                         dst_uv[x + 0] = u;
88                         dst_uv[x + 1] = v;
89                 }
91                 dst_uv += dst_fb.stride(1);
92         }
93 }
95 static void fb_rgb_to_rgb565(Framebuffer& dst_fb, const Framebuffer& src_fb)
96 {
97         unsigned w = src_fb.width();
98         unsigned h = src_fb.height();
100         uint8_t *dst = dst_fb.map(0);
102         for (unsigned y = 0; y < h; ++y) {
103                 for (unsigned x = 0; x < w; ++x) {
104                         RGB rgb = read_rgb(src_fb, x, y);
106                         unsigned r = rgb.r * 32 / 256;
107                         unsigned g = rgb.g * 64 / 256;
108                         unsigned b = rgb.b * 32 / 256;
110                         ((uint16_t *)dst)[x] = (r << 11) | (g << 5) | (b << 0);
111                 }
113                 dst += dst_fb.stride(0);
114         }
117 void color_convert(Framebuffer& dst, const Framebuffer &src)
119         switch (dst.format()) {
120         case DRM_FORMAT_NV12:
121         case DRM_FORMAT_NV21:
122                 fb_rgb_to_semiplanar_yuv(dst, src);
123                 break;
125         case DRM_FORMAT_YUYV:
126         case DRM_FORMAT_UYVY:
127                 fb_rgb_to_packed_yuv(dst, src);
128                 break;
130         case DRM_FORMAT_RGB565:
131                 fb_rgb_to_rgb565(dst, src);
132                 break;
134         default:
135                 throw std::invalid_argument("fo");
136         }