mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-05-31 11:15:31 +03:00
Apply new regex replacement with method's guards in .cxx Update GH workflow with style checking
452 lines
16 KiB
C++
452 lines
16 KiB
C++
// Created on: 2015-06-10
|
|
// Created by: Kirill Gavrilov
|
|
// Copyright (c) 2015 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
#include <d3d9.h>
|
|
|
|
#include <D3DHost_FrameBuffer.hxx>
|
|
|
|
#include <OpenGl_GlCore20.hxx>
|
|
#include <OpenGl_ArbFBO.hxx>
|
|
#include <OpenGl_Context.hxx>
|
|
#include <OpenGl_Texture.hxx>
|
|
#include <Standard_ProgramError.hxx>
|
|
|
|
IMPLEMENT_STANDARD_RTTIEXT(D3DHost_FrameBuffer, OpenGl_FrameBuffer)
|
|
|
|
//=================================================================================================
|
|
|
|
D3DHost_FrameBuffer::D3DHost_FrameBuffer()
|
|
: myD3dSurf(NULL),
|
|
myD3dSurfShare(NULL),
|
|
myGlD3dDevice(NULL),
|
|
myGlD3dSurf(NULL),
|
|
myLockCount(0),
|
|
myD3dFallback(Standard_False),
|
|
myIsSRGBReady(Standard_False)
|
|
{
|
|
//
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
D3DHost_FrameBuffer::~D3DHost_FrameBuffer()
|
|
{
|
|
Release(NULL);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void D3DHost_FrameBuffer::Release(OpenGl_Context* theCtx)
|
|
{
|
|
if (myGlD3dDevice != NULL)
|
|
{
|
|
const OpenGl_GlFunctions* aFuncs =
|
|
(theCtx != NULL && theCtx->IsValid()) ? theCtx->Functions() : NULL;
|
|
if (myGlD3dSurf != NULL)
|
|
{
|
|
if (aFuncs != NULL)
|
|
{
|
|
aFuncs->wglDXUnregisterObjectNV(myGlD3dDevice, myGlD3dSurf);
|
|
}
|
|
myGlD3dSurf = NULL;
|
|
}
|
|
|
|
if (aFuncs != NULL)
|
|
{
|
|
aFuncs->wglDXCloseDeviceNV(myGlD3dDevice);
|
|
}
|
|
myGlD3dDevice = NULL;
|
|
}
|
|
|
|
if (myD3dSurf != NULL)
|
|
{
|
|
myD3dSurf->Release();
|
|
myD3dSurf = NULL;
|
|
myD3dSurfShare = NULL;
|
|
}
|
|
|
|
OpenGl_FrameBuffer::Release(theCtx);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean D3DHost_FrameBuffer::Init(const Handle(OpenGl_Context)& theCtx,
|
|
IDirect3DDevice9* theD3DDevice,
|
|
const Standard_Boolean theIsD3dEx,
|
|
const Standard_Integer theSizeX,
|
|
const Standard_Integer theSizeY)
|
|
{
|
|
if (InitD3dInterop(theCtx, theD3DDevice, theIsD3dEx, theSizeX, theSizeY, GL_DEPTH24_STENCIL8))
|
|
{
|
|
return Standard_True;
|
|
}
|
|
return InitD3dFallback(theCtx, theD3DDevice, theIsD3dEx, theSizeX, theSizeY, GL_DEPTH24_STENCIL8);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
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_Integer theDepthFormat)
|
|
{
|
|
const Standard_Boolean isGlInit = OpenGl_FrameBuffer::Init(theCtx,
|
|
Graphic3d_Vec2i(theSizeX, theSizeY),
|
|
GL_RGBA8,
|
|
theDepthFormat,
|
|
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 create D3DFMT_X8R8G8B8 render target ")
|
|
+ aSizeX + "x" + aSizeY);
|
|
return Standard_False;
|
|
}
|
|
return isGlInit;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean D3DHost_FrameBuffer::InitD3dInterop(const Handle(OpenGl_Context)& theCtx,
|
|
IDirect3DDevice9* theD3DDevice,
|
|
const Standard_Boolean theIsD3dEx,
|
|
const Standard_Integer theSizeX,
|
|
const Standard_Integer theSizeY,
|
|
const Standard_Integer theDepthFormat)
|
|
{
|
|
Release(theCtx.operator->());
|
|
|
|
myDepthFormat = theDepthFormat;
|
|
myVPSizeX = theSizeX;
|
|
myVPSizeY = theSizeY;
|
|
myInitVPSizeX = theSizeX;
|
|
myInitVPSizeY = theSizeY;
|
|
const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
|
|
const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
|
|
|
|
const OpenGl_GlFunctions* aFuncs = theCtx->Functions();
|
|
if (aFuncs->wglDXOpenDeviceNV == NULL)
|
|
{
|
|
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;
|
|
}
|
|
|
|
// Render target surface should be lockable on
|
|
// Windows XP and non-lockable on Windows Vista or higher
|
|
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 create D3DFMT_X8R8G8B8 render target ")
|
|
+ aSizeX + "x" + aSizeY);
|
|
return Standard_False;
|
|
}
|
|
|
|
myGlD3dDevice = aFuncs->wglDXOpenDeviceNV(theD3DDevice);
|
|
if (myGlD3dDevice == NULL)
|
|
{
|
|
Release(theCtx.operator->());
|
|
theCtx->PushMessage(
|
|
GL_DEBUG_SOURCE_APPLICATION,
|
|
GL_DEBUG_TYPE_ERROR,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH,
|
|
"D3DHost_FrameBuffer, could not create the GL <-> DirectX Interop using wglDXOpenDeviceNV()");
|
|
return Standard_False;
|
|
}
|
|
|
|
if (!registerD3dBuffer(theCtx))
|
|
{
|
|
Release(theCtx.operator->());
|
|
return Standard_False;
|
|
}
|
|
|
|
myIsOwnBuffer = true;
|
|
myIsOwnDepth = true;
|
|
theCtx->arbFBO->glGenFramebuffers(1, &myGlFBufferId);
|
|
|
|
const OpenGl_TextureFormat aDepthFormat =
|
|
OpenGl_TextureFormat::FindSizedFormat(theCtx, myDepthFormat);
|
|
if (aDepthFormat.IsValid()
|
|
&& !myDepthStencilTexture->Init(theCtx,
|
|
aDepthFormat,
|
|
Graphic3d_Vec2i(aSizeX, aSizeY),
|
|
Graphic3d_TypeOfTexture_2D))
|
|
{
|
|
Release(theCtx.get());
|
|
theCtx->PushMessage(GL_DEBUG_SOURCE_APPLICATION,
|
|
GL_DEBUG_TYPE_ERROR,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH,
|
|
TCollection_AsciiString(
|
|
"D3DHost_FrameBuffer, could not initialize GL_DEPTH24_STENCIL8 texture ")
|
|
+ aSizeX + "x" + aSizeY);
|
|
return Standard_False;
|
|
}
|
|
|
|
myD3dFallback = Standard_False;
|
|
return Standard_True;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean D3DHost_FrameBuffer::registerD3dBuffer(const Handle(OpenGl_Context)& theCtx)
|
|
{
|
|
const OpenGl_GlFunctions* aFuncs = theCtx->Functions();
|
|
if (myGlD3dSurf != NULL)
|
|
{
|
|
if (!aFuncs->wglDXUnregisterObjectNV(myGlD3dDevice, myGlD3dSurf))
|
|
{
|
|
theCtx->PushMessage(GL_DEBUG_SOURCE_APPLICATION,
|
|
GL_DEBUG_TYPE_ERROR,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH,
|
|
"D3DHost_FrameBuffer, can not unregister color buffer");
|
|
return Standard_False;
|
|
}
|
|
myGlD3dSurf = NULL;
|
|
}
|
|
|
|
if (!aFuncs->wglDXSetResourceShareHandleNV(myD3dSurf, myD3dSurfShare))
|
|
{
|
|
theCtx->PushMessage(GL_DEBUG_SOURCE_APPLICATION,
|
|
GL_DEBUG_TYPE_ERROR,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH,
|
|
"D3DHost_FrameBuffer, wglDXSetResourceShareHandleNV() has failed");
|
|
return Standard_False;
|
|
}
|
|
|
|
myIsOwnColor = true;
|
|
myColorTextures(0)->Release(theCtx.operator->());
|
|
myColorTextures(0)->Create(theCtx);
|
|
|
|
myGlD3dSurf = aFuncs->wglDXRegisterObjectNV(myGlD3dDevice,
|
|
myD3dSurf,
|
|
myColorTextures(0)->TextureId(),
|
|
GL_TEXTURE_2D,
|
|
WGL_ACCESS_WRITE_DISCARD_NV);
|
|
theCtx->ResetErrors(true);
|
|
if (myGlD3dSurf == NULL)
|
|
{
|
|
theCtx->PushMessage(GL_DEBUG_SOURCE_APPLICATION,
|
|
GL_DEBUG_TYPE_ERROR,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH,
|
|
"D3DHost_FrameBuffer, can not register color buffer");
|
|
return Standard_False;
|
|
}
|
|
|
|
return Standard_True;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
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);
|
|
theCtx->SetFrameBufferSRGB(true, myIsSRGBReady);
|
|
if (myD3dFallback)
|
|
{
|
|
return;
|
|
}
|
|
|
|
theCtx->arbFBO->glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
GL_COLOR_ATTACHMENT0,
|
|
myColorTextures(0)->GetTarget(),
|
|
myColorTextures(0)->TextureId(),
|
|
0);
|
|
|
|
const OpenGl_TextureFormat aDepthFormat =
|
|
OpenGl_TextureFormat::FindSizedFormat(theCtx, myDepthFormat);
|
|
if (myDepthStencilTexture->IsValid())
|
|
{
|
|
theCtx->arbFBO->glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
aDepthFormat.PixelFormat() == GL_DEPTH_STENCIL
|
|
? GL_DEPTH_STENCIL_ATTACHMENT
|
|
: GL_DEPTH_ATTACHMENT,
|
|
myDepthStencilTexture->GetTarget(),
|
|
myDepthStencilTexture->TextureId(),
|
|
0);
|
|
}
|
|
if (theCtx->arbFBO->glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
{
|
|
if (myDepthStencilTexture->IsValid())
|
|
{
|
|
theCtx->arbFBO->glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
aDepthFormat.PixelFormat() == GL_DEPTH_STENCIL
|
|
? GL_DEPTH_STENCIL_ATTACHMENT
|
|
: GL_DEPTH_ATTACHMENT,
|
|
myDepthStencilTexture->GetTarget(),
|
|
0,
|
|
0);
|
|
}
|
|
if (theCtx->arbFBO->glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
{
|
|
theCtx->PushMessage(GL_DEBUG_SOURCE_APPLICATION,
|
|
GL_DEBUG_TYPE_ERROR,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH,
|
|
"D3DHost_FrameBuffer, OpenGL FBO is incomplete!");
|
|
Release(theCtx.operator->());
|
|
}
|
|
else
|
|
{
|
|
myDepthFormat = 0;
|
|
myDepthStencilTexture->Release(theCtx.get());
|
|
theCtx->PushMessage(
|
|
GL_DEBUG_SOURCE_APPLICATION,
|
|
GL_DEBUG_TYPE_PORTABILITY,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH,
|
|
"D3DHost_FrameBuffer, OpenGL FBO is created without Depth+Stencil attachments!");
|
|
}
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void D3DHost_FrameBuffer::LockSurface(const Handle(OpenGl_Context)& theCtx)
|
|
{
|
|
if (++myLockCount > 1)
|
|
{
|
|
return;
|
|
}
|
|
if (myGlD3dSurf == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const OpenGl_GlFunctions* aFuncs = theCtx->Functions();
|
|
if (!aFuncs->wglDXLockObjectsNV(myGlD3dDevice, 1, &myGlD3dSurf))
|
|
{
|
|
theCtx->PushMessage(GL_DEBUG_SOURCE_APPLICATION,
|
|
GL_DEBUG_TYPE_ERROR,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH,
|
|
"D3DHost_FrameBuffer::LockSurface(), lock failed!");
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void D3DHost_FrameBuffer::UnlockSurface(const Handle(OpenGl_Context)& theCtx)
|
|
{
|
|
if (--myLockCount != 0)
|
|
{
|
|
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;
|
|
}
|
|
|
|
const OpenGl_GlFunctions* aFuncs = theCtx->Functions();
|
|
aFuncs->wglDXUnlockObjectsNV(myGlD3dDevice, 1, &myGlD3dSurf);
|
|
}
|