Which Function For Scaling/zooming?


A question came to me after playing around with an iPad. How are they doing the scaling on the iPhone/iPad? When you zoom in and out text still is very readable and there is no blurry filter being used (would not be good for reading text). It looks like they are doing some kind of sub-pixel thing. Could something like that be used instead if the contrast/sharpness killing fuzzy way (Ginge, PSX4All) that is being done on some Pandora apps?
 
Text is not raster, it's rendered as a set of vector definitions into the point size requested. You can't compare these things.
 
Exophase said:
Text is not raster, it's rendered as a set of vector definitions into the point size requested. You can't compare these things.
It is not *just* text. All graphic elements including bitmaps while viewing webpages on the iPad look the same, those aren't all vector. Same with photos, pixel art, and everything else. Things will get blocky if you zoom in too much obviously, but to the point where most pandora apps would zoom it would be ok.
 
Last edited by a moderator:
SteveM said:
Right now I've lost audio, but I suspect that's just down to missing ALSA stuff on my part.
Just tried it and it works great! Even sound works still fine in UAE4All - probably because it's still using some old gp2x-stuff.
 
Last edited by a moderator:
Encountered a very weird problem: setting UAE4All to 320x200 pixels doesn't work with framebuffer. While the menu works fine as soon as you start emulation UAE4All crashes.
320x200 without framebuffer works fine.
Also doesn't matter if you set framebuffer to 320x200, too, or some larger area - if the SDL_Surface in UAE4All is 320x200 it crashes (but only in framebuffer-mode).

