1 /* $Id: PictureGLView.mm,v 1.18 2005/08/01 15:10:44 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
7 #include <OpenGL/OpenGL.h>
9 #include <OpenGL/glext.h>
12 #include "PictureGLView.h"
14 static int GetAlignedSize( int size )
17 while( result < size )
24 @implementation HBPictureGLView
26 - (id) initWithFrame: (NSRect) frame
28 fHasQE = CGDisplayUsesOpenGLAcceleration( kCGDirectMainDisplay );
29 fTarget = fHasQE ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D;
40 NSOpenGLPFANoRecovery,
42 NSOpenGLPFAAccelerated,
43 NSOpenGLPFADoubleBuffer,
44 NSOpenGLPFAColorSize, 24,
45 NSOpenGLPFAAlphaSize, 8,
46 NSOpenGLPFADepthSize, 24,
47 NSOpenGLPFAStencilSize, 8,
48 NSOpenGLPFAAccumSize, 0,
52 NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc]
53 initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs];
55 self = [super initWithFrame:frame pixelFormat: [fmt autorelease]];
62 [[self openGLContext] makeCurrentContext];
65 glGenTextures( 2, fTextures );
73 [[self openGLContext] update];
74 [[self openGLContext] makeCurrentContext];
75 bounds = [self bounds];
76 glViewport( 0, 0, (int) bounds.size.width,
77 (int) bounds.size.height );
80 - (void) drawRect: (NSRect) rect
82 [[self openGLContext] makeCurrentContext];
84 glDisable( GL_DEPTH_TEST );
85 glDisable( GL_CULL_FACE );
86 glDisable( GL_BLEND );
88 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
92 glMatrixMode( GL_PROJECTION );
94 glMatrixMode( GL_MODELVIEW );
98 glBindTexture( fTarget, fTextures[0] );
99 glTexImage2D( fTarget, 0, GL_RGBA, fTexWidth, fTexHeight, 0,
100 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, fBuffers[0] );
101 glTexParameteri( fTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
102 glTexParameteri( fTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
105 glTexCoord2f( 0.0 , 0.0 ); glVertex2f( -1.0, 1.0 );
106 glTexCoord2f( 0.0 , fCoordY ); glVertex2f( -1.0, -1.0 );
107 glTexCoord2f( fCoordX, fCoordY ); glVertex2f( 1.0, -1.0 );
108 glTexCoord2f( fCoordX, 0.0 ); glVertex2f( 1.0, 1.0 );
111 [[self openGLContext] flushBuffer];
114 #define FRUSTUM_NEAR 2.5
115 #define FRUSTUM_FAR 20.0
117 - (void) drawCube: (int) anim
120 float w, rotation, translation;
122 w = ( anim & HB_ANIMATE_BACKWARD ) ? 1.0 : -1.0;
124 glEnable( GL_DEPTH_TEST );
125 glEnable( GL_CULL_FACE );
126 glDisable( GL_BLEND );
128 for( rotation = 0.0; w * rotation < 90.0;
129 rotation += w * 90 * 1000 / fAnimDuration / fFrameRate )
131 date = hb_get_date();
132 translation = - FRUSTUM_NEAR - cos( rotation * M_PI / 180 ) *
133 ( 1 + w * tan( rotation * M_PI / 180 ) );
135 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
137 glMatrixMode( GL_PROJECTION );
139 glFrustum( -1.0, 1.0, -1.0, 1.0, FRUSTUM_NEAR, FRUSTUM_FAR );
140 glMatrixMode( GL_MODELVIEW );
142 glTranslatef( 0.0, 0.0, translation );
143 glRotatef( rotation, 0.0, 1.0, 0.0 );
145 glBindTexture( fTarget, fTextures[0] );
147 glTexCoord2f( 0.0 , 0.0 ); glVertex3f( -1.0, 1.0, 1.0 );
148 glTexCoord2f( 0.0 , fCoordY ); glVertex3f( -1.0, -1.0, 1.0 );
149 glTexCoord2f( fCoordX, fCoordY ); glVertex3f( 1.0, -1.0, 1.0 );
150 glTexCoord2f( fCoordX, 0.0 ); glVertex3f( 1.0, 1.0, 1.0 );
153 glBindTexture( fTarget, fTextures[1] );
155 if( anim & HB_ANIMATE_FORWARD )
157 glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 1.0, 1.0 );
158 glTexCoord2f( 0.0, fCoordY ); glVertex3f( 1.0, -1.0, 1.0 );
159 glTexCoord2f( fCoordX, fCoordY ); glVertex3f( 1.0, -1.0, -1.0 );
160 glTexCoord2f( fCoordX, 0.0 ); glVertex3f( 1.0, 1.0, -1.0 );
164 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 1.0, -1.0 );
165 glTexCoord2f( 0.0, fCoordY ); glVertex3f( -1.0, -1.0, -1.0 );
166 glTexCoord2f( fCoordX, fCoordY ); glVertex3f( -1.0, -1.0, 1.0 );
167 glTexCoord2f( fCoordX, 0.0 ); glVertex3f( -1.0, 1.0, 1.0 );
171 [[self openGLContext] flushBuffer];
173 hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
178 - (void) drawSwap: (int) anim
181 float w, rotation, x, z;
183 w = ( anim & HB_ANIMATE_BACKWARD ) ? 1.0 : -1.0;
185 glEnable( GL_DEPTH_TEST );
186 glEnable( GL_CULL_FACE );
187 glDisable( GL_BLEND );
189 glMatrixMode( GL_PROJECTION );
191 glFrustum( -1.0, 1.0, -1.0, 1.0, FRUSTUM_NEAR, FRUSTUM_FAR );
192 glMatrixMode( GL_MODELVIEW );
194 glTranslatef( 0.0, 0.0, - FRUSTUM_NEAR - 1.0 );
196 for( rotation = 0.0; w * rotation < 180.0;
197 rotation += w * 180 * 1000 / fAnimDuration / fFrameRate )
199 date = hb_get_date();
201 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
203 x = 1.1 * sin( rotation * M_PI / 180 );
204 z = cos( rotation * M_PI / 180 );
206 glBindTexture( fTarget, fTextures[0] );
208 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0 + x, 1.0, z );
209 glTexCoord2f( 0.0, fCoordY ); glVertex3f( -1.0 + x, -1.0, z );
210 glTexCoord2f( fCoordX, fCoordY ); glVertex3f( 1.0 + x, -1.0, z );
211 glTexCoord2f( fCoordX, 0.0 ); glVertex3f( 1.0 + x, 1.0, z );
214 glBindTexture( fTarget, fTextures[1] );
216 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0 - x, 1.0, - z );
217 glTexCoord2f( 0.0, fCoordY ); glVertex3f( -1.0 - x, -1.0, - z );
218 glTexCoord2f( fCoordX, fCoordY ); glVertex3f( 1.0 - x, -1.0, - z );
219 glTexCoord2f( fCoordX, 0.0 ); glVertex3f( 1.0 - x, 1.0, - z );
222 [[self openGLContext] flushBuffer];
224 hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
233 glDisable( GL_DEPTH_TEST );
234 glDisable( GL_CULL_FACE );
235 glEnable( GL_BLEND );
237 glMatrixMode( GL_PROJECTION );
239 glMatrixMode( GL_MODELVIEW );
242 for( alpha = 0.0; alpha < 1.0;
243 alpha += 1000.0 / fAnimDuration / fFrameRate )
245 date = hb_get_date();
247 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
249 glColor4f( 1.0, 1.0, 1.0, 1.0 - alpha );
250 glBlendFunc( GL_SRC_ALPHA, GL_ONE );
252 glBindTexture( fTarget, fTextures[0] );
254 glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, 1.0 );
255 glTexCoord2f( 0.0, fCoordY ); glVertex2f( -1.0, -1.0 );
256 glTexCoord2f( fCoordX, fCoordY ); glVertex2f( 1.0, -1.0 );
257 glTexCoord2f( fCoordX, 0.0 ); glVertex2f( 1.0, 1.0 );
260 glColor4f( 1.0, 1.0, 1.0, alpha );
261 glBlendFunc( GL_SRC_ALPHA, GL_ONE );
263 glBindTexture( fTarget, fTextures[1] );
265 glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, 1.0 );
266 glTexCoord2f( 0.0, fCoordY ); glVertex2f( -1.0, -1.0 );
267 glTexCoord2f( fCoordX, fCoordY ); glVertex2f( 1.0, -1.0 );
268 glTexCoord2f( fCoordX, 0.0 ); glVertex2f( 1.0, 1.0 );
271 [[self openGLContext] flushBuffer];
273 hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
277 - (void) drawSlide: (int) anim
282 if( anim & HB_ANIMATE_FORWARD )
295 glDisable( GL_DEPTH_TEST );
296 glDisable( GL_CULL_FACE );
297 glDisable( GL_BLEND );
299 glMatrixMode( GL_PROJECTION );
301 glMatrixMode( GL_MODELVIEW );
304 for( foo = w; foo >= -1.0 && foo <= 1.0;
305 foo -= w * 2000.0 / fAnimDuration / fFrameRate )
307 date = hb_get_date();
309 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
311 glBindTexture( fTarget, fTextures[left] );
313 glTexCoord2f( 0.0, 0.0 ); glVertex2f( foo - 2.0, 1.0 );
314 glTexCoord2f( 0.0, fCoordY ); glVertex2f( foo - 2.0, -1.0 );
315 glTexCoord2f( fCoordX, fCoordY ); glVertex2f( foo, -1.0 );
316 glTexCoord2f( fCoordX, 0.0 ); glVertex2f( foo, 1.0 );
319 glBindTexture( fTarget, fTextures[right] );
321 glTexCoord2f( 0.0, 0.0 ); glVertex2f( foo, 1.0 );
322 glTexCoord2f( 0.0, fCoordY ); glVertex2f( foo, -1.0 );
323 glTexCoord2f( fCoordX, fCoordY ); glVertex2f( foo + 2.0, -1.0 );
324 glTexCoord2f( fCoordX, 0.0 ); glVertex2f( foo + 2.0, 1.0 );
327 [[self openGLContext] flushBuffer];
329 hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
336 - (void) drawAnimation: (int) anim
340 glBindTexture( fTarget, fTextures[0] );
341 glTexImage2D( fTarget, 0, GL_RGBA, fTexWidth, fTexHeight, 0,
342 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, fBuffers[1] );
343 glTexParameteri( fTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
344 glTexParameteri( fTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
346 glBindTexture( fTarget, fTextures[1] );
347 glTexImage2D( fTarget, 0, GL_RGBA, fTexWidth, fTexHeight, 0,
348 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, fBuffers[0] );
349 glTexParameteri( fTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
350 glTexParameteri( fTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
352 /* Draw a random animation, just making sure we don't use the same
353 effect two times in a row */
357 effect = hb_get_date() % 4;
359 while( effect == fLastEffect );
361 fAnimDuration = ( anim & HB_ANIMATE_SLOW ) ? 3000 : 600;
367 [self drawCube: anim];
370 [self drawSwap: anim];
376 [self drawSlide: anim];
380 fLastEffect = effect;
383 - (void) Display: (int) anim buffer1: (uint8_t *) buffer1
384 buffer2: (uint8_t *) buffer2 width: (int) width height: (int) height
386 [[self openGLContext] makeCurrentContext];
388 if( width != fWidth || height != fHeight )
395 fTexHeight = fHeight;
396 fCoordX = (float) fWidth;
397 fCoordY = (float) fHeight;
401 fTexWidth = GetAlignedSize( fWidth );
402 fTexHeight = GetAlignedSize( fHeight );
403 fCoordX = (float) fWidth / (float) fTexWidth;
404 fCoordY = (float) fHeight / (float) fTexHeight;
406 [self clearGLContext];
407 [self openGLContext];
411 fBuffers[0] = buffer1;
412 fBuffers[1] = buffer2;
414 /* Swap buffers only during the vertical retrace of the monitor.
415 http://developer.apple.com/documentation/GraphicsImaging/
416 Conceptual/OpenGL/chap5/chapter_5_section_44.html */
417 long params[] = { 1 };
418 CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval,
421 if( !( anim & HB_ANIMATE_NONE ) )
423 [self drawAnimation: anim];
426 [self drawRect: [self bounds]];