Sdl Screen Tearing Issue


EvilDragon said:
This is part of the code like I currently have changed it:

Code:
void vid_end()
{
	if (overlay)
	{
		SDL_UnlockYUVOverlay(overlay);
		if (fb.enabled)
			int arg = 0;
			ioctl(fbdev, FBIO_WAITFORVSYNC, &arg);
			SDL_DisplayYUVOverlay(overlay, &overlay_rect);
		return;
	}
	SDL_UnlockSurface(screen);
	if (fb.enabled)
	{
	  SDL_Flip(screen);
	}
}

That does lead to:

Code:
sys/sdl/sdl.c: In function 'vid_end':
sys/sdl/sdl.c:440: error: expected expression before 'int'
sys/sdl/sdl.c:441: error: 'arg' undeclared (first use in this function)
sys/sdl/sdl.c:441: error: (Each undeclared identifier is reported only once
sys/sdl/sdl.c:441: error: for each function it appears in.)
make: *** [sys/sdl/sdl.o] Error 1
Yes, because what you've actually written there is the same as:

Code:
if (fb.enabled) {
	int arg = 0; // arg is defined here
}
// arg is no longer defined here!
ioctl(fbdev, FBIO_WAITFORVSYNC, &arg);
SDL_DisplayYUVOverlay(overlay, &overlay_rect);
return;
You need the braces to "if" multiple statements.

If I do it like this:

Code:
void vid_end()
{
	if (overlay)
	{
		SDL_UnlockYUVOverlay(overlay);
		if (fb.enabled)
			ioctl(fbdev, FBIO_WAITFORVSYNC, 0);
			SDL_DisplayYUVOverlay(overlay, &overlay_rect);
		return;
	}
	SDL_UnlockSurface(screen);
	if (fb.enabled)
	{
	  SDL_Flip(screen);
	}
}

I get no errors, but no VSync either...
Putting this in front of SDL_Flip also doesn't work.
I guess SDL_Flip is not even used here - if I remove it, GnuBoy still works fine.
If I remove SDL_DisplayYUVOverlay(overlay, &overlay_rect); however, there's no video anymore... so I guess the WAITFORSYNC is okay before that?
The ioctl takes a pointer as an argument, so it probably won't work (unless address 0 happens to contain zero). Is it that SDL_Flip() isn't being called or that you just don't see any difference? Does fb.enabled evaluate to true? I'm not sure (would need to experiment) but it would probably be better to put the v-sync call right at the start of the vid_end() function.
 
Last edited by a moderator:
Farox said:
I'm not an expert...but i think you could place it at the end of blitting function...inside the last routine
Code:
VIDEO_MODE video_yv12={
  init_video_yv12,
  reinit_video_yuv,
  //  draw_screen_col_yv12,
  //  draw_screen_wb_yv12,
  //  NULL,
  blit_screen_yv12,
  blit_sgb_mask_yv12

  // insert call to fbdev here !!!!!!

  //  set_pal_yv12,
  //draw_message_yv12,
  //NULL
};
Yikes - that's not a function, it's a structure ;-)

Pickle said:
if the blit is drawing direct to the screen then wouldnt you want to put the vsync right before the blit?
Yep: wait for sync, then draw to the screen.

I remember I had trouble understanding why to start with, but you just need to think about what you're actually doing. What we're referring to as "v-sync" is waiting for the start of the vertical blanking interval, which is the period between drawing the last line of the current frame and the first line of the next. Nothing actually changes one the screen during this period, so you want to start drawing when it starts and make sure you're done before it finishes. Then, when the blanking period is over, your frame gets displayed in its entirety in one "scan" of the screen.
 
Last edited by a moderator:
dgame said:
So here an extract of what I tried:
while ((ioctl(fbdev, FBIO_WAITFORVSYNC, &arg)) != 1) {;}
SDL_Flip(gb_screen);
Well, ioctl(fbdev, FBIO_WAITFORVSYNC, &arg) seems to always be != 1. Thus it's no surprise your screen stays black. (Just tried that myself.)

Simply change your code like this:

while ((ioctl(fbdev, FBIO_WAITFORVSYNC, &arg)) != 1);

Then it should work.
 
Last edited by a moderator:
I tried that John4p and it compiles but has no effect on the screen tearing.

What is " ioctl(fbdev, FBIO_WAITFORVSYNC, &arg) " supposed to do before SDL_DisplayYUVOverlay(overlay, &overlay_rect)?

It seems like it would just execute and proceed to the blit? Can ioctl(fbdev, FBIO_WAITFORVSYNC, &arg) stop/delay the blit?
 
doublebeta said:
Place braces after that if. It should work without them but...try it with them.
like this.

Okay, that compiled GnuBoy. But still no VSync :(

SteveM said:
The ioctl takes a pointer as an argument, so it probably won't work (unless address 0 happens to contain zero). Is it that SDL_Flip() isn't being called or that you just don't see any difference? Does fb.enabled evaluate to true? I'm not sure (would need to experiment) but it would probably be better to put the v-sync call right at the start of the vid_end() function.

Well, if I remove SDL_Flip(), GnuBoy still runs with video, etc.
It wouldn't do that... would it?

I'm pretty sure fb.enable evaluates to true - when I remove the SDL_DisplayYUVOverlay(overlay, &overlay_rect), GnuBoy doesn't show any video anymore.
As that call is within that if-function, fb.enabled should be true, right? :)
 
Last edited:
EvilDragon said:
doublebeta said:
Place braces after that if. It should work without them but...try it with them.
like this.

Okay, that compiled GnuBoy. But still no VSync :(

SteveM said:
The ioctl takes a pointer as an argument, so it probably won't work (unless address 0 happens to contain zero). Is it that SDL_Flip() isn't being called or that you just don't see any difference? Does fb.enabled evaluate to true? I'm not sure (would need to experiment) but it would probably be better to put the v-sync call right at the start of the vid_end() function.

Well, if I remove SDL_Flip(), GnuBoy still runs with video, etc.
It wouldn't do that... would it?

I'm pretty sure fb.enable evaluates to true - when I remove the SDL_DisplayYUVOverlay(overlay, &overlay_rect), GnuBoy doesn't show any video anymore.
As that call is within that if-function, fb.enabled should be true, right? :)

it probably is still working with without the SDL_Flip since the DoubleBuffering doesnt work with pandora SDL

Im trying to figure out how this ioctl works and i came across this EGL code by whynodd.
From this is appears ioctl should *wait* until its time to swap the buffer, so the while loop is not necessary.
Code:
int swapBuffers()
{
        if ( vsync )
        {
                int fd = open( "/dev/fb0" , O_RDWR );
                if( 0 < fd )
                {
                        int ret = 0;
                        ret = ioctl(fd, FBIO_WAITFORVSYNC, &ret );
                        if ( ret != 0 )
                        {
                                printf ("FBIO_WAITFORVSYNC failed!");
                        }
                }
                close(fd);
        }
        eglSwapBuffers( eglDisplay, eglSurface );
        if ( !testEGLError((char *) "eglSwapBuffers" ) )
        {
                return 0;
        }
        return 1;
}
 
Last edited by a moderator:
I think the above code is correct...
The wait for vsync shouldn't need a while loop.

For reference here is what I have in Penjin: http://code.google.com/p/penjin/source/browse/trunk/GFX.cpp#80
It gives vsync, but there appears to be tearing on clearing the screen to a colour in SDL... which I'm going to try and fix when I have some time...
 
dgame said:
Can ioctl(fbdev, FBIO_WAITFORVSYNC, &arg) stop/delay the blit?
Yes, the function should wait until it gets the next vertical blank.


I don't use SDL_DisplayYUVOverlay but I don't see why this ioctl wouldn't work with it, too. Maybe it's considerably slower than SDL_Flip/SDL_UpdateRect?
 
Last edited by a moderator:
john4p said:
dgame said:
Can ioctl(fbdev, FBIO_WAITFORVSYNC, &arg) stop/delay the blit?
Yes, the function should wait until it gets the next vertical blank.


I don't use SDL_DisplayYUVOverlay but I don't see why this ioctl wouldn't work with it, too. Maybe it's considerably slower than SDL_Flip/SDL_UpdateRect?

How have you done that in UAE4ALL?
If there's a way to replace SDL_DisplayYUVOverlay and make VSync work, I'll try it :)
 
Last edited:
EvilDragon said:
How have you done that in UAE4ALL?
If there's a way to replace SDL_DisplayYUVOverlay and make VSync work, I'll try it :)
Did it like this (in sdlgfx.cpp):

Code:
...
#ifdef PANDORA
#include <linux/fb.h>
#include <sys/ioctl.h>
#ifndef FBIO_WAITFORVSYNC
    #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
#endif
int fbdev = open("/dev/fb0", O_RDONLY);
int arg = 0;
#endif
...
...
...
void updatescreen(...)
{
...
    //wait for vsync
    arg = 0;
    ioctl(fbdev, FBIO_WAITFORVSYNC, &arg);
    #if defined(DOUBLEBUFFER)
	SDL_Flip(prSDLScreen);
    #else
	SDL_UpdateRect(prSDLScreen, 0, 0, 0, 0);
    #endif
...
}
So exactly like it's described in our official FAQ...
 
Last edited by a moderator:
Back
Top