00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <errno.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034
00035 #include <vlc_keys.h>
00036
00037 #include "intf.h"
00038 #include "vout.h"
00039
00040 #include <OpenGL/OpenGL.h>
00041 #include <OpenGL/gl.h>
00042
00043
00044
00045
00046 @interface VLCGLView : NSOpenGLView
00047 {
00048 vout_thread_t * p_vout;
00049 }
00050
00051 - (id) initWithVout: (vout_thread_t *) p_vout;
00052 @end
00053
00054 struct vout_sys_t
00055 {
00056 NSAutoreleasePool * o_pool;
00057 VLCWindow * o_window;
00058 VLCGLView * o_glview;
00059 vlc_bool_t b_saved_frame;
00060 NSRect s_frame;
00061 vlc_bool_t b_got_frame;
00062 vlc_mutex_t lock;
00063 };
00064
00065
00066
00067
00068
00069 static int Init ( vout_thread_t * p_vout );
00070 static void End ( vout_thread_t * p_vout );
00071 static int Manage ( vout_thread_t * p_vout );
00072 static int Control( vout_thread_t *, int, va_list );
00073 static void Swap ( vout_thread_t * p_vout );
00074 static int Lock ( vout_thread_t * p_vout );
00075 static void Unlock ( vout_thread_t * p_vout );
00076
00077 int E_(OpenVideoGL) ( vlc_object_t * p_this )
00078 {
00079 vout_thread_t * p_vout = (vout_thread_t *) p_this;
00080
00081 if( !CGDisplayUsesOpenGLAcceleration( kCGDirectMainDisplay ) )
00082 {
00083 msg_Warn( p_vout, "no hardware acceleration" );
00084 return( 1 );
00085 }
00086 msg_Dbg( p_vout, "display is Quartz Extreme accelerated" );
00087
00088 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00089 if( p_vout->p_sys == NULL )
00090 {
00091 msg_Err( p_vout, "out of memory" );
00092 return( 1 );
00093 }
00094
00095 memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
00096
00097 p_vout->p_sys->o_pool = [[NSAutoreleasePool alloc] init];
00098 vlc_mutex_init( p_vout, &p_vout->p_sys->lock );
00099
00100
00101 p_vout->p_sys->o_glview = [[VLCGLView alloc] initWithVout: p_vout];
00102 [p_vout->p_sys->o_glview autorelease];
00103
00104
00105 p_vout->p_sys->b_got_frame = VLC_FALSE;
00106 p_vout->p_sys->o_window = [[VLCWindow alloc] initWithVout: p_vout
00107 view: p_vout->p_sys->o_glview frame: nil];
00108 if( !p_vout->p_sys->o_window )
00109 {
00110 return VLC_EGENERIC;
00111 }
00112
00113 p_vout->pf_init = Init;
00114 p_vout->pf_end = End;
00115 p_vout->pf_manage = Manage;
00116 p_vout->pf_control= Control;
00117 p_vout->pf_swap = Swap;
00118 p_vout->pf_lock = Lock;
00119 p_vout->pf_unlock = Unlock;
00120
00121 return VLC_SUCCESS;
00122 }
00123
00124 void E_(CloseVideoGL) ( vlc_object_t * p_this )
00125 {
00126 vout_thread_t * p_vout = (vout_thread_t *) p_this;
00127 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
00128
00129
00130 [p_vout->p_sys->o_window close];
00131
00132
00133 vlc_mutex_destroy( &p_vout->p_sys->lock );
00134 [o_pool release];
00135 free( p_vout->p_sys );
00136 }
00137
00138 static int Init( vout_thread_t * p_vout )
00139 {
00140 [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext];
00141 return VLC_SUCCESS;
00142 }
00143
00144 static void End( vout_thread_t * p_vout )
00145 {
00146 [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext];
00147 }
00148
00149 static int Manage( vout_thread_t * p_vout )
00150 {
00151 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
00152 {
00153 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
00154
00155 if( !p_vout->b_fullscreen )
00156 {
00157
00158 p_vout->p_sys->s_frame.size =
00159 [[p_vout->p_sys->o_window contentView] frame].size;
00160 p_vout->p_sys->s_frame.origin =
00161 [p_vout->p_sys->o_window frame].origin;
00162 p_vout->p_sys->b_saved_frame = VLC_TRUE;
00163 }
00164 [p_vout->p_sys->o_window close];
00165
00166 p_vout->b_fullscreen = !p_vout->b_fullscreen;
00167
00168 #define o_glview p_vout->p_sys->o_glview
00169 o_glview = [[VLCGLView alloc] initWithVout: p_vout];
00170 [o_glview autorelease];
00171
00172 if( p_vout->p_sys->b_saved_frame )
00173 {
00174 p_vout->p_sys->o_window = [[VLCWindow alloc]
00175 initWithVout: p_vout view: o_glview
00176 frame: &p_vout->p_sys->s_frame];
00177 }
00178 else
00179 {
00180 p_vout->p_sys->o_window = [[VLCWindow alloc]
00181 initWithVout: p_vout view: o_glview frame: nil];
00182 }
00183
00184 [[o_glview openGLContext] makeCurrentContext];
00185 #undef o_glview
00186
00187 [o_pool release];
00188
00189 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
00190 }
00191 [p_vout->p_sys->o_window manage];
00192 return VLC_SUCCESS;
00193 }
00194
00195
00196
00197
00198 static int Control( vout_thread_t *p_vout, int i_query, va_list args )
00199 {
00200 vlc_bool_t b_arg;
00201
00202 switch( i_query )
00203 {
00204 case VOUT_SET_STAY_ON_TOP:
00205 b_arg = va_arg( args, vlc_bool_t );
00206 [p_vout->p_sys->o_window setOnTop: b_arg];
00207 return VLC_SUCCESS;
00208
00209 case VOUT_CLOSE:
00210 case VOUT_REPARENT:
00211 default:
00212 return vout_vaControlDefault( p_vout, i_query, args );
00213 }
00214 }
00215
00216 static void Swap( vout_thread_t * p_vout )
00217 {
00218 p_vout->p_sys->b_got_frame = VLC_TRUE;
00219 [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext];
00220 glFlush();
00221 }
00222
00223 static int Lock( vout_thread_t * p_vout )
00224 {
00225 vlc_mutex_lock( &p_vout->p_sys->lock );
00226 return 0;
00227 }
00228
00229 static void Unlock( vout_thread_t * p_vout )
00230 {
00231 vlc_mutex_unlock( &p_vout->p_sys->lock );
00232 }
00233
00234
00235
00236
00237 @implementation VLCGLView
00238
00239 - (id) initWithVout: (vout_thread_t *) vout
00240 {
00241 p_vout = vout;
00242
00243 NSOpenGLPixelFormatAttribute attribs[] =
00244 {
00245 NSOpenGLPFAAccelerated,
00246 NSOpenGLPFANoRecovery,
00247 NSOpenGLPFAColorSize, 24,
00248 NSOpenGLPFAAlphaSize, 8,
00249 NSOpenGLPFADepthSize, 24,
00250 NSOpenGLPFAWindow,
00251 0
00252 };
00253
00254 NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc]
00255 initWithAttributes: attribs];
00256
00257 if( !fmt )
00258 {
00259 msg_Warn( p_vout, "Cannot create NSOpenGLPixelFormat" );
00260 return nil;
00261 }
00262
00263 self = [super initWithFrame: NSMakeRect(0,0,10,10) pixelFormat: fmt];
00264 [fmt release];
00265
00266 [[self openGLContext] makeCurrentContext];
00267 [[self openGLContext] update];
00268
00269
00270
00271
00272 long params[] = { 1 };
00273 CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval,
00274 params );
00275 return self;
00276 }
00277
00278 - (void) reshape
00279 {
00280 int x, y;
00281 vlc_value_t val;
00282
00283 Lock( p_vout );
00284 NSRect bounds = [self bounds];
00285
00286 [[self openGLContext] makeCurrentContext];
00287
00288 var_Get( p_vout, "macosx-stretch", &val );
00289 if( val.b_bool )
00290 {
00291 x = bounds.size.width;
00292 y = bounds.size.height;
00293 }
00294 else if( bounds.size.height * p_vout->render.i_aspect <
00295 bounds.size.width * VOUT_ASPECT_FACTOR )
00296 {
00297 x = bounds.size.height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
00298 y = bounds.size.height;
00299 }
00300 else
00301 {
00302 x = bounds.size.width;
00303 y = bounds.size.width * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
00304 }
00305
00306 glViewport( ( bounds.size.width - x ) / 2,
00307 ( bounds.size.height - y ) / 2, x, y );
00308
00309 if( p_vout->p_sys->b_got_frame )
00310 {
00311
00312 vout_thread_t * p_parent;
00313 p_parent = (vout_thread_t *) p_vout->p_parent;
00314 Unlock( p_vout );
00315 if( p_parent && p_parent->pf_display )
00316 {
00317 p_parent->pf_display( p_parent, NULL );
00318 }
00319 }
00320 else
00321 {
00322 glClear( GL_COLOR_BUFFER_BIT );
00323 Unlock( p_vout );
00324 }
00325 [super reshape];
00326 }
00327
00328 - (void) update
00329 {
00330 Lock( p_vout );
00331 [super update];
00332 Unlock( p_vout );
00333 }
00334
00335 - (void) drawRect: (NSRect) rect
00336 {
00337 Lock( p_vout );
00338 [[self openGLContext] makeCurrentContext];
00339 glFlush();
00340 [super drawRect:rect];
00341 Unlock( p_vout );
00342 }
00343
00344 @end
00345
00346