SDLVisibleSurfaceBase.cc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include "SDLVisibleSurfaceBase.hh"
  2. #include "InitException.hh"
  3. #include "Icon.hh"
  4. #include "Display.hh"
  5. #include "RenderSettings.hh"
  6. #include "PNG.hh"
  7. #include "FileContext.hh"
  8. #include "CliComm.hh"
  9. #include "build-info.hh"
  10. #include <cassert>
  11. namespace openmsx {
  12. int SDLVisibleSurfaceBase::windowPosX = SDL_WINDOWPOS_UNDEFINED;
  13. int SDLVisibleSurfaceBase::windowPosY = SDL_WINDOWPOS_UNDEFINED;
  14. SDLVisibleSurfaceBase::~SDLVisibleSurfaceBase()
  15. {
  16. // store last known position for when we recreate it
  17. // the window gets recreated when changing renderers, for instance.
  18. // Do not store if we're fullscreen, the location is the top-left
  19. if ((SDL_GetWindowFlags(window.get()) & SDL_WINDOW_FULLSCREEN) == 0) {
  20. SDL_GetWindowPosition(window.get(), &windowPosX, &windowPosY);
  21. }
  22. }
  23. // TODO: The video subsystem is not de-inited on errors.
  24. // While it would be consistent to do so, doing it in this class is
  25. // not ideal since the init doesn't happen here.
  26. void SDLVisibleSurfaceBase::createSurface(int width, int height, unsigned flags)
  27. {
  28. if (getDisplay().getRenderSettings().getFullScreen()) {
  29. flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
  30. }
  31. flags |= SDL_WINDOW_ALLOW_HIGHDPI;
  32. assert(!window);
  33. window.reset(SDL_CreateWindow(
  34. getDisplay().getWindowTitle().c_str(),
  35. windowPosX, windowPosY,
  36. width, height,
  37. flags));
  38. if (!window) {
  39. std::string err = SDL_GetError();
  40. throw InitException("Could not create window: ", err);
  41. }
  42. updateWindowTitle();
  43. // prefer linear filtering (instead of nearest neighbour)
  44. SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
  45. // set icon
  46. if (OPENMSX_SET_WINDOW_ICON) {
  47. SDLSurfacePtr iconSurf;
  48. // always use 32x32 icon on Windows, for some reason you get badly scaled icons there
  49. #ifndef _WIN32
  50. try {
  51. iconSurf = PNG::load(preferSystemFileContext().resolve("icons/openMSX-logo-256.png"), true);
  52. } catch (MSXException& e) {
  53. getCliComm().printWarning(
  54. "Falling back to built in 32x32 icon, because failed to load icon: ",
  55. e.getMessage());
  56. #endif
  57. iconSurf.reset(SDL_CreateRGBSurfaceFrom(
  58. const_cast<char*>(openMSX_icon.pixel_data),
  59. openMSX_icon.width, openMSX_icon.height,
  60. openMSX_icon.bytes_per_pixel * 8,
  61. openMSX_icon.bytes_per_pixel * openMSX_icon.width,
  62. OPENMSX_BIGENDIAN ? 0xFF000000 : 0x000000FF,
  63. OPENMSX_BIGENDIAN ? 0x00FF0000 : 0x0000FF00,
  64. OPENMSX_BIGENDIAN ? 0x0000FF00 : 0x00FF0000,
  65. OPENMSX_BIGENDIAN ? 0x000000FF : 0xFF000000));
  66. #ifndef _WIN32
  67. }
  68. #endif
  69. SDL_SetColorKey(iconSurf.get(), SDL_TRUE, 0);
  70. SDL_SetWindowIcon(window.get(), iconSurf.get());
  71. }
  72. }
  73. void SDLVisibleSurfaceBase::updateWindowTitle()
  74. {
  75. assert(window);
  76. SDL_SetWindowTitle(window.get(), getDisplay().getWindowTitle().c_str());
  77. }
  78. bool SDLVisibleSurfaceBase::setFullScreen(bool fullscreen)
  79. {
  80. auto flags = SDL_GetWindowFlags(window.get());
  81. // Note: SDL_WINDOW_FULLSCREEN_DESKTOP also has the SDL_WINDOW_FULLSCREEN
  82. // bit set.
  83. bool currentState = (flags & SDL_WINDOW_FULLSCREEN) != 0;
  84. if (currentState == fullscreen) {
  85. // already wanted stated
  86. return true;
  87. }
  88. // in win32, toggling full screen requires opening a new SDL screen
  89. // in Linux calling the SDL_WM_ToggleFullScreen usually works fine
  90. // We now always create a new screen to make the code on both OSes
  91. // more similar (we had a windows-only bug because of this difference)
  92. return false;
  93. }
  94. } // namespace openmsx