renderspu_cocoa_helper.m revision a8d502445ce722c6b9700c5579b4a38b58827b7d
1ce069685b24d243eb0464f46d4c56b250c64445vboxsync * VirtualBox OpenGL Cocoa Window System Helper Implementation.
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * Copyright (C) 2009-2012 Oracle Corporation
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * available from http://www.virtualbox.org. This file is free software;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * you can redistribute it and/or modify it under the terms of the GNU
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * General Public License (GPL) as published by the Free Software
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#include "chromium.h" /* For the visual bits of chromium */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/** @page pg_opengl_cocoa OpenGL - Cocoa Window System Helper
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync * How this works:
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * In general it is not so easy like on the other platforms, cause Cocoa
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * doesn't support any clipping of already painted stuff. In Mac OS X there is
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * the concept of translucent canvas's e.g. windows and there it is just
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * painted what should be visible to the user. Unfortunately this isn't the
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * concept of chromium. Therefor I reroute all OpenGL operation from the guest
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * to a frame buffer object (FBO). This is a OpenGL extension, which is
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * supported by all OS X versions we support (AFAIC tell). Of course the guest
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * doesn't know that and we have to make sure that the OpenGL state always is
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * in the right state to paint into the FBO and not to the front/back buffer.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * Several functions below (like cocoaBindFramebufferEXT, cocoaGetIntegerv,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * ...) doing this. When a swap or finish is triggered by the guest, the
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * content (which is already bound to an texture) is painted on the screen
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * within a separate OpenGL context. This allows the usage of the same
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * resources (texture ids, buffers ...) but at the same time having an
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * different internal OpenGL state. Another advantage is that we can paint a
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * thumbnail of the current output in a much more smaller (GPU accelerated
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * scale) version on a third context and use glReadPixels to get the actual
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * data. glReadPixels is a very slow operation, but as we just use a much more
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * smaller image, we can handle it (anyway this is only done 5 times per
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * Other things to know:
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * - If the guest request double buffering, we have to make sure there are two
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * buffers. We use the same FBO with 2 color attachments. Also glDrawBuffer
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * and glReadBuffer is intercepted to make sure it is painted/read to/from
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * the correct buffers. On swap our buffers are swapped and not the
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * - If the guest request a depth/stencil buffer, a combined render buffer for
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * this is created.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * - If the size of the guest OpenGL window changes, all FBO's, textures, ...
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * need to be recreated.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * - We need to track any changes to the parent window
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * (create/destroy/move/resize). The various classes like OverlayHelperView,
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync * OverlayWindow, ... are there for.
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync * - The HGCM service runs on a other thread than the Main GUI. Keeps this
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync * always in mind (see e.g. performSelectorOnMainThread in renderFBOToView)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * - We make heavy use of late binding. We can not be sure that the GUI (or any
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * other third party GUI), overwrite our NSOpenGLContext. So we always ask if
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * this is our own one, before use. Really neat concept of Objective-C/Cocoa
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/* Debug macros */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#define FBO 1 /* Disable this to see how the output is without the FBO in the middle of the processing chain. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync# define CR_RENDER_FORCE_PRESENT_MAIN_THREAD /* force present schedule to main thread */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync# define SHOW_WINDOW_BACKGROUND 1 /* Define this to see the window background even if the window is clipped */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync# define DEBUG_VERBOSE /* Define this to get some debug info about the messages flow. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } while (0)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync do {} while (0)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } while (0)
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync do {} while (0)
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync }while (0);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync case GL_INVALID_ENUM: errStr = RTStrDup("GL_INVALID_ENUM"); break;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync case GL_INVALID_VALUE: errStr = RTStrDup("GL_INVALID_VALUE"); break;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync case GL_INVALID_OPERATION: errStr = RTStrDup("GL_INVALID_OPERATION"); break;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync case GL_STACK_OVERFLOW: errStr = RTStrDup("GL_STACK_OVERFLOW"); break;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync case GL_STACK_UNDERFLOW: errStr = RTStrDup("GL_STACK_UNDERFLOW"); break;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync case GL_OUT_OF_MEMORY: errStr = RTStrDup("GL_OUT_OF_MEMORY"); break;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync case GL_TABLE_TOO_LARGE: errStr = RTStrDup("GL_TABLE_TOO_LARGE"); break;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync DEBUG_MSG(("%s:%d: glError %d (%s)\n", file, line, g, errStr));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync do {} while (0)
b986941f0aa5155c7fd37da0aa5876675a7680e4vboxsync NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync renderspu_SystemMakeCurrent(pWinInfo, 0, pCtxInfo);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync} VBOX_CR_RENDER_CTX_INFO, *PVBOX_CR_RENDER_CTX_INFO;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsyncstatic void vboxCtxEnter(NSOpenGLContext*pCtx, PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync NSView *pOldView = (pOldCtx ? [pOldCtx view] : nil);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync bool fNeedCtxSwitch = (pOldCtx != pCtx || pOldView != pView);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync // Assert(pOldCtx == m_pGLCtx);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync // Assert(pOldView == self);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync // Assert(fNeedCtxSwitch);
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsyncstatic void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync NSOpenGLContext *pTstOldCtx = [NSOpenGLContext currentContext];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync NSView *pTstOldView = (pTstOldCtx ? [pTstOldCtx view] : nil);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/** Custom OpenGL context class.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * This implementation doesn't allow to set a view to the
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * context, but save the view for later use. Also it saves a copy of the
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * pixel format used to create that context for later use. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/** The custom view class.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * This is the main class of the cocoa OpenGL implementation. It
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * manages an frame buffer object for the rendering of the guest
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * applications. The guest applications render in this frame buffer which
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * is bind to an OpenGL texture. To display the guest content, an secondary
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * shared OpenGL context of the main OpenGL context is created. The secondary
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * context is marked as non opaque & the texture is displayed on an object
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * which is composed out of the several visible region rectangles. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /** The corresponding dock tile view of this OpenGL view & all helper
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * members. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* For clipping */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* Position/Size tracking */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync /** This is necessary for clipping on the root window */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync- (void)vboxPresent:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync- (void)vboxPresentCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync- (void)vboxPresentToDockTileCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync- (void)vboxPresentToViewCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync- (void)presentComposition:(const VBOXVR_SCR_COMPOSITOR_ENTRY*)pChangedEntry;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync- (void)setVisibleRegions:(GLint)cRects paRects:(const GLint*)paRects;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/** Helper view.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * This view is added as a sub view of the parent view to track
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * main window changes. Whenever the main window is changed
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * (which happens on fullscreen/seamless entry/exit) the overlay
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * window is informed & can add them self as a child window
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * again. */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync-(id)initWithOverlayWindow:(OverlayWindow*)pOverlayWindow;
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync/** Custom window class.
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync * This is the overlay window which contains our custom NSView.
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync * Its a direct child of the Qt Main window. It marks its background
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync * transparent & non opaque to make clipping possible. It also disable mouse
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync * events and handle frame change events of the parent view. */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView;
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync- (void)parentWindowFrameChanged:(NSNotification *)note;
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* We need a lock cause the thumb image could be accessed from the main
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync * thread when someone is calling display on the dock tile & from the
8ccde4f32d77b1ad3f02111f28a48ee85abf6779vboxsync * OpenGL thread when the thumbnail is updated. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* Create a buffer for our thumbnail image. Its in the size of this view. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync m_ThumbBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync m_ThumbImage = [[NSImage alloc] initWithSize:[m_ThumbBitmap size]];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7] set];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [NSBezierPath fillRect:NSMakeRect(0, 0, frame.size.width, frame.size.height)];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [m_ThumbImage drawAtPoint:NSMakePoint(0, 0) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/********************************************************************************
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync* OverlayOpenGLContext class implementation
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync********************************************************************************/
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync-(id)initWithFormat:(NSOpenGLPixelFormat*)format shareContext:(NSOpenGLContext*)share
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync self = [super initWithFormat:format shareContext:share];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OCTX(%p): init OverlayOpenGLContext\n", (void*)self));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OCTX(%p): dealloc OverlayOpenGLContext\n", (void*)self));
e48239695d41f806ff02d8a60b97dc20d4822d7avboxsync [m_pPixelFormat getValues:&val forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:0];
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync DEBUG_MSG(("OCTX(%p): setView: new view: %p\n", (void*)self, (void*)view));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync return [super view];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OCTX(%p): clearDrawable\n", (void*)self));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/********************************************************************************
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync* OverlayHelperView class implementation
36a04912b64bea8318327fe0723535f1b3f041b0vboxsync********************************************************************************/
36a04912b64bea8318327fe0723535f1b3f041b0vboxsync-(id)initWithOverlayWindow:(OverlayWindow*)pOverlayWindow
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OHVW(%p): init OverlayHelperView\n", (void*)self));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OHVW(%p): viewDidMoveToWindow: new win: %p\n", (void*)self, (void*)[self window]));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [m_pOverlayWindow parentWindowChanged:[self window]];
3933885bc0c2c93436d858a14564c6179ec72872vboxsync/********************************************************************************
3933885bc0c2c93436d858a14564c6179ec72872vboxsync* OverlayWindow class implementation
3933885bc0c2c93436d858a14564c6179ec72872vboxsync********************************************************************************/
3933885bc0c2c93436d858a14564c6179ec72872vboxsync- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if((self = [super initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]))
3933885bc0c2c93436d858a14564c6179ec72872vboxsync m_pOverlayHelperView = [[OverlayHelperView alloc] initWithOverlayWindow:self];
3933885bc0c2c93436d858a14564c6179ec72872vboxsync /* Add the helper view as a child of the parent view to get notifications */
060f7ec6ae5c99df18341ef2e1f3e91f4b0c89f1vboxsync /* Make sure this window is transparent */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* For debugging */
cc74f15083bf80fbc96723a89faa06c15d0dead8vboxsync [self setBackgroundColor:[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7]];
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync /* Disable mouse events for this window */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync /* Initial set the position to the parents view top/left (Compiz fix). */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync [m_pParentView convertPoint:NSZeroPoint toView:nil]]];
3933885bc0c2c93436d858a14564c6179ec72872vboxsync /* Set the overlay view as our content view */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync /* Add ourself as a child to the parent views window. Note: this has to
3933885bc0c2c93436d858a14564c6179ec72872vboxsync * be done last so that everything else is setup in
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync * parentWindowChanged. */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync [pParentWin addChildWindow:self ordered:NSWindowAbove];
3933885bc0c2c93436d858a14564c6179ec72872vboxsync DEBUG_MSG(("OWIN(%p): init OverlayWindow\n", (void*)self));
3933885bc0c2c93436d858a14564c6179ec72872vboxsync DEBUG_MSG(("OWIN(%p): dealloc OverlayWindow\n", (void*)self));
3933885bc0c2c93436d858a14564c6179ec72872vboxsync [[NSNotificationCenter defaultCenter] removeObserver:self];
3933885bc0c2c93436d858a14564c6179ec72872vboxsync- (void)parentWindowFrameChanged:(NSNotification*)pNote
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync DEBUG_MSG(("OWIN(%p): parentWindowFrameChanged\n", (void*)self));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* Reposition this window with the help of the OverlayView. Perform the
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * call in the OpenGL thread. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [m_pOverlayView performSelector:@selector(vboxReshapePerform) onThread:m_Thread withObject:nil waitUntilDone:YES];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OWIN(%p): parentWindowChanged\n", (void*)self));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [[NSNotificationCenter defaultCenter] removeObserver:self];
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync /* Ask to get notifications when our parent window frame changes. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* Add us self as child window */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [pWindow addChildWindow:self ordered:NSWindowAbove];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* Reshape the overlay view after a short waiting time to let the main
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync * window resize itself properly. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [m_pOverlayView performSelector:@selector(vboxReshapePerform) withObject:nil afterDelay:0.2];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(vboxReshapePerform) userInfo:nil repeats:NO];
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/********************************************************************************
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync* OverlayView class implementation
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync********************************************************************************/
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* Make some reasonable defaults */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync m_RootRect = NSMakeRect(0, 0, m_Size.width, m_Size.height);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OVIW(%p): init OverlayView\n", (void*)self));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OVIW(%p): dealloc OverlayView\n", (void*)self));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OVIW(%p): setGLCtx: new ctx: %p\n", (void*)self, (void*)pCtx));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* ensure the context drawable is cleared to avoid holding a reference to inexistent view */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /*[m_pGLCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OVIW(%p): setParentView: new view: %p\n", (void*)self, (void*)pView));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OVIW(%p): setOverlayWin: new win: %p\n", (void*)self, (void*)pWin));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OVIW(%p): setPos: new pos: %d, %d\n", (void*)self, (int)pos.x, (int)pos.y));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* we need to redwar on regions change, however the compositor now is cleared
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * because all compositor&window data-related modifications are performed with compositor cleared
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * the renderspu client will re-set the compositor after modifications are complete
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * this way we indicate renderspu generic code not to ignore the empty compositor */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* generally this should not be needed for setPos because compositor should not be zeroed with it,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * in any way setting this flag here should not hurt as it will be re-set on next present */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OVIW(%p): setSize: new size: %dx%d\n", (void*)self, (int)size.width, (int)size.height));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync [self performSelectorOnMainThread:@selector(vboxReshapeOnResizePerform) withObject:nil waitUntilDone:NO];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* we need to redwar on regions change, however the compositor now is cleared
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * because all compositor&window data-related modifications are performed with compositor cleared
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * the renderspu client will re-set the compositor after modifications are complete
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * this way we indicate renderspu generic code not to ignore the empty compositor */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* generally this should not be needed for setSize because compositor should not be zeroed with it,
c9e3f6ad81ea9a279ffb537720699e552882c40avboxsync * in any way setting this flag here should not hurt as it will be re-set on next present */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OVIW(%p): updateViewport\n", (void*)self));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* Update the viewport for our OpenGL view */
629169500a4e1696f37dd3118a791d68278f71davboxsync /* Clear background to transparent */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (pCurCtx && pCurCtx == m_pGLCtx && (pCurView = [pCurCtx view]) == self)
4c13f0d619c9707412b40eae8e3beafae5cf1858vboxsync /* do it in a lazy way */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("OVIW(%p): vboxReshapePerform\n", (void*)self));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("FIXED parentFrame [%f:%f], [%f:%f]\n", parentFrame.origin.x, parentFrame.origin.y, parentFrame.size.width, parentFrame.size.height));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("FIXED(view) parentPos [%f:%f]\n", parentPos.x, parentPos.y));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync parentPos = [m_pParentView convertPoint:parentPos toView:nil];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("FIXED parentPos(win) [%f:%f]\n", parentPos.x, parentPos.y));
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync parentPos = [[m_pParentView window] convertBaseToScreen:parentPos];
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync DEBUG_MSG(("FIXED parentPos(screen) [%f:%f]\n", parentPos.x, parentPos.y));
b2c92fb03e119c7de54f86a32fae9c1d59bc479evboxsync childPos = NSMakePoint(m_Pos.x, m_Pos.y + m_Size.height);
b2c92fb03e119c7de54f86a32fae9c1d59bc479evboxsync DEBUG_MSG(("FIXED(view) childPos [%f:%f]\n", childPos.x, childPos.y));
b2c92fb03e119c7de54f86a32fae9c1d59bc479evboxsync childPos = [m_pParentView convertPoint:childPos toView:nil];
b2c92fb03e119c7de54f86a32fae9c1d59bc479evboxsync DEBUG_MSG(("FIXED(win) childPos [%f:%f]\n", childPos.x, childPos.y));
b2c92fb03e119c7de54f86a32fae9c1d59bc479evboxsync childPos = [[m_pParentView window] convertBaseToScreen:childPos];
b2c92fb03e119c7de54f86a32fae9c1d59bc479evboxsync DEBUG_MSG(("FIXED childPos(screen) [%f:%f]\n", childPos.x, childPos.y));
b2c92fb03e119c7de54f86a32fae9c1d59bc479evboxsync childFrame = NSMakeRect(childPos.x, childPos.y, m_Size.width, m_Size.height);
b2c92fb03e119c7de54f86a32fae9c1d59bc479evboxsync DEBUG_MSG(("FIXED childFrame [%f:%f], [%f:%f]\n", childFrame.origin.x, childFrame.origin.y, childFrame.size.width, childFrame.size.height));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* We have to make sure that the overlay window will not be displayed out
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * of the parent window. So intersect both frames & use the result as the new
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * frame for the window. */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync newFrame = NSIntersectionRect(parentFrame, childFrame);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("[%#p]: parentFrame pos[%f : %f] size[%f : %f]\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("[%#p]: childFrame pos[%f : %f] size[%f : %f]\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync DEBUG_MSG(("[%#p]: newFrame pos[%f : %f] size[%f : %f]\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* Later we have to correct the texture position in the case the window is
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * 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);
(void*)self,
printf ("sc rect: %d %d %d %d\n", (int) scrollRect.origin.x,(int) scrollRect.origin.y,(int) scrollRect.size.width,(int) scrollRect.size.height);
printf ("bound rect: %d %d %d %d\n", (int) b.origin.x,(int) b.origin.y,(int) b.size.width,(int) b.size.height);
if (m_pSharedGLCtx)
- (void)createDockTile
if (pDockScreen)
- (void)deleteDockTile
- (void)makeCurrentFBO
if (m_pGLCtx)
glFlush();
if (m_fNeedCtxUpdate == true)
m_fNeedCtxUpdate = false;
if (!m_FBOId)
if (m_pSharedGLCtx)
if (!m_pBlitter)
int rc = CrBltInit(m_pBlitter, NULL, false, false, &render_spu.GlobalShaders, &render_spu.blitterDispatch);
NSOpenGLContext *pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
m_fNeedViewportUpdate = true;
- (void)vboxTryDraw
glFlush();
- (void)vboxTryDrawUI
if (pCompositor)
if (!m_pSharedGLCtx)
if (!pCompositor)
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(vboxTryDrawUI) userInfo:nil repeats:NO];
- (void)swapFBO
m_fNeedViewportUpdate = true;
m_fNeedViewportUpdate = false;
DECLINLINE(void) vboxNSRectToRectUnstretched(const NSRect *pR, RTRECT *pRect, float xStretch, float yStretch)
DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, float xStretch, float yStretch)
DEBUG_MSG(("OVIW(%p): rF2V frame: [%i, %i, %i, %i]\n", (void*)self, (int)r.origin.x, (int)r.origin.y, (int)r.size.width, (int)r.size.height));
m_fDataVisible = false;
int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
uint32_t i;
VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags | CRBLT_F_NOALPHA);
m_fDataVisible = true;
- (void)vboxBlitterSyncWindow
NSRect r;
if (!m_pBlitter)
glFlush();
int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
uint32_t i;
VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
glFinish();
[[[NSApplication sharedApplication] dockTile] performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:NO];
- (void)clearVisibleRegions
if(m_paClipRects)
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]));
screenContent = [contentView performSelector:@selector(screenContentWithParentView:) withObject:(id)m_pParentView];
return screenContent;
- (void)reshapeDockTile
/* todo: this is not correct, we should use framebuffer size here, while parent view frame size may differ in case of scrolling */
newFrame = NSMakeRect((int)(m_Pos.x * m_FBOThumbScaleX), (int)(dockFrame.size.height - (m_Pos.y + m_Size.height - m_yInvRootOffset) * m_FBOThumbScaleY), (int)(m_Size.width * m_FBOThumbScaleX), (int)(m_Size.height * m_FBOThumbScaleY));
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));
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));
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);
@end
void cocoaGLCtxCreate(NativeNSOpenGLContextRef *ppCtx, GLbitfield fVisParams, NativeNSOpenGLContextRef pSharedCtx)
if (pFmt)
void cocoaViewCreate(NativeNSViewRef *ppView, WindowInfo *pWinInfo, NativeNSViewRef pParentView, GLbitfield fVisParams)
OverlayView* pView = [[OverlayView alloc] initWithFrame:NSZeroRect thread:RTThreadSelf() parentView:pParentView winInfo:pWinInfo];
if (pView)
if (pOView)
[pOView performSelectorOnMainThread:@selector(vboxReshapeOnReparentPerform) withObject:nil waitUntilDone:NO];
void cocoaViewPresentComposition(NativeNSViewRef pView, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry)
if (!pCtx)
if (!pCtxInfo)
if (pView)