0029138: Visualization - D3DHost_FrameBuffer should provide software fallback when...
authorkgv <kgv@opencascade.com>
Mon, 25 Sep 2017 12:54:45 +0000 (15:54 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 6 Oct 2017 07:28:04 +0000 (10:28 +0300)
D3DHost_FrameBuffer now provides fallback code copying OpenGL FBO content into D3D surface (slow).
OpenGl_FrameBuffer::BufferDump() - FBO dump implementation has been moved from OpenGl_Workspace::BufferDump().

13 files changed:
adm/genconf.tcl
src/D3DHost/D3DHost_FrameBuffer.cxx
src/D3DHost/D3DHost_FrameBuffer.hxx
src/D3DHost/D3DHost_GraphicDriver.cxx
src/D3DHost/D3DHost_View.cxx
src/D3DHost/D3DHost_View.hxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_FrameBuffer.cxx
src/OpenGl/OpenGl_FrameBuffer.hxx
src/OpenGl/OpenGl_GlFunctions.hxx
src/OpenGl/OpenGl_View_Redraw.cxx
src/OpenGl/OpenGl_Window.cxx
src/OpenGl/OpenGl_Workspace.cxx

index f7717ec..be4d747 100644 (file)
@@ -142,9 +142,6 @@ proc wokdep:gui:UpdateList {} {
     if { "$::HAVE_GL2PS" == "true" } {
       lappend anIncErrs "Error: gl2ps can not be used with OpenGL ES"
     }
-    if { "$::HAVE_D3D" == "true" } {
-      lappend anIncErrs "Error: Direct3D can not be used with OpenGL ES"
-    }
     wokdep:SearchEGL     anIncErrs anLib32Errs anLib64Errs anBin32Errs anBin64Errs
     wokdep:SearchGLES    anIncErrs anLib32Errs anLib64Errs anBin32Errs anBin64Errs
   }
index b6dfeb0..6dd55a9 100644 (file)
@@ -33,7 +33,8 @@ D3DHost_FrameBuffer::D3DHost_FrameBuffer()
   myD3dSurfShare (NULL),
   myGlD3dDevice  (NULL),
   myGlD3dSurf    (NULL),
-  myLockCount    (0)
+  myLockCount    (0),
+  myD3dFallback  (Standard_False)
 {
   //
 }
@@ -96,6 +97,50 @@ Standard_Boolean D3DHost_FrameBuffer::Init (const Handle(OpenGl_Context)& theCtx
                                             const Standard_Integer        theSizeX,
                                             const Standard_Integer        theSizeY)
 {
+  if (InitD3dInterop (theCtx, theD3DDevice, theIsD3dEx, theSizeX, theSizeY))
+  {
+    return Standard_True;
+  }
+  return InitD3dFallback (theCtx, theD3DDevice, theIsD3dEx, theSizeX, theSizeY);
+}
+
+// =======================================================================
+// function : InitD3dFallback
+// purpose  :
+// =======================================================================
+Standard_Boolean D3DHost_FrameBuffer::InitD3dFallback (const Handle(OpenGl_Context)& theCtx,
+                                                       IDirect3DDevice9*             theD3DDevice,
+                                                       const Standard_Boolean        theIsD3dEx,
+                                                       const Standard_Integer        theSizeX,
+                                                       const Standard_Integer        theSizeY)
+{
+  const Standard_Boolean isGlInit = Init (theCtx, theSizeX, theSizeY, GL_RGBA8, GL_DEPTH24_STENCIL8, 0);
+  myD3dFallback = Standard_True;
+
+  const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
+  const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
+  if (theD3DDevice->CreateRenderTarget (aSizeX, aSizeY,
+                                        D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, theIsD3dEx ? TRUE : FALSE,
+                                        &myD3dSurf, theIsD3dEx ? &myD3dSurfShare : NULL) != D3D_OK)
+  {
+    Release (theCtx.operator->());
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                         TCollection_AsciiString ("D3DHost_FrameBuffer, could not D3DFMT_X8R8G8B8 render target ") + aSizeX + "x" + aSizeY);
+    return Standard_False;
+  }
+  return isGlInit;
+}
+
+// =======================================================================
+// function : InitD3dInterop
+// purpose  :
+// =======================================================================
+Standard_Boolean D3DHost_FrameBuffer::InitD3dInterop (const Handle(OpenGl_Context)& theCtx,
+                                                      IDirect3DDevice9*             theD3DDevice,
+                                                      const Standard_Boolean        theIsD3dEx,
+                                                      const Standard_Integer        theSizeX,
+                                                      const Standard_Integer        theSizeY)
+{
   Release (theCtx.operator->());
 #if !defined(GL_ES_VERSION_2_0)
   myVPSizeX = theSizeX;
@@ -108,10 +153,8 @@ Standard_Boolean D3DHost_FrameBuffer::Init (const Handle(OpenGl_Context)& theCtx
   const OpenGl_GlFunctions* aFuncs = theCtx->Functions();
   if (aFuncs->wglDXOpenDeviceNV == NULL)
   {
-    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                         GL_DEBUG_TYPE_ERROR_ARB,
-                         0,
-                         GL_DEBUG_SEVERITY_HIGH_ARB,
+    Release (theCtx.operator->());
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
                          "D3DHost_FrameBuffer, WGL_NV_DX_interop is unavailable!");
     return Standard_False;
   }
@@ -156,6 +199,7 @@ Standard_Boolean D3DHost_FrameBuffer::Init (const Handle(OpenGl_Context)& theCtx
     return Standard_False;
   }
 
+  myD3dFallback = Standard_False;
   return Standard_True;
 #else
   (void )theD3DDevice;
@@ -203,7 +247,6 @@ Standard_Boolean D3DHost_FrameBuffer::registerD3dBuffer (const Handle(OpenGl_Con
                                                myColorTextures (0)->TextureId(),
                                                GL_TEXTURE_2D,
                                                WGL_ACCESS_WRITE_DISCARD_NV);
-
   if (myGlD3dSurf == NULL)
   {
     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
@@ -222,8 +265,17 @@ Standard_Boolean D3DHost_FrameBuffer::registerD3dBuffer (const Handle(OpenGl_Con
 void D3DHost_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theCtx)
 {
   Standard_ProgramError_Raise_if (myLockCount < 1, "D3DHost_FrameBuffer::BindBuffer(), resource should be locked beforehand!");
+  if (theCtx->arbFBO == NULL)
+  {
+    return;
+  }
 
   OpenGl_FrameBuffer::BindBuffer (theCtx);
+  if (myD3dFallback)
+  {
+    return;
+  }
+
   theCtx->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                           myColorTextures (0)->GetTarget(), myColorTextures (0)->TextureId(), 0);
 #ifdef GL_DEPTH_STENCIL_ATTACHMENT
@@ -280,6 +332,42 @@ void D3DHost_FrameBuffer::UnlockSurface (const Handle(OpenGl_Context)& theCtx)
   {
     return;
   }
+
+  if (myD3dFallback)
+  {
+    if (myD3dSurf == NULL)
+    {
+      return;
+    }
+
+    D3DLOCKED_RECT aLockedRect;
+    if (myD3dSurf->LockRect (&aLockedRect, NULL, 0) != 0)
+    {
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                           "D3DHost_FrameBuffer::UnlockSurface(), lock failed!");
+      return;
+    }
+
+    Image_PixMap anImg;
+    if (anImg.InitWrapper (Image_Format_BGRA, (Standard_Byte* )aLockedRect.pBits, myInitVPSizeX, myInitVPSizeY, aLockedRect.Pitch))
+    {
+      anImg.SetTopDown (!IsValid()); // flip in software if OpenGL FBO is unavailable
+      myLockCount = 1;
+      if (!BufferDump (theCtx, this, anImg, Graphic3d_BT_RGBA))
+      {
+        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                             "D3DHost_FrameBuffer::UnlockSurface(), buffer dump failed!");
+      }
+      myLockCount = 0;
+    }
+    else
+    {
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                           "D3DHost_FrameBuffer::UnlockSurface(), buffer dump failed!");
+    }
+    myD3dSurf->UnlockRect();
+    return;
+  }
   if (myGlD3dSurf == NULL)
   {
     return;
index e3c9338..ecfabc1 100644 (file)
@@ -35,13 +35,27 @@ public:
   //! Releases D3D and OpenGL resources.
   Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE;
 
-  //! Initializes OpenGL FBO for Direct3D interoperability.
+  //! Initializes OpenGL FBO for Direct3D interoperability or in fallback mode.
   Standard_EXPORT Standard_Boolean Init (const Handle(OpenGl_Context)& theCtx,
                                          IDirect3DDevice9*             theD3DDevice,
                                          const Standard_Boolean        theIsD3dEx,
                                          const Standard_Integer        theSizeX,
                                          const Standard_Integer        theSizeY);
 
+  //! Initializes OpenGL FBO for Direct3D interoperability.
+  Standard_EXPORT Standard_Boolean InitD3dInterop (const Handle(OpenGl_Context)& theCtx,
+                                                   IDirect3DDevice9*             theD3DDevice,
+                                                   const Standard_Boolean        theIsD3dEx,
+                                                   const Standard_Integer        theSizeX,
+                                                   const Standard_Integer        theSizeY);
+
+  //! Initializes OpenGL FBO + Direct3D surface for copying memory using fallback.
+  Standard_EXPORT Standard_Boolean InitD3dFallback (const Handle(OpenGl_Context)& theCtx,
+                                                    IDirect3DDevice9*             theD3DDevice,
+                                                    const Standard_Boolean        theIsD3dEx,
+                                                    const Standard_Integer        theSizeX,
+                                                    const Standard_Integer        theSizeY);
+
   //! Binds Direct3D color buffer to OpenGL texture.
   Standard_EXPORT Standard_Boolean registerD3dBuffer (const Handle(OpenGl_Context)& theCtx);
 
@@ -58,9 +72,12 @@ public:
   //! Returns D3D surface used as color buffer.
   IDirect3DSurface9* D3dColorSurface()      { return myD3dSurf; }
 
-  //! Returns WDDM hande for D3D color surface.
+  //! Returns WDDM handle for D3D color surface.
   void*              D3dColorSurfaceShare() { return myD3dSurfShare; }
 
+  //! Returns TRUE if FBO has been initialized without WGL/D3D interop.
+  Standard_Boolean   D3dFallback() const { return myD3dFallback; }
+
 protected:
 
   using OpenGl_FrameBuffer::Init;
@@ -72,6 +89,7 @@ protected:
   void*              myGlD3dDevice;  //!< WGL/D3D device  handle
   void*              myGlD3dSurf;    //!< WGL/D3D surface handle
   Standard_Integer   myLockCount;    //!< locking counter
+  Standard_Boolean   myD3dFallback;  //!< indicates that FBO has been initialized without WGL/D3D interop
 
 public:
 
index 76a8789..6483e70 100644 (file)
@@ -29,7 +29,7 @@ IMPLEMENT_STANDARD_RTTIEXT(D3DHost_GraphicDriver,OpenGl_GraphicDriver)
 // purpose  :
 // =======================================================================
 D3DHost_GraphicDriver::D3DHost_GraphicDriver()
-: OpenGl_GraphicDriver (Handle(Aspect_DisplayConnection)(), Standard_False)
+: OpenGl_GraphicDriver (Handle(Aspect_DisplayConnection)(), Standard_True)
 {
   //
 }
index e92d424..f540526 100644 (file)
@@ -93,6 +93,15 @@ D3DHost_View::~D3DHost_View()
 }
 
 // =======================================================================
+// function : D3dColorSurface
+// purpose  :
+// =======================================================================
+IDirect3DSurface9* D3DHost_View::D3dColorSurface() const
+{
+  return myD3dWglFbo->D3dColorSurface();
+}
+
+// =======================================================================
 // function : SetWindow
 // purpose  :
 // =======================================================================
@@ -158,11 +167,7 @@ bool D3DHost_View::d3dInit()
 {
   if (!d3dInitLib())
   {
-    myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                                              GL_DEBUG_TYPE_ERROR_ARB,
-                                              0,
-                                              GL_DEBUG_SEVERITY_HIGH_ARB,
-                                              "Direct3DCreate9 failed!");
+    myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Direct3DCreate9 failed!");
     return false;
   }
 
@@ -221,17 +226,34 @@ bool D3DHost_View::d3dReset()
 // =======================================================================
 bool D3DHost_View::d3dCreateRenderTarget()
 {
+  bool toD3dFallback = false;
   if (myD3dWglFbo.IsNull())
   {
     myD3dWglFbo = new D3DHost_FrameBuffer();
   }
-  if (!myD3dWglFbo->Init (myWorkspace->GetGlContext(),
-                          myD3dDevice,
-                          myIsD3dEx,
-                          myWindow->Width(),
-                          myWindow->Height()))
+  else
   {
-    return false;
+    toD3dFallback = myD3dWglFbo->D3dFallback();
+  }
+
+  if (!toD3dFallback)
+  {
+    toD3dFallback = !myD3dWglFbo->InitD3dInterop (myWorkspace->GetGlContext(),
+                                                  myD3dDevice,
+                                                  myIsD3dEx,
+                                                  myWindow->Width(),
+                                                  myWindow->Height());
+  }
+  if (toD3dFallback)
+  {
+    if (!myD3dWglFbo->InitD3dFallback (myWorkspace->GetGlContext(),
+                                       myD3dDevice,
+                                       myIsD3dEx,
+                                       myWindow->Width(),
+                                       myWindow->Height()))
+    {
+      return false;
+    }
   }
 
   myD3dDevice->SetRenderTarget (0, myD3dWglFbo->D3dColorSurface());
@@ -280,13 +302,8 @@ bool D3DHost_View::d3dSwap()
   const HRESULT isOK = myD3dDevice->Present (NULL, NULL, NULL, NULL);
   if (isOK != D3D_OK)
   {
-    TCollection_ExtendedString aMsg = TCollection_ExtendedString()
-      + "Direct3D9, Present device failed, " + d3dFormatError (isOK);
-    myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                                              GL_DEBUG_TYPE_ERROR_ARB,
-                                              0,
-                                              GL_DEBUG_SEVERITY_HIGH_ARB,
-                                              aMsg);
+    myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                                              TCollection_AsciiString("Direct3D9, Present device failed, ") + d3dFormatError (isOK));
   }
   return isOK == D3D_OK;
 }
@@ -309,9 +326,32 @@ void D3DHost_View::Redraw()
   }
 
   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
-  myToFlipOutput = Standard_True;
+  if (myWindow->PlatformWindow()->IsVirtual()
+  &&  aCtx->arbFBO == NULL)
+  {
+    // do a dirty hack in extreme fallback mode with OpenGL driver not supporting FBO,
+    // the back buffer of hidden window is used for rendering as offscreen buffer
+    myTransientDrawToFront = false;
+    int aWinSizeX = 0, aWinSizeY = 0;
+    myWindow->PlatformWindow()->Size (aWinSizeX, aWinSizeY);
+    WINDOWPLACEMENT aPlace;
+    GetWindowPlacement ((HWND )myWindow->PlatformWindow()->NativeHandle(), &aPlace);
+    if (aPlace.rcNormalPosition.right  - aPlace.rcNormalPosition.left != aWinSizeX
+     || aPlace.rcNormalPosition.bottom - aPlace.rcNormalPosition.top  != aWinSizeY)
+    {
+      aPlace.rcNormalPosition.right  = aPlace.rcNormalPosition.left + aWinSizeX;
+      aPlace.rcNormalPosition.bottom = aPlace.rcNormalPosition.top  + aWinSizeY;
+      aPlace.showCmd = SW_HIDE;
+      SetWindowPlacement ((HWND )myWindow->PlatformWindow()->NativeHandle(), &aPlace);
+    }
+  }
+
   myD3dWglFbo->LockSurface   (aCtx);
-  myFBO = myD3dWglFbo;
+  if (myD3dWglFbo->IsValid())
+  {
+    myToFlipOutput = Standard_True;
+    myFBO = myD3dWglFbo;
+  }
   OpenGl_View::Redraw();
   myFBO.Nullify();
   myD3dWglFbo->UnlockSurface (aCtx);
@@ -358,9 +398,12 @@ void D3DHost_View::RedrawImmediate()
     return;
   }
 
-  myToFlipOutput = Standard_True;
   myD3dWglFbo->LockSurface   (aCtx);
-  myFBO = myD3dWglFbo;
+  if (myD3dWglFbo->IsValid())
+  {
+    myToFlipOutput = Standard_True;
+    myFBO = myD3dWglFbo;
+  }
   OpenGl_View::RedrawImmediate();
   myFBO.Nullify();
   myD3dWglFbo->UnlockSurface (aCtx);
index 8a7ac76..47b4bb1 100644 (file)
@@ -70,7 +70,7 @@ public:
   const Handle(D3DHost_FrameBuffer)& D3dWglBuffer() const { return myD3dWglFbo; }
 
   //! Return D3D surface.
-  IDirect3DSurface9* D3dColorSurface() const { return myD3dWglFbo->D3dColorSurface(); }
+  Standard_EXPORT IDirect3DSurface9* D3dColorSurface() const;
 
 protected:
 
index 790be6e..525fbc6 100644 (file)
@@ -2776,12 +2776,12 @@ void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString
   if ((theFlags & Graphic3d_DiagnosticInfo_NativePlatform) != 0)
   {
   #if defined(HAVE_EGL)
-    addInfo (theDict, "EGLVersion",    ::eglQueryString ((Aspect_Display)myDisplay, EGL_VERSION));
-    addInfo (theDict, "EGLVendor",     ::eglQueryString ((Aspect_Display)myDisplay, EGL_VENDOR));
-    addInfo (theDict, "EGLClientAPIs", ::eglQueryString ((Aspect_Display)myDisplay, EGL_CLIENT_APIS));
+    addInfo (theDict, "EGLVersion",    ::eglQueryString ((EGLDisplay )myDisplay, EGL_VERSION));
+    addInfo (theDict, "EGLVendor",     ::eglQueryString ((EGLDisplay )myDisplay, EGL_VENDOR));
+    addInfo (theDict, "EGLClientAPIs", ::eglQueryString ((EGLDisplay )myDisplay, EGL_CLIENT_APIS));
     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
     {
-      addInfo (theDict, "EGLExtensions", ::eglQueryString ((Aspect_Display)myDisplay, EGL_EXTENSIONS));
+      addInfo (theDict, "EGLExtensions", ::eglQueryString ((EGLDisplay )myDisplay, EGL_EXTENSIONS));
     }
   #elif defined(_WIN32)
     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0
index f58dd92..4be39d9 100644 (file)
@@ -15,6 +15,7 @@
 #include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_ArbFBO.hxx>
 
+#include <NCollection_AlignedAllocator.hxx>
 #include <Standard_Assert.hxx>
 #include <TCollection_ExtendedString.hxx>
 
@@ -818,3 +819,240 @@ void OpenGl_FrameBuffer::UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx)
     theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, NO_FRAMEBUFFER);
   }
 }
+
+// =======================================================================
+// function : getAligned
+// purpose  :
+// =======================================================================
+inline Standard_Size getAligned (const Standard_Size theNumber,
+                                 const Standard_Size theAlignment)
+{
+  return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
+}
+
+template<typename T>
+inline void convertRowFromRgba (T* theRgbRow,
+                                const Image_ColorRGBA* theRgbaRow,
+                                const Standard_Size theWidth)
+{
+  for (Standard_Size aCol = 0; aCol < theWidth; ++aCol)
+  {
+    const Image_ColorRGBA& anRgba = theRgbaRow[aCol];
+    T& anRgb = theRgbRow[aCol];
+    anRgb.r() = anRgba.r();
+    anRgb.g() = anRgba.g();
+    anRgb.b() = anRgba.b();
+  }
+}
+
+// =======================================================================
+// function : BufferDump
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& theGlCtx,
+                                                 const Handle(OpenGl_FrameBuffer)& theFbo,
+                                                 Image_PixMap& theImage,
+                                                 Graphic3d_BufferType theBufferType)
+{
+  if (theGlCtx.IsNull()
+   || theImage.IsEmpty())
+  {
+    return Standard_False;
+  }
+
+  GLenum aFormat = 0;
+  GLenum aType   = 0;
+  bool toSwapRgbaBgra = false;
+  bool toConvRgba2Rgb = false;
+  switch (theImage.Format())
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    case Image_Format_Gray:
+      aFormat = GL_DEPTH_COMPONENT;
+      aType   = GL_UNSIGNED_BYTE;
+      break;
+    case Image_Format_GrayF:
+      aFormat = GL_DEPTH_COMPONENT;
+      aType   = GL_FLOAT;
+      break;
+    case Image_Format_RGB:
+      aFormat = GL_RGB;
+      aType   = GL_UNSIGNED_BYTE;
+      break;
+    case Image_Format_BGR:
+      aFormat = GL_BGR;
+      aType   = GL_UNSIGNED_BYTE;
+      break;
+    case Image_Format_BGRA:
+    case Image_Format_BGR32:
+      aFormat = GL_BGRA;
+      aType   = GL_UNSIGNED_BYTE;
+      break;
+    case Image_Format_BGRF:
+      aFormat = GL_BGR;
+      aType   = GL_FLOAT;
+      break;
+    case Image_Format_BGRAF:
+      aFormat = GL_BGRA;
+      aType   = GL_FLOAT;
+      break;
+  #else
+    case Image_Format_Gray:
+    case Image_Format_GrayF:
+    case Image_Format_BGRF:
+    case Image_Format_BGRAF:
+      return Standard_False;
+    case Image_Format_BGRA:
+    case Image_Format_BGR32:
+      aFormat = GL_RGBA;
+      aType   = GL_UNSIGNED_BYTE;
+      toSwapRgbaBgra = true;
+      break;
+    case Image_Format_BGR:
+    case Image_Format_RGB:
+      aFormat = GL_RGBA;
+      aType   = GL_UNSIGNED_BYTE;
+      toConvRgba2Rgb = true;
+      break;
+  #endif
+    case Image_Format_RGBA:
+    case Image_Format_RGB32:
+      aFormat = GL_RGBA;
+      aType   = GL_UNSIGNED_BYTE;
+      break;
+    case Image_Format_RGBF:
+      aFormat = GL_RGB;
+      aType   = GL_FLOAT;
+      break;
+    case Image_Format_RGBAF:
+      aFormat = GL_RGBA;
+      aType   = GL_FLOAT;
+      break;
+    case Image_Format_Alpha:
+    case Image_Format_AlphaF:
+      return Standard_False; // GL_ALPHA is no more supported in core context
+    case Image_Format_UNKNOWN:
+      return Standard_False;
+  }
+
+  if (aFormat == 0)
+  {
+    return Standard_False;
+  }
+
+#if !defined(GL_ES_VERSION_2_0)
+  GLint aReadBufferPrev = GL_BACK;
+  if (theBufferType == Graphic3d_BT_Depth
+   && aFormat != GL_DEPTH_COMPONENT)
+  {
+    return Standard_False;
+  }
+#else
+  (void )theBufferType;
+#endif
+
+  // bind FBO if used
+  if (!theFbo.IsNull() && theFbo->IsValid())
+  {
+    theFbo->BindBuffer (theGlCtx);
+  }
+  else
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
+    GLint aDrawBufferPrev = GL_BACK;
+    glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
+    glReadBuffer (aDrawBufferPrev);
+  #endif
+  }
+
+  // setup alignment
+  const GLint anAligment   = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
+  glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
+  bool isBatchCopy = !theImage.IsTopDown();
+
+  const GLint   anExtraBytes       = GLint(theImage.RowExtraBytes());
+  GLint         aPixelsWidth       = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
+  Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
+  if (anExtraBytes < anAligment)
+  {
+    aPixelsWidth = 0;
+  }
+  else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
+  {
+    aPixelsWidth = 0;
+    isBatchCopy  = false;
+  }
+#if !defined(GL_ES_VERSION_2_0)
+  glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
+#else
+  if (aPixelsWidth != 0)
+  {
+    isBatchCopy = false;
+  }
+#endif
+  if (toConvRgba2Rgb)
+  {
+    Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
+    const Standard_Size aRowSize = theImage.SizeX() * 4;
+    NCollection_Buffer aRowBuffer (anAlloc);
+    if (!aRowBuffer.Allocate (aRowSize))
+    {
+      return Standard_False;
+    }
+
+    for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
+    {
+      // Image_PixMap rows indexation always starts from the upper corner
+      // while order in memory depends on the flag and processed by ChangeRow() method
+      glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, aRowBuffer.ChangeData());
+      const Image_ColorRGBA* aRowDataRgba = (const Image_ColorRGBA* )aRowBuffer.Data();
+      if (theImage.Format() == Image_Format_BGR)
+      {
+        convertRowFromRgba ((Image_ColorBGR* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
+      }
+      else
+      {
+        convertRowFromRgba ((Image_ColorRGB* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
+      }
+    }
+  }
+  else if (!isBatchCopy)
+  {
+    // copy row by row
+    for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
+    {
+      // Image_PixMap rows indexation always starts from the upper corner
+      // while order in memory depends on the flag and processed by ChangeRow() method
+      glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
+    }
+  }
+  else
+  {
+    glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
+  }
+  const bool hasErrors = theGlCtx->ResetErrors (true);
+
+  glPixelStorei (GL_PACK_ALIGNMENT,  1);
+#if !defined(GL_ES_VERSION_2_0)
+  glPixelStorei (GL_PACK_ROW_LENGTH, 0);
+#endif
+
+  if (!theFbo.IsNull() && theFbo->IsValid())
+  {
+    theFbo->UnbindBuffer (theGlCtx);
+  }
+  else
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    glReadBuffer (aReadBufferPrev);
+  #endif
+  }
+
+  if (toSwapRgbaBgra)
+  {
+    Image_PixMap::SwapRgbaBgra (theImage);
+  }
+
+  return !hasErrors;
+}
index 9d6ead1..9e01ab9 100644 (file)
@@ -19,6 +19,7 @@
 #include <OpenGl_Resource.hxx>
 #include <OpenGl_Texture.hxx>
 
+#include <Graphic3d_BufferType.hxx>
 #include <NCollection_Vector.hxx>
 
 class OpenGl_FrameBuffer;
@@ -40,6 +41,19 @@ public:
 
 public:
 
+  //! Dump content into image.
+  //! @param theGlCtx      bound OpenGL context
+  //! @param theFbo        FBO to dump (or window buffer, if NULL)
+  //! @param theImage      target image
+  //! @param theBufferType buffer type (attachment) to dump
+  //! @return TRUE on success
+  Standard_EXPORT static Standard_Boolean BufferDump (const Handle(OpenGl_Context)& theGlCtx,
+                                                      const Handle(OpenGl_FrameBuffer)& theFbo,
+                                                      Image_PixMap& theImage,
+                                                      Graphic3d_BufferType theBufferType);
+
+public:
+
   //! Empty constructor
   Standard_EXPORT OpenGl_FrameBuffer();
 
index 686bbf4..3f00bb1 100644 (file)
@@ -771,53 +771,53 @@ public: //! @name OpenGL ES 2.0
 
 public: //! @name OpenGL ES 3.0
 
-  typedef void (*glBlitFramebuffer_t)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+  typedef void (APIENTRY *glBlitFramebuffer_t)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
   glBlitFramebuffer_t glBlitFramebuffer;
 
-  typedef void (*glTexImage3D_t)(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* data);
+  typedef void (APIENTRY *glTexImage3D_t)(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* data);
   glTexImage3D_t glTexImage3D;
 
-  typedef void (*glDrawBuffers_t)(GLsizei n, const GLenum* bufs);
+  typedef void (APIENTRY *glDrawBuffers_t)(GLsizei n, const GLenum* bufs);
   glDrawBuffers_t glDrawBuffers;
 
-  typedef void (*glGenSamplers_t)(GLsizei count, GLuint* samplers);
+  typedef void (APIENTRY *glGenSamplers_t)(GLsizei count, GLuint* samplers);
   glGenSamplers_t glGenSamplers;
 
-  typedef void (*glDeleteSamplers_t)(GLsizei count, const GLuint* samplers);
+  typedef void (APIENTRY *glDeleteSamplers_t)(GLsizei count, const GLuint* samplers);
   glDeleteSamplers_t glDeleteSamplers;
 
-  typedef GLboolean (*glIsSampler_t)(GLuint sampler);
+  typedef GLboolean (APIENTRY *glIsSampler_t)(GLuint sampler);
   glIsSampler_t glIsSampler;
 
-  typedef void (*glBindSampler_t)(GLuint unit, GLuint sampler);
+  typedef void (APIENTRY *glBindSampler_t)(GLuint unit, GLuint sampler);
   glBindSampler_t glBindSampler;
 
-  typedef void (*glSamplerParameteri_t)(GLuint sampler, GLenum pname, GLint param);
+  typedef void (APIENTRY *glSamplerParameteri_t)(GLuint sampler, GLenum pname, GLint param);
   glSamplerParameteri_t glSamplerParameteri;
 
-  typedef void (*glSamplerParameteriv_t)(GLuint sampler, GLenum pname, const GLint* param);
+  typedef void (APIENTRY *glSamplerParameteriv_t)(GLuint sampler, GLenum pname, const GLint* param);
   glSamplerParameteriv_t glSamplerParameteriv;
 
-  typedef void (*glSamplerParameterf_t)(GLuint sampler, GLenum pname, GLfloat param);
+  typedef void (APIENTRY *glSamplerParameterf_t)(GLuint sampler, GLenum pname, GLfloat param);
   glSamplerParameterf_t glSamplerParameterf;
 
-  typedef void (*glSamplerParameterfv_t)(GLuint sampler, GLenum pname, const GLfloat* param);
+  typedef void (APIENTRY *glSamplerParameterfv_t)(GLuint sampler, GLenum pname, const GLfloat* param);
   glSamplerParameterfv_t glSamplerParameterfv;
 
-  typedef void (*glGetSamplerParameteriv_t)(GLuint sampler, GLenum pname, GLint* params);
+  typedef void (APIENTRY *glGetSamplerParameteriv_t)(GLuint sampler, GLenum pname, GLint* params);
   glGetSamplerParameteriv_t glGetSamplerParameteriv;
 
-  typedef void (*glGetSamplerParameterfv_t)(GLuint sampler, GLenum pname, GLfloat* params);
+  typedef void (APIENTRY *glGetSamplerParameterfv_t)(GLuint sampler, GLenum pname, GLfloat* params);
   glGetSamplerParameterfv_t glGetSamplerParameterfv;
 
 public: //! @name OpenGL ES 3.1
 
-  typedef void (*glTexStorage2DMultisample_t)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+  typedef void (APIENTRY *glTexStorage2DMultisample_t)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
   glTexStorage2DMultisample_t glTexStorage2DMultisample;
 
 public: //! @name OpenGL ES 3.2
 
-  typedef void (*glTexBuffer_t)(GLenum target, GLenum internalFormat, GLuint buffer);
+  typedef void (APIENTRY *glTexBuffer_t)(GLenum target, GLenum internalFormat, GLuint buffer);
   glTexBuffer_t glTexBuffer;
 
 public: //! @name GL_KHR_debug (optional)
index 5b6bb69..1bdacad 100644 (file)
@@ -800,7 +800,8 @@ bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProject
   #if !defined(GL_ES_VERSION_2_0)
     aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
   #endif
-    if (toCopyBackToFront)
+    if (toCopyBackToFront
+     && myTransientDrawToFront)
     {
       if (!HasImmediateStructures()
        && !theIsPartialUpdate)
index 4345397..73891f2 100644 (file)
@@ -715,8 +715,11 @@ void OpenGl_Window::Init()
     return;
 
 #if defined(HAVE_EGL)
-  eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH,  &myWidth);
-  eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);
+  if (!myPlatformWindow->IsVirtual())
+  {
+    eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH,  &myWidth);
+    eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);
+  }
 #elif defined(_WIN32)
   //
 #else
index a8a0238..e6b2419 100644 (file)
@@ -518,31 +518,6 @@ void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo)
 }
 
 // =======================================================================
-// function : getAligned
-// purpose  :
-// =======================================================================
-inline Standard_Size getAligned (const Standard_Size theNumber,
-                                 const Standard_Size theAlignment)
-{
-  return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
-}
-
-template<typename T>
-inline void convertRowFromRgba (T* theRgbRow,
-                                const Image_ColorRGBA* theRgbaRow,
-                                const Standard_Size theWidth)
-{
-  for (Standard_Size aCol = 0; aCol < theWidth; ++aCol)
-  {
-    const Image_ColorRGBA& anRgba = theRgbaRow[aCol];
-    T& anRgb = theRgbRow[aCol];
-    anRgb.r() = anRgba.r();
-    anRgb.g() = anRgba.g();
-    anRgb.b() = anRgba.b();
-  }
-}
-
-// =======================================================================
 // function : BufferDump
 // purpose  :
 // =======================================================================
@@ -550,207 +525,9 @@ Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)&
                                                Image_PixMap&                     theImage,
                                                const Graphic3d_BufferType&       theBufferType)
 {
-  if (theImage.IsEmpty()
-  || !Activate())
-  {
-    return Standard_False;
-  }
-
-  GLenum aFormat = 0;
-  GLenum aType   = 0;
-  bool toSwapRgbaBgra = false;
-  bool toConvRgba2Rgb = false;
-  switch (theImage.Format())
-  {
-  #if !defined(GL_ES_VERSION_2_0)
-    case Image_Format_Gray:
-      aFormat = GL_DEPTH_COMPONENT;
-      aType   = GL_UNSIGNED_BYTE;
-      break;
-    case Image_Format_GrayF:
-      aFormat = GL_DEPTH_COMPONENT;
-      aType   = GL_FLOAT;
-      break;
-    case Image_Format_RGB:
-      aFormat = GL_RGB;
-      aType   = GL_UNSIGNED_BYTE;
-      break;
-    case Image_Format_BGR:
-      aFormat = GL_BGR;
-      aType   = GL_UNSIGNED_BYTE;
-      break;
-    case Image_Format_BGRA:
-    case Image_Format_BGR32:
-      aFormat = GL_BGRA;
-      aType   = GL_UNSIGNED_BYTE;
-      break;
-    case Image_Format_BGRF:
-      aFormat = GL_BGR;
-      aType   = GL_FLOAT;
-      break;
-    case Image_Format_BGRAF:
-      aFormat = GL_BGRA;
-      aType   = GL_FLOAT;
-      break;
-  #else
-    case Image_Format_Gray:
-    case Image_Format_GrayF:
-    case Image_Format_BGRF:
-    case Image_Format_BGRAF:
-      return Standard_False;
-    case Image_Format_BGRA:
-    case Image_Format_BGR32:
-      aFormat = GL_RGBA;
-      aType   = GL_UNSIGNED_BYTE;
-      toSwapRgbaBgra = true;
-      break;
-    case Image_Format_BGR:
-    case Image_Format_RGB:
-      aFormat = GL_RGBA;
-      aType   = GL_UNSIGNED_BYTE;
-      toConvRgba2Rgb = true;
-      break;
-  #endif
-    case Image_Format_RGBA:
-    case Image_Format_RGB32:
-      aFormat = GL_RGBA;
-      aType   = GL_UNSIGNED_BYTE;
-      break;
-    case Image_Format_RGBF:
-      aFormat = GL_RGB;
-      aType   = GL_FLOAT;
-      break;
-    case Image_Format_RGBAF:
-      aFormat = GL_RGBA;
-      aType   = GL_FLOAT;
-      break;
-    case Image_Format_Alpha:
-    case Image_Format_AlphaF:
-      return Standard_False; // GL_ALPHA is no more supported in core context
-    case Image_Format_UNKNOWN:
-      return Standard_False;
-  }
-
-  if (aFormat == 0)
-  {
-    return Standard_False;
-  }
-
-#if !defined(GL_ES_VERSION_2_0)
-  GLint aReadBufferPrev = GL_BACK;
-  if (theBufferType == Graphic3d_BT_Depth
-   && aFormat != GL_DEPTH_COMPONENT)
-  {
-    return Standard_False;
-  }
-#else
-  (void )theBufferType;
-#endif
-
-  // bind FBO if used
-  if (!theFbo.IsNull() && theFbo->IsValid())
-  {
-    theFbo->BindBuffer (GetGlContext());
-  }
-  else
-  {
-  #if !defined(GL_ES_VERSION_2_0)
-    glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
-    GLint aDrawBufferPrev = GL_BACK;
-    glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
-    glReadBuffer (aDrawBufferPrev);
-  #endif
-  }
-
-  // setup alignment
-  const GLint anAligment   = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
-  glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
-  bool isBatchCopy = !theImage.IsTopDown();
-
-  const GLint   anExtraBytes       = GLint(theImage.RowExtraBytes());
-  GLint         aPixelsWidth       = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
-  Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
-  if (anExtraBytes < anAligment)
-  {
-    aPixelsWidth = 0;
-  }
-  else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
-  {
-    aPixelsWidth = 0;
-    isBatchCopy  = false;
-  }
-#if !defined(GL_ES_VERSION_2_0)
-  glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
-#else
-  if (aPixelsWidth != 0)
-  {
-    isBatchCopy = false;
-  }
-#endif
-  if (toConvRgba2Rgb)
-  {
-    Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
-    const Standard_Size aRowSize = theImage.SizeX() * 4;
-    NCollection_Buffer aRowBuffer (anAlloc);
-    if (!aRowBuffer.Allocate (aRowSize))
-    {
-      return Standard_False;
-    }
-
-    for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
-    {
-      // Image_PixMap rows indexation always starts from the upper corner
-      // while order in memory depends on the flag and processed by ChangeRow() method
-      glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, aRowBuffer.ChangeData());
-      const Image_ColorRGBA* aRowDataRgba = (const Image_ColorRGBA* )aRowBuffer.Data();
-      if (theImage.Format() == Image_Format_BGR)
-      {
-        convertRowFromRgba ((Image_ColorBGR* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
-      }
-      else
-      {
-        convertRowFromRgba ((Image_ColorRGB* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
-      }
-    }
-  }
-  else if (!isBatchCopy)
-  {
-    // copy row by row
-    for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
-    {
-      // Image_PixMap rows indexation always starts from the upper corner
-      // while order in memory depends on the flag and processed by ChangeRow() method
-      glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
-    }
-  }
-  else
-  {
-    glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
-  }
-  const bool hasErrors = myGlContext->ResetErrors (true);
-
-  glPixelStorei (GL_PACK_ALIGNMENT,  1);
-#if !defined(GL_ES_VERSION_2_0)
-  glPixelStorei (GL_PACK_ROW_LENGTH, 0);
-#endif
-
-  if (!theFbo.IsNull() && theFbo->IsValid())
-  {
-    theFbo->UnbindBuffer (GetGlContext());
-  }
-  else
-  {
-  #if !defined(GL_ES_VERSION_2_0)
-    glReadBuffer (aReadBufferPrev);
-  #endif
-  }
-
-  if (toSwapRgbaBgra)
-  {
-    Image_PixMap::SwapRgbaBgra (theImage);
-  }
-
-  return !hasErrors;
+  return !theImage.IsEmpty()
+      && Activate()
+      && OpenGl_FrameBuffer::BufferDump (GetGlContext(), theFbo, theImage, theBufferType);
 }
 
 // =======================================================================