Double buffering waitretrace and flickering

Ok I am not sure what I am doing wrong. I am setting up a 640x480 fullscreen
mode in X with double buffering. Basically I am setting up another surface
64x64 and blitting it to the screen. I am using double buffering so my basic
loop goes something like.

-fill screen rectangle with black
(I know this is a slow way of earasing but
I am just using it to test this.)

-blit surface to screen
-flip buffers

I am getting lots of flicker for some reason in fullscreen mode. After
checking the return of setting video mode I see that the double buffering and
hw flags are set (I am running under root using DGA). Is there any reason why
this would flicker? It flickers whether I am moving the sprite arround or if it
is just sitting there. I am not framerate limmiting at all so its going really
fast… Is this a problem?? The only other thing I can think of is that my
rectangle filling is not really doing it to the back buffer but to screen? How
do you make sure that you are writing to the back buffer? Anyway I don’t see
how it could flicker… If I draw to a back buffer it shouldn’t matter how slow
fill rectangle and blitting is. The only thing I can think of is that
SDL_flip isn’t doing a wait for vertical retrace?? Any ideas anyone??

are you drawing to the back buffer or to the screen. If you are drawing to
the screen you will still get the screen tearing as you are not wating for
the vsync of the monitor. you need to do all your work to the back buffer
and once that is complete you then flip the surface to display the contents.

hope this helps.

Michael> ----- Original Message -----

From: dtabuenc@cs.ucr.edu (Daniel Tabuenca)
To: sdl at surfnetcity.com.au
Date: Wednesday, 18 August 1999 17:10
Subject: [SDL] Double buffering waitretrace and flickering

Ok I am not sure what I am doing wrong. I am setting up a 640x480
fullscreen
mode in X with double buffering. Basically I am setting up another surface
64x64 and blitting it to the screen. I am using double buffering so my
basic
loop goes something like.

-fill screen rectangle with black
(I know this is a slow way of earasing but
I am just using it to test this.)

-blit surface to screen
-flip buffers

I am getting lots of flicker for some reason in fullscreen mode. After
checking the return of setting video mode I see that the double buffering
and
hw flags are set (I am running under root using DGA). Is there any reason
why
this would flicker? It flickers whether I am moving the sprite arround or
if it
is just sitting there. I am not framerate limmiting at all so its going
really
fast… Is this a problem?? The only other thing I can think of is that my
rectangle filling is not really doing it to the back buffer but to screen?
How
do you make sure that you are writing to the back buffer? Anyway I don’t
see
how it could flicker… If I draw to a back buffer it shouldn’t matter how
slow
fill rectangle and blitting is. The only thing I can think of is that
SDL_flip isn’t doing a wait for vertical retrace?? Any ideas anyone??

Perhaps I am totally clueless (or just used to opengl) but I was under
the impression that all writes were to the backbuffer. If not How do
you write to the backbuffer? I am just writing to the surface returned
by SDL_SetVideoMode. How do I reach or write to that back buffer?On 18 Aug, Michael Lunnay wrote:

are you drawing to the back buffer or to the screen. If you are drawing to
the screen you will still get the screen tearing as you are not wating for
the vsync of the monitor. you need to do all your work to the back buffer
and once that is complete you then flip the surface to display the contents.

hope this helps.

Hi,

on Mit, 18 Aug 1999 dtabuenc at cs.ucr.edu wrote:

Perhaps I am totally clueless (or just used to opengl) but I was under
the impression that all writes were to the backbuffer. If not How do
you write to the backbuffer? I am just writing to the surface returned
by SDL_SetVideoMode. How do I reach or write to that back buffer?

are you drawing to the back buffer or to the screen. If you are drawing to
the screen you will still get the screen tearing as you are not wating for
the vsync of the monitor. you need to do all your work to the back buffer
and once that is complete you then flip the surface to display the contents.

hope this helps.

to my knowledge you only have access to the backbuffer.
When using double buffering you should test the return value of
SDL_SetVideoMode in order to check if you have really a double buffer.
As far as I know SDL_Flip() waits to vsync, the one possible reason for the
flickering might be, that your back- and frontbuffer are not in sync, meaning,
they contain different content.

hope this help, somehow.>On 18 Aug, Michael Lunnay wrote:


Karsten-O. Laux
klaux at student.uni-kl.de
http://www.rhrk.uni-kl.de/~klaux

to my knowledge you only have access to the backbuffer.
When using double buffering you should test the return value of
SDL_SetVideoMode in order to check if you have really a double buffer.
As far as I know SDL_Flip() waits to vsync, the one possible reason for the
flickering might be, that your back- and frontbuffer are not in sync, meaning,
they contain different content.

I believe this is correct. Usually the cause of flickering when double
buffering is set up is that the two video pages have different contents.
When using double-buffering, you have to remember that after the flip,
the contents of the new buffer are the screen contents from the previous
frame. This is ONLY true if the SDL_DOUBLEBUF flag is really set in the
screen surface after you call SDL_SetVideoMode().

-Sam Lantinga				(slouken at devolution.com)

Lead Programmer, Loki Entertainment Software–
“Any sufficiently advanced bug is indistinguishable from a feature”
– Rich Kulawiec

I believe this is correct. Usually the cause of flickering when double
buffering is set up is that the two video pages have different contents.
When using double-buffering, you have to remember that after the flip,
the contents of the new buffer are the screen contents from the previous
frame. This is ONLY true if the SDL_DOUBLEBUF flag is really set in the
screen surface after you call SDL_SetVideoMode().

-Sam Lantinga (slouken at devolution.com)
Yeah… But did you see what I am doing? I am clearing to black with
SDL_FillRect, then I do a blit to the surface and then I do
SDL_flip(screen) then rinse and repeat. Screen is the surface which I did
verify has the SDL_DOUBLEBUF bit on. So since I am clearing the buffer
completely before blitting again it still flickers, and I am not even
animating anything at this point. It looks as though the flip is not doing
a wait for retrace… I can’t think how else I can get flicker since I use
double buffering, clear the entire backbuffer and blit one single 64x64
image onto it then flip.

What about locking the screen, then draw your stuff, then unlock and flip
the buffer.

That might work.On Wed, 18 Aug 1999 dtabuenc at cs.ucr.edu wrote:

Perhaps I am totally clueless (or just used to opengl) but I was under
the impression that all writes were to the backbuffer. If not How do
you write to the backbuffer? I am just writing to the surface returned
by SDL_SetVideoMode. How do I reach or write to that back buffer?

On 18 Aug, Michael Lunnay wrote:

are you drawing to the back buffer or to the screen. If you are drawing to
the screen you will still get the screen tearing as you are not wating for
the vsync of the monitor. you need to do all your work to the back buffer
and once that is complete you then flip the surface to display the contents.

hope this helps.

Did you initialize SDL with SDL_DOUBLEBUFFER or SDL_DOUBLEBUF? (i’m not sure which
is is right now) but you have to do it to have access to the back buffer, right?

I don’t mean to be rude but do people actually read the body of the
message or just the subject? I’ve been getting responses that tell me
to enable double buffering… I already said that I am checking the
return and verifying that I am in fact double buffering.The functions
UI am using are SDL or Fill_Rect to clear the screen to black, then
SDL_BlitSurface or whatever the blitting function is called to blit a
64x64 image to the screen (which is 640x480x16). Then I just use
SDL_Flip to swap the buffers. I do this over and over in a tight loop.
This is not part of anything I am just using it to test so the 3
functions are in a tight loop. Also I read that I wasn’t supposed to
use SDL_BlitSurface on a locked surface. Hmm… Just occoured to me.
does that mean you can use it on a surface that requires locking? I
guess not because then you would never be able to blit ANYTHING to the
screen. Again the only thing I can figure out is that it is not waiting
for a retrace. Can I just post the code so you can figure it out? It’s
pretty small…

