renderspu_cocoa.c revision d171c6e83ee2cdae7d630182ee101efbf0f8c0e8
/** @file
* VirtualBox OpenGL Cocoa Window System implementation
*/
/*
* Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* 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 <OpenGL/OpenGL.h>
#include "renderspu.h"
#include <iprt/process.h>
#include <iprt/string.h>
#include <iprt/path.h>
GLboolean renderspu_SystemInitVisual(VisualInfo *pVisInfo)
{
CRASSERT(pVisInfo);
/* cocoaGLVisualCreate(&pCtxInfo->context);*/
return GL_TRUE;
}
GLboolean renderspu_SystemCreateContext(VisualInfo *pVisInfo, ContextInfo *pCtxInfo, ContextInfo *pSharedCtxInfo)
{
CRASSERT(pVisInfo);
CRASSERT(pCtxInfo);
pCtxInfo->currentWindow = NULL;
cocoaGLCtxCreate(&pCtxInfo->context, pVisInfo->visAttribs, pSharedCtxInfo ? pSharedCtxInfo->context : NULL);
return GL_TRUE;
}
void renderspu_SystemDestroyContext(ContextInfo *pCtxInfo)
{
if(!pCtxInfo)
return;
if(pCtxInfo->context)
{
cocoaGLCtxDestroy(pCtxInfo->context);
pCtxInfo->context = NULL;
}
}
void renderspuFullscreen(WindowInfo *pWinInfo, GLboolean fFullscreen)
{
/* Real fullscreen isn't supported by VirtualBox */
}
GLboolean renderspu_SystemVBoxCreateWindow(VisualInfo *pVisInfo, GLboolean fShowIt, WindowInfo *pWinInfo)
{
CRASSERT(pVisInfo);
CRASSERT(pWinInfo);
/* VirtualBox is the only frontend which support 3D right now. */
char pszName[256];
if (RTProcGetExecutablePath(pszName, sizeof(pszName)))
/* Check for VirtualBox and VirtualBoxVM */
if (RTStrNICmp(RTPathFilename(pszName), "VirtualBox", 10) != 0)
return GL_FALSE;
pWinInfo->visual = pVisInfo;
pWinInfo->window = NULL;
pWinInfo->nativeWindow = NULL;
pWinInfo->currentCtx = NULL;
#ifdef __LP64__
NativeNSViewRef pParentWin = (NativeNSViewRef)render_spu_parent_window_id;
#else /* __LP64__ */
NativeNSViewRef pParentWin = (NativeNSViewRef)(uint32_t)render_spu_parent_window_id;
#endif /* __LP64__ */
cocoaViewCreate(&pWinInfo->window, pWinInfo, pParentWin, pVisInfo->visAttribs);
if (fShowIt)
renderspu_SystemShowWindow(pWinInfo, fShowIt);
return GL_TRUE;
}
void renderspu_SystemReparentWindow(WindowInfo *pWinInfo)
{
#ifdef __LP64__
NativeNSViewRef pParentWin = (NativeNSViewRef)render_spu_parent_window_id;
#else /* __LP64__ */
NativeNSViewRef pParentWin = (NativeNSViewRef)(uint32_t)render_spu_parent_window_id;
#endif /* __LP64__ */
cocoaViewReparent(pWinInfo->window, pParentWin);
}
void renderspu_SystemDestroyWindow(WindowInfo *pWinInfo)
{
CRASSERT(pWinInfo);
cocoaViewDestroy(pWinInfo->window);
}
void renderspu_SystemWindowPosition(WindowInfo *pWinInfo, GLint x, GLint y)
{
CRASSERT(pWinInfo);
#ifdef __LP64__
NativeNSViewRef pParentWin = (NativeNSViewRef)render_spu_parent_window_id;
#else /* __LP64__ */
NativeNSViewRef pParentWin = (NativeNSViewRef)(uint32_t)render_spu_parent_window_id;
#endif /* __LP64__ */
/*pParentWin is unused in the call, otherwise it might hold incorrect value if for ex. last reparent call was for
a different screen*/
cocoaViewSetPosition(pWinInfo->window, pParentWin, x, y);
}
void renderspu_SystemWindowSize(WindowInfo *pWinInfo, GLint w, GLint h)
{
CRASSERT(pWinInfo);
cocoaViewSetSize(pWinInfo->window, w, h);
}
void renderspu_SystemGetWindowGeometry(WindowInfo *pWinInfo, GLint *pX, GLint *pY, GLint *pW, GLint *pH)
{
CRASSERT(pWinInfo);
cocoaViewGetGeometry(pWinInfo->window, pX, pY, pW, pH);
}
void renderspu_SystemGetMaxWindowSize(WindowInfo *pWinInfo, GLint *pW, GLint *pH)
{
CRASSERT(pWinInfo);
*pW = 10000;
*pH = 10000;
}
void renderspu_SystemShowWindow(WindowInfo *pWinInfo, GLboolean fShowIt)
{
CRASSERT(pWinInfo);
cocoaViewShow(pWinInfo->window, fShowIt);
}
void renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
{
cocoaViewPresentComposition(window->window, pChangedEntry);
}
void renderspu_SystemMakeCurrent(WindowInfo *pWinInfo, GLint nativeWindow, ContextInfo *pCtxInfo)
{
/* if(pWinInfo->visual != pCtxInfo->visual)*/
/* printf ("visual mismatch .....................\n");*/
nativeWindow = 0;
if (pWinInfo && pCtxInfo)
cocoaViewMakeCurrentContext(pWinInfo->window, pCtxInfo->context);
else
cocoaViewMakeCurrentContext(NULL, NULL);
}
void renderspu_SystemSwapBuffers(WindowInfo *pWinInfo, GLint flags)
{
CRASSERT(pWinInfo);
cocoaViewDisplay(pWinInfo->window);
}
void renderspu_SystemWindowVisibleRegion(WindowInfo *pWinInfo, GLint cRects, const GLint* paRects)
{
CRASSERT(pWinInfo);
cocoaViewSetVisibleRegion(pWinInfo->window, cRects, paRects);
}
void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *pWinInfo)
{
}
int renderspu_SystemInit()
{
return VINF_SUCCESS;
}
int renderspu_SystemTerm()
{
CrGlslTerm(&render_spu.GlobalShaders);
return VINF_SUCCESS;
}
typedef struct CR_RENDER_CTX_INFO
{
ContextInfo * pContext;
WindowInfo * pWindow;
} CR_RENDER_CTX_INFO;
void renderspuCtxInfoInitCurrent(CR_RENDER_CTX_INFO *pInfo)
{
GET_CONTEXT(pCurCtx);
pInfo->pContext = pCurCtx;
pInfo->pWindow = pCurCtx->currentWindow;
}
void renderspuCtxInfoRestoreCurrent(CR_RENDER_CTX_INFO *pInfo)
{
GET_CONTEXT(pCurCtx);
if (pCurCtx == pInfo->pContext && (!pCurCtx || pCurCtx->currentWindow == pInfo->pWindow))
return;
renderspuPerformMakeCurrent(pInfo->pWindow, 0, pInfo->pContext);
}
GLboolean renderspuCtxSetCurrentWithAnyWindow(ContextInfo * pContext, CR_RENDER_CTX_INFO *pInfo)
{
WindowInfo * window;
renderspuCtxInfoInitCurrent(pInfo);
if (pInfo->pContext == pContext)
return GL_TRUE;
window = pContext->currentWindow;
if (!window)
{
window = renderspuGetDummyWindow(pContext->BltInfo.Base.visualBits);
if (!window)
{
crWarning("renderspuGetDummyWindow failed");
return GL_FALSE;
}
}
Assert(window);
renderspuPerformMakeCurrent(window, 0, pContext);
return GL_TRUE;
}
void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext)
{
CRASSERT(fromContext != toContext);
if (!CrGlslIsInited(&render_spu.GlobalShaders))
{
CrGlslInit(&render_spu.GlobalShaders, render_spu.blitterDispatch);
}
if (fromContext)
{
if (CrGlslNeedsCleanup(&render_spu.GlobalShaders))
{
CR_RENDER_CTX_INFO Info;
if (renderspuCtxSetCurrentWithAnyWindow(fromContext, &Info))
{
CrGlslCleanup(&render_spu.GlobalShaders);
renderspuCtxInfoRestoreCurrent(&Info);
}
else
crWarning("renderspuCtxSetCurrentWithAnyWindow failed!");
}
}
else
{
CRASSERT(!CrGlslNeedsCleanup(&render_spu.GlobalShaders));
}
CRASSERT(!CrGlslNeedsCleanup(&render_spu.GlobalShaders));
if (toContext)
{
CR_RENDER_CTX_INFO Info;
if (renderspuCtxSetCurrentWithAnyWindow(toContext, &Info))
{
int rc = CrGlslProgGenAllNoAlpha(&render_spu.GlobalShaders);
if (!RT_SUCCESS(rc))
crWarning("CrGlslProgGenAllNoAlpha failed, rc %d", rc);
renderspuCtxInfoRestoreCurrent(&Info);
}
else
crWarning("renderspuCtxSetCurrentWithAnyWindow failed!");
}
}