SDL  2.0
SDL_rpivideo.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 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 
22 #include "../../SDL_internal.h"
23 
24 #if SDL_VIDEO_DRIVER_RPI
25 
26 /* References
27  * http://elinux.org/RPi_VideoCore_APIs
28  * https://github.com/raspberrypi/firmware/blob/master/opt/vc/src/hello_pi/hello_triangle/triangle.c
29  * http://cgit.freedesktop.org/wayland/weston/tree/src/rpi-renderer.c
30  * http://cgit.freedesktop.org/wayland/weston/tree/src/compositor-rpi.c
31  */
32 
33 /* SDL internals */
34 #include "../SDL_sysvideo.h"
35 #include "SDL_version.h"
36 #include "SDL_syswm.h"
37 #include "SDL_loadso.h"
38 #include "SDL_events.h"
39 #include "../../events/SDL_mouse_c.h"
40 #include "../../events/SDL_keyboard_c.h"
41 #include "SDL_hints.h"
42 
43 #ifdef SDL_INPUT_LINUXEV
44 #include "../../core/linux/SDL_evdev.h"
45 #endif
46 
47 /* RPI declarations */
48 #include "SDL_rpivideo.h"
49 #include "SDL_rpievents_c.h"
50 #include "SDL_rpiopengles.h"
51 #include "SDL_rpimouse.h"
52 
53 static int
54 RPI_Available(void)
55 {
56  return 1;
57 }
58 
59 static void
60 RPI_Destroy(SDL_VideoDevice * device)
61 {
62  SDL_free(device->driverdata);
63  SDL_free(device);
64 }
65 
66 static SDL_VideoDevice *
67 RPI_Create()
68 {
70  SDL_VideoData *phdata;
71 
72  /* Initialize SDL_VideoDevice structure */
73  device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
74  if (device == NULL) {
76  return NULL;
77  }
78 
79  /* Initialize internal data */
80  phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
81  if (phdata == NULL) {
83  SDL_free(device);
84  return NULL;
85  }
86 
87  device->driverdata = phdata;
88 
89  /* Setup amount of available displays */
90  device->num_displays = 0;
91 
92  /* Set device free function */
93  device->free = RPI_Destroy;
94 
95  /* Setup all functions which we can handle */
96  device->VideoInit = RPI_VideoInit;
97  device->VideoQuit = RPI_VideoQuit;
106  device->ShowWindow = RPI_ShowWindow;
107  device->HideWindow = RPI_HideWindow;
108  device->RaiseWindow = RPI_RaiseWindow;
114 #if 0
116 #endif
126  device->GL_DefaultProfileConfig = RPI_GLES_DefaultProfileConfig;
127 
128  device->PumpEvents = RPI_PumpEvents;
129 
130  return device;
131 }
132 
134  "RPI",
135  "RPI Video Driver",
136  RPI_Available,
137  RPI_Create
138 };
139 
140 /*****************************************************************************/
141 /* SDL Video and Display initialization/handling functions */
142 /*****************************************************************************/
143 int
145 {
146  SDL_VideoDisplay display;
147  SDL_DisplayMode current_mode;
149  uint32_t w,h;
150 
151  /* Initialize BCM Host */
152  bcm_host_init();
153 
154  SDL_zero(current_mode);
155 
156  if (graphics_get_display_size( 0, &w, &h) < 0) {
157  return -1;
158  }
159 
160  current_mode.w = w;
161  current_mode.h = h;
162  /* FIXME: Is there a way to tell the actual refresh rate? */
163  current_mode.refresh_rate = 60;
164  /* 32 bpp for default */
165  current_mode.format = SDL_PIXELFORMAT_ABGR8888;
166 
167  current_mode.driverdata = NULL;
168 
169  SDL_zero(display);
170  display.desktop_mode = current_mode;
171  display.current_mode = current_mode;
172 
173  /* Allocate display internal data */
174  data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData));
175  if (data == NULL) {
176  return SDL_OutOfMemory();
177  }
178 
179  data->dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
180 
181  display.driverdata = data;
182 
183  SDL_AddVideoDisplay(&display);
184 
185 #ifdef SDL_INPUT_LINUXEV
186  if (SDL_EVDEV_Init() < 0) {
187  return -1;
188  }
189 #endif
190 
192 
193  return 1;
194 }
195 
196 void
198 {
199 #ifdef SDL_INPUT_LINUXEV
200  SDL_EVDEV_Quit();
201 #endif
202 }
203 
204 void
206 {
207  /* Only one display mode available, the current one */
208  SDL_AddDisplayMode(display, &display->current_mode);
209 }
210 
211 int
213 {
214  return 0;
215 }
216 
217 int
219 {
220  SDL_WindowData *wdata;
221  SDL_VideoDisplay *display;
222  SDL_DisplayData *displaydata;
223  VC_RECT_T dst_rect;
224  VC_RECT_T src_rect;
225  VC_DISPMANX_ALPHA_T dispman_alpha;
226  DISPMANX_UPDATE_HANDLE_T dispman_update;
228  const char *env;
229 
230  /* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */
231  dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
232  dispman_alpha.opacity = 0xFF;
233  dispman_alpha.mask = 0;
234 
235  /* Allocate window internal data */
236  wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
237  if (wdata == NULL) {
238  return SDL_OutOfMemory();
239  }
240  display = SDL_GetDisplayForWindow(window);
241  displaydata = (SDL_DisplayData *) display->driverdata;
242 
243  /* Windows have one size for now */
244  window->w = display->desktop_mode.w;
245  window->h = display->desktop_mode.h;
246 
247  /* OpenGL ES is the law here, buddy */
248  window->flags |= SDL_WINDOW_OPENGL;
249 
250  /* Create a dispman element and associate a window to it */
251  dst_rect.x = 0;
252  dst_rect.y = 0;
253  dst_rect.width = window->w;
254  dst_rect.height = window->h;
255 
256  src_rect.x = 0;
257  src_rect.y = 0;
258  src_rect.width = window->w << 16;
259  src_rect.height = window->h << 16;
260 
262  if (env) {
263  layer = SDL_atoi(env);
264  }
265 
266  dispman_update = vc_dispmanx_update_start( 0 );
267  wdata->dispman_window.element = vc_dispmanx_element_add (dispman_update,
268  displaydata->dispman_display,
269  layer /* layer */,
270  &dst_rect,
271  0 /*src*/,
272  &src_rect,
273  DISPMANX_PROTECTION_NONE,
274  &dispman_alpha /*alpha*/,
275  0 /*clamp*/,
276  0 /*transform*/);
277  wdata->dispman_window.width = window->w;
278  wdata->dispman_window.height = window->h;
279  vc_dispmanx_update_submit_sync(dispman_update);
280 
281  if (!_this->egl_data) {
282  if (SDL_GL_LoadLibrary(NULL) < 0) {
283  return -1;
284  }
285  }
286  wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) &wdata->dispman_window);
287 
288  if (wdata->egl_surface == EGL_NO_SURFACE) {
289  return SDL_SetError("Could not create GLES window surface");
290  }
291 
292  /* Setup driver data for this window */
293  window->driverdata = wdata;
294 
295  /* One window, it always has focus */
296  SDL_SetMouseFocus(window);
297  SDL_SetKeyboardFocus(window);
298 
299  /* Window has been successfully created */
300  return 0;
301 }
302 
303 void
305 {
306  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
307  if(data) {
308 #if SDL_VIDEO_OPENGL_EGL
309  if (data->egl_surface != EGL_NO_SURFACE) {
310  SDL_EGL_DestroySurface(_this, data->egl_surface);
311  }
312 #endif
313  SDL_free(data);
314  window->driverdata = NULL;
315  }
316 }
317 
318 int
319 RPI_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
320 {
321  return -1;
322 }
323 
324 void
326 {
327 }
328 void
330 {
331 }
332 void
334 {
335 }
336 void
338 {
339 }
340 void
342 {
343 }
344 void
346 {
347 }
348 void
350 {
351 }
352 void
354 {
355 }
356 void
358 {
359 }
360 void
362 {
363 }
364 void
365 RPI_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
366 {
367 
368 }
369 
370 /*****************************************************************************/
371 /* SDL Window Manager function */
372 /*****************************************************************************/
373 #if 0
374 SDL_bool
375 RPI_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
376 {
377  if (info->version.major <= SDL_MAJOR_VERSION) {
378  return SDL_TRUE;
379  } else {
380  SDL_SetError("application not compiled with SDL %d.%d",
382  return SDL_FALSE;
383  }
384 
385  /* Failed to get window manager information */
386  return SDL_FALSE;
387 }
388 #endif
389 
390 #endif /* SDL_VIDEO_DRIVER_RPI */
391 
392 /* vi: set ts=4 sw=4 expandtab: */
void(* GetDisplayModes)(_THIS, SDL_VideoDisplay *display)
Definition: SDL_sysvideo.h:196
void(* MinimizeWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:226
#define SDL_RPI_VIDEOLAYER
Definition: SDL_rpivideo.h:53
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
SDL_bool(* GetWindowWMInfo)(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
Definition: SDL_sysvideo.h:247
void RPI_DestroyWindow(_THIS, SDL_Window *window)
void(* RaiseWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:224
void RPI_RestoreWindow(_THIS, SDL_Window *window)
void * RPI_GLES_GetProcAddress(_THIS, const char *proc)
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
int RPI_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
void RPI_SetWindowTitle(_THIS, SDL_Window *window)
#define EGL_NO_SURFACE
Definition: egl.h:100
void RPI_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
void(* HideWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:223
int RPI_GLES_LoadLibrary(_THIS, const char *path)
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:258
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
GLfloat GLfloat GLfloat GLfloat h
void RPI_GLES_UnloadLibrary(_THIS)
void RPI_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
int RPI_GLES_MakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context)
void(* GL_DefaultProfileConfig)(_THIS, int *mask, int *major, int *minor)
Definition: SDL_sysvideo.h:264
void(* SetWindowGrab)(_THIS, SDL_Window *window, SDL_bool grabbed)
Definition: SDL_sysvideo.h:233
The structure that defines a display mode.
Definition: SDL_video.h:53
#define SDL_GetHint
SDL_version version
Definition: SDL_syswm.h:196
Uint8 major
Definition: SDL_version.h:53
void(* SetWindowIcon)(_THIS, SDL_Window *window, SDL_Surface *icon)
Definition: SDL_sysvideo.h:213
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
void RPI_RaiseWindow(_THIS, SDL_Window *window)
GLenum GLuint GLint GLint layer
int RPI_GLES_GetSwapInterval(_THIS)
void RPI_MaximizeWindow(_THIS, SDL_Window *window)
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:149
#define SDL_GL_LoadLibrary
int SDL_AddVideoDisplay(const SDL_VideoDisplay *display)
Definition: SDL_video.c:606
void(* free)(_THIS)
Definition: SDL_sysvideo.h:390
int RPI_VideoInit(_THIS)
void RPI_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
int(* GL_SetSwapInterval)(_THIS, int interval)
Definition: SDL_sysvideo.h:260
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
EGLNativeWindowType NativeWindowType
Definition: eglplatform.h:112
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void(* GL_UnloadLibrary)(_THIS)
Definition: SDL_sysvideo.h:256
int(* CreateSDLWindowFrom)(_THIS, SDL_Window *window, const void *data)
Definition: SDL_sysvideo.h:211
void * SDL_calloc(size_t nmemb, size_t size)
int(* CreateSDLWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:210
int(* VideoInit)(_THIS)
Definition: SDL_sysvideo.h:160
#define _THIS
void RPI_PumpEvents(_THIS)
void SDL_free(void *mem)
EGL_DISPMANX_WINDOW_T dispman_window
Definition: SDL_rpivideo.h:47
void * driverdata
Definition: SDL_video.h:59
void RPI_HideWindow(_THIS, SDL_Window *window)
void RPI_SetWindowSize(_THIS, SDL_Window *window)
SDL_DisplayMode current_mode
Definition: SDL_sysvideo.h:132
GLenum mode
GLubyte GLubyte GLubyte GLubyte w
void RPI_GLES_DeleteContext(_THIS, SDL_GLContext context)
#define SDL_zero(x)
Definition: SDL_stdinc.h:385
DISPMANX_DISPLAY_HANDLE_T dispman_display
Definition: SDL_rpivideo.h:41
void(* SetWindowPosition)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:214
void(* PumpEvents)(_THIS)
Definition: SDL_sysvideo.h:280
void RPI_VideoQuit(_THIS)
#define SDL_atoi
int(* GL_GetSwapInterval)(_THIS)
Definition: SDL_sysvideo.h:261
VideoBootStrap RPI_bootstrap
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
SDL_DisplayMode desktop_mode
Definition: SDL_sysvideo.h:131
unsigned int uint32_t
void(* GL_DeleteContext)(_THIS, SDL_GLContext context)
Definition: SDL_sysvideo.h:263
void(* MaximizeWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:225
void RPI_ShowWindow(_THIS, SDL_Window *window)
void RPI_MinimizeWindow(_THIS, SDL_Window *window)
#define SDL_SetError
void(* DestroyWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:234
int(* GL_SwapWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:262
#define SDL_HINT_RPI_VIDEO_LAYER
Tell SDL which Dispmanx layer to use on a Raspberry PI.
Definition: SDL_hints.h:798
int RPI_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
void(* SetWindowSize)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:215
int(* SetDisplayMode)(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
Definition: SDL_sysvideo.h:204
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1073
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_GLContext RPI_GLES_CreateContext(_THIS, SDL_Window *window)
SDL_GLContext(* GL_CreateContext)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:257
int(* GL_LoadLibrary)(_THIS, const char *path)
Definition: SDL_sysvideo.h:254
void(* VideoQuit)(_THIS)
Definition: SDL_sysvideo.h:166
void(* ShowWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:222
int RPI_CreateWindow(_THIS, SDL_Window *window)
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
Definition: SDL_video.c:743
void * driverdata
Definition: SDL_sysvideo.h:111
void(* SetWindowTitle)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:212
Uint32 format
Definition: SDL_video.h:55
Uint32 flags
Definition: SDL_sysvideo.h:83
SDL_bool RPI_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
void RPI_SetWindowPosition(_THIS, SDL_Window *window)
void *(* GL_GetProcAddress)(_THIS, const char *proc)
Definition: SDL_sysvideo.h:255
void RPI_InitMouse(_THIS)
int RPI_GLES_SwapWindow(_THIS, SDL_Window *window)
EGLSurface egl_surface
void(* RestoreWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:227
int RPI_GLES_SetSwapInterval(_THIS, int interval)