Bad flickering when using hardware

I wrote a simple test program, that moves a square around the screen. As long as I use software rendering
(SDL_FULLSCREEN | SDL_SWSURFACE) all goes well but, when I try to change to SDL_HWSURFACE, SDL_FillRect
functions are displayed immediately, without any need of SDL_UpdateRect, resulting in a bad flickering (since I
draw a black box and then, over it, a blue box). Also, double buffering doesn’t initialize at all. I’ve also
tried using glSDL (SDL_FULLSCREEN | SDL_HWSURFACE | SDL_GLSDL) but nothing changes.

Here you are my specs:

Windows 98
SDL 1.2.4
DirectX 8.1
Matrox Mystique G200 AGP2x 8MB with the latest BIOS and the latest official drivers
Asus P2B AGP2x with the latest BIOS
15’ CRT monitor

Thanks
CRV?ADER/KY

-------------- next part --------------
A non-text attachment was scrubbed…
Name: test.c
Type: application/octet-stream
Size: 1104 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020618/4c5b10a0/attachment.obj

An embedded and charset-unspecified text was scrubbed…
Name: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020618/fd44190e/attachment.txt

An embedded and charset-unspecified text was scrubbed…
Name: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020618/ca8f717b/attachment.asc

I wrote a simple test program, that moves a square around the screen. As long as I use software rendering
(SDL_FULLSCREEN | SDL_SWSURFACE) all goes well but,

That’s only because SDL_SWSURFACE implies double buffering through a software shadow surface.

when I try to change to SDL_HWSURFACE, SDL_FillRect
functions are displayed immediately, without any need of SDL_UpdateRect, resulting in a bad flickering (since I
draw a black box and then, over it, a blue box).

Of course - that’s to be expected if you set up a single buffered h/w surface display… (And obviously, that is supported on DirectX in fullscreen mode.)

Also, double buffering doesn’t initialize at all.

That’s interesting… What goes wrong? (And yes, this is exactly what you need… heh)

I’ve also
tried using glSDL (SDL_FULLSCREEN | SDL_HWSURFACE | SDL_GLSDL) but nothing changes.

Right. In fact, glSDL is the only “target” I’ve seen so far that demonstrates this behavior on Linux, in fullscreen as well as windowed modes. (If you tell OpenGL to set up a single buffered display, that’s exactly what you get - it really does render directly into the window, resulting in terrible flickering.)

In short, never use SDL_GLSDL without SDL_DOUBLEBUFFER. :slight_smile:

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn Tue, 18/06/2002 14:37:06 , CRV?ADER/KY wrote:

I think the correct solution is to clip all your
drawing so you only draw each opaque pixel once per
draw (alpha-ed pixels would still flicker, but that’s
a harder problem to solve…)…

You said you are drawing one black rectangle with a
smaller blue rectangle on top of it:

The black rectangle with the blue rectangle EXCLUDED
can be broken into 4 rectangles, and THEN draw the
blue rectangle… Maybe something like this:

SDL_Surface *pDest;
SDL_Rect BlackRect;
SDL_Rect BlueRect;

/* Initialize the above */

Uint32 BlackColor = 0x000000;
Uint32 BlueColor = 0x0000FF;
SDL_Rect WorkingRect;

