• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
RPI_Available(void)54 RPI_Available(void)
55 {
56     return 1;
57 }
58 
59 static void
RPI_Destroy(SDL_VideoDevice * device)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 *
RPI_Create()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) {
78         SDL_OutOfMemory();
79         return NULL;
80     }
81 
82     /* Initialize internal data */
83     phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
84     if (phdata == NULL) {
85         SDL_OutOfMemory();
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;
101     device->GetDisplayModes = RPI_GetDisplayModes;
102     device->SetDisplayMode = RPI_SetDisplayMode;
103     device->CreateWindow = RPI_CreateWindow;
104     device->CreateWindowFrom = RPI_CreateWindowFrom;
105     device->SetWindowTitle = RPI_SetWindowTitle;
106     device->SetWindowIcon = RPI_SetWindowIcon;
107     device->SetWindowPosition = RPI_SetWindowPosition;
108     device->SetWindowSize = RPI_SetWindowSize;
109     device->ShowWindow = RPI_ShowWindow;
110     device->HideWindow = RPI_HideWindow;
111     device->RaiseWindow = RPI_RaiseWindow;
112     device->MaximizeWindow = RPI_MaximizeWindow;
113     device->MinimizeWindow = RPI_MinimizeWindow;
114     device->RestoreWindow = RPI_RestoreWindow;
115     device->SetWindowGrab = RPI_SetWindowGrab;
116     device->DestroyWindow = RPI_DestroyWindow;
117     device->GetWindowWMInfo = RPI_GetWindowWMInfo;
118     device->GL_LoadLibrary = RPI_GLES_LoadLibrary;
119     device->GL_GetProcAddress = RPI_GLES_GetProcAddress;
120     device->GL_UnloadLibrary = RPI_GLES_UnloadLibrary;
121     device->GL_CreateContext = RPI_GLES_CreateContext;
122     device->GL_MakeCurrent = RPI_GLES_MakeCurrent;
123     device->GL_SetSwapInterval = RPI_GLES_SetSwapInterval;
124     device->GL_GetSwapInterval = RPI_GLES_GetSwapInterval;
125     device->GL_SwapWindow = RPI_GLES_SwapWindow;
126     device->GL_DeleteContext = RPI_GLES_DeleteContext;
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
RPI_VideoInit(_THIS)144 RPI_VideoInit(_THIS)
145 {
146     SDL_VideoDisplay display;
147     SDL_DisplayMode current_mode;
148     SDL_DisplayData *data;
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 
189     RPI_InitMouse(_this);
190 
191     return 1;
192 }
193 
194 void
RPI_VideoQuit(_THIS)195 RPI_VideoQuit(_THIS)
196 {
197 #ifdef SDL_INPUT_LINUXEV
198     SDL_EVDEV_Quit();
199 #endif
200 }
201 
202 void
RPI_GetDisplayModes(_THIS,SDL_VideoDisplay * display)203 RPI_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
204 {
205     /* Only one display mode available, the current one */
206     SDL_AddDisplayMode(display, &display->current_mode);
207 }
208 
209 int
RPI_SetDisplayMode(_THIS,SDL_VideoDisplay * display,SDL_DisplayMode * mode)210 RPI_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
211 {
212     return 0;
213 }
214 
215 int
RPI_CreateWindow(_THIS,SDL_Window * window)216 RPI_CreateWindow(_THIS, SDL_Window * window)
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;
225     uint32_t layer = SDL_RPI_VIDEOLAYER;
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 
259     env = SDL_GetHint(SDL_HINT_RPI_VIDEO_LAYER);
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
RPI_DestroyWindow(_THIS,SDL_Window * window)302 RPI_DestroyWindow(_THIS, SDL_Window * window)
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
RPI_CreateWindowFrom(_THIS,SDL_Window * window,const void * data)317 RPI_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
318 {
319     return -1;
320 }
321 
322 void
RPI_SetWindowTitle(_THIS,SDL_Window * window)323 RPI_SetWindowTitle(_THIS, SDL_Window * window)
324 {
325 }
326 void
RPI_SetWindowIcon(_THIS,SDL_Window * window,SDL_Surface * icon)327 RPI_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
328 {
329 }
330 void
RPI_SetWindowPosition(_THIS,SDL_Window * window)331 RPI_SetWindowPosition(_THIS, SDL_Window * window)
332 {
333 }
334 void
RPI_SetWindowSize(_THIS,SDL_Window * window)335 RPI_SetWindowSize(_THIS, SDL_Window * window)
336 {
337 }
338 void
RPI_ShowWindow(_THIS,SDL_Window * window)339 RPI_ShowWindow(_THIS, SDL_Window * window)
340 {
341 }
342 void
RPI_HideWindow(_THIS,SDL_Window * window)343 RPI_HideWindow(_THIS, SDL_Window * window)
344 {
345 }
346 void
RPI_RaiseWindow(_THIS,SDL_Window * window)347 RPI_RaiseWindow(_THIS, SDL_Window * window)
348 {
349 }
350 void
RPI_MaximizeWindow(_THIS,SDL_Window * window)351 RPI_MaximizeWindow(_THIS, SDL_Window * window)
352 {
353 }
354 void
RPI_MinimizeWindow(_THIS,SDL_Window * window)355 RPI_MinimizeWindow(_THIS, SDL_Window * window)
356 {
357 }
358 void
RPI_RestoreWindow(_THIS,SDL_Window * window)359 RPI_RestoreWindow(_THIS, SDL_Window * window)
360 {
361 }
362 void
RPI_SetWindowGrab(_THIS,SDL_Window * window,SDL_bool grabbed)363 RPI_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
364 {
365 
366 }
367 
368 /*****************************************************************************/
369 /* SDL Window Manager function                                               */
370 /*****************************************************************************/
371 SDL_bool
RPI_GetWindowWMInfo(_THIS,SDL_Window * window,struct SDL_SysWMinfo * info)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",
378                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
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: */
389