SFML community forums

Help => Window => Topic started by: espectra on October 08, 2015, 08:55:57 pm

Title: What obvious thing am I screwing up to make opening a fullscreen window fail?
Post by: espectra on October 08, 2015, 08:55:57 pm
Should this test program below succeed at opening a "window" in fullscreen mode with the same attributes as the current desktop mode? (When I write "window", I mean a fullscreen OpenlGL surface separate from the OS'es desktop.

This is on an hp dv4 notebook PC running Windows Vista. GPU is Mobile Intel 4 Series Express chipset. And I'm using SFML 2.3.1

When I run it, it opens a regular window with titlebar on the desktop and the output has red log info:

"Failed to change display mode for fullscreen"

//
// Test opening a fullscreen window on my hp dv4 laptop
//

#include <SFML/Graphics.hpp>

int main()
{
  // Create a fullscreen window
  sf::RenderWindow renderWindow(sf::VideoMode::getFullscreenModes()[0],"Test", sf::Style::Fullscreen);

  // set up a multi-colored quad
  sf::VertexArray quad(sf::Quads, 4);
  quad[0].position = sf::Vector2f(100,100);
  quad[1].position = sf::Vector2f(200,100);
  quad[2].position = sf::Vector2f(200,200);
  quad[3].position = sf::Vector2f(100,200);

  quad[0].color = sf::Color::Blue;
  quad[1].color = sf::Color::Red;
  quad[2].color = sf::Color::Green;
  quad[3].color = sf::Color::White;

  // ********************************************************************************************************************
  // Start the "game" loop
  // ********************************************************************************************************************
  while (renderWindow.isOpen())
  {

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
          renderWindow.close();
    }

    sf::Event event;
    while (renderWindow.pollEvent(event)) {
        // DO NOTHING
    }

    renderWindow.clear(sf::Color::Black);
    renderWindow.draw(quad);
    renderWindow.display();

  }
  return EXIT_SUCCESS;
}
 

I've been able to switch to fullscreen mode in past projects (using LWJGL), so I doubt it's an OpenGL driver problem.

Am I screwing up something obvious?
Title: Re: What obvious thing am I screwing up to make opening a fullscreen window fail?
Post by: Laurent on October 08, 2015, 09:04:51 pm
Quote
with the same attributes as the current desktop mode?
getFullscreenModes()[0] is not guaranteed to be the desktop mode. There's getDesktopMode() for that.

Other than that, I see nothing wrong in your code. I guess we could make the error output more verbose, it doesn't help much.
Title: Re: What obvious thing am I screwing up to make opening a fullscreen window fail?
Post by: espectra on October 08, 2015, 09:26:46 pm
getFullscreenModes()[0] is not guaranteed to be the desktop mode. There's getDesktopMode() for that.

Other than that, I see nothing wrong in your code. I guess we could make the error output more verbose, it doesn't help much.

Thanks!

I changed it to use getDesktopMode() and it gives the same error, unfortunately.

So I added a couple of lines to the SFML source, WindowImplWin32.cpp to print out a bit of info just to verify what options it's passing to the ChangeDisplaySettingsW() call and I get this as error output:

Failed to change display mode for fullscreen
More info:
   width=1280 height=800 BitsPerPel=32 Fields=1c0000
 

which corresponds to the default desktop parameters Windows is using on my PC, and I guess the fields are just bits to tell ChangeDisplaySettingsW() which fields it's passing.

I'm reading the Windows ChangeDisplaySettings() docs (https://msdn.microsoft.com/en-us/library/windows/desktop/dd183411%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396) now to try and get an error code from the call. I'll update when/if I figure something out.

UPDATE: Ok, adding the frequency in the call to ChangeDisplaySettingsW() fixes the problem.

Well, sort of -- the call works and it opens fullscreen, but it's a borderless fullscreen window still on the desktop. Hard to explain, but most gamers and devs will know, i.e. hitting alt-tab takes you to the previous OS window with the game still visible in the background.

Whereas the "separate fullscreen" mode would take you to the previous OS window without the game visibile in the background.

Not a big deal. The main reason I'm looking into all this is that I still can't get vertical sync to work on my PC as I detailed in this post: http://en.sfml-dev.org/forums/index.php?topic=19082.0 (http://en.sfml-dev.org/forums/index.php?topic=19082.0)

I'll keep experimenting with this.

Here's the change I made to WindowImplWin32::switchToFullscreen() BTW

