We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5338

Summary: SDL_SetWindowDisplayMode changes display mode, but not the window size.
Product: SDL Reporter: Taavi Teemaa <taavi.teemaa>
Component: videoAssignee: Sam Lantinga <slouken>
Status: NEW --- QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2    
Version: 2.0.12   
Hardware: x86_64   
OS: Windows 10   

Description Taavi Teemaa 2020-11-03 19:04:45 UTC
The documentation says:

"Fullscreen windows automatically match the size of the display mode, and you should use SDL_SetWindowDisplayMode() to change their size."

Example code at the bottom.

But when I call the function I see that the actual display mode is changed, but the window size or OpenGL backbuffer size doesn't change, UNTIL I go to the desktop and open the window again. SDL_WINDOWEVENT_SIZE_CHANGED event is also received only after this.

I use SDL only for creating window and input handling. I first noticed the problem when implementing resolution change to my game and when I changed to a resolution with a different height. I got a black bar on top. I checked with RenderDoc and saw that the backbuffer was still actually the same and I was drawing to the bottom left corner of it with the new viewport and because the actual screen resolution was changed it only showed the top left of the backbuffer.

I managed to recreate the problem with a small application. You can't see anything visually in this, because the clear clears the whole backbuffer, but the std::cout prints the current resolution of the window. And it only updates to the new resolution when I go to desktop and reopen the window.

Workaround is that I call SDL_SetWindowSize() right after the SDL_SetWindowDisplayMode(). Then the size changes immediately.


#include "SDL.h"

#include <iostream>
#include <vector>

int main(int argc, char* argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);

    int current_display_mode = 0;
    std::vector<SDL_DisplayMode> display_modes;
    // Fetch display modes with desktop pixel format and refresh rate
    {
        SDL_DisplayMode desktop_display_mode;
        SDL_GetDesktopDisplayMode(0, &desktop_display_mode);
        auto used_pixel_format = desktop_display_mode.format;
        auto used_refresh_rate = desktop_display_mode.refresh_rate;

        SDL_DisplayMode display_mode;
        auto num_display_modes = SDL_GetNumDisplayModes(0);
        for (auto i = 0; i < num_display_modes; ++i)
        {
            SDL_GetDisplayMode(0, i, &display_mode);

            if (display_mode.format != used_pixel_format)
                continue;
            if (display_mode.refresh_rate != used_refresh_rate)
                continue;

            display_modes.push_back(display_mode);
        }
    }

    SDL_Window* window = SDL_CreateWindow(
        "title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        display_modes[current_display_mode].w,
        display_modes[current_display_mode].h, SDL_WINDOW_FULLSCREEN);

    SDL_SetWindowDisplayMode(window, &display_modes[current_display_mode]);

    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);

    bool running = true;
    while (running)
    {
        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
                running = false;

            if (event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_D)
            {
                current_display_mode =
                    (current_display_mode + 1) % display_modes.size();
                auto& mode = display_modes[current_display_mode];
                SDL_SetWindowDisplayMode(window, &mode);
            }

            if (event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_ESCAPE)
                running = false;
        }

        if (!running)
            break;

        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        SDL_RenderClear(renderer);
        SDL_RenderPresent(renderer);

        SDL_Delay(100);

        int dims[2];
        SDL_GetWindowSize(window, dims, dims + 1);
        std::cout << dims[0] << " " << dims[1] << std::endl;
    }

    SDL_Quit();

    return 0;
}