예제 #1
0
static void
SDL_GameControllerLoadHints()
{
    const char *hint = SDL_GetHint(SDL_HINT_GAMECONTROLLERCONFIG);
    if (hint && hint[0]) {
        size_t nchHints = SDL_strlen(hint);
        char *pUserMappings = SDL_malloc(nchHints + 1);
        char *pTempMappings = pUserMappings;
        SDL_memcpy(pUserMappings, hint, nchHints);
        pUserMappings[nchHints] = '\0';
        while (pUserMappings) {
            char *pchNewLine = NULL;

            pchNewLine = SDL_strchr(pUserMappings, '\n');
            if (pchNewLine)
                *pchNewLine = '\0';

            SDL_GameControllerAddMapping(pUserMappings);

            if (pchNewLine) {
                pUserMappings = pchNewLine + 1;
            } else {
                pUserMappings = NULL;
            }
        }
        SDL_free(pTempMappings);
    }
}
예제 #2
0
파일: window.cpp 프로젝트: fesh0r/mame-full
bool sdl_osd_interface::window_init()
{
	osd_printf_verbose("Enter sdlwindow_init\n");

	// initialize the drawers

	switch (video_config.mode)
	{
		case VIDEO_MODE_BGFX:
			renderer_bgfx::init(machine());
			break;
#if (USE_OPENGL)
		case VIDEO_MODE_OPENGL:
			renderer_ogl::init(machine());
			break;
#endif
		case VIDEO_MODE_SDL2ACCEL:
			renderer_sdl2::init(machine());
			break;
		case VIDEO_MODE_SOFT:
			renderer_sdl1::init(machine());
			break;
	}

	/* We may want to set a number of the hints SDL2 provides.
	 * The code below will document which hints were set.
	 */
	const char * hints[] = { SDL_HINT_FRAMEBUFFER_ACCELERATION,
			SDL_HINT_RENDER_DRIVER, SDL_HINT_RENDER_OPENGL_SHADERS,
			SDL_HINT_RENDER_SCALE_QUALITY,
			SDL_HINT_RENDER_VSYNC,
			SDL_HINT_VIDEO_X11_XVIDMODE, SDL_HINT_VIDEO_X11_XINERAMA,
			SDL_HINT_VIDEO_X11_XRANDR, SDL_HINT_GRAB_KEYBOARD,
			SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, SDL_HINT_IDLE_TIMER_DISABLED,
			SDL_HINT_ORIENTATIONS,
			SDL_HINT_XINPUT_ENABLED, SDL_HINT_GAMECONTROLLERCONFIG,
			SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_HINT_ALLOW_TOPMOST,
			SDL_HINT_TIMER_RESOLUTION,
#if SDL_VERSION_ATLEAST(2, 0, 2)
			SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_HINT_VIDEO_ALLOW_SCREENSAVER,
			SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK,
			SDL_HINT_VIDEO_WIN_D3DCOMPILER, SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT,
			SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_HINT_MOUSE_RELATIVE_MODE_WARP,
#endif
#if SDL_VERSION_ATLEAST(2, 0, 3)
			SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_HINT_VIDEO_HIGHDPI_DISABLED,
			SDL_HINT_WINRT_PRIVACY_POLICY_URL, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL,
			SDL_HINT_WINRT_HANDLE_BACK_BUTTON,
#endif
			nullptr
	};

	osd_printf_verbose("\nHints:\n");
	for (int i = 0; hints[i] != nullptr; i++)
		osd_printf_verbose("\t%-40s %s\n", hints[i], SDL_GetHint(hints[i]));

	// set up the window list
	osd_printf_verbose("Leave sdlwindow_init\n");
	return true;
}
예제 #3
0
int
WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
{
    HWND hwnd = (HWND) data;
    LPTSTR title;
    int titleLen;

    /* Query the title from the existing window */
    titleLen = GetWindowTextLength(hwnd);
    title = SDL_stack_alloc(TCHAR, titleLen + 1);
    if (title) {
        titleLen = GetWindowText(hwnd, title, titleLen);
    } else {
        titleLen = 0;
    }
    if (titleLen > 0) {
        window->title = WIN_StringToUTF8(title);
    }
    if (title) {
        SDL_stack_free(title);
    }

    if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
        return -1;
    }

    // Urho3D: if window will be used for OpenGL, choose pixel format
    if (window->flags & SDL_WINDOW_OPENGL) {
        if (WIN_GL_SetupWindow(_this, window) < 0) {
            return -1;
        }
    }

#if SDL_VIDEO_OPENGL_WGL
    {
        const char *hint = SDL_GetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT);
        if (hint) {
            // This hint is a pointer (in string form) of the address of
            // the window to share a pixel format with
            SDL_Window *otherWindow = NULL;
            SDL_sscanf(hint, "%p", (void**)&otherWindow);

            // Do some error checking on the pointer
            if (otherWindow != NULL && otherWindow->magic == &_this->window_magic)
            {
                // If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well
                if (otherWindow->flags & SDL_WINDOW_OPENGL)
                {
                    window->flags |= SDL_WINDOW_OPENGL;
                    if(!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
                        return -1;
                    }
                }
            }
        }
    }
