mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-02 17:46:22 +03:00
V3d_View::AutoZFit() is now called only before redraw within methods V3d_View::Redraw() and V3d_View::Update(). Graphic3d_CView now holds Aspect_ExtendedRealitySession object. Aspect_OpenVRSession implements new interface via optional OpenVR library. Graphic3d_CView::ProcessInput() - added new interface method which should be called for processing positional input (head tracking). Graphic3d_Camera now allows setting custom stereoscopic Projection matrices. OpenGl_Context::Camera() - context now holds Camera object in addition to active camera matrices. genproj.tcl has been extended to handle optional CSF_OpenVR dependency.
404 lines
12 KiB
Plaintext
404 lines
12 KiB
Plaintext
// Created on: 2012-11-12
|
|
// Created by: Kirill Gavrilov
|
|
// Copyright (c) 2012-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
#if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
|
|
|
|
#ifndef GL_GLEXT_LEGACY
|
|
#define GL_GLEXT_LEGACY // To prevent inclusion of system glext.h on Mac OS X 10.6.8
|
|
#endif
|
|
|
|
// macOS 10.4 deprecated OpenGL framework - suppress useless warnings
|
|
#define GL_SILENCE_DEPRECATION
|
|
|
|
#import <TargetConditionals.h>
|
|
|
|
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
|
#import <UIKit/UIKit.h>
|
|
#else
|
|
#import <Cocoa/Cocoa.h>
|
|
|
|
#if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7)
|
|
@interface NSView (LionAPI)
|
|
- (NSSize )convertSizeToBacking: (NSSize )theSize;
|
|
@end
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#include <OpenGl_Window.hxx>
|
|
#include <OpenGl_FrameBuffer.hxx>
|
|
|
|
#include <OpenGl_Context.hxx>
|
|
#include <Aspect_GraphicDeviceDefinitionError.hxx>
|
|
#include <Cocoa_LocalPool.hxx>
|
|
#include <TCollection_AsciiString.hxx>
|
|
#include <TCollection_ExtendedString.hxx>
|
|
|
|
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
|
//
|
|
#else
|
|
#include <OpenGL/CGLRenderers.h>
|
|
#endif
|
|
|
|
// =======================================================================
|
|
// function : OpenGl_Window
|
|
// purpose :
|
|
// =======================================================================
|
|
OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
|
|
const Handle(Aspect_Window)& thePlatformWindow,
|
|
Aspect_RenderingContext theGContext,
|
|
const Handle(OpenGl_Caps)& theCaps,
|
|
const Handle(OpenGl_Context)& theShareCtx)
|
|
: myGlContext (new OpenGl_Context (theCaps)),
|
|
myOwnGContext (theGContext == 0),
|
|
myPlatformWindow (thePlatformWindow),
|
|
#if defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
|
myUIView (NULL),
|
|
#endif
|
|
mySwapInterval (theCaps->swapInterval)
|
|
{
|
|
(void )theDriver;
|
|
myPlatformWindow->Size (myWidth, myHeight);
|
|
|
|
#if defined(__APPLE__)
|
|
myWidthPt = myWidth;
|
|
myHeightPt = myHeight;
|
|
#endif
|
|
|
|
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
|
EAGLContext* aGLContext = theGContext;
|
|
if (aGLContext == NULL)
|
|
{
|
|
void* aViewPtr = (void* )myPlatformWindow->NativeHandle();
|
|
|
|
myUIView = (__bridge UIView* )aViewPtr;
|
|
CAEAGLLayer* anEaglLayer = (CAEAGLLayer* )myUIView.layer;
|
|
anEaglLayer.opaque = TRUE;
|
|
anEaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
[NSNumber numberWithBool: FALSE], kEAGLDrawablePropertyRetainedBacking,
|
|
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
|
|
NULL];
|
|
|
|
aGLContext = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES3];
|
|
if (aGLContext == NULL
|
|
|| ![EAGLContext setCurrentContext: aGLContext])
|
|
{
|
|
aGLContext = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
|
|
|
|
if (aGLContext == NULL
|
|
|| ![EAGLContext setCurrentContext: aGLContext])
|
|
{
|
|
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: EAGLContext creation failed");
|
|
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
|
|
return;
|
|
}
|
|
}
|
|
|
|
myGlContext->Init (aGLContext, Standard_False);
|
|
}
|
|
else
|
|
{
|
|
if (![EAGLContext setCurrentContext: aGLContext])
|
|
{
|
|
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: EAGLContext can not be assigned");
|
|
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
|
|
return;
|
|
}
|
|
|
|
myGlContext->Init (aGLContext, Standard_False);
|
|
}
|
|
#else
|
|
|
|
Cocoa_LocalPool aLocalPool;
|
|
|
|
// all GL context within one OpenGl_GraphicDriver should be shared!
|
|
NSOpenGLContext* aGLCtxShare = theShareCtx.IsNull() ? NULL : theShareCtx->myGContext;
|
|
NSOpenGLContext* aGLContext = theGContext;
|
|
bool isCore = false;
|
|
if (aGLContext == NULL)
|
|
{
|
|
NSOpenGLPixelFormatAttribute anAttribs[32] = {};
|
|
Standard_Integer aLastAttrib = 0;
|
|
//anAttribs[aLastAttrib++] = NSOpenGLPFAColorSize; anAttribs[aLastAttrib++] = 32,
|
|
anAttribs[aLastAttrib++] = NSOpenGLPFADepthSize; anAttribs[aLastAttrib++] = 24;
|
|
anAttribs[aLastAttrib++] = NSOpenGLPFAStencilSize; anAttribs[aLastAttrib++] = 8;
|
|
anAttribs[aLastAttrib++] = NSOpenGLPFADoubleBuffer;
|
|
if (theCaps->contextNoAccel)
|
|
{
|
|
anAttribs[aLastAttrib++] = NSOpenGLPFARendererID;
|
|
anAttribs[aLastAttrib++] = (NSOpenGLPixelFormatAttribute )kCGLRendererGenericFloatID;
|
|
}
|
|
else
|
|
{
|
|
anAttribs[aLastAttrib++] = NSOpenGLPFAAccelerated;
|
|
}
|
|
anAttribs[aLastAttrib] = 0;
|
|
const Standard_Integer aLastMainAttrib = aLastAttrib;
|
|
Standard_Integer aTryCore = 0;
|
|
Standard_Integer aTryStereo = 0;
|
|
for (aTryCore = 1; aTryCore >= 0; --aTryCore)
|
|
{
|
|
aLastAttrib = aLastMainAttrib;
|
|
if (aTryCore == 1)
|
|
{
|
|
if (theCaps->contextCompatible)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// supported since OS X 10.7+
|
|
anAttribs[aLastAttrib++] = 99; // NSOpenGLPFAOpenGLProfile
|
|
anAttribs[aLastAttrib++] = 0x3200; // NSOpenGLProfileVersion3_2Core
|
|
}
|
|
|
|
for (aTryStereo = 1; aTryStereo >= 0; --aTryStereo)
|
|
{
|
|
if (aTryStereo == 1)
|
|
{
|
|
if (!theCaps->contextStereo)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// deprecated since macOS 10.12 without replacement
|
|
Standard_DISABLE_DEPRECATION_WARNINGS
|
|
anAttribs[aLastAttrib++] = NSOpenGLPFAStereo;
|
|
Standard_ENABLE_DEPRECATION_WARNINGS
|
|
}
|
|
|
|
anAttribs[aLastAttrib] = 0;
|
|
|
|
NSOpenGLPixelFormat* aGLFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes: anAttribs] autorelease];
|
|
aGLContext = [[NSOpenGLContext alloc] initWithFormat: aGLFormat
|
|
shareContext: aGLCtxShare];
|
|
if (aGLContext != NULL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (aGLContext != NULL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (aGLContext == NULL)
|
|
{
|
|
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: NSOpenGLContext creation failed");
|
|
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
|
|
return;
|
|
}
|
|
|
|
if (aTryStereo == 0
|
|
&& theCaps->contextStereo)
|
|
{
|
|
TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: QuadBuffer is unavailable!");
|
|
myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
|
|
}
|
|
if (aTryCore == 0
|
|
&& !theCaps->contextCompatible)
|
|
{
|
|
TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
|
|
myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
|
|
}
|
|
|
|
NSView* aView = (NSView* )myPlatformWindow->NativeHandle();
|
|
[aGLContext setView: aView];
|
|
isCore = (aTryCore == 1);
|
|
}
|
|
|
|
myGlContext->Init (aGLContext, isCore);
|
|
#endif
|
|
|
|
myGlContext->Share (theShareCtx);
|
|
myGlContext->SetSwapInterval (mySwapInterval);
|
|
Init();
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : ~OpenGl_Window
|
|
// purpose :
|
|
// =======================================================================
|
|
OpenGl_Window::~OpenGl_Window()
|
|
{
|
|
if (!myOwnGContext
|
|
|| myGlContext.IsNull())
|
|
{
|
|
myGlContext.Nullify();
|
|
return;
|
|
}
|
|
|
|
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
|
myGlContext.Nullify();
|
|
[EAGLContext setCurrentContext: NULL];
|
|
myUIView = NULL;
|
|
#else
|
|
NSOpenGLContext* aGLCtx = myGlContext->myGContext;
|
|
myGlContext.Nullify();
|
|
|
|
[NSOpenGLContext clearCurrentContext];
|
|
[aGLCtx clearDrawable];
|
|
[aGLCtx release];
|
|
#endif
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : Resize
|
|
// purpose : call_subr_resize
|
|
// =======================================================================
|
|
void OpenGl_Window::Resize()
|
|
{
|
|
// If the size is not changed - do nothing
|
|
Standard_Integer aWidthPt = 0;
|
|
Standard_Integer aHeightPt = 0;
|
|
myPlatformWindow->Size (aWidthPt, aHeightPt);
|
|
if (myWidthPt == aWidthPt
|
|
&& myHeightPt == aHeightPt)
|
|
{
|
|
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
|
return;
|
|
#else
|
|
// check backing store change (moving to another screen)
|
|
NSOpenGLContext* aGLCtx = myGlContext->myGContext;
|
|
NSView* aView = [aGLCtx view];
|
|
if (![aView respondsToSelector: @selector(convertSizeToBacking:)])
|
|
{
|
|
return;
|
|
}
|
|
|
|
NSRect aBounds = [aView bounds];
|
|
NSSize aRes = [aView convertSizeToBacking: aBounds.size];
|
|
if (myWidth == Standard_Integer(aRes.width)
|
|
&& myHeight == Standard_Integer(aRes.height))
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
myWidthPt = aWidthPt;
|
|
myHeightPt = aHeightPt;
|
|
|
|
Init();
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : Init
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Window::Init()
|
|
{
|
|
if (!Activate())
|
|
{
|
|
return;
|
|
}
|
|
|
|
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
|
Handle(OpenGl_FrameBuffer) aDefFbo = myGlContext->SetDefaultFrameBuffer (NULL);
|
|
if (!aDefFbo.IsNull())
|
|
{
|
|
aDefFbo->Release (myGlContext.operator->());
|
|
}
|
|
else
|
|
{
|
|
aDefFbo = new OpenGl_FrameBuffer();
|
|
}
|
|
|
|
if (myOwnGContext)
|
|
{
|
|
EAGLContext* aGLCtx = myGlContext->myGContext;
|
|
CAEAGLLayer* anEaglLayer = (CAEAGLLayer* )myUIView.layer;
|
|
GLuint aWinRBColor = 0;
|
|
::glGenRenderbuffers (1, &aWinRBColor);
|
|
::glBindRenderbuffer (GL_RENDERBUFFER, aWinRBColor);
|
|
[aGLCtx renderbufferStorage: GL_RENDERBUFFER fromDrawable: anEaglLayer];
|
|
::glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &myWidth);
|
|
::glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &myHeight);
|
|
::glBindRenderbuffer (GL_RENDERBUFFER, 0);
|
|
|
|
if (!aDefFbo->InitWithRB (myGlContext, myWidth, myHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, aWinRBColor))
|
|
{
|
|
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
|
|
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!aDefFbo->InitWrapper (myGlContext))
|
|
{
|
|
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO wrapper creation failed");
|
|
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
|
|
return;
|
|
}
|
|
|
|
myWidth = aDefFbo->GetVPSizeX();
|
|
myHeight = aDefFbo->GetVPSizeY();
|
|
}
|
|
myGlContext->SetDefaultFrameBuffer (aDefFbo);
|
|
aDefFbo->BindBuffer (myGlContext);
|
|
aDefFbo.Nullify();
|
|
#else
|
|
NSOpenGLContext* aGLCtx = myGlContext->myGContext;
|
|
NSView* aView = [aGLCtx view];
|
|
NSRect aBounds = [aView bounds];
|
|
|
|
// we should call this method each time when window is resized
|
|
[aGLCtx update];
|
|
|
|
if ([aView respondsToSelector: @selector(convertSizeToBacking:)])
|
|
{
|
|
NSSize aRes = [aView convertSizeToBacking: aBounds.size];
|
|
myWidth = Standard_Integer(aRes.width);
|
|
myHeight = Standard_Integer(aRes.height);
|
|
}
|
|
else
|
|
{
|
|
myWidth = Standard_Integer(aBounds.size.width);
|
|
myHeight = Standard_Integer(aBounds.size.height);
|
|
}
|
|
myWidthPt = Standard_Integer(aBounds.size.width);
|
|
myHeightPt = Standard_Integer(aBounds.size.height);
|
|
#endif
|
|
|
|
::glDisable (GL_DITHER);
|
|
::glDisable (GL_SCISSOR_TEST);
|
|
::glViewport (0, 0, myWidth, myHeight);
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
::glDrawBuffer (GL_BACK);
|
|
if (myGlContext->core11 != NULL)
|
|
{
|
|
::glMatrixMode (GL_MODELVIEW);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : SetSwapInterval
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Window::SetSwapInterval (Standard_Boolean theToForceNoSync)
|
|
{
|
|
const Standard_Integer aSwapInterval = theToForceNoSync ? 0 : myGlContext->caps->swapInterval;
|
|
if (mySwapInterval != aSwapInterval)
|
|
{
|
|
mySwapInterval = aSwapInterval;
|
|
myGlContext->SetSwapInterval (mySwapInterval);
|
|
}
|
|
}
|
|
|
|
#endif // __APPLE__
|