Window.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /**
  2. * Copyright (c) 2006-2013 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. // STL
  21. #include <iostream>
  22. // SDL
  23. #include <SDL.h>
  24. // LOVE
  25. #include "common/config.h"
  26. #include "Window.h"
  27. namespace love
  28. {
  29. namespace window
  30. {
  31. namespace sdl
  32. {
  33. Window::Window()
  34. : windowTitle("")
  35. , created(false)
  36. {
  37. // Window should be centered.
  38. SDL_putenv(const_cast<char *>("SDL_VIDEO_CENTERED=center"));
  39. if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
  40. throw love::Exception(SDL_GetError());
  41. }
  42. Window::~Window()
  43. {
  44. SDL_QuitSubSystem(SDL_INIT_VIDEO);
  45. }
  46. Window::_currentMode::_currentMode()
  47. : width(800), height(600), fullscreen(false), vsync(true), fsaa(0)
  48. {
  49. }
  50. bool Window::setWindow(int width, int height, WindowFlags *flags)
  51. {
  52. bool fullscreen = false;
  53. bool vsync = true;
  54. int fsaa = 0;
  55. bool resizable = false;
  56. bool borderless = false;
  57. if (flags)
  58. {
  59. fullscreen = flags->fullscreen;
  60. vsync = flags->vsync;
  61. fsaa = flags->fsaa;
  62. resizable = flags->resizable;
  63. borderless = flags->borderless;
  64. }
  65. bool mouseVisible = getMouseVisible();
  66. int keyrepeatDelay, keyrepeatInterval;
  67. SDL_GetKeyRepeat(&keyrepeatDelay, &keyrepeatInterval);
  68. // We need to restart the subsystem for two reasons:
  69. // 1) Special case for fullscreen -> windowed. Windows XP did not
  70. // work well with "normal" display mode change in this case.
  71. // The application window does leave fullscreen, but the desktop
  72. // resolution does not revert to the correct one. Restarting the
  73. // SDL video subsystem does the trick, though.
  74. // 2) Restart the event system (for whatever reason the event system
  75. // started and stopped with SDL_INIT_VIDEO, see:
  76. // http://sdl.beuc.net/sdl.wiki/Introduction_to_Events)
  77. // because the mouse position will not be able to exceed
  78. // the previous' video mode window size (i.e. alway
  79. // love.mouse.getX() < 800 when switching from 800x600 to a
  80. // higher resolution)
  81. SDL_QuitSubSystem(SDL_INIT_VIDEO);
  82. if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
  83. {
  84. std::cout << "Could not init SDL_VIDEO: " << SDL_GetError() << std::endl;
  85. return false;
  86. }
  87. // Set caption.
  88. setWindowTitle(windowTitle);
  89. setMouseVisible(mouseVisible);
  90. SDL_EnableKeyRepeat(keyrepeatDelay, keyrepeatInterval);
  91. // Set GL attributes
  92. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  93. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  94. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  95. SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
  96. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  97. SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vsync ? 1 : 0));
  98. SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
  99. // FSAA
  100. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
  101. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
  102. Uint32 sdlflags = SDL_OPENGL;
  103. // Flags
  104. if (fullscreen)
  105. sdlflags |= SDL_FULLSCREEN;
  106. if (resizable)
  107. sdlflags |= SDL_RESIZABLE;
  108. if (borderless)
  109. sdlflags |= SDL_NOFRAME;
  110. // Have SDL set the video mode.
  111. SDL_Surface *surface;
  112. if ((surface = SDL_SetVideoMode(width, height, 32, sdlflags)) == 0)
  113. {
  114. bool failed = true;
  115. if (fsaa > 0)
  116. {
  117. // FSAA might have caused the failure, disable it and try again
  118. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
  119. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
  120. failed = SDL_SetVideoMode(width, height, 32, sdlflags) == 0;
  121. }
  122. if (failed)
  123. {
  124. std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
  125. return false;
  126. }
  127. }
  128. created = true;
  129. if (width == 0 || height == 0)
  130. {
  131. const SDL_VideoInfo *videoinfo = SDL_GetVideoInfo();
  132. width = videoinfo->current_w;
  133. height = videoinfo->current_h;
  134. }
  135. int buffers;
  136. int samples;
  137. SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
  138. SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples);
  139. // Don't fail because of this, but issue a warning.
  140. if ((!buffers && fsaa) || (samples != fsaa))
  141. {
  142. std::cerr << "Warning, FSAA setting failed! (Result: buffers: " << buffers << ", samples: " << samples << ")" << std::endl;
  143. fsaa = (buffers > 0) ? samples : 0;
  144. }
  145. // Get the actual vsync status
  146. int real_vsync;
  147. SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &real_vsync);
  148. // Set the new display mode as the current display mode.
  149. currentMode.width = width;
  150. currentMode.height = height;
  151. currentMode.fsaa = fsaa;
  152. currentMode.fullscreen = fullscreen;
  153. currentMode.vsync = (real_vsync != 0);
  154. currentMode.resizable = ((surface->flags & SDL_RESIZABLE) != 0);
  155. currentMode.borderless = ((surface->flags & SDL_NOFRAME) != 0);
  156. return true;
  157. }
  158. void Window::getWindow(int &width, int &height, WindowFlags &flags) const
  159. {
  160. width = currentMode.width;
  161. height = currentMode.height;
  162. flags.fullscreen = currentMode.fullscreen;
  163. flags.vsync = currentMode.vsync;
  164. flags.fsaa = currentMode.fsaa;
  165. flags.resizable = currentMode.resizable;
  166. flags.borderless = currentMode.borderless;
  167. }
  168. bool Window::checkWindowSize(int width, int height, bool fullscreen) const
  169. {
  170. Uint32 sdlflags = fullscreen ? (SDL_OPENGL | SDL_FULLSCREEN) : SDL_OPENGL;
  171. // Check if mode is supported
  172. int bpp = SDL_VideoModeOK(width, height, 32, sdlflags);
  173. return (bpp >= 16);
  174. }
  175. typedef Window::WindowSize WindowSize;
  176. WindowSize **Window::getFullscreenSizes(int &n) const
  177. {
  178. SDL_Rect **modes = SDL_ListModes(0, SDL_OPENGL | SDL_FULLSCREEN);
  179. if (modes == (SDL_Rect **)0 || modes == (SDL_Rect **)-1)
  180. {
  181. n = 0;
  182. return NULL;
  183. }
  184. n = 0;
  185. for (int i = 0; modes[i]; i++)
  186. n++;
  187. WindowSize **sizes = new WindowSize*[n];
  188. for (int i = 0; i < n; i++)
  189. {
  190. sizes[i] = new WindowSize;
  191. sizes[i]->width = modes[i]->w;
  192. sizes[i]->height = modes[i]->h;
  193. }
  194. return sizes;
  195. }
  196. int Window::getWidth() const
  197. {
  198. return currentMode.width;
  199. }
  200. int Window::getHeight() const
  201. {
  202. return currentMode.height;
  203. }
  204. bool Window::isCreated() const
  205. {
  206. return created;
  207. }
  208. void Window::setWindowTitle(std::string &title)
  209. {
  210. windowTitle = title;
  211. SDL_WM_SetCaption(windowTitle.c_str(), 0);
  212. }
  213. std::string Window::getWindowTitle() const
  214. {
  215. // not a reference
  216. // because we want this untouched
  217. // const std::string& might be an option
  218. return windowTitle;
  219. }
  220. bool Window::setIcon(love::image::ImageData *imgd)
  221. {
  222. Uint32 rmask, gmask, bmask, amask;
  223. #ifdef LOVE_BIG_ENDIAN
  224. rmask = 0xFF000000;
  225. gmask = 0x00FF0000;
  226. bmask = 0x0000FF00;
  227. amask = 0x000000FF;
  228. #else
  229. rmask = 0x000000FF;
  230. gmask = 0x0000FF00;
  231. bmask = 0x00FF0000;
  232. amask = 0xFF000000;
  233. #endif
  234. int w = static_cast<int>(imgd->getWidth());
  235. int h = static_cast<int>(imgd->getHeight());
  236. int pitch = static_cast<int>(imgd->getWidth() * 4);
  237. SDL_Surface *icon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, 32, pitch, rmask, gmask, bmask, amask);
  238. SDL_WM_SetIcon(icon, NULL);
  239. SDL_FreeSurface(icon);
  240. return true;
  241. }
  242. void Window::swapBuffers()
  243. {
  244. SDL_GL_SwapBuffers();
  245. }
  246. bool Window::hasFocus() const
  247. {
  248. return (SDL_GetAppState() & SDL_APPINPUTFOCUS) != 0;
  249. }
  250. void Window::setMouseVisible(bool visible)
  251. {
  252. SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE);
  253. }
  254. bool Window::getMouseVisible() const
  255. {
  256. return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) ? true : false;
  257. }
  258. love::window::Window *Window::getSingleton()
  259. {
  260. if (!singleton)
  261. singleton = new Window();
  262. else
  263. singleton->retain();
  264. return singleton;
  265. }
  266. const char *Window::getName() const
  267. {
  268. return "love.window.sdl";
  269. }
  270. } // sdl
  271. } // window
  272. } // love