if(BlueRect.y > BlackRect.y)
{
WorkingRect.x = BlackRect.x;
WorkingRect.y = BlackRect.y;
WorkingRect.w = BlackRect.w;
WorkingRect.h = BlueRect.y - BlackRect.y;
SDL_FillRect(pDest, &WorkingRect, BlackColor );

}
if(BlueRect.x > BlackRect.x)
{
WorkingRect.x = BlackRect.x;
if(BlueRect.y > BlackRect.y)
{
WorkingRect.y = BlueRect.y;
}
else
{
WorkingRect.y = BlackRect.y;
}
WorkingRect.w = BlueRect.x - BlackRect.x;
if((BlueRect.y+BlueRect.h) >
(BlackRect.y+BackRect.h))
{
WorkingRect.h = (BlackRect.y+BackRect.h) -
WorkingRect.y;
}
else
{
WorkingRect.h = (BlueRect.y+BlueRect.h) -
WorkingRect.y;
}
SDL_FillRect(pDest, &WorkingRect, BlackColor );
}
if((BlueRect.x+BlueRect.w) < (BlackRect.x+BackRect.w))
{
WorkingRect.x = (BlueRect.x+BlueRect.w);
if(BlueRect.y > BlackRect.y)
{
WorkingRect.y = BlueRect.y;
}
else
{
WorkingRect.y = BlackRect.y;
}
WorkingRect.w = (BlackRect.x+BackRect.w) -
WorkingRect.x;
if((BlueRect.y+BlueRect.h) >
(BlackRect.y+BackRect.h))
{
WorkingRect.h = (BlackRect.y+BackRect.h) -
WorkingRect.y;
}
else
{
WorkingRect.h = (BlueRect.y+BlueRect.h) -
WorkingRect.y;
}
SDL_FillRect(pDest, &WorkingRect, BlackColor );
}
if((BlueRect.y+BlueRect.h) < (BlackRect.y+BackRect.h))
{
WorkingRect.x = BlackRect.x;
WorkingRect.y = (BlueRect.y+BlueRect.h);
WorkingRect.w = BlackRect.w;
WorkingRect.h = (BlackRect.y+BackRect.h) -
WorkingRect.y;
SDL_FillRect(pDest, &WorkingRect, BlackColor );
}
SDL_FillRect(pDest, &BlueRect, BlueColor );

— patrick at 2dgame-tutorial.com wrote:> That it draws immediatly when your single screen

surface is in videomemory is obvious: you are
drawing to the videomemory, so it is visible
immediatly.


Do You Yahoo!?
Yahoo! - Official partner of 2002 FIFA World Cup

I wrote a simple test program, that moves a square around the screen. As long as I use software rendering
(SDL_FULLSCREEN | SDL_SWSURFACE) all goes well but,

That’s only because SDL_SWSURFACE implies double buffering through a software shadow surface.

when I try to change to SDL_HWSURFACE, SDL_FillRect
functions are displayed immediately, without any need of SDL_UpdateRect, resulting in a bad flickering (since
I

draw a black box and then, over it, a blue box).

Of course - that’s to be expected if you set up a single buffered h/w surface display… (And obviously, that
is supported on DirectX in fullscreen mode.)

Also, double buffering doesn’t initialize at all.

That’s interesting… What goes wrong? (And yes, this is exactly what you need… heh)

with
#include <SDL.h>
[…]
screen = SDL_SetVideoMode(800,600,32, SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF);

it tells me

“Can’t set video mode: DirectDrawSurface3::lock: DirectDraw is still drawing”

The funny thing is that with

#include <glSDL.h>
[...]
screen = SDL_SetVideoMode(800,600,32, SDL_FULLSCREEN | SDL_HWSURFACE | SDL_GLSDL | SDL_DOUBLEBUF);

it gives the SAME ERROR!!! WHY IS DIRECTDRAW INVOLVED???

Even if my Matrox Mystique G200 is quite old, it supports in all game I’ve played so far double buffering.

CRV?ADER/KY

[…]

That’s interesting… What goes wrong? (And yes, this is exactly what you need… heh)

with
#include <SDL.h>
[…]
screen = SDL_SetVideoMode(800,600,32, SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF);

it tells me

“Can’t set video mode: DirectDrawSurface3::lock: DirectDraw is still drawing”

I’d guess DirectX is in the middle of doing something when SDL tries to lock the screen surface - but what, and why?

The funny thing is that with

#include <glSDL.h>
[…]
screen = SDL_SetVideoMode(800,600,32, SDL_FULLSCREEN | SDL_HWSURFACE | SDL_GLSDL | SDL_DOUBLEBUF);

it gives the SAME ERROR!!! WHY IS DIRECTDRAW INVOLVED???

Even more interesting. heh

IIRC, SDL doesn’t use DirectX to set up OpenGL contexts for some reason…

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn Wed, 19/06/2002 21:30:46 , CRV?ADER/KY wrote:

That’s interesting… What goes wrong? (And yes, this is exactly what you need… heh)

with
#include <SDL.h>
[…]
screen = SDL_SetVideoMode(800,600,32, SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF);

it tells me

“Can’t set video mode: DirectDrawSurface3::lock: DirectDraw is still drawing”

I’d guess DirectX is in the middle of doing something when SDL tries to lock the screen surface - but what,
and why?

The funny thing is that with

#include <glSDL.h>
[…]
screen = SDL_SetVideoMode(800,600,32, SDL_FULLSCREEN | SDL_HWSURFACE | SDL_GLSDL | SDL_DOUBLEBUF);

