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 ((EGLDisplay )myDisplay == EGL_NO_DISPLAY
|| (EGLSurface )myWindow == EGL_NO_SURFACE
|| (EGLContext )myGContext == EGL_NO_CONTEXT)
{
return Standard_False;
@@ -580,7 +579,6 @@ Standard_Boolean OpenGl_Context::MakeCurrent()
{
#if defined(HAVE_EGL)
if ((EGLDisplay )myDisplay == EGL_NO_DISPLAY
|| (EGLSurface )myWindow == EGL_NO_SURFACE
|| (EGLContext )myGContext == EGL_NO_CONTEXT)
{
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
{
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;
}
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)
myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
if (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[] =
@@ -384,14 +400,22 @@ Standard_Boolean OpenGl_GraphicDriver::InitEglContext (Aspect_Display t
#endif
if ((EGLDisplay )theEglDisplay == EGL_NO_DISPLAY
|| (EGLContext )theEglContext == EGL_NO_CONTEXT
|| theEglConfig == NULL)
|| (EGLContext )theEglContext == EGL_NO_CONTEXT)
{
return Standard_False;
}
myEglDisplay = theEglDisplay;
myEglContext = theEglContext;
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;
}
#endif

View File

@@ -18,6 +18,7 @@
#include <OpenGl_Context.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <OpenGl_Window.hxx>
#include <OpenGl_FrameBuffer.hxx>
#include <Aspect_GraphicDeviceDefinitionError.hxx>
#include <Graphic3d_TransformUtils.hxx>
@@ -181,14 +182,15 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
EGLConfig anEglConfig = (EGLConfig )theDriver->getRawGlConfig();
if (anEglDisplay == EGL_NO_DISPLAY
|| anEglContext == EGL_NO_CONTEXT
|| anEglConfig == NULL)
|| (anEglConfig == NULL
&& (EGLContext )theGContext == EGL_NO_CONTEXT))
{
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
return;
}
EGLSurface anEglSurf = EGL_NO_SURFACE;
if (theGContext == (EGLContext )EGL_NO_CONTEXT)
if ((EGLContext )theGContext == EGL_NO_CONTEXT)
{
// create new surface
anEglSurf = eglCreateWindowSurface (anEglDisplay,
@@ -211,8 +213,24 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
anEglSurf = eglGetCurrentSurface(EGL_DRAW);
if (anEglSurf == EGL_NO_SURFACE)
{
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
return;
// window-less EGL context (off-screen)
//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;
#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_HEIGHT, &myHeight);

View File

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

View File

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