mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-04 18:06:22 +03:00
0029138: Visualization - D3DHost_FrameBuffer should provide software fallback when WGL_NV_DX_interop is unavailable
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().
This commit is contained in:
parent
c98fcb6456
commit
6cde53c431
@ -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
|
||||
}
|
||||
|
@ -33,7 +33,8 @@ D3DHost_FrameBuffer::D3DHost_FrameBuffer()
|
||||
myD3dSurfShare (NULL),
|
||||
myGlD3dDevice (NULL),
|
||||
myGlD3dSurf (NULL),
|
||||
myLockCount (0)
|
||||
myLockCount (0),
|
||||
myD3dFallback (Standard_False)
|
||||
{
|
||||
//
|
||||
}
|
||||
@ -95,6 +96,50 @@ Standard_Boolean D3DHost_FrameBuffer::Init (const Handle(OpenGl_Context)& theCtx
|
||||
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)
|
||||
@ -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;
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
@ -92,6 +92,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,11 +226,27 @@ bool D3DHost_View::d3dReset()
|
||||
// =======================================================================
|
||||
bool D3DHost_View::d3dCreateRenderTarget()
|
||||
{
|
||||
bool toD3dFallback = false;
|
||||
if (myD3dWglFbo.IsNull())
|
||||
{
|
||||
myD3dWglFbo = new D3DHost_FrameBuffer();
|
||||
}
|
||||
if (!myD3dWglFbo->Init (myWorkspace->GetGlContext(),
|
||||
else
|
||||
{
|
||||
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(),
|
||||
@ -233,6 +254,7 @@ bool D3DHost_View::d3dCreateRenderTarget()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
myD3dDevice->SetRenderTarget (0, myD3dWglFbo->D3dColorSurface());
|
||||
return true;
|
||||
@ -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);
|
||||
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);
|
||||
if (myD3dWglFbo->IsValid())
|
||||
{
|
||||
myToFlipOutput = Standard_True;
|
||||
myFBO = myD3dWglFbo;
|
||||
}
|
||||
OpenGl_View::RedrawImmediate();
|
||||
myFBO.Nullify();
|
||||
myD3dWglFbo->UnlockSurface (aCtx);
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <OpenGl_Resource.hxx>
|
||||
#include <OpenGl_Texture.hxx>
|
||||
|
||||
#include <Graphic3d_BufferType.hxx>
|
||||
#include <NCollection_Vector.hxx>
|
||||
|
||||
class OpenGl_FrameBuffer;
|
||||
@ -38,6 +39,19 @@ public:
|
||||
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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -715,8 +715,11 @@ void OpenGl_Window::Init()
|
||||
return;
|
||||
|
||||
#if defined(HAVE_EGL)
|
||||
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
|
||||
|
@ -517,31 +517,6 @@ void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo)
|
||||
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 :
|
||||
@ -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);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
Loading…
x
Reference in New Issue
Block a user