src/video/raspberry/SDL_rpivideo.c
author Sam Lantinga
Sat, 02 Jan 2016 10:10:34 -0800
changeset 9998 f67cf37e9cd4
parent 9711 0a329b2a297f
child 10202 16c283d1dcca
permissions -rw-r--r--
Updated copyright to 2016
     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 
    42 #ifdef SDL_INPUT_LINUXEV
    43 #include "../../core/linux/SDL_evdev.h"
    44 #endif
    45 
    46 /* RPI declarations */
    47 #include "SDL_rpivideo.h"
    48 #include "SDL_rpievents_c.h"
    49 #include "SDL_rpiopengles.h"
    50 #include "SDL_rpimouse.h"
    51 
    52 static int
    53 RPI_Available(void)
    54 {
    55     return 1;
    56 }
    57 
    58 static void
    59 RPI_Destroy(SDL_VideoDevice * device)
    60 {
    61     /*    SDL_VideoData *phdata = (SDL_VideoData *) device->driverdata; */
    62 
    63     if (device->driverdata != NULL) {
    64         device->driverdata = NULL;
    65     }
    66 }
    67 
    68 static SDL_VideoDevice *
    69 RPI_Create()
    70 {
    71     SDL_VideoDevice *device;
    72     SDL_VideoData *phdata;
    73 
    74     /* Initialize SDL_VideoDevice structure */
    75     device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
    76     if (device == NULL) {
    77         SDL_OutOfMemory();
    78         return NULL;
    79     }
    80 
    81     /* Initialize internal data */
    82     phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
    83     if (phdata == NULL) {
    84         SDL_OutOfMemory();
    85         SDL_free(device);
    86         return NULL;
    87     }
    88 
    89     device->driverdata = phdata;
    90 
    91     /* Setup amount of available displays and current display */
    92     device->num_displays = 0;
    93 
    94     /* Set device free function */
    95     device->free = RPI_Destroy;
    96 
    97     /* Setup all functions which we can handle */
    98     device->VideoInit = RPI_VideoInit;
    99     device->VideoQuit = RPI_VideoQuit;
   100     device->GetDisplayModes = RPI_GetDisplayModes;
   101     device->SetDisplayMode = RPI_SetDisplayMode;
   102     device->CreateWindow = RPI_CreateWindow;
   103     device->CreateWindowFrom = RPI_CreateWindowFrom;
   104     device->SetWindowTitle = RPI_SetWindowTitle;
   105     device->SetWindowIcon = RPI_SetWindowIcon;
   106     device->SetWindowPosition = RPI_SetWindowPosition;
   107     device->SetWindowSize = RPI_SetWindowSize;
   108     device->ShowWindow = RPI_ShowWindow;
   109     device->HideWindow = RPI_HideWindow;
   110     device->RaiseWindow = RPI_RaiseWindow;
   111     device->MaximizeWindow = RPI_MaximizeWindow;
   112     device->MinimizeWindow = RPI_MinimizeWindow;
   113     device->RestoreWindow = RPI_RestoreWindow;
   114     device->SetWindowGrab = RPI_SetWindowGrab;
   115     device->DestroyWindow = RPI_DestroyWindow;
   116     device->GetWindowWMInfo = RPI_GetWindowWMInfo;
   117     device->GL_LoadLibrary = RPI_GLES_LoadLibrary;
   118     device->GL_GetProcAddress = RPI_GLES_GetProcAddress;
   119     device->GL_UnloadLibrary = RPI_GLES_UnloadLibrary;
   120     device->GL_CreateContext = RPI_GLES_CreateContext;
   121     device->GL_MakeCurrent = RPI_GLES_MakeCurrent;
   122     device->GL_SetSwapInterval = RPI_GLES_SetSwapInterval;
   123     device->GL_GetSwapInterval = RPI_GLES_GetSwapInterval;
   124     device->GL_SwapWindow = RPI_GLES_SwapWindow;
   125     device->GL_DeleteContext = RPI_GLES_DeleteContext;
   126 
   127     device->PumpEvents = RPI_PumpEvents;
   128 
   129     return device;
   130 }
   131 
   132 VideoBootStrap RPI_bootstrap = {
   133     "RPI",
   134     "RPI Video Driver",
   135     RPI_Available,
   136     RPI_Create
   137 };
   138 
   139 /*****************************************************************************/
   140 /* SDL Video and Display initialization/handling functions                   */
   141 /*****************************************************************************/
   142 int
   143 RPI_VideoInit(_THIS)
   144 {
   145     SDL_VideoDisplay display;
   146     SDL_DisplayMode current_mode;
   147     SDL_DisplayData *data;
   148     uint32_t w,h;
   149 
   150     /* Initialize BCM Host */
   151     bcm_host_init();
   152 
   153     SDL_zero(current_mode);
   154 
   155     if (graphics_get_display_size( 0, &w, &h) < 0) {
   156         return -1;
   157     }
   158 
   159     current_mode.w = w;
   160     current_mode.h = h;
   161     /* FIXME: Is there a way to tell the actual refresh rate? */
   162     current_mode.refresh_rate = 60;
   163     /* 32 bpp for default */
   164     current_mode.format = SDL_PIXELFORMAT_ABGR8888;
   165 
   166     current_mode.driverdata = NULL;
   167 
   168     SDL_zero(display);
   169     display.desktop_mode = current_mode;
   170     display.current_mode = current_mode;
   171 
   172     /* Allocate display internal data */
   173     data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData));
   174     if (data == NULL) {
   175         return SDL_OutOfMemory();
   176     }
   177 
   178     data->dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
   179 
   180     display.driverdata = data;
   181 
   182     SDL_AddVideoDisplay(&display);
   183 
   184 #ifdef SDL_INPUT_LINUXEV    
   185     SDL_EVDEV_Init();
   186 #endif    
   187     
   188     RPI_InitMouse(_this);
   189 
   190     return 1;
   191 }
   192 
   193 void
   194 RPI_VideoQuit(_THIS)
   195 {
   196 #ifdef SDL_INPUT_LINUXEV    
   197     SDL_EVDEV_Quit();
   198 #endif    
   199 }
   200 
   201 void
   202 RPI_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
   203 {
   204     /* Only one display mode available, the current one */
   205     SDL_AddDisplayMode(display, &display->current_mode);
   206 }
   207 
   208 int
   209 RPI_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
   210 {
   211     return 0;
   212 }
   213 
   214 int
   215 RPI_CreateWindow(_THIS, SDL_Window * window)
   216 {
   217     SDL_WindowData *wdata;
   218     SDL_VideoDisplay *display;
   219     SDL_DisplayData *displaydata;
   220     VC_RECT_T dst_rect;
   221     VC_RECT_T src_rect;
   222     VC_DISPMANX_ALPHA_T         dispman_alpha;
   223     DISPMANX_UPDATE_HANDLE_T dispman_update;
   224 
   225     /* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */
   226     dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; 
   227     dispman_alpha.opacity = 0xFF; 
   228     dispman_alpha.mask = 0;
   229 
   230     /* Allocate window internal data */
   231     wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
   232     if (wdata == NULL) {
   233         return SDL_OutOfMemory();
   234     }
   235     display = SDL_GetDisplayForWindow(window);
   236     displaydata = (SDL_DisplayData *) display->driverdata;
   237 
   238     /* Windows have one size for now */
   239     window->w = display->desktop_mode.w;
   240     window->h = display->desktop_mode.h;
   241 
   242     /* OpenGL ES is the law here, buddy */
   243     window->flags |= SDL_WINDOW_OPENGL;
   244 
   245     /* Create a dispman element and associate a window to it */
   246     dst_rect.x = 0;
   247     dst_rect.y = 0;
   248     dst_rect.width = window->w;
   249     dst_rect.height = window->h;
   250 
   251     src_rect.x = 0;
   252     src_rect.y = 0;
   253     src_rect.width = window->w << 16;
   254     src_rect.height = window->h << 16;
   255 
   256     dispman_update = vc_dispmanx_update_start( 0 );
   257     wdata->dispman_window.element = vc_dispmanx_element_add ( dispman_update, displaydata->dispman_display, SDL_RPI_VIDEOLAYER /* layer */, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE, &dispman_alpha /*alpha*/, 0/*clamp*/, 0/*transform*/);
   258     wdata->dispman_window.width = window->w;
   259     wdata->dispman_window.height = window->h;
   260     vc_dispmanx_update_submit_sync( dispman_update );
   261     
   262     if (!_this->egl_data) {
   263         if (SDL_GL_LoadLibrary(NULL) < 0) {
   264             return -1;
   265         }
   266     }
   267     wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) &wdata->dispman_window);
   268 
   269     if (wdata->egl_surface == EGL_NO_SURFACE) {
   270         return SDL_SetError("Could not create GLES window surface");
   271     }
   272 
   273     /* Setup driver data for this window */
   274     window->driverdata = wdata;
   275     
   276     /* One window, it always has focus */
   277     SDL_SetMouseFocus(window);
   278     SDL_SetKeyboardFocus(window);
   279 
   280     /* Window has been successfully created */
   281     return 0;
   282 }
   283 
   284 void
   285 RPI_DestroyWindow(_THIS, SDL_Window * window)
   286 {
   287     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   288     if(data) {
   289 #if SDL_VIDEO_OPENGL_EGL
   290         if (data->egl_surface != EGL_NO_SURFACE) {
   291             SDL_EGL_DestroySurface(_this, data->egl_surface);
   292         }
   293 #endif
   294         SDL_free(data);
   295         window->driverdata = NULL;
   296     }
   297 }
   298 
   299 int
   300 RPI_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   301 {
   302     return -1;
   303 }
   304 
   305 void
   306 RPI_SetWindowTitle(_THIS, SDL_Window * window)
   307 {
   308 }
   309 void
   310 RPI_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   311 {
   312 }
   313 void
   314 RPI_SetWindowPosition(_THIS, SDL_Window * window)
   315 {
   316 }
   317 void
   318 RPI_SetWindowSize(_THIS, SDL_Window * window)
   319 {
   320 }
   321 void
   322 RPI_ShowWindow(_THIS, SDL_Window * window)
   323 {
   324 }
   325 void
   326 RPI_HideWindow(_THIS, SDL_Window * window)
   327 {
   328 }
   329 void
   330 RPI_RaiseWindow(_THIS, SDL_Window * window)
   331 {
   332 }
   333 void
   334 RPI_MaximizeWindow(_THIS, SDL_Window * window)
   335 {
   336 }
   337 void
   338 RPI_MinimizeWindow(_THIS, SDL_Window * window)
   339 {
   340 }
   341 void
   342 RPI_RestoreWindow(_THIS, SDL_Window * window)
   343 {
   344 }
   345 void
   346 RPI_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
   347 {
   348 
   349 }
   350 
   351 /*****************************************************************************/
   352 /* SDL Window Manager function                                               */
   353 /*****************************************************************************/
   354 SDL_bool
   355 RPI_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
   356 {
   357     if (info->version.major <= SDL_MAJOR_VERSION) {
   358         return SDL_TRUE;
   359     } else {
   360         SDL_SetError("application not compiled with SDL %d.%d\n",
   361                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   362         return SDL_FALSE;
   363     }
   364 
   365     /* Failed to get window manager information */
   366     return SDL_FALSE;
   367 }
   368 
   369 #endif /* SDL_VIDEO_DRIVER_RPI */
   370 
   371 /* vi: set ts=4 sw=4 expandtab: */