Esempio n. 1
0
/*
 * SDL.getHintBoolean(name[, default])
 *
 * Get a hint as a boolean value.
 * If the hint does not exist, returns the 'truthyness'
 * of the 'default' argument.
 *
 * Arguments:
 *	The name of the hint to query.
 *	The default value to return if the hint does not exist.
 *
 * Returns:
 *	The hint value as a boolean.
 */
static int
l_getHintBoolean(lua_State *L)
{
	const char *name	= luaL_checkstring(L, 1);
	int val			= lua_toboolean(L, 2);

	return commonPush(L, "b", SDL_GetHintBoolean(name, val));
}
Esempio n. 2
0
static SDL_bool
SDL_XInputUseOldJoystickMapping()
{
    static int s_XInputUseOldJoystickMapping = -1;
    if (s_XInputUseOldJoystickMapping < 0) {
        s_XInputUseOldJoystickMapping = SDL_GetHintBoolean(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING, SDL_FALSE);
    }
    return (s_XInputUseOldJoystickMapping > 0);
}
Esempio n. 3
0
static SDL_bool
ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
{
    if (!mouse->SetRelativeMouseMode) {
        return SDL_TRUE;
    }

    return SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, SDL_FALSE);
}
Esempio n. 4
0
int
SDL_XINPUT_JoystickInit(void)
{
    s_bXInputEnabled = SDL_GetHintBoolean(SDL_HINT_XINPUT_ENABLED, SDL_TRUE);

    if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
        s_bXInputEnabled = SDL_FALSE;  /* oh well. */
    }
    return 0;
}
Esempio n. 5
0
static SDL_bool
ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
{
    if (!mouse->SetRelativeMouseMode) {
        SDL_assert(mouse->WarpMouse);   /* Need this functionality for relative mode warp implementation */
        return SDL_TRUE;
    }

    return SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, SDL_FALSE);
}
Esempio n. 6
0
SDL_bool
X11_GL_UseEGL(_THIS)
{
    SDL_assert(_this->gl_data != NULL);
    SDL_assert(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES);

    return (SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, SDL_FALSE)
            || _this->gl_config.major_version == 1 /* No GLX extension for OpenGL ES 1.x profiles. */
            || _this->gl_config.major_version > _this->gl_data->es_profile_max_supported_version.major
            || (_this->gl_config.major_version == _this->gl_data->es_profile_max_supported_version.major
                && _this->gl_config.minor_version > _this->gl_data->es_profile_max_supported_version.minor));
}
Esempio n. 7
0
int
SDL_SYS_JoystickInit(void)
{
    SDL_SYS_JoystickDetect();
    
    if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
        /* Default behavior, accelerometer as joystick */
        Android_AddJoystick(ANDROID_ACCELEROMETER_DEVICE_ID, ANDROID_ACCELEROMETER_NAME, ANDROID_ACCELEROMETER_NAME, SDL_TRUE, 0, 3, 0, 0);
    }
   
    return (numjoysticks);

}
Esempio n. 8
0
static SDL_bool
SDL_XInputUseOldJoystickMapping()
{
#ifdef __WINRT__
    /* TODO: remove this __WINRT__ block, but only after integrating with UWP/WinRT's HID API */
    return SDL_TRUE;
#else
    static int s_XInputUseOldJoystickMapping = -1;
    if (s_XInputUseOldJoystickMapping < 0) {
        s_XInputUseOldJoystickMapping = SDL_GetHintBoolean(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING, SDL_FALSE);
    }
    return (s_XInputUseOldJoystickMapping > 0);
#endif
}
Esempio n. 9
0
static SDL_bool
SDL_XInputUseOldJoystickMapping()
{
#ifdef __WINRT__
    /* TODO: remove this __WINRT__ block, but only after integrating with UWP/WinRT's HID API */
    /* FIXME: Why are Win8/10 different here? -flibit */
    return (NTDDI_VERSION < NTDDI_WIN10);
#else
    static int s_XInputUseOldJoystickMapping = -1;
    if (s_XInputUseOldJoystickMapping < 0) {
        s_XInputUseOldJoystickMapping = SDL_GetHintBoolean(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING, SDL_FALSE);
    }
    return (s_XInputUseOldJoystickMapping > 0);
#endif
}
Esempio n. 10
0
void
SDL_SYS_SetupThread(const char *name)
{
    if ((name != NULL) && IsDebuggerPresent()) {
        THREADNAME_INFO inf;

        /* C# and friends will try to catch this Exception, let's avoid it. */
        if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, SDL_FALSE)) {
            return;
        }

        /* This magic tells the debugger to name a thread if it's listening. */
        SDL_zero(inf);
        inf.dwType = 0x1000;
        inf.szName = name;
        inf.dwThreadID = (DWORD) -1;
        inf.dwFlags = 0;

        /* The debugger catches this, renames the thread, continues on. */
        RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);
    }
}
Esempio n. 11
0
static DWORD
GetWindowStyle(SDL_Window * window)
{
    DWORD style = 0;

    if (window->flags & SDL_WINDOW_FULLSCREEN) {
        style |= STYLE_FULLSCREEN;
    } else {
        if (window->flags & SDL_WINDOW_BORDERLESS) {
            /* SDL 2.1:
               This behavior more closely matches other platform where the window is borderless
               but still interacts with the window manager (e.g. task bar shows above it, it can
               be resized to fit within usable desktop area, etc.) so this should be the behavior
               for a future SDL release.

               If you want a borderless window the size of the desktop that looks like a fullscreen
               window, then you should use the SDL_WINDOW_FULLSCREEN_DESKTOP flag.
             */
            if (SDL_GetHintBoolean("SDL_BORDERLESS_WINDOWED_STYLE", SDL_FALSE)) {
                style |= STYLE_BORDERLESS_WINDOWED;
            } else {
                style |= STYLE_BORDERLESS;
            }
        } else {
            style |= STYLE_NORMAL;
        }

        /* You can have a borderless resizable window */
        if (window->flags & SDL_WINDOW_RESIZABLE) {
            style |= STYLE_RESIZABLE;
        }

        /* Need to set initialize minimize style, or when we call ShowWindow with WS_MINIMIZE it will activate a random window */
        if (window->flags & SDL_WINDOW_MINIMIZED) {
            style |= WS_MINIMIZE;
        }
    }
    return style;
}
Esempio n. 12
0
SDL_EVDEV_keyboard_state *
SDL_EVDEV_kbd_init(void)
{
    SDL_EVDEV_keyboard_state *kbd;
    int i;
    char flag_state;
    char shift_state[2] = {TIOCL_GETSHIFTSTATE, 0};

    kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
    if (!kbd) {
        return NULL;
    }

    kbd->npadch = -1;

    /* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
    kbd->console_fd = open("/dev/tty", O_RDONLY);

    if (ioctl(kbd->console_fd, TIOCLINUX, shift_state) == 0) {
        kbd->shift_state = *shift_state;
    }

    if (ioctl(kbd->console_fd, KDGKBLED, &flag_state) == 0) {
        kbd->ledflagstate = flag_state;
    }

    kbd->accents = &default_accents;
    if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) {
        /* No worries, we'll use the default accent table */
    }

    kbd->key_maps = default_key_maps;
    if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
        /* Set the keyboard in UNICODE mode and load the keymaps */
        ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE);

        if (SDL_EVDEV_kbd_load_keymaps(kbd) < 0) {
            for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
                if (kbd->key_maps[i]) {
                    SDL_free(kbd->key_maps[i]);
                }
            }
            SDL_free(kbd->key_maps);

            kbd->key_maps = default_key_maps;
        }

        /* Allow inhibiting keyboard mute with env. variable for debugging etc. */
        if (getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) {
            /* Mute the keyboard so keystrokes only generate evdev events
             * and do not leak through to the console
             */
            ioctl(kbd->console_fd, KDSKBMODE, K_OFF);

            /* Make sure to restore keyboard if application fails to call
             * SDL_Quit before exit or fatal signal is raised.
             */
            if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) {
                kbd_register_emerg_cleanup(kbd);
            }
        }
    }