#endif
    return 0;
}
예제 #4
0
파일: hint.c 프로젝트: furunkel/ruby-sdl2
/*
 * @overload [](hint)
 *   Get the value of a hint.
 *
 *   @param hint [String] the name of the hint to query
 *   
 * @return [String] the string value of a hint
 * @return [nil] if the hint isn't set
 */
static VALUE Hints_s_aref(VALUE self, VALUE name)
{
    const char* value = SDL_GetHint(StringValueCStr(name));
    if (value)
        return utf8str_new_cstr(value);
    else
        return Qnil;
}
예제 #5
0
static SDL_bool
SDL_XInputUseOldJoystickMapping()
{
    static int s_XInputUseOldJoystickMapping = -1;
    if (s_XInputUseOldJoystickMapping < 0) {
        const char *hint = SDL_GetHint(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING);
        s_XInputUseOldJoystickMapping = (hint && *hint == '1') ? 1 : 0;
    }
    return (s_XInputUseOldJoystickMapping > 0);
}
예제 #6
0
파일: SDL_hints.c 프로젝트: 0-wiz-0/mame
void
SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
{
    SDL_Hint *hint;
    SDL_HintWatch *entry;
    const char *value;

    if (!name || !*name) {
        SDL_InvalidParamError("name");
        return;
    }
    if (!callback) {
        SDL_InvalidParamError("callback");
        return;
    }

    SDL_DelHintCallback(name, callback, userdata);

    entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
    if (!entry) {
        SDL_OutOfMemory();
        return;
    }
    entry->callback = callback;
    entry->userdata = userdata;

    for (hint = SDL_hints; hint; hint = hint->next) {
        if (SDL_strcmp(name, hint->name) == 0) {
            break;
        }
    }
    if (!hint) {
        /* Need to add a hint entry for this watcher */
        hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
        if (!hint) {
            SDL_OutOfMemory();
            SDL_free(entry);
            return;
        }
        hint->name = SDL_strdup(name);
        hint->value = NULL;
        hint->priority = SDL_HINT_DEFAULT;
        hint->callbacks = NULL;
        hint->next = SDL_hints;
        SDL_hints = hint;
    }

    /* Add it to the callbacks for this hint */
    entry->next = hint->callbacks;
    hint->callbacks = entry;

    /* Now call it with the current value */
    value = SDL_GetHint(name);
    callback(userdata, name, value, value);
}
예제 #7
0
static GLenum
GetScaleQuality(void)
{
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);

    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
        return GL_NEAREST;
    } else {
        return GL_LINEAR;
    }
}
예제 #8
0
파일: SDL_render_sw.c 프로젝트: ifzz/exsdk
static int
GetScaleQuality(void)
{
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);

    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
        return 0;
    } else {
        return 1;
    }
}
예제 #9
0
/* Pause (block) all non already paused audio devices by taking their mixer lock */
void AndroidAUD_PauseDevices(void)
{
    /* TODO: Handle multiple devices? */
	const char* hint = SDL_GetHint(SDL_HINT_BACKGROUND_AUDIO);

    struct SDL_PrivateAudioData *private;
    if(audioDevice != NULL && audioDevice->hidden != NULL) {
        private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
        if (audioDevice->paused) {
            /* The device is already paused, leave it alone */
            private->resume = SDL_FALSE;
        }
예제 #10
0
파일: SDL_hints.c 프로젝트: 0-wiz-0/mame
SDL_bool
SDL_GetHintBoolean(const char *name, SDL_bool default_value)
{
    const char *hint = SDL_GetHint(name);
    if (!hint) {
        return default_value;
    }
    if (*hint == '0' || SDL_strcasecmp(hint, "false") == 0) {
        return SDL_FALSE;
    }
    return SDL_TRUE;
}
예제 #11
0
std::string hint( const std::string& name )
{
  const char* result;

  result = SDL_GetHint( name.c_str() );

  // Success
  if( result != nullptr ) return result;

  // Err
  return "\0";
}
예제 #12
0
파일: SDL.c 프로젝트: RichardRanft/luasdl2
/*
 * SDL.getHint(name)
 *
 * Arguments:
 *	name the hint name
 *
 * Returns:
 *	The hint value or nil
 */
static int
l_getHint(lua_State *L)
{
	const char *name = luaL_checkstring(L, 1);
	const char *value = SDL_GetHint(name);

	if (value == NULL)
		lua_pushnil(L);
	else
		lua_pushstring(L, value);

	return 1;
}
static D3DTEXTUREFILTERTYPE
GetScaleQuality(void)
{
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);

    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
        return D3DTEXF_POINT;
    } else if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) {
        return D3DTEXF_LINEAR;
    } else {
        return D3DTEXF_ANISOTROPIC;
    }
}
예제 #14
0
int
SDL_XINPUT_JoystickInit(void)
{
    const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
    if (env && !SDL_atoi(env)) {
        s_bXInputEnabled = SDL_FALSE;
    }

    if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
        s_bXInputEnabled = SDL_FALSE;  /* oh well. */
    }
    return 0;
}
예제 #15
0
int
SDL_SYS_JoystickInit(void)
{
    const char *hint;
    SDL_SYS_JoystickDetect();
    
    hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
    if (!hint || SDL_atoi(hint)) {
        /* Default behavior, accelerometer as joystick */
        Android_AddJoystick(ANDROID_ACCELEROMETER_DEVICE_ID, ANDROID_ACCELEROMETER_NAME, SDL_TRUE, 0, 3, 0, 0);
    }
   
    return (numjoysticks);

}
예제 #16
0
int
SDL_XINPUT_HapticInit(void)
{
    const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
    if (!env || SDL_atoi(env)) {
        loaded_xinput = (WIN_LoadXInputDLL() == 0);
    }

    if (loaded_xinput) {
        DWORD i;
        for (i = 0; i < XUSER_MAX_COUNT; i++) {
            SDL_XINPUT_MaybeAddDevice(i);
        }
    }
    return 0;
}
예제 #17
0
int
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
{
    pthread_attr_t type;
    size_t ss;
    const char *hint = SDL_GetHint(SDL_HINT_THREAD_STACK_SIZE);

    /* do this here before any threads exist, so there's no race condition. */
    #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
    if (!checked_setname) {
        void *fn = dlsym(RTLD_DEFAULT, "pthread_setname_np");
        #if defined(__MACOSX__) || defined(__IPHONEOS__)
        ppthread_setname_np = (int(*)(const char*)) fn;
        #elif defined(__LINUX__)
        ppthread_setname_np = (int(*)(pthread_t, const char*)) fn;
        #endif
        checked_setname = SDL_TRUE;
    }
    #endif

    /* Set the thread attributes */
    if (pthread_attr_init(&type) != 0) {
        return SDL_SetError("Couldn't initialize pthread attributes");
    }
    pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
    
    /* If the SDL_HINT_THREAD_STACK_SIZE exists and it seems to be a positive number, use it */
    if (hint && hint[0] >= '0' && hint[0] <= '9') {
        const size_t stacksize = (size_t) SDL_atoi(hint);
        if (stacksize > 0) {
            pthread_attr_setstacksize(&type, stacksize);
        }
    }
    
    pthread_attr_getstacksize(&type, &ss);

    /* Create the thread and go! */
    if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
        return SDL_SetError("Not enough resources to create thread");
    }

    return 0;
}
예제 #18
0
static SDL_bool
ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
{
    const char *hint;

    if (!mouse->SetRelativeMouseMode) {
        return SDL_TRUE;
    }

    hint = SDL_GetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP);
    if (hint) {
        if (*hint == '0') {
            return SDL_FALSE;
        } else {
            return SDL_TRUE;
        }
    }
    return SDL_FALSE;
}
예제 #19
0
bool sdl_osd_interface::window_init()
{
	osd_printf_verbose("Enter sdlwindow_init\n");
	// determine if we are using multithreading or not
	multithreading_enabled = options().multithreading();

	// get the main thread ID before anything else
	main_threadid = SDL_ThreadID();

	// if multithreading, create a thread to run the windows
	if (multithreading_enabled)
	{
		// create a thread to run the windows from
		work_queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_IO);
		if (work_queue == NULL)
			return false;
		osd_work_item_queue(work_queue, &sdlwindow_thread_id, NULL, WORK_ITEM_FLAG_AUTO_RELEASE);
		sdlwindow_sync();
	}
	else
	{
		// otherwise, treat the window thread as the main thread
		//window_threadid = main_threadid;
		sdlwindow_thread_id(NULL, 0);
	}

	// initialize the drawers
