VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m@ 52639

最後變更 在這個檔案從52639是 52625,由 vboxsync 提交於 11 年 前

crOpenGL some cleanup

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 75.4 KB
 
1/* $Id: renderspu_cocoa_helper.m 52625 2014-09-05 19:19:38Z vboxsync $ */
2/** @file
3 * VirtualBox OpenGL Cocoa Window System Helper Implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2014 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "renderspu_cocoa_helper.h"
19
20#import <Cocoa/Cocoa.h>
21#undef PVM
22
23#include "chromium.h" /* For the visual bits of chromium */
24
25#include <iprt/thread.h>
26#include <iprt/string.h>
27#include <iprt/mem.h>
28#include <iprt/time.h>
29#include <iprt/assert.h>
30#include <VBox/VBoxOGLTest.h>
31
32#include <cr_vreg.h>
33#include <cr_error.h>
34#include <cr_blitter.h>
35#ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
36# include <cr_pixeldata.h>
37#endif
38
39
40#include "renderspu.h"
41
42/** @page pg_opengl_cocoa OpenGL - Cocoa Window System Helper
43 *
44 * How this works:
45 * In general it is not so easy like on the other platforms, cause Cocoa
46 * doesn't support any clipping of already painted stuff. In Mac OS X there is
47 * the concept of translucent canvas's e.g. windows and there it is just
48 * painted what should be visible to the user. Unfortunately this isn't the
49 * concept of chromium. Therefor I reroute all OpenGL operation from the guest
50 * to a frame buffer object (FBO). This is a OpenGL extension, which is
51 * supported by all OS X versions we support (AFAIC tell). Of course the guest
52 * doesn't know that and we have to make sure that the OpenGL state always is
53 * in the right state to paint into the FBO and not to the front/back buffer.
54 * Several functions below (like cocoaBindFramebufferEXT, cocoaGetIntegerv,
55 * ...) doing this. When a swap or finish is triggered by the guest, the
56 * content (which is already bound to an texture) is painted on the screen
57 * within a separate OpenGL context. This allows the usage of the same
58 * resources (texture ids, buffers ...) but at the same time having an
59 * different internal OpenGL state. Another advantage is that we can paint a
60 * thumbnail of the current output in a much more smaller (GPU accelerated
61 * scale) version on a third context and use glReadPixels to get the actual
62 * data. glReadPixels is a very slow operation, but as we just use a much more
63 * smaller image, we can handle it (anyway this is only done 5 times per
64 * second).
65 *
66 * Other things to know:
67 * - If the guest request double buffering, we have to make sure there are two
68 * buffers. We use the same FBO with 2 color attachments. Also glDrawBuffer
69 * and glReadBuffer is intercepted to make sure it is painted/read to/from
70 * the correct buffers. On swap our buffers are swapped and not the
71 * front/back buffer.
72 * - If the guest request a depth/stencil buffer, a combined render buffer for
73 * this is created.
74 * - If the size of the guest OpenGL window changes, all FBO's, textures, ...
75 * need to be recreated.
76 * - We need to track any changes to the parent window
77 * (create/destroy/move/resize). The various classes like OverlayHelperView,
78 * OverlayWindow, ... are there for.
79 * - The HGCM service runs on a other thread than the Main GUI. Keeps this
80 * always in mind (see e.g. performSelectorOnMainThread in renderFBOToView)
81 * - We make heavy use of late binding. We can not be sure that the GUI (or any
82 * other third party GUI), overwrite our NSOpenGLContext. So we always ask if
83 * this is our own one, before use. Really neat concept of Objective-C/Cocoa
84 * ;)
85 */
86
87/* Debug macros */
88#define FBO 1 /* Disable this to see how the output is without the FBO in the middle of the processing chain. */
89#if 0
90# define CR_RENDER_FORCE_PRESENT_MAIN_THREAD /* force present schedule to main thread */
91# define SHOW_WINDOW_BACKGROUND 1 /* Define this to see the window background even if the window is clipped */
92# define DEBUG_VERBOSE /* Define this to get some debug info about the messages flow. */
93#endif
94
95#ifdef DEBUG_VERBOSE
96# error "should be disabled!"
97# define DEBUG_INFO(text) do { \
98 crWarning text ; \
99 Assert(0); \
100 } while (0)
101
102# define DEBUG_MSG(text) \
103 printf text
104
105# define DEBUG_WARN(text) do { \
106 crWarning text ; \
107 Assert(0); \
108 } while (0)
109
110# define DEBUG_MSG_1(text) \
111 DEBUG_MSG(text)
112
113#else
114
115# define DEBUG_INFO(text) do { \
116 crInfo text ; \
117 } while (0)
118
119# define DEBUG_MSG(text) \
120 do {} while (0)
121
122# define DEBUG_WARN(text) do { \
123 crWarning text ; \
124 } while (0)
125
126# define DEBUG_MSG_1(text) \
127 do {} while (0)
128
129#endif
130
131
132#define DEBUG_FUNC_ENTER() do { \
133 DEBUG_MSG(("==>%s\n", __PRETTY_FUNCTION__)); \
134 } while (0)
135
136#define DEBUG_FUNC_LEAVE() do { \
137 DEBUG_MSG(("<==%s\n", __PRETTY_FUNCTION__)); \
138 } while (0)
139
140
141#ifdef DEBUG_poetzsch
142# define CHECK_GL_ERROR()\
143 do \
144 { \
145 checkGLError(__FILE__, __LINE__); \
146 }while (0);
147
148 static void checkGLError(char *file, int line)
149 {
150 GLenum g = glGetError();
151 if (g != GL_NO_ERROR)
152 {
153 char *errStr;
154 switch (g)
155 {
156 case GL_INVALID_ENUM: errStr = RTStrDup("GL_INVALID_ENUM"); break;
157 case GL_INVALID_VALUE: errStr = RTStrDup("GL_INVALID_VALUE"); break;
158 case GL_INVALID_OPERATION: errStr = RTStrDup("GL_INVALID_OPERATION"); break;
159 case GL_STACK_OVERFLOW: errStr = RTStrDup("GL_STACK_OVERFLOW"); break;
160 case GL_STACK_UNDERFLOW: errStr = RTStrDup("GL_STACK_UNDERFLOW"); break;
161 case GL_OUT_OF_MEMORY: errStr = RTStrDup("GL_OUT_OF_MEMORY"); break;
162 case GL_TABLE_TOO_LARGE: errStr = RTStrDup("GL_TABLE_TOO_LARGE"); break;
163 default: errStr = RTStrDup("UNKNOWN"); break;
164 }
165 DEBUG_MSG(("%s:%d: glError %d (%s)\n", file, line, g, errStr));
166 RTMemFree(errStr);
167 }
168 }
169#else
170# define CHECK_GL_ERROR()\
171 do {} while (0)
172#endif
173
174#define GL_SAVE_STATE \
175 do \
176 { \
177 glPushAttrib(GL_ALL_ATTRIB_BITS); \
178 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); \
179 glMatrixMode(GL_PROJECTION); \
180 glPushMatrix(); \
181 glMatrixMode(GL_TEXTURE); \
182 glPushMatrix(); \
183 glMatrixMode(GL_COLOR); \
184 glPushMatrix(); \
185 glMatrixMode(GL_MODELVIEW); \
186 glPushMatrix(); \
187 } \
188 while(0);
189
190#define GL_RESTORE_STATE \
191 do \
192 { \
193 glMatrixMode(GL_MODELVIEW); \
194 glPopMatrix(); \
195 glMatrixMode(GL_COLOR); \
196 glPopMatrix(); \
197 glMatrixMode(GL_TEXTURE); \
198 glPopMatrix(); \
199 glMatrixMode(GL_PROJECTION); \
200 glPopMatrix(); \
201 glPopClientAttrib(); \
202 glPopAttrib(); \
203 } \
204 while(0);
205
206static NSOpenGLContext * vboxCtxGetCurrent()
207{
208 GET_CONTEXT(pCtxInfo);
209 if (pCtxInfo)
210 {
211 Assert(pCtxInfo->context);
212 return pCtxInfo->context;
213 }
214
215 return nil;
216}
217
218static bool vboxCtxSyncCurrentInfo()
219{
220 GET_CONTEXT(pCtxInfo);
221 NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
222 NSView *pView = pCtx ? [pCtx view] : nil;
223 bool fAdjusted = false;
224 if (pCtxInfo)
225 {
226 WindowInfo *pWinInfo = pCtxInfo->currentWindow;
227 Assert(pWinInfo);
228 if (pCtxInfo->context != pCtx
229 || pWinInfo->window != pView)
230 {
231 renderspu_SystemMakeCurrent(pWinInfo, 0, pCtxInfo);
232 fAdjusted = true;
233 }
234 }
235 else
236 {
237 if (pCtx)
238 {
239 [NSOpenGLContext clearCurrentContext];
240 fAdjusted = true;
241 }
242 }
243
244 return fAdjusted;
245}
246
247typedef struct VBOX_CR_RENDER_CTX_INFO
248{
249 bool fIsValid;
250 NSOpenGLContext *pCtx;
251 NSView *pView;
252} VBOX_CR_RENDER_CTX_INFO, *PVBOX_CR_RENDER_CTX_INFO;
253
254static void vboxCtxEnter(NSOpenGLContext*pCtx, PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
255{
256 NSOpenGLContext *pOldCtx = vboxCtxGetCurrent();
257 NSView *pOldView = (pOldCtx ? [pOldCtx view] : nil);
258 NSView *pView = [pCtx view];
259 bool fNeedCtxSwitch = (pOldCtx != pCtx || pOldView != pView);
260 Assert(pCtx);
261 // Assert(pOldCtx == m_pGLCtx);
262 // Assert(pOldView == self);
263 // Assert(fNeedCtxSwitch);
264 if (fNeedCtxSwitch)
265 {
266 if(pOldCtx != nil)
267 glFlush();
268
269 [pCtx makeCurrentContext];
270
271 pCtxInfo->fIsValid = true;
272 pCtxInfo->pCtx = pOldCtx;
273 pCtxInfo->pView = pView;
274 }
275 else
276 {
277 pCtxInfo->fIsValid = false;
278 }
279}
280
281static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
282{
283 if (pCtxInfo->fIsValid)
284 {
285 NSOpenGLContext *pOldCtx = pCtxInfo->pCtx;
286 NSView *pOldView = pCtxInfo->pView;
287
288 glFlush();
289 if (pOldCtx != nil)
290 {
291 if ([pOldCtx view] != pOldView)
292 {
293 [pOldCtx setView: pOldView];
294 }
295
296 [pOldCtx makeCurrentContext];
297
298#ifdef DEBUG
299 {
300 NSOpenGLContext *pTstOldCtx = [NSOpenGLContext currentContext];
301 NSView *pTstOldView = (pTstOldCtx ? [pTstOldCtx view] : nil);
302 Assert(pTstOldCtx == pOldCtx);
303 Assert(pTstOldView == pOldView);
304 }
305#endif
306 }
307 else
308 {
309 [NSOpenGLContext clearCurrentContext];
310 }
311 }
312}
313
314/** Custom OpenGL context class.
315 *
316 * This implementation doesn't allow to set a view to the
317 * context, but save the view for later use. Also it saves a copy of the
318 * pixel format used to create that context for later use. */
319@interface OverlayOpenGLContext: NSOpenGLContext
320{
321@private
322 NSOpenGLPixelFormat *m_pPixelFormat;
323 NSView *m_pView;
324}
325- (NSOpenGLPixelFormat*)openGLPixelFormat;
326@end
327
328@interface VBoxTask : NSObject
329{
330}
331- (void)run;
332@end
333
334@interface VBoxTaskPerformSelector : VBoxTask
335{
336@private
337 id m_Object;
338 SEL m_Selector;
339 id m_Arg;
340}
341- (id)initWithObject:(id)aObject selector:(SEL)aSelector arg:(id)aArg;
342- (void)run;
343- (void)dealloc;
344@end
345
346#if 0
347typedef DECLCALLBACKPTR(void, PFNVBOXTASKCALLBACK)(void *pvCb);
348
349@interface VBoxTaskCallback: VBoxTask
350{
351@private
352 PFNVBOXTASKCALLBACK m_pfnCb;
353 void *m_pvCb;
354}
355- (id)initWithCb:(PFNVBOXTASKCALLBACK)pfnCb arg:(void*)pvCb;
356- (void)run;
357@end
358#endif
359
360@interface VBoxTaskComposite: VBoxTask
361{
362@private
363 NSUInteger m_CurIndex;
364 RTCRITSECT m_Lock;
365 NSMutableArray *m_pArray;
366}
367- (id)init;
368- (void)add:(VBoxTask*)pTask;
369- (void)run;
370- (void)dealloc;
371@end
372
373@implementation VBoxTask
374@end
375
376@implementation VBoxTaskPerformSelector
377- (id)initWithObject:(id)aObject selector:(SEL)aSelector arg:(id)aArg
378{
379 self = [super init];
380
381 if (self)
382 {
383 [aObject retain];
384 m_Object = aObject;
385 m_Selector = aSelector;
386 if (aArg != nil)
387 [aArg retain];
388 m_Arg = aArg;
389 }
390
391 return self;
392}
393
394- (void)run
395{
396 [m_Object performSelector:m_Selector withObject:m_Arg];
397}
398
399- (void)dealloc
400{
401 [m_Object release];
402 if (m_Arg != nil)
403 [m_Arg release];
404
405 [super dealloc];
406}
407@end
408
409@implementation VBoxTaskComposite
410- (id)init
411{
412 self = [super init];
413
414 if (self)
415 {
416 int rc = RTCritSectInit(&m_Lock);
417 if (!RT_SUCCESS(rc))
418 {
419 DEBUG_WARN(("RTCritSectInit failed %d\n", rc));
420 return nil;
421 }
422
423 m_CurIndex = 0;
424
425 m_pArray = [[NSMutableArray alloc] init];
426 }
427
428 return self;
429}
430
431- (void)add:(VBoxTask*)pTask
432{
433 [pTask retain];
434 int rc = RTCritSectEnter(&m_Lock);
435 if (RT_SUCCESS(rc))
436 {
437 [m_pArray addObject:pTask];
438 RTCritSectLeave(&m_Lock);
439 }
440 else
441 {
442 DEBUG_WARN(("RTCritSectEnter failed %d\n", rc));
443 [pTask release];
444 }
445}
446
447- (void)run
448{
449 for(;;)
450 {
451 int rc = RTCritSectEnter(&m_Lock);
452 if (RT_FAILURE(rc))
453 {
454 DEBUG_WARN(("RTCritSectEnter failed %d\n", rc));
455 break;
456 }
457
458 NSUInteger count = [m_pArray count];
459 Assert(m_CurIndex <= count);
460 if (m_CurIndex == count)
461 {
462 [m_pArray removeAllObjects];
463 m_CurIndex = 0;
464 RTCritSectLeave(&m_Lock);
465 break;
466 }
467
468 VBoxTask* pTask = (VBoxTask*)[m_pArray objectAtIndex:m_CurIndex];
469 Assert(pTask != nil);
470
471 ++m_CurIndex;
472
473 if (m_CurIndex > 1024)
474 {
475 NSRange range;
476 range.location = 0;
477 range.length = m_CurIndex;
478 [m_pArray removeObjectsInRange:range];
479 m_CurIndex = 0;
480 }
481 RTCritSectLeave(&m_Lock);
482
483 [pTask run];
484 [pTask release];
485 }
486}
487
488- (void)dealloc
489{
490 NSUInteger count = [m_pArray count];
491 for(;m_CurIndex < count; ++m_CurIndex)
492 {
493 VBoxTask* pTask = (VBoxTask*)[m_pArray objectAtIndex:m_CurIndex];
494 DEBUG_WARN(("dealloc with non-empty tasks! %p\n", pTask));
495 [pTask release];
496 }
497
498 [m_pArray release];
499 RTCritSectDelete(&m_Lock);
500
501 [super dealloc];
502}
503@end
504
505@interface VBoxMainThreadTaskRunner : NSObject
506{
507@private
508 VBoxTaskComposite *m_pTasks;
509}
510- (id)init;
511- (void)add:(VBoxTask*)pTask;
512- (void)addObj:(id)aObject selector:(SEL)aSelector arg:(id)aArg;
513- (void)runTasks;
514- (bool)runTasksSyncIfPossible;
515- (void)dealloc;
516+ (VBoxMainThreadTaskRunner*) globalInstance;
517@end
518
519@implementation VBoxMainThreadTaskRunner
520- (id)init
521{
522 self = [super init];
523 if (self)
524 {
525 m_pTasks = [[VBoxTaskComposite alloc] init];
526 }
527
528 return self;
529}
530
531+ (VBoxMainThreadTaskRunner*) globalInstance
532{
533 static dispatch_once_t dispatchOnce;
534 static VBoxMainThreadTaskRunner *pRunner = nil;
535 dispatch_once(&dispatchOnce, ^{
536 pRunner = [[VBoxMainThreadTaskRunner alloc] init];
537 });
538 return pRunner;
539}
540
541typedef struct CR_RCD_RUN
542{
543 VBoxMainThreadTaskRunner *pRunner;
544} CR_RCD_RUN;
545
546static DECLCALLBACK(void) vboxRcdRun(void *pvCb)
547{
548 DEBUG_FUNC_ENTER();
549 CR_RCD_RUN * pRun = (CR_RCD_RUN*)pvCb;
550 [pRun->pRunner runTasks];
551 DEBUG_FUNC_LEAVE();
552}
553
554- (void)add:(VBoxTask*)pTask
555{
556 DEBUG_FUNC_ENTER();
557 [m_pTasks add:pTask];
558 [self retain];
559
560 if (![self runTasksSyncIfPossible])
561 {
562 DEBUG_MSG(("task will be processed async\n"));
563 [self performSelectorOnMainThread:@selector(runTasks) withObject:nil waitUntilDone:NO];
564 }
565
566 DEBUG_FUNC_LEAVE();
567}
568
569- (void)addObj:(id)aObject selector:(SEL)aSelector arg:(id)aArg
570{
571 VBoxTaskPerformSelector *pSelTask = [[VBoxTaskPerformSelector alloc] initWithObject:aObject selector:aSelector arg:aArg];
572 [self add:pSelTask];
573 [pSelTask release];
574}
575
576- (void)runTasks
577{
578 BOOL fIsMain = [NSThread isMainThread];
579 Assert(fIsMain);
580 if (fIsMain)
581 {
582 [m_pTasks run];
583 [self release];
584 }
585 else
586 {
587 DEBUG_WARN(("run tasks called not on main thread!\n"));
588 [self performSelectorOnMainThread:@selector(runTasks) withObject:nil waitUntilDone:YES];
589 }
590}
591
592- (bool)runTasksSyncIfPossible
593{
594 if (renderspuCalloutAvailable())
595 {
596 CR_RCD_RUN Run;
597 Run.pRunner = self;
598 Assert(![NSThread isMainThread]);
599 renderspuCalloutClient(vboxRcdRun, &Run);
600 return true;
601 }
602
603 if ([NSThread isMainThread])
604 {
605 [self runTasks];
606 return true;
607 }
608
609 return false;
610}
611
612- (void)dealloc
613{
614 [m_pTasks release];
615 [super dealloc];
616}
617
618@end
619
620@class DockOverlayView;
621
622/** The custom view class.
623 * This is the main class of the cocoa OpenGL implementation. It
624 * manages an frame buffer object for the rendering of the guest
625 * applications. The guest applications render in this frame buffer which
626 * is bind to an OpenGL texture. To display the guest content, an secondary
627 * shared OpenGL context of the main OpenGL context is created. The secondary
628 * context is marked as non opaque & the texture is displayed on an object
629 * which is composed out of the several visible region rectangles. */
630@interface OverlayView: NSView
631{
632@private
633 NSView *m_pParentView;
634 NSWindow *m_pOverlayWin;
635
636 NSOpenGLContext *m_pGLCtx;
637 NSOpenGLContext *m_pSharedGLCtx;
638 RTTHREAD mThread;
639
640 GLuint m_FBOId;
641
642 /** The corresponding dock tile view of this OpenGL view & all helper
643 * members. */
644 DockOverlayView *m_DockTileView;
645
646 GLfloat m_FBOThumbScaleX;
647 GLfloat m_FBOThumbScaleY;
648 uint64_t m_uiDockUpdateTime;
649
650 /* For clipping */
651 GLint m_cClipRects;
652 GLint *m_paClipRects;
653
654 /* Position/Size tracking */
655 NSPoint m_Pos;
656 NSSize m_Size;
657
658 /** This is necessary for clipping on the root window */
659 NSRect m_RootRect;
660 float m_yInvRootOffset;
661
662 CR_BLITTER *m_pBlitter;
663 WindowInfo *m_pWinInfo;
664 bool m_fNeedViewportUpdate;
665 bool m_fNeedCtxUpdate;
666 bool m_fDataVisible;
667 bool m_fCleanupNeeded;
668 bool m_fEverSized;
669}
670- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo;
671- (void)setGLCtx:(NSOpenGLContext*)pCtx;
672- (NSOpenGLContext*)glCtx;
673
674- (void)setParentView: (NSView*)view;
675- (NSView*)parentView;
676- (void)setOverlayWin: (NSWindow*)win;
677- (NSWindow*)overlayWin;
678
679- (void)vboxSetPos:(NSPoint)pos;
680- (void)vboxSetPosUI:(NSPoint)pos;
681- (void)vboxSetPosUIObj:(NSValue*)pPos;
682- (NSPoint)pos;
683- (bool)isEverSized;
684- (void)vboxDestroy;
685- (void)vboxSetSizeUI:(NSSize)size;
686- (void)vboxSetSizeUIObj:(NSValue*)pSize;
687- (void)vboxSetSize:(NSSize)size;
688- (NSSize)size;
689- (void)updateViewportCS;
690- (void)vboxReshapePerform;
691- (void)vboxReshapeOnResizePerform;
692- (void)vboxReshapeOnReparentPerform;
693
694- (void)createDockTile;
695- (void)deleteDockTile;
696
697- (void)makeCurrentFBO;
698- (void)swapFBO;
699- (void)vboxSetVisible:(GLboolean)fVisible;
700- (void)vboxSetVisibleUIObj:(NSNumber*)pVisible;
701- (void)vboxSetVisibleUI:(GLboolean)fVisible;
702- (void)vboxTryDraw;
703- (void)vboxTryDrawUI;
704- (void)vboxReparent:(NSView*)pParentView;
705- (void)vboxReparentUI:(NSView*)pParentView;
706- (void)vboxPresent:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
707- (void)vboxPresentCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
708- (void)vboxPresentToDockTileCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
709- (void)vboxPresentToViewCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
710- (void)presentComposition:(const VBOXVR_SCR_COMPOSITOR_ENTRY*)pChangedEntry;
711- (void)vboxBlitterSyncWindow;
712
713- (void)clearVisibleRegions;
714- (void)setVisibleRegions:(GLint)cRects paRects:(const GLint*)paRects;
715- (GLboolean)vboxNeedsEmptyPresent;
716
717- (NSView*)dockTileScreen;
718- (void)reshapeDockTile;
719- (void)cleanupData;
720@end
721
722/** Helper view.
723 *
724 * This view is added as a sub view of the parent view to track
725 * main window changes. Whenever the main window is changed
726 * (which happens on fullscreen/seamless entry/exit) the overlay
727 * window is informed & can add them self as a child window
728 * again. */
729@class OverlayWindow;
730@interface OverlayHelperView: NSView
731{
732@private
733 OverlayWindow *m_pOverlayWindow;
734}
735-(id)initWithOverlayWindow:(OverlayWindow*)pOverlayWindow;
736@end
737
738/** Custom window class.
739 *
740 * This is the overlay window which contains our custom NSView.
741 * Its a direct child of the Qt Main window. It marks its background
742 * transparent & non opaque to make clipping possible. It also disable mouse
743 * events and handle frame change events of the parent view. */
744@interface OverlayWindow: NSWindow
745{
746@private
747 NSView *m_pParentView;
748 OverlayView *m_pOverlayView;
749 OverlayHelperView *m_pOverlayHelperView;
750 NSThread *m_Thread;
751}
752- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView;
753- (void)parentWindowFrameChanged:(NSNotification *)note;
754- (void)parentWindowChanged:(NSWindow*)pWindow;
755@end
756
757@interface DockOverlayView: NSView
758{
759 NSBitmapImageRep *m_ThumbBitmap;
760 NSImage *m_ThumbImage;
761 NSLock *m_Lock;
762}
763- (void)dealloc;
764- (void)cleanup;
765- (void)lock;
766- (void)unlock;
767- (void)setFrame:(NSRect)frame;
768- (void)drawRect:(NSRect)aRect;
769- (NSBitmapImageRep*)thumbBitmap;
770- (NSImage*)thumbImage;
771@end
772
773@implementation DockOverlayView
774- (id)init
775{
776 DEBUG_FUNC_ENTER();
777 self = [super init];
778
779 if (self)
780 {
781 /* We need a lock cause the thumb image could be accessed from the main
782 * thread when someone is calling display on the dock tile & from the
783 * OpenGL thread when the thumbnail is updated. */
784 m_Lock = [[NSLock alloc] init];
785 }
786
787 DEBUG_FUNC_LEAVE();
788
789 return self;
790}
791
792- (void)dealloc
793{
794 DEBUG_FUNC_ENTER();
795
796 [self cleanup];
797 [m_Lock release];
798
799 [super dealloc];
800
801 DEBUG_FUNC_LEAVE();
802}
803
804- (void)cleanup
805{
806 DEBUG_FUNC_ENTER();
807
808 if (m_ThumbImage != nil)
809 {
810 [m_ThumbImage release];
811 m_ThumbImage = nil;
812 }
813 if (m_ThumbBitmap != nil)
814 {
815 [m_ThumbBitmap release];
816 m_ThumbBitmap = nil;
817 }
818
819 DEBUG_FUNC_LEAVE();
820}
821
822- (void)lock
823{
824 DEBUG_FUNC_ENTER();
825 [m_Lock lock];
826 DEBUG_FUNC_LEAVE();
827}
828
829- (void)unlock
830{
831 DEBUG_FUNC_ENTER();
832 [m_Lock unlock];
833 DEBUG_FUNC_LEAVE();
834}
835
836- (void)setFrame:(NSRect)frame
837{
838 DEBUG_FUNC_ENTER();
839 [super setFrame:frame];
840
841 [self lock];
842 [self cleanup];
843
844 if ( frame.size.width > 0
845 && frame.size.height > 0)
846 {
847 /* Create a buffer for our thumbnail image. Its in the size of this view. */
848 m_ThumbBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
849 pixelsWide:frame.size.width
850 pixelsHigh:frame.size.height
851 bitsPerSample:8
852 samplesPerPixel:4
853 hasAlpha:YES
854 isPlanar:NO
855 colorSpaceName:NSDeviceRGBColorSpace
856 bitmapFormat:NSAlphaFirstBitmapFormat
857 bytesPerRow:frame.size.width * 4
858 bitsPerPixel:8 * 4];
859 m_ThumbImage = [[NSImage alloc] initWithSize:[m_ThumbBitmap size]];
860 [m_ThumbImage addRepresentation:m_ThumbBitmap];
861 }
862 [self unlock];
863 DEBUG_FUNC_LEAVE();
864}
865
866- (BOOL)isFlipped
867{
868 DEBUG_FUNC_ENTER();
869 DEBUG_FUNC_LEAVE();
870 return YES;
871}
872
873- (void)drawRect:(NSRect)aRect
874{
875 DEBUG_FUNC_ENTER();
876 NSRect frame;
877
878 [self lock];
879#ifdef SHOW_WINDOW_BACKGROUND
880 [[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7] set];
881 frame = [self frame];
882 [NSBezierPath fillRect:NSMakeRect(0, 0, frame.size.width, frame.size.height)];
883#endif /* SHOW_WINDOW_BACKGROUND */
884 if (m_ThumbImage != nil)
885 [m_ThumbImage drawAtPoint:NSMakePoint(0, 0) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
886 [self unlock];
887 DEBUG_FUNC_LEAVE();
888}
889
890- (NSBitmapImageRep*)thumbBitmap
891{
892 DEBUG_FUNC_ENTER();
893 DEBUG_FUNC_LEAVE();
894 return m_ThumbBitmap;
895}
896
897- (NSImage*)thumbImage
898{
899 DEBUG_FUNC_ENTER();
900 DEBUG_FUNC_LEAVE();
901
902 return m_ThumbImage;
903}
904@end
905
906/********************************************************************************
907*
908* OverlayOpenGLContext class implementation
909*
910********************************************************************************/
911@implementation OverlayOpenGLContext
912
913-(id)initWithFormat:(NSOpenGLPixelFormat*)format shareContext:(NSOpenGLContext*)share
914{
915 DEBUG_FUNC_ENTER();
916
917 m_pPixelFormat = NULL;
918 m_pView = NULL;
919
920 self = [super initWithFormat:format shareContext:share];
921 if (self)
922 m_pPixelFormat = format;
923
924 DEBUG_MSG(("OCTX(%p): init OverlayOpenGLContext\n", (void*)self));
925
926 DEBUG_FUNC_LEAVE();
927
928 return self;
929}
930
931- (void)dealloc
932{
933 DEBUG_FUNC_ENTER();
934
935 DEBUG_MSG(("OCTX(%p): dealloc OverlayOpenGLContext\n", (void*)self));
936
937 [m_pPixelFormat release];
938
939 [super dealloc];
940
941 DEBUG_FUNC_LEAVE();
942}
943
944-(bool)isDoubleBuffer
945{
946 DEBUG_FUNC_ENTER();
947
948 GLint val;
949 [m_pPixelFormat getValues:&val forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:0];
950
951 DEBUG_FUNC_LEAVE();
952
953 return val == GL_TRUE ? YES : NO;
954}
955
956-(void)setView:(NSView*)view
957{
958 DEBUG_FUNC_ENTER();
959
960 DEBUG_MSG(("OCTX(%p): setView: new view: %p\n", (void*)self, (void*)view));
961
962#if 1 /* def FBO */
963 m_pView = view;;
964#else
965 [super setView: view];
966#endif
967
968 DEBUG_FUNC_LEAVE();
969}
970
971-(NSView*)view
972{
973 DEBUG_FUNC_ENTER();
974 DEBUG_FUNC_LEAVE();
975
976#if 1 /* def FBO */
977 return m_pView;
978#else
979 return [super view];
980#endif
981}
982
983-(void)clearDrawable
984{
985 DEBUG_FUNC_ENTER();
986
987 DEBUG_MSG(("OCTX(%p): clearDrawable\n", (void*)self));
988
989 m_pView = NULL;;
990 [super clearDrawable];
991
992 DEBUG_FUNC_LEAVE();
993}
994
995-(NSOpenGLPixelFormat*)openGLPixelFormat
996{
997 DEBUG_FUNC_ENTER();
998 DEBUG_FUNC_LEAVE();
999
1000 return m_pPixelFormat;
1001}
1002
1003@end
1004
1005/********************************************************************************
1006*
1007* OverlayHelperView class implementation
1008*
1009********************************************************************************/
1010@implementation OverlayHelperView
1011
1012-(id)initWithOverlayWindow:(OverlayWindow*)pOverlayWindow
1013{
1014 DEBUG_FUNC_ENTER();
1015
1016 self = [super initWithFrame:NSZeroRect];
1017
1018 m_pOverlayWindow = pOverlayWindow;
1019
1020 DEBUG_MSG(("OHVW(%p): init OverlayHelperView\n", (void*)self));
1021
1022 DEBUG_FUNC_LEAVE();
1023
1024 return self;
1025}
1026
1027-(void)viewDidMoveToWindow
1028{
1029 DEBUG_FUNC_ENTER();
1030
1031 DEBUG_MSG(("OHVW(%p): viewDidMoveToWindow: new win: %p\n", (void*)self, (void*)[self window]));
1032
1033 [m_pOverlayWindow parentWindowChanged:[self window]];
1034
1035 DEBUG_FUNC_LEAVE();
1036}
1037
1038@end
1039
1040/********************************************************************************
1041*
1042* OverlayWindow class implementation
1043*
1044********************************************************************************/
1045@implementation OverlayWindow
1046
1047- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView
1048{
1049 DEBUG_FUNC_ENTER();
1050
1051 NSWindow *pParentWin = nil;
1052
1053 if((self = [super initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]))
1054 {
1055 m_pParentView = pParentView;
1056 m_pOverlayView = pOverlayView;
1057 m_Thread = [NSThread currentThread];
1058
1059 [m_pOverlayView setOverlayWin: self];
1060
1061 m_pOverlayHelperView = [[OverlayHelperView alloc] initWithOverlayWindow:self];
1062 /* Add the helper view as a child of the parent view to get notifications */
1063 [pParentView addSubview:m_pOverlayHelperView];
1064
1065 /* Make sure this window is transparent */
1066#ifdef SHOW_WINDOW_BACKGROUND
1067 /* For debugging */
1068 [self setBackgroundColor:[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7]];
1069#else
1070 [self setBackgroundColor:[NSColor clearColor]];
1071#endif
1072 [self setOpaque:NO];
1073 [self setAlphaValue:.999];
1074 /* Disable mouse events for this window */
1075 [self setIgnoresMouseEvents:YES];
1076
1077 pParentWin = [m_pParentView window];
1078
1079 /* Initial set the position to the parents view top/left (Compiz fix). */
1080 [self setFrameOrigin:
1081 [pParentWin convertBaseToScreen:
1082 [m_pParentView convertPoint:NSZeroPoint toView:nil]]];
1083
1084 /* Set the overlay view as our content view */
1085 [self setContentView:m_pOverlayView];
1086
1087 /* Add ourself as a child to the parent views window. Note: this has to
1088 * be done last so that everything else is setup in
1089 * parentWindowChanged. */
1090 [pParentWin addChildWindow:self ordered:NSWindowAbove];
1091 }
1092 DEBUG_MSG(("OWIN(%p): init OverlayWindow\n", (void*)self));
1093
1094 DEBUG_FUNC_LEAVE();
1095
1096 return self;
1097}
1098
1099- (void)dealloc
1100{
1101 DEBUG_FUNC_ENTER();
1102
1103 DEBUG_MSG(("OWIN(%p): dealloc OverlayWindow\n", (void*)self));
1104
1105 [[NSNotificationCenter defaultCenter] removeObserver:self];
1106
1107 [m_pOverlayHelperView removeFromSuperview];
1108 [m_pOverlayHelperView release];
1109
1110 [super dealloc];
1111
1112 DEBUG_FUNC_LEAVE();
1113}
1114
1115- (void)parentWindowFrameChanged:(NSNotification*)pNote
1116{
1117 DEBUG_FUNC_ENTER();
1118
1119 DEBUG_MSG(("OWIN(%p): parentWindowFrameChanged\n", (void*)self));
1120
1121 /* Reposition this window with the help of the OverlayView. Perform the
1122 * call in the OpenGL thread. */
1123 /*
1124 [m_pOverlayView performSelector:@selector(vboxReshapePerform) onThread:m_Thread withObject:nil waitUntilDone:YES];
1125 */
1126
1127 if ([m_pOverlayView isEverSized])
1128 {
1129 if([NSThread isMainThread])
1130 [m_pOverlayView vboxReshapePerform];
1131 else
1132 [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
1133 }
1134
1135 DEBUG_FUNC_LEAVE();
1136}
1137
1138- (void)parentWindowChanged:(NSWindow*)pWindow
1139{
1140 DEBUG_FUNC_ENTER();
1141
1142 DEBUG_MSG(("OWIN(%p): parentWindowChanged\n", (void*)self));
1143
1144 [[NSNotificationCenter defaultCenter] removeObserver:self];
1145
1146 if(pWindow != nil)
1147 {
1148 /* Ask to get notifications when our parent window frame changes. */
1149 [[NSNotificationCenter defaultCenter]
1150 addObserver:self
1151 selector:@selector(parentWindowFrameChanged:)
1152 name:NSWindowDidResizeNotification
1153 object:pWindow];
1154 /* Add us self as child window */
1155 [pWindow addChildWindow:self ordered:NSWindowAbove];
1156 /* Reshape the overlay view after a short waiting time to let the main
1157 * window resize itself properly. */
1158 /*
1159 [m_pOverlayView performSelector:@selector(vboxReshapePerform) withObject:nil afterDelay:0.2];
1160 [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(vboxReshapePerform) userInfo:nil repeats:NO];
1161 */
1162
1163 if ([m_pOverlayView isEverSized])
1164 {
1165 if([NSThread isMainThread])
1166 [m_pOverlayView vboxReshapePerform];
1167 else
1168 [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
1169 }
1170 }
1171
1172 DEBUG_FUNC_LEAVE();
1173}
1174
1175@end
1176
1177/********************************************************************************
1178*
1179* OverlayView class implementation
1180*
1181********************************************************************************/
1182@implementation OverlayView
1183
1184- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo
1185{
1186 DEBUG_FUNC_ENTER();
1187
1188 m_pParentView = pParentView;
1189 /* Make some reasonable defaults */
1190 m_pGLCtx = nil;
1191 m_pSharedGLCtx = nil;
1192 mThread = aThread;
1193 m_FBOId = 0;
1194 m_cClipRects = 0;
1195 m_paClipRects = NULL;
1196 m_Pos = NSZeroPoint;
1197 m_Size = NSMakeSize(1, 1);
1198 m_RootRect = NSMakeRect(0, 0, m_Size.width, m_Size.height);
1199 m_yInvRootOffset = 0;
1200 m_pBlitter = nil;
1201 m_pWinInfo = pWinInfo;
1202 m_fNeedViewportUpdate = true;
1203 m_fNeedCtxUpdate = true;
1204 m_fDataVisible = false;
1205 m_fCleanupNeeded = false;
1206 m_fEverSized = false;
1207
1208 self = [super initWithFrame:frame];
1209
1210 DEBUG_MSG(("OVIW(%p): init OverlayView\n", (void*)self));
1211
1212 DEBUG_FUNC_LEAVE();
1213
1214 return self;
1215}
1216
1217- (void)cleanupData
1218{
1219 DEBUG_FUNC_ENTER();
1220
1221 [self deleteDockTile];
1222
1223 [self setGLCtx:nil];
1224
1225 if (m_pSharedGLCtx)
1226 {
1227 if ([m_pSharedGLCtx view] == self)
1228 [m_pSharedGLCtx clearDrawable];
1229
1230 [m_pSharedGLCtx release];
1231
1232 m_pSharedGLCtx = nil;
1233
1234 CrBltTerm(m_pBlitter);
1235
1236 RTMemFree(m_pBlitter);
1237
1238 m_pBlitter = nil;
1239 }
1240
1241 [self clearVisibleRegions];
1242
1243 DEBUG_FUNC_LEAVE();
1244}
1245
1246- (void)dealloc
1247{
1248 DEBUG_FUNC_ENTER();
1249
1250 DEBUG_MSG(("OVIW(%p): dealloc OverlayView\n", (void*)self));
1251
1252 [self cleanupData];
1253
1254 [super dealloc];
1255
1256 DEBUG_FUNC_LEAVE();
1257}
1258
1259- (void)drawRect:(NSRect)aRect
1260{
1261 [self vboxTryDrawUI];
1262}
1263
1264- (void)setGLCtx:(NSOpenGLContext*)pCtx
1265{
1266 DEBUG_FUNC_ENTER();
1267
1268 DEBUG_MSG(("OVIW(%p): setGLCtx: new ctx: %p\n", (void*)self, (void*)pCtx));
1269 if (m_pGLCtx == pCtx)
1270 {
1271 DEBUG_FUNC_LEAVE();
1272 return;
1273 }
1274
1275 /* ensure the context drawable is cleared to avoid holding a reference to inexistent view */
1276 if (m_pGLCtx)
1277 {
1278 [m_pGLCtx clearDrawable];
1279 [m_pGLCtx release];
1280 /*[m_pGLCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
1281 }
1282
1283 m_pGLCtx = pCtx;
1284 if (pCtx)
1285 [pCtx retain];
1286
1287 DEBUG_FUNC_LEAVE();
1288}
1289
1290- (NSOpenGLContext*)glCtx
1291{
1292 DEBUG_FUNC_ENTER();
1293 DEBUG_FUNC_LEAVE();
1294
1295 return m_pGLCtx;
1296}
1297
1298- (NSView*)parentView
1299{
1300 DEBUG_FUNC_ENTER();
1301 DEBUG_FUNC_LEAVE();
1302
1303 return m_pParentView;
1304}
1305
1306- (void)setParentView:(NSView*)pView
1307{
1308 DEBUG_FUNC_ENTER();
1309
1310 DEBUG_MSG(("OVIW(%p): setParentView: new view: %p\n", (void*)self, (void*)pView));
1311
1312 m_pParentView = pView;
1313
1314 DEBUG_FUNC_LEAVE();
1315}
1316
1317- (void)setOverlayWin:(NSWindow*)pWin
1318{
1319 DEBUG_FUNC_ENTER();
1320
1321 DEBUG_MSG(("OVIW(%p): setOverlayWin: new win: %p\n", (void*)self, (void*)pWin));
1322
1323 m_pOverlayWin = pWin;
1324
1325 DEBUG_FUNC_LEAVE();
1326}
1327
1328- (NSWindow*)overlayWin
1329{
1330 DEBUG_FUNC_ENTER();
1331 DEBUG_FUNC_LEAVE();
1332
1333 return m_pOverlayWin;
1334}
1335
1336- (void)vboxSetPosUI:(NSPoint)pos
1337{
1338 DEBUG_FUNC_ENTER();
1339
1340 m_Pos = pos;
1341
1342 if (m_fEverSized)
1343 [self vboxReshapePerform];
1344
1345 DEBUG_FUNC_LEAVE();
1346}
1347
1348- (void)vboxSetPosUIObj:(NSValue*)pPos
1349{
1350 DEBUG_FUNC_ENTER();
1351
1352 NSPoint pos = [pPos pointValue];
1353 [self vboxSetPosUI:pos];
1354
1355 DEBUG_FUNC_LEAVE();
1356}
1357
1358typedef struct CR_RCD_SETPOS
1359{
1360 OverlayView *pView;
1361 NSPoint pos;
1362} CR_RCD_SETPOS;
1363
1364static DECLCALLBACK(void) vboxRcdSetPos(void *pvCb)
1365{
1366 DEBUG_FUNC_ENTER();
1367
1368 CR_RCD_SETPOS * pPos = (CR_RCD_SETPOS*)pvCb;
1369 [pPos->pView vboxSetPosUI:pPos->pos];
1370
1371 DEBUG_FUNC_LEAVE();
1372}
1373
1374- (void)vboxSetPos:(NSPoint)pos
1375{
1376 DEBUG_FUNC_ENTER();
1377
1378 DEBUG_MSG(("OVIW(%p): vboxSetPos: new pos: %d, %d\n", (void*)self, (int)pos.x, (int)pos.y));
1379 VBoxMainThreadTaskRunner *pRunner = [VBoxMainThreadTaskRunner globalInstance];
1380 NSValue *pPos = [NSValue valueWithPoint:pos];
1381 [pRunner addObj:self selector:@selector(vboxSetPosUIObj:) arg:pPos];
1382
1383 DEBUG_FUNC_LEAVE();
1384}
1385
1386- (NSPoint)pos
1387{
1388 DEBUG_FUNC_ENTER();
1389 DEBUG_FUNC_LEAVE();
1390 return m_Pos;
1391}
1392
1393- (bool)isEverSized
1394{
1395 DEBUG_FUNC_ENTER();
1396 DEBUG_FUNC_LEAVE();
1397 return m_fEverSized;
1398}
1399
1400- (void)vboxDestroy
1401{
1402 DEBUG_FUNC_ENTER();
1403 BOOL fIsMain = [NSThread isMainThread];
1404 NSWindow *pWin = nil;
1405
1406 Assert(fIsMain);
1407
1408 /* Hide the view early */
1409 [self setHidden: YES];
1410
1411 pWin = [self window];
1412 [[NSNotificationCenter defaultCenter] removeObserver:pWin];
1413 [pWin setContentView: nil];
1414 [[pWin parentWindow] removeChildWindow: pWin];
1415
1416 if (fIsMain)
1417 [pWin release];
1418 else
1419 {
1420 /* We can NOT run synchronously with the main thread since this may lead to a deadlock,
1421 caused by main thread waiting xpcom thread, xpcom thread waiting to main hgcm thread,
1422 and main hgcm thread waiting for us, this is why use waitUntilDone:NO,
1423 which should cause no harm */
1424 [pWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
1425 }
1426
1427 [self cleanupData];
1428
1429 if (fIsMain)
1430 [self release];
1431 else
1432 {
1433 /* We can NOT run synchronously with the main thread since this may lead to a deadlock,
1434 caused by main thread waiting xpcom thread, xpcom thread waiting to main hgcm thread,
1435 and main hgcm thread waiting for us, this is why use waitUntilDone:NO.
1436 We need to avoid concurrency though, so we cleanup some data right away via a cleanupData call */
1437 [self performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
1438 }
1439
1440 renderspuWinRelease(m_pWinInfo);
1441
1442 DEBUG_FUNC_LEAVE();
1443}
1444
1445- (void)vboxSetSizeUIObj:(NSValue*)pSize
1446{
1447 DEBUG_FUNC_ENTER();
1448 NSSize size = [pSize sizeValue];
1449 [self vboxSetSizeUI:size];
1450 DEBUG_FUNC_LEAVE();
1451}
1452
1453- (void)vboxSetSizeUI:(NSSize)size
1454{
1455 DEBUG_FUNC_ENTER();
1456 m_Size = size;
1457
1458 m_fEverSized = true;
1459
1460 DEBUG_MSG(("OVIW(%p): vboxSetSize: new size: %dx%d\n", (void*)self, (int)m_Size.width, (int)m_Size.height));
1461 [self vboxReshapeOnResizePerform];
1462
1463 /* ensure window contents is updated after that */
1464 [self vboxTryDrawUI];
1465 DEBUG_FUNC_LEAVE();
1466}
1467
1468typedef struct CR_RCD_SETSIZE
1469{
1470 OverlayView *pView;
1471 NSSize size;
1472} CR_RCD_SETSIZE;
1473
1474static DECLCALLBACK(void) vboxRcdSetSize(void *pvCb)
1475{
1476 DEBUG_FUNC_ENTER();
1477 CR_RCD_SETSIZE * pSetSize = (CR_RCD_SETSIZE*)pvCb;
1478 [pSetSize->pView vboxSetSizeUI:pSetSize->size];
1479 DEBUG_FUNC_LEAVE();
1480}
1481
1482- (void)vboxSetSize:(NSSize)size
1483{
1484 DEBUG_FUNC_ENTER();
1485
1486 VBoxMainThreadTaskRunner *pRunner = [VBoxMainThreadTaskRunner globalInstance];
1487 NSValue *pSize = [NSValue valueWithSize:size];
1488 [pRunner addObj:self selector:@selector(vboxSetSizeUIObj:) arg:pSize];
1489
1490 DEBUG_FUNC_LEAVE();
1491}
1492
1493- (NSSize)size
1494{
1495 DEBUG_FUNC_ENTER();
1496 return m_Size;
1497 DEBUG_FUNC_LEAVE();
1498}
1499
1500- (void)updateViewportCS
1501{
1502 DEBUG_FUNC_ENTER();
1503 DEBUG_MSG(("OVIW(%p): updateViewport\n", (void*)self));
1504
1505 /* Update the viewport for our OpenGL view */
1506 [m_pSharedGLCtx update];
1507
1508 [self vboxBlitterSyncWindow];
1509
1510 /* Clear background to transparent */
1511 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1512 DEBUG_FUNC_LEAVE();
1513}
1514
1515- (void)vboxReshapeOnResizePerform
1516{
1517 DEBUG_FUNC_ENTER();
1518 [self vboxReshapePerform];
1519
1520 [self createDockTile];
1521 /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
1522 m_fNeedViewportUpdate = true;
1523#if 0
1524 pCurCtx = [NSOpenGLContext currentContext];
1525 if (pCurCtx && pCurCtx == m_pGLCtx && (pCurView = [pCurCtx view]) == self)
1526 {
1527 [m_pGLCtx update];
1528 m_fNeedCtxUpdate = false;
1529 }
1530 else
1531 {
1532 /* do it in a lazy way */
1533 m_fNeedCtxUpdate = true;
1534 }
1535#endif
1536 DEBUG_FUNC_LEAVE();
1537}
1538
1539- (void)vboxReshapeOnReparentPerform
1540{
1541 DEBUG_FUNC_ENTER();
1542 [self createDockTile];
1543 DEBUG_FUNC_LEAVE();
1544}
1545
1546- (void)vboxReshapePerform
1547{
1548 DEBUG_FUNC_ENTER();
1549 NSRect parentFrame = NSZeroRect;
1550 NSPoint parentPos = NSZeroPoint;
1551 NSPoint childPos = NSZeroPoint;
1552 NSRect childFrame = NSZeroRect;
1553 NSRect newFrame = NSZeroRect;
1554
1555 DEBUG_MSG(("OVIW(%p): vboxReshapePerform\n", (void*)self));
1556
1557 parentFrame = [m_pParentView frame];
1558 DEBUG_MSG(("FIXED parentFrame [%f:%f], [%f:%f]\n", parentFrame.origin.x, parentFrame.origin.y, parentFrame.size.width, parentFrame.size.height));
1559 parentPos = parentFrame.origin;
1560 parentPos.y += parentFrame.size.height;
1561 DEBUG_MSG(("FIXED(view) parentPos [%f:%f]\n", parentPos.x, parentPos.y));
1562 parentPos = [m_pParentView convertPoint:parentPos toView:nil];
1563 DEBUG_MSG(("FIXED parentPos(win) [%f:%f]\n", parentPos.x, parentPos.y));
1564 parentPos = [[m_pParentView window] convertBaseToScreen:parentPos];
1565 DEBUG_MSG(("FIXED parentPos(screen) [%f:%f]\n", parentPos.x, parentPos.y));
1566 parentFrame.origin = parentPos;
1567
1568 childPos = NSMakePoint(m_Pos.x, m_Pos.y + m_Size.height);
1569 DEBUG_MSG(("FIXED(view) childPos [%f:%f]\n", childPos.x, childPos.y));
1570 childPos = [m_pParentView convertPoint:childPos toView:nil];
1571 DEBUG_MSG(("FIXED(win) childPos [%f:%f]\n", childPos.x, childPos.y));
1572 childPos = [[m_pParentView window] convertBaseToScreen:childPos];
1573 DEBUG_MSG(("FIXED childPos(screen) [%f:%f]\n", childPos.x, childPos.y));
1574 childFrame = NSMakeRect(childPos.x, childPos.y, m_Size.width, m_Size.height);
1575 DEBUG_MSG(("FIXED childFrame [%f:%f], [%f:%f]\n", childFrame.origin.x, childFrame.origin.y, childFrame.size.width, childFrame.size.height));
1576
1577 /* We have to make sure that the overlay window will not be displayed out
1578 * of the parent window. So intersect both frames & use the result as the new
1579 * frame for the window. */
1580 newFrame = NSIntersectionRect(parentFrame, childFrame);
1581
1582 DEBUG_MSG(("[%#p]: parentFrame pos[%f : %f] size[%f : %f]\n",
1583 (void*)self,
1584 parentFrame.origin.x, parentFrame.origin.y,
1585 parentFrame.size.width, parentFrame.size.height));
1586 DEBUG_MSG(("[%#p]: childFrame pos[%f : %f] size[%f : %f]\n",
1587 (void*)self,
1588 childFrame.origin.x, childFrame.origin.y,
1589 childFrame.size.width, childFrame.size.height));
1590
1591 DEBUG_MSG(("[%#p]: newFrame pos[%f : %f] size[%f : %f]\n",
1592 (void*)self,
1593 newFrame.origin.x, newFrame.origin.y,
1594 newFrame.size.width, newFrame.size.height));
1595
1596 /* Later we have to correct the texture position in the case the window is
1597 * out of the parents window frame. So save the shift values for later use. */
1598 m_RootRect.origin.x = newFrame.origin.x - childFrame.origin.x;
1599 m_RootRect.origin.y = childFrame.size.height + childFrame.origin.y - (newFrame.size.height + newFrame.origin.y);
1600 m_RootRect.size = newFrame.size;
1601 m_yInvRootOffset = newFrame.origin.y - childFrame.origin.y;
1602
1603 DEBUG_MSG(("[%#p]: m_RootRect pos[%f : %f] size[%f : %f]\n",
1604 (void*)self,
1605 m_RootRect.origin.x, m_RootRect.origin.y,
1606 m_RootRect.size.width, m_RootRect.size.height));
1607
1608
1609 /*
1610 NSScrollView *pScrollView = [[[m_pParentView window] contentView] enclosingScrollView];
1611 if (pScrollView)
1612 {
1613 NSRect scrollRect = [pScrollView documentVisibleRect];
1614 NSRect scrollRect = [m_pParentView visibleRect];
1615 printf ("sc rect: %d %d %d %d\n", (int) scrollRect.origin.x,(int) scrollRect.origin.y,(int) scrollRect.size.width,(int) scrollRect.size.height);
1616 NSRect b = [[m_pParentView superview] bounds];
1617 printf ("bound rect: %d %d %d %d\n", (int) b.origin.x,(int) b.origin.y,(int) b.size.width,(int) b.size.height);
1618 newFrame.origin.x += scrollRect.origin.x;
1619 newFrame.origin.y += scrollRect.origin.y;
1620 }
1621 */
1622
1623 /* Set the new frame. */
1624 [[self window] setFrame:newFrame display:YES];
1625
1626 /* Inform the dock tile view as well */
1627 [self reshapeDockTile];
1628
1629 /* Make sure the context is updated according */
1630 /* [self updateViewport]; */
1631 if (m_pSharedGLCtx)
1632 {
1633 VBOX_CR_RENDER_CTX_INFO CtxInfo;
1634 vboxCtxEnter(m_pSharedGLCtx, &CtxInfo);
1635
1636 [self updateViewportCS];
1637
1638 vboxCtxLeave(&CtxInfo);
1639 }
1640 DEBUG_FUNC_LEAVE();
1641}
1642
1643- (void)createDockTile
1644{
1645 DEBUG_FUNC_ENTER();
1646 NSView *pDockScreen = nil;
1647 [self deleteDockTile];
1648
1649 /* Is there a dock tile preview enabled in the GUI? If so setup a
1650 * additional thumbnail view for the dock tile. */
1651 pDockScreen = [self dockTileScreen];
1652 if (pDockScreen)
1653 {
1654 m_DockTileView = [[DockOverlayView alloc] init];
1655 [self reshapeDockTile];
1656 [pDockScreen addSubview:m_DockTileView];
1657 }
1658 DEBUG_FUNC_LEAVE();
1659}
1660
1661- (void)deleteDockTile
1662{
1663 DEBUG_FUNC_ENTER();
1664 if (m_DockTileView != nil)
1665 {
1666 [m_DockTileView removeFromSuperview];
1667 [m_DockTileView release];
1668 m_DockTileView = nil;
1669 }
1670 DEBUG_FUNC_LEAVE();
1671}
1672
1673- (void)makeCurrentFBO
1674{
1675 DEBUG_MSG(("OVIW(%p): makeCurrentFBO\n", (void*)self));
1676
1677 if (m_pGLCtx)
1678 {
1679 if ([m_pGLCtx view] != self)
1680 {
1681 /* We change the active view, so flush first */
1682 if([NSOpenGLContext currentContext] != 0)
1683 glFlush();
1684 [m_pGLCtx setView: self];
1685 CHECK_GL_ERROR();
1686 }
1687 /*
1688 if ([NSOpenGLContext currentContext] != m_pGLCtx)
1689 */
1690 {
1691 [m_pGLCtx makeCurrentContext];
1692 CHECK_GL_ERROR();
1693 if (m_fNeedCtxUpdate == true)
1694 {
1695 [m_pGLCtx update];
1696 m_fNeedCtxUpdate = false;
1697 }
1698 }
1699
1700 if (!m_FBOId)
1701 {
1702 glGenFramebuffersEXT(1, &m_FBOId);
1703 Assert(m_FBOId);
1704 }
1705
1706 }
1707}
1708
1709- (bool)vboxSharedCtxCreate
1710{
1711 DEBUG_FUNC_ENTER();
1712 if (m_pSharedGLCtx)
1713 {
1714 DEBUG_FUNC_LEAVE();
1715 return true;
1716 }
1717
1718 Assert(!m_pBlitter);
1719 m_pBlitter = RTMemAlloc(sizeof (*m_pBlitter));
1720 if (!m_pBlitter)
1721 {
1722 DEBUG_WARN(("m_pBlitter allocation failed"));
1723 DEBUG_FUNC_LEAVE();
1724 return false;
1725 }
1726
1727 int rc = CrBltInit(m_pBlitter, NULL, false, false, &render_spu.GlobalShaders, &render_spu.blitterDispatch);
1728 if (RT_SUCCESS(rc))
1729 {
1730 DEBUG_MSG(("blitter created successfully for view 0x%p\n", (void*)self));
1731 }
1732 else
1733 {
1734 DEBUG_WARN(("CrBltInit failed, rc %d", rc));
1735 RTMemFree(m_pBlitter);
1736 m_pBlitter = NULL;
1737 DEBUG_FUNC_LEAVE();
1738 return false;
1739 }
1740
1741 GLint opaque = 0;
1742 /* Create a shared context out of the main context. Use the same pixel format. */
1743 NSOpenGLContext *pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
1744
1745 /* Set the new context as non opaque */
1746 [pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
1747 /* Set this view as the drawable for the new context */
1748 [pSharedGLCtx setView: self];
1749 m_fNeedViewportUpdate = true;
1750
1751 m_pSharedGLCtx = pSharedGLCtx;
1752
1753 DEBUG_FUNC_LEAVE();
1754 return true;
1755}
1756
1757- (void)vboxTryDraw
1758{
1759 glFlush();
1760
1761 DEBUG_MSG(("My[%p]: Draw\n", self));
1762 /* issue to the gui thread */
1763 [self performSelectorOnMainThread:@selector(vboxTryDrawUI) withObject:nil waitUntilDone:NO];
1764}
1765
1766typedef struct CR_RCD_SETVISIBLE
1767{
1768 OverlayView *pView;
1769 BOOL fVisible;
1770} CR_RCD_SETVISIBLE;
1771
1772static DECLCALLBACK(void) vboxRcdSetVisible(void *pvCb)
1773{
1774 DEBUG_FUNC_ENTER();
1775 CR_RCD_SETVISIBLE * pVisible = (CR_RCD_SETVISIBLE*)pvCb;
1776
1777 [pVisible->pView vboxSetVisibleUI:pVisible->fVisible];
1778 DEBUG_FUNC_LEAVE();
1779}
1780
1781- (void)vboxSetVisible:(GLboolean)fVisible
1782{
1783 DEBUG_FUNC_ENTER();
1784
1785 VBoxMainThreadTaskRunner *pRunner = [VBoxMainThreadTaskRunner globalInstance];
1786 NSNumber* pVisObj = [NSNumber numberWithBool:fVisible];
1787 [pRunner addObj:self selector:@selector(vboxSetVisibleUIObj:) arg:pVisObj];
1788
1789 DEBUG_FUNC_LEAVE();
1790}
1791
1792- (void)vboxSetVisibleUI:(GLboolean)fVisible
1793{
1794 DEBUG_FUNC_ENTER();
1795 [self setHidden: !fVisible];
1796 DEBUG_FUNC_LEAVE();
1797}
1798
1799- (void)vboxSetVisibleUIObj:(NSNumber*)pVisible
1800{
1801 DEBUG_FUNC_ENTER();
1802 BOOL fVisible = [pVisible boolValue];
1803 [self vboxSetVisibleUI:fVisible];
1804 DEBUG_FUNC_LEAVE();
1805}
1806
1807typedef struct CR_RCD_REPARENT
1808{
1809 OverlayView *pView;
1810 NSView *pParent;
1811} CR_RCD_REPARENT;
1812
1813static DECLCALLBACK(void) vboxRcdReparent(void *pvCb)
1814{
1815 DEBUG_FUNC_ENTER();
1816 CR_RCD_REPARENT * pReparent = (CR_RCD_REPARENT*)pvCb;
1817 [pReparent->pView vboxReparentUI:pReparent->pParent];
1818 DEBUG_FUNC_LEAVE();
1819}
1820
1821- (void)vboxReparent:(NSView*)pParentView
1822{
1823 DEBUG_FUNC_ENTER();
1824
1825 VBoxMainThreadTaskRunner *pRunner = [VBoxMainThreadTaskRunner globalInstance];
1826 [pRunner addObj:self selector:@selector(vboxReparentUI:) arg:pParentView];
1827
1828 DEBUG_FUNC_LEAVE();
1829}
1830
1831- (void)vboxReparentUI:(NSView*)pParentView
1832{
1833 DEBUG_FUNC_ENTER();
1834 /* Make sure the window is removed from any previous parent window. */
1835 if ([[self overlayWin] parentWindow] != nil)
1836 {
1837 [[[self overlayWin] parentWindow] removeChildWindow:[self overlayWin]];
1838 }
1839
1840 /* Set the new parent view */
1841 [self setParentView: pParentView];
1842
1843 /* Add the overlay window as a child to the new parent window */
1844 if (pParentView != nil)
1845 {
1846 [[pParentView window] addChildWindow:[self overlayWin] ordered:NSWindowAbove];
1847 if ([self isEverSized])
1848 [self vboxReshapeOnReparentPerform];
1849 }
1850
1851 DEBUG_FUNC_LEAVE();
1852}
1853
1854- (void)vboxTryDrawUI
1855{
1856 DEBUG_MSG(("My[%p]: DrawUI\n", self));
1857 const VBOXVR_SCR_COMPOSITOR *pCompositor;
1858
1859 if ([self isHidden])
1860 {
1861 DEBUG_INFO(("request to draw on a hidden view"));
1862 return;
1863 }
1864
1865 if ([[self overlayWin] parentWindow] == nil)
1866 {
1867 DEBUG_INFO(("request to draw a view w/o a parent"));
1868 return;
1869 }
1870
1871 int rc = renderspuVBoxCompositorLock(m_pWinInfo, &pCompositor);
1872 if (RT_FAILURE(rc))
1873 {
1874 DEBUG_WARN(("renderspuVBoxCompositorLock failed\n"));
1875 return;
1876 }
1877
1878 if (!pCompositor && !m_fCleanupNeeded)
1879 {
1880 DEBUG_MSG(("My[%p]: noCompositorUI\n", self));
1881 renderspuVBoxCompositorUnlock(m_pWinInfo);
1882 return;
1883 }
1884
1885 VBOXVR_SCR_COMPOSITOR TmpCompositor;
1886
1887 if (pCompositor)
1888 {
1889 if (!m_pSharedGLCtx)
1890 {
1891 Assert(!m_fDataVisible);
1892 Assert(!m_fCleanupNeeded);
1893 renderspuVBoxCompositorRelease(m_pWinInfo);
1894 if (![self vboxSharedCtxCreate])
1895 {
1896 DEBUG_WARN(("vboxSharedCtxCreate failed\n"));
1897 return;
1898 }
1899
1900 Assert(m_pSharedGLCtx);
1901
1902 pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
1903 Assert(!m_fDataVisible);
1904 Assert(!m_fCleanupNeeded);
1905 if (!pCompositor)
1906 return;
1907 }
1908 }
1909 else
1910 {
1911 DEBUG_MSG(("My[%p]: NeedCleanup\n", self));
1912 Assert(m_fCleanupNeeded);
1913 CrVrScrCompositorInit(&TmpCompositor, NULL);
1914 pCompositor = &TmpCompositor;
1915 }
1916
1917 if ([self lockFocusIfCanDraw])
1918 {
1919 [self vboxPresent:pCompositor];
1920 [self unlockFocus];
1921 }
1922 else if (!m_pWinInfo->visible)
1923 {
1924 DEBUG_MSG(("My[%p]: NotVisible\n", self));
1925 m_fCleanupNeeded = false;
1926 }
1927 else
1928 {
1929 DEBUG_MSG(("My[%p]: Reschedule\n", self));
1930 [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(vboxTryDrawUI) userInfo:nil repeats:NO];
1931 }
1932
1933 renderspuVBoxCompositorUnlock(m_pWinInfo);
1934}
1935
1936- (void)swapFBO
1937{
1938 DEBUG_FUNC_ENTER();
1939 [m_pGLCtx flushBuffer];
1940 DEBUG_FUNC_LEAVE();
1941}
1942
1943- (void)vboxPresent:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
1944{
1945 VBOX_CR_RENDER_CTX_INFO CtxInfo;
1946
1947 DEBUG_MSG(("OVIW(%p): renderFBOToView\n", (void*)self));
1948
1949 Assert(pCompositor);
1950
1951 vboxCtxEnter(m_pSharedGLCtx, &CtxInfo);
1952
1953 [self vboxPresentCS:pCompositor];
1954
1955 vboxCtxLeave(&CtxInfo);
1956}
1957
1958- (void)vboxPresentCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
1959{
1960 {
1961 if ([m_pSharedGLCtx view] != self)
1962 {
1963 DEBUG_MSG(("OVIW(%p): not current view of shared ctx! Switching ...\n", (void*)self));
1964 [m_pSharedGLCtx setView: self];
1965 m_fNeedViewportUpdate = true;
1966 }
1967
1968 if (m_fNeedViewportUpdate)
1969 {
1970 [self updateViewportCS];
1971 m_fNeedViewportUpdate = false;
1972 }
1973
1974 m_fCleanupNeeded = false;
1975
1976 /* Render FBO content to the dock tile when necessary. */
1977 [self vboxPresentToDockTileCS:pCompositor];
1978 /* change to #if 0 to see thumbnail image */
1979#if 1
1980 [self vboxPresentToViewCS:pCompositor];
1981#else
1982 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1983 [m_pSharedGLCtx flushBuffer];
1984#endif
1985
1986 }
1987}
1988
1989DECLINLINE(void) vboxNSRectToRect(const NSRect *pR, RTRECT *pRect)
1990{
1991 pRect->xLeft = (int)pR->origin.x;
1992 pRect->yTop = (int)pR->origin.y;
1993 pRect->xRight = (int)(pR->origin.x + pR->size.width);
1994 pRect->yBottom = (int)(pR->origin.y + pR->size.height);
1995}
1996
1997DECLINLINE(void) vboxNSRectToRectUnstretched(const NSRect *pR, RTRECT *pRect, float xStretch, float yStretch)
1998{
1999 pRect->xLeft = (int)(pR->origin.x / xStretch);
2000 pRect->yTop = (int)(pR->origin.y / yStretch);
2001 pRect->xRight = (int)((pR->origin.x + pR->size.width) / xStretch);
2002 pRect->yBottom = (int)((pR->origin.y + pR->size.height) / yStretch);
2003}
2004
2005DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, float xStretch, float yStretch)
2006{
2007 pRect->xLeft = (int)(pR->origin.x * xStretch);
2008 pRect->yTop = (int)(pR->origin.y * yStretch);
2009 pRect->xRight = (int)((pR->origin.x + pR->size.width) * xStretch);
2010 pRect->yBottom = (int)((pR->origin.y + pR->size.height) * yStretch);
2011}
2012
2013- (void)vboxPresentToViewCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
2014{
2015 NSRect r = [self frame];
2016 float xStretch, yStretch;
2017 DEBUG_MSG(("OVIW(%p): rF2V frame: [%i, %i, %i, %i]\n", (void*)self, (int)r.origin.x, (int)r.origin.y, (int)r.size.width, (int)r.size.height));
2018
2019#if 1 /* Set to 0 to see the docktile instead of the real output */
2020 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
2021 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
2022
2023 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
2024
2025 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
2026 glDrawBuffer(GL_BACK);
2027
2028 /* Clear background to transparent */
2029 glClear(GL_COLOR_BUFFER_BIT);
2030
2031 m_fDataVisible = false;
2032
2033 CrVrScrCompositorGetStretching(pCompositor, &xStretch, &yStretch);
2034
2035 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
2036 {
2037 uint32_t cRegions;
2038 const RTRECT *paSrcRegions, *paDstRegions;
2039 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
2040 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
2041 if (RT_SUCCESS(rc))
2042 {
2043 uint32_t i;
2044 int rc = CrBltEnter(m_pBlitter);
2045 if (RT_SUCCESS(rc))
2046 {
2047 for (i = 0; i < cRegions; ++i)
2048 {
2049 const RTRECT * pSrcRect = &paSrcRegions[i];
2050 const RTRECT * pDstRect = &paDstRegions[i];
2051 RTRECT DstRect, RestrictDstRect;
2052 RTRECT SrcRect, RestrictSrcRect;
2053
2054 vboxNSRectToRect(&m_RootRect, &RestrictDstRect);
2055 VBoxRectIntersected(&RestrictDstRect, pDstRect, &DstRect);
2056
2057 if (VBoxRectIsZero(&DstRect))
2058 continue;
2059
2060 VBoxRectTranslate(&DstRect, -RestrictDstRect.xLeft, -RestrictDstRect.yTop);
2061
2062 vboxNSRectToRectUnstretched(&m_RootRect, &RestrictSrcRect, xStretch, yStretch);
2063 VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
2064 VBoxRectIntersected(&RestrictSrcRect, pSrcRect, &SrcRect);
2065
2066 if (VBoxRectIsZero(&SrcRect))
2067 continue;
2068
2069 pSrcRect = &SrcRect;
2070 pDstRect = &DstRect;
2071
2072 const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2073
2074 CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags | CRBLT_F_NOALPHA);
2075
2076 m_fDataVisible = true;
2077 }
2078 CrBltLeave(m_pBlitter);
2079 }
2080 else
2081 {
2082 DEBUG_WARN(("CrBltEnter failed rc %d", rc));
2083 }
2084 }
2085 else
2086 {
2087 Assert(0);
2088 DEBUG_MSG_1(("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d\n", rc));
2089 }
2090 }
2091#endif
2092 /*
2093 glFinish();
2094 */
2095 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
2096 [m_pSharedGLCtx flushBuffer];
2097}
2098
2099- (void)presentComposition:(const VBOXVR_SCR_COMPOSITOR_ENTRY*)pChangedEntry
2100{
2101 [self vboxTryDraw];
2102}
2103
2104- (void)vboxBlitterSyncWindow
2105{
2106 CR_BLITTER_WINDOW WinInfo;
2107 NSRect r;
2108
2109 if (!m_pBlitter)
2110 return;
2111
2112 memset(&WinInfo, 0, sizeof (WinInfo));
2113
2114 r = [self frame];
2115 WinInfo.width = r.size.width;
2116 WinInfo.height = r.size.height;
2117
2118 Assert(WinInfo.width == m_RootRect.size.width);
2119 Assert(WinInfo.height == m_RootRect.size.height);
2120
2121 /*CrBltMuralSetCurrentInfo(m_pBlitter, NULL);*/
2122
2123 CrBltMuralSetCurrentInfo(m_pBlitter, &WinInfo);
2124 CrBltCheckUpdateViewport(m_pBlitter);
2125}
2126
2127#ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
2128static int g_cVBoxTgaCtr = 0;
2129#endif
2130- (void)vboxPresentToDockTileCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
2131{
2132 NSRect r = [self frame];
2133 NSRect rr = NSZeroRect;
2134 GLint i = 0;
2135 NSDockTile *pDT = nil;
2136 float xStretch, yStretch;
2137
2138 if ([m_DockTileView thumbBitmap] != nil)
2139 {
2140 /* Only update after at least 200 ms, cause glReadPixels is
2141 * heavy performance wise. */
2142 uint64_t uiNewTime = RTTimeMilliTS();
2143 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
2144 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
2145
2146 if (uiNewTime - m_uiDockUpdateTime > 200)
2147 {
2148 m_uiDockUpdateTime = uiNewTime;
2149#if 0
2150 /* todo: check this for optimization */
2151 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
2152 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE,
2153 GL_STORAGE_SHARED_APPLE);
2154 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
2155 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
2156 sizex, sizey, 0, GL_BGRA,
2157 GL_UNSIGNED_INT_8_8_8_8_REV, myImagePtr);
2158 glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
2159 0, 0, 0, 0, 0, image_width, image_height);
2160 glFlush();
2161 /* Do other work processing here, using a double or triple buffer */
2162 glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
2163 GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
2164#endif
2165 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
2166 glDrawBuffer(GL_BACK);
2167
2168 /* Clear background to transparent */
2169 glClear(GL_COLOR_BUFFER_BIT);
2170
2171 rr = [m_DockTileView frame];
2172
2173 CrVrScrCompositorGetStretching(pCompositor, &xStretch, &yStretch);
2174
2175 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
2176 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
2177 {
2178 uint32_t cRegions;
2179 const RTRECT *paSrcRegions, *paDstRegions;
2180 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
2181 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
2182 if (RT_SUCCESS(rc))
2183 {
2184 uint32_t i;
2185 int rc = CrBltEnter(m_pBlitter);
2186 if (RT_SUCCESS(rc))
2187 {
2188 for (i = 0; i < cRegions; ++i)
2189 {
2190 const RTRECT * pSrcRect = &paSrcRegions[i];
2191 const RTRECT * pDstRect = &paDstRegions[i];
2192 RTRECT SrcRect, DstRect, RestrictSrcRect, RestrictDstRect;
2193
2194 vboxNSRectToRect(&m_RootRect, &RestrictDstRect);
2195 VBoxRectIntersected(&RestrictDstRect, pDstRect, &DstRect);
2196
2197 VBoxRectTranslate(&DstRect, -RestrictDstRect.xLeft, -RestrictDstRect.yTop);
2198
2199 VBoxRectScale(&DstRect, m_FBOThumbScaleX, m_FBOThumbScaleY);
2200
2201 if (VBoxRectIsZero(&DstRect))
2202 continue;
2203
2204 vboxNSRectToRectUnstretched(&m_RootRect, &RestrictSrcRect, xStretch, yStretch);
2205 VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
2206 VBoxRectIntersected(&RestrictSrcRect, pSrcRect, &SrcRect);
2207
2208 if (VBoxRectIsZero(&SrcRect))
2209 continue;
2210
2211 pSrcRect = &SrcRect;
2212 pDstRect = &DstRect;
2213
2214 const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2215
2216 CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags);
2217 }
2218 CrBltLeave(m_pBlitter);
2219 }
2220 else
2221 {
2222 DEBUG_WARN(("CrBltEnter failed rc %d", rc));
2223 }
2224 }
2225 else
2226 {
2227 Assert(0);
2228 DEBUG_MSG_1(("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d\n", rc));
2229 }
2230 }
2231
2232 glFinish();
2233
2234 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
2235 glReadBuffer(GL_BACK);
2236 /* Here the magic of reading the FBO content in our own buffer
2237 * happens. We have to lock this access, in the case the dock
2238 * is updated currently. */
2239 [m_DockTileView lock];
2240 glReadPixels(0, m_RootRect.size.height - rr.size.height, rr.size.width, rr.size.height,
2241 GL_BGRA,
2242 GL_UNSIGNED_INT_8_8_8_8,
2243 [[m_DockTileView thumbBitmap] bitmapData]);
2244 [m_DockTileView unlock];
2245
2246#ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
2247 ++g_cVBoxTgaCtr;
2248 crDumpNamedTGAF((GLint)rr.size.width, (GLint)rr.size.height,
2249 [[m_DockTileView thumbBitmap] bitmapData], "/Users/leo/vboxdumps/dump%d.tga", g_cVBoxTgaCtr);
2250#endif
2251
2252 pDT = [[NSApplication sharedApplication] dockTile];
2253
2254 /* Send a display message to the dock tile in the main thread */
2255 [[[NSApplication sharedApplication] dockTile] performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:NO];
2256 }
2257 }
2258}
2259
2260- (void)clearVisibleRegions
2261{
2262 DEBUG_FUNC_ENTER();
2263 if(m_paClipRects)
2264 {
2265 RTMemFree(m_paClipRects);
2266 m_paClipRects = NULL;
2267 }
2268 m_cClipRects = 0;
2269 DEBUG_FUNC_LEAVE();
2270}
2271
2272- (GLboolean)vboxNeedsEmptyPresent
2273{
2274 if (m_fDataVisible)
2275 {
2276 m_fCleanupNeeded = true;
2277 return GL_TRUE;
2278 }
2279
2280 return GL_FALSE;
2281}
2282
2283- (void)setVisibleRegions:(GLint)cRects paRects:(const GLint*)paRects
2284{
2285 DEBUG_FUNC_ENTER();
2286 GLint cOldRects = m_cClipRects;
2287
2288 DEBUG_MSG_1(("OVIW(%p): setVisibleRegions: cRects=%d\n", (void*)self, cRects));
2289
2290 [self clearVisibleRegions];
2291
2292 if (cRects > 0)
2293 {
2294#ifdef DEBUG_poetzsch
2295 int i =0;
2296 for (i = 0; i < cRects; ++i)
2297 DEBUG_MSG_1(("OVIW(%p): setVisibleRegions: %d - %d %d %d %d\n", (void*)self, i, paRects[i * 4], paRects[i * 4 + 1], paRects[i * 4 + 2], paRects[i * 4 + 3]));
2298#endif
2299
2300 m_paClipRects = (GLint*)RTMemAlloc(sizeof(GLint) * 4 * cRects);
2301 m_cClipRects = cRects;
2302 memcpy(m_paClipRects, paRects, sizeof(GLint) * 4 * cRects);
2303 }
2304
2305 DEBUG_FUNC_LEAVE();
2306}
2307
2308- (NSView*)dockTileScreen
2309{
2310 DEBUG_FUNC_ENTER();
2311 NSView *contentView = [[[NSApplication sharedApplication] dockTile] contentView];
2312 NSView *screenContent = nil;
2313 /* First try the new variant which checks if this window is within the
2314 screen which is previewed in the dock. */
2315 if ([contentView respondsToSelector:@selector(screenContentWithParentView:)])
2316 screenContent = [contentView performSelector:@selector(screenContentWithParentView:) withObject:(id)m_pParentView];
2317 /* If it fails, fall back to the old variant (VBox...) */
2318 else if ([contentView respondsToSelector:@selector(screenContent)])
2319 screenContent = [contentView performSelector:@selector(screenContent)];
2320
2321 DEBUG_FUNC_LEAVE();
2322 return screenContent;
2323}
2324
2325- (void)reshapeDockTile
2326{
2327 DEBUG_FUNC_ENTER();
2328 NSRect newFrame = NSZeroRect;
2329
2330 NSView *pView = [self dockTileScreen];
2331 if (pView != nil)
2332 {
2333 NSRect dockFrame = [pView frame];
2334 /* todo: this is not correct, we should use framebuffer size here, while parent view frame size may differ in case of scrolling */
2335 NSRect parentFrame = [m_pParentView frame];
2336
2337 m_FBOThumbScaleX = (float)dockFrame.size.width / parentFrame.size.width;
2338 m_FBOThumbScaleY = (float)dockFrame.size.height / parentFrame.size.height;
2339 newFrame = NSMakeRect((int)(m_Pos.x * m_FBOThumbScaleX), (int)(dockFrame.size.height - (m_Pos.y + m_Size.height - m_yInvRootOffset) * m_FBOThumbScaleY), (int)(m_Size.width * m_FBOThumbScaleX), (int)(m_Size.height * m_FBOThumbScaleY));
2340 /*
2341 NSRect newFrame = NSMakeRect ((int)roundf(m_Pos.x * m_FBOThumbScaleX), (int)roundf(dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (int)roundf(m_Size.width * m_FBOThumbScaleX), (int)roundf(m_Size.height * m_FBOThumbScaleY));
2342 NSRect newFrame = NSMakeRect ((m_Pos.x * m_FBOThumbScaleX), (dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (m_Size.width * m_FBOThumbScaleX), (m_Size.height * m_FBOThumbScaleY));
2343 printf ("%f %f %f %f - %f %f\n", newFrame.origin.x, newFrame.origin.y, newFrame.size.width, newFrame.size.height, m_Size.height, m_FBOThumbScaleY);
2344 */
2345 [m_DockTileView setFrame: newFrame];
2346 }
2347 DEBUG_FUNC_LEAVE();
2348}
2349
2350@end
2351
2352/********************************************************************************
2353*
2354* OpenGL context management
2355*
2356********************************************************************************/
2357void cocoaGLCtxCreate(NativeNSOpenGLContextRef *ppCtx, GLbitfield fVisParams, NativeNSOpenGLContextRef pSharedCtx)
2358{
2359 DEBUG_FUNC_ENTER();
2360 NSOpenGLPixelFormat *pFmt = nil;
2361
2362 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2363
2364 NSOpenGLPixelFormatAttribute attribs[24] =
2365 {
2366 NSOpenGLPFAWindow,
2367 NSOpenGLPFAAccelerated,
2368 NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24
2369 };
2370
2371 int i = 4;
2372
2373 if (fVisParams & CR_ALPHA_BIT)
2374 {
2375 DEBUG_MSG(("CR_ALPHA_BIT requested\n"));
2376 attribs[i++] = NSOpenGLPFAAlphaSize;
2377 attribs[i++] = 8;
2378 }
2379 if (fVisParams & CR_DEPTH_BIT)
2380 {
2381 DEBUG_MSG(("CR_DEPTH_BIT requested\n"));
2382 attribs[i++] = NSOpenGLPFADepthSize;
2383 attribs[i++] = 24;
2384 }
2385 if (fVisParams & CR_STENCIL_BIT)
2386 {
2387 DEBUG_MSG(("CR_STENCIL_BIT requested\n"));
2388 attribs[i++] = NSOpenGLPFAStencilSize;
2389 attribs[i++] = 8;
2390 }
2391 if (fVisParams & CR_ACCUM_BIT)
2392 {
2393 DEBUG_MSG(("CR_ACCUM_BIT requested\n"));
2394 attribs[i++] = NSOpenGLPFAAccumSize;
2395 if (fVisParams & CR_ALPHA_BIT)
2396 attribs[i++] = 32;
2397 else
2398 attribs[i++] = 24;
2399 }
2400 if (fVisParams & CR_MULTISAMPLE_BIT)
2401 {
2402 DEBUG_MSG(("CR_MULTISAMPLE_BIT requested\n"));
2403 attribs[i++] = NSOpenGLPFASampleBuffers;
2404 attribs[i++] = 1;
2405 attribs[i++] = NSOpenGLPFASamples;
2406 attribs[i++] = 4;
2407 }
2408 if (fVisParams & CR_DOUBLE_BIT)
2409 {
2410 DEBUG_MSG(("CR_DOUBLE_BIT requested\n"));
2411 attribs[i++] = NSOpenGLPFADoubleBuffer;
2412 }
2413 if (fVisParams & CR_STEREO_BIT)
2414 {
2415 /* We don't support that.
2416 DEBUG_MSG(("CR_STEREO_BIT requested\n"));
2417 attribs[i++] = NSOpenGLPFAStereo;
2418 */
2419 }
2420
2421 if (VBoxOglIsOfflineRenderingAppropriate())
2422 {
2423 DEBUG_MSG(("Offline rendering is enabled\n"));
2424 attribs[i++] = NSOpenGLPFAAllowOfflineRenderers;
2425 }
2426
2427 /* Mark the end */
2428 attribs[i++] = 0;
2429
2430 /* Choose a pixel format */
2431 pFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
2432
2433 if (pFmt)
2434 {
2435 *ppCtx = [[OverlayOpenGLContext alloc] initWithFormat:pFmt shareContext:pSharedCtx];
2436
2437 /* Enable multi threaded OpenGL engine */
2438 /*
2439 CGLContextObj cglCtx = [*ppCtx CGLContextObj];
2440 CGLError err = CGLEnable(cglCtx, kCGLCEMPEngine);
2441 if (err != kCGLNoError)
2442 printf ("Couldn't enable MT OpenGL engine!\n");
2443 */
2444
2445 DEBUG_MSG(("New context %X\n", (uint)*ppCtx));
2446 }
2447
2448 [pPool release];
2449
2450 DEBUG_FUNC_LEAVE();
2451}
2452
2453void cocoaGLCtxDestroy(NativeNSOpenGLContextRef pCtx)
2454{
2455 DEBUG_FUNC_ENTER();
2456 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2457
2458 [pCtx release];
2459 /*[pCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
2460
2461 [pPool release];
2462 DEBUG_FUNC_LEAVE();
2463}
2464
2465/********************************************************************************
2466*
2467* View management
2468*
2469********************************************************************************/
2470typedef struct CR_RCD_CREATEVIEW
2471{
2472 WindowInfo *pWinInfo;
2473 NSView *pParentView;
2474 GLbitfield fVisParams;
2475 /* out */
2476 OverlayView *pView;
2477} CR_RCD_CREATEVIEW;
2478
2479static OverlayView * vboxViewCreate(WindowInfo *pWinInfo, NativeNSViewRef pParentView)
2480{
2481 DEBUG_FUNC_ENTER();
2482 /* Create our worker view */
2483 OverlayView* pView = [[OverlayView alloc] initWithFrame:NSZeroRect thread:RTThreadSelf() parentView:pParentView winInfo:pWinInfo];
2484
2485 if (pView)
2486 {
2487 /* We need a real window as container for the view */
2488 [[OverlayWindow alloc] initWithParentView:pParentView overlayView:pView];
2489 /* Return the freshly created overlay view */
2490 DEBUG_FUNC_LEAVE();
2491 return pView;
2492 }
2493
2494 DEBUG_FUNC_LEAVE();
2495 return NULL;
2496}
2497
2498static DECLCALLBACK(void) vboxRcdCreateView(void *pvCb)
2499{
2500 DEBUG_FUNC_ENTER();
2501 CR_RCD_CREATEVIEW * pCreateView = (CR_RCD_CREATEVIEW*)pvCb;
2502 pCreateView->pView = vboxViewCreate(pCreateView->pWinInfo, pCreateView->pParentView);
2503 DEBUG_FUNC_LEAVE();
2504}
2505
2506void cocoaViewCreate(NativeNSViewRef *ppView, WindowInfo *pWinInfo, NativeNSViewRef pParentView, GLbitfield fVisParams)
2507{
2508 DEBUG_FUNC_ENTER();
2509 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2510
2511 VBoxMainThreadTaskRunner *pRunner = [VBoxMainThreadTaskRunner globalInstance];
2512 /* make sure all tasks are run, to preserve the order */
2513 [pRunner runTasksSyncIfPossible];
2514
2515 renderspuWinRetain(pWinInfo);
2516
2517 if (renderspuCalloutAvailable())
2518 {
2519 CR_RCD_CREATEVIEW CreateView;
2520 CreateView.pWinInfo = pWinInfo;
2521 CreateView.pParentView = pParentView;
2522 CreateView.fVisParams = fVisParams;
2523 CreateView.pView = NULL;
2524 renderspuCalloutClient(vboxRcdCreateView, &CreateView);
2525 *ppView = CreateView.pView;
2526 }
2527 else
2528 {
2529 DEBUG_MSG(("no callout available on createWindow\n"));
2530#if 0
2531 dispatch_sync(dispatch_get_main_queue(), ^{
2532#endif
2533 *ppView = vboxViewCreate(pWinInfo, pParentView);
2534#if 0
2535 });
2536#endif
2537 }
2538
2539 if (!*ppView)
2540 renderspuWinRelease(pWinInfo);
2541
2542 [pPool release];
2543
2544 DEBUG_FUNC_LEAVE();
2545}
2546
2547void cocoaViewReparent(NativeNSViewRef pView, NativeNSViewRef pParentView)
2548{
2549 DEBUG_FUNC_ENTER();
2550 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2551
2552 OverlayView* pOView = (OverlayView*)pView;
2553
2554 if (pOView)
2555 {
2556 [pOView vboxReparent:pParentView];
2557 }
2558
2559 [pPool release];
2560
2561 DEBUG_FUNC_LEAVE();
2562}
2563
2564typedef struct CR_RCD_DESTROYVIEW
2565{
2566 OverlayView *pView;
2567} CR_RCD_DESTROYVIEW;
2568
2569static DECLCALLBACK(void) vboxRcdDestroyView(void *pvCb)
2570{
2571 DEBUG_FUNC_ENTER();
2572 CR_RCD_DESTROYVIEW * pDestroyView = (CR_RCD_DESTROYVIEW*)pvCb;
2573 [pDestroyView->pView vboxDestroy];
2574 DEBUG_FUNC_LEAVE();
2575}
2576
2577void cocoaViewDestroy(NativeNSViewRef pView)
2578{
2579 DEBUG_FUNC_ENTER();
2580 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2581
2582 VBoxMainThreadTaskRunner *pRunner = [VBoxMainThreadTaskRunner globalInstance];
2583 [pRunner addObj:pView selector:@selector(vboxDestroy) arg:nil];
2584
2585 [pPool release];
2586
2587 DEBUG_FUNC_LEAVE();
2588}
2589
2590void cocoaViewShow(NativeNSViewRef pView, GLboolean fShowIt)
2591{
2592 DEBUG_FUNC_ENTER();
2593 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2594
2595 [(OverlayView*)pView vboxSetVisible:fShowIt];
2596
2597 [pPool release];
2598 DEBUG_FUNC_LEAVE();
2599}
2600
2601void cocoaViewDisplay(NativeNSViewRef pView)
2602{
2603 DEBUG_FUNC_ENTER();
2604 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2605
2606 DEBUG_WARN(("cocoaViewDisplay should never happen!\n"));
2607 DEBUG_MSG_1(("cocoaViewDisplay %p\n", (void*)pView));
2608 [(OverlayView*)pView swapFBO];
2609
2610 [pPool release];
2611
2612 DEBUG_FUNC_LEAVE();
2613}
2614
2615void cocoaViewSetPosition(NativeNSViewRef pView, NativeNSViewRef pParentView, int x, int y)
2616{
2617 DEBUG_FUNC_ENTER();
2618 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2619
2620 [(OverlayView*)pView vboxSetPos:NSMakePoint(x, y)];
2621
2622 [pPool release];
2623
2624 DEBUG_FUNC_LEAVE();
2625}
2626
2627void cocoaViewSetSize(NativeNSViewRef pView, int w, int h)
2628{
2629 DEBUG_FUNC_ENTER();
2630 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2631
2632 [(OverlayView*)pView vboxSetSize:NSMakeSize(w, h)];
2633
2634 [pPool release];
2635
2636 DEBUG_FUNC_LEAVE();
2637}
2638
2639typedef struct CR_RCD_GETGEOMETRY
2640{
2641 OverlayView *pView;
2642 NSRect rect;
2643} CR_RCD_GETGEOMETRY;
2644
2645static DECLCALLBACK(void) vboxRcdGetGeomerty(void *pvCb)
2646{
2647 DEBUG_FUNC_ENTER();
2648 CR_RCD_GETGEOMETRY * pGetGeometry = (CR_RCD_GETGEOMETRY*)pvCb;
2649 pGetGeometry->rect = [[pGetGeometry->pView window] frame];
2650 DEBUG_FUNC_LEAVE();
2651}
2652
2653void cocoaViewGetGeometry(NativeNSViewRef pView, int *pX, int *pY, int *pW, int *pH)
2654{
2655 DEBUG_FUNC_ENTER();
2656 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2657
2658 NSRect frame;
2659 VBoxMainThreadTaskRunner *pRunner = [VBoxMainThreadTaskRunner globalInstance];
2660 /* make sure all tasks are run, to preserve the order */
2661 [pRunner runTasksSyncIfPossible];
2662
2663
2664 if (renderspuCalloutAvailable())
2665 {
2666 CR_RCD_GETGEOMETRY GetGeometry;
2667 GetGeometry.pView = (OverlayView*)pView;
2668 renderspuCalloutClient(vboxRcdGetGeomerty, &GetGeometry);
2669 frame = GetGeometry.rect;
2670 }
2671 else
2672 {
2673 DEBUG_MSG(("no callout available on getGeometry\n"));
2674 frame = [[pView window] frame];
2675 }
2676
2677 *pX = frame.origin.x;
2678 *pY = frame.origin.y;
2679 *pW = frame.size.width;
2680 *pH = frame.size.height;
2681
2682 [pPool release];
2683
2684 DEBUG_FUNC_LEAVE();
2685}
2686
2687void cocoaViewPresentComposition(NativeNSViewRef pView, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry)
2688{
2689 DEBUG_FUNC_ENTER();
2690 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2691 NSOpenGLContext *pCtx;
2692
2693 /* view should not necesserily have a context set */
2694 pCtx = [(OverlayView*)pView glCtx];
2695 if (!pCtx)
2696 {
2697 ContextInfo * pCtxInfo = renderspuDefaultSharedContextAcquire();
2698 if (!pCtxInfo)
2699 {
2700 DEBUG_WARN(("renderspuDefaultSharedContextAcquire returned NULL"));
2701
2702 [pPool release];
2703 DEBUG_FUNC_LEAVE();
2704 return;
2705 }
2706
2707 pCtx = pCtxInfo->context;
2708
2709 [(OverlayView*)pView setGLCtx:pCtx];
2710 }
2711
2712 [(OverlayView*)pView presentComposition:pChangedEntry];
2713
2714 [pPool release];
2715
2716 DEBUG_FUNC_LEAVE();
2717}
2718
2719void cocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx)
2720{
2721 DEBUG_FUNC_ENTER();
2722 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2723
2724 DEBUG_MSG(("cocoaViewMakeCurrentContext(%p, %p)\n", (void*)pView, (void*)pCtx));
2725
2726 if (pView)
2727 {
2728 [(OverlayView*)pView setGLCtx:pCtx];
2729 [(OverlayView*)pView makeCurrentFBO];
2730 }
2731 else
2732 {
2733 [NSOpenGLContext clearCurrentContext];
2734 }
2735
2736 [pPool release];
2737
2738 DEBUG_FUNC_LEAVE();
2739}
2740
2741GLboolean cocoaViewNeedsEmptyPresent(NativeNSViewRef pView)
2742{
2743 DEBUG_FUNC_ENTER();
2744
2745 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2746
2747 GLboolean fNeedsPresent = [(OverlayView*)pView vboxNeedsEmptyPresent];
2748
2749 [pPool release];
2750
2751 DEBUG_FUNC_LEAVE();
2752
2753 return fNeedsPresent;
2754}
2755
2756void cocoaViewSetVisibleRegion(NativeNSViewRef pView, GLint cRects, const GLint* paRects)
2757{
2758 DEBUG_FUNC_ENTER();
2759 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
2760
2761 [(OverlayView*)pView setVisibleRegions:cRects paRects:paRects];
2762
2763 [pPool release];
2764
2765 DEBUG_FUNC_LEAVE();
2766}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette