Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

voutgl.m

00001 /*****************************************************************************
00002  * voutgl.m: MacOS X OpenGL provider
00003  *****************************************************************************
00004  * Copyright (C) 2001-2004 the VideoLAN team
00005  * $Id: vout.m 8351 2004-08-02 13:06:38Z hartman $
00006  *
00007  * Authors: Colin Delacroix <[email protected]>
00008  *          Florian G. Pflug <[email protected]>
00009  *          Jon Lech Johansen <[email protected]>
00010  *          Derk-Jan Hartman <hartman at videolan dot org>
00011  *          Eric Petit <[email protected]>
00012  *
00013  * This program is free software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation; either version 2 of the License, or
00016  * (at your option) any later version.
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00026  *****************************************************************************/
00027 
00028 /*****************************************************************************
00029  * Preamble
00030  *****************************************************************************/
00031 #include <errno.h>                                                 /* ENOMEM */
00032 #include <stdlib.h>                                                /* free() */
00033 #include <string.h>                                            /* strerror() */
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  * VLCView interface
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  * Local prototypes
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     /* Create the GL view */
00101     p_vout->p_sys->o_glview = [[VLCGLView alloc] initWithVout: p_vout];
00102     [p_vout->p_sys->o_glview autorelease];
00103 
00104     /* Spawn the window */
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     /* Close the window */
00130     [p_vout->p_sys->o_window close];
00131 
00132     /* Clean up */
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             /* Save window size and position */
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  * Control: control facility for the vout
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  * VLCGLView implementation
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     /* Swap buffers only during the vertical retrace of the monitor.
00270        http://developer.apple.com/documentation/GraphicsImaging/
00271        Conceptual/OpenGL/chap5/chapter_5_section_44.html */
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         /* Ask the opengl module to redraw */
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 

Generated on Tue Dec 20 10:14:38 2005 for vlc-0.8.4a by  doxygen 1.4.2