#if USE_OPENGL
	if (video_config.mode == VIDEO_MODE_OPENGL)
	{
		if (drawogl_init(machine(), &draw))
			video_config.mode = VIDEO_MODE_SOFT;
	}
#endif
#if SDLMAME_SDL2
	if (video_config.mode == VIDEO_MODE_SDL2ACCEL)
	{
		if (drawsdl2_init(machine(), &draw))
			video_config.mode = VIDEO_MODE_SOFT;
	}
#endif
#ifdef USE_BGFX
	if (video_config.mode == VIDEO_MODE_BGFX)
	{
		if (drawbgfx_init(machine(), &draw))
			video_config.mode = VIDEO_MODE_SOFT;
	}
#endif
	if (video_config.mode == VIDEO_MODE_SOFT)
	{
		if (drawsdl_init(&draw))
			return false;
	}

#if SDLMAME_SDL2
	/* We may want to set a number of the hints SDL2 provides.
	 * The code below will document which hints were set.
	 */
	const char * hints[] = { SDL_HINT_FRAMEBUFFER_ACCELERATION,
			SDL_HINT_RENDER_DRIVER, SDL_HINT_RENDER_OPENGL_SHADERS,
			SDL_HINT_RENDER_SCALE_QUALITY,
			SDL_HINT_RENDER_VSYNC,
			SDL_HINT_VIDEO_X11_XVIDMODE, SDL_HINT_VIDEO_X11_XINERAMA,
			SDL_HINT_VIDEO_X11_XRANDR, SDL_HINT_GRAB_KEYBOARD,
			SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, SDL_HINT_IDLE_TIMER_DISABLED,
			SDL_HINT_ORIENTATIONS,
			SDL_HINT_XINPUT_ENABLED, SDL_HINT_GAMECONTROLLERCONFIG,
			SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_HINT_ALLOW_TOPMOST,
			SDL_HINT_TIMER_RESOLUTION,
#if SDL_VERSION_ATLEAST(2, 0, 2)
			SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_HINT_VIDEO_ALLOW_SCREENSAVER,
			SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK,
			SDL_HINT_VIDEO_WIN_D3DCOMPILER, SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT,
			SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_HINT_MOUSE_RELATIVE_MODE_WARP,
#endif
#if SDL_VERSION_ATLEAST(2, 0, 3)
			SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_HINT_VIDEO_HIGHDPI_DISABLED,
			SDL_HINT_WINRT_PRIVACY_POLICY_URL, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL,
			SDL_HINT_WINRT_HANDLE_BACK_BUTTON,
#endif
			NULL
	};

	osd_printf_verbose("\nHints:\n");
	for (int i = 0; hints[i] != NULL; i++)
		osd_printf_verbose("\t%-40s %s\n", hints[i], SDL_GetHint(hints[i]));
