VirtualBox

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

Last change on this file since 52560 was 52560, checked in by vboxsync, 10 years ago

crOpenGL: window reference

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

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