OSDN Git Service

Don't drop subtitles when crossing PTS discontinuities by using buffer sequence numbe...
[handbrake-jp/handbrake-jp-git.git] / macosx / PictureGLView.mm
index 8df1990..611fb3a 100644 (file)
-/* $Id: PictureGLView.mm,v 1.3 2003/11/03 22:01:13 titer Exp $
+/* $Id: PictureGLView.mm,v 1.18 2005/08/01 15:10:44 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://handbrake.m0k.org/>.
    It may be used under the terms of the GNU General Public License. */
 
+#include <OpenGL/OpenGL.h>
 #include <OpenGL/gl.h>
+#include <OpenGL/glext.h>
 #include <math.h>
 
 #include "PictureGLView.h"
 
-#define PROUT 2.5
-
-/* XXX This file needs some serious cleaning XXX */
-
-GLuint    texture[2];
-float     rotation;
-float     translation;
-uint8_t * truc;
-
-@implementation HBPictureGLView
-
-- (void) SetHandle: (HBHandle*) handle
+static int GetAlignedSize( int size )
 {
-    fHandle = handle;
-}
-
-- (void) SetTitle: (HBTitle*) title
-{
-    fTitle = title;
-
-    /* This is needed as the view's size may have changed */
-    [self clearGLContext];
-    [self openGLContext];
-}
-
-- (void) ShowPicture: (int) index animate: (int) how
-{
-    if( fOldPicture ) free( fOldPicture );
-    fOldPicture = fPicture;
-
-    /* Get the picture */
-    uint8_t * tmp = HBGetPreview( fHandle, fTitle, index );
-
-    /* Make it be upside-down */
-    fPicture = (uint8_t*) malloc( 4 * ( fTitle->outWidthMax + 2 ) *
-                                  ( fTitle->outHeightMax + 2 ) );
-    uint8_t * in  = tmp;
-    uint8_t * out = fPicture +
-        4 * ( fTitle->outWidthMax + 2 ) * ( fTitle->outHeightMax + 1 );
-    for( int i = 0; i < fTitle->outHeightMax + 2; i++ )
-    {
-        memcpy( out, in, 4 * ( fTitle->outWidthMax + 2 ) );
-        in  += 4 * ( fTitle->outWidthMax + 2 );
-        out -= 4 * ( fTitle->outWidthMax + 2 );
-    }
-    free( tmp );
-
-    /* ARGB -> RGBA */
-    uint32_t * p = (uint32_t*) fPicture;
-    for( int i = 0;
-         i < ( fTitle->outHeightMax + 2 ) * ( fTitle->outWidthMax + 2 );
-         i++ )
-    {
-        *(p++) = ( ( (*p) & 0xff000000 ) >> 24 ) |
-                 ( ( (*p) & 0x00ff0000 ) <<  8 ) |
-                 ( ( (*p) & 0x0000ff00 ) <<  8 ) |
-                 ( ( (*p) & 0x000000ff ) <<  8 );
-    }
-
-    if( how == HB_ANIMATE_NONE )
+    int result = 1;
+    while( result < size )
     {
-        [self drawRect: [self bounds]];
-        return;
+        result *= 2;
     }
-
-    in  = fOldPicture;
-    out = truc;
-    for( int i = 0; i < fTitle->outHeightMax + 2; i++ )
-    {
-        memcpy( out, in, ( fTitle->outWidthMax + 2 ) * 4 );
-        in  += ( fTitle->outWidthMax + 2 ) * 4;
-        out += 1024 * 4;
-    }
-    glBindTexture( GL_TEXTURE_2D, texture[0] );
-    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 1024,
-                  1024, 0, GL_RGBA,
-                  GL_UNSIGNED_BYTE, truc );
-    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
-
-    in  = fPicture;
-    out = truc;
-    for( int i = 0; i < fTitle->outHeightMax + 2; i++ )
-    {
-        memcpy( out, in, ( fTitle->outWidthMax + 2 ) * 4 );
-        in  += ( fTitle->outWidthMax + 2 ) * 4;
-        out += 1024 * 4;
-    }
-    glBindTexture( GL_TEXTURE_2D, texture[1] );
-    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 1024,
-                 1024, 0, GL_RGBA,
-                 GL_UNSIGNED_BYTE, truc );
-    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
-
-    glEnable( GL_TEXTURE_2D );
-    glShadeModel( GL_SMOOTH );
-    glClearColor( 0.0f, 0.0f, 0.0f, 0.5f );
-    glClearDepth( 1.0f );
-    glEnable( GL_DEPTH_TEST );
-    glDepthFunc( GL_LEQUAL );
-    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
-
-#define ANIMATION_TIME  500000
-
-    rotation = 0.0;
-    float w = ( how == HB_ANIMATE_LEFT ) ? 1.0 : -1.0;
-    uint64_t date;
-    int64_t  wait;
-    for( ;; )
-    {
-        date = HBGetDate();
-        translation = - PROUT - cos( rotation * M_PI / 180 ) *
-                             ( 1 + w * tan( rotation * M_PI / 180 ) );
-
-        [self drawAnimation: how];
-
-        rotation += w;
-        if( w * rotation >= 90.0 )
-        {
-            break;
-        }
-
-        wait = ANIMATION_TIME / 90 - ( HBGetDate() - date );
-        if( wait > 0 )
-        {
-            HBSnooze( wait );
-        }
-    }
-
-    [self drawRect: [self bounds]];
+    return result;
 }
 