#endif

	// set up the window list
	last_window_ptr = &sdl_window_list;
	osd_printf_verbose("Leave sdlwindow_init\n");
	return true;
}
예제 #20
0
std::vector<Window::ContextAttribs> Window::getContextAttribsList() const
{
	// If we already have a set of context attributes that we know work, just
	// return that. love.graphics doesn't really support switching GL versions
	// after the first initialization.
	if (contextAttribs.versionMajor > 0)
		return std::vector<ContextAttribs>{contextAttribs};

	bool preferGLES = false;

#ifdef LOVE_GRAPHICS_USE_OPENGLES
	preferGLES = true;
#endif

	const char *curdriver = SDL_GetCurrentVideoDriver();
	const char *glesdrivers[] = {"RPI", "Android", "uikit", "winrt", "emscripten"};

	// We always want to try OpenGL ES first on certain video backends.
	for (const char *glesdriver : glesdrivers)
	{
		if (curdriver && strstr(curdriver, glesdriver) == curdriver)
		{
			preferGLES = true;

			// Prior to SDL 2.0.4, backends that use OpenGL ES didn't properly
			// ask for a sRGB framebuffer when requested by SDL_GL_SetAttribute.
			// FIXME: This doesn't account for windowing backends that sometimes
			// use EGL, e.g. the X11 and windows SDL backends.
			if (hasSDL203orEarlier)
				graphics::setGammaCorrect(false);

			break;
		}
	}

	if (!preferGLES)
	{
		const char *gleshint = SDL_GetHint("LOVE_GRAPHICS_USE_OPENGLES");
		preferGLES = (gleshint != nullptr && gleshint[0] != '0');
	}

	// Do we want a debug context?
	bool debug = love::graphics::isDebugEnabled();

	const char *preferGL2hint = SDL_GetHint("LOVE_GRAPHICS_USE_GL2");
	bool preferGL2 = (preferGL2hint != nullptr && preferGL2hint[0] != '0');

	std::vector<ContextAttribs> glcontexts = {{2, 1, false, debug}};
	glcontexts.insert(preferGL2 ? glcontexts.end() : glcontexts.begin(), {3, 3, false, debug});

	std::vector<ContextAttribs> glescontexts = {{2, 0, true, debug}};

	// While UWP SDL is above 2.0.4, it still doesn't support OpenGL ES 3+
#ifndef LOVE_WINDOWS_UWP
	// OpenGL ES 3+ contexts are only properly supported in SDL 2.0.4+.
	if (!hasSDL203orEarlier)
		glescontexts.insert(preferGL2 ? glescontexts.end() : glescontexts.begin(), {3, 0, true, debug});
#endif

	std::vector<ContextAttribs> attribslist;

	if (preferGLES)
	{
		attribslist.insert(attribslist.end(), glescontexts.begin(), glescontexts.end());
		attribslist.insert(attribslist.end(), glcontexts.begin(), glcontexts.end());
	}
	else
	{
		attribslist.insert(attribslist.end(), glcontexts.begin(), glcontexts.end());
		attribslist.insert(attribslist.end(), glescontexts.begin(), glescontexts.end());
	}

	return attribslist;
}
예제 #21
0
SDL_Renderer *
SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
{
    SDL_Renderer *renderer = NULL;
    int n = SDL_GetNumRenderDrivers();
    const char *hint;

    if (!window) {
        SDL_SetError("Invalid window");
        return NULL;
    }

    if (SDL_GetRenderer(window)) {
        SDL_SetError("Renderer already associated with window");
        return NULL;
    }

    hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC);
    if (hint) {
        if (*hint == '0') {
            flags &= ~SDL_RENDERER_PRESENTVSYNC;
        } else {
            flags |= SDL_RENDERER_PRESENTVSYNC;
        }
    }

    if (index < 0) {
        hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
        if (hint) {
            for (index = 0; index < n; ++index) {
                const SDL_RenderDriver *driver = render_drivers[index];

                if (SDL_strcasecmp(hint, driver->info.name) == 0) {
                    /* Create a new renderer instance */
                    renderer = driver->CreateRenderer(window, flags);
                    break;
                }
            }
        }

        if (!renderer) {
            for (index = 0; index < n; ++index) {
                const SDL_RenderDriver *driver = render_drivers[index];

                if ((driver->info.flags & flags) == flags) {
                    /* Create a new renderer instance */
                    renderer = driver->CreateRenderer(window, flags);
                    if (renderer) {
                        /* Yay, we got one! */
                        break;
                    }
                }
            }
        }
        if (index == n) {
            SDL_SetError("Couldn't find matching render driver");
            return NULL;
        }
    } else {
        if (index >= SDL_GetNumRenderDrivers()) {
            SDL_SetError("index must be -1 or in the range of 0 - %d",
                         SDL_GetNumRenderDrivers() - 1);
            return NULL;
        }
        /* Create a new renderer instance */
        renderer = render_drivers[index]->CreateRenderer(window, flags);
    }

    if (renderer) {
        renderer->magic = &renderer_magic;
        renderer->window = window;

        if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) {
            renderer->minimized = SDL_TRUE;
        } else {
            renderer->minimized = SDL_FALSE;
        }

        SDL_SetWindowData(window, SDL_WINDOWRENDERDATA, renderer);

        SDL_RenderSetViewport(renderer, NULL);

        SDL_AddEventWatch(SDL_RendererEventWatch, renderer);

        SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,
                    "Created renderer: %s", renderer->info.name);
    }
    return renderer;
}
예제 #22
0
int
SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform)
{
    void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
    const char *path = NULL;
    int egl_version_major = 0, egl_version_minor = 0;
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
    const char *d3dcompiler;
#endif

    if (_this->egl_data) {
        return SDL_SetError("OpenGL ES context already created");
    }

    _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
    if (!_this->egl_data) {
        return SDL_OutOfMemory();
    }

#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
    d3dcompiler = SDL_GetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER);
    if (!d3dcompiler) {
        if (WIN_IsWindowsVistaOrGreater()) {
            d3dcompiler = "d3dcompiler_46.dll";
        } else {
            d3dcompiler = "d3dcompiler_43.dll";
        }
    }
    if (SDL_strcasecmp(d3dcompiler, "none") != 0) {
        if (SDL_LoadObject(d3dcompiler) == NULL) {
            SDL_ClearError();
        }
    }
#endif

#ifndef SDL_VIDEO_STATIC_ANGLE
    /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
    path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
    if (path != NULL) {
        egl_dll_handle = SDL_LoadObject(path);
    }

    if (egl_dll_handle == NULL) {
        if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
            if (_this->gl_config.major_version > 1) {
                path = DEFAULT_OGL_ES2;
                egl_dll_handle = SDL_LoadObject(path);
#ifdef ALT_OGL_ES2
                if (egl_dll_handle == NULL) {
                    path = ALT_OGL_ES2;
                    egl_dll_handle = SDL_LoadObject(path);
                }
#endif

            } else {
                path = DEFAULT_OGL_ES;
                egl_dll_handle = SDL_LoadObject(path);
                if (egl_dll_handle == NULL) {
                    path = DEFAULT_OGL_ES_PVR;
                    egl_dll_handle = SDL_LoadObject(path);
                }
            }
        }
#ifdef DEFAULT_OGL         
        else {
            path = DEFAULT_OGL;
            egl_dll_handle = SDL_LoadObject(path);
        }
#endif        
    }
    _this->egl_data->egl_dll_handle = egl_dll_handle;

    if (egl_dll_handle == NULL) {
        return SDL_SetError("Could not initialize OpenGL / GLES library");
    }

    /* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
    if (egl_path != NULL) {
        dll_handle = SDL_LoadObject(egl_path);
    }   
    /* Try loading a EGL symbol, if it does not work try the default library paths */
    if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) {
        if (dll_handle != NULL) {
            SDL_UnloadObject(dll_handle);
        }
        path = SDL_getenv("SDL_VIDEO_EGL_DRIVER");
        if (path == NULL) {
            path = DEFAULT_EGL;
        }
        dll_handle = SDL_LoadObject(path);

#ifdef ALT_EGL
        if (dll_handle == NULL) {
            path = ALT_EGL;
            dll_handle = SDL_LoadObject(path);
        }
#endif

        if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) {
            if (dll_handle != NULL) {
                SDL_UnloadObject(dll_handle);
            }
            return SDL_SetError("Could not load EGL library");
        }
        SDL_ClearError();
    }
#endif

    _this->egl_data->dll_handle = dll_handle;

    /* Load new function pointers */
    LOAD_FUNC(eglGetDisplay);
    LOAD_FUNC(eglInitialize);
    LOAD_FUNC(eglTerminate);
    LOAD_FUNC(eglGetProcAddress);
    LOAD_FUNC(eglChooseConfig);
    LOAD_FUNC(eglGetConfigAttrib);
    LOAD_FUNC(eglCreateContext);
    LOAD_FUNC(eglDestroyContext);
    LOAD_FUNC(eglCreateWindowSurface);
    LOAD_FUNC(eglDestroySurface);
    LOAD_FUNC(eglMakeCurrent);
    LOAD_FUNC(eglSwapBuffers);
    LOAD_FUNC(eglSwapInterval);
    LOAD_FUNC(eglWaitNative);
    LOAD_FUNC(eglWaitGL);
    LOAD_FUNC(eglBindAPI);
    LOAD_FUNC(eglQueryString);
    LOAD_FUNC(eglGetError);

    if (_this->egl_data->eglQueryString) {
        /* EGL 1.5 allows querying for client version */
        const char *egl_version = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_VERSION);
        if (egl_version != NULL) {
            if (SDL_sscanf(egl_version, "%d.%d", &egl_version_major, &egl_version_minor) != 2) {
                egl_version_major = 0;
                egl_version_minor = 0;
                SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not parse EGL version string: %s", egl_version);
            }
        }
    }

    if (egl_version_major == 1 && egl_version_minor == 5) {
        LOAD_FUNC(eglGetPlatformDisplay);
    }

    _this->egl_data->egl_display = EGL_NO_DISPLAY;
