libretro / RetroArch

Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3.
http://www.libretro.com
GNU General Public License v3.0
10.4k stars 1.84k forks source link

Window size issues on ekeeke's gen_plus_gx, need help for ReroArch devs #6075

Open eugene-s-nesdev opened 6 years ago

eugene-s-nesdev commented 6 years ago

Bug description: https://github.com/ekeeke/Genesis-Plus-GX/issues/205 586x384 must be 586x448 verbose.txt - eeepc laptop (SDL) verbose2.txt - modern intel desktop (GL)

eke eke wrote:

Yes, looking at the log, windows remains stuck to 586x384 (which corresponds to twice the core-reported base height on core reset i.e 192 lines) but do not get updated when SET_GEOMETRY is used by the core to update the video base height (to 224 lines). You should ask retroarch devs if this is something that is expected or was changed and if there is a way to bypass that through retroarch settings because you are the first person reporting this to me and I personally never noticed such thing.

Also, the reason it does not occur with other cores is probably that they don't use dynamic video height change but since Mega Drive system could switch between several video heights during game execution (and all MD games switch from 192 lines output to 224 lines output on startup), we are forced to do so. See also this discussion refering to dynamic video height change in retroarch using libretro API: 693ce4d#diff-7aa14b06c2301aaaddb7e9983d2af13e

When switching between fullscreen and windowed mode or when changing video related core settings, video driver is reseted (by retroarch itself in first case or by the core calling libretro SET_SYSTEM_AV_INFO callback in second cas) which explain why the window size is correct in these cases.

ghost commented 6 years ago

the way the core is layed-out, i think another call to RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO or RETRO_ENVIRONMENT_SET_GEOMETRY is what you need during the 1st loop of retro_run. in any case this issue should be in the cores section as these adjustments are done in core rather than in retroarch.

On Tue, Jan 9, 2018 at 2:36 PM, eugene-s-nesdev notifications@github.com wrote:

ekeeke/Genesis-Plus-GX#205 https://github.com/ekeeke/Genesis-Plus-GX/issues/205

eke eke wrote:

Yes, looking at the log, windows remains stuck to 586x384 (which corresponds to twice the core-reported base height on core reset i.e 192 lines) but do not get updated when SET_GEOMETRY is used by the core to update the video base height (to 224 lines). You should ask retroarch devs if this is something that is expected or was changed and if there is a way to bypass that through retroarch settings because you are the first person reporting this to me and I personally never noticed such thing.

Also, the reason it does not occur with other cores is probably that they don't use dynamic video height change but since Mega Drive system could switch between several video heights during game execution (and all MD games switch from 192 lines output to 224 lines output on startup), we are forced to do so. See also this discussion refering to dynamic video height change in retroarch using libretro API: 693ce4d#diff- 7aa14b06c2301aaaddb7e9983d2af13e

When switching between fullscreen and windowed mode or when changing video related core settings, video driver is reseted (by retroarch itself in first case or by the core calling libretro SET_SYSTEM_AV_INFO callback in second cas) which explain why the window size is correct in these cases.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/libretro/RetroArch/issues/6075, or mute the thread https://github.com/notifications/unsubscribe-auth/AWPDtm2ishFBLsp7QiKSmfQUC2n8QIWcks5tIwjZgaJpZM4RXX8g .

andres-asm commented 6 years ago

Well window is re-created on set-avinfo not on set-geometry, this is perfectly normal and by design, set geometry supposed to be lighter / faster.

You wouldn't RA to be re-creating and tearing down the window on every resolution switch.

I guess we could make it resize the window like other emulators...

inactive123 commented 6 years ago

Set a high enough resolution that could cover all potential resolution changes and then just continue changing the width/height that you feed to video_cb.

Whatever you do, do not abuse SET_SYSTEM_AV_INFO, it is a very, very expensive state switch that would tear down the entire video state and set it up again. You don't want that to happen during runtime.

Read again this part that is described in libretro.h -

' This should only* be used if the core is completely altering the

andres-asm commented 6 years ago

He's not using SET_AV_INFO The problem is the user is using windowed mode and the window size never changes to accommodate the bigger resolution so at some point you get a 224 pixel tall framebuffer inside a 192 pixel tall viewport

The easiest solution would be to have the highest resolution possible as the initial resolution but there would be scaling artifacts unless integer scale is enabled.

