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