#ifdef DUMP_ACCENTS
    SDL_EVDEV_dump_accents(kbd);
#endif
#ifdef DUMP_KEYMAP
    SDL_EVDEV_dump_keymap(kbd);
#endif
    return kbd;
}
Esempio n. 13
0
int
SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst)
{
    Sint64 fp_offset;
    int i, pad;
    SDL_Surface *surface;
    Uint8 *bits;
    SDL_bool save32bit = SDL_FALSE;
    SDL_bool saveLegacyBMP = SDL_FALSE;

    /* The Win32 BMP file header (14 bytes) */
    char magic[2] = { 'B', 'M' };
    Uint32 bfSize;
    Uint16 bfReserved1;
    Uint16 bfReserved2;
    Uint32 bfOffBits;

    /* The Win32 BITMAPINFOHEADER struct (40 bytes) */
    Uint32 biSize;
    Sint32 biWidth;
    Sint32 biHeight;
    Uint16 biPlanes;
    Uint16 biBitCount;
    Uint32 biCompression;
    Uint32 biSizeImage;
    Sint32 biXPelsPerMeter;
    Sint32 biYPelsPerMeter;
    Uint32 biClrUsed;
    Uint32 biClrImportant;

    /* The additional header members from the Win32 BITMAPV4HEADER struct (108 bytes in total) */
    Uint32 bV4RedMask = 0;
    Uint32 bV4GreenMask = 0;
    Uint32 bV4BlueMask = 0;
    Uint32 bV4AlphaMask = 0;
    Uint32 bV4CSType = 0;
    Sint32 bV4Endpoints[3 * 3] = {0};
    Uint32 bV4GammaRed = 0;
    Uint32 bV4GammaGreen = 0;
    Uint32 bV4GammaBlue = 0;

    /* Make sure we have somewhere to save */
    surface = NULL;
    if (dst) {
#ifdef SAVE_32BIT_BMP
        /* We can save alpha information in a 32-bit BMP */
        if (saveme->format->BitsPerPixel >= 8 && (saveme->format->Amask ||
            saveme->map->info.flags & SDL_COPY_COLORKEY)) {
            save32bit = SDL_TRUE;
        }
#endif /* SAVE_32BIT_BMP */

        if (saveme->format->palette && !save32bit) {
            if (saveme->format->BitsPerPixel == 8) {
                surface = saveme;
            } else {
                SDL_SetError("%d bpp BMP files not supported",
                             saveme->format->BitsPerPixel);
            }
        } else if ((saveme->format->BitsPerPixel == 24) && !save32bit &&
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
                   (saveme->format->Rmask == 0x00FF0000) &&
                   (saveme->format->Gmask == 0x0000FF00) &&
                   (saveme->format->Bmask == 0x000000FF)
#else
                   (saveme->format->Rmask == 0x000000FF) &&
                   (saveme->format->Gmask == 0x0000FF00) &&
                   (saveme->format->Bmask == 0x00FF0000)
#endif
            ) {
            surface = saveme;
        } else {
            SDL_PixelFormat format;

            /* If the surface has a colorkey or alpha channel we'll save a
               32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
            if (save32bit) {
                SDL_InitFormat(&format, SDL_PIXELFORMAT_BGRA32);
            } else {
                SDL_InitFormat(&format, SDL_PIXELFORMAT_BGR24);
            }
            surface = SDL_ConvertSurface(saveme, &format, 0);
            if (!surface) {
                SDL_SetError("Couldn't convert image to %d bpp",
                             format.BitsPerPixel);
            }
        }
    } else {
        /* Set no error here because it may overwrite a more useful message from
           SDL_RWFromFile() if SDL_SaveBMP_RW() is called from SDL_SaveBMP(). */
        return -1;
    }

    if (save32bit) {
        saveLegacyBMP = SDL_GetHintBoolean(SDL_HINT_BMP_SAVE_LEGACY_FORMAT, SDL_FALSE);
    }

    if (surface && (SDL_LockSurface(surface) == 0)) {
        const int bw = surface->w * surface->format->BytesPerPixel;

        /* Set the BMP file header values */
        bfSize = 0;             /* We'll write this when we're done */
        bfReserved1 = 0;
        bfReserved2 = 0;
        bfOffBits = 0;          /* We'll write this when we're done */

        /* Write the BMP file header values */
        fp_offset = SDL_RWtell(dst);
        SDL_ClearError();
        SDL_RWwrite(dst, magic, 2, 1);
        SDL_WriteLE32(dst, bfSize);
        SDL_WriteLE16(dst, bfReserved1);
        SDL_WriteLE16(dst, bfReserved2);
        SDL_WriteLE32(dst, bfOffBits);

        /* Set the BMP info values */
        biSize = 40;
        biWidth = surface->w;
        biHeight = surface->h;
        biPlanes = 1;
        biBitCount = surface->format->BitsPerPixel;
        biCompression = BI_RGB;
        biSizeImage = surface->h * surface->pitch;
        biXPelsPerMeter = 0;
        biYPelsPerMeter = 0;
        if (surface->format->palette) {
            biClrUsed = surface->format->palette->ncolors;
        } else {
            biClrUsed = 0;
        }
        biClrImportant = 0;

        /* Set the BMP info values for the version 4 header */
        if (save32bit && !saveLegacyBMP) {
            biSize = 108;
            biCompression = BI_BITFIELDS;
            /* The BMP format is always little endian, these masks stay the same */
            bV4RedMask   = 0x00ff0000;
            bV4GreenMask = 0x0000ff00;
            bV4BlueMask  = 0x000000ff;
            bV4AlphaMask = 0xff000000;
            bV4CSType = LCS_WINDOWS_COLOR_SPACE;
            bV4GammaRed = 0;
            bV4GammaGreen = 0;
            bV4GammaBlue = 0;
        }

        /* Write the BMP info values */
        SDL_WriteLE32(dst, biSize);
        SDL_WriteLE32(dst, biWidth);
        SDL_WriteLE32(dst, biHeight);
        SDL_WriteLE16(dst, biPlanes);
        SDL_WriteLE16(dst, biBitCount);
        SDL_WriteLE32(dst, biCompression);
        SDL_WriteLE32(dst, biSizeImage);
        SDL_WriteLE32(dst, biXPelsPerMeter);
        SDL_WriteLE32(dst, biYPelsPerMeter);
        SDL_WriteLE32(dst, biClrUsed);
        SDL_WriteLE32(dst, biClrImportant);

        /* Write the BMP info values for the version 4 header */
        if (save32bit && !saveLegacyBMP) {
            SDL_WriteLE32(dst, bV4RedMask);
            SDL_WriteLE32(dst, bV4GreenMask);
            SDL_WriteLE32(dst, bV4BlueMask);
            SDL_WriteLE32(dst, bV4AlphaMask);
            SDL_WriteLE32(dst, bV4CSType);
            for (i = 0; i < 3 * 3; i++) {
                SDL_WriteLE32(dst, bV4Endpoints[i]);
            }
            SDL_WriteLE32(dst, bV4GammaRed);
            SDL_WriteLE32(dst, bV4GammaGreen);
            SDL_WriteLE32(dst, bV4GammaBlue);
        }

        /* Write the palette (in BGR color order) */
        if (surface->format->palette) {
            SDL_Color *colors;
            int ncolors;

            colors = surface->format->palette->colors;
            ncolors = surface->format->palette->ncolors;
            for (i = 0; i < ncolors; ++i) {
                SDL_RWwrite(dst, &colors[i].b, 1, 1);
                SDL_RWwrite(dst, &colors[i].g, 1, 1);
                SDL_RWwrite(dst, &colors[i].r, 1, 1);
                SDL_RWwrite(dst, &colors[i].a, 1, 1);
            }
        }

        /* Write the bitmap offset */
        bfOffBits = (Uint32)(SDL_RWtell(dst) - fp_offset);
        if (SDL_RWseek(dst, fp_offset + 10, RW_SEEK_SET) < 0) {
            SDL_Error(SDL_EFSEEK);
        }
        SDL_WriteLE32(dst, bfOffBits);
        if (SDL_RWseek(dst, fp_offset + bfOffBits, RW_SEEK_SET) < 0) {
            SDL_Error(SDL_EFSEEK);
        }

        /* Write the bitmap image upside down */
        bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
        pad = ((bw % 4) ? (4 - (bw % 4)) : 0);
        while (bits > (Uint8 *) surface->pixels) {
            bits -= surface->pitch;
            if (SDL_RWwrite(dst, bits, 1, bw) != bw) {
                SDL_Error(SDL_EFWRITE);
                break;
            }
            if (pad) {
                const Uint8 padbyte = 0;
                for (i = 0; i < pad; ++i) {
                    SDL_RWwrite(dst, &padbyte, 1, 1);
                }
            }
        }

        /* Write the BMP file size */
        bfSize = (Uint32)(SDL_RWtell(dst) - fp_offset);
        if (SDL_RWseek(dst, fp_offset + 2, RW_SEEK_SET) < 0) {
            SDL_Error(SDL_EFSEEK);
        }
        SDL_WriteLE32(dst, bfSize);
        if (SDL_RWseek(dst, fp_offset + bfSize, RW_SEEK_SET) < 0) {
            SDL_Error(SDL_EFSEEK);
        }

        /* Close it up.. */
        SDL_UnlockSurface(surface);
        if (surface != saveme) {
            SDL_FreeSurface(surface);
        }
    }

    if (freedst && dst) {
        SDL_RWclose(dst);
    }
    return ((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1);
}
Esempio n. 14
0
/* Public functions */
static int
SDL_QuitInit_Internal(void)
{
#ifdef HAVE_SIGACTION
    struct sigaction action;
    sigaction(SIGINT, NULL, &action);
#ifdef HAVE_SA_SIGACTION
    if ( action.sa_handler == SIG_DFL && (void (*)(int))action.sa_sigaction == SIG_DFL ) {
#else
    if ( action.sa_handler == SIG_DFL ) {
#endif
        action.sa_handler = SDL_HandleSIG;
        sigaction(SIGINT, &action, NULL);
    }
    sigaction(SIGTERM, NULL, &action);

#ifdef HAVE_SA_SIGACTION
    if ( action.sa_handler == SIG_DFL && (void (*)(int))action.sa_sigaction == SIG_DFL ) {
#else
    if ( action.sa_handler == SIG_DFL ) {
#endif
        action.sa_handler = SDL_HandleSIG;
        sigaction(SIGTERM, &action, NULL);
    }
#elif HAVE_SIGNAL_H
    void (*ohandler) (int);

    /* Both SIGINT and SIGTERM are translated into quit interrupts */
    ohandler = signal(SIGINT, SDL_HandleSIG);
    if (ohandler != SIG_DFL)
        signal(SIGINT, ohandler);
    ohandler = signal(SIGTERM, SDL_HandleSIG);
    if (ohandler != SIG_DFL)
        signal(SIGTERM, ohandler);
#endif /* HAVE_SIGNAL_H */

    /* That's it! */
    return 0;
}

int
SDL_QuitInit(void)
{
    if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) {
        return SDL_QuitInit_Internal();
    }
    return 0;
}

static void
SDL_QuitQuit_Internal(void)
{
#ifdef HAVE_SIGACTION
    struct sigaction action;
    sigaction(SIGINT, NULL, &action);
    if ( action.sa_handler == SDL_HandleSIG ) {
        action.sa_handler = SIG_DFL;
        sigaction(SIGINT, &action, NULL);
    }
    sigaction(SIGTERM, NULL, &action);
    if ( action.sa_handler == SDL_HandleSIG ) {
        action.sa_handler = SIG_DFL;
        sigaction(SIGTERM, &action, NULL);
    }
#elif HAVE_SIGNAL_H
    void (*ohandler) (int);

    ohandler = signal(SIGINT, SIG_DFL);
    if (ohandler != SDL_HandleSIG)
        signal(SIGINT, ohandler);
    ohandler = signal(SIGTERM, SIG_DFL);
    if (ohandler != SDL_HandleSIG)
        signal(SIGTERM, ohandler);
#endif /* HAVE_SIGNAL_H */
}

void
SDL_QuitQuit(void)
{
    if (!disable_signals) {
        SDL_QuitQuit_Internal();
    }
}

/* This function returns 1 if it's okay to close the application window */
int
SDL_SendQuit(void)
{
    send_quit_pending = SDL_FALSE;
    return SDL_SendAppEvent(SDL_QUIT);
}

void
SDL_SendPendingQuit(void)
{
    if (send_quit_pending) {
        SDL_SendQuit();
        SDL_assert(!send_quit_pending);
    }
}
Esempio n. 15
0
int
KMSDRM_CreateWindow(_THIS, SDL_Window * window)
{
    SDL_WindowData *wdata;
    SDL_VideoDisplay *display;
    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
    Uint32 surface_fmt, surface_flags;

    /* Allocate window internal data */
    wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
    if (wdata == NULL) {
        SDL_OutOfMemory();
        goto error;
    }

    wdata->waiting_for_flip = SDL_FALSE;
    display = SDL_GetDisplayForWindow(window);

    /* Windows have one size for now */
    window->w = display->desktop_mode.w;
    window->h = display->desktop_mode.h;

    /* Maybe you didn't ask for a fullscreen OpenGL window, but that's what you get */
    window->flags |= (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);

    surface_fmt = GBM_FORMAT_XRGB8888;
    surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;

    if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, surface_fmt, surface_flags)) {
        SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "GBM surface format not supported. Trying anyway.");
    }
    wdata->gs = KMSDRM_gbm_surface_create(vdata->gbm, window->w, window->h, surface_fmt, surface_flags);

#if SDL_VIDEO_OPENGL_EGL
    if (!_this->egl_data) {
        if (SDL_GL_LoadLibrary(NULL) < 0) {
            goto error;
        }
    }
    wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wdata->gs);

    if (wdata->egl_surface == EGL_NO_SURFACE) {
        SDL_SetError("Could not create EGL window surface");
        goto error;
    }
