libkmsxx: Add Android.bp file to build with AOSP
[android/external-libkmsxx.git] / kms++util / src / testpat.cpp
2 //#define DRAW_PERF_PRINT
4 #include <cstring>
5 #include <cassert>
6 #include <thread>
8 #include <kms++/kms++.h>
9 #include <kms++util/kms++util.h>
11 using namespace std;
13 namespace kms
14 {
16 static RGB get_test_pattern_pixel(IFramebuffer& fb, unsigned x, unsigned y)
17 {
18         const unsigned w = fb.width();
19         const unsigned h = fb.height();
21         const unsigned mw = 20;
23         const unsigned xm1 = mw;
24         const unsigned xm2 = w - mw - 1;
25         const unsigned ym1 = mw;
26         const unsigned ym2 = h - mw - 1;
28         // white margin lines
29         if (x == xm1 || x == xm2 || y == ym1 || y == ym2)
30                 return RGB(255, 255, 255);
31         // white box in top left corner
32         else if (x < xm1 && y < ym1)
33                 return RGB(255, 255, 255);
34         // white box outlines to corners
35         else if ((x == 0 || x == w - 1) && (y < ym1 || y > ym2))
36                 return RGB(255, 255, 255);
37         // white box outlines to corners
38         else if ((y == 0 || y == h - 1) && (x < xm1 || x > xm2))
39                 return RGB(255, 255, 255);
40         // blue bar on the left
41         else if (x < xm1 && (y > ym1 && y < ym2))
42                 return RGB(0, 0, 255);
43         // blue bar on the top
44         else if (y < ym1 && (x > xm1 && x < xm2))
45                 return RGB(0, 0, 255);
46         // red bar on the right
47         else if (x > xm2 && (y > ym1 && y < ym2))
48                 return RGB(255, 0, 0);
49         // red bar on the bottom
50         else if (y > ym2 && (x > xm1 && x < xm2))
51                 return RGB(255, 0, 0);
52         // inside the margins
53         else if (x > xm1 && x < xm2 && y > ym1 && y < ym2) {
54                 // diagonal line
55                 if (x == y || w - x == h - y)
56                         return RGB(255, 255, 255);
57                 // diagonal line
58                 else if (w - x - 1 == y || x == h - y - 1)
59                         return RGB(255, 255, 255);
60                 else {
61                         int t = (x - xm1 - 1) * 8 / (xm2 - xm1 - 1);
62                         unsigned r = 0, g = 0, b = 0;
64                         unsigned c = (y - ym1 - 1) % 256;
66                         switch (t) {
67                         case 0:
68                                 r = c;
69                                 break;
70                         case 1:
71                                 g = c;
72                                 break;
73                         case 2:
74                                 b = c;
75                                 break;
76                         case 3:
77                                 g = b = c;
78                                 break;
79                         case 4:
80                                 r = b = c;
81                                 break;
82                         case 5:
83                                 r = g = c;
84                                 break;
85                         case 6:
86                                 r = g = b = c;
87                                 break;
88                         case 7:
89                                 break;
90                         }
92                         return RGB(r, g, b);
93                 }
94         } else {
95                 // black corners
96                 return RGB(0, 0, 0);
97         }
98 }
100 static void draw_test_pattern_part(IFramebuffer& fb, unsigned start_y, unsigned end_y, YUVType yuvt)
102         unsigned x, y;
103         unsigned w = fb.width();
105         switch (fb.format()) {
106         case PixelFormat::XRGB8888:
107         case PixelFormat::XBGR8888:
108         case PixelFormat::ARGB8888:
109         case PixelFormat::ABGR8888:
110         case PixelFormat::RGB888:
111         case PixelFormat::BGR888:
112         case PixelFormat::RGB565:
113         case PixelFormat::BGR565:
114                 for (y = start_y; y < end_y; y++) {
115                         for (x = 0; x < w; x++) {
116                                 RGB pixel = get_test_pattern_pixel(fb, x, y);
117                                 draw_rgb_pixel(fb, x, y, pixel);
118                         }
119                 }
120                 break;
122         case PixelFormat::UYVY:
123         case PixelFormat::YUYV:
124         case PixelFormat::YVYU:
125         case PixelFormat::VYUY:
126                 for (y = start_y; y < end_y; y++) {
127                         for (x = 0; x < w; x += 2) {
128                                 RGB pixel1 = get_test_pattern_pixel(fb, x, y);
129                                 RGB pixel2 = get_test_pattern_pixel(fb, x + 1, y);
130                                 draw_yuv422_macropixel(fb, x, y, pixel1.yuv(yuvt), pixel2.yuv(yuvt));
131                         }
132                 }
133                 break;
135         case PixelFormat::NV12:
136         case PixelFormat::NV21:
137                 for (y = start_y; y < end_y; y += 2) {
138                         for (x = 0; x < w; x += 2) {
139                                 RGB pixel00 = get_test_pattern_pixel(fb, x, y);
140                                 RGB pixel10 = get_test_pattern_pixel(fb, x + 1, y);
141                                 RGB pixel01 = get_test_pattern_pixel(fb, x, y + 1);
142                                 RGB pixel11 = get_test_pattern_pixel(fb, x + 1, y + 1);
143                                 draw_yuv420_macropixel(fb, x, y,
144                                                        pixel00.yuv(yuvt), pixel10.yuv(yuvt),
145                                                        pixel01.yuv(yuvt), pixel11.yuv(yuvt));
146                         }
147                 }
148                 break;
149         default:
150                 throw std::invalid_argument("unknown pixelformat");
151         }
154 static void draw_test_pattern_impl(IFramebuffer& fb, YUVType yuvt)
156         if (fb.height() < 20) {
157                 draw_test_pattern_part(fb, 0, fb.height(), yuvt);
158                 return;
159         }
161         // Create the mmaps before starting the threads
162         for (unsigned i = 0; i < fb.num_planes(); ++i)
163                 fb.map(0);
165         unsigned num_threads = thread::hardware_concurrency();
166         vector<thread> workers;
168         unsigned part = (fb.height() / num_threads) & ~1;
170         for (unsigned n = 0; n < num_threads; ++n) {
171                 unsigned start = n * part;
172                 unsigned end = start + part;
174                 if (n == num_threads - 1)
175                         end = fb.height();
177                 workers.push_back(thread([&fb, start, end, yuvt]() { draw_test_pattern_part(fb, start, end, yuvt); }));
178         }
180         for (thread& t : workers)
181                 t.join();
184 void draw_test_pattern(IFramebuffer &fb, YUVType yuvt)
186 #ifdef DRAW_PERF_PRINT
187         Stopwatch sw;
188         sw.start();
189 #endif
191         draw_test_pattern_impl(fb, yuvt);
193 #ifdef DRAW_PERF_PRINT
194         double us = sw.elapsed_us();
195         printf("draw took %u us\n", (unsigned)us);
196 #endif