/* $Id$ */
/** @file
* VirtualBox OpenGL Cocoa Window System Helper Implementation.
*
* @remarks Inspired by HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m.
*/
/*
* Copyright (C) 2009-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "DevVGA-SVGA3d-cocoa.h"
#import <Cocoa/Cocoa.h>
#import <OpenGL/gl.h>
/* Debug macros */
#if 0 /*def DEBUG_VERBOSE*/
/*# error "should be disabled!"*/
Assert(0); \
} while (0)
Assert(0); \
} while (0)
# define DEBUG_FUNC_ENTER() \
#define DEBUG_FUNC_LEAVE() do { \
} while (0)
DEBUG_MSG(valuefmtnl); \
} while (0)
#else
} while (0)
do {} while (0)
} while (0)
do {} while (0)
# define CHECK_GL_ERROR()\
do {} while (0)
/** Custom OpenGL context class.
*
* This implementation doesn't allow to set a view to the
* context, but save the view for later use. Also it saves a copy of the
* pixel format used to create that context for later use. */
@interface VMSVGA3DOpenGLContext: NSOpenGLContext
{
@private
}
@end
@interface VMSVGA3DOverlayView: NSView
{
@private
/** This is necessary for clipping on the root window */
float m_yInvRootOffset;
}
- (NSOpenGLContext*)glCtx;
- (NSWindow*)overlayWin;
- (void)updateViewportCS;
- (void)reshape;
@end
/** Helper view.
*
* This view is added as a sub view of the parent view to track
* main window changes. Whenever the main window is changed
* (which happens on fullscreen/seamless entry/exit) the overlay
* window is informed & can add them self as a child window
* again. */
@class VMSVGA3DOverlayWindow;
@interface VMSVGA3DOverlayHelperView: NSView
{
@private
}
@end
/** Custom window class.
*
* This is the overlay window which contains our custom NSView.
* Its a direct child of the Qt Main window. It marks its background
* transparent & non opaque to make clipping possible. It also disable mouse
* events and handle frame change events of the parent view. */
@interface VMSVGA3DOverlayWindow: NSWindow
{
@private
}
@end
/********************************************************************************
*
* VMSVGA3DOpenGLContext class implementation
*
********************************************************************************/
{
if (self)
return self;
}
- (void)dealloc
{
[super dealloc];
}
{
}
{
}
{
return m_pView;
}
-(void)clearDrawable
{
[super clearDrawable];
}
{
return m_pPixelFormat;
}
@end
/********************************************************************************
*
* VMSVGA3DOverlayHelperView class implementation
*
********************************************************************************/
{
return self;
}
-(void)viewDidMoveToWindow
{
}
@end
/********************************************************************************
*
* VMSVGA3DOverlayWindow class implementation
*
********************************************************************************/
{
if((self = [super initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]))
{
/* Add the helper view as a child of the parent view to get notifications */
/* Make sure this window is transparent */
/* For debugging */
#else
/* Disable mouse events for this window */
/* Set the overlay view as our content view */
/* Add ourself as a child to the parent views window. Note: this has to
* be done last so that everything else is setup in
* parentWindowChanged. */
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
{
}
{
{
/* Ask to get notifications when our parent window frame changes. */
/* Add us self as child window */
}
}
@end
/********************************************************************************
*
* VMSVGA3DOverlayView class implementation
*
********************************************************************************/
{
/* Make some reasonable defaults */
m_Pos = NSZeroPoint;
m_yInvRootOffset = 0;
return self;
}
- (void)cleanupData
{
/*[self deleteDockTile];*/
#if 0
if (m_pSharedGLCtx)
{
m_pBlitter = nil;
}
/*[self clearVisibleRegions];*/
}
- (void)dealloc
{
[self cleanupData];
[super dealloc];
}
{
DEBUG_MSG(("OVIW(%p): setGLCtx: new ctx: %p (old: %p)\n", (void*)self, (void*)pCtx, (void *)m_pGLCtx));
{
return;
}
/* ensure the context drawable is cleared to avoid holding a reference to inexistent view */
if (m_pGLCtx)
{
/*[m_pGLCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
}
if (pCtx)
}
- (NSOpenGLContext*)glCtx
{
return m_pGLCtx;
}
{
}
- (NSWindow*)overlayWin
{
return m_pOverlayWin;
}
{
}
{
return m_Pos;
}
{
}
{
return m_Size;
}
- (void)updateViewportCS
{
/* Update the viewport for our OpenGL view */
/* [m_pSharedGLCtx update]; */
/* Clear background to transparent */
/* glClearColor(0.0f, 0.0f, 0.0f, 0.0f);*/
}
- (void)reshape
{
/* Getting the right screen coordinates of the parents frame is a little bit
* complicated. */
DEBUG_MSG(("FIXED parentFrame [%f:%f], [%f:%f]\n", parentFrame.origin.x, parentFrame.origin.y, parentFrame.size.width, parentFrame.size.height));
parentPos = [[m_pParentView window] convertBaseToScreen:[[m_pParentView superview] convertPointToBase:NSMakePoint(parentFrame.origin.x, parentFrame.origin.y + parentFrame.size.height)]];
/* Calculate the new screen coordinates of the overlay window. */
childPos = [[m_pParentView window] convertBaseToScreen:[[m_pParentView superview] convertPointToBase:childPos]];
/* Make a frame out of it. */
DEBUG_MSG(("FIXED childFrame [%f:%f], [%f:%f]\n", childFrame.origin.x, childFrame.origin.y, childFrame.size.width, childFrame.size.height));
/* We have to make sure that the overlay window will not be displayed out
* of the parent window. So intersect both frames & use the result as the new
* frame for the window. */
DEBUG_MSG(("[%p]: parentFrame pos[%f : %f] size[%f : %f]\n",
(void*)self,
DEBUG_MSG(("[%p]: childFrame pos[%f : %f] size[%f : %f]\n",
(void*)self,
DEBUG_MSG(("[%p]: newFrame pos[%f : %f] size[%f : %f]\n",
(void*)self,
/* Later we have to correct the texture position in the case the window is
* out of the parents window frame. So save the shift values for later use. */
m_RootRect.origin.y = childFrame.size.height + childFrame.origin.y - (newFrame.size.height + newFrame.origin.y);
DEBUG_MSG(("[%p]: m_RootRect pos[%f : %f] size[%f : %f]\n",
(void*)self,
/* Set the new frame. */
#if 0
/* Make sure the context is updated according */
/* [self updateViewport]; */
if (m_pSharedGLCtx)
{
}
}
@end
void vmsvga3dCocoaCreateContext(NativeNSOpenGLContextRef *ppCtx, NativeNSOpenGLContextRef pShareCtx, bool fOtherProfile)
{
// Consider to remove it and check if it's harmless.
{
//NSOpenGLPFAWindow, - obsolete/deprecated, try work without it...
0
};
/* Choose a pixel format */
if (pFmt)
{
}
else
{
AssertFailed();
}
}
{
}
{
/* Create our worker view */
VMSVGA3DOverlayView* pView = [[VMSVGA3DOverlayView alloc] initWithFrame:NSZeroRect parentView:pParentView];
if (pView)
{
/* We need a real window as container for the view */
/* Return the freshly created overlay view */
}
}
{
}
{
}
{
}
{
/* Always flush before flush. glXMakeCurrent and wglMakeCurrent does this
implicitly, seemingly NSOpenGLContext::makeCurrentContext doesn't. */
glFlush();
if (pView)
{
/* [(VMSVGA3DOverlayView*)pView makeCurrentFBO];*/
}
else
{
}
}
{
[pCtx flushBuffer];
}