src/video/kmsdrm/SDL_kmsdrmopengles.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 24 Sep 2018 11:49:25 -0700
changeset 12201 8bdc4d340419
parent 11811 5d94cb6b24d3
child 12299 d8683d6ff2f8
permissions -rw-r--r--
Fixed whitespace
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 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_KMSDRM && SDL_VIDEO_OPENGL_EGL
    25 
    26 #include "SDL_log.h"
    27 
    28 #include "SDL_kmsdrmvideo.h"
    29 #include "SDL_kmsdrmopengles.h"
    30 #include "SDL_kmsdrmdyn.h"
    31 
    32 #ifndef EGL_PLATFORM_GBM_MESA
    33 #define EGL_PLATFORM_GBM_MESA 0x31D7
    34 #endif
    35 
    36 /* EGL implementation of SDL OpenGL support */
    37 
    38 int
    39 KMSDRM_GLES_LoadLibrary(_THIS, const char *path) {
    40     return SDL_EGL_LoadLibrary(_this, path, ((SDL_VideoData *)_this->driverdata)->gbm, EGL_PLATFORM_GBM_MESA);
    41 }
    42 
    43 SDL_EGL_CreateContext_impl(KMSDRM)
    44 
    45 SDL_bool
    46 KMSDRM_GLES_SetupCrtc(_THIS, SDL_Window * window) {
    47     SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
    48     SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
    49     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
    50     KMSDRM_FBInfo *fb_info;
    51 
    52     if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
    53         SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed on CRTC setup");
    54         return SDL_FALSE;
    55     }
    56 
    57     wdata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
    58     if (wdata->next_bo == NULL) {
    59         SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer on CRTC setup");
    60         return SDL_FALSE;
    61     }
    62 
    63     fb_info = KMSDRM_FBFromBO(_this, wdata->next_bo);
    64     if (fb_info == NULL) {
    65         return SDL_FALSE;
    66     }
    67 
    68     if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
    69                             0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode) != 0) {
    70        SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC to a GBM buffer");
    71        return SDL_FALSE;
    72 
    73     }
    74 
    75     wdata->crtc_ready = SDL_TRUE;
    76     return SDL_TRUE;
    77 }
    78 
    79 int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
    80     if (!_this->egl_data) {
    81         return SDL_SetError("EGL not initialized");
    82     }
    83 
    84     if (interval == 0 || interval == 1) {
    85         _this->egl_data->egl_swapinterval = interval;
    86     } else {
    87         return SDL_SetError("Only swap intervals of 0 or 1 are supported");
    88     }
    89 
    90     return 0;
    91 }
    92 
    93 int
    94 KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
    95     SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
    96     SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
    97     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
    98     KMSDRM_FBInfo *fb_info;
    99     int ret;
   100 
   101     /* Do we still need to wait for a flip? */
   102     int timeout = 0;
   103     if (_this->egl_data->egl_swapinterval == 1) {
   104         timeout = -1;
   105     }
   106     if (!KMSDRM_WaitPageFlip(_this, wdata, timeout)) {
   107         return 0;
   108     }
   109 
   110     /* Release previously displayed buffer (which is now the backbuffer) and lock a new one */
   111     if (wdata->next_bo != NULL) {
   112         KMSDRM_gbm_surface_release_buffer(wdata->gs, wdata->current_bo);
   113         /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)wdata->next_bo); */
   114 
   115         wdata->current_bo = wdata->next_bo;
   116         wdata->next_bo = NULL;
   117     }
   118 
   119     if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
   120         SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
   121         return 0;
   122     }
   123 
   124     if (wdata->current_bo == NULL) {
   125         wdata->current_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
   126         if (wdata->current_bo == NULL) {
   127             return 0;
   128         }
   129     }
   130 
   131     wdata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
   132     if (wdata->next_bo == NULL) {
   133         SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
   134         return 0;
   135     /* } else {
   136         SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)wdata->next_bo); */
   137     }
   138 
   139     fb_info = KMSDRM_FBFromBO(_this, wdata->next_bo);
   140     if (fb_info == NULL) {
   141         return 0;
   142     }
   143     if (_this->egl_data->egl_swapinterval == 0) {
   144         /* Swap buffers instantly, possible tearing */
   145         /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)",
   146             vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, vdata->saved_conn_id,
   147             displaydata->cur_mode.hdisplay, displaydata->cur_mode.vdisplay, displaydata->cur_mode.vrefresh); */
   148         ret = KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
   149                                     0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode);
   150         if(ret != 0) {
   151             SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not pageflip with drmModeSetCrtc: %d", ret);
   152         }
   153     } else {
   154         /* Queue page flip at vsync */
   155 
   156         /* Have we already setup the CRTC to one of the GBM buffers? Do so if we have not,
   157            or FlipPage won't work in some cases. */
   158         if (!wdata->crtc_ready) {
   159             if(!KMSDRM_GLES_SetupCrtc(_this, window)) {
   160                 SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC for doing vsync-ed pageflips");
   161                 return 0;
   162             }
   163         }
   164 
   165         /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)",
   166             vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
   167         ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
   168                                      DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip);
   169         if (ret == 0) {
   170             wdata->waiting_for_flip = SDL_TRUE;
   171         } else {
   172             SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
   173         }
   174 
   175         /* Wait immediately for vsync (as if we only had two buffers), for low input-lag scenarios.
   176            Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>" to enable this. */
   177         if (wdata->double_buffer) {
   178             KMSDRM_WaitPageFlip(_this, wdata, -1);
   179         }
   180     }
   181 
   182     return 0;
   183 }
   184 
   185 SDL_EGL_MakeCurrent_impl(KMSDRM)
   186 
   187 #endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */
   188 
   189 /* vi: set ts=4 sw=4 expandtab: */