#if !defined(__WINRT__)
    if (platform) {
        if (egl_version_major == 1 && egl_version_minor == 5) {
            _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(size_t)native_display, NULL);
        } else {
            if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) {
                _this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddress(_this, "eglGetPlatformDisplayEXT");
                if (_this->egl_data->eglGetPlatformDisplayEXT) {
                    _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, (void *)(size_t)native_display, NULL);
                }
            }
        }
    }
    /* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */
    if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
        _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
    }
    if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
        return SDL_SetError("Could not get EGL display");
    }
    
    if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
        return SDL_SetError("Could not initialize EGL");
    }
#endif

    if (path) {
        SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
    } else {
        *_this->gl_config.driver_path = '\0';
    }
    
    return 0;
}
예제 #23
0
파일: SDL_egl.c 프로젝트: wpbest/UWP
int
SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display)
{
    void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
    char *path = NULL;
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
    const char *d3dcompiler;
#endif

    if (_this->egl_data) {
        return SDL_SetError("OpenGL ES context already created");
    }

    _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
    if (!_this->egl_data) {
        return SDL_OutOfMemory();
    }

#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
    d3dcompiler = SDL_GetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER);
    if (!d3dcompiler) {
        if (WIN_IsWindowsVistaOrGreater()) {
            //WPB Changed to from d3dcompiler_46.dll to d3dcompiler_47.dll
            d3dcompiler = "d3dcompiler_47.dll";
        } else {
            d3dcompiler = "d3dcompiler_43.dll";
        }
    }
    if (SDL_strcasecmp(d3dcompiler, "none") != 0) {
        SDL_LoadObject(d3dcompiler);
    }
#endif

    /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
    path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
    if (path != NULL) {
        egl_dll_handle = SDL_LoadObject(path);
    }

    if (egl_dll_handle == NULL) {
        if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
            if (_this->gl_config.major_version > 1) {
                path = DEFAULT_OGL_ES2;
                egl_dll_handle = SDL_LoadObject(path);
            } else {
                path = DEFAULT_OGL_ES;
                egl_dll_handle = SDL_LoadObject(path);
                if (egl_dll_handle == NULL) {
                    path = DEFAULT_OGL_ES_PVR;
                    egl_dll_handle = SDL_LoadObject(path);
                }
            }
        }
#ifdef DEFAULT_OGL
        else {
            path = DEFAULT_OGL;
            egl_dll_handle = SDL_LoadObject(path);
        }
#endif
    }
    _this->egl_data->egl_dll_handle = egl_dll_handle;

    if (egl_dll_handle == NULL) {
        return SDL_SetError("Could not initialize OpenGL / GLES library");
    }

    /* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
    if (egl_path != NULL) {
        dll_handle = SDL_LoadObject(egl_path);
    }
    /* Try loading a EGL symbol, if it does not work try the default library paths */
    if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) {
        if (dll_handle != NULL) {
            SDL_UnloadObject(dll_handle);
        }
        path = SDL_getenv("SDL_VIDEO_EGL_DRIVER");
        if (path == NULL) {
            path = DEFAULT_EGL;
        }
        dll_handle = SDL_LoadObject(path);
        if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) {
            if (dll_handle != NULL) {
                SDL_UnloadObject(dll_handle);
            }
            return SDL_SetError("Could not load EGL library");
        }
        SDL_ClearError();
    }

    _this->egl_data->dll_handle = dll_handle;

    /* Load new function pointers */
    LOAD_FUNC(eglGetDisplay);
    LOAD_FUNC(eglInitialize);
    LOAD_FUNC(eglTerminate);
    LOAD_FUNC(eglGetProcAddress);
    LOAD_FUNC(eglChooseConfig);
    LOAD_FUNC(eglGetConfigAttrib);
    LOAD_FUNC(eglCreateContext);
    LOAD_FUNC(eglDestroyContext);
    LOAD_FUNC(eglCreateWindowSurface);
    LOAD_FUNC(eglDestroySurface);
    LOAD_FUNC(eglMakeCurrent);
    LOAD_FUNC(eglSwapBuffers);
    LOAD_FUNC(eglSwapInterval);
    LOAD_FUNC(eglWaitNative);
    LOAD_FUNC(eglWaitGL);
    LOAD_FUNC(eglBindAPI);
    LOAD_FUNC(eglQueryString);

#if !defined(__WINRT__)
    _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
    if (!_this->egl_data->egl_display) {
        return SDL_SetError("Could not get EGL display");
    }

    if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
        return SDL_SetError("Could not initialize EGL");
    }