+@implementation HBPictureGLView
+
 - (id) initWithFrame: (NSRect) frame
 {
-    fHandle    = NULL;
-    fTitle      = NULL;
-    fPicture    = NULL;
-    fOldPicture = NULL;
+    fHasQE  = CGDisplayUsesOpenGLAcceleration( kCGDirectMainDisplay );
+    fTarget = fHasQE ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D;
 
+    fBuffers[0] = NULL;
+    fBuffers[1] = NULL;
+    fWidth      = 0;
+    fHeight     = 0;
+
+    fLastEffect = -1;
+    
     GLuint attribs[] =
     {
         NSOpenGLPFANoRecovery,
@@ -176,99 +62,368 @@ uint8_t * truc;
     [[self openGLContext] makeCurrentContext];
     [self reshape];
 
-    glGenTextures( 2, texture );
-    truc = (uint8_t*) malloc( 1024*1024*4 );
+    glGenTextures( 2, fTextures );
 
     return self;
 }
 
-/*
- * Resize ourself
- */
 - (void) reshape
 {
-   NSRect bounds;
+    NSRect bounds;
+    [[self openGLContext] update];
+    [[self openGLContext] makeCurrentContext];
+    bounds = [self bounds];
+    glViewport( 0, 0, (int) bounds.size.width,
+                (int) bounds.size.height );
+}
+
+- (void) drawRect: (NSRect) rect
+{
+    [[self openGLContext] makeCurrentContext];
+
+    glDisable( GL_DEPTH_TEST );
+    glDisable( GL_CULL_FACE );
+    glDisable( GL_BLEND );
 
-   [[self openGLContext] update];
-   bounds = [self bounds];
-   glViewport( 0, 0, (GLsizei) bounds.size.width,
-               (GLsizei) bounds.size.height );
+    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+    if( fBuffers[0] )
+    {
+        glMatrixMode( GL_PROJECTION );
+        glLoadIdentity();
+        glMatrixMode( GL_MODELVIEW );
+        glLoadIdentity();
+
+        glEnable( fTarget );
+        glBindTexture( fTarget, fTextures[0] );
+        glTexImage2D( fTarget, 0, GL_RGBA, fTexWidth, fTexHeight, 0,
+                      GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, fBuffers[0] );
+        glTexParameteri( fTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+        glTexParameteri( fTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+        glBegin( GL_QUADS );
+        glTexCoord2f( 0.0    , 0.0     ); glVertex2f( -1.0,  1.0 );
+        glTexCoord2f( 0.0    , fCoordY ); glVertex2f( -1.0, -1.0 );
+        glTexCoord2f( fCoordX, fCoordY ); glVertex2f(  1.0, -1.0 );
+        glTexCoord2f( fCoordX, 0.0     ); glVertex2f(  1.0,  1.0 );
+        glEnd();
+    }
+    [[self openGLContext] flushBuffer];
 }
 
-- (void) drawAnimation: (int) how
+#define FRUSTUM_NEAR   2.5
+#define FRUSTUM_FAR    20.0
+
+- (void) drawCube: (int) anim
 {
-   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-   glMatrixMode( GL_PROJECTION );
-   glLoadIdentity();
-   glFrustum( -1.0, 1.0, -1.0, 1.0, PROUT, 20.0 );
-   glMatrixMode( GL_MODELVIEW );
-   glLoadIdentity();
-   glTranslatef( 0.0, 0.0, translation );
-   glRotatef( rotation, 0.0, 1.0, 0.0 );
-
-   glEnable( GL_POLYGON_SMOOTH );
-   glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
-
-   glBindTexture( GL_TEXTURE_2D, texture[0] );
-
-   glBegin( GL_QUADS );
-   glTexCoord2f( 0.0, 0.0 );
-   glVertex3f( -1.0, -1.0,  1.0 );
-   glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024, 0.0 );
-   glVertex3f(  1.0, -1.0,  1.0 );
-   glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024,
-                 ( 2.0 + fTitle->outHeightMax ) / 1024 );
-   glVertex3f(  1.0,  1.0,  1.0 );
-   glTexCoord2f( 0.0, ( 2.0 + fTitle->outHeightMax ) / 1024 );
-   glVertex3f( -1.0,  1.0,  1.0 );
-   glEnd();
-
-   glBindTexture( GL_TEXTURE_2D, texture[1] );
-
-   glBegin( GL_QUADS );
-   if( how == HB_ANIMATE_RIGHT )
-   {
-       glTexCoord2f( 0.0, 0.0 );
-       glVertex3f(  1.0, -1.0,  1.0 );
-       glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024, 0.0 );
-       glVertex3f(  1.0, -1.0,  -1.0 );
-       glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024,
-                     ( 2.0 + fTitle->outHeightMax ) / 1024 );
-       glVertex3f(  1.0,  1.0,  -1.0 );
-       glTexCoord2f( 0.0, ( 2.0 + fTitle->outHeightMax ) / 1024 );
-       glVertex3f(  1.0,  1.0,  1.0 );
-   }
-   else
-   {
-       glTexCoord2f( 0.0, 0.0 );
-       glVertex3f(  -1.0, -1.0, -1.0 );
-       glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024, 0.0 );
-       glVertex3f(  -1.0, -1.0, 1.0 );
-       glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024,
-                     ( 2.0 + fTitle->outHeightMax ) / 1024 );
-       glVertex3f(  -1.0,  1.0, 1.0 );
-       glTexCoord2f( 0.0, ( 2.0 + fTitle->outHeightMax ) / 1024 );
-       glVertex3f(  -1.0,  1.0, -1.0 );
-   }
-   glEnd();
-
-   [[self openGLContext] flushBuffer];
+    uint64_t date;
+    float w, rotation, translation;
+    
+    w = ( anim & HB_ANIMATE_BACKWARD ) ? 1.0 : -1.0;
+
+    glEnable( GL_DEPTH_TEST );
+    glEnable( GL_CULL_FACE );
+    glDisable( GL_BLEND );
+
+    for( rotation = 0.0; w * rotation < 90.0;
+         rotation += w * 90 * 1000 / fAnimDuration / fFrameRate )
+    {
+        date = hb_get_date();
+        translation = - FRUSTUM_NEAR - cos( rotation * M_PI / 180 ) *
+            ( 1 + w * tan( rotation * M_PI / 180 ) );
+
+        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+        glMatrixMode( GL_PROJECTION );
+        glLoadIdentity();
+        glFrustum( -1.0, 1.0, -1.0, 1.0, FRUSTUM_NEAR, FRUSTUM_FAR );
+        glMatrixMode( GL_MODELVIEW );
+        glLoadIdentity();
+        glTranslatef( 0.0, 0.0, translation );
+        glRotatef( rotation, 0.0, 1.0, 0.0 );
+     
+        glBindTexture( fTarget, fTextures[0] );
+        glBegin( GL_QUADS );
+        glTexCoord2f( 0.0    , 0.0 );     glVertex3f( -1.0,  1.0, 1.0 );
+        glTexCoord2f( 0.0    , fCoordY ); glVertex3f( -1.0, -1.0, 1.0 );
+        glTexCoord2f( fCoordX, fCoordY ); glVertex3f(  1.0, -1.0, 1.0 );
+        glTexCoord2f( fCoordX, 0.0 );     glVertex3f(  1.0,  1.0, 1.0 );
+        glEnd();
+     
+        glBindTexture( fTarget, fTextures[1] );
+        glBegin( GL_QUADS );
+        if( anim & HB_ANIMATE_FORWARD )
+        {
+            glTexCoord2f( 0.0,    0.0 );     glVertex3f( 1.0,  1.0,  1.0 );
+            glTexCoord2f( 0.0,    fCoordY ); glVertex3f( 1.0, -1.0,  1.0 );
+            glTexCoord2f( fCoordX, fCoordY ); glVertex3f( 1.0, -1.0, -1.0 );
+            glTexCoord2f( fCoordX, 0.0 );     glVertex3f( 1.0,  1.0, -1.0 );
+        }
+        else
+        {
+            glTexCoord2f( 0.0,    0.0 );     glVertex3f( -1.0,  1.0, -1.0 );
+            glTexCoord2f( 0.0,    fCoordY ); glVertex3f( -1.0, -1.0, -1.0 );
+            glTexCoord2f( fCoordX, fCoordY ); glVertex3f( -1.0, -1.0,  1.0 );
+            glTexCoord2f( fCoordX, 0.0 );     glVertex3f( -1.0,  1.0,  1.0 );
+        }
+        glEnd();
+     
+        [[self openGLContext] flushBuffer];
+
+        hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
+    }
+
 }
 
