1 /*
2  * Copyright (c) 2018 Jan Van Winkel <jan.van_winkel@dxplore.eu>
3  * Copyright (c) 2023 Nordic Semiconductor
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <stdint.h>
9 #include <stddef.h>
10 #include <stdbool.h>
11 #include <SDL.h>
12 #include "nsi_tracing.h"
13 
sdl_display_init_bottom(uint16_t height,uint16_t width,uint16_t zoom_pct,bool use_accelerator,void ** window,void ** renderer,void ** mutex,void ** texture,void ** read_texture)14 int sdl_display_init_bottom(uint16_t height, uint16_t width, uint16_t zoom_pct,
15 			    bool use_accelerator, void **window, void **renderer, void **mutex,
16 			    void **texture, void **read_texture)
17 {
18 	*window = SDL_CreateWindow("Zephyr Display", SDL_WINDOWPOS_UNDEFINED,
19 				   SDL_WINDOWPOS_UNDEFINED, width * zoom_pct / 100,
20 				   height * zoom_pct / 100, SDL_WINDOW_SHOWN);
21 	if (*window == NULL) {
22 		nsi_print_warning("Failed to create SDL window: %s", SDL_GetError());
23 		return -1;
24 	}
25 
26 	if (use_accelerator) {
27 		*renderer = SDL_CreateRenderer(*window, -1, SDL_RENDERER_ACCELERATED);
28 	} else {
29 		*renderer = SDL_CreateRenderer(*window, -1, SDL_RENDERER_SOFTWARE);
30 	}
31 
32 	if (*renderer == NULL) {
33 		nsi_print_warning("Failed to create SDL renderer: %s",
34 				SDL_GetError());
35 		return -1;
36 	}
37 
38 	*mutex = SDL_CreateMutex();
39 	if (*mutex == NULL) {
40 		nsi_print_warning("Failed to create SDL mutex: %s", SDL_GetError());
41 		return -1;
42 	}
43 
44 	SDL_RenderSetLogicalSize(*renderer, width, height);
45 
46 	*texture = SDL_CreateTexture(*renderer, SDL_PIXELFORMAT_ARGB8888,
47 				     SDL_TEXTUREACCESS_STATIC, width, height);
48 	if (*texture == NULL) {
49 		nsi_print_warning("Failed to create SDL texture: %s", SDL_GetError());
50 		return -1;
51 	}
52 
53 	*read_texture = SDL_CreateTexture(*renderer, SDL_PIXELFORMAT_ARGB8888,
54 					  SDL_TEXTUREACCESS_TARGET, width, height);
55 	if (*read_texture == NULL) {
56 		nsi_print_warning("Failed to create SDL texture for read: %s", SDL_GetError());
57 		return -1;
58 	}
59 
60 	SDL_SetRenderDrawColor(*renderer, 0, 0, 0, 0xFF);
61 	SDL_RenderClear(*renderer);
62 	SDL_RenderPresent(*renderer);
63 
64 	return 0;
65 }
66 
sdl_display_write_bottom(const uint16_t height,const uint16_t width,const uint16_t x,const uint16_t y,void * renderer,void * mutex,void * texture,uint8_t * buf,bool display_on)67 void sdl_display_write_bottom(const uint16_t height, const uint16_t width,
68 			      const uint16_t x, const uint16_t y,
69 			      void *renderer, void *mutex, void *texture,
70 			      uint8_t *buf, bool display_on)
71 {
72 	SDL_Rect rect;
73 	int err;
74 
75 	rect.x = x;
76 	rect.y = y;
77 	rect.w = width;
78 	rect.h = height;
79 
80 	err = SDL_TryLockMutex(mutex);
81 	if (err) {
82 		nsi_print_warning("Failed to lock SDL mutex: %s", SDL_GetError());
83 		return;
84 	}
85 
86 	SDL_UpdateTexture(texture, &rect, buf, 4 * rect.w);
87 
88 	if (display_on) {
89 		SDL_RenderClear(renderer);
90 		SDL_RenderCopy(renderer, texture, NULL, NULL);
91 		SDL_RenderPresent(renderer);
92 	}
93 
94 	SDL_UnlockMutex(mutex);
95 }
96 
sdl_display_read_bottom(const uint16_t height,const uint16_t width,const uint16_t x,const uint16_t y,void * renderer,void * buf,uint16_t pitch,void * mutex,void * texture,void * read_texture)97 int sdl_display_read_bottom(const uint16_t height, const uint16_t width,
98 			    const uint16_t x, const uint16_t y,
99 			    void *renderer, void *buf, uint16_t pitch,
100 			    void *mutex, void *texture, void *read_texture)
101 {
102 	SDL_Rect rect;
103 	int err;
104 
105 	rect.x = x;
106 	rect.y = y;
107 	rect.w = width;
108 	rect.h = height;
109 
110 	err = SDL_TryLockMutex(mutex);
111 	if (err) {
112 		nsi_print_warning("Failed to lock SDL mutex: %s", SDL_GetError());
113 		return -1;
114 	}
115 
116 	SDL_SetRenderTarget(renderer, read_texture);
117 
118 	SDL_RenderClear(renderer);
119 	SDL_RenderCopy(renderer, texture, NULL, NULL);
120 	SDL_RenderReadPixels(renderer, &rect, SDL_PIXELFORMAT_ARGB8888, buf, width * 4);
121 
122 	SDL_SetRenderTarget(renderer, NULL);
123 
124 	SDL_UnlockMutex(mutex);
125 
126 	return err;
127 }
128 
sdl_display_blanking_off_bottom(void * renderer,void * texture)129 void sdl_display_blanking_off_bottom(void *renderer, void *texture)
130 {
131 	SDL_RenderClear(renderer);
132 	SDL_RenderCopy(renderer, texture, NULL, NULL);
133 	SDL_RenderPresent(renderer);
134 }
135 
sdl_display_blanking_on_bottom(void * renderer)136 void sdl_display_blanking_on_bottom(void *renderer)
137 {
138 	SDL_RenderClear(renderer);
139 	SDL_RenderPresent(renderer);
140 }
141 
sdl_display_cleanup_bottom(void ** window,void ** renderer,void ** mutex,void ** texture,void ** read_texture)142 void sdl_display_cleanup_bottom(void **window, void **renderer, void **mutex, void **texture,
143 				void **read_texture)
144 {
145 	if (*read_texture != NULL) {
146 		SDL_DestroyTexture(*read_texture);
147 		*read_texture = NULL;
148 	}
149 
150 	if (*texture != NULL) {
151 		SDL_DestroyTexture(*texture);
152 		*texture = NULL;
153 	}
154 
155 	if (*mutex != NULL) {
156 		SDL_DestroyMutex(*mutex);
157 		*mutex = NULL;
158 	}
159 
160 	if (*renderer != NULL) {
161 		SDL_DestroyRenderer(*renderer);
162 		*renderer = NULL;
163 	}
164 
165 	if (*window != NULL) {
166 		SDL_DestroyWindow(*window);
167 		*window = NULL;
168 	}
169 }
170