VirtualBox

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

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

Preps for replacing DevVGA-SVGA3d-cocoa.m with renderspu_cocoa_helper.m, i.e. sharing the objective-C OpenGL wrappers between the two 3D solutions.

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