it gives the SAME ERROR!!! WHY IS DIRECTDRAW INVOLVED???

Even more interesting. heh

IIRC, SDL doesn’t use DirectX to set up OpenGL contexts for some reason…

Some tests using parallax: (compiled with Dev-C++)

parallax OK
parallax -gl OK
parallax -f OK
parallax -f -gl OK
parallax -f -d ERROR
parallax -f -gl -d ERROR
parallax -d OK (It switches to software)
parallax -gl -d OK (Does it switch to software, too?)

Actually, I am pretty sure it’s a bug in SDL. I’ll check wheter it works or not in linux.

CRV?ADER/KY

[…]

Some tests using parallax: (compiled with Dev-C++)

parallax OK
parallax -gl OK
parallax -f OK
parallax -f -gl OK
parallax -f -d ERROR
parallax -f -gl -d ERROR

Ok. Looks like things go wrong as soon as h/w pageflipping is involved…

parallax -d OK (It switches to software)

Yes, because you can’t h/w pageflip in windowed mode on any current mainstream windowing systems.

parallax -gl -d OK (Does it switch to software, too?)

No, but there is a major difference. While -gl -f -d will most probably use h/w pageflipping (depends on the OpenGL driver, actually), -gl -d will cause the driver to render into a back buffer, which is then blitted into the window. No h/w pageflipping that is.

Actually, I am pretty sure it’s a bug in SDL. I’ll check wheter it works or not in linux.

It looks more like a flaky driver to me. Never seen it anywhere with any SDL version…

Could the driver be trying to be smart about double buffering in some way that could confuse SDL?

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn Thu, 20/06/2002 14:52:44 , CRV?ADER/KY wrote:

[…]
Actually, I am pretty sure it’s a bug in SDL. I’ll check wheter it works or not in linux.

That’s another problem… in linux my test app seems to always switch to software, even with SDL_GLSDL |
SDL_FULLSCREEN | SDL_HWSURFACE. In fact, without SDL_DOUBLEBUF, if I don’t call SDL_Flip nor SDL_UpdateRect I
can’t see anything, while I should.

I have:
Mandrake Linux 8.2
linux-2.4.18 (not the -mdk one) with enabled "matrox video cards"
XFree 4.2.0 hardware accelerated, as it comes with the distribution.

It looks more like a flaky driver to me. Never seen it anywhere with any SDL version…

Could the driver be trying to be smart about double buffering in some way that could confuse SDL?

It’s the latest (6.82.016 win98) driver from Matrox, that usually delivers high quality drivers. I’ve also got
DirectX 8.1.

[…]
Actually, I am pretty sure it’s a bug in SDL. I’ll check wheter it works or not in linux.

That’s another problem… in linux my test app seems to always switch to software, even with SDL_GLSDL |
SDL_FULLSCREEN | SDL_HWSURFACE.
In fact, without SDL_DOUBLEBUF, if I don’t call SDL_Flip nor SDL_UpdateRect I
can’t see anything, while I should.

That’s interesting… On my systems, regardless of OS, using GLSDL in single buffer mode is the only way to avoid the shadow surface - and it doesn’t matter if I’m using fullscreen mode or not; rendering is simply done directly to the screen. (Which results in terrible flickering, of course.)

Either way, doesn’t SDL report that you’re in software/shadow surface mode? (Flags should be set accordingly.)

No matter what target you’re using (glSDL included), you should never assume that you actually get a pure single buffered display, just because you ask for it. On most targets, it’s just not possible to do.

I have:
Mandrake Linux 8.2
linux-2.4.18 (not the -mdk one) with enabled "matrox video cards"
XFree 4.2.0 hardware accelerated, as it comes with the distribution.

It looks more like a flaky driver to me. Never seen it anywhere with any SDL version…

Could the driver be trying to be smart about double buffering in some way that could confuse SDL?

It’s the latest (6.82.016 win98) driver from Matrox, that usually delivers high quality drivers. I’ve also got
DirectX 8.1.

Well, Matrox usually make solid stuff, but every driver I’ve tried so far for the G400 has contained one or two more or less annoying bugs. (Apart from that total lack of support for multiple contexts, that is.)

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn Thu, 20/06/2002 18:25:57 , CRV?ADER/KY wrote: