1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0030364: Visualization, TKOpenGl - allow initializing a Surface-less EGL context

OpenGl_Context::MakeCurrent()/OpenGl_Context::IsCurrent() have been modified to NOT fail
in case if myWindow is EGL_NO_SURFACE (valid off-screen rendering case within EGL).
OpenGl_GraphicDriver::InitEglContext() now finds EGL surface config in case if it has not been passed by argument.

OpenGl_Window constructor now allows wrapping an off-screen rendering surface EGL_NO_SURFACE.
However, it still creates a dummy surface eglCreatePbufferSurface() to workaround bugs in some GLES drivers (Vivante GC2000).

V3d_View::SetWindow()/V3d_View::MustBeResized()/V3d_Viewer::SetViewOn() have been modified
to avoid implicit View redraw (leading to undefined behavior/crashes in case if rendering
should be done into default FBO defined right after V3d_View initialization).
This commit is contained in:
kgv
2018-11-12 15:46:40 +03:00
committed by san
parent 4473e33655
commit 39235bedc6
5 changed files with 112 additions and 40 deletions

View File

@@ -544,7 +544,6 @@ Standard_Boolean OpenGl_Context::IsCurrent() const
{ {
#if defined(HAVE_EGL) #if defined(HAVE_EGL)
if ((EGLDisplay )myDisplay == EGL_NO_DISPLAY if ((EGLDisplay )myDisplay == EGL_NO_DISPLAY
|| (EGLSurface )myWindow == EGL_NO_SURFACE
|| (EGLContext )myGContext == EGL_NO_CONTEXT) || (EGLContext )myGContext == EGL_NO_CONTEXT)
{ {
return Standard_False; return Standard_False;
@@ -580,7 +579,6 @@ Standard_Boolean OpenGl_Context::MakeCurrent()
{ {
#if defined(HAVE_EGL) #if defined(HAVE_EGL)
if ((EGLDisplay )myDisplay == EGL_NO_DISPLAY if ((EGLDisplay )myDisplay == EGL_NO_DISPLAY
|| (EGLSurface )myWindow == EGL_NO_SURFACE
|| (EGLContext )myGContext == EGL_NO_CONTEXT) || (EGLContext )myGContext == EGL_NO_CONTEXT)
{ {
Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!"); Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");

View File

@@ -55,6 +55,45 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
namespace namespace
{ {
static const Handle(OpenGl_Context) TheNullGlCtx; static const Handle(OpenGl_Context) TheNullGlCtx;
#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
//! Wrapper over eglChooseConfig() called with preferred defaults.
static EGLConfig chooseEglSurfConfig (EGLDisplay theDisplay)
{
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
};
EGLConfig aCfg = NULL;
EGLint aNbConfigs = 0;
if (eglChooseConfig (theDisplay, aConfigAttribs, &aCfg, 1, &aNbConfigs) == EGL_TRUE
|| aCfg != NULL)
{
return aCfg;
}
eglGetError();
aConfigAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
if (eglChooseConfig (theDisplay, aConfigAttribs, &aCfg, 1, &aNbConfigs) != EGL_TRUE
|| aCfg == NULL)
{
eglGetError();
}
return aCfg;
}
#endif
} }
// ======================================================================= // =======================================================================
@@ -299,35 +338,12 @@ Standard_Boolean OpenGl_GraphicDriver::InitContext()
return Standard_False; return Standard_False;
} }
EGLint aConfigAttribs[] = myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
{ if (myEglConfig == NULL)
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); ::Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
return Standard_False; return Standard_False;
} }
}
#if defined(GL_ES_VERSION_2_0) #if defined(GL_ES_VERSION_2_0)
EGLint anEglCtxAttribs[] = EGLint anEglCtxAttribs[] =
@@ -384,14 +400,22 @@ Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display t
#endif #endif
if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY
|| (EGLContext )theEglContext == EGL_NO_CONTEXT || (EGLContext )theEglContext == EGL_NO_CONTEXT)
|| theEglConfig == NULL)
{ {
return Standard_False; return Standard_False;
} }
myEglDisplay = theEglDisplay; myEglDisplay = theEglDisplay;
myEglContext = theEglContext; myEglContext = theEglContext;
myEglConfig = theEglConfig; myEglConfig = theEglConfig;
if (theEglConfig == NULL)
{
myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
if (myEglConfig == NULL)
{
::Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
return Standard_False;
}
}
return Standard_True; return Standard_True;
} }
#endif #endif

View File