The lowest working height is 205 pixels meaning 320x205 (and any higher resolution) works fine in framebuffer mode (320x204 and anything lower doesn't) so it's not a big issue (as this still almost uses the full height of games in 320x200 resolution).

I just don't understand why the menu works fine in framebuffer-mode with an SDL_Surface of 320x200 but crashes once you start emulation whilst everything works fine with an SDL_Surface of 320x200 without framebuffer. <_<
 
john4p said:
Just tried it and it works great! Even sound works still fine in UAE4All - probably because it's still using some old gp2x-stuff.
Ah, I guess it's just writing to /dev/dsp directly? Still no luck getting SDL audio to work. I got the ALSA stuff compiled in but starting the audio thread still fails.

john4p said:
Encountered a very weird problem: setting UAE4All to 320x200 pixels doesn't work with framebuffer. While the menu works fine as soon as you start emulation UAE4All crashes.
320x200 without framebuffer works fine.
Also doesn't matter if you set framebuffer to 320x200, too, or some larger area - if the SDL_Surface in UAE4All is 320x200 it crashes (but only in framebuffer-mode).

The lowest working height is 205 pixels meaning 320x205 (and any higher resolution) works fine in framebuffer mode (320x204 and anything lower doesn't) so it's not a big issue (as this still almost uses the full height of games in 320x200 resolution).

I just don't understand why the menu works fine in framebuffer-mode with an SDL_Surface of 320x200 but crashes once you start emulation whilst everything works fine with an SDL_Surface of 320x200 without framebuffer. <_<
That really does sound odd. I've been testing with Handy which has a tiny resolution (160x102) and that worked OK. I'm guessing by crash you mean a segfault? What are the other parameters, like bpp and your ofbset/fbset stuff? I don't know if the library I posted had debugging symbols in it, but I can definitely make a new one which does if you're interested in troubleshooting it.
 
Last edited by a moderator:
john4p said:
Encountered a very weird problem: setting UAE4All to 320x200 pixels doesn't work with framebuffer. While the menu works fine as soon as you start emulation UAE4All crashes.
320x200 without framebuffer works fine.
Sounds like the emu is simply writing beyond 200 lines. That 320x200 mode might be a be larger in reality (just a guess, not familiar with Amiga's video hardware), or it might be doing this because of some optimization.
 
Last edited by a moderator:
Thanks for the quick replies.


SteveM said:
Ah, I guess it's just writing to /dev/dsp directly? Still no luck getting SDL audio to work. I got the ALSA stuff compiled in but starting the audio thread still fails.
Correct. In the src-file sound_gp2x.cpp "/dev/dsp" is opened and used.

SteveM said:
john4p said:
Encountered a very weird problem: setting UAE4All to 320x200 pixels doesn't work with framebuffer. While the menu works fine as soon as you start emulation UAE4All crashes.
320x200 without framebuffer works fine.
Also doesn't matter if you set framebuffer to 320x200, too, or some larger area - if the SDL_Surface in UAE4All is 320x200 it crashes (but only in framebuffer-mode).

The lowest working height is 205 pixels meaning 320x205 (and any higher resolution) works fine in framebuffer mode (320x204 and anything lower doesn't) so it's not a big issue (as this still almost uses the full height of games in 320x200 resolution).

I just don't understand why the menu works fine in framebuffer-mode with an SDL_Surface of 320x200 but crashes once you start emulation whilst everything works fine with an SDL_Surface of 320x200 without framebuffer. <_<
That really does sound odd. I've been testing with Handy which has a tiny resolution (160x102) and that worked OK. I'm guessing by crash you mean a segfault? What are the other parameters, like bpp and your ofbset/fbset stuff? I don't know if the library I posted had debugging symbols in it, but I can definitely make a new one which does if you're interested in troubleshooting it.
I don't think there's a bug in ofbset/fbset. UAE4All's menu works fine at 320x200 with framebuffer. Only once you start emulation it crashes - and not with a segfault, but this:
*** glibc detected *** ./uae4all: free(): invalid pointer: 0x00aa12b0 ***

The values for ofbset/fbset are correct:
ofbset -fb $SDL_FBDEV -pos 16 0 -size 768 480 -mem 128000 -en 1 (<= also tried with 800x480 and 640x480)
fbset -fb $SDL_FBDEV -g 320 200 320 200 16


notaz said:
Sounds like the emu is simply writing beyond 200 lines. That 320x200 mode might be a be larger in reality (just a guess, not familiar with Amiga's video hardware), or it might be doing this because of some optimization.
But why does it then work without framebuffer? Without framebuffer I also just call SDL_SetVideoMode with width 320 and height 200 and it still works fine when you start emulation (of course without framebuffer the 320x200 area is a tiny rectangle in the middle of our 800x480 screen).

Btw., with an SDL_Surface of 320x200 UAE4All also crashes if I use for example 320x240 or even 800x480 with fbset.


But well, 320x205 (upscaled to 750x480 to keep correct x:y-aspect ratio) looks great already. The picture is huge. The very few black lines on top and bottom (when playing games with a 320x200-resolution) are hardly noticable.

___________________________________________________________________________

Another issue:

I tried to call ofbset and fbset using system(...) from UAE4All to change the framebuffer dimensions on the fly in UAE4All via button-press. This works flawlessly.

But this would only make sense if I could also change the SDL Surface to the changed dimensions on the fly.
Unfortunately I can't get this to work.

Calling SDL_SetVideoMode again resulted in a segfault. Okay, that's probably because there was still something being drawn to the old Surface when it ceased to exist.
Thus I tried calling graphics_init() at the end of flush_block() in sdlgfx.cpp in order to reinitialize the SDL_Surface - of course with changed dimensions.

When I try this UAE4All also crashes - but instead of a segfault with this:

*** glibc detected *** ./uae4all: double free or corruption (out): 0x00b51488 ***

As suggested by some website I exported MALLOC_CHECK_=0 before starting UAE4All to just ignore this double deletion error. But the error is not ignored. Still crashes.

I also searched every source for possible bad "new", "malloc" and "SDL_FreeSurface"-calls. Without success.


So it looks like there won't be the possibility to change the resolution on the fly in UAE4All for now.
You'll have to decide for one at the start (and quit and restart if you want to play at a different resolution).
 
Last edited by a moderator:
john4p said:
The values for ofbset/fbset are correct:
ofbset -fb $SDL_FBDEV -pos 16 0 -size 768 480 -mem 128000 -en 1 (<= also tried with 800x480 and 640x480)
fbset -fb $SDL_FBDEV -g 320 200 320 200 16
You're not using double buffering? If so, you'll ned something like:
ofbset -fb $SDL_FBDEV -pos 16 0 -size 768 480 -mem 256000 -en 1
fbset -fb $SDL_FBDEV -g 320 200 320 400 16

Not sure what's happening with the dynamic screen mode changes. I'm pretty sure you should always be able to call SDL_SetVideoMode multiple times. Does this work using the default driver (i.e. without fbcon)?
 
Last edited by a moderator:
No, I don't use double buffering since it runs perfectly smooth without it (vsync is enough). Also someone meant our SDL wouldn't properly support doublebuffering.

Calling SDL_SetVideoMode multiple times always makes UAE4All crash - also without framebuffer mode.
 
Hello the community,

While waiting for my Pandora I look the source codes and I found this function of double scaling at Pandora file archive:
The surface->pitch is multiplied by 2 in the 2 directions.
It must be used instead of SDL_BlitSurface (surface, & src, dest, & dst).
I tested on the PSP and it works great with double buffering!

Code:
 void pixel_doubling_blit(SDL_Surface* surface, SDL_Surface* dest)
 {
   register int i, j;
 
//   SDL_Surface* dest = SDL_GetVideoSurface();
 
   int bpp = surface->format->BytesPerPixel;
 
   bpp == dest->format->BytesPerPixel;
 
   if (SDL_MUSTLOCK(dest) != 0)
   {
     if (SDL_LockSurface(dest) < 0)
     {
       fprintf(stderr, "dest locking failed\n");
       return;
     }
   }
 
   switch (bpp)
   {
     case 2:
     {
       int tpitch = dest->pitch / 2;
       int spitch = surface->pitch / 2;
        /* :COMMENT: 051223.15: pitch is always in bytes
         * However, incrementing is done in sizeof(Uint16)
         * and sizeof(Uint16) is two bytes. */
 
       Uint16* tp = (Uint16*) dest->pixels;
       Uint16* sp = (Uint16*) surface->pixels;
 
       const int wd = ((dest->w / 2) < (surface->w))
           ? (dest->w / 2) : (surface->w);
 
       const int hg = ((dest->h) < (surface->h*2))
           ? (dest->h) : (surface->h*2);
 
       for (j = 0; j < hg; ++j)
       {
         for (i = 0; i < wd; ++i)
         {
           tp[i*2] = sp[i];
           tp[i*2 + 1] = sp[i];
         }
         tp += tpitch;
         if (j % 2 != 0)  sp += spitch;
       }
 
       break;
     }
     case 3:
     {
        /* :COMMENT: 051223.18: This case has only been tested on
         *                      little-endian machine. */
 
       int tpitch = dest->pitch;
       int spitch = surface->pitch;
 
       const int wd = ((dest->w / 2) < (surface->w))
           ? (dest->w / 2) : (surface->w);
 
       const int hg = ((dest->h) < (surface->h*2))
           ? (dest->h) : (surface->h*2);
 
       Uint8* tp = (Uint8*) dest->pixels;
       Uint8* sp = (Uint8*) surface->pixels;
 
       for (j = 0; j < hg; ++j)
       {
         for (i = 0; i < 3 * wd; i += 3)
         {
           int i2 = i * 2;
           tp[i2 + 0] = sp[i];
           tp[i2 + 1] = sp[i + 1];
           tp[i2 + 2] = sp[i + 2];
           tp[i2 + 3] = sp[i];
           tp[i2 + 4] = sp[i + 1];
           tp[i2 + 5] = sp[i + 2];
         }
         tp += tpitch;
         if (j % 2 != 0)  sp += spitch;
       }
 
       break;
     }
     case 4:
     {
       int tpitch = dest->pitch / 4;
       int spitch = surface->pitch / 4;
        /* :COMMENT: 051223.15: pitch is always in bytes
         * However, incrementing is done in sizeof(Uint32)
         * and sizeof(Uint32) is four bytes. */
 
       Uint32* tp = (Uint32*) dest->pixels;
       Uint32* sp = (Uint32*) surface->pixels;
 
       const int wd = ((dest->w / 2) < (surface->w))
           ? (dest->w / 2) : (surface->w);
 
       const int hg = ((dest->h) < (surface->h*2))
           ? (dest->h) : (surface->h*2);
 
       for (j = 0; j < hg; ++j)
       {
         for (i = 0; i < wd; ++i)
         {
           tp[i*2] = sp[i];
           tp[i*2 + 1] = sp[i];
         }
         tp += tpitch;
         if (j % 2 != 0)  sp += spitch;
       }
 
       break;
     }
     default:
       /* :COMMENT: 051223.17: This should never happen. */
       fprintf(stderr, "Unknown bitdepth.\n");
       break;
   }
 
 
   if (SDL_MUSTLOCK(dest) != 0)
   {
     SDL_UnlockSurface(dest);
   }
 }

Enjoy ;) .
 
From the UAE thread:

EvilDragon said:
john4p said:
@EvilDragon: But how could we solve this issue easily so that no one would have to manually copy the library?
(Note it's worth it - the hardware scaled modes are great.)
Shall I just release the new version already with instructions as to how to install the modified SDL-lib or with a script that does that?

Just talked to DJWillis and notaz - seems it's still a quick and dirty fix that seems to break stuff like input by not using X...
If the patch was clean and working nicely, I'd be happy to include that in the official firmware :)

I'd appreciate some more detailed feedback on this. I can adapt it to use X events, although I do kind of wonder why not using X in a console-based driver is necessarily an issue. I'm guessing there are some kind of interoperability issues, but I'd like to hear the specifics. It'd be nice to get something workable into the firmware even if it's not 100% ideal as yet.

There are of course other approaches which may be preferable. For example, making use of the DirectFB driver (although talking to DJWillis, getting DirectFB itself into the firmware has issues of its own).
 
Last edited by a moderator:
Please link your latest patch again, it's very exhausting to search these forums.

The basic requirement is that SDL X windowed mode would still work, i.e. you could launch 2 windowed SDL apps and the one with focus would get input. It should not mess with the scaler or /dev/input/ until it's in fullscreen mode.
 
notaz said:
Please link your latest patch again, it's very exhausting to search these forums.
http://www.cosam.org/computers/pandora/SDL-1.2.14-pandora-fb.patch
Had to go back a whole page to find that ;-)

The basic requirement is that SDL X windowed mode would still work, i.e. you could launch 2 windowed SDL apps and the one with focus would get input. It should not mess with the scaler or /dev/input/ until it's in fullscreen mode.
So allowing fbcon only if SDL_FULLSCREEN is set would technically be enough? Windowed apps would then use the (unaltered) X driver. The fbcon stuff is only enabled if explicitly specified by setting the SDL_VIDEODRIVER environment variable. Or does switching between windowed/full screen need to be supported? In that case it'd probably be neater to just allow the default driver use the scaler when in full screen mode.
 
Last edited by a moderator:
SteveM said:
So allowing fbcon only if SDL_FULLSCREEN is set would technically be enough? Windowed apps would then use the (unaltered) X driver. The fbcon stuff is only enabled if explicitly specified by setting the SDL_VIDEODRIVER environment variable. Or does switching between windowed/full screen need to be supported? In that case it'd probably be neater to just allow the default driver use the scaler when in full screen mode.
Oh, if X driver is unaltered then env var is enough. So now the main issue I have with it is that you break it fbcon when it's used from framebuffer console (do 'sudo chvt 1' to get there). It will fight with Linux console if you run SDL game there. You may think nobody uses it this way, but even I sometimes do and there may be others.

What about leaving fbcon alone creating custom SDL_VIDEODRIVER? All this is custom pandora code anyway, you can copy from fbcon what you need, and all existing functionality would stay. You can call it 'SteveM' driver if you like, and we could take the patch without fear of anything breaking :) . Later when (if) Paeryn releases his hw-accelerated version, it could co-exist with yours and old apps would still work.
 
Last edited by a moderator:
john4p said:
No, I don't use double buffering since it runs perfectly smooth without it (vsync is enough). Also someone meant our SDL wouldn't properly support doublebuffering.

Actually that is not entirely true. I get screen tearing (double mode) in allot of Amiga games depending on scroll speed etc.
 
Last edited by a moderator:
DaveC said:
john4p said:
No, I don't use double buffering since it runs perfectly smooth without it (vsync is enough). Also someone meant our SDL wouldn't properly support doublebuffering.

Actually that is not entirely true. I get screen tearing (double mode) in allot of Amiga games depending on scroll speed etc.
Sometimes it goes out of sync. Just shortly enter the menu and leave it again (so just press "Select" twice) and scrolling will be perfect. Btw., "Scroll speed" doesn't matter at all. Either 50fps can be drawn in time (and synchronized to the lcd refresh rate) or not.

Already tried doublebuffering - but that made everything worse (there's always a tearing line). Probably because it's not really supported by our SDL.
 
Last edited by a moderator:
notaz said:
What about leaving fbcon alone creating custom SDL_VIDEODRIVER? All this is custom pandora code anyway, you can copy from fbcon what you need, and all existing functionality would stay. You can call it 'SteveM' driver if you like, and we could take the patch without fear of anything breaking :)

Sounds like a plan. Not having to worry about breaking stuff means I can also add a few extra features which would be hard to shoehorn into an existing driver. I'll see what I can rustle up...
 
Last edited by a moderator:
notaz said:
What I recommend is doing it like psx4pandora does, using wrapper script technique:
Code:
 ofbset -fb /dev/fb1 -pos 0 0 -size 800 480 -mem 307200 -en 1
 fbset -fb /dev/fb1 -g 320 240 320 480 16
 export SDL_VIDEODRIVER=fbcon
 export SDL_FBDEV=/dev/fb1
 
 op_runfbapp ./your_app_here
 
 ofbset -fb /dev/fb1 -pos 0 0 -size 0 0 -mem 0 -en 0

EDIT: this doesn't work with SDL, because it wants to grab console and fails to do it from X. This will work if you use framebuffer directly though.

I tried yesterday night to get this working. As your edit state SDL cant grab a tty, but this works :
Code:
sudo SDL_VIDEODRIVER=fbcon SDL_FBDEV=/dev/fb1 op_runfbapp ./your_app_here
As gdb never provide anything usefull with sdl, I used strace. I found It try to open /dev/tty and fail, so I chmoded it and it wasn't enough, so I guess I'm still missing something...

As a matter of fact, I'm trying to implement this for the Zelda's games. These are 320*240 games than are scaled to 640*480 by software. So I removed the scaling code from 3t to test. It now output 320*240 16bpp.

With the -mem value you posted up here, I get a segfault, but I know for sure that the game draw (some garbage) after the last 320 column. So I tried to :
Code:
ofbset -fb /dev/fb1 -pos 80 0 -size 640 480 -mem $((640*480*2)) -en 1
 fbset -fb /dev/fb1 -g 320 240 320 480 16
But all I get is vertical scalling. So I tried this geometry : 320 240 640 480 16, but now I get no scalling at all.

I'm afraid I don't understand all i'm doing, so a bit of help would be welcome. :)
 
Last edited by a moderator:
Maybe it sill switches the resolution to 640x480 then? Run the game and on another terminal run "fbset -fb /dev/fb1" so that it prints current geometry. It's important that game sets the fb resolution to 320x240 and not something else.
 
Back
Top