Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix rendering issue after window resize #1987

Merged
merged 1 commit into from
Oct 10, 2021
Merged

Conversation

ArnaudValensi
Copy link
Contributor

At the initialization CORE.Window.currentFbo.width and CORE.Window.render.width was set to the variable passed from InitWindow which is the virtual width, but the framebuffer size created by glfw is width * dpi scale.

After resize CORE.Window.screen.width was set to the framebuffer size which is the physical width instead of the logical width (on all platform except macos).

@ArnaudValensi ArnaudValensi changed the title Fix rendering issue after window resize #1982 Fix rendering issue after window resize Sep 12, 2021
@ArnaudValensi
Copy link
Contributor Author

Fix issue #1982

src/core.c Outdated
}

// Get current screen height
int GetScreenHeight(void)
{
return CORE.Window.currentFbo.height;
return CORE.Window.screen.height;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we expect to get back the logical size from these functions, so it returns the screen size now.
I've created two more functions (GetRenderWidth/GetRenderHeight) in case we want the physical size.
They all return the same size on macos though, maybe I should add this the comment.

src/core.c Outdated
#endif
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved these logs because we only have the real CORE.Window.render size later on.

src/core.c Outdated
CORE.Window.currentFbo.width = fbWidth;
CORE.Window.currentFbo.height = fbHeight;
CORE.Window.render.width = CORE.Window.currentFbo.width;
CORE.Window.render.height = CORE.Window.currentFbo.height;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These four lines are the most important part. Before this change, CORE.Window.currentFbo and CORE.Window.render.width were filed with the width and height passed in parameter by the user to this function. It was not correct because when creating a window at a specific size, glfw create a framebuffer with the size window size * dpi scale factor (for all desktop platform except macos).

src/core.c Outdated

// Initialize OpenGL context (states and resources)
// NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl
rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this line here so we can call it with the correct values.

src/core.c Outdated

#else
CORE.Window.screen.width = width / windowScaleDPI.x;
CORE.Window.screen.height = height / windowScaleDPI.y;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This callback gives the physical size (framebuffer size), so we need to divide by the dpi scale factor.

@raysan5
Copy link
Owner

raysan5 commented Sep 12, 2021

@ArnaudValensi this PR needs to be reviewed very carefully because it can break other things. Some situations to review:

  • When user do not want to use HighDPI despite the monitor is HighDPI (not enabled FLAG_WINDOW_HIGHDPI)
  • When using BeginTextureMode(RenderTexture), currentFBO is stored for further retrieval (and the size is independent of the DPI because is defined by user)
  • When scaling the Window on HTML5 (EmscriptenResizeCallback)
  • Mouse/Touch input interaction when using HighDPI

@ArnaudValensi
Copy link
Contributor Author

ArnaudValensi commented Sep 13, 2021

Ok, let me create a checklist:

  • When user do not want to use HighDPI despite the monitor is HighDPI (not enabled FLAG_WINDOW_HIGHDPI)
  • When scaling the Window on HTML5 (EmscriptenResizeCallback)
  • Mouse input interaction when using HighDPI on windows/linux/macos
  • Mouse/Touch input interaction when using HighDPI on web
  • When using BeginTextureMode(RenderTexture), currentFBO is stored for further retrieval (and the size is independent of the DPI because is defined by user)
  • Fix scissor
  • Touch input interaction when using HighDPI on mobile

@raysan5
Copy link
Owner

raysan5 commented Sep 13, 2021

@ArnaudValensi Just note that those are only some things that should be reviewed for this change, they could be working ok. I reviewed HighDPI several times in the past and I always found some side case where things do not work as expected.

For reference: #1086, #837, #814, #1931

When possible, I think it's a good idea to give control of the HighDPI to the user (so GetWindowScaleDPI() is provided).

@ArnaudValensi
Copy link
Contributor Author

@raysan5 Ok, thank you for the references.

Maybe these recurring problems/regressions are a good sign that some automated testing could be nice to be implemented. It would make us more confident about the features and the changes we make. I know it is not easy because automated tests often need to be headless, but it is not impossible. We can take a look at how Monogame implemented their tests.
What do you think?

When possible, I think it's a good idea to give control of the HighDPI to the user (so GetWindowScaleDPI() is provided).

Are you suggesting to not take into account the dpi scaling factor in some cases?
Or are you suggesting that you are not very comfortable with this PR? (I would understand)

@raysan5
Copy link
Owner

raysan5 commented Sep 13, 2021

Hi @ArnaudValensi, I'm comfortable with this PR, HighDPI has given problems for some time (specially on macOS) but I'm a bit afraid of the side problems that could arise. HighDPI has been reviewed several times and it seems there is always some side case that breaks or does not work as expected.

For example, if HighDPI is enabled and user creates a (800, 600) Window, actually the internal framebuffer created could be (8001.5, 6001.5) but a novel user expects to work with the size of (800, 600) for the game logic. An advance user could be creating a RenderTexture of (800, 600) and notice that when drawing it, the Window is bigger (x1.5) than the RenderTexture, in those cases I think it's up to the user to manage RenderTexture drawing considering the GetWindowScaleDPI().

@ArnaudValensi
Copy link
Contributor Author

ArnaudValensi commented Sep 14, 2021

@raysan5 I have made the following tests on windows/linux/macos/web:

eF9sbeaXPC.mp4

Everything is fine. The web platform doesn't seem to use hdpi scale factor at all, so I did not modify its code.
I also tried the web on mobile, but I did not try ios or android builds (I don't have an android phone).

I still need to check BeginTextureMode.

All the checks are made using this repository: https://github.com/ArnaudValensi/raylib-highdpi-issue
This raylib libraries corresponding to this PR are directly on the repository, so you can check by doing:
make run on window, linux or macos
make game-web && make run-web on any platform to build the web version. Docker is needed though.

@ArnaudValensi
Copy link
Contributor Author

I've found a missing modification in EndTextureMode 8b1dd7a

I've checked the example textures\textures_mouse_painting.c and it works fine.

LoadRenderTexture(width, height) does not use the dpi scale factor, but like you said, we can use GetWindowScaleDPI() if needed.

I will check the scissor mode.

@ArnaudValensi
Copy link
Contributor Author

I discovered a bug with the scissor mode, it was here before this PR:

xxZDdCzHM5.mp4

I fixed it in 9187180

UTD3LoGiil.mp4

It solves this issue #1931

@ArnaudValensi
Copy link
Contributor Author

ArnaudValensi commented Sep 14, 2021

The julia example works fine with hdpi enabled (#837), I've tried on windows and macos.

My only left concern is that I don't know how the hdpi behave on mobile devices, but maybe it can be the scope of another PR if there is some trouble.

So, we might be good to go.
Also, if there is some other troubles around hdpi in the future, I can be available.

Here a repost of the checklist:

  • When user do not want to use HighDPI despite the monitor is HighDPI (not enabled FLAG_WINDOW_HIGHDPI)
  • When scaling the Window on HTML5 (EmscriptenResizeCallback)
  • Mouse input interaction when using HighDPI on windows/linux/macos
  • Mouse/Touch input interaction when using HighDPI on web
  • When using BeginTextureMode(RenderTexture), currentFBO is stored for further retrieval (and the size is independent of the DPI because is defined by user)
  • Fix scissor [Core] Scissor Mode & High DPI Issue #1931
  • Julia shader test [examples] shaders_julia_set doesn't fill screen on Macbook Retina #837
  • Touch input interaction when using HighDPI on mobile (I'm pretty confident with this)
  • Check resize on mobile (I don't know if it's relevant, but it might be an issue)

@ArnaudValensi
Copy link
Contributor Author

I think for the scissor, we should only multiply by the scale if the hdpi flag is set. I will make the change Wednesday.

@raysan5
Copy link
Owner

raysan5 commented Sep 14, 2021

@ArnaudValensi Very nice! Thank you very much for the review of all the HighDPI involved issues and the detailed report! About resize event on mobile using a NativeActivity (Android), I think it's not relevant but it's important to support the touch input properly.

@ArnaudValensi
Copy link
Contributor Author

@raysan5 I fully fixed the scissor, it now works with and without the high dpi flag.

I wanted to try if this PR works on Android but I was not able to compile raylib due to this issue #1997
I don't have the time to figure out why. But if compilation on Android works again, I can finalize the checks to validate this PR.

@raysan5
Copy link
Owner

raysan5 commented Sep 22, 2021

@ArnaudValensi I'm afraid I renamed this module and now changes can not be merged due to conflicts... Could you open a new PR with those changes for merging? By the way, Android compilation should be working again.

Sorry for the inconvenience.

@ArnaudValensi
Copy link
Contributor Author

Ok, I will try to find the time this week.

@ArnaudValensi
Copy link
Contributor Author

I have rebased this PR.
I still need to check on Android and we should be good.

@raysan5
Copy link
Owner

raysan5 commented Sep 29, 2021

@ArnaudValensi Nice! Thank you very much for reviewing it again! Please, let me know when ready to merge! :D

@ArnaudValensi
Copy link
Contributor Author

I rebased one more time.

I tried to test on android but I didn't manage to. Unfortunately, I don't have more time to allocate to this project. I think this PR works on Android, but not 100% sure. @raysan5, I let you decide what to do.

@raysan5
Copy link
Owner

raysan5 commented Oct 10, 2021

@ArnaudValensi thank you very much for all the time you put on this improvement, I'm merging it and reviewing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants