SDL_Flip() - what's wrong?

Hi!

I want to use SDL_Flip with SDL on hardware that supports double buffer.
I wrote small test program (source below) and after running it
in full screen and SDL_DOUBLEBUF (test -full -flip) i see strange effect:
My rectangle moves on the screen with very huge steps. It suddenly disappears
and then appears in the other part of the screen.
After disabling DOUBLEBUF i see normal diagonal movement by 2 points per frame.
Would you mind telling me what i am doing wrong?

Usage:
flip_test -full -flip -> fullscreen and double buffer flipping (if supported)
flip_test -> windowed test without double buffer flipping.

After running ‘flip_test -full -flip’ i got output that proves i have
hardware flipping.

Here is my test source code (flip_test.cpp):-----------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include “SDL.h”

const int mainl=1024;
const int mainh=768;

SDL_Surface *mainw;
Uint32 wcolor, bcolor;

void flip_test(bool hw_accel)
{
int x=0, y=0, step=2;
SDL_Event event;
SDL_Rect rect[2];

rect[0].x=x;
rect[0].y=y;
rect[0].w=100;
rect[0].h=100;
rect[1]=rect[0];

while(1)
{
rect[1]=rect[0];
SDL_FillRect(mainw, rect, bcolor);

rect[0].x=x;
rect[0].y=y;
rect[0].w=100;
rect[0].h=100;

SDL_FillRect(mainw, rect, wcolor);
SDL_UpdateRects(mainw, 2, rect);

SDL_Flip(mainw);

//Moving rectangle
x+=step;y+=step;
if(x<0 || y<0)
{
    x=0;y=0;
    step=-step;
}
if(y+rect[0].h>=mainh)
{
    x-=step;
    y-=step;
    step=-step;
}

if(SDL_PollEvent(&event) && 
   (event.type==SDL_QUIT || event.type==SDL_KEYDOWN))
    return;
SDL_Delay(10);
}

}

int main(int argc, char** argv)
{
int i;
if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 )
{
fprintf(stderr, “Unable to init SDL: %s\n”, SDL_GetError());
return 1;
}

Uint32 flags=0, bpp=16;
const SDL_VideoInfo *nfo;

for(i=1;i<argc;i++)
{
if(strcmp(argv[i], "-full")==0)
{
    flags|=SDL_FULLSCREEN;
    continue;
}
if(strcmp(argv[i], "-flip")==0)
{
    flags|=SDL_DOUBLEBUF;
    break;
}
if(strcmp(argv[i], "-any")==0)
{
    flags|=SDL_ANYFORMAT;
    break;
}
if(strcmp(argv[i], "-hw")==0)
{
    flags|=SDL_HWSURFACE;
    break;
}
if(strcmp(argv[i], "-32")==0)
{
    bpp=32;
    break;
}
if(strcmp(argv[i], "-16")==0)
{
    bpp=16;
    break;
}
if(strcmp(argv[i], "-8")==0)
{
    bpp=8;
    break;
}	
}

nfo=SDL_GetVideoInfo();

fprintf(stderr, "Hardware video acceleration is %s supported\n",
       nfo->hw_available ? "" : "NOT");

mainw = SDL_SetVideoMode(mainl, mainh, bpp, 
		     flags);
if( mainw == 0 ) 
{
    fprintf(stderr, "Unable to set %dx%dx%d video: %s\n",mainl, mainh, bpp, 
	SDL_GetError());
    SDL_Quit();
return 1;
}
SDL_WM_SetCaption("FlipTest v 0.0.5", "");
fprintf(stderr,"VIDEO_INIT: Set %dx%dx%d video mode\n", 
       mainl, mainh, mainw->format->BitsPerPixel);


wcolor=SDL_MapRGB(mainw->format, 205, 220, 240);
bcolor=SDL_MapRGB(mainw->format,   0,   0,   0);

flip_test(nfo->hw_available);

SDL_Quit();
return 0;

}


Best regards,
Leo
Solvo Ltd.
St.Petersburg, Russia

I had the same problem. I don’t know why it is happening, but placing
SDL_Flip() after the SDL_Delay() solved it.

It interesting that it only happens on faster machines…?–
Milan Babuskov
http://njam.sourceforge.net

“Leonid V. Khramov” writes:

SDL_UpdateRects(mainw, 2, rect);

SDL_Flip(mainw);

Remove the SDL_UpdateRects - that shouldn’t be used when you use
double buffering (the purpose of SDL_UpdateRects is to copy the screen
surface from system memory to the graphics card).–
[ Below is a random fortune, which is unrelated to the above message. ]
Dr. Jekyll had something to Hyde.

Leonid V. Khramov wrote:

I’ve seen that a guy already told you not to use SDL_UpdateRects, but
there is another potential problem in this code, when you use double
buffering you have TWO surfaces, so when you remove the rectangle from
the surface you should remember its position “2 cycles ago” (you need 3
SDL_Rects to remember those coords).

Beside this you should also remember that most platforms when doing
hardware double buffering also sync the swap with vertical blank, so
your SDL_Delay() can make movement not smooth as it should be. You
should instead make the “step” variable based on the SDL_GetTicks()
difference between two frames.

Bye,
Gabry