Or to resize the window on set_geometry

andres-asm commented 6 years ago

Or you could use a fixed window size under settings / video and integer scale with a core override. I think the frontend provides enough options to solve this but I guess some people may like an automatic resize option.

I've seen other emus like bizhawk change window size as required.

inactive123 commented 6 years ago

Alright then, that helps clear it up.

ghost commented 6 years ago

ok, since both are replying here, ill add my thoughts.

bitmap.viewport.h + (2 * bitmap.viewport.y) is giving a starting height of

  1. so thats the root of the issue. he should start core with a sane base_height of 240 or 224 it thats the one mostly used.

On Wed, Jan 10, 2018 at 1:18 AM, Twinaphex notifications@github.com wrote:

Alright then, that helps clear it up.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/libretro/RetroArch/issues/6075#issuecomment-356352281, or mute the thread https://github.com/notifications/unsubscribe-auth/AWPDtsi-hX3Opwwq6h6SMYzgohpljre6ks5tI59rgaJpZM4RXX8g .

andres-asm commented 6 years ago

It will still scale horribly in windowed mode

ekeeke commented 6 years ago

@retro-wertz: it is only true when top/botttom borders are not emulated (when emulated, base_height is fixed to 240 or 288 regardless of bitmap.viewport.h so reported problem does not occur). Fixing it to 224 is not a proper solution since there are few games that use 240-lines mode so we would end up in the same situation with those games being downscaled in a vertically narrower window.

Anyway, i know the root of the problem, I was only looking for a confirmation that SET_GEOMETRY do not actually reset the window size as I initially thought it did so thanks to @fr500 for having taken the time to understand and confirm the underlying problem.

And there are indeed two ways to solve this (within the core):

1) force base_height to max possible rendered height when initializing (on content load) or reinitializing (on core settings change through SET_AV_INFO) retroarch video driver and keep calling SET_GEOMETRY for dynamic width/height changes to maintain proper aspect ratio.

or

2) Keep base_height set to current rendered height but reinitialize AV_INFO when height is changed during emulation and keep SET_GEOMETRY for width changes.

Drawback of 1) is that for most MD games (and even more for MS and GG games), this will always give you empty bars at the top/bottom of the window, which is something you can already achieve (and more accurately) in current core version by enabling top/bottom borders emulation, so I do not see much benefits with this solution.

Only drawback of 2) is that it forces video driver reinit whenever rendered height is changed but since games don't do this frequently but rather switch video mode (from default 192-line mode to 224 or 240-line mode) once on startup then don't change it anymore, it should be quite an harmless solution.

Now, if it could be possible for retroarch to simply resize the window without reinitializing the video driver, this would be the perfect solution.

andres-asm commented 6 years ago

I think frontend solution is the proper solution to this. Add an option to scale the window on geometry changes.

ghost commented 6 years ago

thats what i said.. start base_height with sane values 224 or 240 or what ever your core mostly starts with(its your design). you cant seem to use bitmap.viewport.h + (2 * bitmap.viewport.y) to give initial height as this is giving out 192 as its starting height, not the height that the framebuffer or the loaded game will be using. there is no problem using that later though.

on a similar note, max height and max width should correspond to max the core supports.. 576 height seems to be a multiple of 192, when i thought that 480(interlace mode) or PAL #scanlines if its emulated was highest or max.

Yes, this will result in black bars when the game uses lower height/width than that. But thats currently how this works(imagine this looking at crt TV). Better that a very small image inside a big frame.

A frontend update to allow retro_get_system_av_info() to run somewhat when retro_run() has already loop at least once. this would allow loaded games to give the correct width/height and start from there. (this is similar as calling SET_AV_INFO, but on a frontend level.)

Anyways the problem is just during that starting dimension. nothing that pressing F and then F again if wants a window mode can deal with.

On Wed, Jan 10, 2018 at 8:15 AM, Andrés notifications@github.com wrote:

I think frontend solution is the proper solution to this.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/libretro/RetroArch/issues/6075#issuecomment-356456806, or mute the thread https://github.com/notifications/unsubscribe-auth/AWPDtk_UabW0cusz4nAQDmqO3x1NpMnhks5tJAETgaJpZM4RXX8g .

ekeeke commented 6 years ago

