gnash-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-dev] Vblank sync and double buffering


From: Michael McTernan
Subject: [Gnash-dev] Vblank sync and double buffering
Date: Tue, 26 Aug 2008 17:17:28 +0100

Hi,

I've been trying to use gnash with the openGL renderer to get some smooth
graphics.  I managed to do this building 0.8.3 from source with some changes
to fix some problems I found on the way:

1) GtkGlExtGlue::init() may fail to get a double buffered context.

This function first attempts to get a context with 
GDK_GL_MODE_RGB | GDK_GL_MODE_STENCIL | GDK_GL_MODE_DOUBLE |
GDK_GL_MODE_ACCUM.  If this fails (which it does for my Radeon based setup)
it goes on to get a context with just GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH.
The problem here is that the render_handler_ogl::end_display() clears then
redraws the screen *8* times in a row leading to really bad flickering and
tearing.   It's trying to do antialiasing via the accumulation buffer, but
since we don't have one and only a single buffer this just adds visual
discomfort.

As it happens, I found that I could get a context with GDK_GL_MODE_RGB |
GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE, so went with this and disable the
anti-aliasing attempt in end_display() leading the much improved graphics
but still tearing due to a lack of vsync/vblank sync.

It would probably be better if GtkGlExtGlue::init() tried a display with
double buffering but without the accumulation buffer first, and if
end_display() also didn't attempt anti-aliasing if the accumulation buffer
is absent.

2) GtkGlExtGlue::render() doesn't vsync.

I'm not sure why gdk_gl_drawable_swap_buffers() doesn't wait for a vsync,
but it doesn't under my setup.  I forced vsync on using driconf and this
verifiably works for GL based apps (e.g. glxgears FPS=60), but isn't doing
it for gnash.  I suspect a GLX pixmap is being used and preventing direct
rendering and hence sync, but not sure.  In anycase, I modified the function
to use gdk_gl_glXWaitVideoSyncSGI():

void
GtkGlExtGlue::render()
{
    static GdkGLProc wvs = gdk_gl_get_glXWaitVideoSyncSGI();

    //    GNASH_REPORT_FUNCTION;
    GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (_drawing_area);
    if (gdk_gl_drawable_is_double_buffered (gldrawable)) {
        unsigned int a = 0;

        if(wvs)
        {
            gdk_gl_glXWaitVideoSyncSGI(wvs, 2, 0, &a);
            gdk_gl_glXWaitVideoSyncSGI(wvs, 2, 1, &a);
        }

        gdk_gl_drawable_swap_buffers (gldrawable);
    } else {
      glFlush();
    }
}

Waiting for 2 vsyncs can be avoided if gdk_gl_glXGetVideoSyncSGI() were also
used to first get the count then wait for it to change, but this illustrates
the method.

So I've now got some really smooth flash animations running under Gnash
without flickering or tearing.  As a 'proof' that the vsync is working I got
a friend to make a flash animation consisting of a black then white screen
rapidly flickering.  This now appears as a shimmering grey box on the
display, where as previously it was broken by various horizontal bands.

Regards,

Mike









reply via email to

[Prev in Thread] Current Thread [Next in Thread]