1 /*
2  * Copyright (c) 2024 TOKITA Hiroshi
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "utils.h"
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/display.h>
11 #include <zephyr/ztest.h>
12 #include <zephyr/logging/log.h>
13 
14 LOG_MODULE_REGISTER(cfb_test_draw_text_and_print_utils, CONFIG_CFB_LOG_LEVEL);
15 
16 static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
17 static const uint32_t display_width = DT_PROP(DT_CHOSEN(zephyr_display), width);
18 static const uint32_t display_height = DT_PROP(DT_CHOSEN(zephyr_display), height);
19 uint8_t read_buffer[DT_PROP(DT_CHOSEN(zephyr_display), width) *
20 		    DT_PROP(DT_CHOSEN(zephyr_display), height) * 4];
21 
mono_pixel_order(uint32_t order)22 inline uint32_t mono_pixel_order(uint32_t order)
23 {
24 	if (IS_ENABLED(CONFIG_SDL_DISPLAY_MONO_MSB_FIRST)) {
25 		return BIT(7 - order);
26 	} else {
27 		return BIT(order);
28 	}
29 }
30 
display_pixel(int x,int y)31 uint32_t display_pixel(int x, int y)
32 {
33 	const uint8_t *ptr = read_buffer + (display_width * (y / 8) + x);
34 	struct display_capabilities display_caps;
35 
36 	display_get_capabilities(dev, &display_caps);
37 
38 	if (display_caps.current_pixel_format == PIXEL_FORMAT_MONO10) {
39 		return !(*ptr & mono_pixel_order(y % 8));
40 	}
41 
42 	return !!(*ptr & mono_pixel_order(y % 8));
43 }
44 
image_pixel(const uint32_t * img,size_t width,int x,int y)45 uint32_t image_pixel(const uint32_t *img, size_t width, int x, int y)
46 {
47 	const uint32_t *ptr = img + (width * y + x);
48 
49 	return !!(*ptr & 0xFFFFFF);
50 }
51 
verify_pixel(int x,int y,uint32_t color)52 bool verify_pixel(int x, int y, uint32_t color)
53 {
54 	struct display_buffer_descriptor desc = {
55 		.height = display_height,
56 		.pitch = display_width,
57 		.width = display_width,
58 		.buf_size = display_height * display_width / 8,
59 	};
60 
61 	zassert_ok(display_read(dev, 0, 0, &desc, read_buffer), "display_read failed");
62 
63 	return ((!!display_pixel(x, y)) == (!!color));
64 }
65 
verify_image(int cmp_x,int cmp_y,const uint32_t * img,size_t width,size_t height)66 bool verify_image(int cmp_x, int cmp_y, const uint32_t *img, size_t width, size_t height)
67 {
68 	struct display_buffer_descriptor desc = {
69 		.height = display_height,
70 		.pitch = display_width,
71 		.width = display_width,
72 		.buf_size = display_height * display_width / 8,
73 	};
74 
75 	zassert_ok(display_read(dev, 0, 0, &desc, read_buffer), "display_read failed");
76 
77 	for (size_t y = 0; y < height; y++) {
78 		for (size_t x = 0; x < width; x++) {
79 			uint32_t disp_pix = display_pixel(cmp_x + x, cmp_y + y);
80 			uint32_t img_pix = image_pixel(img, width, x, y);
81 
82 			if (disp_pix != img_pix) {
83 				LOG_INF("get_pixel(%d, %d) = %lu", x, y, disp_pix);
84 				LOG_INF("pixel_color(%d, %d) = %lu", x, y, img_pix);
85 				LOG_INF("disp@(0, %d) %p", y, read_buffer + (y * width / 8));
86 				LOG_HEXDUMP_INF(read_buffer + (y * width / 8), 64, "");
87 				LOG_INF("img@(0, %d) %p", y, (uint32_t *)img + (y * width));
88 				LOG_HEXDUMP_INF((uint32_t *)img + (y * width), 64, "");
89 				return false;
90 			}
91 		}
92 	}
93 
94 	return true;
95 }
96 
verify_color_inside_rect(int x,int y,size_t width,size_t height,uint32_t color)97 bool verify_color_inside_rect(int x, int y, size_t width, size_t height, uint32_t color)
98 {
99 	struct display_buffer_descriptor desc = {
100 		.height = display_height,
101 		.pitch = display_width,
102 		.width = display_width,
103 		.buf_size = display_height * display_width / 8,
104 	};
105 
106 	zassert_ok(display_read(dev, 0, 0, &desc, read_buffer), "display_read failed");
107 
108 	for (size_t y_ = 0; y_ < height; y_++) {
109 		for (size_t x_ = 0; x_ < width; x_++) {
110 			uint32_t disp_pix = display_pixel(x + x_, y + y_);
111 
112 			if (!!disp_pix != !!color) {
113 				return false;
114 			}
115 		}
116 	}
117 
118 	return true;
119 }
120 
verify_color_outside_rect(int x,int y,size_t width,size_t height,uint32_t color)121 bool verify_color_outside_rect(int x, int y, size_t width, size_t height, uint32_t color)
122 {
123 	bool ret = true;
124 
125 	if (x > 0) {
126 		ret = verify_color_inside_rect(0, 0, x, y + height, color);
127 		if (!ret) {
128 			return false;
129 		}
130 	}
131 
132 	if ((y + height) <= display_height) {
133 		ret = verify_color_inside_rect(0, y + height, x + width,
134 					       display_height - (y + height), color);
135 		if (!ret) {
136 			return false;
137 		}
138 	}
139 
140 	if ((x + width) <= display_width) {
141 		ret = verify_color_inside_rect(x + width, y, display_width - (x + width),
142 					       display_height - y, color);
143 		if (!ret) {
144 			return false;
145 		}
146 	}
147 
148 	if (y > 0) {
149 		ret = verify_color_inside_rect(x, 0, display_width - x, y, color);
150 		if (!ret) {
151 			return false;
152 		}
153 	}
154 
155 	return true;
156 }
157 
verify_image_and_bg(int x,int y,const uint32_t * img,size_t width,size_t height,uint32_t color)158 bool verify_image_and_bg(int x, int y, const uint32_t *img, size_t width, size_t height,
159 			 uint32_t color)
160 {
161 	bool ret = true;
162 
163 	ret = verify_image(x, y, img, width, height);
164 	if (!ret) {
165 		return false;
166 	}
167 
168 	ret = verify_color_outside_rect(x, y, width, height, color);
169 
170 	return ret;
171 }
172 
verify_pixel_and_bg(int x,int y,uint32_t pixcolor,uint32_t bgcolor)173 bool verify_pixel_and_bg(int x, int y, uint32_t pixcolor, uint32_t bgcolor)
174 {
175 	bool ret = true;
176 
177 	ret = verify_pixel(x, y, pixcolor);
178 	if (!ret) {
179 		return false;
180 	}
181 
182 	ret = verify_color_outside_rect(x, y, 1, 1, bgcolor);
183 
184 	return ret;
185 }
186