Closed mithrendal closed 4 years ago
I implemented an ALT+ENTER fullscreen toggle.
I got the the manual pixel surface render method to work π...
The texture render method gives me still riddles ...
it somehow only shows the left bottom part of the screen buffer....
With try and error I set the coordinates in fullscreen xOff=-17, yOff=198, wOff=158, hOff=96 then it looks already quite acceptable, but I can not interprete the numbers yet ...
with this offset, the canvas in window mode (when you leave fullscreen) looks like this
int emu_width = NTSC_PIXELS;
int emu_height = PAL_RASTERLINES;
void draw_one_frame_into_SDL2_Texture(void *thisC64) {
C64 *c64 = (C64 *)thisC64;
c64->executeOneFrame();
void *texture = c64->vic.screenBuffer();
int surface_width = window_surface->w;
int surface_height = window_surface->h;
SDL_RenderClear(renderer);
SDL_UpdateTexture(screen_texture, NULL, texture, emu_width * 4);
SDL_Rect SrcR;
SDL_Rect DestR;
SrcR.x = 0;
SrcR.y = 0;
SrcR.w = emu_width;
SrcR.h = emu_height;
//pos: x=-17, y=198, w=158, h=96
DestR.x = xOff;
DestR.y = yOff;
DestR.w = wOff;
DestR.h = hOff;
SDL_RenderCopy(renderer, screen_texture, &SrcR, &DestR);
SDL_RenderPresent(renderer);
}
Hmmm, strange.
I got the the manual pixel surface render method to work π...
Can you paste the code?
Can you paste the code?
in the SDL event loop I added the fullscreen toggle code
case SDL_KEYDOWN:
if ( event->key.keysym.sym == SDLK_RETURN &&
event->key.keysym.mod & KMOD_ALT )
{
if(!bFullscreen)
{
bFullscreen=true;
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
}
else
{
bFullscreen=false;
SDL_SetWindowFullscreen(window, 0);
SDL_RestoreWindow(window);
SDL_SetWindowSize(window, emu_width, emu_height);
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
}
}
which effectively switches the resolution to fullscreen when ALT+ENTER is pressed
Size changed: 1440, 900
and back to the smaller canvas when ALT+ENTER ist pressed again ...
Size changed: 428, 284
manually drawing all Pixels works fine, in canvas and fullscreen, had to adapt only one line to make it work
_((Uint32)pixels + row * surface_width + col) =_ ...
surface_width instead of emu_width ππ»
here is the complete working render method
void draw_one_frame_into_SDL2_Pixel(void *thisC64) {
C64 *c64 = (C64 *)thisC64;
c64->executeOneFrame();
void *texture = c64->vic.screenBuffer();
int surface_width = window_surface->w;
int surface_height = window_surface->h;
for (int row = 0; row < emu_height; row++) {
for (int col = 0; col < emu_width; col++) {
Uint32 rgba = *(((Uint32*)texture) + row * emu_width + col);
int a= (rgba>>24) & 0xff;
int b= (rgba>>16) & 0xff;
int g= (rgba>>8) & 0xff;
int r= rgba & 0xff;
*((Uint32*)pixels + row * surface_width + col) = SDL_MapRGBA(window_surface->format, r, g, b, a);
}
}
SDL_UpdateWindowSurface(window);
}
I can't get why draw_one_frame_intoSDL2Texture() is giving me such an unexpecting behaviour in fullscreen mode ...π€ Something SDL-esque code is still missing for sure ...
πΆ Don't know.
In draw_one_frame_into_SDL2_Pixel
, is pixels
also a texture or is it a frame buffer? Unfortunately, I've never written any SDL code.
In draw_one_frame_into_SDL2_Pixel, is pixels also a texture or is it a frame buffer?
Its the framebuffer. I only gave the variable the name βtextureβ. I am too completely new to SDL donβt know what I am doing. But donβt worry I will solve the riddle ... π€
@mithrendal I don't know if I can help, but can you commit the non-working code to the dev branch? I will have a look at it. I think it is fair to committ non working code to dev - this is why you have "dev" after all (in contrast to master)... :-)
but can you commit the non-working code to the dev branch?
sure. π
The pixel wise rendering works fine in both resolutions Fullscreen 1440 x 900 and the original screenbuffer resolution of the emulator 428 x 284
ALT+ENTER toggles fullscreen
But the texture is still a miracle for me. Rendering in original size works good. What I now have discovered is that not only does it not work in 1440x900 fullscreen resolution but it is also not working when increasing the target size by just 5 Pixels.
To get some sort of understanding what happens here I hang into the event loop for the following keys: Arrow keys -> increases/decreases position in target rectangle w -> increments width in target rectangle (shift+w decrements) h -> increments height in target rectangle (shift+h decrements) mouse click -> prints the x y w h offsets into the console
by modifing this way the x y position and w h of the target we get a good looking picture but at weird values ....
I for sure must be missing something fundamental here π₯΄...
#ifdef USE_SDL_2_PIXEL
DestR.x = xOff ;
DestR.y = yOff ;
#endif
#ifdef USE_SDL_2_TEXTURE
//just a try...
DestR.x = xOff + (emu_width - surface_width);
DestR.y = yOff + (surface_height - emu_height);
#endif
DestR.w = surface_width + wOff;
DestR.h = surface_height + hOff;
//SDL_RenderSetViewport(renderer, &DestR);
SDL_RenderCopy(renderer, screen_texture, &SrcR, &DestR);
status update ... very promising ... news ... I think I cracked it ... On changing target resolution it works now when I completely destroy π₯ π the SDL window, renderer and texture and create new ones for the new resolution ... somewhow it did not like me to use the existing ones and just reset the size ...
Have to do some cleanups code is in a complete messy desparate condition π due to fiercely executed hacks π«π£ here and there ...
Congrats!
Oh boy π, it only works when the first window is fullscreen π³ the second the small window the third the fullscreen ... and so on
But it does not work when the first is small and the second window is fullscreen ...π
Also not so good π΅ when I destroy the SDL window, it logs to the console
Window 11 hidden
Window 11 lost keyboard focus
Window 12 resized to 1440x900
Mouse entered window 12
Window 12 gained keyboard focus
Window 12 shown
...
hidden ??? I want to destroy... I am a destroyer !!π€
does it really destroy the unused window or am I wasting memory here π€ ...
I like to try something else, it must be possible to not always "destroy?" and re-create the windows. Because the SDL guys have invented the flag SDL_WINDOW_RESIZABLE when creating a window
window = SDL_CreateWindow("",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
w, h, SDL_WINDOW_RESIZABLE
);
@mithrendal
I went back to what you had committed in dev
because I cannot believe that destroying and redoing everything is necessary. I also think it is not an SDL problem, but an SDL + emscripten problem, so I found this here and started reading:
https://emscripten.org/docs/api_reference/html5.h#fullscreen
(I just started reading, no results, yet, but I thought this might be interessting for you, too)
@mithrendal and these findings might be interessting, too: https://floooh.github.io/2017/02/22/emsc-html.html
@mithrendal and this one might be the most helpful: https://glow3d.com/blog/2019/10/fullscreen-in-emscripten
@mithrendal: Yes this last hint from glow3d.com
works nicely. What I did: used your initial code from the dev
branch (so forget the stuff about window destroying :-) ) and then:
#include <emscripten/html5.h>
and then in your SDL_KEYDOWN EVENT:
if(!bFullscreen)
{
bFullscreen=true;
EmscriptenFullscreenStrategy strategy;
strategy.scaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
//strategy.canvasResizedCallback = emscripten_window_resized_callback;
//strategy.canvasResizedCallbackUserData = this; // pointer to user data
emscripten_enter_soft_fullscreen("canvas", &strategy);
}
Works like a charm.
Proof picture :-)
You just need to adjust leaving fullscreen in a similar way.
And there might be more things to consider, maybe other scaling modes, other fullscreen modes, ...
very nice I did not know about this special emscripten way ...
okay lets try it their way ...
bummer it works π€π
but ... I noticed two things ...
first of course that is not a real fullscreen, we still see the titlebar of the browser and it is only rendered in the browsers space. Fair enough, if your browser is fullscreen, you will get a really full picture nearly as full as a complete full screen.
second ... in pixel rendering mode everything is fine so far .. but that rendering method was already working with the "real" fullscreen π³
lets see what happens when we enable texture rendering ...
//#define USE_SDL_2_PIXEL 1
#define USE_SDL_2_TEXTURE 1
π« Oh no, still black screen in pseudo fullscreen .... same as in the real fullscreen
π€ maybe a little piece of the puzzle is still missing ...
BTW exit works like this
bFullscreen=false;
emscripten_exit_soft_fullscreen();
this is the evil code "the texture render method" ... maybe buggy π»
void draw_one_frame_into_SDL2_Texture(void *thisC64) {
C64 *c64 = (C64 *)thisC64;
c64->executeOneFrame();
void *texture = c64->vic.screenBuffer();
int surface_width = window_surface->w;
int surface_height = window_surface->h;
SDL_RenderClear(renderer);
SDL_UpdateTexture(screen_texture, NULL, texture, emu_width * 4);
SDL_Rect SrcR;
SDL_Rect DestR;
SrcR.x = 0;
SrcR.y = 0;
SrcR.w = emu_width;
SrcR.h = emu_height;
DestR.x = xOff ;
DestR.y = yOff ;
DestR.w = surface_width + wOff;
DestR.h = surface_height + hOff;
//SDL_RenderSetViewport(renderer, &DestR);
SDL_RenderCopy(renderer, screen_texture, &SrcR, &DestR);
//SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
Thank you for your feedback. Can you check-in your latest status in dev
? I'd love to have a look.
I just pushed the commit with your suggestions to dev. I also found out, that there is another method called _emscripten_request_fullscreenstrategy which gives us the real thing π
unfortunately still the oddity with the scaling ... when texture rendering method is used.
Anyway I feel the path which you proposed (using emscriptens special "driver" API) is the way to go ...
Oh yes and try this ... go to fullscreen -> leave fullscreen -> go to fullscreen and voila you see again the bottom left egde of the blue C64 screen.
Maybe lets use some different fullscreen strategy hints ... will try that π€
@mithrendal Thank you for the push of dev
. I double checked: you already had #define USE_SDL_2_TEXTURE 1
and you had commented out the other pixel define. So compiled this and here are good news: It works for me :-)
When I press ALT+ENTER I see a nice and real full screen without any errors.
Here is a video I made (download link works only 7 days, video is 19MB):
But what I saw - and that might be the reason that you receive errors: There is an index out of bounds exception, when I come back from full screen to normal screen. I showed the expection in the video and here is a screenshot of it:
Unfortunatelly I need to run now. I would have loved to debug it, but other committments are calling my attention. But I thought this feedback might be of value for you.
Interesting stuff on your computer it works on my not. I also don't get the exception which I saw in your video.
I strolled through the console and found one lonely error ...
Error: WebGL warning: drawArraysInstanced: Drawing to a destination rect smaller than the viewport rect. (This warning will only be given once) vC64.js:1:134676
Ah it only gives me this warning only once, why ? Wait ... the next time ... there will be punishment π³ ? We better obey the computers messages ....
Do you see that message too ?
Do you think it could be my graphics card ? I will try that on another computer ... hang on ...
EDIT: No on another computer also no success ... strange .. your computer does know how to behave π€...
Since the pixel render method works without any flaws on any computer it must be this part of code in the texture render method I guess
SDL_Rect SrcR;
SDL_Rect DestR;
SrcR.x = 0;
SrcR.y = 0;
SrcR.w = emu_width;
SrcR.h = emu_height;
DestR.x = xOff ;
DestR.y = yOff ;
DestR.w = surface_width + wOff;
DestR.h = surface_height + hOff;
//SDL_RenderSetViewport(renderer, &DestR);
//SDL_RenderCopy(renderer, screen_texture, &SrcR, &DestR);
SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
which is somehow wrong ! Because it is the only difference in code ... So it says to us "Drawing to a destination rect smaller than the viewport rect. " ... wait does that mean the DestR is smaller than the viewport rect ???
when I change code to this it does not complain anymore π....
DestR.x = xOff ;
DestR.y = yOff ;
DestR.w = surface_width + wOff;
DestR.h = surface_height + hOff;
SDL_RenderSetViewport(renderer, &DestR);
SDL_RenderCopy(renderer, screen_texture, &SrcR, &DestR);
//SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
SDL_RenderPresent(renderer);
I effectivly just gave it what it wanted π: a destination rect not smaller than the viewport ...
Now sometimes it works fine in 1 case out of 5 when I switch to fullscreen, in 4 cases I also have a picture but the complete vC64 screen buffer in the bottom left edge ... Nice !! I think we got near the hot core .... should we wear masks π· and protection suits from now on ?
this version works perfectly for my computer. So happy. The javascript exception in Web-Console but no WebGL warning anymore and ALWAYS a perfect display π on all my computers safari and firefox. (same as the pixel render method)
void draw_one_frame_into_SDL2_Texture(void *thisC64) {
C64 *c64 = (C64 *)thisC64;
c64->executeOneFrame();
void *texture = c64->vic.screenBuffer();
int surface_width = window_surface->w;
int surface_height = window_surface->h;
SDL_RenderClear(renderer);
SDL_UpdateTexture(screen_texture, NULL, texture, emu_width * 4);
SDL_Rect SrcR;
SDL_Rect DestR;
SrcR.x = 0;
SrcR.y = 0;
SrcR.w = emu_width;
SrcR.h = emu_height;
DestR.x = xOff ;
DestR.y = yOff ;
DestR.w = surface_width + wOff;
DestR.h = surface_height + hOff;
SDL_RenderSetViewport(renderer, &SrcR);
SDL_RenderCopy(renderer, screen_texture, &SrcR, &SrcR);
//SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
hope it works on your computer too ...
If yes we just have to clean up a little redundant code etc. π
just pushed that to the dev branch
Finding: no javascript exception when using the pixel render method. That means despite everything looks good now and no WebGL error anymore when using texture-rendering something still throws a lonly index out of bounds exception which is ignored but written to the log ...
Unfortunatelly, on my computer this version never works. It looks like this:
I think we did step #1 but are missing step #2 of these instructions:
Haha π thats exactly how it looks on mine when I just do
SDL_RenderSetViewport(renderer, &DestR);
SDL_RenderCopy(renderer, screen_texture, &SrcR, &DestR);
with the latest it worked so well for all my macs safari and firefox ...
SDL_RenderSetViewport(renderer, &SrcR);
SDL_RenderCopy(renderer, screen_texture, &SrcR, &SrcR);
Ok enough said π€, now lets swap out the big "canvasResizedCallback" rocket launcher π and put it into place to fight this enemy -> π»
Wow, that's all very exciting (and very funny to read). I'll try to download the code in the afternoon π€€. First, I have to solve a bigger problem: Finding a store that still has bread. Yesterday, I found one, but the guy in front of me took the last loaf π.
Ah it only gives me this warning only once, why ? Wait ... the next time ...
Uh oh, yes, you better take care. I remember to have received many MSG_CLEAN_UP_YOUR_ROOM messages when I was a child. They also had the "This warning will only be given once" label on it π¬.
news ticker: ... sy2002 special version is in place ... in latest commit on dev branch ... use with caution ... last loafs being bought by some hungry guys in southern germany ...
@mithrendal:
WOW I guess you nailed it!!
I don't have a lot of time right now (need to work ;-) ) but I quickly pulled your code, compiled... ...and: IT WORKS PERFECTLY!
I switched about 25 times between fullscreen and non fullscreen using ALT+ENTER: Perfect.
(Disclaimer: Only tested on a MacBook Pro and only on a Firefox)
But well - I guess you are on the road to success now! :-)
Congrats. Great job!
But well - I guess you are on the road to success now! :-)
Me, too. Me, too. Me, too π₯³.
Download complete... it's compiling now π€€.
OK, the executable is ready. Let's try in Safari first. Looks good, something's coming up...
Ooups π³. It definitely does something, but I get a different display window each time I switch back and forth between full screen mode and window mode. Seems like some random number generator is involved. Maybe a virus π€.
Same in Chrome on my machine here πͺ.
there we have it ... I told you before to be very careful π· ... now see ... genetic mutation ... on all our computers the virus behaves differently. π±
on my mac mini in safari I see the same random results as dirk ... whereas firefox on another mac works fine ... nevertheless in the end we will succeed πͺπΎ because we are humans
BTW: if you are sick of the random results, you can enable pixel render method to practical endlessly enjoy correct and consistent back and forth switching for hours ... good way of passing time in a quarantine π...
in the end we will succeed πͺπΎ because we are humans
That's what I call an attitude π.
Gentlemen, this is really an interessting riddle. :-)
Two quick thoughts:
We might want to compare our browsers and machines using this tool, i.e. check the WebGL capabilities, since SDL in Emscripten uses WebGL:
But even before we do that: This here is DOSBOX compiled with SDL and Emscripten:
https://archive.org/details/msdos_Prince_of_Persia_1990
Can you check, if this works on the machine/browser combination that does not work on your side? Because if this is the case, we just need to look into the source code of the web version of DosBox:
Prince of Persia π€€ ... on my way...
Results on Catalina 10.15.4:
Bottom line: Epic fail πͺ
@dirkwhoffmann Interessting: On my Computer (Mojave 10.14.6) here are the test results:
Bottom line: We are at the bleeding edge of technology here.
Maybe the best compromise for now is:
soft fullscreen combined with streaming textures
The latter one for speed and the soft fullscreen for better compatibility?
strategy.scaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
strategy.canvasResizedCallback = emscripten_window_resized_callback;
strategy.canvasResizedCallbackUserData = this; // pointer to user data
emscripten_enter_soft_fullscreen("canvas", &strategy);
Update from my side:
BTW, the fullscreen button only seems to work after DosBox has been launched.
my results... prince of persia real fullscreen test parcour ...
old safari 11.1.2 works π latest firefox works π safari 13.1 does not work inconsistent/random π·
vc64web real fullscreen test parcour ... (for both render methods: pixel, texture) old safari 11.1.2 works π latest firefox works π safari 13.1 does not work or inconsistent/random π·
I like to follow the advice of sy2002 ...
hang on I have to clear the area first from any virus ...
sector cleared capitain sy2002
new code is in place ....
lets do the test parcour again
vc64web soft fullscreen test parcour ... (for both render methods: pixel, texture) old safari 11.1.2 works π latest firefox works π safari 13.1 works π
new code pushed to dev π
The latest checkin seems to do the trick π. At first, I though it doesn't work, because I was using the Fullscreen button. But pressing ALT-ENTER works like a charm in all browsers π. I guess the Fullscreen button invokes different code (which exhibits the snap-back, white screen, random stuff bug).
BTW, I think you had your webcam on while coding π³. This one must have been recorded yesterday in the afternoon I think:
And this one is time-stamped around the time when you uploaded the bug fix:
Yes the fullscreen button is from the emscripten tutorial from the starter custom html template which does not work. I think the code behind the button is for SDL1. I will remove that guy and make a better looking html page.
BTW, I think you had your webcam on while coding π³.
oh thanks mate. That was true π± Just turned it off.
@mithrendal I also tested on my side. Works fine now. Congrats! :-) So, three Mac guys. Anyone volunteering with a Windows 10 in Parallels to test if it works there? ;-)
About the Fullscreen button: Here is a code suggestion (which includes changes to the Makefile, to the .html shell and to the .cpp file) that makes the Fullscreen button work (ZIP attached)
Anyone volunteering with a Windows 10
What's Windows? π€
What's Windows? π€
An operating system especially made for game remakes. Most of these are poorly done and brutally over engineered. π
C64 Version -> name of the windows remake Commando -> Battlefield Pirates-> assassin creed black flag High noon-> red dead redemption The last v8-> GTA5 Pitstop2 -> Need for speed
@sy2002 The next two days I am off from a computer. NeXt week I look ahead to review and merge your changes.
@mithrendal Thanks for havinging a look at my changes.
Two days off from a computer
?? !! WOW! That's a tough one :-)
VirtualC64web running in Edge. Fullscreen mode works like a charm π. Sound is perfect, too.
Thanks for having a look at my changes.
The commits where fine, I merged them. Exactly the road which we want to go ... brilliant ... give me five π... oh no that was an error ... corona π· ... lets wash our hands π¬
Why not use github pull requests next time ?
@mithrendal Great news - thank you.
I guess fullscreen works now? Even on this obscure OS, that is mainly used for poorly done and brutally over engineered game remakes ;-)
Looks like another long running issue can be closed :-)
@sy2002 Yes looks fine π. Thank you for great and helpful analyse work and code contribution !
@mithrendal you are very welcome - was a big pleasure :-)
works with SDL1 but not in SDL2