#include "pch.h"
#include "KSurfaceImageSourceManager.h"
using namespace SurfaceImageSourceManager;
using namespace Platform;
KSurfaceImageSourceManager::KSurfaceImageSourceManager()
{
// This flag adds support for surfaces with a different color channel ordering than the API default.
// It is recommended usage, and is required for compatibility with Direct2D.
UINT creationFlags = D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if defined(_DEBUG)
// If the project is in a debug build, enable debugging via SDK Layers with this flag.
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
// This array defines the set of DirectX hardware feature levels this app will support.
// Note the ordering should be preserved.
D3D_FEATURE_LEVEL _featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
};
// Create the D3D11 API device object, and get a corresponding context.
ComPtr<ID3D11DeviceContext> d3dContext;
DX::ThrowIfFailed(
D3D11CreateDevice(
nullptr, // specify null to use the default adapter
D3D_DRIVER_TYPE_HARDWARE,
0, // leave as 0 unless software device
creationFlags, // optionally set debug and Direct2D compatibility flags
_featureLevels, // list of feature levels this app can support
ARRAYSIZE(_featureLevels), // number of entries in above list
D3D11_SDK_VERSION, // always set this to D3D11_SDK_VERSION for Metro style apps
&m_pID3D11Device, // returns the Direct3D device created
&m_featureLevel, // returns feature level of device created
&m_d3dContext // returns the device immediate context
)
);
m_d3dDevice = ComPtr<ID3D11Device>(m_pID3D11Device);
// Obtain the underlying DXGI device of the Direct3D11.1 device.
DX::ThrowIfFailed(m_d3dDevice.As(&m_dxgiDevice));
// m_d2dFactory
{
D2D1_FACTORY_OPTIONS _options;
ZeroMemory(&_options, sizeof(D2D1_FACTORY_OPTIONS));
DX::ThrowIfFailed(D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory1), &_options, &m_d2dFactory));
}
// Obtain the Direct2D device for 2-D rendering.
DX::ThrowIfFailed(m_d2dFactory->CreateDevice(m_dxgiDevice.Get(), &m_d2dDevice));
// m_d2dDeviceContext
DX::ThrowIfFailed(m_d2dDevice->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &m_d2dDeviceContext));
}
int KSurfaceImageSourceManager::Get_ID3D11Device()
{
if (m_d3dDevice == nullptr) return 0;
return (int)m_d3dDevice.Get();
}
int KSurfaceImageSourceManager::Get_ID3D11DeviceContext()
{
if (m_d3dContext == nullptr) return 0;
return (int)m_d3dContext.Get();
}
int KSurfaceImageSourceManager::Get_IDXGIDevice()
{
if (m_dxgiDevice==nullptr) return 0;
return (int)m_dxgiDevice.Get();
}
int KSurfaceImageSourceManager::Get_ID2D1Factory1()
{
if (m_d2dFactory==nullptr) return 0;
return (int)m_d2dFactory.Get();
}
int KSurfaceImageSourceManager::Get_ID2D1Device()
{
if (m_d2dDevice==nullptr) return 0;
return (int)m_d2dDevice.Get();
}
int KSurfaceImageSourceManager::Get_ID2D1DeviceContext()
{
if (m_d2dDeviceContext==nullptr) return 0;
return (int)m_d2dDeviceContext.Get();
}
SurfaceImageSource^ KSurfaceImageSourceManager::NewSurfaceImageSource(int pixelWidth, int pixelHeight)
{
SurfaceImageSource^ vret = nullptr;
// Native interface of the virtual surface image source
ComPtr<ISurfaceImageSourceNative> _imageSourceNative;
// Create an image source at the initial pixel size.
vret = ref new SurfaceImageSource(pixelWidth, pixelHeight, false);
ComPtr<IUnknown> unknown(reinterpret_cast<IUnknown*>(vret));
unknown.As(&_imageSourceNative);
_imageSourceNative->SetDevice(m_dxgiDevice.Get());
m_std_Id_Width.insert(std::pair<int,int>(vret->GetHashCode(), pixelWidth));
m_std_Id_Height.insert(std::pair<int,int>(vret->GetHashCode(), pixelHeight));
int _id = vret->GetHashCode();
int _width = m_std_Id_Width.find(_id)->second;
int _height = m_std_Id_Height.find(_id)->second;
return vret;
}
void KSurfaceImageSourceManager::DeleteSurfaceImageSource(SurfaceImageSource^ pSurfaceImageSource)
{
if (pSurfaceImageSource==nullptr) return;
int _id = pSurfaceImageSource->GetHashCode();
m_std_Id_Width.erase(_id);
m_std_Id_Height.erase(_id);
}
int KSurfaceImageSourceManager::GetSurfaceImageSourceSize(SurfaceImageSource^ pSurfaceImageSource, int* pSurfaceWidth, int* pSurfaceHeight)
{
if (pSurfaceWidth != NULL) *pSurfaceWidth = 0;
if (pSurfaceHeight != NULL) *pSurfaceHeight = 0;
if (pSurfaceImageSource == nullptr) return 1;
if (pSurfaceWidth == NULL) return 2;
if (pSurfaceHeight == NULL) return 3;
int _id = pSurfaceImageSource->GetHashCode();
std::map<int,int>::iterator _it = m_std_Id_Width.find(_id);
if (_it != m_std_Id_Width.end())
{
*pSurfaceWidth = _it->second;
}
else
{
return 4;
}
_it = m_std_Id_Height.find(_id);
if (_it != m_std_Id_Height.end())
{
*pSurfaceHeight = _it->second;
}
else
{
return 5;
}
return 0;
}
int KSurfaceImageSourceManager::ClearSurfaceImageSource(SurfaceImageSource^ pSurfaceImageSource, float R, float G, float B, float A)
{
if (pSurfaceImageSource == nullptr) return 1;
int _width = 0;
int _height = 0;
int _retcode = GetSurfaceImageSourceSize(pSurfaceImageSource, &_width, &_height);
if (_retcode != 0) return 2;
ComPtr<ISurfaceImageSourceNative> _imageSourceNative;
ComPtr<IUnknown> unknown(reinterpret_cast<IUnknown*>(pSurfaceImageSource));
unknown.As(&_imageSourceNative);
if (_imageSourceNative==nullptr) return 3;
HRESULT hr;
ComPtr<IDXGISurface> _dxgiSurface;
POINT _surfaceOffset = {0};
RECT _drawingBounds = {0, 0, _width, _height};
// BeginDraw
hr = _imageSourceNative->BeginDraw(_drawingBounds, &_dxgiSurface, &_surfaceOffset);
if (FAILED(hr)) return 2;
IDXGISurface* _pIDXGISurface = _dxgiSurface.Get();
ComPtr<ID2D1Bitmap1> _bitmap;
hr = m_d2dDeviceContext->CreateBitmapFromDxgiSurface(_pIDXGISurface, nullptr, &_bitmap);
if (FAILED(hr)) return 4;
// Begin the drawing batch
m_d2dDeviceContext->BeginDraw();
// Set the render target to surface given by the framework
m_d2dDeviceContext->SetTarget(_bitmap.Get());
//
m_d2dDeviceContext->Clear(D2D1::ColorF(R, G, B, A));
//
m_d2dDeviceContext->SetTarget(nullptr);
//
m_d2dDeviceContext->EndDraw();
// EndDraw
hr = _imageSourceNative->EndDraw();
if (FAILED(hr)) return 5;
return 0;
}
int KSurfaceImageSourceManager::BeginDraw2D(SurfaceImageSource^ pSurfaceImageSource, int* pOffsetX, int* pOffsetY, int* pSurfaceWidth, int* pSurfaceHeight)
{
if (pSurfaceImageSource == nullptr) return 0;
if (pOffsetX==nullptr || pOffsetY==nullptr || pSurfaceWidth==nullptr || pSurfaceHeight==nullptr) return 0;
*pOffsetX = *pOffsetY = *pSurfaceWidth = *pSurfaceHeight = 0;
int _width = 0;
int _height = 0;
int _retcode = GetSurfaceImageSourceSize(pSurfaceImageSource, &_width, &_height);
if (_retcode != 0) return 0;
ComPtr<ISurfaceImageSourceNative> _imageSourceNative;
{
ComPtr<IUnknown> unknown(reinterpret_cast<IUnknown*>(pSurfaceImageSource));
unknown.As(&_imageSourceNative);
}
if (_imageSourceNative==nullptr) return 0;
HRESULT hr;
ComPtr<IDXGISurface> _dxgiSurface;
{
POINT _surfaceOffset = {0};
RECT _drawingBounds = {0, 0, _width, _height};
// BeginDraw -> _dxgiSurface
hr = _imageSourceNative->BeginDraw(_drawingBounds, &_dxgiSurface, &_surfaceOffset);
if (FAILED(hr)) return 0;
*pOffsetX = _surfaceOffset.x;
*pOffsetY = _surfaceOffset.y;
}
{
DXGI_SURFACE_DESC _surfacedesc;
ZeroMemory(&_surfacedesc, sizeof(DXGI_SURFACE_DESC));
_dxgiSurface->GetDesc(&_surfacedesc);
*pSurfaceWidth =_surfacedesc.Width;
*pSurfaceHeight = _surfacedesc.Height;
}
IDXGISurface* _pIDXGISurface = _dxgiSurface.Get();
if (_pIDXGISurface==nullptr) return 0;
{
// Create the DXGI Surface Render Target.
FLOAT dpiX;
FLOAT dpiY;
m_d2dFactory->GetDesktopDpi(&dpiX, &dpiY);
D2D1_RENDER_TARGET_PROPERTIES _props =
D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
dpiX,
dpiY
);
hr = m_d2dFactory->CreateDxgiSurfaceRenderTarget(_pIDXGISurface, &_props, &m_pRenderTarget_Draw2D);
if (FAILED(hr)) return 0;
return (int)m_pRenderTarget_Draw2D.Get();
}
}
void KSurfaceImageSourceManager::EndDraw2D(SurfaceImageSource^ pSurfaceImageSource)
{
if (pSurfaceImageSource == nullptr) return;
ComPtr<ISurfaceImageSourceNative> _imageSourceNative;
ComPtr<IUnknown> unknown(reinterpret_cast<IUnknown*>(pSurfaceImageSource));
unknown.As(&_imageSourceNative);
if (_imageSourceNative != nullptr)
{
HRESULT hr = _imageSourceNative->EndDraw();
}
m_pRenderTarget_Draw2D = nullptr;
}
int KSurfaceImageSourceManager::BeginDraw3D(SurfaceImageSource^ pSurfaceImageSource, int* pOffsetX, int* pOffsetY, int* pSurfaceWidth, int* pSurfaceHeight)
{
if (pSurfaceImageSource == nullptr) return 0;
if (pOffsetX==nullptr || pOffsetY==nullptr || pSurfaceWidth==nullptr || pSurfaceHeight==nullptr) return 0;
*pOffsetX = *pOffsetY = *pSurfaceWidth = *pSurfaceHeight = 0;
int _width = 0;
int _height = 0;
int _retcode = GetSurfaceImageSourceSize(pSurfaceImageSource, &_width, &_height);
if (_retcode != 0) return 0;
ComPtr<ISurfaceImageSourceNative> _imageSourceNative;
{
ComPtr<IUnknown> unknown(reinterpret_cast<IUnknown*>(pSurfaceImageSource));
unknown.As(&_imageSourceNative);
}
if (_imageSourceNative==nullptr) return 0;
HRESULT hr;
ComPtr<IDXGISurface> _dxgiSurface;
{
POINT _surfaceOffset = {0};
RECT _drawingBounds = {0, 0, _width, _height};
// BeginDraw -> _dxgiSurface
hr = _imageSourceNative->BeginDraw(_drawingBounds, &_dxgiSurface, &_surfaceOffset);
if (FAILED(hr)) return 0;
*pOffsetX = _surfaceOffset.x;
*pOffsetY = _surfaceOffset.y;
}
{
DXGI_SURFACE_DESC _surfacedesc;
ZeroMemory(&_surfacedesc, sizeof(DXGI_SURFACE_DESC));
_dxgiSurface->GetDesc(&_surfacedesc);
*pSurfaceWidth =_surfacedesc.Width;
*pSurfaceHeight = _surfacedesc.Height;
}
IDXGISurface* _pIDXGISurface = _dxgiSurface.Get();
if (_pIDXGISurface == nullptr) return 0;
hr = _pIDXGISurface->QueryInterface(IID_ID3D11Texture2D, &m_pTexture2D_Draw3D);
if (FAILED(hr)) return 0;
return (int)m_pTexture2D_Draw3D.Get();
}
void KSurfaceImageSourceManager::EndDraw3D(SurfaceImageSource^ pSurfaceImageSource)
{
if (pSurfaceImageSource == nullptr) return;
ComPtr<ISurfaceImageSourceNative> _imageSourceNative;
ComPtr<IUnknown> unknown(reinterpret_cast<IUnknown*>(pSurfaceImageSource));
unknown.As(&_imageSourceNative);
if (_imageSourceNative != nullptr)
{
HRESULT hr = _imageSourceNative->EndDraw();
}
m_pTexture2D_Draw3D = nullptr;
}