123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- /**
- * Copyright (c) 2006-2013 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
- // LOVE
- #include "common/config.h"
- #include "Window.h"
- // SDL
- #include <SDL.h>
- // STL
- #include <iostream>
- namespace love
- {
- namespace window
- {
- namespace sdl
- {
- Window::Window()
- : windowTitle("")
- , created(false)
- {
- if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
- throw love::Exception(SDL_GetError());
- }
- Window::~Window()
- {
- SDL_QuitSubSystem(SDL_INIT_VIDEO);
- }
- Window::_currentMode::_currentMode()
- : width(800)
- , height(600)
- , flags()
- {
- }
- bool Window::setWindow(int width, int height, graphics::Graphics *graphics, WindowFlags *flags)
- {
- if (graphics)
- graphics->unSetMode();
- bool fullscreen = false;
- bool vsync = true;
- int fsaa = 0;
- bool resizable = false;
- bool borderless = false;
- bool centered = true;
- if (flags)
- {
- fullscreen = flags->fullscreen;
- vsync = flags->vsync;
- fsaa = flags->fsaa;
- resizable = flags->resizable;
- borderless = flags->borderless;
- centered = flags->centered;
- }
- bool mouseVisible = getMouseVisible();
- int keyrepeatDelay, keyrepeatInterval;
- SDL_GetKeyRepeat(&keyrepeatDelay, &keyrepeatInterval);
- // We need to restart the subsystem for two reasons:
- // 1) Special case for fullscreen -> windowed. Windows XP did not
- // work well with "normal" display mode change in this case.
- // The application window does leave fullscreen, but the desktop
- // resolution does not revert to the correct one. Restarting the
- // SDL video subsystem does the trick, though.
- // 2) Restart the event system (for whatever reason the event system
- // started and stopped with SDL_INIT_VIDEO, see:
- // http://sdl.beuc.net/sdl.wiki/Introduction_to_Events)
- // because the mouse position will not be able to exceed
- // the previous' video mode window size (i.e. alway
- // love.mouse.getX() < 800 when switching from 800x600 to a
- // higher resolution)
- SDL_QuitSubSystem(SDL_INIT_VIDEO);
- if (centered) // Window should be centered.
- SDL_putenv(const_cast<char *>("SDL_VIDEO_CENTERED=center"));
- else
- SDL_putenv(const_cast<char *>("SDL_VIDEO_CENTERED="));
- if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
- {
- std::cout << "Could not init SDL_VIDEO: " << SDL_GetError() << std::endl;
- return false;
- }
- // Set caption.
- setWindowTitle(windowTitle);
- setMouseVisible(mouseVisible);
- SDL_EnableKeyRepeat(keyrepeatDelay, keyrepeatInterval);
- // Set GL attributes
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vsync ? 1 : 0));
- SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
- // FSAA
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
- Uint32 sdlflags = SDL_OPENGL;
- // Flags
- if (fullscreen)
- sdlflags |= SDL_FULLSCREEN;
- if (resizable)
- sdlflags |= SDL_RESIZABLE;
- if (borderless)
- sdlflags |= SDL_NOFRAME;
- // Have SDL set the video mode.
- SDL_Surface *surface;
- if ((surface = SDL_SetVideoMode(width, height, 32, sdlflags)) == 0)
- {
- bool failed = true;
- if (fsaa > 0)
- {
- // FSAA might have caused the failure, disable it and try again
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
- failed = (surface = SDL_SetVideoMode(width, height, 32, sdlflags)) == 0;
- }
- if (failed)
- {
- std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
- return false;
- }
- }
- created = true;
- const SDL_VideoInfo *videoinfo = SDL_GetVideoInfo();
- width = videoinfo->current_w;
- height = videoinfo->current_h;
- int buffers;
- int samples;
- SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
- SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples);
- // Don't fail because of this, but issue a warning.
- if ((!buffers && fsaa) || (samples != fsaa))
- {
- std::cerr << "Warning, FSAA setting failed! (Result: buffers: " << buffers << ", samples: " << samples << ")" << std::endl;
- fsaa = (buffers > 0) ? samples : 0;
- }
- // Get the actual vsync status
- int real_vsync;
- SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &real_vsync);
- // Set the new display mode as the current display mode.
- currentMode.width = width;
- currentMode.height = height;
- currentMode.flags.fsaa = fsaa;
- currentMode.flags.fullscreen = fullscreen;
- currentMode.flags.vsync = (real_vsync != 0);
- currentMode.flags.resizable = ((surface->flags & SDL_RESIZABLE) != 0);
- currentMode.flags.borderless = ((surface->flags & SDL_NOFRAME) != 0);
- currentMode.flags.centered = centered;
- if (graphics)
- graphics->setMode(width, height);
- return true;
- }
- void Window::getWindow(int &width, int &height, WindowFlags &flags) const
- {
- width = currentMode.width;
- height = currentMode.height;
- flags = currentMode.flags;
- }
- bool Window::checkWindowSize(int width, int height, bool fullscreen) const
- {
- Uint32 sdlflags = fullscreen ? (SDL_OPENGL | SDL_FULLSCREEN) : SDL_OPENGL;
- // Check if mode is supported
- int bpp = SDL_VideoModeOK(width, height, 32, sdlflags);
- return (bpp >= 16);
- }
- typedef Window::WindowSize WindowSize;
- WindowSize *Window::getFullscreenSizes(int &n) const
- {
- SDL_Rect **modes = SDL_ListModes(0, SDL_OPENGL | SDL_FULLSCREEN);
- if (modes == (SDL_Rect **)0 || modes == (SDL_Rect **)-1)
- {
- n = 0;
- return NULL;
- }
- n = 0;
- for (int i = 0; modes[i]; i++)
- n++;
- WindowSize *sizes = new WindowSize[n];
- for (int i = 0; i < n; i++)
- {
- WindowSize w = {modes[i]->w, modes[i]->h};
- sizes[i] = w;
- }
- return sizes;
- }
- int Window::getWidth() const
- {
- return currentMode.width;
- }
- int Window::getHeight() const
- {
- return currentMode.height;
- }
- bool Window::isCreated() const
- {
- return created;
- }
- void Window::setWindowTitle(const std::string &title)
- {
- windowTitle = title;
- SDL_WM_SetCaption(windowTitle.c_str(), 0);
- }
- std::string Window::getWindowTitle() const
- {
- // not a reference
- // because we want this untouched
- // const std::string& might be an option
- return windowTitle;
- }
- bool Window::setIcon(love::image::ImageData *imgd)
- {
- Uint32 rmask, gmask, bmask, amask;
- #ifdef LOVE_BIG_ENDIAN
- rmask = 0xFF000000;
- gmask = 0x00FF0000;
- bmask = 0x0000FF00;
- amask = 0x000000FF;
- #else
- rmask = 0x000000FF;
- gmask = 0x0000FF00;
- bmask = 0x00FF0000;
- amask = 0xFF000000;
- #endif
- int w = static_cast<int>(imgd->getWidth());
- int h = static_cast<int>(imgd->getHeight());
- int pitch = static_cast<int>(imgd->getWidth() * 4);
- SDL_Surface *icon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, 32, pitch, rmask, gmask, bmask, amask);
- SDL_WM_SetIcon(icon, NULL);
- SDL_FreeSurface(icon);
- return true;
- }
- void Window::swapBuffers()
- {
- SDL_GL_SwapBuffers();
- }
- bool Window::hasFocus() const
- {
- return (SDL_GetAppState() & SDL_APPINPUTFOCUS) != 0;
- }
- bool Window::hasMouseFocus() const
- {
- return (SDL_GetAppState() & SDL_APPMOUSEFOCUS) != 0;
- }
- bool Window::isVisible() const
- {
- return (SDL_GetAppState() & SDL_APPACTIVE) != 0;
- }
- void Window::setMouseVisible(bool visible)
- {
- SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE);
- }
- bool Window::getMouseVisible() const
- {
- return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) ? true : false;
- }
- love::window::Window *Window::getSingleton()
- {
- if (!singleton)
- singleton = new Window();
- else
- singleton->retain();
- return singleton;
- }
- const char *Window::getName() const
- {
- return "love.window.sdl";
- }
- } // sdl
- } // window
- } // love
|