/* $Id: PictureGLView.mm,v 1.6 2004/03/08 12:39:49 titer Exp $ This file is part of the HandBrake source code. Homepage: . It may be used under the terms of the GNU General Public License. */ #include #include #include #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 { 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 = 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 = ( fTitle->outHeightMax + 2 ) * ( fTitle->outWidthMax + 2 ); i--; ) { *(p++) = ( ( (*p) & 0x00FFFFFF ) << 8 ) | 0xFF; } if( how == HB_ANIMATE_NONE ) { [self drawRect: [self bounds]]; return; } in = fOldPicture; out = truc; for( int 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 = 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 #define FRAME_PER_SEC 50 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 * 90 * 1000000 / ANIMATION_TIME / FRAME_PER_SEC; if( w * rotation >= 90.0 ) { break; } wait = 1000000 / FRAME_PER_SEC - ( HBGetDate() - date ); if( wait > 0 ) { HBSnooze( wait ); } } [self drawRect: [self bounds]]; } - (id) initWithFrame: (NSRect) frame { fHandle = NULL; fTitle = NULL; fPicture = NULL; fOldPicture = NULL; GLuint attribs[] = { NSOpenGLPFANoRecovery, NSOpenGLPFAWindow, NSOpenGLPFAAccelerated, NSOpenGLPFADoubleBuffer, NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, NSOpenGLPFADepthSize, 24, NSOpenGLPFAStencilSize, 8, NSOpenGLPFAAccumSize, 0, 0 }; NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs]; self = [super initWithFrame:frame pixelFormat: [fmt autorelease]]; if( !self ) { return NULL; } [[self openGLContext] makeCurrentContext]; [self reshape]; glGenTextures( 2, texture ); truc = (uint8_t*) malloc( 1024*1024*4 ); return self; } /* * Resize ourself */ - (void) reshape { NSRect bounds; [[self openGLContext] update]; bounds = [self bounds]; if( fTitle ) { glViewport( 0, 0, fTitle->outWidthMax + 2, fTitle->outHeightMax + 2 ); } } - (void) drawAnimation: (int) how { /* 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 ); 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]; } - (void) drawRect: (NSRect) rect { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); if( !fPicture ) { return; } glDrawPixels( fTitle->outWidthMax + 2, fTitle->outHeightMax + 2, GL_RGBA, GL_UNSIGNED_BYTE, fPicture ); [[self openGLContext] flushBuffer]; } @end