Ok here is the code I promissed. It’s pretty straight forward so I am
either making a really silly mistake or something is not right.
Basically I even took away the image blit and I am just filling a
rectangle now. It runs fine in windowed mode (single buffered) when
doing it in DGA mode under root horrible flicker! Anyone know where
this flicker is comming from?

#include <SDL/SDL.h>
#include <iostream.h>
#include <stdlib.h>
int main()
{
SDL_Surface *screen;
SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);
screen=SDL_SetVideoMode(640,480,16,SDL_FULLSCREEN|SDL_DOUBLEBUF);
if(screen->flags&&SDL_DOUBLEBUF)
cout << “Using Double Buffering\n”;
else
cout << “Using a single buffer\n”;
static Uint32 black=SDL_MapRGB(screen->format,0,0,0);
static Uint32 blue= SDL_MapRGB(screen->format,0,0,255);;
SDL_Rect dstrect;
dstrect.x = (640/2-16);
dstrect.y = (480-64);
dstrect.w = 64;
dstrect.h = 64;
SDL_Event event;
while(true)
{
SDL_FillRect(screen, 0,black);//Clear whole buffer
SDL_FillRect(screen,&dstrect, blue); //Fill in little blue rect on bottom
SDL_Flip(screen);
SDL_PollEvent(&event);
if(event.type == SDL_KEYDOWN)
exit(0);
}
}

on Don, 19 Aug 1999 dtabuenc at cs.ucr.edu wrote:

Ok here is the code I promissed. It’s pretty straight forward so I am
either making a really silly mistake or something is not right.
Basically I even took away the image blit and I am just filling a
rectangle now. It runs fine in windowed mode (single buffered) when
doing it in DGA mode under root horrible flicker! Anyone know where
this flicker is comming from?

#include <SDL/SDL.h>
#include <iostream.h>
#include <stdlib.h>
int main()
{
SDL_Surface *screen;
SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);
screen=SDL_SetVideoMode(640,480,16,SDL_FULLSCREEN|SDL_DOUBLEBUF);

if(screen->flags&&SDL_DOUBLEBUF)
<<<<<<< this should be

if(screen->flags & SDL_DOUBLEBUF)

(this is one of my favorite faults … I can’t code a 100 lines without messing
"&&" and “&”) your version returns always true, since both values are unequal 0
(meaning true in c). So there might be still the chance, that you are in fact
not running a doublebuffer.> cout << “Using Double Buffering\n”;

else
cout << “Using a single buffer\n”;
static Uint32 black=SDL_MapRGB(screen->format,0,0,0);
static Uint32 blue= SDL_MapRGB(screen->format,0,0,255);;
SDL_Rect dstrect;
dstrect.x = (640/2-16);
dstrect.y = (480-64);
dstrect.w = 64;
dstrect.h = 64;
SDL_Event event;
while(true)
{
SDL_FillRect(screen, 0,black);//Clear whole buffer
SDL_FillRect(screen,&dstrect, blue); //Fill in little blue rect on bottom
SDL_Flip(screen);
SDL_PollEvent(&event);
if(event.type == SDL_KEYDOWN)
exit(0);
}
}

Karsten-O. Laux
klaux at student.uni-kl.de
http://www.rhrk.uni-kl.de/~klaux

(this is one of my favorite faults … I can’t code a 100 lines without messing
"&&" and “&”) your version returns always true, since both values are unequal 0
(meaning true in c). So there might be still the chance, that you are in fact
not running a doublebuff

Ok, dumb mistake but it still is flickering. I fixed that and I still
know it is running doublebuffered. Actually I am quite sure. I am
beginning to think it is something weird with my video (VOODOO 3). I
don’t know. I just can’t think of anything else.

Hmm, I don’t have any idea. It should work properly.
The DGA driver does wait for vertical retrace on the flip.
Err, actually it waits for vertical retrace on the lock.
You are locking the buffer, right?

Hmm… where would I lock thje buffer? Right before the flip? The blit
documentation says I shouldn’t blit to a locked buffer… is this correct?
Also the flip documentation says that it waits for a vertical refresh so
you are saying this is not correct?On Wed, 18 Aug 1999, Sam Lantinga wrote:

