Uae, softstretch of screen-backbuffer, problem and fix [long]

While hacking around on UAE, the U*nix Amiga Emulator:

I did want to have the amiga game area fullscreen w/o
the sdl going to switch the screen mode (it would
otherwise crash that display on exit from game). So,
I started to look at SDL_SoftStretch.

That did work, just let the UAE draw into a backbuffer
surface, and on the update-call from UAE make it a
softstretch to the real screen surface with an update
on that screen surface rect. Works good, However…

There was a considerable flicker while being stretched.
Some lines were moving up and down constantly (this moving
of lines can not occur horizontally since UAE calls update
only on full backbuffer screenlines). Just a single line
or so but very annoying. Quite like an old tv screen w/o
proper vsync.

So I gone to look at the implementation of SDL_SoftStretch.
At first, I wondered what those pos/inc are about since I
have been under the impression that a brezenham style
scaling should have worked okay and be even faster and better.
Dunno, even teenage hackers should’ve always seen such I guess.

Since I did not understand the pos/inc code anyway, I did
switch over to proper step-scaling. It did work but it turned
out to be the quite like the original, with its jumping lines.
Atleast we were to prove that a step-scaling works quite like
that inc/pos code. :wink:

First, I was thinking that it would have to do with improper
line fractions, so that some of the inner lines in a rect
copy would perhaps sometimes drawn one line upper or lower.
Nope, wasn’t quite it. 't’seems more like the rectstarts.

After some rounds, I did get the clue what was the real cause
has been of the jumping lines: - the softstretching works based
on the target rect, and the scaling factor is derived from it.
Since UAE calls the update on small amounts of screenlines, that
can have a considerable effect.

Likewise, the caller code was bound to hand over a dstrect info
and it did compute the measures from srcrect info statically.
Of course, there is no room for handing over any linefractions
here or something like that, perhaps tweaking the calculations
to include invisible lines above the area would help. But that
would require knowledge of the implementation details of the
softstretch code.

So, after all, I did decide to make up a variant of SoftStretch
that does not look at the dstrect info at all. Instead, it
uses the dstrect info as a returnvalue argument, so that one
call call a real SDL_Update(…,dstrect) with it.

Here, the SDL_UpdateStretch implementation decides where the actual
destrect will placed in the output surface, and it does so
based on calculations that include linefractions of untouched
lines above the rect to be copied/stretched. The scaling factor
is constant and taken from the h/w of the input/output surfaces.

That made the flicker to go away. - in essence both things did
need to be fixed, the jumping scale factor and the jumping
dstrect start. Now, the question is whether that kind of softstretch
is more common, i.e that we want a constant scale of the input
surface rect to the output surface rect instead of the input
view rect to the output view rect. That’s what the current
SDL_SoftStretch code does. And also bound the dstrect placement
on the stretch algorithm including its memorized linefractions.

To boil it down for one side atleast, please have a look at
SDL12/video/SDL_stretch.c, and look for the line that reads
inc = (srcrect->h << 16) / dstrect->h;
that’s the roblem for the flicker according to jumping scale
factors. My change here might be backported like this:
inc = (src->h << 16) / dst->h;
which kills the jumping scaling factor atleast. But I do not quite
understand the original inc/pos code, so I don’t fiddle it in here.
It might not kill the jumping dstrect-start either, I guess.

Anyway, attached is my current implementation, it is not perfect,
the linecopy code should be adapted as well but done only partially.
Along with the asm-snippet enabled for i386, it works fine at
the moment. And remember that dstrect is a return-arg here. The
common call scheme would be to

SDL_UpdateStretch(backbuffer, updatedrect, screen, &dstrect);
SDL_UpdateRects(screen, 1, &dstrect);

instead of the usual:
//dstrect = scaled(srcrect,backbuffer,screen);
//SDL_SoftStretch(backbuffer, updatedrect, screen, dstrect);
//SDL_UpdateRects(screen, 1, dstrect);

btw, I can swith both at runtime as the call synopsis happens
to be the same and dstrect tmp is overwritten then :wink:
cheers,
– guido http://google.de/search?q=guidod
GCS/E/S/P C++/++++$ ULHS L++w- N++@ d(±) s+a- r+@>+++ y++ 5++X- (geekcode)
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed…
Name: sdlstretch.c
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20030819/b651f5ae/attachment.asc

That made the flicker to go away. - in essence both things did
need to be fixed, the jumping scale factor and the jumping
dstrect start. Now, the question is whether that kind of softstretch
is more common, i.e that we want a constant scale of the input
surface rect to the output surface rect instead of the input
view rect to the output view rect. That’s what the current
SDL_SoftStretch code does. And also bound the dstrect placement
on the stretch algorithm including its memorized linefractions.

