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