void WindowImplWin32::switchToFullscreen(const VideoMode& mode)
{
    DEVMODE devMode;
    devMode.dmSize       = sizeof(devMode);
    devMode.dmPelsWidth  = mode.width;
    devMode.dmPelsHeight = mode.height;
    devMode.dmBitsPerPel = mode.bitsPerPixel;
    //devMode.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
    // Also pass frequency
    devMode.dmDisplayFrequency = 60;
    devMode.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;

    // Change Display and get error code if any
    long code;
    code = ChangeDisplaySettingsW(&devMode, CDS_FULLSCREEN);

    // Apply fullscreen mode
    if (
        //ChangeDisplaySettingsW(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL
        code != DISP_CHANGE_SUCCESSFUL
        )
    {
        err() << "Failed to change display mode for fullscreen" << std::endl;

        err() << "More info:\n";
        err() << "   width=" << mode.width << " height=" << mode.height <<
                      " BitsPerPel=" << mode.bitsPerPixel << " Fields=" << std::hex <<
                      (devMode.dmFields) << std::endl;

        switch(code) {
        case DISP_CHANGE_SUCCESSFUL:
          err() << "        DISP_CHANGE_SUCCESSFUL\n"; break;
        case DISP_CHANGE_BADDUALVIEW:
          err() << "        DISP_CHANGE_BADDUALVIEW\n"; break;
        case DISP_CHANGE_BADFLAGS:
          err() << "        DISP_CHANGE_BADFLAGS\n"; break;
        case DISP_CHANGE_BADMODE:
          err() << "        DISP_CHANGE_BADMODE\n"; break;
        case DISP_CHANGE_BADPARAM:
          err() << "        DISP_CHANGE_BADPARAM\n"; break;
        case DISP_CHANGE_FAILED:
          err() << "        DISP_CHANGE_FAILED\n"; break;
        case DISP_CHANGE_NOTUPDATED:
          err() << "        DISP_CHANGE_NOTUPDATED\n"; break;
        case DISP_CHANGE_RESTART:
          err() << "        DISP_CHANGE_RESTART\n"; break;
        default:
          err() << "        unrecognized error...\n"; break;
        }

        return;
    }

    // Make the window flags compatible with fullscreen mode
    SetWindowLongW(m_handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
    SetWindowLongW(m_handle, GWL_EXSTYLE, WS_EX_APPWINDOW);

    // Resize the window so that it fits the entire screen
    SetWindowPos(m_handle, HWND_TOP, 0, 0, mode.width, mode.height, SWP_FRAMECHANGED);
    ShowWindow(m_handle, SW_SHOW);

    // Set "this" as the current fullscreen window
    fullscreenWindow = this;
}

 
Title: What obvious thing am I screwing up to make opening a fullscreen window fail?
Post by: eXpl0it3r on October 08, 2015, 10:06:23 pm
If you try an OpenGL based game, can you go into fullscreen mode for the same resolution?

Also go to Intel's website and make sure that your GPU driver is uptodate.
Title: Re: What obvious thing am I screwing up to make opening a fullscreen window fail?
Post by: espectra on October 08, 2015, 10:24:31 pm
If you try an OpenGL based game, can you go into fullscreen mode for the same resolution?

Also go to Intel's website and make sure that your GPU driver is uptodate.

Yes, my previous game was built with LWJGL and works in fullscreen mode at 1280x800 (my PC's default resolution). It also works in both "separate fullscreen" and "borderless window on desktop fullscreen" modes, with the former being the default when changing to fullscreen in LWJGL and the latter being achieved with a "no decoration" flag if I recall correctly.

Anyway, I edited my reply to Laurent to note that I can make the fullscreen mode change succeed if SFML passes the frequency in the ChangeDisplaySettings() Windows call, although it's really just a borderless fullscreen window still "on" the desktop. The only difference between that and a "separate from desktop" fullscreen would be how alt-tab works (no big deal) and whether a separate mode would make vsync start working for me.

I may search through the LWJGL native Windows code to see if they're doing the mode change slightly differently than SFML does it. Seems like it's only a problem for my PC and possibly other Intel graphics notebooks I guess.
Title: Re: What obvious thing am I screwing up to make opening a fullscreen window fail?
Post by: Laurent on October 08, 2015, 11:21:04 pm
https://github.com/LWJGL/lwjgl/blob/master/src/native/windows/display.c#L121

Seems like frequency is optional, so the only true difference is that they correctly ZeroMemory the DEVMODE structure before initializing it.
Title: Re: What obvious thing am I screwing up to make opening a fullscreen window fail?
Post by: binary1248 on October 09, 2015, 01:08:03 am
https://github.com/LWJGL/lwjgl/blob/master/src/native/windows/display.c#L121

Seems like frequency is optional, so the only true difference is that they correctly ZeroMemory the DEVMODE structure before initializing it.
The frequency is set if some sane (non-zero) value is returned in freq. I'm assuming that if no frequency is specified by the user, LWJGL just takes the one returned from the system (through EnumDisplaySettings). Although not documented by Microsoft (we all know how crappy their documentation is sometimes), I can imagine ChangeDisplaySettings doesn't touch settings not passed to it. If changing the screen resolution to something that requires a frequency change doesn't actually change the frequency, stuff might go wrong. We already take extra precautions to make sure we only set valid fullscreen modes on Unix by (re-)enumerating them when setting, we might want to do the same on Windows as well.

Also, zeroing out the struct is unnecessary in this case because we already have to specify which fields actually contain valid information.