-- (void) drawRect: (NSRect) rect
+- (void) drawSwap: (int) anim
 {
-   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+    uint64_t date;
+    float w, rotation, x, z;
+    
+    w = ( anim & HB_ANIMATE_BACKWARD ) ? 1.0 : -1.0;
 
-   if( !fPicture )
-   {
-       return;
-   }
+    glEnable( GL_DEPTH_TEST );
+    glEnable( GL_CULL_FACE );
+    glDisable( GL_BLEND );
+
+    glMatrixMode( GL_PROJECTION );
+    glLoadIdentity();
+    glFrustum( -1.0, 1.0, -1.0, 1.0, FRUSTUM_NEAR, FRUSTUM_FAR );
+    glMatrixMode( GL_MODELVIEW );
+    glLoadIdentity();
+    glTranslatef( 0.0, 0.0, - FRUSTUM_NEAR - 1.0 );
+
+    for( rotation = 0.0; w * rotation < 180.0;
+         rotation += w * 180 * 1000 / fAnimDuration / fFrameRate )
+    {
+        date = hb_get_date();
+
+        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+        x = 1.1 * sin( rotation * M_PI / 180 );
+        z = cos( rotation * M_PI / 180 );
+
+        glBindTexture( fTarget, fTextures[0] );
+        glBegin( GL_QUADS );
+        glTexCoord2f( 0.0,    0.0 );     glVertex3f( -1.0 + x,  1.0, z );
+        glTexCoord2f( 0.0,    fCoordY ); glVertex3f( -1.0 + x, -1.0, z );
+        glTexCoord2f( fCoordX, fCoordY ); glVertex3f(  1.0 + x, -1.0, z );
+        glTexCoord2f( fCoordX, 0.0 );     glVertex3f(  1.0 + x,  1.0, z );
+        glEnd();
+     
+        glBindTexture( fTarget, fTextures[1] );
+        glBegin( GL_QUADS );
+        glTexCoord2f( 0.0,    0.0 );     glVertex3f( -1.0 - x,  1.0, - z );
+        glTexCoord2f( 0.0,    fCoordY ); glVertex3f( -1.0 - x, -1.0, - z );
+        glTexCoord2f( fCoordX, fCoordY ); glVertex3f(  1.0 - x, -1.0, - z );
+        glTexCoord2f( fCoordX, 0.0 );     glVertex3f(  1.0 - x,  1.0, - z );
+        glEnd();
+     
+        [[self openGLContext] flushBuffer];
+
+        hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
+    }
+}
+
+- (void) drawFade
+{
+    uint64_t date;
+    float alpha;
+
+    glDisable( GL_DEPTH_TEST );
+    glDisable( GL_CULL_FACE );
+    glEnable( GL_BLEND );
+
+    glMatrixMode( GL_PROJECTION );
+    glLoadIdentity();
+    glMatrixMode( GL_MODELVIEW );
+    glLoadIdentity();
+
+    for( alpha = 0.0; alpha < 1.0;
+         alpha += 1000.0 / fAnimDuration / fFrameRate )
+    {
+        date = hb_get_date();
+
+        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+        glColor4f( 1.0, 1.0, 1.0, 1.0 - alpha );
+        glBlendFunc( GL_SRC_ALPHA, GL_ONE );
+
+        glBindTexture( fTarget, fTextures[0] );
+        glBegin( GL_QUADS );
+        glTexCoord2f( 0.0,    0.0 );     glVertex2f( -1.0,  1.0 );
+        glTexCoord2f( 0.0,    fCoordY ); glVertex2f( -1.0, -1.0 );
+        glTexCoord2f( fCoordX, fCoordY ); glVertex2f(  1.0, -1.0 );
+        glTexCoord2f( fCoordX, 0.0 );     glVertex2f(  1.0,  1.0 );
+        glEnd();
+
+        glColor4f( 1.0, 1.0, 1.0, alpha );
+        glBlendFunc( GL_SRC_ALPHA, GL_ONE );
+
+        glBindTexture( fTarget, fTextures[1] );
+        glBegin( GL_QUADS );
+        glTexCoord2f( 0.0,    0.0 );     glVertex2f( -1.0,  1.0 );
+        glTexCoord2f( 0.0,    fCoordY ); glVertex2f( -1.0, -1.0 );
+        glTexCoord2f( fCoordX, fCoordY ); glVertex2f(  1.0, -1.0 );
+        glTexCoord2f( fCoordX, 0.0 );     glVertex2f(  1.0,  1.0 );
+        glEnd();
+
+        [[self openGLContext] flushBuffer];
+
+        hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
+    }
+}
+
+- (void) drawSlide: (int) anim
+{
+    uint64_t date;
+    float foo, w;
+    int left, right;
+    if( anim & HB_ANIMATE_FORWARD )
+    {
+        left  = 0;
+        right = 1;
+        w     = 1.0;
+    }
+    else
+    {
+        left  = 1;
+        right = 0;
+        w     = -1.0;
+    }
+
+    glDisable( GL_DEPTH_TEST );
+    glDisable( GL_CULL_FACE );
+    glDisable( GL_BLEND );
+
+    glMatrixMode( GL_PROJECTION );
+    glLoadIdentity();
+    glMatrixMode( GL_MODELVIEW );
+    glLoadIdentity();
+
+    for( foo = w; foo >= -1.0 && foo <= 1.0;
+         foo -= w * 2000.0 / fAnimDuration / fFrameRate )
+    {
+        date = hb_get_date();
+
+        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+        glBindTexture( fTarget, fTextures[left] );
+        glBegin( GL_QUADS );
+        glTexCoord2f( 0.0,    0.0 );     glVertex2f( foo - 2.0,  1.0 );
+        glTexCoord2f( 0.0,    fCoordY ); glVertex2f( foo - 2.0, -1.0 );
+        glTexCoord2f( fCoordX, fCoordY ); glVertex2f( foo,       -1.0 );
+        glTexCoord2f( fCoordX, 0.0 );     glVertex2f( foo,        1.0 );
+        glEnd();
 
-   glDrawPixels( fTitle->outWidthMax + 2,
-                 fTitle->outHeightMax + 2, GL_RGBA,
-                 GL_UNSIGNED_BYTE, fPicture );
+        glBindTexture( fTarget, fTextures[right] );
+        glBegin( GL_QUADS );
+        glTexCoord2f( 0.0,    0.0 );     glVertex2f( foo,        1.0 );
+        glTexCoord2f( 0.0,    fCoordY ); glVertex2f( foo,       -1.0 );
+        glTexCoord2f( fCoordX, fCoordY ); glVertex2f( foo + 2.0, -1.0 );
+        glTexCoord2f( fCoordX, 0.0 );     glVertex2f( foo + 2.0,  1.0 );
+        glEnd();
 
-   [[self openGLContext] flushBuffer];
+        [[self openGLContext] flushBuffer];
+
+        hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
+    }
+}
+
+#undef FRUSTUM_NEAR
+#undef FRUSTUM_FAR
+
+- (void) drawAnimation: (int) anim
+{
+    glEnable( fTarget );
+
+    glBindTexture( fTarget, fTextures[0] );
+    glTexImage2D( fTarget, 0, GL_RGBA, fTexWidth, fTexHeight, 0,
+                  GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, fBuffers[1] );
+    glTexParameteri( fTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+    glTexParameteri( fTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+    glBindTexture( fTarget, fTextures[1] );
+    glTexImage2D( fTarget, 0, GL_RGBA, fTexWidth, fTexHeight, 0,
+                  GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, fBuffers[0] );
+    glTexParameteri( fTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+    glTexParameteri( fTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+    /* Draw a random animation, just making sure we don't use the same
+       effect two times in a row */
+    int effect;
+    do
+    {
+        effect = hb_get_date() % 4;
+    }
+    while( effect == fLastEffect );
+
+    fAnimDuration = ( anim & HB_ANIMATE_SLOW ) ? 3000 : 600;
+    fFrameRate    = 60.0;
+    
+    switch( effect )
+    {
+        case 0:
+            [self drawCube: anim];
+            break;
+        case 1:
+            [self drawSwap: anim];
+            break;
+        case 2:
+            [self drawFade];
+            break;
+        case 3:
+            [self drawSlide: anim];
+            break;
+    }
+
+    fLastEffect = effect;
+}
+
+- (void) Display: (int) anim buffer1: (uint8_t *) buffer1
+    buffer2: (uint8_t *) buffer2 width: (int) width height: (int) height
+{
+    [[self openGLContext] makeCurrentContext];
+
+    if( width != fWidth || height != fHeight )
+    {
+        fWidth  = width;
+        fHeight = height;
+        if( fHasQE )
+        {
+            fTexWidth  = fWidth;
+            fTexHeight = fHeight;
+            fCoordX    = (float) fWidth;
+            fCoordY    = (float) fHeight;
+        }
+        else
+        {
+            fTexWidth  = GetAlignedSize( fWidth );
+            fTexHeight = GetAlignedSize( fHeight );
+            fCoordX    = (float) fWidth  / (float) fTexWidth;
+            fCoordY    = (float) fHeight / (float) fTexHeight;
+        }
+        [self clearGLContext];
+        [self openGLContext];
+        [self reshape];
+    }
+
+    fBuffers[0] = buffer1;
+    fBuffers[1] = buffer2;
+
+    /* Swap buffers only during the vertical retrace of the monitor.
+       http://developer.apple.com/documentation/GraphicsImaging/
+       Conceptual/OpenGL/chap5/chapter_5_section_44.html */
+    long params[] = { 1 };
+    CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval,
+                     params );
+
+    if( !( anim & HB_ANIMATE_NONE ) )
+    {
+        [self drawAnimation: anim];
+    }
+    
+    [self drawRect: [self bounds]];
 }
 
 @end