VirtualBox

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

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

Use a context configured with the legacy OpenGL profile for getting information not available when using the OpenGL32Core profile.

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