OSDN Git Service

Repeat after me, eddyg is a wally.
[handbrake-jp/handbrake-jp-git.git] / macosx / PictureGLView.mm
1 /* $Id: PictureGLView.mm,v 1.18 2005/08/01 15:10:44 titer Exp $
2
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. */
6
7 #include <OpenGL/OpenGL.h>
8 #include <OpenGL/gl.h>
9 #include <OpenGL/glext.h>
10 #include <math.h>
11
12 #include "PictureGLView.h"
13
14 static int GetAlignedSize( int size )
15 {
16     int result = 1;
17     while( result < size )
18     {
19         result *= 2;
20     }
21     return result;
22 }
23
24 @implementation HBPictureGLView
25
26 - (id) initWithFrame: (NSRect) frame
27 {
28     fHasQE  = CGDisplayUsesOpenGLAcceleration( kCGDirectMainDisplay );
29     fTarget = fHasQE ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D;
30
31     fBuffers[0] = NULL;
32     fBuffers[1] = NULL;
33     fWidth      = 0;
34     fHeight     = 0;
35
36     fLastEffect = -1;
37     
38     GLuint attribs[] =
39     {
40         NSOpenGLPFANoRecovery,
41         NSOpenGLPFAWindow,
42         NSOpenGLPFAAccelerated,
43         NSOpenGLPFADoubleBuffer,
44         NSOpenGLPFAColorSize, 24,
45         NSOpenGLPFAAlphaSize, 8,
46         NSOpenGLPFADepthSize, 24,
47         NSOpenGLPFAStencilSize, 8,
48         NSOpenGLPFAAccumSize, 0,
49         0
50     };
51
52     NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc]
53         initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs];
54
55     self = [super initWithFrame:frame pixelFormat: [fmt autorelease]];
56
57     if( !self )
58     {
59         return NULL;
60     }
61
62     [[self openGLContext] makeCurrentContext];
63     [self reshape];
64
65     glGenTextures( 2, fTextures );
66
67     return self;
68 }
69
70 - (void) reshape
71 {
72     NSRect bounds;
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 );
78 }
79
80 - (void) drawRect: (NSRect) rect
81 {
82     [[self openGLContext] makeCurrentContext];
83
84     glDisable( GL_DEPTH_TEST );
85     glDisable( GL_CULL_FACE );
86     glDisable( GL_BLEND );
87
88     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
89
90     if( fBuffers[0] )
91     {
92         glMatrixMode( GL_PROJECTION );
93         glLoadIdentity();
94         glMatrixMode( GL_MODELVIEW );
95         glLoadIdentity();
96
97         glEnable( fTarget );
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 );
103
104         glBegin( GL_QUADS );
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 );
109         glEnd();
110     }
111     [[self openGLContext] flushBuffer];
112 }
113
114 #define FRUSTUM_NEAR   2.5
115 #define FRUSTUM_FAR    20.0
116
117 - (void) drawCube: (int) anim
118 {
119     uint64_t date;
120     float w, rotation, translation;
121     
122     w = ( anim & HB_ANIMATE_BACKWARD ) ? 1.0 : -1.0;
123
124     glEnable( GL_DEPTH_TEST );
125     glEnable( GL_CULL_FACE );
126     glDisable( GL_BLEND );
127
128     for( rotation = 0.0; w * rotation < 90.0;
129          rotation += w * 90 * 1000 / fAnimDuration / fFrameRate )
130     {
131         date = hb_get_date();
132         translation = - FRUSTUM_NEAR - cos( rotation * M_PI / 180 ) *
133             ( 1 + w * tan( rotation * M_PI / 180 ) );
134
135         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
136
137         glMatrixMode( GL_PROJECTION );
138         glLoadIdentity();
139         glFrustum( -1.0, 1.0, -1.0, 1.0, FRUSTUM_NEAR, FRUSTUM_FAR );
140         glMatrixMode( GL_MODELVIEW );
141         glLoadIdentity();
142         glTranslatef( 0.0, 0.0, translation );
143         glRotatef( rotation, 0.0, 1.0, 0.0 );
144      
145         glBindTexture( fTarget, fTextures[0] );
146         glBegin( GL_QUADS );
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 );
151         glEnd();
152      
153         glBindTexture( fTarget, fTextures[1] );
154         glBegin( GL_QUADS );
155         if( anim & HB_ANIMATE_FORWARD )
156         {
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 );
161         }
162         else
163         {
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 );
168         }
169         glEnd();
170      
171         [[self openGLContext] flushBuffer];
172
173         hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
174     }
175
176 }
177
178 - (void) drawSwap: (int) anim
179 {
180     uint64_t date;
181     float w, rotation, x, z;
182     
183     w = ( anim & HB_ANIMATE_BACKWARD ) ? 1.0 : -1.0;
184
185     glEnable( GL_DEPTH_TEST );
186     glEnable( GL_CULL_FACE );
187     glDisable( GL_BLEND );
188
189     glMatrixMode( GL_PROJECTION );
190     glLoadIdentity();
191     glFrustum( -1.0, 1.0, -1.0, 1.0, FRUSTUM_NEAR, FRUSTUM_FAR );
192     glMatrixMode( GL_MODELVIEW );
193     glLoadIdentity();
194     glTranslatef( 0.0, 0.0, - FRUSTUM_NEAR - 1.0 );
195
196     for( rotation = 0.0; w * rotation < 180.0;
197          rotation += w * 180 * 1000 / fAnimDuration / fFrameRate )
198     {
199         date = hb_get_date();
200
201         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
202
203         x = 1.1 * sin( rotation * M_PI / 180 );
204         z = cos( rotation * M_PI / 180 );
205
206         glBindTexture( fTarget, fTextures[0] );
207         glBegin( GL_QUADS );
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 );
212         glEnd();
213      
214         glBindTexture( fTarget, fTextures[1] );
215         glBegin( GL_QUADS );
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 );
220         glEnd();
221      
222         [[self openGLContext] flushBuffer];
223
224         hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
225     }
226 }
227
228 - (void) drawFade
229 {
230     uint64_t date;
231     float alpha;
232
233     glDisable( GL_DEPTH_TEST );
234     glDisable( GL_CULL_FACE );
235     glEnable( GL_BLEND );
236
237     glMatrixMode( GL_PROJECTION );
238     glLoadIdentity();
239     glMatrixMode( GL_MODELVIEW );
240     glLoadIdentity();
241
242     for( alpha = 0.0; alpha < 1.0;
243          alpha += 1000.0 / fAnimDuration / fFrameRate )
244     {
245         date = hb_get_date();
246
247         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
248
249         glColor4f( 1.0, 1.0, 1.0, 1.0 - alpha );
250         glBlendFunc( GL_SRC_ALPHA, GL_ONE );
251
252         glBindTexture( fTarget, fTextures[0] );
253         glBegin( GL_QUADS );
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 );
258         glEnd();
259
260         glColor4f( 1.0, 1.0, 1.0, alpha );
261         glBlendFunc( GL_SRC_ALPHA, GL_ONE );
262
263         glBindTexture( fTarget, fTextures[1] );
264         glBegin( GL_QUADS );
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 );
269         glEnd();
270
271         [[self openGLContext] flushBuffer];
272
273         hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
274     }
275 }
276
277 - (void) drawSlide: (int) anim
278 {
279     uint64_t date;
280     float foo, w;
281     int left, right;
282     if( anim & HB_ANIMATE_FORWARD )
283     {
284         left  = 0;
285         right = 1;
286         w     = 1.0;
287     }
288     else
289     {
290         left  = 1;
291         right = 0;
292         w     = -1.0;
293     }
294
295     glDisable( GL_DEPTH_TEST );
296     glDisable( GL_CULL_FACE );
297     glDisable( GL_BLEND );
298
299     glMatrixMode( GL_PROJECTION );
300     glLoadIdentity();
301     glMatrixMode( GL_MODELVIEW );
302     glLoadIdentity();
303
304     for( foo = w; foo >= -1.0 && foo <= 1.0;
305          foo -= w * 2000.0 / fAnimDuration / fFrameRate )
306     {
307         date = hb_get_date();
308
309         glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
310
311         glBindTexture( fTarget, fTextures[left] );
312         glBegin( GL_QUADS );
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 );
317         glEnd();
318
319         glBindTexture( fTarget, fTextures[right] );
320         glBegin( GL_QUADS );
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 );
325         glEnd();
326
327         [[self openGLContext] flushBuffer];
328
329         hb_snooze( 1000 / fFrameRate - ( hb_get_date() - date ) );
330     }
331 }
332
333 #undef FRUSTUM_NEAR
334 #undef FRUSTUM_FAR
335
336 - (void) drawAnimation: (int) anim
337 {
338     glEnable( fTarget );
339
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 );
345
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 );
351
352     /* Draw a random animation, just making sure we don't use the same
353        effect two times in a row */
354     int effect;
355     do
356     {
357         effect = hb_get_date() % 4;
358     }
359     while( effect == fLastEffect );
360
361     fAnimDuration = ( anim & HB_ANIMATE_SLOW ) ? 3000 : 600;
362     fFrameRate    = 60.0;
363     
364     switch( effect )
365     {
366         case 0:
367             [self drawCube: anim];
368             break;
369         case 1:
370             [self drawSwap: anim];
371             break;
372         case 2:
373             [self drawFade];
374             break;
375         case 3:
376             [self drawSlide: anim];
377             break;
378     }
379
380     fLastEffect = effect;
381 }
382
383 - (void) Display: (int) anim buffer1: (uint8_t *) buffer1
384     buffer2: (uint8_t *) buffer2 width: (int) width height: (int) height
385 {
386     [[self openGLContext] makeCurrentContext];
387
388     if( width != fWidth || height != fHeight )
389     {
390         fWidth  = width;
391         fHeight = height;
392         if( fHasQE )
393         {
394             fTexWidth  = fWidth;
395             fTexHeight = fHeight;
396             fCoordX    = (float) fWidth;
397             fCoordY    = (float) fHeight;
398         }
399         else
400         {
401             fTexWidth  = GetAlignedSize( fWidth );
402             fTexHeight = GetAlignedSize( fHeight );
403             fCoordX    = (float) fWidth  / (float) fTexWidth;
404             fCoordY    = (float) fHeight / (float) fTexHeight;
405         }
406         [self clearGLContext];
407         [self openGLContext];
408         [self reshape];
409     }
410
411     fBuffers[0] = buffer1;
412     fBuffers[1] = buffer2;
413
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,
419                      params );
420
421     if( !( anim & HB_ANIMATE_NONE ) )
422     {
423         [self drawAnimation: anim];
424     }
425     
426     [self drawRect: [self bounds]];
427 }
428
429 @end