Page 1 of 1
Screen tearing: ClearFrameBuffer() and VSync
Posted: Sat Feb 20, 2010 5:48 pm
by Lin
I'm programming the Wii. I'm trying to draw a 10-pixel-wide frame on the border of the screen. The top of the frame does not appear until I exit, where the last frame stays on the screen for a second before the launcher reappears. About 70 rows from the top of the screen are missing.
My hypothesis is that part of the frame buffer is getting cleared before the buffer is actually displayed. I don't know why my code would produce this behavior. It's generally as follows.
Code: Select all
// initialization stuff from template.c, including initializing rmode and xfb pointers
while (1)
{
// get WPAD buttons, WPAD_IR structure, exit if home is pressed
VIDEO_ClearFrameBuffer(rmode, xfb, COLOR_BLACK);
drawBorder(); // a function that loops through four sections of the frame buffer, setting individual pixels
VIDEO_Flush();
VIDEO_WaitVSync();
}
I tried adding a second VIDEO_WaitVSync() to the end of the while loop. This made the top of the frame visible, but it flickered.
Any ideas? Is there a better way to synchronize internal frames with the display?
Re: Screen tearing: ClearFrameBuffer() and VSync
Posted: Sun Feb 21, 2010 6:13 pm
by Lin
So, I learned about double buffering yesterday, and this solves the problem (surprise surprise). I still want to know why the problem occurred in the first place, but it's probably to do with the VSync timing system that's deeper within libogc than I want to dig at this time.
For any interested parties with a similar problem, double buffering involves initializing two frame buffers. At any time one is set to be displayed and the other is being modified. On each frame cycle you copy the "display" buffer to the screen, modify the "background" buffer, and then switch the roles of the buffers: once the "background" buffer is modified it is ready to be displayed, so it becomes the "display" buffer, and once the "display" buffer is copied over it becomes the new "background" buffer.
My code now basically looks like this. Its double buffering stuff is based on the sprites example code from devkitPro, so look at that for details.
Code: Select all
// initialization stuff from template.c, including initializing rmode and xfb pointer array
while (1)
{
// get WPAD buttons, WPAD_IR structure, exit if home is pressed
VIDEO_ClearFrameBuffer(rmode, xfb[xfb_index], COLOR_BLACK);
drawBorder(); // a function that loops through four sections of the frame buffer, setting individual pixels
VIDEO_SetNextFramebuffer(xfb[xfb_index])
VIDEO_Flush();
VIDEO_WaitVSync();
xfb_index ^= 1; // toggle active frame buffer
}
Re: Screen tearing: ClearFrameBuffer() and VSync
Posted: Wed Feb 24, 2010 6:58 pm
by Izhido
I actually have a question regarding that border you implemented.
Not everyone has LCD or Plasma TVs, or a 480p cable for it; meaning, not everyone will be able to see a 10 pix border around the screen, since many TVs actually aren't able to show anything in that area (mine, for instance, doesn't show the top/bottom 30 rows of pixels, and approx. 5 left/right "columns" of them). Do you have anything planned in your app when that happens?
Re: Screen tearing: ClearFrameBuffer() and VSync
Posted: Sat Mar 06, 2010 12:54 am
by Lin
Hey, sorry for the delay.
Even my LCD television doesn't scan exactly as you'd expect. It won't be much of a problem for me, since I'm just making a tic-tac-toe game. I suppose I could buffer everything by 50 blank pixels from the edge. Otherwise I don't have a good answer.
Also, I realized that my ramblings above were about "page-flipping," which is not the same as "double buffering" even though I used that term.
Re: Screen tearing: ClearFrameBuffer() and VSync
Posted: Fri Aug 13, 2010 7:47 pm
by DeeKay
Code: Select all
code snippet:
...
VIDEO_Flush();
VIDEO_WaitVSync();
....
Do not know if it's true for the Wii but in my opinion these two are in the wrong order. You should wait for the Vsync before you flush (draw on screen). It's all to do with timing.
That is why you would first draw in another region of memory before showing on screen (page flipping) because there isn't enough time to (realtime draw and show on screen. That's the main cause for tearing. Because you draw out-of-sync with the screen.
The border issue explained above has to do with the so called "safe area" of the screen where safe area means the part that is actually displayed. On some TV-sets some(differs from brand to brand) of the border is "clipped" off screen. Don't know the real reason for that though.
Hope this explains a bit more...
Greetz DeeKay