John Garrison wrote:

Perhaps I am totally clueless (or just used to opengl) but I was under
the impression that all writes were to the backbuffer. If not How do
you write to the backbuffer? I am just writing to the surface returned
by SDL_SetVideoMode. How do I reach or write to that back buffer?

Did you initialize SDL with SDL_DOUBLEBUFFER or SDL_DOUBLEBUF? (i’m not sure which
is is right now) but you have to do it to have access to the back buffer, right?

I think that’s it! At least on my computer SDL_DOUBLEBUF doesn’t work,
but SDL_DOUBLEBUFFER does!

Bye, Karl> > On Wed, 18 Aug 1999 dtabuenc at cs.ucr.edu wrote:

WHAT??? SDL_DOUBLEBUFFER is not even defined in the header files… Only
SDL_DOUBLEBUF… I am using SDL0.10 maybe it’s different?> I think that’s it! At least on my computer SDL_DOUBLEBUF doesn’t work,

but SDL_DOUBLEBUFFER does!

Bye, Karl

Did you initialize SDL with SDL_DOUBLEBUFFER or SDL_DOUBLEBUF? (i’m not sure which
is is right now) but you have to do it to have access to the back buffer, right?> On Wed, 18 Aug 1999 dtabuenc at cs.ucr.edu wrote:

Perhaps I am totally clueless (or just used to opengl) but I was under
the impression that all writes were to the backbuffer. If not How do
you write to the backbuffer? I am just writing to the surface returned
by SDL_SetVideoMode. How do I reach or write to that back buffer?

Just to add another data point on this:

I’m using an old ATI Rage card, using the XFree86-Mach64-3.3.2-8
driver. I’m using a 1024x768 16bpp visual as my default.

The plasma demo clearly shows tearing, regardless of the options
specified, when run as root and fullscreen.

I’ve doctored up the originally posted demo to print the results of
various queries; apparently double buffering isn’t getting honored on my
platform:

hw_available: 1
wm_available: 1
UnusedBits1: 0
UnusedBits2: 0
blit_hw: 0
blit_hw_CC: 0
blit_hw_A: 0
blit_sw: 0
blit_sw_CC: 0
blit_sw_A: 0
blit_fill: 0
UnusedBits3: 0
video_mem: 2046K
BitsPerPixel: 16

screen flags: 80000001
w: 640
h: 480
pitch: 2048
clip_minx: 0
clip_maxx: 639
clip_miny: 0
clip_maxy: 479

Using a single buffer
Must lock surface

Could someone out there please check this, let me know what the obvious
mistake is, or run it on a different platform to see whether this in
fact works?

Thanks!----------------------------------------------------------------

/*
*

  • $Author: gary $
  • $Revision: 1.1 $
  • $Log: sdldbuftest.c,v $
  • Revision 1.1 1999/08/19 22:07:27 gary
  • Initial revision

*/
#include <SDL.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
static Uint32 black, blue ;
SDL_Surface *screen;
SDL_Rect dstrect;
SDL_Event event;
SDL_VideoInfo const *vinfo ;

if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
	fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
	exit(2);
}

vinfo = SDL_GetVideoInfo() ;

printf ("hw_available:  %d\n", vinfo->hw_available) ;
printf ("wm_available:  %d\n", vinfo->wm_available) ;
printf ("UnusedBits1:   %d\n", vinfo->UnusedBits1) ;
printf ("UnusedBits2:   %d\n", vinfo->UnusedBits2) ;
printf ("blit_hw:       %d\n", vinfo->blit_hw) ;
printf ("blit_hw_CC:    %d\n", vinfo->blit_hw_CC) ;
printf ("blit_hw_A:     %d\n", vinfo->blit_hw_A) ;
printf ("blit_sw:       %d\n", vinfo->blit_sw) ;
printf ("blit_sw_CC:    %d\n", vinfo->blit_sw_CC) ;
printf ("blit_sw_A:     %d\n", vinfo->blit_sw_A) ;
printf ("blit_fill:     %d\n", vinfo->blit_fill) ;
printf ("UnusedBits3:   %d\n", vinfo->UnusedBits3) ;
printf ("video_mem:     %dK\n", vinfo->video_mem) ;
printf ("BitsPerPixel:  %d\n\n", vinfo->vfmt->BitsPerPixel) ;