#endif /* SDL_VIDEO_OPENGL_EGL */

    /* In case we want low-latency, double-buffer video, we take note here */
    wdata->double_buffer = SDL_FALSE;
    if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) {
        wdata->double_buffer = SDL_TRUE;
    }

    /* Window is created, but we have yet to set up CRTC to one of the GBM buffers if we want
       drmModePageFlip to work, and we can't do it until EGL is completely setup, because we
       need to do eglSwapBuffers so we can get a valid GBM buffer object to call
       drmModeSetCrtc on it. */
    wdata->crtc_ready = SDL_FALSE;

    /* Setup driver data for this window */
    window->driverdata = wdata;

    /* One window, it always has focus */
    SDL_SetMouseFocus(window);
    SDL_SetKeyboardFocus(window);

    /* Window has been successfully created */
    return 0;

error:
    if (wdata != NULL) {
#if SDL_VIDEO_OPENGL_EGL
        if (wdata->egl_surface != EGL_NO_SURFACE)
            SDL_EGL_DestroySurface(_this, wdata->egl_surface);
#endif /* SDL_VIDEO_OPENGL_EGL */
        if (wdata->gs != NULL)
            KMSDRM_gbm_surface_destroy(wdata->gs);
        SDL_free(wdata);
    }
    return -1;
}