VirtualBox

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

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

Rename include/VBox/VBoxOGLTest.h to more common name (VBoxOGL.h) since it is planned to use it in order to share functionality between 3D and GUI.

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