@retro-wertz : yes, I know all about that, this is pretty much what we have been discussed so far and we already know about the possible solutions so there is not much anything more to debate., although it seems you have some misunderstanding about how genesis plus gx core is working which I can try to clear out if this is any interest for you

thats what i said.. start base_height with sane values 224 or 240

As explained above, the only sane value if the window height must be fixed and cannot be changed dynamically would be the maximal possible height, which is 240 or 288.

or what ever your core mostly starts with(its your design).

The core does not start with 224 or 240 but with 192 because that's the mode used by the console hardware (and the game) on reset then for at least a few frames

you cant seem to use bitmap.viewport.h + (2 * bitmap.viewport.y) to give initial height as this is giving out 192 as its starting height, not the height that the framebuffer or the loaded game will be using.there is no problem using that later though.

There is no way to know when loading a game what the height of framebuffer will be (unless borders are emulated), MS and MD games can switch to any supported height and the consoles could output 192,224 or 240 active lines (which correspond to bitmap.viewport.h) without top/bottom borders (which corresponds to bitmap.viewport.y * 2)

Again, the solution is either to fix window height to max possible value (240 or 288 depending on PAL/NTSC and border emulation) and eventually do not fill the window vertically OR to change it dynamically to fit the video height.

on a similar note, max height and max width should correspond to max the core supports.. 576 height seems to be a multiple of 192, when i thought that 480(interlace mode) or PAL #scanlines if its emulated was highest or max.

576 corresponds to 288 x 2 which is the maximal framebuffer height (case with double-field interlaced mode + PAL mode + top/bottom borders emulated)

But thats currently how this works(imagine this looking at crt TV). Better that a very small image inside a big frame.

I know that but that's what optional top/bottom border emulation is already doing with current core version and some users obviously prefer having that option disabled and a window filled without black bars since those bars were not really visible on CRT TVs because of TV overscan (at least in 224-line NTSC mode).

A frontend update to allow retro_get_system_av_info() to run somewhat when retro_run() has already loop at least once. this would allow loaded games to give the correct width/height and start from there. (this is similar as calling SET_AV_INFO, but on a frontend level.)

This would be exactly the same as calling SET_AV_INFO from the core after the first rendered frame: doing this by default in the frontend instead is not a proper solution since most cores do not require this and for cores that need it, deciding to do this after just one frame is kinda arbitrary (some games might select height mode after 2 or 3 executed frames, who knows?), hence why doing it in the core is the most logical option.

ekeeke commented 6 years ago

@fr500 : I agree, do you mean this is something that is possible for retroarch and that you are planning to implement ? In this case, I guess I could pick first solution for the core: 1) use AV_INFO callbacks to initialize window size to max possible screen size (when game is loaded or when core settings are modified) 2) use SET_GEOMETRY to inform frontend about actual screen size (when game is switching screen modes) 3) let the frontend decides how to deal with actual screen size inside the window.

andres-asm commented 6 years ago

I for one use non-integer scaling with pixelate and a 1920x1080 fixed window when I have to be in windowed mode :p

I could try to implement resizing, the window resizing at some moments may look weird too. Playing in a tiny window seems to be a niche situation. So now I'm backpedaling a bit, I guess the best solution is to initialize in the biggest possible size for the platform and let the front handle scaling yeah.

The user can then use integer scale if he wants perfectly scaled pixels or non-integer if he wants to fill the window area.

But if you prefer this to be done in the frontend I can try to hook up resizing instead :)

kivutar commented 5 years ago

I've encountered an issue certainly related to this while coding Ludo (another libretro frontend).

Genesis Plus GX will behaves like this when loading a Genesis game, the first two frames will be at a resolution, and the latest frames at another resolution, like @ekeeke explained:

2019/02/28 22:57:59 [Core]: Game loaded: /Users/kivutar/uncompressed_roms/Sonic & Knuckles + Sonic The Hedgehog 3 (World).md
{1.5238096714019775 256 192}
{1.5238096714019775 256 192}
{1.3061226606369019 320 224}
{1.3061226606369019 320 224}
{1.3061226606369019 320 224}
{1.3061226606369019 320 224}

This causes a few issue for the frontend implementer.

If I call retro_system_av_info on every frame, I'm able to get the right resolution and ratio at the right time. But doing this breaks another core, FBAlpha.

I've tried to implement RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, but it's not made for small resolution changes like this one, and Genesis Plus GX doesn't call it on the third frame anyway.