Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement of RenderTargetBitmap to Support Hardware Rendering #9024

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 23 additions & 16 deletions src/Microsoft.DotNet.Wpf/src/WpfGfx/core/api/api_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,31 +279,38 @@ CMILFactory::CreateBitmapRenderTarget(
}
if (SUCCEEDED(hr))
{
if ((format != MilPixelFormat::PBGRA32bpp) && (format != MilPixelFormat::PRGBA128bppFloat))
if (format != MilPixelFormat::PBGRA32bpp)
{
MIL_THR(WGXERR_UNSUPPORTEDPIXELFORMAT);
}
}

CHybridSurfaceRenderTarget *pRenderTarget = NULL;
if (SUCCEEDED(hr))
{
if ( !(dwFlags & MilRTInitialization::HardwareOnly) )
{
MIL_THR(CSwRenderTargetBitmap::Create(
CDisplaySet const *pDisplaySet = NULL;
GetCurrentDisplaySet(&pDisplaySet); // pDisplaySet can be NULL so we dont need to get hr

MIL_THR(CHybridSurfaceRenderTarget::Create(
pDisplaySet,
dwFlags,
dpiX,
dpiY,
OUT &pRenderTarget));
}
if (SUCCEEDED(hr))
{
IntermediateRTUsage rtUsage;
rtUsage.flags = IntermediateRTUsage::ForBlending;
rtUsage.wrapMode = MilBitmapWrapMode::Extend;
MIL_THR(pRenderTarget->CreateRenderTargetBitmap(
width,
height,
format,
dpiX,
dpiY,
DisplayId::None,
ppIRenderTargetBitmap
DBG_STEP_RENDERING_COMMA_PARAM(NULL) // pDisplayRTParent
));
}
else
{
MIL_THR(WGXERR_NOTIMPLEMENTED);
}
rtUsage,
dwFlags,
ppIRenderTargetBitmap));

pRenderTarget->Release();
}

API_CHECK(hr);
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.DotNet.Wpf/src/WpfGfx/core/hw/hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,4 @@
#include "HwShaderEffect.h"
#include "ShaderAssemblies\Shaders.h"


#include "hybridrt.h"
1 change: 1 addition & 0 deletions src/Microsoft.DotNet.Wpf/src/WpfGfx/core/hw/hw.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
<ClCompile Include="InteropDeviceBitmap.cpp" />
<ClCompile Include="swfallback.cpp" />
<ClCompile Include="Waffler.cpp" />
<ClCompile Include="hybridrt.cpp" />
</ItemGroup>
<ItemGroup>
<AdditionalLinkerInputs Include="$(IntermediateOutputPath)hw.res" />
Expand Down
175 changes: 175 additions & 0 deletions src/Microsoft.DotNet.Wpf/src/WpfGfx/core/hw/hybridrt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.


//-----------------------------------------------------------------------------
//
//
// Description:
// CHybridSurfaceRenderTarget implementation
//
// This object creates the hybrid render target.
// Which means it automatically creates HW or SW based on MilRTInitialization::Flags
// and fallback to SW if HW is not available.
//

#include "precomp.hpp"

//+------------------------------------------------------------------------
//
// Function: CHybridSurfaceRenderTarget::Create
//
// Synopsis: 1. Create the CD3DDeviceLevel1
// 2. Check format support
// 3. Create and initialize the CHybridSurfaceRenderTarget
//
//-------------------------------------------------------------------------
HRESULT
CHybridSurfaceRenderTarget::Create(
__in_ecount_opt(1) CDisplaySet const *pDisplaySet,
MilRTInitialization::Flags dwFlags,
FLOAT dpiX, FLOAT dpiY,
__deref_out_ecount(1) CHybridSurfaceRenderTarget **ppRenderTarget
)
{
HRESULT hr = S_OK;

*ppRenderTarget = NULL;

CDisplay *pDisplay = NULL;
D3DDEVTYPE type = D3DDEVTYPE_SW;

if (pDisplaySet && pDisplaySet->GetDisplayCount() > 0)
{
pDisplay = const_cast<CDisplay *>(pDisplaySet->Display(0));
type = D3DDEVTYPE_HAL;
}

CD3DDeviceLevel1 *pD3DDevice = NULL;

D3DPRESENT_PARAMETERS D3DPresentParams;
UINT AdapterOrdinalInGroup;

CD3DDeviceManager *pD3DDeviceManager = CD3DDeviceManager::Get();
Assert(pDisplay->D3DObject()); // we should not get here with null pID3D

IFC(pD3DDeviceManager->GetD3DDeviceAndPresentParams(
NULL,
dwFlags,
pDisplay,
type,
&pD3DDevice,
&D3DPresentParams,
&AdapterOrdinalInGroup
));

HRESULT const *phrTestGetDC;

IFC(pD3DDevice->CheckRenderTargetFormat(
D3DPresentParams.BackBufferFormat,
OUT &phrTestGetDC
));

{
DisplayId associatedDisplay = pDisplay->GetDisplayId();

*ppRenderTarget = new CHybridSurfaceRenderTarget(
pD3DDevice,
D3DPresentParams,
associatedDisplay,
dpiX,
dpiY
);

IFCOOM(*ppRenderTarget);
(*ppRenderTarget)->AddRef(); // CHybridSurfaceRenderTarget::ctor sets ref count == 0
}

Cleanup:
if (FAILED(hr))
{
ReleaseInterface(*ppRenderTarget);
}
ReleaseInterfaceNoNULL(pD3DDevice);
pD3DDeviceManager->Release();
RRETURN(hr);
}