#endif

    _this->gl_config.driver_loaded = 1;

    if (path) {
        SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
    } else {
        *_this->gl_config.driver_path = '\0';
    }

    return 0;
}
예제 #24
0
SDL_Renderer *
GL_CreateRenderer(SDL_Window * window, Uint32 flags)
{
    SDL_Renderer *renderer;
    GL_RenderData *data;
    const char *hint;
    GLint value;
    Uint32 window_flags;

    window_flags = SDL_GetWindowFlags(window);
    if (!(window_flags & SDL_WINDOW_OPENGL)) {
        if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
            return NULL;
        }
    }

    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
    if (!renderer) {
        SDL_OutOfMemory();
        return NULL;
    }

    data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
    if (!data) {
        GL_DestroyRenderer(renderer);
        SDL_OutOfMemory();
        return NULL;
    }

    renderer->WindowEvent = GL_WindowEvent;
    renderer->CreateTexture = GL_CreateTexture;
    renderer->UpdateTexture = GL_UpdateTexture;
    renderer->LockTexture = GL_LockTexture;
    renderer->UnlockTexture = GL_UnlockTexture;
    renderer->UpdateViewport = GL_UpdateViewport;
    renderer->RenderClear = GL_RenderClear;
    renderer->RenderDrawPoints = GL_RenderDrawPoints;
    renderer->RenderDrawLines = GL_RenderDrawLines;
    renderer->RenderFillRects = GL_RenderFillRects;
    renderer->RenderCopy = GL_RenderCopy;
    renderer->RenderReadPixels = GL_RenderReadPixels;
    renderer->RenderPresent = GL_RenderPresent;
    renderer->DestroyTexture = GL_DestroyTexture;
    renderer->DestroyRenderer = GL_DestroyRenderer;
    renderer->info = GL_RenderDriver.info;
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
    renderer->driverdata = data;

    data->context = SDL_GL_CreateContext(window);
    if (!data->context) {
        GL_DestroyRenderer(renderer);
        return NULL;
    }
    if (SDL_GL_MakeCurrent(window, data->context) < 0) {
        GL_DestroyRenderer(renderer);
        return NULL;
    }

    if (GL_LoadFunctions(data) < 0) {
        GL_DestroyRenderer(renderer);
        return NULL;
    }

#ifdef __MACOSX__
    /* Enable multi-threaded rendering */
    /* Disabled until Ryan finishes his VBO/PBO code...
       CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
     */
#endif

    if (flags & SDL_RENDERER_PRESENTVSYNC) {
        SDL_GL_SetSwapInterval(1);
    } else {
        SDL_GL_SetSwapInterval(0);
    }
    if (SDL_GL_GetSwapInterval() > 0) {
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
    }

    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
    renderer->info.max_texture_width = value;
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
    renderer->info.max_texture_height = value;

    if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
        || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
        data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
    }
    if (SDL_GL_ExtensionSupported("GL_APPLE_texture_range")) {
        data->glTextureRangeAPPLE =
            (void (*)(GLenum, GLsizei, const GLvoid *))
            SDL_GL_GetProcAddress("glTextureRangeAPPLE");
    }

    /* Check for multitexture support */
    if (SDL_GL_ExtensionSupported("GL_ARB_multitexture")) {
        data->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
        if (data->glActiveTextureARB) {
            data->GL_ARB_multitexture_supported = SDL_TRUE;
            data->glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &data->num_texture_units);
        }
    }

    /* Check for shader support */
    hint = SDL_GetHint(SDL_HINT_RENDER_OPENGL_SHADERS);
    if (!hint || *hint != '0') {
        data->shaders = GL_CreateShaderContext();
    }
    SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
                data->shaders ? "ENABLED" : "DISABLED");

    /* We support YV12 textures using 3 textures and a shader */
    if (data->shaders && data->num_texture_units >= 3) {
        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
    }

    /* Set up parameters for rendering */
    GL_ResetState(renderer);

    return renderer;
}
예제 #25
0
bool SDL2Window::initializeFramework() {

#if defined(ARX_DEBUG) && defined(SDL_HINT_NO_SIGNAL_HANDLERS)
    // SDL 2.0.4+
    SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
#endif

    const char * minimize = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
    if(minimize) {
        if(*minimize == '0') {
            m_minimizeOnFocusLost = AlwaysDisabled;
        } else {
            m_minimizeOnFocusLost = AlwaysEnabled;
        }
    } else {
        m_minimizeOnFocusLost = Enabled;
    }

    arx_assert(s_mainWindow == NULL, "SDL only supports one window"); // TODO it supports multiple windows now!
    arx_assert(m_displayModes.empty());

    const char * headerVersion = ARX_STR(SDL_MAJOR_VERSION) "." ARX_STR(SDL_MINOR_VERSION)
                                 "." ARX_STR(SDL_PATCHLEVEL);
    CrashHandler::setVariable("SDL version (headers)", headerVersion);

#if ARX_PLATFORM != ARX_PLATFORM_WIN32 && ARX_HAVE_SETENV && ARX_HAVE_UNSETENV
    /*
     * We want the X11 WM_CLASS to match the .desktop file and icon name,
     * but SDL does not let us set it directly.
     */
    const char * oldClass = std::getenv("SDL_VIDEO_X11_WMCLASS");
    if(!oldClass) {
        setenv("SDL_VIDEO_X11_WMCLASS", arx_icon_name.c_str(), 1);
    }
    BOOST_SCOPE_EXIT((oldClass)) {
        if(!oldClass) {
            // Don't overrride WM_CLASS for SDL child processes
            unsetenv("SDL_VIDEO_X11_WMCLASS");
        }
    }
    BOOST_SCOPE_EXIT_END
#endif

    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
        LogError << "Failed to initialize SDL: " << SDL_GetError();
        return false;
    }

    SDL_version ver;
    SDL_GetVersion(&ver);
    std::ostringstream runtimeVersion;
    runtimeVersion << int(ver.major) << '.' << int(ver.minor) << '.' << int(ver.patch);
    LogInfo << "Using SDL " << runtimeVersion.str();
    CrashHandler::setVariable("SDL version (runtime)", runtimeVersion.str());
    credits::setLibraryCredits("windowing", "SDL " + runtimeVersion.str());

