1. Anders Ruud
  2. love

Issues

Issue #761 resolved

Retina (aka high DPI) support

Alex Szpakowski
created an issue

SDL 2 just added Retina support to its API. This is something LÖVE definitely needs in my opinion - there's a discussion on the LÖVE forums about it.

Now, support for retina-resolution windows can't just be added internally without any changes to LÖVE's API. This is partly because of the way the OS handles windows on a Retina display.

Window dimensions, and the position of the mouse, are measured in 'points' rather than real pixels. A point could be 2x as big as a real pixel, or 1x, or whatever. Adding "retina support" really means making the graphics view measured in real pixels rather than scaled points, so the graphics can take full advantage of the screen's super high resolution (at the potential cost of framerate.)

However, window sizes are still always requested in terms of points rather than pixels. There's no way I know of to change that.

So the API for creating a retina window might look something like this:

love.window.setMode(800, 600, {highdpi=true})

Which would make a window which reports as 800x600 but its graphics view is really 1600x1200 or something, on a retina display.

SDL handles the difference between the size of the "drawable" and the size of the window by having different functions to get the size of each. It's up to the user of SDL to scale the mouse position (which is always reported in terms of the window size) when doing mouse click hit-tests and such.

This is one option for how LÖVE could handle it: have love.graphics.getWidth and co. report the size of the graphics view, and love.window.getWidth and co. report the size of the window.

Another option is to attempt to eliminate the need for two different sizes: scale the mouse coordinates by graphics_size / window_size internally, and send a love.resize event when a retina resolution window is successfully created (since the reported size will be different from the requested size.)

With the second option there are some potential issues and drawbacks.

  • What happens when the window is moved from a retina display to a non-retina display?

  • Will the absolute position of the window ever be exposed to lovers? If so, I don't think this option would work well with it.

But the first option is not really intuitive enough for my liking. Does anyone have more thoughts or ideas for different options?

Comments (8)

  1. hahawoo

    So, just to help me understand things, let's say I have something like this:

    -- conf.lua
    
    function love.conf(t)
        t.window.width = 700
        t.window.height = 700
    end
    
    -- main.lua
    
    function love.load()
        image = love.graphics.newImage('image.png')
        x = 0
    end
    
    function love.update(dt)
        x = x + dt
    end
    
    function love.mousepressed(mx)
        x = mx
    end
    
    function love.draw()
        love.graphics.draw(image, x)
    end
    

    If the user has a high DPI display, I want the window size and image size to look the same, and "gameplay" to be the same, but I want things to look nicer by using a version of the image which is double the resolution, and make the animation smoother

    Is this the type of thing someone might want to do to make use of a high DPI display? If so, how might I change the code to do this?

  2. Bart van Strien

    I'd like to note that there are reasons to care about pixels instead of points, for instance when choosing fonts. I assume proper behaviour for retina displays is doubling the font size (effectively keeping it the same), and not just having tiny fonts everywhere. Similarly, you'd probably opt to modify your UI. Basically, you probably want to consciously choose for retina. That said, you could, if it doesn't look to bad simply scale 2x when retina mode wasn't explicitly enabled (isn't that the default anyway?)

  3. Alex Szpakowski reporter

    Is this the type of thing someone might want to do to make use of a high DPI display?

    Yes.

    If so, how might I change the code to do this?

    The purpose of this issue is to figure out the nicest way to handle this question, I guess. :)

    That said, you could, if it doesn't look to bad simply scale 2x when retina mode wasn't explicitly enabled (isn't that the default anyway?)

    Yeah, when a GL application doesn't explicitly have retina support, OS X just scales everything into 'points' so the backbuffer is scaled up 2x.

    I definitely think full highdpi support should be opt-in and explicit, I guess the main issue is how best to handle differences in coordinate systems (graphics viewport versus mouse coordinates versus reported window size versus window position, etc.) once it is enabled.

  4. Alex Szpakowski reporter

    Added opt-in support for high-dpi mode in OS X when on a retina display (resolves issue #761).

    Added a ‘highdpi’ boolean flag to t.window/love.window.setMode (defaults to false.) When the window is actually in high-dpi mode on a supported display, the graphics width and height and the mouse position are in pixels, rather than ‘window coordinates’.

    Added love.window.getPixelScale. Returns the scale factor of the window from user-space points to pixels (e.g. it will be 1 normally, and 2 on a retina display in OS X with high-dpi mode enabled.)

    → <<cset d311c1b7a681>>

  5. Alex Gleason

    Doesn't seem to work on my high-dpi Linux laptop. I created a conf.lua file like this:

    function love.conf(t)
        t.window.highdpi = true
    end
    

    but the window still shows up very tiny on my screen.

    screenshot.png

  6. Log in to comment