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 - SDL_SetWindowDisplayMode changes display mode, but not the window size.
Summary: SDL_SetWindowDisplayMode changes display mode, but not the window size.
Status: NEW
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: 2.0.12
Hardware: x86_64 Windows 10
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-11-03 19:04 UTC by Taavi Teemaa
Modified: 2020-11-03 19:04 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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;
}