SDL  2.0
SDL_rpivideo.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 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_VideoData *phdata = (SDL_VideoData *) device->driverdata; */
63 
64  if (device->driverdata != NULL) {
65  device->driverdata = NULL;
66  }
67 }
68 
69 static SDL_VideoDevice *
70 RPI_Create()
71 {
72  SDL_VideoDevice *device;
73  SDL_VideoData *phdata;
74 
75  /* Initialize SDL_VideoDevice structure */
76  device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
77  if (device == NULL) {
79  return NULL;
80  }
81 
82  /* Initialize internal data */
83  phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
84  if (phdata == NULL) {
86  SDL_free(device);
87  return NULL;
88  }
89 
90  device->driverdata = phdata;
91 
92  /* Setup amount of available displays */
93  device->num_displays = 0;
94 
95  /* Set device free function */
96  device->free = RPI_Destroy;
97 
98  /* Setup all functions which we can handle */
99  device->VideoInit = RPI_VideoInit;
100  device->VideoQuit = RPI_VideoQuit;
103  device->CreateWindow = RPI_CreateWindow;
109  device->ShowWindow = RPI_ShowWindow;
110  device->HideWindow = RPI_HideWindow;
111  device->RaiseWindow = RPI_RaiseWindow;
127 
128  device->PumpEvents = RPI_PumpEvents;
129 
130  return device;
131 }
132 
133 VideoBootStrap RPI_bootstrap = {
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  SDL_EVDEV_Init();
187 #endif
188 
190 
191  return 1;
192 }
193 
194 void
196 {
197 #ifdef SDL_INPUT_LINUXEV
198  SDL_EVDEV_Quit();
199 #endif
200 }
201 
202 void
204 {
205  /* Only one display mode available, the current one */
206  SDL_AddDisplayMode(display, &display->current_mode);
207 }
208 
209 int
211 {
212  return 0;
213 }
214 
215 int
217 {
218  SDL_WindowData *wdata;
219  SDL_VideoDisplay *display;
220  SDL_DisplayData *displaydata;
221  VC_RECT_T dst_rect;
222  VC_RECT_T src_rect;
223  VC_DISPMANX_ALPHA_T dispman_alpha;
224  DISPMANX_UPDATE_HANDLE_T dispman_update;
226  const char *env;
227 
228  /* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */
229  dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
230  dispman_alpha.opacity = 0xFF;
231  dispman_alpha.mask = 0;
232 
233  /* Allocate window internal data */
234  wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
235  if (wdata == NULL) {
236  return SDL_OutOfMemory();
237  }
238  display = SDL_GetDisplayForWindow(window);
239  displaydata = (SDL_DisplayData *) display->driverdata;
240 
241  /* Windows have one size for now */
242  window->w = display->desktop_mode.w;
243  window->h = display->desktop_mode.h;
244 
245  /* OpenGL ES is the law here, buddy */
246  window->flags |= SDL_WINDOW_OPENGL;
247 
248  /* Create a dispman element and associate a window to it */
249  dst_rect.x = 0;
250  dst_rect.y = 0;
251  dst_rect.width = window->w;
252  dst_rect.height = window->h;
253 
254  src_rect.x = 0;
255  src_rect.y = 0;
256  src_rect.width = window->w << 16;
257  src_rect.height = window->h << 16;
258 
260  if (env) {
261  layer = SDL_atoi(env);
262  }
263 
264  dispman_update = vc_dispmanx_update_start( 0 );
265  wdata->dispman_window.element = vc_dispmanx_element_add (dispman_update,
266  displaydata->dispman_display,
267  layer /* layer */,
268  &dst_rect,
269  0 /*src*/,
270  &src_rect,
271  DISPMANX_PROTECTION_NONE,
272  &dispman_alpha /*alpha*/,
273  0 /*clamp*/,
274  0 /*transform*/);
275  wdata->dispman_window.width = window->w;
276  wdata->dispman_window.height = window->h;
277  vc_dispmanx_update_submit_sync(dispman_update);
278 
279  if (!_this->egl_data) {
280  if (SDL_GL_LoadLibrary(NULL) < 0) {
281  return -1;
282  }
283  }
284  wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) &wdata->dispman_window);
285 
286  if (wdata->egl_surface == EGL_NO_SURFACE) {
287  return SDL_SetError("Could not create GLES window surface");
288  }
289 
290  /* Setup driver data for this window */
291  window->driverdata = wdata;
292 
293  /* One window, it always has focus */
294  SDL_SetMouseFocus(window);
295  SDL_SetKeyboardFocus(window);
296 
297  /* Window has been successfully created */
298  return 0;
299 }
300 
301 void
303 {
304  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
305  if(data) {
306 #if SDL_VIDEO_OPENGL_EGL
307  if (data->egl_surface != EGL_NO_SURFACE) {
308  SDL_EGL_DestroySurface(_this, data->egl_surface);
309  }
310 #endif
311  SDL_free(data);
312  window->driverdata = NULL;
313  }
314 }
315 
316 int
317 RPI_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
318 {
319  return -1;
320 }
321 
322 void
324 {
325 }
326 void
328 {
329 }
330 void
332 {
333 }
334 void
336 {
337 }
338 void
340 {
341 }
342 void
344 {
345 }
346 void
348 {
349 }
350 void
352 {
353 }
354 void
356 {
357 }
358 void
360 {
361 }
362 void
363 RPI_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
364 {
365 
366 }
367 
368 /*****************************************************************************/
369 /* SDL Window Manager function */
370 /*****************************************************************************/
371 SDL_bool
372 RPI_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
373 {
374  if (info->version.major <= SDL_MAJOR_VERSION) {
375  return SDL_TRUE;
376  } else {
377  SDL_SetError("application not compiled with SDL %d.%d\n",
379  return SDL_FALSE;
380  }
381 
382  /* Failed to get window manager information */
383  return SDL_FALSE;
384 }
385 
386 #endif /* SDL_VIDEO_DRIVER_RPI */
387 
388 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_RPI_VIDEOLAYER
Definition: SDL_rpivideo.h:53
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
void RPI_DestroyWindow(_THIS, SDL_Window *window)
void RPI_RestoreWindow(_THIS, SDL_Window *window)
void(* RestoreWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:220
void * RPI_GLES_GetProcAddress(_THIS, const char *proc)
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:612
int RPI_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
void RPI_SetWindowTitle(_THIS, SDL_Window *window)
void RPI_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
int RPI_GLES_LoadLibrary(_THIS, const char *path)
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
int(* CreateWindowFrom)(_THIS, SDL_Window *window, const void *data)
Definition: SDL_sysvideo.h:204
static SDL_Window * window
void(* free)(_THIS)
Definition: SDL_sysvideo.h:358
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(* GL_SetSwapInterval)(_THIS, int interval)
Definition: SDL_sysvideo.h:253
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
int RPI_GLES_MakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context)
void(* ShowWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:215
The structure that defines a display mode.
Definition: SDL_video.h:53
#define SDL_GetHint
SDL_version version
Definition: SDL_syswm.h:195
Uint8 major
Definition: SDL_version.h:53
void(* SetWindowSize)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:208
void RPI_RaiseWindow(_THIS, SDL_Window *window)
int RPI_GLES_GetSwapInterval(_THIS)
void RPI_MaximizeWindow(_THIS, SDL_Window *window)
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:103
void(* GL_SwapWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:255
#define SDL_GL_LoadLibrary
int SDL_AddVideoDisplay(const SDL_VideoDisplay *display)
Definition: SDL_video.c:591
int(* GL_LoadLibrary)(_THIS, const char *path)
Definition: SDL_sysvideo.h:247
int RPI_VideoInit(_THIS)
int(* SetDisplayMode)(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
Definition: SDL_sysvideo.h:197
void RPI_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
void(* HideWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:216
void(* RaiseWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:217
void * SDL_calloc(size_t nmemb, size_t size)
SDL_bool(* GetWindowWMInfo)(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
Definition: SDL_sysvideo.h:240
SDL_GLContext(* GL_CreateContext)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:250
GLenum GLuint GLint GLint layer
#define _THIS
void RPI_PumpEvents(_THIS)
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:251
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:130
GLenum mode
void(* DestroyWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:227
void RPI_GLES_DeleteContext(_THIS, SDL_GLContext context)
#define SDL_zero(x)
Definition: SDL_stdinc.h:361
void(* SetWindowIcon)(_THIS, SDL_Window *window, SDL_Surface *icon)
Definition: SDL_sysvideo.h:206
DISPMANX_DISPLAY_HANDLE_T dispman_display
Definition: SDL_rpivideo.h:41
void RPI_VideoQuit(_THIS)
#define SDL_atoi
void(* GL_UnloadLibrary)(_THIS)
Definition: SDL_sysvideo.h:249
void(* GetDisplayModes)(_THIS, SDL_VideoDisplay *display)
Definition: SDL_sysvideo.h:189
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
void RPI_GLES_SwapWindow(_THIS, SDL_Window *window)
SDL_DisplayMode desktop_mode
Definition: SDL_sysvideo.h:129
unsigned int uint32_t
void(* VideoQuit)(_THIS)
Definition: SDL_sysvideo.h:164
void RPI_ShowWindow(_THIS, SDL_Window *window)
void RPI_MinimizeWindow(_THIS, SDL_Window *window)
#define SDL_SetError
#define SDL_HINT_RPI_VIDEO_LAYER
Tell SDL which Dispmanx layer to use on a Raspberry PI.
Definition: SDL_hints.h:708
int RPI_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1058
void(* SetWindowPosition)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:207
int(* CreateWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:203
The type used to identify a window.
Definition: SDL_sysvideo.h:71
SDL_GLContext RPI_GLES_CreateContext(_THIS, SDL_Window *window)
void(* MinimizeWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:219
int RPI_CreateWindow(_THIS, SDL_Window *window)
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
Definition: SDL_video.c:728
int(* VideoInit)(_THIS)
Definition: SDL_sysvideo.h:158
GLubyte GLubyte GLubyte GLubyte w
void * driverdata
Definition: SDL_sysvideo.h:109
void(* GL_DeleteContext)(_THIS, SDL_GLContext context)
Definition: SDL_sysvideo.h:256
Uint32 format
Definition: SDL_video.h:55
void(* SetWindowTitle)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:205
int(* GL_GetSwapInterval)(_THIS)
Definition: SDL_sysvideo.h:254
void(* MaximizeWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:218
Uint32 flags
Definition: SDL_sysvideo.h:81
SDL_bool RPI_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
void RPI_SetWindowPosition(_THIS, SDL_Window *window)
void(* SetWindowGrab)(_THIS, SDL_Window *window, SDL_bool grabbed)
Definition: SDL_sysvideo.h:226
void RPI_InitMouse(_THIS)
GLfloat GLfloat GLfloat GLfloat h
void *(* GL_GetProcAddress)(_THIS, const char *proc)
Definition: SDL_sysvideo.h:248
EGLSurface egl_surface
void(* PumpEvents)(_THIS)
Definition: SDL_sysvideo.h:262
int RPI_GLES_SetSwapInterval(_THIS, int interval)