//+------------------------------------------------------------------------
//
// Function: CHybridSurfaceRenderTarget::HrFindInterface
//
// Synopsis: HrFindInterface implementation
//
//-------------------------------------------------------------------------
STDMETHODIMP
CHybridSurfaceRenderTarget::HrFindInterface(
__in_ecount(1) REFIID riid,
__deref_out void** ppvObject
)
{
AssertMsg(false, "CHybridSurfaceRenderTarget is not allowed to be QI'ed.");
RRETURN(E_NOINTERFACE);
}

//+------------------------------------------------------------------------
//
// Function: CHwDisplayRenderTarget::CHwDisplayRenderTarget
//
// Synopsis: ctor
//
//-------------------------------------------------------------------------
CHybridSurfaceRenderTarget::CHybridSurfaceRenderTarget(
__inout_ecount(1) CD3DDeviceLevel1 *pD3DDevice,
__in_ecount(1) D3DPRESENT_PARAMETERS const &D3DPresentParams,
DisplayId associatedDisplay,
FLOAT dpiX, FLOAT dpiY
) :
CHwSurfaceRenderTarget(
pD3DDevice,
D3DFormatToPixelFormat(D3DPresentParams.BackBufferFormat, TRUE),
D3DPresentParams.BackBufferFormat,
associatedDisplay
)
{
m_DeviceTransform.Scale(dpiX, dpiY);
}

//+----------------------------------------------------------------------------
//
// Member: CHybridSurfaceRenderTarget::IsValid
//
// Synopsis: Returns FALSE when rendering with this render target or any use
// is no longer allowed. Mode change is a common cause of of
// invalidation.
//
//-----------------------------------------------------------------------------

bool
CHybridSurfaceRenderTarget::IsValid() const
{
return true;
}


#if DBG_STEP_RENDERING

//+------------------------------------------------------------------------
//
// Function: CHwDisplayRenderTarget::ShowSteppedRendering
//
// Synopsis: Present the current backbuffer or the given texture
// when enabled in debug builds
//
//-------------------------------------------------------------------------

void
CHybridSurfaceRenderTarget::ShowSteppedRendering(
__in LPCTSTR pszRenderDesc,
__in_ecount(1) const ISteppedRenderingSurfaceRT *pRT
)
{ }

#endif DBG_STEP_RENDERING
73 changes: 73 additions & 0 deletions src/Microsoft.DotNet.Wpf/src/WpfGfx/core/hw/hybridrt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

MtExtern(CHybridSurfaceRenderTarget);

//------------------------------------------------------------------------------
//
// Class: CHybridSurfaceRenderTarget
//
// Description:
// This object creates the hybrid render target.
// Which means it automatically creates HW or SW based on MilRTInitialization::Flags
// and fallback to SW if HW is not available.
//
//------------------------------------------------------------------------------
class CHybridSurfaceRenderTarget :
public CMILCOMBase,
public CHwSurfaceRenderTarget
{
public:

static HRESULT Create(
__in_ecount(1) CDisplaySet const *pDisplaySet,
MilRTInitialization::Flags dwFlags,
FLOAT dpiX, FLOAT dpiY,
__deref_out_ecount(1) CHybridSurfaceRenderTarget **ppRenderTarget
);

//
// IUnknown methods
//

DECLARE_COM_BASE;
STDMETHOD(HrFindInterface)(
__in_ecount(1) REFIID riid,
__deref_out void** ppv
);

private:

CHybridSurfaceRenderTarget(
__inout_ecount(1) CD3DDeviceLevel1 *pD3DDevice,
__in_ecount(1) D3DPRESENT_PARAMETERS const &D3DPresentParams,
DisplayId associatedDisplay,
FLOAT dpiX, FLOAT dpiY
);

protected:

//
// CHybridSurfaceRenderTarget methods
//

//+------------------------------------------------------------------------
//
// Member: IsValid
//
// Synopsis: Returns FALSE when rendering with this render target or any
// use is no longer allowed. Mode change is a common cause of
// of invalidation.
//
//-------------------------------------------------------------------------
bool IsValid() const;

#if DBG_STEP_RENDERING
public:
void ShowSteppedRendering(
__in LPCTSTR pszRenderDesc,
__in_ecount(1) const ISteppedRenderingSurfaceRT *pRT
);
#endif DBG_STEP_RENDERING
};
Loading