[SOLVED] Screen not handled

Some more information will be helpful.

Are you running your game in hardware full screen? Does the player have multiple monitors connected? Do you set the window position manually?
Is this a DesktopGL or DX project?

The game starts in fullscreen but i don’t know if it is hardware fullscreen. How can i tell?

Only one monitor is connected.

DesktopGL.

Here is the way i handle fullscreen :

Are you using MonoGame 3.6 or newer?

Hard full screen (or real full screen) is the default, so that is what you are using. If you are using MG 3.6 or newer his is likely an issue on the side of the player, because MonoGame uses SDL2 for windowing since 3.6 which is a pretty robust and widely used library.
That said, you can probably help him work around it by providing the option to set soft full screen instead of hard full screen. Soft full screen is a fake kind of fullscreen that just makes the window of your game the size of the desktop and removes the window border. It does not allow you to mode switch (that is, switch the desktop resolution) like in hard full screen. Soft full screen is less complex, so I think it is a lot more likely to work correctly.

May also be a resolution not supported by the screen. On darty there is only the max resolution not all of the supported ones

I am using 3.6.
And screen resolution is 1920*1080.

Ok to make the edit to use soft full screen but i don’t know how we do it.
Is it simply done by replacing :
screen.IsFullScreen = true;
by
screen.IsBorderless = true;
?

Oh sorry, forgot to mention that. No, you should set GraphicsDeviceManager.HardwareModeSwitch to false then set full screen as usual.

That’s not working as usual on computer/screen where it was working as expected.
Now the game that i was streching to the screen (from 1366768 default size to screen resolution) is not stretched anymore but displayed in top left corner at a 1366768 size and the rest of the screen is filled in black.
Also, i cannot do any screenshot of this. It captures what’s under the game instead (like Visual Studio for example)…

In soft full screen the display mode is not switched, like I said earlier, so your backbuffer size is the actual desktop resolution.
It seems your code expected that a 1366x768 resolution is always supported by the display. That might actually be part of the issue for your player. You would get the same issue you have now with hard full screen if the display does not support that resolution.
It’s good practice to render your game to a RenderTarget first and then scale it as appropriate and optionally use pillar- or letterboxing so the game is not stretched. MonoGame.Extended has some classes that make this easy.

How are you taking a screenshot? On Windows, try using the Snipping Tool.

In fact, 1366x768 is the maimum size in which is drawn a sprite in the game. So when the game is displayed on a wider resolution it will be stretched.

About different resolutions, if that’s what you were asking, i ran a test with a 1400x900 resolution and it’s working well.

Never did/see that.
I don’t want letter boxing.

About the screenshot, i tried your solution, same result.

If you want it to stretch, it’s the same. You need to render to a RenderTarget first, then to the backbuffer. There’s no other way in soft full screen.

I don’t know how to resolve the screenshot issue :confused:

The original issue is because that user’s monitor does not support the screen resolution you are trying to set. This is why many games and even Windows will display a dialog box asking if the resolution change worked, with a countdown timer that reverts to the previous setting if the user does not click “Ok”.

Some games will also provide the graphics options in a standard Windows dialog before the game itself starts. This allows the user to select a graphics mode that they know their card and monitor support.

It is also common practice to start up for the first time in either the user’s desktop resolution (because you know that works) or a lower and more standard resolution, such as 800x600 or 1024x768. These are very likely to be supported, and are more likely to be supported than 1366x768.

For the screenshot issue, how are you trying to take the screenshot? Alt+PrtScn or the Snipping Tool? What mode is the Snipping Tool in? Window, full-screen?

Looking at your ScreenAdaptor code,

            screen_w = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
            screen_h = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;

            scale_factor_w = 1366 / screen_w;
            scale_factor_h = 768 / screen_h;

            scaled_w = screen_w * scale_factor_w;
            scaled_h = screen_h * scale_factor_h;

            screen.PreferredBackBufferWidth = (int)scaled_w;
            screen.PreferredBackBufferHeight = (int)scaled_h;

is a long way of saying

            screen.PreferredBackBufferWidth = 1366;
            screen.PreferredBackBufferHeight = 768;

because that is what it comes out to, no matter the user’s display resolution.

1 Like

If it is an unsupported resolution as I suggested, you can check the supported ones like this:

