Home | History | Annotate | Download | only in src
      1 
      2 //#define DRAW_PERF_PRINT
      3 
      4 #include <cstring>
      5 #include <cassert>
      6 #include <thread>
      7 
      8 #include <kms++/kms++.h>
      9 #include <kms++util/kms++util.h>
     10 
     11 using namespace std;
     12 
     13 namespace kms
     14 {
     15 
     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();
     20 
     21 	const unsigned mw = 20;
     22 
     23 	const unsigned xm1 = mw;
     24 	const unsigned xm2 = w - mw - 1;
     25 	const unsigned ym1 = mw;
     26 	const unsigned ym2 = h - mw - 1;
     27 
     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;
     63 
     64 			unsigned c = (y - ym1 - 1) % 256;
     65 
     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 			}
     91 
     92 			return RGB(r, g, b);
     93 		}
     94 	} else {
     95 		// black corners
     96 		return RGB(0, 0, 0);
     97 	}
     98 }
     99 
    100 static void draw_test_pattern_part(IFramebuffer& fb, unsigned start_y, unsigned end_y, YUVType yuvt)
    101 {
    102 	unsigned x, y;
    103 	unsigned w = fb.width();
    104 
    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;
    121 
    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;
    134 
    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 	}
    152 }
    153 
    154 static void draw_test_pattern_impl(IFramebuffer& fb, YUVType yuvt)
    155 {
    156 	if (fb.height() < 20) {
    157 		draw_test_pattern_part(fb, 0, fb.height(), yuvt);
    158 		return;
    159 	}
    160 
    161 	// Create the mmaps before starting the threads
    162 	for (unsigned i = 0; i < fb.num_planes(); ++i)
    163 		fb.map(0);
    164 
    165 	unsigned num_threads = thread::hardware_concurrency();
    166 	vector<thread> workers;
    167 
    168 	unsigned part = (fb.height() / num_threads) & ~1;
    169 
    170 	for (unsigned n = 0; n < num_threads; ++n) {
    171 		unsigned start = n * part;
    172 		unsigned end = start + part;
    173 
    174 		if (n == num_threads - 1)
    175 			end = fb.height();
    176 
    177 		workers.push_back(thread([&fb, start, end, yuvt]() { draw_test_pattern_part(fb, start, end, yuvt); }));
    178 	}
    179 
    180 	for (thread& t : workers)
    181 		t.join();
    182 }
    183 
    184 void draw_test_pattern(IFramebuffer &fb, YUVType yuvt)
    185 {
    186 #ifdef DRAW_PERF_PRINT
    187 	Stopwatch sw;
    188 	sw.start();
    189 #endif
    190 
    191 	draw_test_pattern_impl(fb, yuvt);
    192 
    193 #ifdef DRAW_PERF_PRINT
    194 	double us = sw.elapsed_us();
    195 	printf("draw took %u us\n", (unsigned)us);
    196 #endif
    197 }
    198 
    199 }
    200