// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-#ifdef HAVE_CONFIG_H
- #include <config.h>
-#endif
-
#include <OpenGl_GraphicDriver.hxx>
#include <OpenGl_Context.hxx>
#include <OpenGl_Flipper.hxx>
#include <OpenGl_Trihedron.hxx>
#include <OpenGl_Workspace.hxx>
+#include <Aspect_GraphicDeviceDefinitionError.hxx>
+#include <Message_Messenger.hxx>
#include <OSD_Environment.hxx>
#include <Standard_NotImplemented.hxx>
-#if (!defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)))
+#if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
#include <X11/Xlib.h> // XOpenDisplay()
#endif
+#if defined(HAVE_EGL) || defined(__ANDROID__)
+ #include <EGL/egl.h>
+#endif
+
IMPLEMENT_STANDARD_HANDLE(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
// function : OpenGl_GraphicDriver
// purpose :
// =======================================================================
-OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnection)& theDisp)
+OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnection)& theDisp,
+ const Standard_Boolean theToInitialize)
: Graphic3d_GraphicDriver (theDisp),
+ myIsOwnContext (Standard_False),
+#if defined(HAVE_EGL) || defined(__ANDROID__)
+ myEglDisplay ((Aspect_Display )EGL_NO_DISPLAY),
+ myEglContext ((Aspect_RenderingContext )EGL_NO_CONTEXT),
+ myEglConfig (NULL),
+#endif
myCaps (new OpenGl_Caps()),
myMapOfView (1, NCollection_BaseAllocator::CommonBaseAllocator()),
myMapOfWS (1, NCollection_BaseAllocator::CommonBaseAllocator()),
myUserDrawCallback (NULL),
myTempText (new OpenGl_Text())
{
-#if (!defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)))
+#if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
if (myDisplayConnection.IsNull())
{
//Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: cannot connect to X server!");
|| ::getenv ("CALL_SYNCHRO_X") != NULL;
XSynchronize (aDisplay, toSync);
+#if !defined(HAVE_EGL)
// does the server know about OpenGL & GLX?
int aDummy;
if (!XQueryExtension (aDisplay, "GLX", &aDummy, &aDummy, &aDummy))
{
- #ifdef DEBUG
- std::cerr << "This system doesn't appear to support OpenGL\n";
+ ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, this system doesn't appear to support OpenGL!", Message_Warning);
+ }
+#endif
+#endif
+ if (theToInitialize
+ && !InitContext())
+ {
+ Aspect_GraphicDeviceDefinitionError::Raise ("OpenGl_GraphicDriver: default context can not be initialized!");
+ }
+}
+
+// =======================================================================
+// function : ~OpenGl_GraphicDriver
+// purpose :
+// =======================================================================
+OpenGl_GraphicDriver::~OpenGl_GraphicDriver()
+{
+ ReleaseContext();
+}
+
+// =======================================================================
+// function : ReleaseContext
+// purpose :
+// =======================================================================
+void OpenGl_GraphicDriver::ReleaseContext()
+{
+ Handle(OpenGl_Context) aCtxShared;
+ for (NCollection_DataMap<Standard_Integer, Handle(OpenGl_Workspace)>::Iterator aWindowIter (myMapOfWS);
+ aWindowIter.More(); aWindowIter.Next())
+ {
+ const Handle(OpenGl_Workspace)& aWindow = aWindowIter.ChangeValue();
+ const Handle(OpenGl_Context)& aCtx = aWindow->GetGlContext();
+ if (aCtx->MakeCurrent()
+ && aCtxShared.IsNull())
+ {
+ aCtxShared = aCtx;
+ }
+ }
+
+ if (!aCtxShared.IsNull())
+ {
+ aCtxShared->MakeCurrent();
+ }
+ for (NCollection_DataMap<Standard_Integer, Handle(OpenGl_View)>::Iterator aViewIter (myMapOfView);
+ aViewIter.More(); aViewIter.Next())
+ {
+ const Handle(OpenGl_View)& aView = aViewIter.ChangeValue();
+ aView->ReleaseGlResources (aCtxShared);
+ }
+
+ for (NCollection_DataMap<Standard_Integer, OpenGl_Structure*>::Iterator aStructIt (myMapOfStructure);
+ aStructIt.More (); aStructIt.Next())
+ {
+ OpenGl_Structure* aStruct = aStructIt.ChangeValue();
+ aStruct->ReleaseGlResources (aCtxShared);
+ }
+ myTempText->Release (aCtxShared.operator->());
+ myDeviceLostFlag = myDeviceLostFlag || !myMapOfStructure.IsEmpty();
+
+ for (NCollection_DataMap<Standard_Integer, Handle(OpenGl_Workspace)>::Iterator aWindowIter (myMapOfWS);
+ aWindowIter.More(); aWindowIter.Next())
+ {
+ const Handle(OpenGl_Workspace)& aWindow = aWindowIter.ChangeValue();
+ const Handle(OpenGl_Context)& aCtx = aWindow->GetGlContext();
+ aCtx->forcedRelease();
+ }
+
+#if defined(HAVE_EGL) || defined(__ANDROID__)
+ if (myIsOwnContext)
+ {
+ if (myEglContext != (Aspect_RenderingContext )EGL_NO_CONTEXT)
+ {
+ if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)
+ {
+ ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, FAILED to release OpenGL context!", Message_Warning);
+ }
+ eglDestroyContext ((EGLDisplay )myEglDisplay, (EGLContext )myEglContext);
+ }
+
+ if (myEglDisplay != (Aspect_Display )EGL_NO_DISPLAY)
+ {
+ if (eglTerminate ((EGLDisplay )myEglDisplay) != EGL_TRUE)
+ {
+ ::Message::DefaultMessenger()->Send ("OpenGl_GraphicDriver, EGL, eglTerminate FAILED!", Message_Warning);
+ }
+ }
+ }
+
+ myEglDisplay = (Aspect_Display )EGL_NO_DISPLAY;
+ myEglContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
+ myEglConfig = NULL;
+#endif
+ myIsOwnContext = Standard_False;
+}
+
+// =======================================================================
+// function : InitContext
+// purpose :
+// =======================================================================
+Standard_Boolean OpenGl_GraphicDriver::InitContext()
+{
+ ReleaseContext();
+#if defined(HAVE_EGL) || defined(__ANDROID__)
+
+#if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
+ if (myDisplayConnection.IsNull())
+ {
+ return Standard_False;
+ }
+ Display* aDisplay = myDisplayConnection->GetDisplay();
+ myEglDisplay = (Aspect_Display )eglGetDisplay (aDisplay);
+#else
+ myEglDisplay = (Aspect_Display )eglGetDisplay (EGL_DEFAULT_DISPLAY);
+#endif
+ if ((EGLDisplay )myEglDisplay == EGL_NO_DISPLAY)
+ {
+ ::Message::DefaultMessenger()->Send ("Error: no EGL display!", Message_Fail);
+ return Standard_False;
+ }
+
+ EGLint aVerMajor = 0; EGLint aVerMinor = 0;
+ if (eglInitialize ((EGLDisplay )myEglDisplay, &aVerMajor, &aVerMinor) != EGL_TRUE)
+ {
+ ::Message::DefaultMessenger()->Send ("Error: EGL display is unavailable!", Message_Fail);
+ return Standard_False;
+ }
+
+ EGLint aConfigAttribs[] =
+ {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 24,
+ EGL_STENCIL_SIZE, 8,
+ #if defined(GL_ES_VERSION_2_0)
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ #else
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
#endif
+ EGL_NONE
+ };
+
+ EGLint aNbConfigs = 0;
+ if (eglChooseConfig ((EGLDisplay )myEglDisplay, aConfigAttribs, &myEglConfig, 1, &aNbConfigs) != EGL_TRUE
+ || myEglConfig == NULL)
+ {
+ eglGetError();
+ aConfigAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
+ if (eglChooseConfig ((EGLDisplay )myEglDisplay, aConfigAttribs, &myEglConfig, 1, &aNbConfigs) != EGL_TRUE
+ || myEglConfig == NULL)
+ {
+ ::Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
+ return Standard_False;
+ }
+ }
+
+#if defined(GL_ES_VERSION_2_0)
+ EGLint anEglCtxAttribs[] =
+ {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+ if (eglBindAPI (EGL_OPENGL_ES_API) != EGL_TRUE)
+ {
+ ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL ES client!", Message_Fail);
+ return Standard_False;
+ }
+#else
+ EGLint* anEglCtxAttribs = NULL;
+ if (eglBindAPI (EGL_OPENGL_API) != EGL_TRUE)
+ {
+ ::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL client!", Message_Fail);
+ return Standard_False;
}
#endif
+
+ myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
+ if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
+ {
+ ::Message::DefaultMessenger()->Send ("Error: EGL is unable to create OpenGL context!", Message_Fail);
+ return Standard_False;
+ }
+ if (eglMakeCurrent ((EGLDisplay )myEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, (EGLContext )myEglContext) != EGL_TRUE)
+ {
+ ::Message::DefaultMessenger()->Send ("Error: EGL is unable bind OpenGL context!", Message_Fail);
+ return Standard_False;
+ }
+#endif
+ myIsOwnContext = Standard_True;
+ return Standard_True;
+}
+
+#if defined(HAVE_EGL) || defined(__ANDROID__)
+// =======================================================================
+// function : InitEglContext
+// purpose :
+// =======================================================================
+Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display theEglDisplay,
+ Aspect_RenderingContext theEglContext,
+ void* theEglConfig)
+{
+ ReleaseContext();
+#if !defined(_WIN32) && !defined(__ANDROID__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
+ if (myDisplayConnection.IsNull())
+ {
+ return Standard_False;
+ }
+#endif
+
+ if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY
+ || (EGLContext )theEglContext == EGL_NO_CONTEXT
+ || theEglConfig == NULL)
+ {
+ return Standard_False;
+ }
+ myEglDisplay = theEglDisplay;
+ myEglContext = theEglContext;
+ myEglConfig = theEglConfig;
+ return Standard_True;
}
+#endif
// =======================================================================
// function : InquireLightLimit