Console.WriteLine("\n Supported display modes:");
foreach(DisplayMode displayMode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
{
Console.WriteLine("\t {0}", displayMode.ToString());
}

Adapt it to write to a file to ease your debug, or to suggest a supported resolution to the user.

That’s what i am working on @KonajuGames and @Alkher. A gamedev mate suggested it also.

I didn’t tried RenderTarget solution yet from @Jjagg because it sounds more like a change that could have potential repercussions on the way i already handle graphics in the game. Because i know nothing about RenderTarget.
However, if GraphicsAdapter.DefaultAdapter.SupportedDisplayModes solution i’m working on don’t work correctly, i will try to use RenderTarget2D.

Simply put, RenderTargets are “just” a simple buffer where you tell the app to draw (ie: offscreen), then you do with this screen what you want: apply effects+shaders, scale/stretch, draw/show it. :wink:

If needed:
https://msdn.microsoft.com/en-us/library/ff434402.aspx
http://rbwhitaker.wikidot.com/render-to-texture

This is not a case of trying to use an unsupported video resolution. The GPU supports the video resolution, but the display device does not. The GPU and game keep going along quite happily because to them everything is fine.

If you consider a simple Draw to be

public override void Draw(GameTime gameTime)
{
    graphicsDevice.Clear();
    spriteBatch.Begin();
    // Do drawing
    spriteBatch.End();
}

the simplest way to adapt to using a RenderTarget2D is

public override void Initialize()
{
    base.Initialize();
    // Create the render target at the desired resolution
    rt = new RenderTarget2D(graphicsDevice, 1366, 768, ...);
}

public override void Draw(GameTime gameTime)
{
    // Render the scene to the render target
    graphicsDevice.SetRenderTarget(rt);

    // Same rendering code as before
    graphicsDevice.Clear();
    spriteBatch.Begin();
    // Do drawing
    spriteBatch.End();

    // Redirect rendering to the back buffer
    graphicsDevice.SetRenderTarget(null);
    spriteBatch.Begin();
    // Draw rt to fill viewport of the GraphicsDevice
    spriteBatch.Draw(rt, ...);
    spriteBatch.End();
}

Oooook! Thanks everyone, it’s finally working :slight_smile:

So here is my code : now

ScreenAdapter.cs : https://gist.github.com/anonymous/eb3eb4f14e9aeb16ffe5eb04c5575bc4

    class ScreenAdapter
            {
                static public Rectangle safe_bounds;
                static public Rectangle safe_ui;
      
                static public float supported_w;
                static public float supported_h;

                static public bool fullscreen = true;

                static public float offset;

                public ScreenAdapter(GraphicsDeviceManager screen)
                {
                    screen.HardwareModeSwitch = false;

                    supported_w = 1366;
                    supported_h = 768;

                    if (fullscreen == true)
                    {
                        screen.PreferredBackBufferWidth = (int)supported_w;
                        screen.PreferredBackBufferHeight = (int)supported_h;

                        screen.IsFullScreen = true;
                    }

                    if (fullscreen == false)
                    {
                        screen.PreferredBackBufferWidth = (int)supported_w;
                        screen.PreferredBackBufferHeight = (int)supported_h;

                        screen.IsFullScreen = false;
                    }

                    safe_bounds = new Rectangle(0, 0, screen.PreferredBackBufferWidth, screen.PreferredBackBufferHeight);

                    float marge_factor = (float)supported_w / 30;
                    float marge = (float)screen.PreferredBackBufferWidth / marge_factor;
                    marge = (int)marge;

                    float offset_factor = (float)supported_w / 400;

                    offset = screen.PreferredBackBufferWidth / offset_factor;
                    offset = (int)offset;

                    safe_ui = new Rectangle(safe_bounds.X + 15, safe_bounds.Y + 15, safe_bounds.Width - (int)marge, safe_bounds.Height - (int)marge);

                    screen.ApplyChanges();
                }
            }
        }

The draw:

protected override void Draw(GameTime gameTime)
        {
            DrawSceneToTexture(renderTarget);

            spriteBatch.Begin();

            if (ScreenAdapter.fullscreen == false)
            {
                spriteBatch.Draw(renderTarget, new Rectangle(0, 0, (int)ScreenAdapter.supported_w, (int)ScreenAdapter.supported_h), Color.White);
            }
            else
            {
                spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width, GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height), Color.White);
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }

Else I did as Konaju said.

I am very thankful because this issue appeared suddenly yesterday and my game will be released tomorrow :smiley:

1 Like

This is only the resolution of the gpu, not the screen? Ain’t there a way to get them?
Apart from changing it and waiting for the user to confirm or revert to the previous one working

The physical display can only try to show what the GPU sends to it. It doesn’t report back if it cannot display it. We set the resolution on the GPU. The GPU generates the video signal from that back buffer at the specified width, height and refresh rate and sends it to the physical display.

I thought there was a way, with nowadays screens running with android or other os, to get the resolutions from the screens too (through the GPU’s cable for ex, a frame sending the data encoded in a texture, or whatever signal).