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
13
+ #include <nsi_tracing.h>
12
14
#include <string.h>
13
15
#include <stdlib.h>
14
16
#include <soc.h>
@@ -22,6 +24,26 @@ LOG_MODULE_REGISTER(display_sdl);
22
24
23
25
static uint32_t sdl_display_zoom_pct ;
24
26
27
+ enum sdl_display_op {
28
+ SDL_WRITE ,
29
+ SDL_BLANKING_OFF ,
30
+ SDL_BLANKING_ON ,
31
+ };
32
+
33
+ struct sdl_display_write {
34
+ uint16_t x ;
35
+ uint16_t y ;
36
+ const struct display_buffer_descriptor * desc ;
37
+ };
38
+
39
+ struct sdl_display_task {
40
+ enum sdl_display_op op ;
41
+ union {
42
+ struct sdl_display_write write ;
43
+ };
44
+ };
45
+
46
+
25
47
struct sdl_display_config {
26
48
uint16_t height ;
27
49
uint16_t width ;
@@ -38,6 +60,12 @@ struct sdl_display_data {
38
60
enum display_pixel_format current_pixel_format ;
39
61
uint8_t * buf ;
40
62
uint8_t * read_buf ;
63
+ struct k_thread sdl_thread ;
64
+
65
+ K_KERNEL_STACK_MEMBER (sdl_thread_stack , CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE );
66
+ struct k_msgq * task_msgq ;
67
+ struct k_sem task_sem ;
68
+ struct k_mutex task_mutex ;
41
69
};
42
70
43
71
static inline uint32_t mono_pixel_order (uint32_t order )
@@ -49,14 +77,73 @@ 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 )
81
+ {
82
+ struct sdl_display_data * disp_data = dev -> data ;
83
+
84
+ switch (task -> op ) {
85
+ case SDL_WRITE :
86
+ sdl_display_write_bottom (task -> write .desc -> height , task -> write .desc -> width ,
87
+ task -> write .x , task -> write .y , disp_data -> renderer ,
88
+ disp_data -> mutex , disp_data -> texture ,
89
+ disp_data -> background_texture , disp_data -> buf ,
90
+ disp_data -> display_on ,
91
+ task -> write .desc -> frame_incomplete );
92
+ break ;
93
+ case SDL_BLANKING_OFF :
94
+ sdl_display_blanking_off_bottom (disp_data -> renderer , disp_data -> texture ,
95
+ disp_data -> background_texture );
96
+ break ;
97
+ case SDL_BLANKING_ON :
98
+ sdl_display_blanking_on_bottom (disp_data -> renderer );
99
+ break ;
100
+ default :
101
+ LOG_ERR ("Unknown SDL task" );
102
+ break ;
103
+ }
104
+ }
105
+
106
+ static void sdl_task_thread (void * p1 , void * p2 , void * p3 )
53
107
{
108
+ const struct device * dev = p1 ;
109
+ struct sdl_display_data * disp_data = dev -> data ;
54
110
const struct sdl_display_config * config = dev -> config ;
111
+ struct sdl_display_task task ;
112
+ bool use_accelerator =
113
+ IS_ENABLED (CONFIG_SDL_DISPLAY_USE_HARDWARE_ACCELERATOR );
114
+
115
+ if (sdl_display_zoom_pct == UINT32_MAX ) {
116
+ sdl_display_zoom_pct = CONFIG_SDL_DISPLAY_ZOOM_PCT ;
117
+ }
118
+
119
+ int rc = sdl_display_init_bottom (config -> height , config -> width , sdl_display_zoom_pct ,
120
+ use_accelerator , & disp_data -> window , dev ,
121
+ & disp_data -> renderer , & disp_data -> mutex ,
122
+ & disp_data -> texture , & disp_data -> read_texture ,
123
+ & disp_data -> background_texture ,
124
+ CONFIG_SDL_DISPLAY_TRANSPARENCY_GRID_CELL_COLOR_1 ,
125
+ CONFIG_SDL_DISPLAY_TRANSPARENCY_GRID_CELL_COLOR_2 ,
126
+ CONFIG_SDL_DISPLAY_TRANSPARENCY_GRID_CELL_SIZE );
127
+
128
+ if (rc != 0 ) {
129
+ nsi_print_error_and_exit ("Failed to create SDL display" );
130
+ return ;
131
+ }
132
+
133
+ disp_data -> display_on = false;
134
+
135
+ while (1 ) {
136
+ k_msgq_get (disp_data -> task_msgq , & task , K_FOREVER );
137
+ exec_sdl_task (dev , & task );
138
+ k_sem_give (& disp_data -> task_sem );
139
+ }
140
+ }
141
+
142
+ static int sdl_display_init (const struct device * dev )
143
+ {
55
144
struct sdl_display_data * disp_data = dev -> data ;
56
- bool use_accelerator = true;
57
- LOG_DBG ("Initializing display driver" );
58
145
59
- IF_DISABLED ( CONFIG_SDL_DISPLAY_USE_HARDWARE_ACCELERATOR , ( use_accelerator = false) );
146
+ LOG_DBG ( "Initializing display driver" );
60
147
61
148
disp_data -> current_pixel_format =
62
149
#if defined(CONFIG_SDL_DISPLAY_DEFAULT_PIXEL_FORMAT_RGB_888 )
@@ -76,25 +163,12 @@ static int sdl_display_init(const struct device *dev)
76
163
#endif /* SDL_DISPLAY_DEFAULT_PIXEL_FORMAT */
77
164
;
78
165
79
- if (sdl_display_zoom_pct == UINT32_MAX ) {
80
- sdl_display_zoom_pct = CONFIG_SDL_DISPLAY_ZOOM_PCT ;
81
- }
82
-
83
- int rc = sdl_display_init_bottom (config -> height , config -> width , sdl_display_zoom_pct ,
84
- use_accelerator , & disp_data -> window , dev ,
85
- & disp_data -> renderer , & disp_data -> mutex ,
86
- & disp_data -> texture , & disp_data -> read_texture ,
87
- & disp_data -> background_texture ,
88
- CONFIG_SDL_DISPLAY_TRANSPARENCY_GRID_CELL_COLOR_1 ,
89
- CONFIG_SDL_DISPLAY_TRANSPARENCY_GRID_CELL_COLOR_2 ,
90
- CONFIG_SDL_DISPLAY_TRANSPARENCY_GRID_CELL_SIZE );
91
-
92
- if (rc != 0 ) {
93
- LOG_ERR ("Failed to create SDL display" );
94
- return - EIO ;
95
- }
96
-
97
- disp_data -> display_on = false;
166
+ k_sem_init (& disp_data -> task_sem , 0 , 1 );
167
+ k_mutex_init (& disp_data -> task_mutex );
168
+ k_thread_create (& disp_data -> sdl_thread , disp_data -> sdl_thread_stack ,
169
+ K_KERNEL_STACK_SIZEOF (disp_data -> sdl_thread_stack ),
170
+ sdl_task_thread , (void * )dev , NULL , NULL ,
171
+ CONFIG_SDL_DISPLAY_THREAD_PRIORITY , 0 , K_NO_WAIT );
98
172
99
173
return 0 ;
100
174
}
@@ -253,6 +327,14 @@ static int sdl_display_write(const struct device *dev, const uint16_t x,
253
327
{
254
328
const struct sdl_display_config * config = dev -> config ;
255
329
struct sdl_display_data * disp_data = dev -> data ;
330
+ struct sdl_display_task task = {
331
+ .op = SDL_WRITE ,
332
+ .write = {
333
+ .x = x ,
334
+ .y = y ,
335
+ .desc = desc ,
336
+ },
337
+ };
256
338
257
339
LOG_DBG ("Writing %dx%d (w,h) bitmap @ %dx%d (x,y)" , desc -> width ,
258
340
desc -> height , x , y );
@@ -273,6 +355,7 @@ static int sdl_display_write(const struct device *dev, const uint16_t x,
273
355
return - EINVAL ;
274
356
}
275
357
358
+ k_mutex_lock (& disp_data -> task_mutex , K_FOREVER );
276
359
if (disp_data -> current_pixel_format == PIXEL_FORMAT_ARGB_8888 ) {
277
360
sdl_display_write_argb8888 (disp_data -> buf , desc , buf );
278
361
} else if (disp_data -> current_pixel_format == PIXEL_FORMAT_RGB_888 ) {
@@ -289,10 +372,14 @@ static int sdl_display_write(const struct device *dev, const uint16_t x,
289
372
sdl_display_write_l8 (disp_data -> buf , desc , buf );
290
373
}
291
374
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 );
375
+ if (k_current_get () == & disp_data -> sdl_thread ) {
376
+ exec_sdl_task (dev , & task );
377
+ } else {
378
+ k_msgq_put (disp_data -> task_msgq , & task , K_FOREVER );
379
+ k_sem_take (& disp_data -> task_sem , K_FOREVER );
380
+ }
381
+
382
+ k_mutex_unlock (& disp_data -> task_mutex );
296
383
297
384
return 0 ;
298
385
}
@@ -445,13 +532,15 @@ static int sdl_display_read(const struct device *dev, const uint16_t x, const ui
445
532
446
533
__ASSERT (desc -> width <= desc -> pitch , "Pitch is smaller than width" );
447
534
535
+ k_mutex_lock (& disp_data -> task_mutex , K_FOREVER );
448
536
memset (disp_data -> read_buf , 0 , desc -> pitch * desc -> height * 4 );
449
537
450
538
err = sdl_display_read_bottom (desc -> height , desc -> width , x , y , disp_data -> renderer ,
451
539
disp_data -> read_buf , desc -> pitch , disp_data -> mutex ,
452
540
disp_data -> texture , disp_data -> read_texture );
453
541
454
542
if (err ) {
543
+ k_mutex_unlock (& disp_data -> task_mutex );
455
544
return err ;
456
545
}
457
546
@@ -470,6 +559,7 @@ static int sdl_display_read(const struct device *dev, const uint16_t x, const ui
470
559
} else if (disp_data -> current_pixel_format == PIXEL_FORMAT_L_8 ) {
471
560
sdl_display_read_l8 (disp_data -> read_buf , desc , buf );
472
561
}
562
+ k_mutex_unlock (& disp_data -> task_mutex );
473
563
474
564
return 0 ;
475
565
}
@@ -509,34 +599,56 @@ static int sdl_display_clear(const struct device *dev)
509
599
return - EINVAL ;
510
600
}
511
601
LOG_DBG ("size: %zu, bgcolor: %hhu" , size , bgcolor );
602
+ k_mutex_lock (& disp_data -> task_mutex , K_FOREVER );
512
603
memset (disp_data -> buf , bgcolor , size );
604
+ k_mutex_unlock (& disp_data -> task_mutex );
513
605
514
606
return 0 ;
515
607
}
516
608
517
609
static int sdl_display_blanking_off (const struct device * dev )
518
610
{
519
611
struct sdl_display_data * disp_data = dev -> data ;
612
+ struct sdl_display_task task = {
613
+ .op = SDL_BLANKING_OFF ,
614
+ };
520
615
521
616
LOG_DBG ("Turning display blacking off" );
522
-
523
617
disp_data -> display_on = true;
618
+ k_mutex_lock (& disp_data -> task_mutex , K_FOREVER );
524
619
525
- sdl_display_blanking_off_bottom (disp_data -> renderer , disp_data -> texture ,
526
- disp_data -> background_texture );
620
+ if (k_current_get () == & disp_data -> sdl_thread ) {
621
+ exec_sdl_task (dev , & task );
622
+ } else {
623
+ k_msgq_put (disp_data -> task_msgq , & task , K_FOREVER );
624
+ k_sem_take (& disp_data -> task_sem , K_FOREVER );
625
+ }
626
+
627
+ k_mutex_unlock (& disp_data -> task_mutex );
527
628
528
629
return 0 ;
529
630
}
530
631
531
632
static int sdl_display_blanking_on (const struct device * dev )
532
633
{
533
634
struct sdl_display_data * disp_data = dev -> data ;
635
+ struct sdl_display_task task = {
636
+ .op = SDL_BLANKING_ON ,
637
+ };
534
638
535
639
LOG_DBG ("Turning display blanking on" );
536
-
537
640
disp_data -> display_on = false;
641
+ k_mutex_lock (& disp_data -> task_mutex , K_FOREVER );
642
+
643
+ if (k_current_get () == & disp_data -> sdl_thread ) {
644
+ exec_sdl_task (dev , & task );
645
+ } else {
646
+ k_msgq_put (disp_data -> task_msgq , & task , K_FOREVER );
647
+ k_sem_take (& disp_data -> task_sem , K_FOREVER );
648
+ }
649
+
650
+ k_mutex_unlock (& disp_data -> task_mutex );
538
651
539
- sdl_display_blanking_on_bottom (disp_data -> renderer );
540
652
return 0 ;
541
653
}
542
654
@@ -609,9 +721,11 @@ static DEVICE_API(display, sdl_display_api) = {
609
721
* DT_INST_PROP(n, width)]; \
610
722
static uint8_t sdl_read_buf_##n[4 * DT_INST_PROP(n, height) \
611
723
* DT_INST_PROP(n, width)]; \
724
+ K_MSGQ_DEFINE(sdl_task_msgq_##n, sizeof(struct sdl_display_task), 1, 4); \
612
725
static struct sdl_display_data sdl_data_##n = { \
613
726
.buf = sdl_buf_##n, \
614
727
.read_buf = sdl_read_buf_##n, \
728
+ .task_msgq = &sdl_task_msgq_##n, \
615
729
}; \
616
730
\
617
731
DEVICE_DT_INST_DEFINE(n, &sdl_display_init, NULL, \
0 commit comments