1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22
23 #if SDL_VIDEO_DRIVER_VIVANTE
24
25 /* SDL internals */
26 #include "../SDL_sysvideo.h"
27 #include "SDL_version.h"
28 #include "SDL_syswm.h"
29 #include "SDL_loadso.h"
30 #include "SDL_events.h"
31 #include "../../events/SDL_events_c.h"
32
33 #ifdef SDL_INPUT_LINUXEV
34 #include "../../core/linux/SDL_evdev.h"
35 #endif
36
37 #include "SDL_vivantevideo.h"
38 #include "SDL_vivanteplatform.h"
39 #include "SDL_vivanteopengles.h"
40 #include "SDL_vivantevulkan.h"
41
42
43 static int
VIVANTE_Available(void)44 VIVANTE_Available(void)
45 {
46 return 1;
47 }
48
49 static void
VIVANTE_Destroy(SDL_VideoDevice * device)50 VIVANTE_Destroy(SDL_VideoDevice * device)
51 {
52 if (device->driverdata != NULL) {
53 SDL_free(device->driverdata);
54 device->driverdata = NULL;
55 }
56 }
57
58 static SDL_VideoDevice *
VIVANTE_Create()59 VIVANTE_Create()
60 {
61 SDL_VideoDevice *device;
62 SDL_VideoData *data;
63
64 /* Initialize SDL_VideoDevice structure */
65 device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
66 if (device == NULL) {
67 SDL_OutOfMemory();
68 return NULL;
69 }
70
71 /* Initialize internal data */
72 data = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
73 if (data == NULL) {
74 SDL_OutOfMemory();
75 SDL_free(device);
76 return NULL;
77 }
78
79 device->driverdata = data;
80
81 /* Setup amount of available displays */
82 device->num_displays = 0;
83
84 /* Set device free function */
85 device->free = VIVANTE_Destroy;
86
87 /* Setup all functions which we can handle */
88 device->VideoInit = VIVANTE_VideoInit;
89 device->VideoQuit = VIVANTE_VideoQuit;
90 device->GetDisplayModes = VIVANTE_GetDisplayModes;
91 device->SetDisplayMode = VIVANTE_SetDisplayMode;
92 device->CreateSDLWindow = VIVANTE_CreateWindow;
93 device->SetWindowTitle = VIVANTE_SetWindowTitle;
94 device->SetWindowPosition = VIVANTE_SetWindowPosition;
95 device->SetWindowSize = VIVANTE_SetWindowSize;
96 device->ShowWindow = VIVANTE_ShowWindow;
97 device->HideWindow = VIVANTE_HideWindow;
98 device->DestroyWindow = VIVANTE_DestroyWindow;
99 device->GetWindowWMInfo = VIVANTE_GetWindowWMInfo;
100
101 #if SDL_VIDEO_OPENGL_EGL
102 device->GL_LoadLibrary = VIVANTE_GLES_LoadLibrary;
103 device->GL_GetProcAddress = VIVANTE_GLES_GetProcAddress;
104 device->GL_UnloadLibrary = VIVANTE_GLES_UnloadLibrary;
105 device->GL_CreateContext = VIVANTE_GLES_CreateContext;
106 device->GL_MakeCurrent = VIVANTE_GLES_MakeCurrent;
107 device->GL_SetSwapInterval = VIVANTE_GLES_SetSwapInterval;
108 device->GL_GetSwapInterval = VIVANTE_GLES_GetSwapInterval;
109 device->GL_SwapWindow = VIVANTE_GLES_SwapWindow;
110 device->GL_DeleteContext = VIVANTE_GLES_DeleteContext;
111 #endif
112
113 #if SDL_VIDEO_VULKAN
114 device->Vulkan_LoadLibrary = VIVANTE_Vulkan_LoadLibrary;
115 device->Vulkan_UnloadLibrary = VIVANTE_Vulkan_UnloadLibrary;
116 device->Vulkan_GetInstanceExtensions = VIVANTE_Vulkan_GetInstanceExtensions;
117 device->Vulkan_CreateSurface = VIVANTE_Vulkan_CreateSurface;
118 #endif
119
120 device->PumpEvents = VIVANTE_PumpEvents;
121
122 return device;
123 }
124
125 VideoBootStrap VIVANTE_bootstrap = {
126 "vivante",
127 "Vivante EGL Video Driver",
128 VIVANTE_Available,
129 VIVANTE_Create
130 };
131
132 /*****************************************************************************/
133 /* SDL Video and Display initialization/handling functions */
134 /*****************************************************************************/
135
136 static int
VIVANTE_AddVideoDisplays(_THIS)137 VIVANTE_AddVideoDisplays(_THIS)
138 {
139 SDL_VideoData *videodata = _this->driverdata;
140 SDL_VideoDisplay display;
141 SDL_DisplayMode current_mode;
142 SDL_DisplayData *data;
143 int pitch = 0, bpp = 0;
144 unsigned long pixels = 0;
145
146 data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData));
147 if (data == NULL) {
148 return SDL_OutOfMemory();
149 }
150
151 SDL_zero(current_mode);
152 #if SDL_VIDEO_DRIVER_VIVANTE_VDK
153 data->native_display = vdkGetDisplay(videodata->vdk_private);
154
155 vdkGetDisplayInfo(data->native_display, ¤t_mode.w, ¤t_mode.h, &pixels, &pitch, &bpp);
156 #else
157 data->native_display = videodata->fbGetDisplayByIndex(0);
158
159 videodata->fbGetDisplayInfo(data->native_display, ¤t_mode.w, ¤t_mode.h, &pixels, &pitch, &bpp);
160 #endif /* SDL_VIDEO_DRIVER_VIVANTE_VDK */
161
162 switch (bpp)
163 {
164 default: /* Is another format used? */
165 case 32:
166 current_mode.format = SDL_PIXELFORMAT_ARGB8888;
167 break;
168 case 16:
169 current_mode.format = SDL_PIXELFORMAT_RGB565;
170 break;
171 }
172 /* FIXME: How do we query refresh rate? */
173 current_mode.refresh_rate = 60;
174
175 SDL_zero(display);
176 display.name = VIVANTE_GetDisplayName(_this);
177 display.desktop_mode = current_mode;
178 display.current_mode = current_mode;
179 display.driverdata = data;
180 SDL_AddVideoDisplay(&display);
181 return 0;
182 }
183
184 int
VIVANTE_VideoInit(_THIS)185 VIVANTE_VideoInit(_THIS)
186 {
187 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
188
189 #if SDL_VIDEO_DRIVER_VIVANTE_VDK
190 videodata->vdk_private = vdkInitialize();
191 if (!videodata->vdk_private) {
192 return SDL_SetError("vdkInitialize() failed");
193 }
194 #else
195 videodata->egl_handle = SDL_LoadObject("libEGL.so.1");
196 if (!videodata->egl_handle) {
197 videodata->egl_handle = SDL_LoadObject("libEGL.so");
198 if (!videodata->egl_handle) {
199 return -1;
200 }
201 }
202 #define LOAD_FUNC(NAME) \
203 videodata->NAME = SDL_LoadFunction(videodata->egl_handle, #NAME); \
204 if (!videodata->NAME) return -1;
205
206 LOAD_FUNC(fbGetDisplay);
207 LOAD_FUNC(fbGetDisplayByIndex);
208 LOAD_FUNC(fbGetDisplayGeometry);
209 LOAD_FUNC(fbGetDisplayInfo);
210 LOAD_FUNC(fbDestroyDisplay);
211 LOAD_FUNC(fbCreateWindow);
212 LOAD_FUNC(fbGetWindowGeometry);
213 LOAD_FUNC(fbGetWindowInfo);
214 LOAD_FUNC(fbDestroyWindow);
215 #endif
216
217 if (VIVANTE_SetupPlatform(_this) < 0) {
218 return -1;
219 }
220
221 if (VIVANTE_AddVideoDisplays(_this) < 0) {
222 return -1;
223 }
224
225 VIVANTE_UpdateDisplayScale(_this);
226
227 #ifdef SDL_INPUT_LINUXEV
228 if (SDL_EVDEV_Init() < 0) {
229 return -1;
230 }
231 #endif
232
233 return 0;
234 }
235
236 void
VIVANTE_VideoQuit(_THIS)237 VIVANTE_VideoQuit(_THIS)
238 {
239 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
240
241 #ifdef SDL_INPUT_LINUXEV
242 SDL_EVDEV_Quit();
243 #endif
244
245 VIVANTE_CleanupPlatform(_this);
246
247 #if SDL_VIDEO_DRIVER_VIVANTE_VDK
248 if (videodata->vdk_private) {
249 vdkExit(videodata->vdk_private);
250 videodata->vdk_private = NULL;
251 }
252 #else
253 if (videodata->egl_handle) {
254 SDL_UnloadObject(videodata->egl_handle);
255 videodata->egl_handle = NULL;
256 }
257 #endif
258 }
259
260 void
VIVANTE_GetDisplayModes(_THIS,SDL_VideoDisplay * display)261 VIVANTE_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
262 {
263 /* Only one display mode available, the current one */
264 SDL_AddDisplayMode(display, &display->current_mode);
265 }
266
267 int
VIVANTE_SetDisplayMode(_THIS,SDL_VideoDisplay * display,SDL_DisplayMode * mode)268 VIVANTE_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
269 {
270 return 0;
271 }
272
273 int
VIVANTE_CreateWindow(_THIS,SDL_Window * window)274 VIVANTE_CreateWindow(_THIS, SDL_Window * window)
275 {
276 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
277 SDL_DisplayData *displaydata;
278 SDL_WindowData *data;
279
280 displaydata = SDL_GetDisplayDriverData(0);
281
282 /* Allocate window internal data */
283 data = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
284 if (data == NULL) {
285 return SDL_OutOfMemory();
286 }
287
288 /* Setup driver data for this window */
289 window->driverdata = data;
290
291 #if SDL_VIDEO_DRIVER_VIVANTE_VDK
292 data->native_window = vdkCreateWindow(displaydata->native_display, window->x, window->y, window->w, window->h);
293 #else
294 data->native_window = videodata->fbCreateWindow(displaydata->native_display, window->x, window->y, window->w, window->h);
295 #endif
296 if (!data->native_window) {
297 return SDL_SetError("VIVANTE: Can't create native window");
298 }
299
300 #if SDL_VIDEO_OPENGL_EGL
301 if (window->flags & SDL_WINDOW_OPENGL) {
302 data->egl_surface = SDL_EGL_CreateSurface(_this, data->native_window);
303 if (data->egl_surface == EGL_NO_SURFACE) {
304 return SDL_SetError("VIVANTE: Can't create EGL surface");
305 }
306 } else {
307 data->egl_surface = EGL_NO_SURFACE;
308 }
309 #endif
310
311 /* Window has been successfully created */
312 return 0;
313 }
314
315 void
VIVANTE_DestroyWindow(_THIS,SDL_Window * window)316 VIVANTE_DestroyWindow(_THIS, SDL_Window * window)
317 {
318 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
319 SDL_WindowData *data;
320
321 data = window->driverdata;
322 if (data) {
323 #if SDL_VIDEO_OPENGL_EGL
324 if (data->egl_surface != EGL_NO_SURFACE) {
325 SDL_EGL_DestroySurface(_this, data->egl_surface);
326 }
327 #endif
328
329 if (data->native_window) {
330 #if SDL_VIDEO_DRIVER_VIVANTE_VDK
331 vdkDestroyWindow(data->native_window);
332 #else
333 videodata->fbDestroyWindow(data->native_window);
334 #endif
335 }
336
337 SDL_free(data);
338 }
339 window->driverdata = NULL;
340 }
341
342 void
VIVANTE_SetWindowTitle(_THIS,SDL_Window * window)343 VIVANTE_SetWindowTitle(_THIS, SDL_Window * window)
344 {
345 #if SDL_VIDEO_DRIVER_VIVANTE_VDK
346 SDL_WindowData *data = window->driverdata;
347 vdkSetWindowTitle(data->native_window, window->title);
348 #endif
349 }
350
351 void
VIVANTE_SetWindowPosition(_THIS,SDL_Window * window)352 VIVANTE_SetWindowPosition(_THIS, SDL_Window * window)
353 {
354 /* FIXME */
355 }
356
357 void
VIVANTE_SetWindowSize(_THIS,SDL_Window * window)358 VIVANTE_SetWindowSize(_THIS, SDL_Window * window)
359 {
360 /* FIXME */
361 }
362
363 void
VIVANTE_ShowWindow(_THIS,SDL_Window * window)364 VIVANTE_ShowWindow(_THIS, SDL_Window * window)
365 {
366 #if SDL_VIDEO_DRIVER_VIVANTE_VDK
367 SDL_WindowData *data = window->driverdata;
368 vdkShowWindow(data->native_window);
369 #endif
370 SDL_SetMouseFocus(window);
371 SDL_SetKeyboardFocus(window);
372 }
373
374 void
VIVANTE_HideWindow(_THIS,SDL_Window * window)375 VIVANTE_HideWindow(_THIS, SDL_Window * window)
376 {
377 #if SDL_VIDEO_DRIVER_VIVANTE_VDK
378 SDL_WindowData *data = window->driverdata;
379 vdkHideWindow(data->native_window);
380 #endif
381 }
382
383 /*****************************************************************************/
384 /* SDL Window Manager function */
385 /*****************************************************************************/
386 SDL_bool
VIVANTE_GetWindowWMInfo(_THIS,SDL_Window * window,struct SDL_SysWMinfo * info)387 VIVANTE_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
388 {
389 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
390 SDL_DisplayData *displaydata = SDL_GetDisplayDriverData(0);
391
392 if (info->version.major == SDL_MAJOR_VERSION &&
393 info->version.minor == SDL_MINOR_VERSION) {
394 info->subsystem = SDL_SYSWM_VIVANTE;
395 info->info.vivante.display = displaydata->native_display;
396 info->info.vivante.window = data->native_window;
397 return SDL_TRUE;
398 } else {
399 SDL_SetError("Application not compiled with SDL %d.%d",
400 SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
401 return SDL_FALSE;
402 }
403 }
404
405 /*****************************************************************************/
406 /* SDL event functions */
407 /*****************************************************************************/
VIVANTE_PumpEvents(_THIS)408 void VIVANTE_PumpEvents(_THIS)
409 {
410 #ifdef SDL_INPUT_LINUXEV
411 SDL_EVDEV_Poll();
412 #endif
413 }
414
415 #endif /* SDL_VIDEO_DRIVER_VIVANTE */
416
417 /* vi: set ts=4 sw=4 expandtab: */
418