Tell me more ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

One of the things I wanted to be sure to do was allow people to play my game at different resolutions and be able to switch between fullscreen, windowed, and borderless. Borderless is a big one for a lot of people as well as myself. I have noticed even since early in my project it would stutter a little bit in borderless windowed mode. It's not terrible but choppy gameplay can get slightly annoying when I want to it to be as smooth as it is in fullscreen. I know other games have always had some issue with being borderless. I just figured since my game isn't that intensive I shouldn't see much of problem.

I am using David Amador's "XNA 2D Independent Resolution Rendering" at http://www.david-amador.com/2010/03/xna-2d-independent-resolution-rendering/. It is as follows:

static class Resolution
{
    static private GraphicsDeviceManager _Device = null;

    static private int _Width = 800;
    static private int _Height = 600;
    static private int _VWidth = 1024;
    static private int _VHeight = 768;
    static private Matrix _ScaleMatrix;
    static private bool _FullScreen = false;
    static private bool _dirtyMatrix = true;

    static public void Init(ref GraphicsDeviceManager device)
    {
        _Width = device.PreferredBackBufferWidth;
        _Height = device.PreferredBackBufferHeight;
        _Device = device;
        _dirtyMatrix = true;
        ApplyResolutionSettings();
    }


    static public Matrix getTransformationMatrix()
    {
        if (_dirtyMatrix) RecreateScaleMatrix();

        return _ScaleMatrix;
    }

    static public void SetResolution(int Width, int Height, bool FullScreen)
    {
        _Width = Width;
        _Height = Height;

        _FullScreen = FullScreen;

        ApplyResolutionSettings();
    }

    static public void SetVirtualResolution(int Width, int Height)
    {
        _VWidth = Width;
        _VHeight = Height;

        _dirtyMatrix = true;
    }

    static private void ApplyResolutionSettings()
    {

#if XBOX360
       _FullScreen = true;
#endif

        // If we aren't using a full screen mode, the height and width of the window can
        // be set to anything equal to or smaller than the actual screen size.
        if (_FullScreen == false)
        {
            if ((_Width <= GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width)
                && (_Height <= GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height))
            {
                _Device.PreferredBackBufferWidth = _Width;
                _Device.PreferredBackBufferHeight = _Height;
                _Device.IsFullScreen = _FullScreen;
                _Device.ApplyChanges();
            }
        }
        else
        {
            // If we are using full screen mode, we should check to make sure that the display
            // adapter can handle the video mode we are trying to set.  To do this, we will
            // iterate through the display modes supported by the adapter and check them against
            // the mode we want to set.
            foreach (DisplayMode dm in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
            {
                // Check the width and height of each mode against the passed values
                if ((dm.Width == _Width) && (dm.Height == _Height))
                {
                    // The mode is supported, so set the buffer formats, apply changes and return
                    _Device.PreferredBackBufferWidth = _Width;
                    _Device.PreferredBackBufferHeight = _Height;
                    _Device.IsFullScreen = _FullScreen;
                    _Device.ApplyChanges();
                }
            }
        }

        _dirtyMatrix = true;

        _Width = _Device.PreferredBackBufferWidth;
        _Height = _Device.PreferredBackBufferHeight;
    }

    /// <summary>
    /// Sets the device to use the draw pump
    /// Sets correct aspect ratio
    /// </summary>
    static public void BeginDraw()
    {
        // Start by reseting viewport to (0,0,1,1)
        FullViewport();
        // Clear to Black
        _Device.GraphicsDevice.Clear(Color.Black);
        // Calculate Proper Viewport according to Aspect Ratio
        ResetViewport();
        // and clear that
        // This way we are gonna have black bars if aspect ratio requires it and
        // the clear color on the rest
        _Device.GraphicsDevice.Clear(Color.CornflowerBlue);
    }

    static private void RecreateScaleMatrix()
    {
        _dirtyMatrix = false;
        _ScaleMatrix = Matrix.CreateScale(
                       (float)_Device.GraphicsDevice.Viewport.Width / _VWidth,
                       (float)_Device.GraphicsDevice.Viewport.Width / _VWidth,
                       1f);
    }


    static public void FullViewport()
    {
        Viewport vp = new Viewport();
        vp.X = vp.Y = 0;
        vp.Width = _Width;
        vp.Height = _Height;
        _Device.GraphicsDevice.Viewport = vp;
    }

    /// <summary>
    /// Get virtual Mode Aspect Ratio
    /// </summary>
    /// <returns>aspect ratio</returns>
    static public float getVirtualAspectRatio()
    {
        return (float)_VWidth / (float)_VHeight;
    }

    static public void ResetViewport()
    {
        float targetAspectRatio = getVirtualAspectRatio();
        // figure out the largest area that fits in this resolution at the desired aspect ratio
        int width = _Device.PreferredBackBufferWidth;
        int height = (int)(width / targetAspectRatio + .5f);
        bool changed = false;

        if (height > _Device.PreferredBackBufferHeight)
        {
            height = _Device.PreferredBackBufferHeight;
            // PillarBox
            width = (int)(height * targetAspectRatio + .5f);
            changed = true;
        }

        // set up the new viewport centered in the backbuffer
        Viewport viewport = new Viewport();

        viewport.X = (_Device.PreferredBackBufferWidth / 2) - (width / 2);
        viewport.Y = (_Device.PreferredBackBufferHeight / 2) - (height / 2);
        viewport.Width = width;
        viewport.Height = height;
        viewport.MinDepth = 0;
        viewport.MaxDepth = 1;

        if (changed)
        {
            _dirtyMatrix = true;
        }

        _Device.GraphicsDevice.Viewport = viewport;
    }
}

I use the following to set up the window's initial parameters:

Resolution.Init(ref graphics);
Resolution.SetVirtualResolution(GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width, GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height);
Resolution.SetResolution(GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width, GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height, false);

I can toggle between false and true to set fullscreen or windowed. The trouble comes next when I create my gameplay screen and use the following to create a borderless window:

Form gameForm = (Form)Form.FromHandle(curGame.control.Handle);
gameForm.FormBorderStyle = FormBorderStyle.None;

If I have it set to fullscreen through Resolution then this borderless code doesn't seem to do anything at all. If I have it set to windowed it does work as expected and creates a borderless window. The only problem is that strange lag/choppy behavior. In full screen it doesn't lag one bit so I'm wondering if there's some issue with how Resolution and the borderless code work. Is how I'm doing a borderless window correct? Am I just going to have to deal with a little bit of stuttering in that mode? I'd appreciate any insight!

share|improve this question
2  
In borderless windowed mode it is drawing/updating the desktop and all of the open applications. Because of this your computer will be under heavier load than going full screen. So there is no way to avoid or even mitigate a performance hit. – ClassicThunder Jan 14 at 14:28
That makes sense, just wanted to be sure I was doing it alright and there wasn't something I could be doing better. Thanks for your input. – Ted Jan 14 at 20:25

Know someone who can answer? Share a link to this question via email, Google+, Twitter, or Facebook.

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.