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().
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
}
myD3dSurfShare (NULL),
myGlD3dDevice (NULL),
myGlD3dSurf (NULL),
- myLockCount (0)
+ myLockCount (0),
+ myD3dFallback (Standard_False)
{
//
}
const Standard_Boolean theIsD3dEx,
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)
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;
}
return Standard_False;
}
+ myD3dFallback = Standard_False;
return Standard_True;
#else
(void )theD3DDevice;
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,
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
{
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;
//! 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);
//! 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;
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:
// purpose :
// =======================================================================
D3DHost_GraphicDriver::D3DHost_GraphicDriver()
-: OpenGl_GraphicDriver (Handle(Aspect_DisplayConnection)(), Standard_False)
+: OpenGl_GraphicDriver (Handle(Aspect_DisplayConnection)(), Standard_True)
{
//
}
}
}
+// =======================================================================
+// function : D3dColorSurface
+// purpose :
+// =======================================================================
+IDirect3DSurface9* D3DHost_View::D3dColorSurface() const
+{
+ return myD3dWglFbo->D3dColorSurface();
+}
+
// =======================================================================
// function : SetWindow
// purpose :
{
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;
}
// =======================================================================
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());
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;
}
}
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);
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);
const Handle(D3DHost_FrameBuffer)& D3dWglBuffer() const { return myD3dWglFbo; }
//! Return D3D surface.
- IDirect3DSurface9* D3dColorSurface() const { return myD3dWglFbo->D3dColorSurface(); }
+ Standard_EXPORT IDirect3DSurface9* D3dColorSurface() const;
protected:
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
#include <OpenGl_FrameBuffer.hxx>
#include <OpenGl_ArbFBO.hxx>
+#include <NCollection_AlignedAllocator.hxx>
#include <Standard_Assert.hxx>
#include <TCollection_ExtendedString.hxx>
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;
+}
#include <OpenGl_Resource.hxx>
#include <OpenGl_Texture.hxx>
+#include <Graphic3d_BufferType.hxx>
#include <NCollection_Vector.hxx>
class OpenGl_FrameBuffer;
static const GLuint NO_FRAMEBUFFER = 0;
static const GLuint NO_RENDERBUFFER = 0;
+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
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)
#if !defined(GL_ES_VERSION_2_0)
aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
#endif
- if (toCopyBackToFront)
+ if (toCopyBackToFront
+ && myTransientDrawToFront)
{
if (!HasImmediateStructures()
&& !theIsPartialUpdate)
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
theFbo.Nullify();
}
-// =======================================================================
-// 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 :
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);
}
// =======================================================================