Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: What obvious thing am I screwing up to make opening a fullscreen window fail?  (Read 2951 times)

0 Members and 1 Guest are viewing this topic.

espectra

  • Newbie
  • *
  • Posts: 9
    • View Profile
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?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
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.
Laurent Gomila - SFML developer

espectra

  • Newbie
  • *
  • Posts: 9
    • View Profile
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 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

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;
}

 
« Last Edit: October 08, 2015, 10:13:22 pm by espectra »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10801
    • View Profile
    • development blog
    • Email
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.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

espectra

  • Newbie
  • *
  • Posts: 9
    • View Profile
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.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
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.
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
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.
« Last Edit: October 09, 2015, 01:10:02 am by binary1248 »
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).