#ifdef ARX_DEBUG
    // No SDL, this is more annoying than helpful!
    if(ver.major == 2 && ver.minor == 0 && ver.patch < 4) {
        // Earlier versions don't support SDL_HINT_NO_SIGNAL_HANDLERS
#if defined(SIGINT)
        signal(SIGINT, SIG_DFL);
#endif
#if defined(SIGTERM)
        signal(SIGTERM, SIG_DFL);
#endif
    }
#endif

    int ndisplays = SDL_GetNumVideoDisplays();
    for(int display = 0; display < ndisplays; display++) {
        int modes = SDL_GetNumDisplayModes(display);
        for(int i = 0; i < modes; i++) {
            SDL_DisplayMode mode;
            if(SDL_GetDisplayMode(display, i, &mode) >= 0) {
                m_displayModes.push_back(Vec2i(mode.w, mode.h));
            }
        }
    }

    std::sort(m_displayModes.begin(), m_displayModes.end());
    m_displayModes.erase(std::unique(m_displayModes.begin(), m_displayModes.end()),
                         m_displayModes.end());

    s_mainWindow = this;

    SDL_SetEventFilter(eventFilter, NULL);

    SDL_EventState(SDL_WINDOWEVENT, SDL_ENABLE);
    SDL_EventState(SDL_QUIT,        SDL_ENABLE);
    SDL_EventState(SDL_SYSWMEVENT,  SDL_IGNORE);
    SDL_EventState(SDL_USEREVENT,   SDL_IGNORE);

    return true;
}
예제 #26
0
/*
 * Initializes the haptic subsystem.
 */
int
SDL_SYS_HapticInit(void)
{
    const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
    HRESULT ret;
    HINSTANCE instance;

    if (dinput != NULL) {       /* Already open. */
        return SDL_SetError("Haptic: SubSystem already open.");
    }

    /* Clear all the memory. */
    SDL_memset(SDL_hapticlist, 0, sizeof(SDL_hapticlist));

    SDL_numhaptics = 0;

    ret = WIN_CoInitialize();
    if (FAILED(ret)) {
        return DI_SetError("Coinitialize", ret);
    }

    coinitialized = SDL_TRUE;

    ret = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
                           &IID_IDirectInput8, (LPVOID) & dinput);
    if (FAILED(ret)) {
        SDL_SYS_HapticQuit();
        return DI_SetError("CoCreateInstance", ret);
    }

    /* Because we used CoCreateInstance, we need to Initialize it, first. */
    instance = GetModuleHandle(NULL);
    if (instance == NULL) {
        SDL_SYS_HapticQuit();
        return SDL_SetError("GetModuleHandle() failed with error code %d.",
                            GetLastError());
    }
    ret = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
    if (FAILED(ret)) {
        SDL_SYS_HapticQuit();
        return DI_SetError("Initializing DirectInput device", ret);
    }

    /* Look for haptic devices. */
    ret = IDirectInput8_EnumDevices(dinput,
                                   0,
                                   EnumHapticsCallback,
                                   NULL,
                                   DIEDFL_FORCEFEEDBACK |
                                   DIEDFL_ATTACHEDONLY);
    if (FAILED(ret)) {
        SDL_SYS_HapticQuit();
        return DI_SetError("Enumerating DirectInput devices", ret);
    }

    if (!env || SDL_atoi(env)) {
        loaded_xinput = (WIN_LoadXInputDLL() == 0);
    }

    if (loaded_xinput) {
        DWORD i;
        const SDL_bool bIs14OrLater = (SDL_XInputVersion >= ((1<<16)|4));

        for (i = 0; (i < SDL_XINPUT_MAX_DEVICES) && (SDL_numhaptics < MAX_HAPTICS); i++) {
            XINPUT_CAPABILITIES caps;
            if (XINPUTGETCAPABILITIES(i, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) {
                if ((!bIs14OrLater) || (caps.Flags & XINPUT_CAPS_FFB_SUPPORTED)) {
                    /* !!! FIXME: I'm not bothering to query for a real name right now. */
                    char buf[64];
                    SDL_snprintf(buf, sizeof (buf), "XInput Controller #%u", i+1);
                    SDL_hapticlist[SDL_numhaptics].name = SDL_strdup(buf);
                    SDL_hapticlist[SDL_numhaptics].bXInputHaptic = 1;
                    SDL_hapticlist[SDL_numhaptics].userid = (Uint8) i;
                    SDL_numhaptics++;
                }
            }
        }
    }

    return SDL_numhaptics;
}