atexit(SDL_Quit);

screen = SDL_SetVideoMode(640, 480, 16, 
		SDL_DOUBLEBUF|SDL_HWSURFACE|SDL_FULLSCREEN);
if ( screen == NULL ) {
	fprintf(stderr, "Couldn't set 640x480 video mode: %s\n",
		SDL_GetError());
	exit(2);
}
printf ("screen flags: %8X\n", screen->flags) ;
printf ("w:            %d\n", screen->w) ;
printf ("h:            %d\n", screen->h) ;
printf ("pitch:        %d\n", screen->pitch) ;
printf ("clip_minx:    %d\n", screen->clip_minx) ;
printf ("clip_maxx:    %d\n", screen->clip_maxx) ;
printf ("clip_miny:    %d\n", screen->clip_miny) ;
printf ("clip_maxy:    %d\n\n", screen->clip_maxy) ;


if(screen->flags & SDL_DOUBLEBUF)
	printf("Using Double Buffering\n") ;
else
	printf("Using a single buffer\n") ;

if (SDL_MUSTLOCK(screen))
	printf("Must lock surface\n") ;
else
	printf("Don't need to lock surface\n") ;

black=SDL_MapRGB(screen->format,0,0,0);
blue= SDL_MapRGB(screen->format,0,0,255);;

dstrect.x = (640/2-16);
dstrect.y = (480-64);
dstrect.w = 64;
dstrect.h = 64;

while(1)
{
	//SDL_LockSurface(screen);		
	SDL_FillRect(screen, 0,black);//Clear whole buffer
	SDL_FillRect(screen,&dstrect, blue); //Fill in little blue rect on

bottom
//SDL_UnlockSurface(screen);
SDL_Flip(screen);
SDL_PollEvent(&event);
if(event.type == SDL_KEYDOWN)
exit(0);
}
}

Gary Scillian @Gary_Scillian
"There’s a seeker born every minute." - Firesign Theatre

I compiled and tried the program. No tearing if run in a window, I
get tearing and flickering on the blue rectangle if I run as root un
full screen. It prints out the following information:
hw_available: 1
wm_available: 1
UnusedBits1: 0
UnusedBits2: 0
blit_hw: 0
blit_hw_CC: 0
blit_hw_A: 0
blit_sw: 0
blit_sw_CC: 0
blit_sw_A: 0
blit_fill: 0
UnusedBits3: 0
video_mem: 16256K
BitsPerPixel: 16

video memory unprotecting
screen flags: C0000001
w: 640
h: 480
pitch: 2048
clip_minx: 0
clip_maxx: 639
clip_miny: 0
clip_maxy: 479

Using Double Buffering
Must lock surface
video memory protecting
video memory protecting

My video board is a Riva TNT with NVidia’s accelerated GLX XF86_SVGA
server.

Hope this helps–
Dave

It is harder, but you can notice tearing even in a window.
It can be avoided if you slow down the movement of the plasma
to reduce the differencies of one frame to another.
When I wrote that demo it was intended to run at around
20 fps (on a 486 33 Mhz), and I was too lazy to implement timing.

What is happening is that the application is updating the screen
faster than the video refreshes it, so that the upper part of
the screen contains an older frame than the lower one, (or the
opposite), or that the screen refreshes itself when the video
memory is only half updated (this is expecially true in hw,
non double buffering mode).

I will hopefully reduce this problem soon.

-MicheleOn Fri, Aug 20, 1999 at 08:49:26PM -0700, Gary Scillian wrote:

Just to add another data point on this:

I’m using an old ATI Rage card, using the XFree86-Mach64-3.3.2-8
driver. I’m using a 1024x768 16bpp visual as my default.

The plasma demo clearly shows tearing, regardless of the options
specified, when run as root and fullscreen.