1 /*
2 * Copyright 2024 (c) TOKITA Hiroshi
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/display.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/device.h>
10 #include <zephyr/logging/log.h>
11
12 LOG_MODULE_DECLARE(display_api, CONFIG_DISPLAY_LOG_LEVEL);
13
14 static const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
15 static const uint32_t display_width = DT_PROP(DT_CHOSEN(zephyr_display), width);
16 static const uint32_t display_height = DT_PROP(DT_CHOSEN(zephyr_display), height);
17 #ifdef CONFIG_DISPLAY_BUFFER_USE_GENERIC_SECTION
18 Z_GENERIC_SECTION(CONFIG_DISPLAY_BUFFER_SECTION)
19 #endif
20 static uint8_t disp_buffer[DT_PROP(DT_CHOSEN(zephyr_display), width) *
21 DT_PROP(DT_CHOSEN(zephyr_display), height) * 4]
22 __aligned(CONFIG_DISPLAY_BUFFER_ALIGNMENT);
23 static struct display_capabilities cfg;
24 static uint8_t bpp;
25 static bool is_tiled;
26
bytes_per_pixel(enum display_pixel_format pixel_format)27 static inline uint8_t bytes_per_pixel(enum display_pixel_format pixel_format)
28 {
29 switch (pixel_format) {
30 case PIXEL_FORMAT_ARGB_8888:
31 return 4;
32 case PIXEL_FORMAT_RGB_888:
33 return 3;
34 case PIXEL_FORMAT_RGB_565:
35 case PIXEL_FORMAT_BGR_565:
36 return 2;
37 case PIXEL_FORMAT_L_8:
38 case PIXEL_FORMAT_MONO01:
39 case PIXEL_FORMAT_MONO10:
40 default:
41 return 1;
42 }
43
44 return 0;
45 }
46
verify_bytes_of_area(uint8_t * data,int cmp_x,int cmp_y,size_t width,size_t height)47 static void verify_bytes_of_area(uint8_t *data, int cmp_x, int cmp_y, size_t width, size_t height)
48 {
49 struct display_buffer_descriptor desc = {
50 .height = height,
51 .pitch = width,
52 .width = width,
53 .buf_size = height * width * bpp,
54 };
55
56 int err = display_read(dev, cmp_x, cmp_y, &desc, disp_buffer);
57
58 zassert_ok(err, "display_read failed");
59
60 if (is_tiled) {
61 zassert_mem_equal(data, disp_buffer, width * height / 8, NULL);
62 } else {
63 zassert_mem_equal(data, disp_buffer, width * height * bpp, NULL);
64 }
65 }
66
verify_background_color(int x,int y,size_t width,size_t height,uint32_t color)67 static void verify_background_color(int x, int y, size_t width, size_t height, uint32_t color)
68 {
69 size_t buf_size = is_tiled ? (height * width / 8) : (height * width * bpp);
70 struct display_buffer_descriptor desc = {
71 .height = height,
72 .pitch = width,
73 .width = width,
74 .buf_size = buf_size,
75 };
76 uint32_t *buf32 = (void *)disp_buffer;
77 uint16_t *buf16 = (void *)disp_buffer;
78 uint8_t *buf8 = disp_buffer;
79 int err;
80
81 err = display_read(dev, x, y, &desc, disp_buffer);
82 zassert_ok(err, "display_read failed");
83
84 for (size_t i = 0; i < width * height; i++) {
85 switch (bpp) {
86 case 4:
87 zassert_equal(buf32[i], color, "@%d", i);
88 break;
89 case 2:
90 zassert_equal(buf16[i], (uint16_t)color, "@%d", i);
91 break;
92 case 1:
93 if (is_tiled) {
94 uint16_t x = i % (width);
95 uint16_t line = (i - x) / width;
96 uint16_t tile = line / 8;
97 uint16_t y = line % 8;
98
99 uint8_t *tptr = disp_buffer + (tile * width + x);
100
101 zassert_equal(!!(*tptr & BIT(y)), !!(color), "@%d", i);
102 } else {
103 zassert_equal(buf8[i], (uint8_t)color, "@%d", i);
104 }
105 break;
106 }
107 }
108 }
109
110 /**
111 * Fill the buffer with 0 before running tests.
112 */
display_before(void * text_fixture)113 static void display_before(void *text_fixture)
114 {
115 display_get_capabilities(dev, &cfg);
116 bpp = bytes_per_pixel(cfg.current_pixel_format);
117 is_tiled = ((bpp == 1) && (cfg.screen_info & SCREEN_INFO_MONO_VTILED));
118
119 struct display_buffer_descriptor desc = {
120 .height = display_height,
121 .pitch = display_width,
122 .width = display_width,
123 .buf_size = display_height * display_width * bpp,
124 };
125
126 memset(disp_buffer, 0, sizeof(disp_buffer));
127 display_write(dev, 0, 0, &desc, disp_buffer);
128 }
129
130 /*
131 * Verify that we can get a color of '0' from all pixels
132 * when after zeroing the buffer.
133 */
ZTEST(display_read_write,test_clear)134 ZTEST(display_read_write, test_clear)
135 {
136 verify_background_color(0, 0, display_width, display_height, 0);
137 }
138
139 /*
140 * Write to the head of the buffer and check that
141 * the same value can be read.
142 */
ZTEST(display_read_write,test_write_to_buffer_head)143 ZTEST(display_read_write, test_write_to_buffer_head)
144 {
145 uint8_t data[4] = {0xFA, 0xAF, 0x9F, 0xFA};
146 uint8_t height = (is_tiled ? 8 : 1);
147 uint16_t width = sizeof(data) / bpp;
148 uint16_t buf_size = width * bpp;
149 struct display_buffer_descriptor desc = {
150 .height = height,
151 .pitch = width,
152 .width = width,
153 .buf_size = buf_size,
154 };
155
156 /* write data to head of buffer */
157 display_write(dev, 0, 0, &desc, data);
158
159 /* check write data and read data are same */
160 verify_bytes_of_area(data, 0, 0, width, height);
161
162 /* check remaining region still black */
163 verify_background_color(0, height, display_width, display_height - height, 0);
164 verify_background_color(width, 0, display_width - width, display_height, 0);
165 }
166
167 /*
168 * Write to the tail of the buffer and check that
169 * the same value can be read.
170 */
ZTEST(display_read_write,test_write_to_buffer_tail)171 ZTEST(display_read_write, test_write_to_buffer_tail)
172 {
173 uint8_t data[4] = {0xFA, 0xAF, 0x9F, 0xFA};
174 uint16_t height = (is_tiled ? 8 : 1);
175 uint16_t width = sizeof(data) / bpp;
176 uint16_t buf_size = width * bpp;
177 struct display_buffer_descriptor desc = {
178 .height = height,
179 .pitch = width,
180 .width = width,
181 .buf_size = buf_size,
182 };
183 struct display_buffer_descriptor desc_whole = {
184 .height = display_height,
185 .pitch = display_width,
186 .width = display_width,
187 .buf_size = display_height * display_width * bpp / height,
188 };
189 int err;
190
191 /* write data to tail of buffer */
192 display_write(dev, display_width - width, display_height - height, &desc, data);
193
194 /* read entire displayed data */
195 err = display_read(dev, 0, 0, &desc_whole, disp_buffer);
196 zassert_ok(err, "display_read failed");
197
198 /* check write data and read data are same */
199 if (is_tiled) {
200 zassert_mem_equal(data,
201 disp_buffer + (display_width * display_height / 8 - buf_size),
202 buf_size, NULL);
203 } else {
204 zassert_mem_equal(data,
205 disp_buffer + (display_width * display_height * bpp - buf_size),
206 buf_size, NULL);
207 }
208
209 /* check remaining region still black */
210 verify_background_color(0, 0, display_width, display_height - height, 0);
211 verify_background_color(0, display_height - height, display_width - width, height, 0);
212 }
213
214 /*
215 * Verify that it will keep the drawn content even if display_read is executed
216 */
ZTEST(display_read_write,test_read_does_not_clear_existing_buffer)217 ZTEST(display_read_write, test_read_does_not_clear_existing_buffer)
218 {
219 uint8_t data[4] = {0xFA, 0xAF, 0x9F, 0xFA};
220 uint8_t height = (is_tiled ? 8 : 1);
221 uint16_t width = sizeof(data) / bpp;
222 uint16_t buf_size = width * bpp;
223 struct display_buffer_descriptor desc = {
224 .height = height,
225 .pitch = width,
226 .width = width,
227 .buf_size = buf_size,
228 };
229 struct display_buffer_descriptor desc_whole = {
230 .height = display_height,
231 .pitch = display_width,
232 .width = display_width,
233 .buf_size = display_height * display_width * bpp / height,
234 };
235 int err;
236
237 /* write data to head of buffer */
238 display_write(dev, 0, 0, &desc, data);
239
240 /* check write data and read data are same */
241 verify_bytes_of_area(data, 0, 0, width, height);
242
243 /* check remaining region still black */
244 verify_background_color(0, height, display_width, display_height - height, 0);
245 verify_background_color(width, 0, display_width - width, display_height, 0);
246
247 /* write data to tail of buffer */
248 display_write(dev, display_width - width, display_height - height, &desc, data);
249
250 /* read entire displayed data */
251 err = display_read(dev, 0, 0, &desc_whole, disp_buffer);
252 zassert_ok(err, "display_read failed");
253
254 /* checking correctly write to the tail of buffer */
255 if (is_tiled) {
256 zassert_mem_equal(data,
257 disp_buffer + (display_width * display_height / 8 - buf_size),
258 buf_size, NULL);
259 } else {
260 zassert_mem_equal(data,
261 disp_buffer + (display_width * display_height * bpp - buf_size),
262 buf_size, NULL);
263 }
264
265 /* checking if the content written before reading is kept */
266 verify_bytes_of_area(data, 0, 0, width, height);
267
268 /* checking remaining region is still black */
269 verify_background_color(width, 0, display_width - width, display_height - height, 0);
270 verify_background_color(0, height, display_width - width, display_height - height, 0);
271 }
272
273 ZTEST_SUITE(display_read_write, NULL, NULL, display_before, NULL, NULL);
274