Actually, the original purpose of the SDL_SoftStretch code was for
stretching video from one surface to a viewing rectangle in another
surface. For this it does exactly what it is supposed to do. I’m
glad you found out why it was having problems for you though. :slight_smile:

You might also take a look at some of the other scaling algorithms
out there, some of the emulators have very nice 2x/4x smoothing code,
although I don’t know how fast it is.

See ya!
-Sam Lantinga, Software Engineer, Blizzard Entertainment

Sam Lantinga wrote:

That made the flicker to go away. - in essence both things did
need to be fixed, the jumping scale factor and the jumping
dstrect start. Now, the question is whether that kind of softstretch
is more common, i.e that we want a constant scale of the input
surface rect to the output surface rect instead of the input
view rect to the output view rect. That’s what the current
SDL_SoftStretch code does. And also bound the dstrect placement
on the stretch algorithm including its memorized linefractions.

Actually, the original purpose of the SDL_SoftStretch code was for
stretching video from one surface to a viewing rectangle in another
surface. For this it does exactly what it is supposed to do. I’m
glad you found out why it was having problems for you though. :slight_smile:

In other words, your common usage is about
SDL_SoftStretch(framebuffer, 0, screen, viewrect);
while mine would be
SDL_UpdateStretch(drawbuffer, updated, screen, 0);

You might also take a look at some of the other scaling algorithms
out there, some of the emulators have very nice 2x/4x smoothing code,
although I don’t know how fast it is.

yepp, - I did not want to blow up the code and so I had been under
the impression that there must be some fix to the SoftStretch
routine. It wasn’t, so… :wink: … still, as I look at the code
of SoftStretch there is some room for improvements oops :-)=)

have fun,
– guido http://google.de/search?q=guidod
GCS/E/S/P C++/++++$ ULHS L++w- N++@ d(±) s+a- r+@>+++ y++ 5++X- (geekcode)

Guido Draheim wrote:

Sam Lantinga wrote:

You might also take a look at some of the other scaling algorithms
out there, some of the emulators have very nice 2x/4x smoothing code,
although I don’t know how fast it is.

yepp, - I did not want to blow up the code and so I had been under
the impression that there must be some fix to the SoftStretch
routine. It wasn’t, so… :wink: … still, as I look at the code
of SoftStretch there is some room for improvements oops :-)=)

Pardon me, Sam, but I’ve been running through the sources of two
dozen libraries and game emulators, and there’s nothing useful.

As for the situation, most game emulators target small or very
oldish devices. They do often use a simple approach towards
scaling or simply implement 2x / 3x integer scaling. That’s out
of question here as an Amiga screen had been screen filling
including hires modes, and I just want to get the next 30%
stretched out to the screen area of a modern pc monnitor.

Likewise, many projects hide the actual flow of information in
a kind of framework, plus it turns out that many many projects
are unmaintained (almost like UAE itself minus the kind people
at winUAE who do some non-sdl work on the project). From the
libsdl.org pages alone, http://fpse.emuunlim.com/ is a 404-type
and http://www.emuhq.com/ljohn/ does not even exist.

The only optimized scaling routines that I know here about are
the rotozoom parts of A.S. but they do much to much of filtering
for what needs to be a fast realtime scaling operation in UAE.

Perhaps you have another hint, Sam?
What’s been on your mind with pointing me to some emulators?

After running up and down all those sources, I am tempted to
wrap up a few routines in their own library and push them
for proper reusage - I have done some tweaking to the
asm-rollout of softstretching as in SDL12, and it works
great (can be backported btw). I’ll attach the sources just
in case you want to have a look - as for more, well, I do
still fear it is doubled work, so…

cheers,
– guido http://google.de/search?q=guidod
GCS/E/S/P C++/++++$ ULHS L++w- N++@ d(±) s+a- r+@>+++ y++ 5++X- (geekcode)
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed…
Name: sdlstretch.c
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20030819/e71f88ea/attachment.asc

As for the situation, most game emulators target small or very
oldish devices. They do often use a simple approach towards
scaling or simply implement 2x / 3x integer scaling. That’s out
of question here as an Amiga screen had been screen filling
including hires modes, and I just want to get the next 30%
stretched out to the screen area of a modern pc monnitor.

Yep, what I was thinking about was the AdvanceMAME Scale2X code:
http://www.libsdl.org/pipermail/sdl/2002-November/050318.html

Like you said, it’s not what you need for your project.

After running up and down all those sources, I am tempted to
wrap up a few routines in their own library and push them
for proper reusage - I have done some tweaking to the
asm-rollout of softstretching as in SDL12, and it works
great (can be backported btw). I’ll attach the sources just
in case you want to have a look - as for more, well, I do
still fear it is doubled work, so…

I’m definitely interested in taking a look.

Thanks!
-Sam Lantinga, Software Engineer, Blizzard Entertainment