7
7
8
8
#define DT_DRV_COMPAT zephyr_sdl_dc
9
9
10
+ #include <zephyr/kernel.h>
10
11
#include <zephyr/drivers/display.h>
11
12
12
13
#include <string.h>
@@ -22,6 +23,26 @@ LOG_MODULE_REGISTER(display_sdl);
22
23
23
24
static uint32_t sdl_display_zoom_pct ;
24
25
26
+ enum sdl_display_op {
27
+ SDL_WRITE ,
28
+ SDL_BLANKING_OFF ,
29
+ SDL_BLANKING_ON ,
30
+ };
31
+
32
+ struct sdl_display_write {
33
+ uint16_t x ;
34
+ uint16_t y ;
35
+ const struct display_buffer_descriptor * desc ;
36
+ };
37
+
38
+ struct sdl_display_task {
39
+ enum sdl_display_op op ;
40
+ union {
41
+ struct sdl_display_write write ;
42
+ };
43
+ };
44
+
45
+
25
46
struct sdl_display_config {
26
47
uint16_t height ;
27
48
uint16_t width ;
@@ -38,6 +59,13 @@ struct sdl_display_data {
38
59
enum display_pixel_format current_pixel_format ;
39
60
uint8_t * buf ;
40
61
uint8_t * read_buf ;
62
+
63
+ struct k_spinlock lock ;
64
+ struct k_thread sdl_thread ;
65
+
66
+ K_KERNEL_STACK_MEMBER (sdl_thread_stack , CONFIG_SDL_DISPLAY_THREAD_STACK_SIZE );
67
+ struct k_msgq * task_msgq ;
68
+ struct k_sem task_sem ;
41
69
};
42
70
43
71
static inline uint32_t mono_pixel_order (uint32_t order )
@@ -49,32 +77,42 @@ static inline uint32_t mono_pixel_order(uint32_t order)
49
77
}
50
78
}
51
79
52
- static int sdl_display_init (const struct device * dev )
80
+ static void exec_sdl_task (const struct device * dev , const struct sdl_display_task * task )
53
81
{
54
- const struct sdl_display_config * config = dev -> config ;
55
82
struct sdl_display_data * disp_data = dev -> data ;
56
- bool use_accelerator = true;
57
- LOG_DBG ("Initializing display driver" );
58
83
59
- IF_DISABLED (CONFIG_SDL_DISPLAY_USE_HARDWARE_ACCELERATOR , (use_accelerator = false));
84
+ K_SPINLOCK (& disp_data -> lock ) {
85
+ switch (task -> op ) {
86
+ case SDL_WRITE :
87
+ sdl_display_write_bottom (task -> write .desc -> height , task -> write .desc -> width ,
88
+ task -> write .x , task -> write .y , disp_data -> renderer ,
89
+ disp_data -> mutex , disp_data -> texture ,
90
+ disp_data -> background_texture , disp_data -> buf ,
91
+ disp_data -> display_on ,
92
+ task -> write .desc -> frame_incomplete );
93
+ break ;
94
+ case SDL_BLANKING_OFF :
95
+ sdl_display_blanking_off_bottom (disp_data -> renderer , disp_data -> texture ,
96
+ disp_data -> background_texture );
97
+ break ;
98
+ case SDL_BLANKING_ON :
99
+ sdl_display_blanking_on_bottom (disp_data -> renderer );
100
+ break ;
101
+ default :
102
+ LOG_ERR ("Unknown SDL task" );
103
+ break ;
104
+ }
105
+ }
106
+ }
60
107
61
- disp_data -> current_pixel_format =
62
- #if defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_RGB_888 )
63
- PIXEL_FORMAT_RGB_888
64
- #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_MONO01 )
65
- PIXEL_FORMAT_MONO01
66
- #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_MONO10 )
67
- PIXEL_FORMAT_MONO10
68
- #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_RGB_565 )
69
- PIXEL_FORMAT_RGB_565
70
- #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_BGR_565 )
71
- PIXEL_FORMAT_BGR_565
72
- #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_L_8 )
73
- PIXEL_FORMAT_L_8
74
- #else /* SDL_DISPLAY_DEFAULT_PIXEL_FORMAT */
75
- PIXEL_FORMAT_ARGB_8888
76
- #endif /* SDL_DISPLAY_DEFAULT_PIXEL_FORMAT */
77
- ;
108
+ static void sdl_task_thread (void * p1 , void * p2 , void * p3 )
109
+ {
110
+ const struct device * dev = p1 ;
111
+ struct sdl_display_data * disp_data = dev -> data ;
112
+ const struct sdl_display_config * config = dev -> config ;
113
+ struct sdl_display_task task ;
114
+ bool use_accelerator =
115
+ IS_ENABLED (CONFIG_SDL_DISPLAY_USE_HARDWARE_ACCELERATOR );
78
116
79
117
if (sdl_display_zoom_pct == UINT32_MAX ) {
80
118
sdl_display_zoom_pct = CONFIG_SDL_DISPLAY_ZOOM_PCT ;
@@ -91,11 +129,48 @@ static int sdl_display_init(const struct device *dev)
91
129
92
130
if (rc != 0 ) {
93
131
LOG_ERR ("Failed to create SDL display" );
94
- return - EIO ;
132
+ return ;
95
133
}
96
134
97
135
disp_data -> display_on = false;
98
136
137
+ while (1 ) {
138
+ k_msgq_get (disp_data -> task_msgq , & task , K_FOREVER );
139
+ exec_sdl_task (dev , & task );
140
+ k_sem_give (& disp_data -> task_sem );
141
+ }
142
+ }
143
+
144
+ static int sdl_display_init (const struct device * dev )
145
+ {
146
+ struct sdl_display_data * disp_data = dev -> data ;
147
+
148
+ LOG_DBG ("Initializing display driver" );
149
+
150
+ disp_data -> current_pixel_format =
151
+ #if defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_RGB_888 )
152
+ PIXEL_FORMAT_RGB_888
153
+ #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_MONO01 )
154
+ PIXEL_FORMAT_MONO01
155
+ #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_MONO10 )
156
+ PIXEL_FORMAT_MONO10
157
+ #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_RGB_565 )
158
+ PIXEL_FORMAT_RGB_565
159
+ #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_BGR_565 )
160
+ PIXEL_FORMAT_BGR_565
161
+ #elif defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_L_8 )
162
+ PIXEL_FORMAT_L_8
163
+ #else /* SDL_DISPLAY_DEFAULT_PIXEL_FORMAT */
164
+ PIXEL_FORMAT_ARGB_8888
165
+ #endif /* SDL_DISPLAY_DEFAULT_PIXEL_FORMAT */
166
+ ;
167
+
168
+ k_sem_init (& disp_data -> task_sem , 0 , 1 );
169
+ k_thread_create (& disp_data -> sdl_thread , disp_data -> sdl_thread_stack ,
170
+ K_KERNEL_STACK_SIZEOF (disp_data -> sdl_thread_stack ),
171
+ sdl_task_thread , (void * )dev , NULL , NULL ,
172
+ CONFIG_SDL_DISPLAY_THREAD_PRIORITY , 0 , K_NO_WAIT );
173
+
99
174
return 0 ;
100
175
}
101
176
@@ -253,6 +328,14 @@ static int sdl_display_write(const struct device *dev, const uint16_t x,
253
328
{
254
329
const struct sdl_display_config * config = dev -> config ;
255
330
struct sdl_display_data * disp_data = dev -> data ;
331
+ struct sdl_display_task task = {
332
+ .op = SDL_WRITE ,
333
+ .write = {
334
+ .x = x ,
335
+ .y = y ,
336
+ .desc = desc ,
337
+ },
338
+ };
256
339
257
340
LOG_DBG ("Writing %dx%d (w,h) bitmap @ %dx%d (x,y)" , desc -> width ,
258
341
desc -> height , x , y );
@@ -273,26 +356,30 @@ static int sdl_display_write(const struct device *dev, const uint16_t x,
273
356
return - EINVAL ;
274
357
}
275
358
276
- if (disp_data -> current_pixel_format == PIXEL_FORMAT_ARGB_8888 ) {
277
- sdl_display_write_argb8888 (disp_data -> buf , desc , buf );
278
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_RGB_888 ) {
279
- sdl_display_write_rgb888 (disp_data -> buf , desc , buf );
280
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_MONO10 ) {
281
- sdl_display_write_mono (disp_data -> buf , desc , buf , true);
282
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_MONO01 ) {
283
- sdl_display_write_mono (disp_data -> buf , desc , buf , false);
284
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_RGB_565 ) {
285
- sdl_display_write_rgb565 (disp_data -> buf , desc , buf );
286
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_BGR_565 ) {
287
- sdl_display_write_bgr565 (disp_data -> buf , desc , buf );
288
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_L_8 ) {
289
- sdl_display_write_l8 (disp_data -> buf , desc , buf );
359
+ K_SPINLOCK (& disp_data -> lock ) {
360
+ if (disp_data -> current_pixel_format == PIXEL_FORMAT_ARGB_8888 ) {
361
+ sdl_display_write_argb8888 (disp_data -> buf , desc , buf );
362
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_RGB_888 ) {
363
+ sdl_display_write_rgb888 (disp_data -> buf , desc , buf );
364
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_MONO10 ) {
365
+ sdl_display_write_mono (disp_data -> buf , desc , buf , true);
366
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_MONO01 ) {
367
+ sdl_display_write_mono (disp_data -> buf , desc , buf , false);
368
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_RGB_565 ) {
369
+ sdl_display_write_rgb565 (disp_data -> buf , desc , buf );
370
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_BGR_565 ) {
371
+ sdl_display_write_bgr565 (disp_data -> buf , desc , buf );
372
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_L_8 ) {
373
+ sdl_display_write_l8 (disp_data -> buf , desc , buf );
374
+ }
290
375
}
291
376
292
- sdl_display_write_bottom (desc -> height , desc -> width , x , y , disp_data -> renderer ,
293
- disp_data -> mutex , disp_data -> texture ,
294
- disp_data -> background_texture , disp_data -> buf ,
295
- disp_data -> display_on , desc -> frame_incomplete );
377
+ if (k_current_get () == & disp_data -> sdl_thread ) {
378
+ exec_sdl_task (dev , & task );
379
+ } else {
380
+ k_msgq_put (disp_data -> task_msgq , & task , K_FOREVER );
381
+ k_sem_take (& disp_data -> task_sem , K_FOREVER );
382
+ }
296
383
297
384
return 0 ;
298
385
}
@@ -438,40 +525,41 @@ static int sdl_display_read(const struct device *dev, const uint16_t x, const ui
438
525
const struct display_buffer_descriptor * desc , void * buf )
439
526
{
440
527
struct sdl_display_data * disp_data = dev -> data ;
441
- int err ;
528
+ int err = 0 ;
442
529
443
530
LOG_DBG ("Reading %dx%d (w,h) bitmap @ %dx%d (x,y)" , desc -> width ,
444
531
desc -> height , x , y );
445
532
446
533
__ASSERT (desc -> width <= desc -> pitch , "Pitch is smaller than width" );
447
534
448
- memset (disp_data -> read_buf , 0 , desc -> pitch * desc -> height * 4 );
535
+ K_SPINLOCK (& disp_data -> lock ) {
536
+ memset (disp_data -> read_buf , 0 , desc -> pitch * desc -> height * 4 );
449
537
450
- err = sdl_display_read_bottom (desc -> height , desc -> width , x , y , disp_data -> renderer ,
451
- disp_data -> read_buf , desc -> pitch , disp_data -> mutex ,
452
- disp_data -> texture , disp_data -> read_texture );
538
+ err = sdl_display_read_bottom (desc -> height , desc -> width , x , y , disp_data -> renderer ,
539
+ disp_data -> read_buf , desc -> pitch , disp_data -> mutex ,
540
+ disp_data -> texture , disp_data -> read_texture );
453
541
454
- if (err ) {
455
- return err ;
456
- }
542
+ if (err ) {
543
+ K_SPINLOCK_BREAK ;
544
+ }
457
545
458
- if (disp_data -> current_pixel_format == PIXEL_FORMAT_ARGB_8888 ) {
459
- sdl_display_read_argb8888 (disp_data -> read_buf , desc , buf );
460
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_RGB_888 ) {
461
- sdl_display_read_rgb888 (disp_data -> read_buf , desc , buf );
462
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_MONO10 ) {
463
- sdl_display_read_mono (disp_data -> read_buf , desc , buf , true);
464
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_MONO01 ) {
465
- sdl_display_read_mono (disp_data -> read_buf , desc , buf , false);
466
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_RGB_565 ) {
467
- sdl_display_read_rgb565 (disp_data -> read_buf , desc , buf );
468
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_BGR_565 ) {
469
- sdl_display_read_bgr565 (disp_data -> read_buf , desc , buf );
470
- } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_L_8 ) {
471
- sdl_display_read_l8 (disp_data -> read_buf , desc , buf );
546
+ if (disp_data -> current_pixel_format == PIXEL_FORMAT_ARGB_8888 ) {
547
+ sdl_display_read_argb8888 (disp_data -> read_buf , desc , buf );
548
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_RGB_888 ) {
549
+ sdl_display_read_rgb888 (disp_data -> read_buf , desc , buf );
550
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_MONO10 ) {
551
+ sdl_display_read_mono (disp_data -> read_buf , desc , buf , true);
552
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_MONO01 ) {
553
+ sdl_display_read_mono (disp_data -> read_buf , desc , buf , false);
554
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_RGB_565 ) {
555
+ sdl_display_read_rgb565 (disp_data -> read_buf , desc , buf );
556
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_BGR_565 ) {
557
+ sdl_display_read_bgr565 (disp_data -> read_buf , desc , buf );
558
+ } else if (disp_data -> current_pixel_format == PIXEL_FORMAT_L_8 ) {
559
+ sdl_display_read_l8 (disp_data -> read_buf , desc , buf );
560
+ }
472
561
}
473
-
474
- return 0 ;
562
+ return err ;
475
563
}
476
564
477
565
static int sdl_display_clear (const struct device * dev )
@@ -509,34 +597,57 @@ static int sdl_display_clear(const struct device *dev)
509
597
return - EINVAL ;
510
598
}
511
599
LOG_DBG ("size: %zu, bgcolor: %hhu" , size , bgcolor );
512
- memset (disp_data -> buf , bgcolor , size );
600
+
601
+ K_SPINLOCK (& disp_data -> lock ) {
602
+ memset (disp_data -> buf , bgcolor , size );
603
+ }
513
604
514
605
return 0 ;
515
606
}
516
607
517
608
static int sdl_display_blanking_off (const struct device * dev )
518
609
{
519
610
struct sdl_display_data * disp_data = dev -> data ;
611
+ struct sdl_display_task task = {
612
+ .op = SDL_BLANKING_OFF ,
613
+ };
520
614
521
615
LOG_DBG ("Turning display blacking off" );
522
616
523
- disp_data -> display_on = true;
617
+ K_SPINLOCK (& disp_data -> lock ) {
618
+ disp_data -> display_on = true;
619
+ }
524
620
525
- sdl_display_blanking_off_bottom (disp_data -> renderer , disp_data -> texture ,
526
- disp_data -> background_texture );
621
+ if (k_current_get () == & disp_data -> sdl_thread ) {
622
+ exec_sdl_task (dev , & task );
623
+ } else {
624
+ k_msgq_put (disp_data -> task_msgq , & task , K_FOREVER );
625
+ k_sem_take (& disp_data -> task_sem , K_FOREVER );
626
+ }
527
627
528
628
return 0 ;
529
629
}
530
630
531
631
static int sdl_display_blanking_on (const struct device * dev )
532
632
{
533
633
struct sdl_display_data * disp_data = dev -> data ;
634
+ struct sdl_display_task task = {
635
+ .op = SDL_BLANKING_ON ,
636
+ };
534
637
535
638
LOG_DBG ("Turning display blanking on" );
536
639
537
- disp_data -> display_on = false;
640
+ K_SPINLOCK (& disp_data -> lock ) {
641
+ disp_data -> display_on = false;
642
+ }
643
+
644
+ if (k_current_get () == & disp_data -> sdl_thread ) {
645
+ exec_sdl_task (dev , & task );
646
+ } else {
647
+ k_msgq_put (disp_data -> task_msgq , & task , K_FOREVER );
648
+ k_sem_take (& disp_data -> task_sem , K_FOREVER );
649
+ }
538
650
539
- sdl_display_blanking_on_bottom (disp_data -> renderer );
540
651
return 0 ;
541
652
}
542
653
@@ -609,9 +720,11 @@ static DEVICE_API(display, sdl_display_api) = {
609
720
* DT_INST_PROP(n, width)]; \
610
721
static uint8_t sdl_read_buf_##n[4 * DT_INST_PROP(n, height) \
611
722
* DT_INST_PROP(n, width)]; \
723
+ K_MSGQ_DEFINE(sdl_task_msgq_##n, sizeof(struct sdl_display_task), 1, 4); \
612
724
static struct sdl_display_data sdl_data_##n = { \
613
725
.buf = sdl_buf_##n, \
614
726
.read_buf = sdl_read_buf_##n, \
727
+ .task_msgq = &sdl_task_msgq_##n, \
615
728
}; \
616
729
\
617
730
DEVICE_DT_INST_DEFINE(n, &sdl_display_init, NULL, \
0 commit comments