@@ -18,6 +18,7 @@
#include <OpenGl_Context.hxx> #include <OpenGl_Context.hxx>
#include <OpenGl_GraphicDriver.hxx> #include <OpenGl_GraphicDriver.hxx>
#include <OpenGl_Window.hxx> #include <OpenGl_Window.hxx>
#include <OpenGl_FrameBuffer.hxx>
#include <Aspect_GraphicDeviceDefinitionError.hxx> #include <Aspect_GraphicDeviceDefinitionError.hxx>
#include <Graphic3d_TransformUtils.hxx> #include <Graphic3d_TransformUtils.hxx>
@@ -181,14 +182,15 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
EGLConfig anEglConfig = (EGLConfig )theDriver->getRawGlConfig(); EGLConfig anEglConfig = (EGLConfig )theDriver->getRawGlConfig();
if (anEglDisplay == EGL_NO_DISPLAY if (anEglDisplay == EGL_NO_DISPLAY
|| anEglContext == EGL_NO_CONTEXT || anEglContext == EGL_NO_CONTEXT
|| anEglConfig == NULL) || (anEglConfig == NULL
&& (EGLContext )theGContext == EGL_NO_CONTEXT))
{ {
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!"); throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
return; return;
} }
EGLSurface anEglSurf = EGL_NO_SURFACE; EGLSurface anEglSurf = EGL_NO_SURFACE;
if (theGContext == (EGLContext )EGL_NO_CONTEXT) if ((EGLContext )theGContext == EGL_NO_CONTEXT)
{ {
// create new surface // create new surface
anEglSurf = eglCreateWindowSurface (anEglDisplay, anEglSurf = eglCreateWindowSurface (anEglDisplay,
@@ -211,8 +213,24 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
anEglSurf = eglGetCurrentSurface(EGL_DRAW); anEglSurf = eglGetCurrentSurface(EGL_DRAW);
if (anEglSurf == EGL_NO_SURFACE) if (anEglSurf == EGL_NO_SURFACE)
{ {
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!"); // window-less EGL context (off-screen)
return; //throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
if (anEglConfig != NULL)
{
const int aSurfAttribs[] =
{
EGL_WIDTH, myWidth,
EGL_HEIGHT, myHeight,
EGL_NONE
};
anEglSurf = eglCreatePbufferSurface (anEglDisplay, anEglConfig, aSurfAttribs);
if (anEglSurf == EGL_NO_SURFACE)
{
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
}
}
myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
"OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
} }
} }
@@ -715,7 +733,30 @@ void OpenGl_Window::Init()
return; return;
#if defined(HAVE_EGL) #if defined(HAVE_EGL)
if (!myPlatformWindow->IsVirtual()) if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE)
{
// define an offscreen default FBO to avoid rendering into EGL_NO_SURFACE;
// note that this code is currently never called, since eglCreatePbufferSurface() is used instead as more robust solution
// for offscreen rendering on bugged OpenGL ES drivers
Handle(OpenGl_FrameBuffer) aDefFbo = myGlContext->SetDefaultFrameBuffer (Handle(OpenGl_FrameBuffer)());
if (!aDefFbo.IsNull())
{
aDefFbo->Release (myGlContext.operator->());
}
else
{
aDefFbo = new OpenGl_FrameBuffer();
}
if (!aDefFbo->InitWithRB (myGlContext, myWidth, myHeight, GL_RGBA8, GL_DEPTH24_STENCIL8))
{
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
}
myGlContext->SetDefaultFrameBuffer (aDefFbo);
aDefFbo->BindBuffer (myGlContext);
}
else if (!myPlatformWindow->IsVirtual())
{ {
eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &myWidth); eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &myWidth);
eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight); eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);

View File

@@ -189,8 +189,11 @@ void V3d_View::SetWindow (const Handle(Aspect_Window)& theWindow,
myView->SetWindow (theWindow, theContext); myView->SetWindow (theWindow, theContext);
MyViewer->SetViewOn (this); MyViewer->SetViewOn (this);
SetRatio(); SetRatio();
if (myImmediateUpdate)
{
Redraw(); Redraw();
} }
}
//============================================================================= //=============================================================================
//function : Remove //function : Remove
@@ -412,9 +415,11 @@ void V3d_View::MustBeResized()
myView->Resized(); myView->Resized();
SetRatio(); SetRatio();
if (myImmediateUpdate)
{
Redraw(); Redraw();
} }
}
//============================================================================= //=============================================================================
//function : SetBackgroundColor //function : SetBackgroundColor

View File

@@ -152,7 +152,11 @@ void V3d_Viewer::SetViewOn (const Handle(V3d_View)& theView)
theView->SetGrid (myPrivilegedPlane, Grid ()); theView->SetGrid (myPrivilegedPlane, Grid ());
theView->SetGridActivity (Grid ()->IsActive ()); theView->SetGridActivity (Grid ()->IsActive ());
if (theView->SetImmediateUpdate (Standard_False))
{
theView->Redraw(); theView->Redraw();
theView->SetImmediateUpdate (Standard_True);
}
} }
// ======================================================================== // ========================================================================