Home | History | Annotate | Download | only in mac
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/engine_configurations.h"
     12 
     13 #if defined(CARBON_RENDERING)
     14 
     15 #include "webrtc/modules/video_render/mac/video_render_agl.h"
     16 
     17 //  includes
     18 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
     19 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     20 #include "webrtc/system_wrappers/interface/event_wrapper.h"
     21 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
     22 #include "webrtc/system_wrappers/interface/trace.h"
     23 
     24 namespace webrtc {
     25 
     26 /*
     27  *
     28  *    VideoChannelAGL
     29  *
     30  */
     31 
     32 #pragma mark VideoChannelAGL constructor
     33 
     34 VideoChannelAGL::VideoChannelAGL(AGLContext& aglContext, int iId, VideoRenderAGL* owner) :
     35     _aglContext( aglContext),
     36     _id( iId),
     37     _owner( owner),
     38     _width( 0),
     39     _height( 0),
     40     _stretchedWidth( 0),
     41     _stretchedHeight( 0),
     42     _startWidth( 0.0f),
     43     _startHeight( 0.0f),
     44     _stopWidth( 0.0f),
     45     _stopHeight( 0.0f),
     46     _xOldWidth( 0),
     47     _yOldHeight( 0),
     48     _oldStretchedHeight(0),
     49     _oldStretchedWidth( 0),
     50     _buffer( 0),
     51     _bufferSize( 0),
     52     _incommingBufferSize(0),
     53     _bufferIsUpdated( false),
     54     _sizeInitialized( false),
     55     _numberOfStreams( 0),
     56     _bVideoSizeStartedChanging(false),
     57     _pixelFormat( GL_RGBA),
     58     _pixelDataType( GL_UNSIGNED_INT_8_8_8_8),
     59     _texture( 0)
     60 
     61 {
     62     //WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s:%d Constructor", __FUNCTION__, __LINE__);
     63 }
     64 
     65 VideoChannelAGL::~VideoChannelAGL()
     66 {
     67     //WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s:%d Destructor", __FUNCTION__, __LINE__);
     68     if (_buffer)
     69     {
     70         delete [] _buffer;
     71         _buffer = NULL;
     72     }
     73 
     74     aglSetCurrentContext(_aglContext);
     75 
     76     if (_texture != 0)
     77     {
     78         glDeleteTextures(1, (const GLuint*) &_texture);
     79         _texture = 0;
     80     }
     81 }
     82 
     83 int32_t VideoChannelAGL::RenderFrame(const uint32_t streamId,
     84                                      I420VideoFrame& videoFrame) {
     85   _owner->LockAGLCntx();
     86   if (_width != videoFrame.width() ||
     87       _height != videoFrame.height()) {
     88     if (FrameSizeChange(videoFrame.width(), videoFrame.height(), 1) == -1) {
     89       WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, "%s:%d FrameSize
     90                    Change returned an error", __FUNCTION__, __LINE__);
     91       _owner->UnlockAGLCntx();
     92       return -1;
     93     }
     94   }
     95 
     96   _owner->UnlockAGLCntx();
     97   return DeliverFrame(videoFrame);
     98 }
     99 
    100 int VideoChannelAGL::UpdateSize(int /*width*/, int /*height*/)
    101 {
    102     _owner->LockAGLCntx();
    103     _owner->UnlockAGLCntx();
    104     return 0;
    105 }
    106 
    107 int VideoChannelAGL::UpdateStretchSize(int stretchHeight, int stretchWidth)
    108 {
    109 
    110     _owner->LockAGLCntx();
    111     _stretchedHeight = stretchHeight;
    112     _stretchedWidth = stretchWidth;
    113     _owner->UnlockAGLCntx();
    114     return 0;
    115 }
    116 
    117 int VideoChannelAGL::FrameSizeChange(int width, int height, int numberOfStreams)
    118 {
    119     //  We'll get a new frame size from VideoAPI, prepare the buffer
    120 
    121     _owner->LockAGLCntx();
    122 
    123     if (width == _width && _height == height)
    124     {
    125         // We already have a correct buffer size
    126         _numberOfStreams = numberOfStreams;
    127         _owner->UnlockAGLCntx();
    128         return 0;
    129     }
    130 
    131     _width = width;
    132     _height = height;
    133 
    134     // Delete the old buffer, create a new one with correct size.
    135     if (_buffer)
    136     {
    137         delete [] _buffer;
    138         _bufferSize = 0;
    139     }
    140 
    141     _incommingBufferSize = CalcBufferSize(kI420, _width, _height);
    142     _bufferSize = CalcBufferSize(kARGB, _width, _height);//_width * _height * bytesPerPixel;
    143     _buffer = new unsigned char [_bufferSize];
    144     memset(_buffer, 0, _bufferSize * sizeof(unsigned char));
    145 
    146     if (aglSetCurrentContext(_aglContext) == false)
    147     {
    148         _owner->UnlockAGLCntx();
    149         return -1;
    150     }
    151 
    152     // Delete a possible old texture
    153     if (_texture != 0)
    154     {
    155         glDeleteTextures(1, (const GLuint*) &_texture);
    156         _texture = 0;
    157     }
    158 
    159     // Create a new texture
    160     glGenTextures(1, (GLuint *) &_texture);
    161 
    162     GLenum glErr = glGetError();
    163 
    164     if (glErr != GL_NO_ERROR)
    165     {
    166     }
    167 
    168     // Do the setup for both textures
    169     // Note: we setup two textures even if we're not running full screen
    170     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
    171 
    172     // Set texture parameters
    173     glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_PRIORITY, 1.0);
    174 
    175     glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    176     glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    177 
    178     glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    179     glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    180     //glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    181     //glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    182 
    183     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    184 
    185     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    186 
    187     glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE);
    188 
    189     // Maximum width/height for a texture
    190     GLint texSize;
    191     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
    192 
    193     if (texSize < _width || texSize < _height)
    194     {
    195         // Image too big for memory
    196         _owner->UnlockAGLCntx();
    197         return -1;
    198     }
    199 
    200     // Set up th texture type and size
    201     glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, // target
    202             0, // level
    203             GL_RGBA, // internal format
    204             _width, // width
    205             _height, // height
    206             0, // border 0/1 = off/on
    207             _pixelFormat, // format, GL_BGRA
    208             _pixelDataType, // data type, GL_UNSIGNED_INT_8_8_8_8
    209             _buffer); // pixel data
    210 
    211     glErr = glGetError();
    212     if (glErr != GL_NO_ERROR)
    213     {
    214         _owner->UnlockAGLCntx();
    215         return -1;
    216     }
    217 
    218     _owner->UnlockAGLCntx();
    219     return 0;
    220 }
    221 
    222 // Called from video engine when a new frame should be rendered.
    223 int VideoChannelAGL::DeliverFrame(const I420VideoFrame& videoFrame) {
    224   _owner->LockAGLCntx();
    225 
    226   if (_texture == 0) {
    227     _owner->UnlockAGLCntx();
    228     return 0;
    229   }
    230 
    231   int length = CalcBufferSize(kI420, videoFrame.width(), videoFrame.height());
    232   if (length != _incommingBufferSize) {
    233     _owner->UnlockAGLCntx();
    234     return -1;
    235   }
    236 
    237   // Setting stride = width.
    238   int rgbret = ConvertFromYV12(videoFrame, kBGRA, 0, _buffer);
    239   if (rgbret < 0) {
    240     _owner->UnlockAGLCntx();
    241     return -1;
    242   }
    243 
    244   aglSetCurrentContext(_aglContext);
    245 
    246   // Put the new frame into the graphic card texture.
    247   // Make sure this texture is the active one
    248   glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
    249   GLenum glErr = glGetError();
    250   if (glErr != GL_NO_ERROR) {
    251     _owner->UnlockAGLCntx();
    252     return -1;
    253   }
    254 
    255   // Copy buffer to texture
    256   glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT,
    257                   0, // Level, not use
    258                   0, // start point x, (low left of pic)
    259                   0, // start point y,
    260                   _width, // width
    261                   _height, // height
    262                   _pixelFormat, // pictue format for _buffer
    263                   _pixelDataType, // data type of _buffer
    264                   (const GLvoid*) _buffer); // the pixel data
    265 
    266   if (glGetError() != GL_NO_ERROR) {
    267     _owner->UnlockAGLCntx();
    268     return -1;
    269   }
    270 
    271   _bufferIsUpdated = true;
    272   _owner->UnlockAGLCntx();
    273 
    274   return 0;
    275 }
    276 
    277 int VideoChannelAGL::RenderOffScreenBuffer()
    278 {
    279 
    280     _owner->LockAGLCntx();
    281 
    282     if (_texture == 0)
    283     {
    284         _owner->UnlockAGLCntx();
    285         return 0;
    286     }
    287 
    288     GLfloat xStart = 2.0f * _startWidth - 1.0f;
    289     GLfloat xStop = 2.0f * _stopWidth - 1.0f;
    290     GLfloat yStart = 1.0f - 2.0f * _stopHeight;
    291     GLfloat yStop = 1.0f - 2.0f * _startHeight;
    292 
    293     aglSetCurrentContext(_aglContext);
    294     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
    295 
    296     if(_stretchedWidth != _oldStretchedWidth || _stretchedHeight != _oldStretchedHeight)
    297     {
    298         glViewport(0, 0, _stretchedWidth, _stretchedHeight);
    299     }
    300     _oldStretchedHeight = _stretchedHeight;
    301     _oldStretchedWidth = _stretchedWidth;
    302 
    303     // Now really put the texture into the framebuffer
    304     glLoadIdentity();
    305 
    306     glEnable(GL_TEXTURE_RECTANGLE_EXT);
    307 
    308     glBegin(GL_POLYGON);
    309     {
    310         glTexCoord2f(0.0, 0.0); glVertex2f(xStart, yStop);
    311         glTexCoord2f(_width, 0.0); glVertex2f(xStop, yStop);
    312         glTexCoord2f(_width, _height); glVertex2f(xStop, yStart);
    313         glTexCoord2f(0.0, _height); glVertex2f(xStart, yStart);
    314     }
    315     glEnd();
    316 
    317     glDisable(GL_TEXTURE_RECTANGLE_EXT);
    318 
    319     _bufferIsUpdated = false;
    320 
    321     _owner->UnlockAGLCntx();
    322     return 0;
    323 }
    324 
    325 int VideoChannelAGL::IsUpdated(bool& isUpdated)
    326 {
    327     _owner->LockAGLCntx();
    328     isUpdated = _bufferIsUpdated;
    329     _owner->UnlockAGLCntx();
    330 
    331     return 0;
    332 }
    333 
    334 int VideoChannelAGL::SetStreamSettings(int /*streamId*/, float startWidth, float startHeight, float stopWidth, float stopHeight)
    335 {
    336 
    337     _owner->LockAGLCntx();
    338 
    339     _startWidth = startWidth;
    340     _stopWidth = stopWidth;
    341     _startHeight = startHeight;
    342     _stopHeight = stopHeight;
    343 
    344     int oldWidth = _width;
    345     int oldHeight = _height;
    346     int oldNumberOfStreams = _numberOfStreams;
    347 
    348     _width = 0;
    349     _height = 0;
    350 
    351     int retVal = FrameSizeChange(oldWidth, oldHeight, oldNumberOfStreams);
    352 
    353     _owner->UnlockAGLCntx();
    354 
    355     return retVal;
    356 }
    357 
    358 int VideoChannelAGL::SetStreamCropSettings(int /*streamId*/, float /*startWidth*/, float /*startHeight*/, float /*stopWidth*/, float /*stopHeight*/)
    359 {
    360     return -1;
    361 }
    362 
    363 #pragma mark VideoRenderAGL WindowRef constructor
    364 
    365 VideoRenderAGL::VideoRenderAGL(WindowRef windowRef, bool fullscreen, int iId) :
    366 _hiviewRef( 0),
    367 _windowRef( windowRef),
    368 _fullScreen( fullscreen),
    369 _id( iId),
    370 _renderCritSec(*CriticalSectionWrapper::CreateCriticalSection()),
    371 _screenUpdateThread( 0),
    372 _screenUpdateEvent( 0),
    373 _isHIViewRef( false),
    374 _aglContext( 0),
    375 _windowWidth( 0),
    376 _windowHeight( 0),
    377 _lastWindowWidth( -1),
    378 _lastWindowHeight( -1),
    379 _lastHiViewWidth( -1),
    380 _lastHiViewHeight( -1),
    381 _currentParentWindowHeight( 0),
    382 _currentParentWindowWidth( 0),
    383 _currentParentWindowBounds( ),
    384 _windowHasResized( false),
    385 _lastParentWindowBounds( ),
    386 _currentHIViewBounds( ),
    387 _lastHIViewBounds( ),
    388 _windowRect( ),
    389 _aglChannels( ),
    390 _zOrderToChannel( ),
    391 _hiviewEventHandlerRef( NULL),
    392 _windowEventHandlerRef( NULL),
    393 _currentViewBounds( ),
    394 _lastViewBounds( ),
    395 _renderingIsPaused( false),
    396 _threadID( )
    397 
    398 {
    399     //WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s");
    400 
    401     _screenUpdateThread = ThreadWrapper::CreateThread(ScreenUpdateThreadProc, this, kRealtimePriority);
    402     _screenUpdateEvent = EventWrapper::Create();
    403 
    404     if(!IsValidWindowPtr(_windowRef))
    405     {
    406         //WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, "%s:%d Invalid WindowRef:0x%x", __FUNCTION__, __LINE__, _windowRef);
    407     }
    408     else
    409     {
    410         //WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "%s:%d WindowRef 0x%x is valid", __FUNCTION__, __LINE__, _windowRef);
    411     }
    412 
    413     GetWindowRect(_windowRect);
    414 
    415     _lastViewBounds.origin.x = 0;
    416     _lastViewBounds.origin.y = 0;
    417     _lastViewBounds.size.width = 0;
    418     _lastViewBounds.size.height = 0;
    419 
    420 }
    421 
    422 // this is a static function. It has been registered (in class constructor) to be called on various window redrawing or resizing.
    423 // Since it is a static method, I have passed in "this" as the userData (one and only allowed) parameter, then calling member methods on it.
    424 #pragma mark WindowRef Event Handler
    425 pascal OSStatus VideoRenderAGL::sHandleWindowResized (EventHandlerCallRef /*nextHandler*/,
    426         EventRef theEvent,
    427         void* userData)
    428 {
    429     WindowRef windowRef = NULL;
    430 
    431     int eventType = GetEventKind(theEvent);
    432 
    433     // see https://dcs.sourcerepo.com/dcs/tox_view/trunk/tox/libraries/i686-win32/include/quicktime/CarbonEvents.h for a list of codes
    434     GetEventParameter (theEvent,
    435             kEventParamDirectObject,
    436             typeWindowRef,
    437             NULL,
    438             sizeof (WindowRef),
    439             NULL,
    440             &windowRef);
    441 
    442     VideoRenderAGL* obj = (VideoRenderAGL*)(userData);
    443 
    444     bool updateUI = true;
    445     if(kEventWindowBoundsChanged == eventType)
    446     {
    447     }
    448     else if(kEventWindowBoundsChanging == eventType)
    449     {
    450     }
    451     else if(kEventWindowZoomed == eventType)
    452     {
    453     }
    454     else if(kEventWindowExpanding == eventType)
    455     {
    456     }
    457     else if(kEventWindowExpanded == eventType)
    458     {
    459     }
    460     else if(kEventWindowClickResizeRgn == eventType)
    461     {
    462     }
    463     else if(kEventWindowClickDragRgn == eventType)
    464     {
    465     }
    466     else
    467     {
    468         updateUI = false;
    469     }
    470 
    471     if(true == updateUI)
    472     {
    473         obj->ParentWindowResized(windowRef);
    474         obj->UpdateClipping();
    475         obj->RenderOffScreenBuffers();
    476     }
    477 
    478     return noErr;
    479 }
    480 
    481 #pragma mark VideoRenderAGL HIViewRef constructor
    482 
    483 VideoRenderAGL::VideoRenderAGL(HIViewRef windowRef, bool fullscreen, int iId) :
    484 _hiviewRef( windowRef),
    485 _windowRef( 0),
    486 _fullScreen( fullscreen),
    487 _id( iId),
    488 _renderCritSec(*CriticalSectionWrapper::CreateCriticalSection()),
    489 _screenUpdateThread( 0),
    490 _screenUpdateEvent( 0),
    491 _isHIViewRef( false),
    492 _aglContext( 0),
    493 _windowWidth( 0),
    494 _windowHeight( 0),
    495 _lastWindowWidth( -1),
    496 _lastWindowHeight( -1),
    497 _lastHiViewWidth( -1),
    498 _lastHiViewHeight( -1),
    499 _currentParentWindowHeight( 0),
    500 _currentParentWindowWidth( 0),
    501 _currentParentWindowBounds( ),
    502 _windowHasResized( false),
    503 _lastParentWindowBounds( ),
    504 _currentHIViewBounds( ),
    505 _lastHIViewBounds( ),
    506 _windowRect( ),
    507 _aglChannels( ),
    508 _zOrderToChannel( ),
    509 _hiviewEventHandlerRef( NULL),
    510 _windowEventHandlerRef( NULL),
    511 _currentViewBounds( ),
    512 _lastViewBounds( ),
    513 _renderingIsPaused( false),
    514 _threadID( )
    515 {
    516     //WEBRTC_TRACE(kTraceDebug, "%s:%d Constructor", __FUNCTION__, __LINE__);
    517     //    _renderCritSec = CriticalSectionWrapper::CreateCriticalSection();
    518 
    519     _screenUpdateThread = ThreadWrapper::CreateThread(ScreenUpdateThreadProc, this, kRealtimePriority);
    520     _screenUpdateEvent = EventWrapper::Create();
    521 
    522     GetWindowRect(_windowRect);
    523 
    524     _lastViewBounds.origin.x = 0;
    525     _lastViewBounds.origin.y = 0;
    526     _lastViewBounds.size.width = 0;
    527     _lastViewBounds.size.height = 0;
    528 
    529 #ifdef NEW_HIVIEW_PARENT_EVENT_HANDLER
    530     // This gets the parent window of the HIViewRef that's passed in and installs a WindowRef event handler on it
    531     // The event handler looks for window resize events and adjusts the offset of the controls.
    532 
    533     //WEBRTC_TRACE(kTraceDebug, "%s:%d Installing Eventhandler for hiviewRef's parent window", __FUNCTION__, __LINE__);
    534 
    535 
    536     static const EventTypeSpec windowEventTypes[] =
    537     {
    538         kEventClassWindow, kEventWindowBoundsChanged,
    539         kEventClassWindow, kEventWindowBoundsChanging,
    540         kEventClassWindow, kEventWindowZoomed,
    541         kEventClassWindow, kEventWindowExpanded,
    542         kEventClassWindow, kEventWindowClickResizeRgn,
    543         kEventClassWindow, kEventWindowClickDragRgn
    544     };
    545 
    546     WindowRef parentWindow = HIViewGetWindow(windowRef);
    547 
    548     InstallWindowEventHandler (parentWindow,
    549             NewEventHandlerUPP (sHandleWindowResized),
    550             GetEventTypeCount(windowEventTypes),
    551             windowEventTypes,
    552             (void *) this, // this is an arbitrary parameter that will be passed on to your event handler when it is called later
    553             &_windowEventHandlerRef);
    554 
    555 #endif
    556 
    557 #ifdef NEW_HIVIEW_EVENT_HANDLER
    558     //WEBRTC_TRACE(kTraceDebug, "%s:%d Installing Eventhandler for hiviewRef", __FUNCTION__, __LINE__);
    559 
    560     static const EventTypeSpec hiviewEventTypes[] =
    561     {
    562         kEventClassControl, kEventControlBoundsChanged,
    563         kEventClassControl, kEventControlDraw
    564         //			kEventControlDragLeave
    565         //			kEventControlDragReceive
    566         //			kEventControlGetFocusPart
    567         //			kEventControlApplyBackground
    568         //			kEventControlDraw
    569         //			kEventControlHit
    570 
    571     };
    572 
    573     HIViewInstallEventHandler(_hiviewRef,
    574             NewEventHandlerUPP(sHandleHiViewResized),
    575             GetEventTypeCount(hiviewEventTypes),
    576             hiviewEventTypes,
    577             (void *) this,
    578             &_hiviewEventHandlerRef);
    579 
    580 #endif
    581 }
    582 
    583 // this is a static function. It has been registered (in constructor) to be called on various window redrawing or resizing.
    584 // Since it is a static method, I have passed in "this" as the userData (one and only allowed) parameter, then calling member methods on it.
    585 #pragma mark HIViewRef Event Handler
    586 pascal OSStatus VideoRenderAGL::sHandleHiViewResized (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
    587 {
    588     //static int      callbackCounter = 1;
    589     HIViewRef hiviewRef = NULL;
    590 
    591     // see https://dcs.sourcerepo.com/dcs/tox_view/trunk/tox/libraries/i686-win32/include/quicktime/CarbonEvents.h for a list of codes
    592     int eventType = GetEventKind(theEvent);
    593     OSStatus status = noErr;
    594     status = GetEventParameter (theEvent,
    595             kEventParamDirectObject,
    596             typeControlRef,
    597             NULL,
    598             sizeof (ControlRef),
    599             NULL,
    600             &hiviewRef);
    601 
    602     VideoRenderAGL* obj = (VideoRenderAGL*)(userData);
    603     WindowRef parentWindow = HIViewGetWindow(hiviewRef);
    604     bool updateUI = true;
    605 
    606     if(kEventControlBoundsChanged == eventType)
    607     {
    608     }
    609     else if(kEventControlDraw == eventType)
    610     {
    611     }
    612     else
    613     {
    614         updateUI = false;
    615     }
    616 
    617     if(true == updateUI)
    618     {
    619         obj->ParentWindowResized(parentWindow);
    620         obj->UpdateClipping();
    621         obj->RenderOffScreenBuffers();
    622     }
    623 
    624     return status;
    625 }
    626 
    627 VideoRenderAGL::~VideoRenderAGL()
    628 {
    629 
    630     //WEBRTC_TRACE(kTraceDebug, "%s:%d Destructor", __FUNCTION__, __LINE__);
    631 
    632 
    633 #ifdef USE_EVENT_HANDLERS
    634     // remove event handlers
    635     OSStatus status;
    636     if(_isHIViewRef)
    637     {
    638         status = RemoveEventHandler(_hiviewEventHandlerRef);
    639     }
    640     else
    641     {
    642         status = RemoveEventHandler(_windowEventHandlerRef);
    643     }
    644     if(noErr != status)
    645     {
    646         if(_isHIViewRef)
    647         {
    648 
    649             //WEBRTC_TRACE(kTraceDebug, "%s:%d Failed to remove hiview event handler: %d", __FUNCTION__, __LINE__, (int)_hiviewEventHandlerRef);
    650         }
    651         else
    652         {
    653             //WEBRTC_TRACE(kTraceDebug, "%s:%d Failed to remove window event handler %d", __FUNCTION__, __LINE__, (int)_windowEventHandlerRef);
    654         }
    655     }
    656 
    657 #endif
    658 
    659     OSStatus status;
    660 #ifdef NEW_HIVIEW_PARENT_EVENT_HANDLER
    661     if(_windowEventHandlerRef)
    662     {
    663         status = RemoveEventHandler(_windowEventHandlerRef);
    664         if(status != noErr)
    665         {
    666             //WEBRTC_TRACE(kTraceDebug, "%s:%d failed to remove window event handler %d", __FUNCTION__, __LINE__, (int)_windowEventHandlerRef);
    667         }
    668     }
    669 #endif
    670 
    671 #ifdef NEW_HIVIEW_EVENT_HANDLER
    672     if(_hiviewEventHandlerRef)
    673     {
    674         status = RemoveEventHandler(_hiviewEventHandlerRef);
    675         if(status != noErr)
    676         {
    677             //WEBRTC_TRACE(kTraceDebug, "%s:%d Failed to remove hiview event handler: %d", __FUNCTION__, __LINE__, (int)_hiviewEventHandlerRef);
    678         }
    679     }
    680 #endif
    681 
    682     // Signal event to exit thread, then delete it
    683     ThreadWrapper* tmpPtr = _screenUpdateThread;
    684     _screenUpdateThread = NULL;
    685 
    686     if (tmpPtr)
    687     {
    688         tmpPtr->SetNotAlive();
    689         _screenUpdateEvent->Set();
    690         _screenUpdateEvent->StopTimer();
    691 
    692         if (tmpPtr->Stop())
    693         {
    694             delete tmpPtr;
    695         }
    696         delete _screenUpdateEvent;
    697         _screenUpdateEvent = NULL;
    698     }
    699 
    700     if (_aglContext != 0)
    701     {
    702         aglSetCurrentContext(_aglContext);
    703         aglDestroyContext(_aglContext);
    704         _aglContext = 0;
    705     }
    706 
    707     // Delete all channels
    708     std::map<int, VideoChannelAGL*>::iterator it = _aglChannels.begin();
    709     while (it!= _aglChannels.end())
    710     {
    711         delete it->second;
    712         _aglChannels.erase(it);
    713         it = _aglChannels.begin();
    714     }
    715     _aglChannels.clear();
    716 
    717     // Clean the zOrder map
    718     std::multimap<int, int>::iterator zIt = _zOrderToChannel.begin();
    719     while(zIt != _zOrderToChannel.end())
    720     {
    721         _zOrderToChannel.erase(zIt);
    722         zIt = _zOrderToChannel.begin();
    723     }
    724     _zOrderToChannel.clear();
    725 
    726     //delete _renderCritSec;
    727 
    728 
    729 }
    730 
    731 int VideoRenderAGL::GetOpenGLVersion(int& aglMajor, int& aglMinor)
    732 {
    733     aglGetVersion((GLint *) &aglMajor, (GLint *) &aglMinor);
    734     return 0;
    735 }
    736 
    737 int VideoRenderAGL::Init()
    738 {
    739     LockAGLCntx();
    740 
    741     // Start rendering thread...
    742     if (!_screenUpdateThread)
    743     {
    744         UnlockAGLCntx();
    745         //WEBRTC_TRACE(kTraceError, "%s:%d Thread not created", __FUNCTION__, __LINE__);
    746         return -1;
    747     }
    748     unsigned int threadId;
    749     _screenUpdateThread->Start(threadId);
    750 
    751     // Start the event triggering the render process
    752     unsigned int monitorFreq = 60;
    753     _screenUpdateEvent->StartTimer(true, 1000/monitorFreq);
    754 
    755     // Create mixing textures
    756     if (CreateMixingContext() == -1)
    757     {
    758         //WEBRTC_TRACE(kTraceError, "%s:%d Could not create a mixing context", __FUNCTION__, __LINE__);
    759         UnlockAGLCntx();
    760         return -1;
    761     }
    762 
    763     UnlockAGLCntx();
    764     return 0;
    765 }
    766 
    767 VideoChannelAGL* VideoRenderAGL::CreateAGLChannel(int channel, int zOrder, float startWidth, float startHeight, float stopWidth, float stopHeight)
    768 {
    769 
    770     LockAGLCntx();
    771 
    772     //WEBRTC_TRACE(kTraceInfo, "%s:%d Creating AGL channel: %d", __FUNCTION__, __LINE__, channel);
    773 
    774     if (HasChannel(channel))
    775     {
    776         //WEBRTC_TRACE(kTraceError, "%s:%d Channel already exists", __FUNCTION__, __LINE__);
    777         UnlockAGLCntx();k
    778         return NULL;
    779     }
    780 
    781     if (_zOrderToChannel.find(zOrder) != _zOrderToChannel.end())
    782     {
    783         // There are already one channel using this zOrder
    784         // TODO: Allow multiple channels with same zOrder
    785     }
    786 
    787     VideoChannelAGL* newAGLChannel = new VideoChannelAGL(_aglContext, _id, this);
    788 
    789     if (newAGLChannel->SetStreamSettings(0, startWidth, startHeight, stopWidth, stopHeight) == -1)
    790     {
    791         if (newAGLChannel)
    792         {
    793             delete newAGLChannel;
    794             newAGLChannel = NULL;
    795         }
    796         //WEBRTC_LOG(kTraceError, "Could not create AGL channel");
    797         //WEBRTC_TRACE(kTraceError, "%s:%d Could not create AGL channel", __FUNCTION__, __LINE__);
    798         UnlockAGLCntx();
    799         return NULL;
    800     }
    801 k
    802     _aglChannels[channel] = newAGLChannel;
    803     _zOrderToChannel.insert(std::pair<int, int>(zOrder, channel));
    804 
    805     UnlockAGLCntx();
    806     return newAGLChannel;
    807 }
    808 
    809 int VideoRenderAGL::DeleteAllAGLChannels()
    810 {
    811     CriticalSectionScoped cs(&_renderCritSec);
    812 
    813     //WEBRTC_TRACE(kTraceInfo, "%s:%d Deleting all AGL channels", __FUNCTION__, __LINE__);
    814     //int i = 0 ;
    815     std::map<int, VideoChannelAGL*>::iterator it;
    816     it = _aglChannels.begin();
    817 
    818     while (it != _aglChannels.end())
    819     {
    820         VideoChannelAGL* channel = it->second;
    821         if (channel)
    822         delete channel;
    823 
    824         _aglChannels.erase(it);
    825         it = _aglChannels.begin();
    826     }
    827     _aglChannels.clear();
    828     return 0;
    829 }
    830 
    831 int VideoRenderAGL::DeleteAGLChannel(int channel)
    832 {
    833     CriticalSectionScoped cs(&_renderCritSec);
    834     //WEBRTC_TRACE(kTraceDebug, "%s:%d Deleting AGL channel %d", __FUNCTION__, __LINE__, channel);
    835 
    836     std::map<int, VideoChannelAGL*>::iterator it;
    837     it = _aglChannels.find(channel);
    838     if (it != _aglChannels.end())
    839     {
    840         delete it->second;
    841         _aglChannels.erase(it);
    842     }
    843     else
    844     {
    845         //WEBRTC_TRACE(kTraceWarning, "%s:%d Channel not found", __FUNCTION__, __LINE__);
    846         return -1;
    847     }
    848 
    849     std::multimap<int, int>::iterator zIt = _zOrderToChannel.begin();
    850     while( zIt != _zOrderToChannel.end())
    851     {
    852         if (zIt->second == channel)
    853         {
    854             _zOrderToChannel.erase(zIt);
    855             break;
    856         }
    857         zIt++;// = _zOrderToChannel.begin();
    858     }
    859 
    860     return 0;
    861 }
    862 
    863 int VideoRenderAGL::StopThread()
    864 {
    865     CriticalSectionScoped cs(&_renderCritSec);
    866     ThreadWrapper* tmpPtr = _screenUpdateThread;
    867     //_screenUpdateThread = NULL;
    868 
    869     if (tmpPtr)
    870     {
    871         tmpPtr->SetNotAlive();
    872         _screenUpdateEvent->Set();
    873         if (tmpPtr->Stop())
    874         {
    875             delete tmpPtr;
    876         }
    877     }
    878 
    879     delete _screenUpdateEvent;
    880     _screenUpdateEvent = NULL;
    881 
    882     return 0;
    883 }
    884 
    885 bool VideoRenderAGL::IsFullScreen()
    886 {
    887     CriticalSectionScoped cs(&_renderCritSec);
    888     return _fullScreen;
    889 }
    890 
    891 bool VideoRenderAGL::HasChannels()
    892 {
    893 
    894     CriticalSectionScoped cs(&_renderCritSec);
    895 
    896     if (_aglChannels.begin() != _aglChannels.end())
    897     {
    898         return true;
    899     }
    900 
    901     return false;
    902 }
    903 
    904 bool VideoRenderAGL::HasChannel(int channel)
    905 {
    906     CriticalSectionScoped cs(&_renderCritSec);
    907 
    908     std::map<int, VideoChannelAGL*>::iterator it = _aglChannels.find(channel);
    909     if (it != _aglChannels.end())
    910     {
    911         return true;
    912     }
    913 
    914     return false;
    915 }
    916 
    917 int VideoRenderAGL::GetChannels(std::list<int>& channelList)
    918 {
    919 
    920     CriticalSectionScoped cs(&_renderCritSec);
    921     std::map<int, VideoChannelAGL*>::iterator it = _aglChannels.begin();
    922 
    923     while (it != _aglChannels.end())
    924     {
    925         channelList.push_back(it->first);
    926         it++;
    927     }
    928 
    929     return 0;
    930 }
    931 
    932 VideoChannelAGL* VideoRenderAGL::ConfigureAGLChannel(int channel, int zOrder, float startWidth, float startHeight, float stopWidth, float stopHeight)
    933 {
    934 
    935     CriticalSectionScoped cs(&_renderCritSec);
    936 
    937     std::map<int, VideoChannelAGL*>::iterator it = _aglChannels.find(channel);
    938 
    939     if (it != _aglChannels.end())
    940     {
    941         VideoChannelAGL* aglChannel = it->second;
    942         if (aglChannel->SetStreamSettings(0, startWidth, startHeight, stopWidth, stopHeight) == -1)
    943         {
    944             return NULL;
    945         }
    946 
    947         std::multimap<int, int>::iterator it = _zOrderToChannel.begin();
    948         while(it != _zOrderToChannel.end())
    949         {
    950             if (it->second == channel)
    951             {
    952                 if (it->first != zOrder)
    953                 {
    954                     _zOrderToChannel.erase(it);
    955                     _zOrderToChannel.insert(std::pair<int, int>(zOrder, channel));
    956                 }
    957                 break;
    958             }
    959             it++;
    960         }
    961         return aglChannel;
    962     }
    963 
    964     return NULL;
    965 }
    966 
    967 bool VideoRenderAGL::ScreenUpdateThreadProc(void* obj)
    968 {
    969     return static_cast<VideoRenderAGL*>(obj)->ScreenUpdateProcess();
    970 }
    971 
    972 bool VideoRenderAGL::ScreenUpdateProcess()
    973 {
    974     _screenUpdateEvent->Wait(100);
    975 
    976     LockAGLCntx();
    977 
    978     if (!_screenUpdateThread)
    979     {
    980         UnlockAGLCntx();
    981         return false;
    982     }
    983 
    984     if (aglSetCurrentContext(_aglContext) == GL_FALSE)
    985     {
    986         UnlockAGLCntx();
    987         return true;
    988     }
    989 
    990     if (GetWindowRect(_windowRect) == -1)
    991     {
    992         UnlockAGLCntx();
    993         return true;
    994     }
    995 
    996     if (_windowWidth != (_windowRect.right - _windowRect.left)
    997             || _windowHeight != (_windowRect.bottom - _windowRect.top))
    998     {
    999         // We have a new window size, update the context.
   1000         if (aglUpdateContext(_aglContext) == GL_FALSE)
   1001         {
   1002             UnlockAGLCntx();
   1003             return true;
   1004         }
   1005         _windowWidth = _windowRect.right - _windowRect.left;
   1006         _windowHeight = _windowRect.bottom - _windowRect.top;
   1007     }
   1008 
   1009     // this section will poll to see if the window size has changed
   1010     // this is causing problem w/invalid windowRef
   1011     // this code has been modified and exists now in the window event handler
   1012 #ifndef NEW_HIVIEW_PARENT_EVENT_HANDLER
   1013     if (_isHIViewRef)
   1014     {
   1015 
   1016         if(FALSE == HIViewIsValid(_hiviewRef))
   1017         {
   1018 
   1019             //WEBRTC_TRACE(kTraceDebug, "%s:%d Invalid windowRef", __FUNCTION__, __LINE__);
   1020             UnlockAGLCntx();
   1021             return true;
   1022         }
   1023         WindowRef window = HIViewGetWindow(_hiviewRef);
   1024 
   1025         if(FALSE == IsValidWindowPtr(window))
   1026         {
   1027             //WEBRTC_TRACE(kTraceDebug, "%s:%d Invalide hiviewRef", __FUNCTION__, __LINE__);
   1028             UnlockAGLCntx();
   1029             return true;
   1030         }
   1031         if (window == NULL)
   1032         {
   1033             //WEBRTC_TRACE(kTraceDebug, "%s:%d WindowRef = NULL", __FUNCTION__, __LINE__);
   1034             UnlockAGLCntx();
   1035             return true;
   1036         }
   1037 
   1038         if(FALSE == MacIsWindowVisible(window))
   1039         {
   1040             //WEBRTC_TRACE(kTraceDebug, "%s:%d MacIsWindowVisible == FALSE. Returning early", __FUNCTION__, __LINE__);
   1041             UnlockAGLCntx();
   1042             return true;
   1043         }
   1044 
   1045         HIRect viewBounds; // Placement and size for HIView
   1046         int windowWidth = 0; // Parent window width
   1047         int windowHeight = 0; // Parent window height
   1048 
   1049         // NOTE: Calling GetWindowBounds with kWindowStructureRgn will crash intermittentaly if the OS decides it needs to push it into the back for a moment.
   1050         // To counter this, we get the titlebar height on class construction and then add it to the content region here. Content regions seems not to crash
   1051         Rect contentBounds =
   1052         {   0, 0, 0, 0}; // The bounds for the parent window
   1053 
   1054 #if		defined(USE_CONTENT_RGN)
   1055         GetWindowBounds(window, kWindowContentRgn, &contentBounds);
   1056 #elif	defined(USE_STRUCT_RGN)
   1057         GetWindowBounds(window, kWindowStructureRgn, &contentBounds);
   1058 #endif
   1059 
   1060         Rect globalBounds =
   1061         {   0, 0, 0, 0}; // The bounds for the parent window
   1062         globalBounds.top = contentBounds.top;
   1063         globalBounds.right = contentBounds.right;
   1064         globalBounds.bottom = contentBounds.bottom;
   1065         globalBounds.left = contentBounds.left;
   1066 
   1067         windowHeight = globalBounds.bottom - globalBounds.top;
   1068         windowWidth = globalBounds.right - globalBounds.left;
   1069 
   1070         // Get the size of the HIViewRef
   1071         HIViewGetBounds(_hiviewRef, &viewBounds);
   1072         HIViewConvertRect(&viewBounds, _hiviewRef, NULL);
   1073 
   1074         // Check if this is the first call..
   1075         if (_lastWindowHeight == -1 &&
   1076                 _lastWindowWidth == -1)
   1077         {
   1078             _lastWindowWidth = windowWidth;
   1079             _lastWindowHeight = windowHeight;
   1080 
   1081             _lastViewBounds.origin.x = viewBounds.origin.x;
   1082             _lastViewBounds.origin.y = viewBounds.origin.y;
   1083             _lastViewBounds.size.width = viewBounds.size.width;
   1084             _lastViewBounds.size.height = viewBounds.size.height;
   1085         }
   1086         sfasdfasdf
   1087 
   1088         bool resized = false;
   1089 
   1090         // Check if parent window size has changed
   1091         if (windowHeight != _lastWindowHeight ||
   1092                 windowWidth != _lastWindowWidth)
   1093         {
   1094             resized = true;
   1095         }
   1096 
   1097         // Check if the HIView has new size or is moved in the parent window
   1098         if (_lastViewBounds.origin.x != viewBounds.origin.x ||
   1099                 _lastViewBounds.origin.y != viewBounds.origin.y ||
   1100                 _lastViewBounds.size.width != viewBounds.size.width ||
   1101                 _lastViewBounds.size.height != viewBounds.size.height)
   1102         {
   1103             // The HiView is resized or has moved.
   1104             resized = true;
   1105         }
   1106 
   1107         if (resized)
   1108         {
   1109 
   1110             //WEBRTC_TRACE(kTraceDebug, "%s:%d Window has resized", __FUNCTION__, __LINE__);
   1111 
   1112             // Calculate offset between the windows
   1113             // {x, y, widht, height}, x,y = lower left corner
   1114             const GLint offs[4] =
   1115             {   (int)(0.5f + viewBounds.origin.x),
   1116                 (int)(0.5f + windowHeight - (viewBounds.origin.y + viewBounds.size.height)),
   1117                 viewBounds.size.width, viewBounds.size.height};
   1118 
   1119             //WEBRTC_TRACE(kTraceDebug, "%s:%d contentBounds	t:%d r:%d b:%d l:%d", __FUNCTION__, __LINE__,
   1120             contentBounds.top, contentBounds.right, contentBounds.bottom, contentBounds.left);
   1121             //WEBRTC_TRACE(kTraceDebug, "%s:%d windowHeight=%d", __FUNCTION__, __LINE__, windowHeight);
   1122             //WEBRTC_TRACE(kTraceDebug, "%s:%d offs[4] = %d, %d, %d, %d", __FUNCTION__, __LINE__, offs[0], offs[1], offs[2], offs[3]);
   1123 
   1124             aglSetDrawable (_aglContext, GetWindowPort(window));
   1125             aglSetInteger(_aglContext, AGL_BUFFER_RECT, offs);
   1126             aglEnable(_aglContext, AGL_BUFFER_RECT);
   1127 
   1128             // We need to change the viewport too if the HIView size has changed
   1129             glViewport(0.0f, 0.0f, (GLsizei) viewBounds.size.width, (GLsizei) viewBounds.size.height);
   1130 
   1131         }
   1132         _lastWindowWidth = windowWidth;
   1133         _lastWindowHeight = windowHeight;
   1134 
   1135         _lastViewBounds.origin.x = viewBounds.origin.x;
   1136         _lastViewBounds.origin.y = viewBounds.origin.y;
   1137         _lastViewBounds.size.width = viewBounds.size.width;
   1138         _lastViewBounds.size.height = viewBounds.size.height;
   1139 
   1140     }
   1141 #endif
   1142     if (_fullScreen)
   1143     {
   1144         // TODO
   1145         // We use double buffers, must always update
   1146         //RenderOffScreenBuffersToBackBuffer();
   1147     }
   1148     else
   1149     {
   1150         // Check if there are any updated buffers
   1151         bool updated = false;
   1152 
   1153         // TODO: check if window size is updated!
   1154         // TODO Improvement: Walk through the zOrder Map to only render the ones in need of update
   1155         std::map<int, VideoChannelAGL*>::iterator it = _aglChannels.begin();
   1156         while (it != _aglChannels.end())
   1157         {
   1158 
   1159             VideoChannelAGL* aglChannel = it->second;
   1160             aglChannel->UpdateStretchSize(_windowHeight, _windowWidth);
   1161             aglChannel->IsUpdated(updated);
   1162             if (updated)
   1163             {
   1164                 break;
   1165             }
   1166             it++;
   1167         }
   1168 
   1169         if (updated)
   1170         {
   1171             // At least on buffers is updated, we need to repaint the texture
   1172             if (RenderOffScreenBuffers() != -1)
   1173             {
   1174                 // MF
   1175                 //SwapAndDisplayBuffers();
   1176             }
   1177             else
   1178             {
   1179                 // Error updating the mixing texture, don't swap.
   1180             }
   1181         }
   1182     }
   1183 
   1184     UnlockAGLCntx();
   1185 
   1186     //WEBRTC_LOG(kTraceDebug, "Leaving ScreenUpdateProcess()");
   1187     return true;
   1188 }
   1189 
   1190 void VideoRenderAGL::ParentWindowResized(WindowRef window)
   1191 {
   1192     //WEBRTC_LOG(kTraceDebug, "%s HIViewRef:%d owner window has resized", __FUNCTION__, (int)_hiviewRef);
   1193 
   1194     LockAGLCntx();
   1195 k
   1196     // set flag
   1197     _windowHasResized = false;
   1198 
   1199     if(FALSE == HIViewIsValid(_hiviewRef))
   1200     {
   1201         //WEBRTC_LOG(kTraceDebug, "invalid windowRef");
   1202         UnlockAGLCntx();
   1203         return;
   1204     }
   1205 
   1206     if(FALSE == IsValidWindowPtr(window))
   1207     {
   1208         //WEBRTC_LOG(kTraceError, "invalid windowRef");
   1209         UnlockAGLCntx();
   1210         return;
   1211     }
   1212 
   1213     if (window == NULL)
   1214     {
   1215         //WEBRTC_LOG(kTraceError, "windowRef = NULL");
   1216         UnlockAGLCntx();
   1217         return;
   1218     }
   1219 
   1220     if(FALSE == MacIsWindowVisible(window))
   1221     {
   1222         //WEBRTC_LOG(kTraceDebug, "MacIsWindowVisible = FALSE. Returning early.");
   1223         UnlockAGLCntx();
   1224         return;
   1225     }
   1226 
   1227     Rect contentBounds =
   1228     {   0, 0, 0, 0};
   1229 
   1230 #if		defined(USE_CONTENT_RGN)
   1231     GetWindowBounds(window, kWindowContentRgn, &contentBounds);
   1232 #elif	defined(USE_STRUCT_RGN)
   1233     GetWindowBounds(window, kWindowStructureRgn, &contentBounds);
   1234 #endif
   1235 
   1236     //WEBRTC_LOG(kTraceDebug, "%s contentBounds	t:%d r:%d b:%d l:%d", __FUNCTION__, contentBounds.top, contentBounds.right, contentBounds.bottom, contentBounds.left);
   1237 
   1238     // update global vars
   1239     _currentParentWindowBounds.top = contentBounds.top;
   1240     _currentParentWindowBounds.left = contentBounds.left;
   1241     _currentParentWindowBounds.bottom = contentBounds.bottom;
   1242     _currentParentWindowBounds.right = contentBounds.right;
   1243 
   1244     _currentParentWindowWidth = _currentParentWindowBounds.right - _currentParentWindowBounds.left;
   1245     _currentParentWindowHeight = _currentParentWindowBounds.bottom - _currentParentWindowBounds.top;
   1246 
   1247     _windowHasResized = true;
   1248 
   1249     // ********* update AGL offsets
   1250     HIRect viewBounds;
   1251     HIViewGetBounds(_hiviewRef, &viewBounds);
   1252     HIViewConvertRect(&viewBounds, _hiviewRef, NULL);
   1253 
   1254     const GLint offs[4] =
   1255     {   (int)(0.5f + viewBounds.origin.x),
   1256         (int)(0.5f + _currentParentWindowHeight - (viewBounds.origin.y + viewBounds.size.height)),
   1257         viewBounds.size.width, viewBounds.size.height};
   1258     //WEBRTC_LOG(kTraceDebug, "%s _currentParentWindowHeight=%d", __FUNCTION__, _currentParentWindowHeight);
   1259     //WEBRTC_LOG(kTraceDebug, "%s offs[4] = %d, %d, %d, %d", __FUNCTION__, offs[0], offs[1], offs[2], offs[3]);
   1260 
   1261     aglSetCurrentContext(_aglContext);
   1262     aglSetDrawable (_aglContext, GetWindowPort(window));
   1263     aglSetInteger(_aglContext, AGL_BUFFER_RECT, offs);
   1264     aglEnable(_aglContext, AGL_BUFFER_RECT);
   1265 
   1266     // We need to change the viewport too if the HIView size has changed
   1267     glViewport(0.0f, 0.0f, (GLsizei) viewBounds.size.width, (GLsizei) viewBounds.size.height);
   1268 
   1269     UnlockAGLCntx();
   1270 
   1271     return;
   1272 }
   1273 
   1274 int VideoRenderAGL::CreateMixingContext()
   1275 {
   1276 
   1277     LockAGLCntx();
   1278 
   1279     //WEBRTC_LOG(kTraceDebug, "Entering CreateMixingContext()");
   1280 
   1281     // Use both AGL_ACCELERATED and AGL_NO_RECOVERY to make sure
   1282     // a hardware renderer is used and not a software renderer.
   1283 
   1284     GLint attributes[] =
   1285     {
   1286         AGL_DOUBLEBUFFER,
   1287         AGL_WINDOW,
   1288         AGL_RGBA,
   1289         AGL_NO_RECOVERY,
   1290         AGL_ACCELERATED,
   1291         AGL_RED_SIZE, 8,
   1292         AGL_GREEN_SIZE, 8,
   1293         AGL_BLUE_SIZE, 8,
   1294         AGL_ALPHA_SIZE, 8,
   1295         AGL_DEPTH_SIZE, 24,
   1296         AGL_NONE,
   1297     };
   1298 
   1299     AGLPixelFormat aglPixelFormat;
   1300 
   1301     // ***** Set up the OpenGL Context *****
   1302 
   1303     // Get a pixel format for the attributes above
   1304     aglPixelFormat = aglChoosePixelFormat(NULL, 0, attributes);
   1305     if (NULL == aglPixelFormat)
   1306     {
   1307         //WEBRTC_LOG(kTraceError, "Could not create pixel format");
   1308         UnlockAGLCntx();
   1309         return -1;
   1310     }
   1311 
   1312     // Create an AGL context
   1313     _aglContext = aglCreateContext(aglPixelFormat, NULL);
   1314     if (_aglContext == NULL)
   1315     {
   1316         //WEBRTC_LOG(kTraceError, "Could no create AGL context");
   1317         UnlockAGLCntx();
   1318         return -1;
   1319     }
   1320 
   1321     // Release the pixel format memory
   1322     aglDestroyPixelFormat(aglPixelFormat);
   1323 
   1324     // Set the current AGL context for the rest of the settings
   1325     if (aglSetCurrentContext(_aglContext) == false)
   1326     {
   1327         //WEBRTC_LOG(kTraceError, "Could not set current context: %d", aglGetError());
   1328         UnlockAGLCntx();
   1329         return -1;
   1330     }
   1331 
   1332     if (_isHIViewRef)
   1333     {
   1334         //---------------------------
   1335         // BEGIN: new test code
   1336 #if 0
   1337         // Don't use this one!
   1338         // There seems to be an OS X bug that can't handle
   1339         // movements and resizing of the parent window
   1340         // and or the HIView
   1341         if (aglSetHIViewRef(_aglContext,_hiviewRef) == false)
   1342         {
   1343             //WEBRTC_LOG(kTraceError, "Could not set WindowRef: %d", aglGetError());
   1344             UnlockAGLCntx();
   1345             return -1;
   1346         }
   1347 #else
   1348 
   1349         // Get the parent window for this control
   1350         WindowRef window = GetControlOwner(_hiviewRef);
   1351 
   1352         Rect globalBounds =
   1353         {   0,0,0,0}; // The bounds for the parent window
   1354         HIRect viewBounds; // Placemnt in the parent window and size.
   1355         int windowHeight = 0;
   1356 
   1357         //		Rect titleBounds = {0,0,0,0};
   1358         //		GetWindowBounds(window, kWindowTitleBarRgn, &titleBounds);
   1359         //		_titleBarHeight = titleBounds.top - titleBounds.bottom;
   1360         //		if(0 == _titleBarHeight)
   1361         //		{
   1362         //            //WEBRTC_LOG(kTraceError, "Titlebar height = 0");
   1363         //            //return -1;
   1364         //		}
   1365 
   1366 
   1367         // Get the bounds for the parent window
   1368 #if		defined(USE_CONTENT_RGN)
   1369         GetWindowBounds(window, kWindowContentRgn, &globalBounds);
   1370 #elif	defined(USE_STRUCT_RGN)
   1371         GetWindowBounds(window, kWindowStructureRgn, &globalBounds);
   1372 #endif
   1373         windowHeight = globalBounds.bottom - globalBounds.top;
   1374 
   1375         // Get the bounds for the HIView
   1376         HIViewGetBounds(_hiviewRef, &viewBounds);
   1377 
   1378         HIViewConvertRect(&viewBounds, _hiviewRef, NULL);
   1379 
   1380         const GLint offs[4] =
   1381         {   (int)(0.5f + viewBounds.origin.x),
   1382             (int)(0.5f + windowHeight - (viewBounds.origin.y + viewBounds.size.height)),
   1383             viewBounds.size.width, viewBounds.size.height};
   1384 
   1385         //WEBRTC_LOG(kTraceDebug, "%s offs[4] = %d, %d, %d, %d", __FUNCTION__, offs[0], offs[1], offs[2], offs[3]);
   1386 
   1387 
   1388         aglSetDrawable (_aglContext, GetWindowPort(window));
   1389         aglSetInteger(_aglContext, AGL_BUFFER_RECT, offs);
   1390         aglEnable(_aglContext, AGL_BUFFER_RECT);
   1391 
   1392         GLint surfaceOrder = 1; // 1: above window, -1 below.
   1393         //OSStatus status = aglSetInteger(_aglContext, AGL_SURFACE_ORDER, &surfaceOrder);
   1394         aglSetInteger(_aglContext, AGL_SURFACE_ORDER, &surfaceOrder);
   1395 
   1396         glViewport(0.0f, 0.0f, (GLsizei) viewBounds.size.width, (GLsizei) viewBounds.size.height);
   1397 #endif
   1398 
   1399     }
   1400     else
   1401     {
   1402         if(GL_FALSE == aglSetDrawable (_aglContext, GetWindowPort(_windowRef)))
   1403         {
   1404             //WEBRTC_LOG(kTraceError, "Could not set WindowRef: %d", aglGetError());
   1405             UnlockAGLCntx();
   1406             return -1;
   1407         }
   1408     }
   1409 
   1410     _windowWidth = _windowRect.right - _windowRect.left;
   1411     _windowHeight = _windowRect.bottom - _windowRect.top;
   1412 
   1413     // opaque surface
   1414     int surfaceOpacity = 1;
   1415     if (aglSetInteger(_aglContext, AGL_SURFACE_OPACITY, (const GLint *) &surfaceOpacity) == false)
   1416     {
   1417         //WEBRTC_LOG(kTraceError, "Could not set surface opacity: %d", aglGetError());
   1418         UnlockAGLCntx();
   1419         return -1;
   1420     }
   1421 
   1422     // 1 -> sync to screen rat, slow...
   1423     //int swapInterval = 0;  // 0 don't sync with vertical trace
   1424     int swapInterval = 0; // 1 sync with vertical trace
   1425     if (aglSetInteger(_aglContext, AGL_SWAP_INTERVAL, (const GLint *) &swapInterval) == false)
   1426     {
   1427         //WEBRTC_LOG(kTraceError, "Could not set swap interval: %d", aglGetError());
   1428         UnlockAGLCntx();
   1429         return -1;
   1430     }
   1431 
   1432     // Update the rect with the current size
   1433     if (GetWindowRect(_windowRect) == -1)
   1434     {
   1435         //WEBRTC_LOG(kTraceError, "Could not get window size");
   1436         UnlockAGLCntx();
   1437         return -1;
   1438     }
   1439 
   1440     // Disable not needed functionality to increase performance
   1441     glDisable(GL_DITHER);
   1442     glDisable(GL_ALPHA_TEST);
   1443     glDisable(GL_STENCIL_TEST);
   1444     glDisable(GL_FOG);
   1445     glDisable(GL_TEXTURE_2D);
   1446     glPixelZoom(1.0, 1.0);
   1447 
   1448     glDisable(GL_BLEND);
   1449     glDisable(GL_DEPTH_TEST);
   1450     glDepthMask(GL_FALSE);
   1451     glDisable(GL_CULL_FACE);
   1452 
   1453     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
   1454     glClear(GL_COLOR_BUFFER_BIT);
   1455 
   1456     GLenum glErr = glGetError();
   1457 
   1458     if (glErr)
   1459     {
   1460     }
   1461 
   1462     UpdateClipping();
   1463 
   1464     //WEBRTC_LOG(kTraceDebug, "Leaving CreateMixingContext()");
   1465 
   1466     UnlockAGLCntx();
   1467     return 0;
   1468 }
   1469 
   1470 int VideoRenderAGL::RenderOffScreenBuffers()
   1471 {
   1472     LockAGLCntx();
   1473 
   1474     // Get the current window size, it might have changed since last render.
   1475     if (GetWindowRect(_windowRect) == -1)
   1476     {
   1477         //WEBRTC_LOG(kTraceError, "Could not get window rect");
   1478         UnlockAGLCntx();
   1479         return -1;
   1480     }
   1481 
   1482     if (aglSetCurrentContext(_aglContext) == false)
   1483     {
   1484         //WEBRTC_LOG(kTraceError, "Could not set current context for rendering");
   1485         UnlockAGLCntx();
   1486         return -1;
   1487     }
   1488 
   1489     // HERE - onl if updated!
   1490     glClear(GL_COLOR_BUFFER_BIT);
   1491 
   1492     // Loop through all channels starting highest zOrder ending with lowest.
   1493     for (std::multimap<int, int>::reverse_iterator rIt = _zOrderToChannel.rbegin();
   1494     rIt != _zOrderToChannel.rend();
   1495     rIt++)
   1496     {
   1497         int channelId = rIt->second;
   1498         std::map<int, VideoChannelAGL*>::iterator it = _aglChannels.find(channelId);
   1499 
   1500         VideoChannelAGL* aglChannel = it->second;
   1501 
   1502         aglChannel->RenderOffScreenBuffer();
   1503     }
   1504 
   1505     SwapAndDisplayBuffers();
   1506 
   1507     UnlockAGLCntx();
   1508     return 0;
   1509 }
   1510 
   1511 int VideoRenderAGL::SwapAndDisplayBuffers()
   1512 {
   1513 
   1514     LockAGLCntx();
   1515     if (_fullScreen)
   1516     {
   1517         // TODO:
   1518         // Swap front and back buffers, rendering taking care of in the same call
   1519         //aglSwapBuffers(_aglContext);
   1520         // Update buffer index to the idx for the next rendering!
   1521         //_textureIdx = (_textureIdx + 1) & 1;
   1522     }
   1523     else
   1524     {
   1525         // Single buffer rendering, only update context.
   1526         glFlush();
   1527         aglSwapBuffers(_aglContext);
   1528         HIViewSetNeedsDisplay(_hiviewRef, true);
   1529     }
   1530 
   1531     UnlockAGLCntx();
   1532     return 0;
   1533 }
   1534 
   1535 int VideoRenderAGL::GetWindowRect(Rect& rect)
   1536 {
   1537 
   1538     LockAGLCntx();
   1539 
   1540     if (_isHIViewRef)
   1541     {
   1542         if (_hiviewRef)
   1543         {
   1544             HIRect HIViewRect1;
   1545             if(FALSE == HIViewIsValid(_hiviewRef))
   1546             {
   1547                 rect.top = 0;
   1548                 rect.left = 0;
   1549                 rect.right = 0;
   1550                 rect.bottom = 0;
   1551                 //WEBRTC_LOG(kTraceError,"GetWindowRect() HIViewIsValid() returned false");
   1552                 UnlockAGLCntx();
   1553             }
   1554             HIViewGetBounds(_hiviewRef,&HIViewRect1);
   1555             HIRectConvert(&HIViewRect1, 1, NULL, 2, NULL);
   1556             if(HIViewRect1.origin.x < 0)
   1557             {
   1558                 rect.top = 0;
   1559                 //WEBRTC_LOG(kTraceDebug, "GetWindowRect() rect.top = 0");
   1560             }
   1561             else
   1562             {
   1563                 rect.top = HIViewRect1.origin.x;
   1564             }
   1565 
   1566             if(HIViewRect1.origin.y < 0)
   1567             {
   1568                 rect.left = 0;
   1569                 //WEBRTC_LOG(kTraceDebug, "GetWindowRect() rect.left = 0");
   1570             }
   1571             else
   1572             {
   1573                 rect.left = HIViewRect1.origin.y;
   1574             }
   1575 
   1576             if(HIViewRect1.size.width < 0)
   1577             {
   1578                 rect.right = 0;
   1579                 //WEBRTC_LOG(kTraceDebug, "GetWindowRect() rect.right = 0");
   1580             }
   1581             else
   1582             {
   1583                 rect.right = HIViewRect1.size.width;
   1584             }
   1585 
   1586             if(HIViewRect1.size.height < 0)
   1587             {
   1588                 rect.bottom = 0;
   1589                 //WEBRTC_LOG(kTraceDebug, "GetWindowRect() rect.bottom = 0");
   1590             }
   1591             else
   1592             {
   1593                 rect.bottom = HIViewRect1.size.height;
   1594             }
   1595 
   1596             ////WEBRTC_LOG(kTraceDebug,"GetWindowRect() HIViewRef: rect.top = %d, rect.left = %d, rect.right = %d, rect.bottom =%d in GetWindowRect", rect.top,rect.left,rect.right,rect.bottom);
   1597             UnlockAGLCntx();
   1598         }
   1599         else
   1600         {
   1601             //WEBRTC_LOG(kTraceError, "invalid HIViewRef");
   1602             UnlockAGLCntx();
   1603         }
   1604     }
   1605     else
   1606     {
   1607         if (_windowRef)
   1608         {
   1609             GetWindowBounds(_windowRef, kWindowContentRgn, &rect);
   1610             UnlockAGLCntx();
   1611         }
   1612         else
   1613         {
   1614             //WEBRTC_LOG(kTraceError, "No WindowRef");
   1615             UnlockAGLCntx();
   1616         }
   1617     }
   1618 }
   1619 
   1620 int VideoRenderAGL::UpdateClipping()
   1621 {
   1622     //WEBRTC_LOG(kTraceDebug, "Entering UpdateClipping()");
   1623     LockAGLCntx();
   1624 
   1625     if(_isHIViewRef)
   1626     {
   1627         if(FALSE == HIViewIsValid(_hiviewRef))
   1628         {
   1629             //WEBRTC_LOG(kTraceError, "UpdateClipping() _isHIViewRef is invalid. Returning -1");
   1630             UnlockAGLCntx();
   1631             return -1;
   1632         }
   1633 
   1634         RgnHandle visibleRgn = NewRgn();
   1635         SetEmptyRgn (visibleRgn);
   1636 
   1637         if(-1 == CalculateVisibleRegion((ControlRef)_hiviewRef, visibleRgn, true))
   1638         {
   1639         }
   1640 
   1641         if(GL_FALSE == aglSetCurrentContext(_aglContext))
   1642         {
   1643             GLenum glErr = aglGetError();
   1644             //WEBRTC_LOG(kTraceError, "aglSetCurrentContext returned FALSE with error code %d at line %d", glErr, __LINE__);
   1645         }
   1646 
   1647         if(GL_FALSE == aglEnable(_aglContext, AGL_CLIP_REGION))
   1648         {
   1649             GLenum glErr = aglGetError();
   1650             //WEBRTC_LOG(kTraceError, "aglEnable returned FALSE with error code %d at line %d\n", glErr, __LINE__);
   1651         }
   1652 
   1653         if(GL_FALSE == aglSetInteger(_aglContext, AGL_CLIP_REGION, (const GLint*)visibleRgn))
   1654         {
   1655             GLenum glErr = aglGetError();
   1656             //WEBRTC_LOG(kTraceError, "aglSetInteger returned FALSE with error code %d at line %d\n", glErr, __LINE__);
   1657         }
   1658 
   1659         DisposeRgn(visibleRgn);
   1660     }
   1661     else
   1662     {
   1663         //WEBRTC_LOG(kTraceDebug, "Not using a hiviewref!\n");
   1664     }
   1665 
   1666     //WEBRTC_LOG(kTraceDebug, "Leaving UpdateClipping()");
   1667     UnlockAGLCntx();
   1668     return true;
   1669 }
   1670 
   1671 int VideoRenderAGL::CalculateVisibleRegion(ControlRef control, RgnHandle &visibleRgn, bool clipChildren)
   1672 {
   1673 
   1674     //	LockAGLCntx();
   1675 
   1676     //WEBRTC_LOG(kTraceDebug, "Entering CalculateVisibleRegion()");
   1677     OSStatus osStatus = 0;
   1678     OSErr osErr = 0;
   1679 
   1680     RgnHandle tempRgn = NewRgn();
   1681     if (IsControlVisible(control))
   1682     {
   1683         RgnHandle childRgn = NewRgn();
   1684         WindowRef window = GetControlOwner(control);
   1685         ControlRef rootControl;
   1686         GetRootControl(window, &rootControl); // 'wvnc'
   1687         ControlRef masterControl;
   1688         osStatus = GetSuperControl(rootControl, &masterControl);
   1689         // //WEBRTC_LOG(kTraceDebug, "IBM GetSuperControl=%d", osStatus);
   1690 
   1691         if (masterControl != NULL)
   1692         {
   1693             CheckValidRegion(visibleRgn);
   1694             // init visibleRgn with region of 'wvnc'
   1695             osStatus = GetControlRegion(rootControl, kControlStructureMetaPart, visibleRgn);
   1696             // //WEBRTC_LOG(kTraceDebug, "IBM GetControlRegion=%d : %d", osStatus, __LINE__);
   1697             //GetSuperControl(rootControl, &rootControl);
   1698             ControlRef tempControl = control, lastControl = 0;
   1699             while (tempControl != masterControl) // current control != master
   1700 
   1701             {
   1702                 CheckValidRegion(tempRgn);
   1703 
   1704                 // //WEBRTC_LOG(kTraceDebug, "IBM tempControl=%d masterControl=%d", tempControl, masterControl);
   1705                 ControlRef subControl;
   1706 
   1707                 osStatus = GetControlRegion(tempControl, kControlStructureMetaPart, tempRgn); // intersect the region of the current control with visibleRgn
   1708                 // //WEBRTC_LOG(kTraceDebug, "IBM GetControlRegion=%d : %d", osStatus, __LINE__);
   1709                 CheckValidRegion(tempRgn);
   1710 
   1711                 osErr = HIViewConvertRegion(tempRgn, tempControl, rootControl);
   1712                 // //WEBRTC_LOG(kTraceDebug, "IBM HIViewConvertRegion=%d : %d", osErr, __LINE__);
   1713                 CheckValidRegion(tempRgn);
   1714 
   1715                 SectRgn(tempRgn, visibleRgn, visibleRgn);
   1716                 CheckValidRegion(tempRgn);
   1717                 CheckValidRegion(visibleRgn);
   1718                 if (EmptyRgn(visibleRgn)) // if the region is empty, bail
   1719                 break;
   1720 
   1721                 if (clipChildren || tempControl != control) // clip children if true, cut out the tempControl if it's not one passed to this function
   1722 
   1723                 {
   1724                     UInt16 numChildren;
   1725                     osStatus = CountSubControls(tempControl, &numChildren); // count the subcontrols
   1726                     // //WEBRTC_LOG(kTraceDebug, "IBM CountSubControls=%d : %d", osStatus, __LINE__);
   1727 
   1728                     // //WEBRTC_LOG(kTraceDebug, "IBM numChildren=%d", numChildren);
   1729                     for (int i = 0; i < numChildren; i++)
   1730                     {
   1731                         osErr = GetIndexedSubControl(tempControl, numChildren - i, &subControl); // retrieve the subcontrol in order by zorder
   1732                         // //WEBRTC_LOG(kTraceDebug, "IBM GetIndexedSubControls=%d : %d", osErr, __LINE__);
   1733                         if ( subControl == lastControl ) // break because of zorder
   1734 
   1735                         {
   1736                             // //WEBRTC_LOG(kTraceDebug, "IBM breaking because of zorder %d", __LINE__);
   1737                             break;
   1738                         }
   1739 
   1740                         if (!IsControlVisible(subControl)) // dont' clip invisible controls
   1741 
   1742                         {
   1743                             // //WEBRTC_LOG(kTraceDebug, "IBM continue. Control is not visible %d", __LINE__);
   1744                             continue;
   1745                         }
   1746 
   1747                         if(!subControl) continue;
   1748 
   1749                         osStatus = GetControlRegion(subControl, kControlStructureMetaPart, tempRgn); //get the region of the current control and union to childrg
   1750                         // //WEBRTC_LOG(kTraceDebug, "IBM GetControlRegion=%d %d", osStatus, __LINE__);
   1751                         CheckValidRegion(tempRgn);
   1752                         if(osStatus != 0)
   1753                         {
   1754                             // //WEBRTC_LOG(kTraceDebug, "IBM ERROR! osStatus=%d. Continuing. %d", osStatus, __LINE__);
   1755                             continue;
   1756                         }
   1757                         if(!tempRgn)
   1758                         {
   1759                             // //WEBRTC_LOG(kTraceDebug, "IBM ERROR! !tempRgn %d", osStatus, __LINE__);
   1760                             continue;
   1761                         }
   1762 
   1763                         osStatus = HIViewConvertRegion(tempRgn, subControl, rootControl);
   1764                         CheckValidRegion(tempRgn);
   1765                         // //WEBRTC_LOG(kTraceDebug, "IBM HIViewConvertRegion=%d %d", osStatus, __LINE__);
   1766                         if(osStatus != 0)
   1767                         {
   1768                             // //WEBRTC_LOG(kTraceDebug, "IBM ERROR! osStatus=%d. Continuing. %d", osStatus, __LINE__);
   1769                             continue;
   1770                         }
   1771                         if(!rootControl)
   1772                         {
   1773                             // //WEBRTC_LOG(kTraceDebug, "IBM ERROR! !rootControl %d", osStatus, __LINE__);
   1774                             continue;
   1775                         }
   1776 
   1777                         UnionRgn(tempRgn, childRgn, childRgn);
   1778                         CheckValidRegion(tempRgn);
   1779                         CheckValidRegion(childRgn);
   1780                         CheckValidRegion(visibleRgn);
   1781                         if(!childRgn)
   1782                         {
   1783                             // //WEBRTC_LOG(kTraceDebug, "IBM ERROR! !childRgn %d", osStatus, __LINE__);
   1784                             continue;
   1785                         }
   1786 
   1787                     }  // next child control
   1788                 }
   1789                 lastControl = tempControl;
   1790                 GetSuperControl(tempControl, &subControl);
   1791                 tempControl = subControl;
   1792             }
   1793 
   1794             DiffRgn(visibleRgn, childRgn, visibleRgn);
   1795             CheckValidRegion(visibleRgn);
   1796             CheckValidRegion(childRgn);
   1797             DisposeRgn(childRgn);
   1798         }
   1799         else
   1800         {
   1801             CopyRgn(tempRgn, visibleRgn);
   1802             CheckValidRegion(tempRgn);
   1803             CheckValidRegion(visibleRgn);
   1804         }
   1805         DisposeRgn(tempRgn);
   1806     }
   1807 
   1808     //WEBRTC_LOG(kTraceDebug, "Leaving CalculateVisibleRegion()");
   1809     //_aglCritPtr->Leave();
   1810     return 0;
   1811 }
   1812 
   1813 bool VideoRenderAGL::CheckValidRegion(RgnHandle rHandle)
   1814 {
   1815 
   1816     Handle hndSize = (Handle)rHandle;
   1817     long size = GetHandleSize(hndSize);
   1818     if(0 == size)
   1819     {
   1820 
   1821         OSErr memErr = MemError();
   1822         if(noErr != memErr)
   1823         {
   1824             // //WEBRTC_LOG(kTraceError, "IBM ERROR Could not get size of handle. MemError() returned %d", memErr);
   1825         }
   1826         else
   1827         {
   1828             // //WEBRTC_LOG(kTraceError, "IBM ERROR Could not get size of handle yet MemError() returned noErr");
   1829         }
   1830 
   1831     }
   1832     else
   1833     {
   1834         // //WEBRTC_LOG(kTraceDebug, "IBM handleSize = %d", size);
   1835     }
   1836 
   1837     if(false == IsValidRgnHandle(rHandle))
   1838     {
   1839         // //WEBRTC_LOG(kTraceError, "IBM ERROR Invalid Region found : $%d", rHandle);
   1840         assert(false);
   1841     }
   1842 
   1843     int err = QDError();
   1844     switch(err)
   1845     {
   1846         case 0:
   1847         break;
   1848         case -147:
   1849         //WEBRTC_LOG(kTraceError, "ERROR region too big");
   1850         assert(false);
   1851         break;
   1852 
   1853         case -149:
   1854         //WEBRTC_LOG(kTraceError, "ERROR not enough stack");
   1855         assert(false);
   1856         break;
   1857 
   1858         default:
   1859         //WEBRTC_LOG(kTraceError, "ERROR Unknown QDError %d", err);
   1860         assert(false);
   1861         break;
   1862     }
   1863 
   1864     return true;
   1865 }
   1866 
   1867 int VideoRenderAGL::ChangeWindow(void* newWindowRef)
   1868 {
   1869 
   1870     LockAGLCntx();
   1871 
   1872     UnlockAGLCntx();
   1873     return -1;
   1874 }
   1875 int32_t VideoRenderAGL::ChangeUniqueID(int32_t id)
   1876 {
   1877     LockAGLCntx();
   1878 
   1879     UnlockAGLCntx();
   1880     return -1;
   1881 }
   1882 
   1883 int32_t VideoRenderAGL::StartRender()
   1884 {
   1885 
   1886     LockAGLCntx();
   1887     const unsigned int MONITOR_FREQ = 60;
   1888     if(TRUE == _renderingIsPaused)
   1889     {
   1890         //WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s:%d Rendering is paused. Restarting now", __FUNCTION__, __LINE__);
   1891 
   1892         // we already have the thread. Most likely StopRender() was called and they were paused
   1893         if(FALSE == _screenUpdateThread->Start(_threadID))
   1894         {
   1895             //WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, "%s:%d Failed to start screenUpdateThread", __FUNCTION__, __LINE__);
   1896             UnlockAGLCntx();
   1897             return -1;
   1898         }
   1899         if(FALSE == _screenUpdateEvent->StartTimer(true, 1000/MONITOR_FREQ))
   1900         {
   1901             //WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, "%s:%d Failed to start screenUpdateEvent", __FUNCTION__, __LINE__);
   1902             UnlockAGLCntx();
   1903             return -1;
   1904         }
   1905 
   1906         return 0;
   1907     }
   1908 
   1909     _screenUpdateThread = ThreadWrapper::CreateThread(ScreenUpdateThreadProc, this, kRealtimePriority);
   1910     _screenUpdateEvent = EventWrapper::Create();
   1911 
   1912     if (!_screenUpdateThread)
   1913     {
   1914         //WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, "%s:%d Failed to start screenUpdateThread", __FUNCTION__, __LINE__);
   1915         UnlockAGLCntx();
   1916         return -1;
   1917     }
   1918 
   1919     _screenUpdateThread->Start(_threadID);
   1920     _screenUpdateEvent->StartTimer(true, 1000/MONITOR_FREQ);
   1921 
   1922     //WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s:%d Started screenUpdateThread", __FUNCTION__, __LINE__);
   1923 
   1924     UnlockAGLCntx();
   1925     return 0;
   1926 
   1927 }
   1928 
   1929 int32_t VideoRenderAGL::StopRender()
   1930 {
   1931     LockAGLCntx();
   1932 
   1933     if(!_screenUpdateThread || !_screenUpdateEvent)
   1934     {
   1935         _renderingIsPaused = TRUE;
   1936         UnlockAGLCntx();
   1937         return 0;
   1938     }
   1939 
   1940     if(FALSE == _screenUpdateThread->Stop() || FALSE == _screenUpdateEvent->StopTimer())
   1941     {
   1942         _renderingIsPaused = FALSE;
   1943         //WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s:%d Could not stop either: screenUpdateThread or screenUpdateEvent", __FUNCTION__, __LINE__);
   1944         UnlockAGLCntx();
   1945         return -1;
   1946     }
   1947 
   1948     _renderingIsPaused = TRUE;
   1949 
   1950     //WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s:%d Stopped screenUpdateThread", __FUNCTION__, __LINE__);
   1951     UnlockAGLCntx();
   1952     return 0;
   1953 }
   1954 
   1955 int32_t VideoRenderAGL::DeleteAGLChannel(const uint32_t streamID)
   1956 {
   1957 
   1958     LockAGLCntx();
   1959 
   1960     std::map<int, VideoChannelAGL*>::iterator it;
   1961     it = _aglChannels.begin();
   1962 
   1963     while (it != _aglChannels.end())
   1964     {
   1965         VideoChannelAGL* channel = it->second;
   1966         //WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s:%d Deleting channel %d", __FUNCTION__, __LINE__, streamID);
   1967         delete channel;
   1968         it++;
   1969     }
   1970     _aglChannels.clear();
   1971 
   1972     UnlockAGLCntx();
   1973     return 0;
   1974 }
   1975 
   1976 int32_t VideoRenderAGL::GetChannelProperties(const uint16_t streamId,
   1977                                              uint32_t& zOrder,
   1978                                              float& left,
   1979                                              float& top,
   1980                                              float& right,
   1981                                              float& bottom)
   1982 {
   1983 
   1984     LockAGLCntx();
   1985     UnlockAGLCntx();
   1986     return -1;
   1987 
   1988 }
   1989 
   1990 void VideoRenderAGL::LockAGLCntx()
   1991 {
   1992     _renderCritSec.Enter();
   1993 }
   1994 void VideoRenderAGL::UnlockAGLCntx()
   1995 {
   1996     _renderCritSec.Leave();
   1997 }
   1998 
   1999 }  // namespace webrtc
   2000 
   2001 #endif   // CARBON_RENDERING
   2002