C++ cli Windows 7上的D3D D2D互操作

C++ cli Windows 7上的D3D D2D互操作,c++-cli,directx-11,direct2d,directx-10,directwrite,C++ Cli,Directx 11,Direct2d,Directx 10,Directwrite,我正在尝试使用DWrite在我的dx11应用程序中绘制文本,但我遇到了很多问题,我在D3D10设备和D3D11设备之间共享了资源,因为dx10能够连接D3D和D2D,这是我的GraphicsDevice的代码: // File: GraphicsDevice.h #pragma once #ifndef _GRAPHICSDEVICE_H_ #define _GRAPHICSDEVICE_H_ #ifndef _DEFINES_H_ #include "Defines.h" #endif

我正在尝试使用DWrite在我的dx11应用程序中绘制文本,但我遇到了很多问题,我在D3D10设备和D3D11设备之间共享了资源,因为dx10能够连接D3D和D2D,这是我的GraphicsDevice的代码:

// File: GraphicsDevice.h

#pragma once

#ifndef _GRAPHICSDEVICE_H_
#define _GRAPHICSDEVICE_H_

#ifndef _DEFINES_H_
#include "Defines.h"
#endif
#ifndef _COLOR_H_
#include "Color.h"
#endif
#ifndef _UTILITIES_H_
#include "Utilities.h"
#endif
#ifndef _DWRITE_H_
#include "DWrite.h"
#endif

// Forward declaration
namespace BSGameFramework { ref class Game; }

using namespace BSGameFramework;
using namespace System;

namespace BSGameFramework
{
namespace Graphics
{
    public ref class GraphicsDevice
    {
        public:

            /// <summary>GraphicsDevice constructor.</summary>
            /// <param name="game">The game wich the device has to work.</param>
            GraphicsDevice(Game^ game);
            virtual ~GraphicsDevice();

            /// <summary>Clear the screen.</summary>
            /// <param name="color">The color that the screen background will assume after clearing.</param>
            void Clear(Color color);
            /// <summary>Render on the screen.</summary>
            void Render();
            /// <summary>Set the full screen state.</summary>
            void FullScreen(bool isFullScreen);

            property Color BlendFactor
            {
                Color get()
                {
                    return blendFactor_;
                }

                void set(Color blendFactor_)
                {
                    blendFactor_ = BlendFactor;
                }
            }

            property D3D_DRIVER_TYPE DriverType
            {
                D3D_DRIVER_TYPE get()
                {
                    return driverType_;
                }
            }

            property D3D_FEATURE_LEVEL FeatureLevel
            {
                D3D_FEATURE_LEVEL get()
                {
                    return featureLevel_;
                }
            }

            property ID3D11Device* D3DDevice
            {
                ID3D11Device* get()
                {
                    return d3dDevice_;
                }
            }

            property ID3D11DeviceContext* D3DContext
            {
                ID3D11DeviceContext* get()
                {
                    return d3dContext_;
                }
            }

            property ID3D10Device1* D3DDevice10_1
            {
                ID3D10Device1* get()
                {
                    return d3dDevice10_1_;
                }
            }

            property ID2D1Factory* D2DFactory
            {
                ID2D1Factory* get()
                {
                    return d2dFactory_;
                }
            }

            property ID2D1RenderTarget* D2DRenderTarget
            {
                ID2D1RenderTarget* get()
                {
                    return d2dRenderTarget_;
                }
            }

            property ID2D1SolidColorBrush* D2DSolidColorBrush
            {
                ID2D1SolidColorBrush* get()
                {
                    return d2dSolidColorBrush_;
                }
            }

            property IDWriteFactory* DWriteFactory
            {
                IDWriteFactory* get()
                {
                    return dWriteFactory_;
                }
            }

            property int WindowWidth
            {
                int get()
                {
                    return GetWindowWidth();
                }
            }

            property int WindowHeight
            {
                int get()
                {
                    return GetWindowHeight();
                }
            }

            property HWND Window
            {
                HWND get()
                {
                    return GetWindow(); 
                }
            }

            property int SafeTitleArea
            {
                int get()
                {
                    return safeTitleArea_;
                }

                void set(int safeTitleArea)
                {
                    safeTitleArea_ = safeTitleArea;
                }
            }

        private:

            void CreateD3D11Resources();
            void CreateD3D10Resources(ID3D11Texture2D* d3d11Texture);
            void CreateD2D1Resources(ID3D10Texture2D* d3d10Texture);

            Game^ game_;
            Color blendFactor_;
            D3D_DRIVER_TYPE driverType_;
            D3D_FEATURE_LEVEL featureLevel_;
            int safeTitleArea_;

            int GetWindowWidth();
            int GetWindowHeight();
            HWND GetWindow();

            // Direct3D 11

            ID3D11Device* d3dDevice_;
            ID3D11DeviceContext* d3dContext_;

            // Direct3D 10

            ID3D10Device1* d3dDevice10_1_;

            // Direct2D

            ID2D1Factory* d2dFactory_;
            ID2D1RenderTarget* d2dRenderTarget_;
            ID2D1SolidColorBrush* d2dSolidColorBrush_;

            // DirectWrite

            IDWriteFactory* dWriteFactory_;

            IDXGISwapChain* swapChain_;
            ID3D11RenderTargetView* backBufferTarget_;
    };
}
}

#endif
//文件:GraphicsDevice.h
#布拉格语一次
#ifndef\u图形设备_
#定义图形设备_
#如果定义了_
#包括“Defines.h”
#恩迪夫
#ifndef\u颜色\u H_
#包括“Color.h”
#恩迪夫
#ifndef(公用事业)_
#包括“Utilities.h”
#恩迪夫
#如果没有写入_
#包括“DWrite.h”
#恩迪夫
//远期申报
命名空间BSGameFramework{ref class Game;}
使用名称空间框架;
使用名称空间系统;
命名空间框架
{
名称空间图形
{
公共参考类图形设备
{
公众:
///图形设备构造函数。
///设备必须工作的游戏。
图形设备(游戏^Game);
虚拟~图形设备();
///清除屏幕。
///清除后屏幕背景将采用的颜色。
空洞清晰(颜色);
///在屏幕上渲染。
void Render();
///设置全屏状态。
无效全屏(bool为全屏);
属性颜色混合因子
{
颜色获取()
{
返回blendFactor;
}
空集(颜色混合因子)
{
blendFactor=blendFactor;
}
}
属性D3D_驱动程序_类型驱动程序类型
{
D3D_驱动程序_类型get()
{
返回驱动器类型;
}
}
属性D3D\U功能\U级别功能级别
{
D3D_功能_级别获取()
{
返回特性级别u0;
}
}
属性ID3D11Device*D3DDevice
{
ID3D11Device*get()
{
返回d3dDevice;
}
}
属性ID3D11DeviceContext*D3DContext
{
ID3D11DeviceContext*get()
{
返回d3dContext;
}
}
属性ID3D10Device1*D3DDevice10\u 1
{
ID3D10Device1*get()
{
返回d3dDevice10\u 1\u;
}
}
属性ID2D1Factory*D2DFFactory
{
ID2D1Factory*get()
{
返回D2D工厂;
}
}
属性ID2D1RenderTarget*D2DRenderTarget
{
ID2D1RenderTarget*get()
{
返回d2dRenderTarget_u2;;
}
}
属性ID2D1SOLIDCORBRUSH*D2DSSOLIDCORBRUSH
{
ID2D1SOLIDCORBRUSH*get()
{
返回d2dSolidColorBrush;
}
}
属性IDWriteFactory*DWriteFactory
{
IDWriteFactory*get()
{
返回数据写入工厂;
}
}
属性int WindowWidth
{
int get()
{
返回GetWindowWidth();
}
}
属性int WindowHeight
{
int get()
{
返回GetWindowHeight();
}
}
属性HWND窗口
{
HWND get()
{
返回GetWindow();
}
}
财产保险公司
{
int get()
{
退回保险箱;
}
无效集(int-SafeTileArea)
{
safeTitleArea=safeTitleArea;
}
}
私人:
void CreateD3D11Resources();
void创建的d3d10resources(ID3D11Texture2D*d3d11Texture);
void CreateD2D1Resources(ID3D10Texture2D*d3d10Texture);
游戏^游戏^;
混色因子;
D3D\U驱动程序类型驱动程序类型;
D3D_功能等级特征等级;
国际安全会议;
int GetWindowWidth();
int GetWindowHeight();
HWND GetWindow();
//Direct3D 11
ID3D11设备*d3dDevice;
ID3D11DeviceContext*d3dContext;
//Direct3D 10
ID3D10设备1*d3dDevice10;
//Direct2D
ID2D1Factory*D2DFFactory;
ID2D1RenderTarget*d2dRenderTarget;
ID2D1SOLIDCORBRUSH*D2DSSOLIDCORBRUSH;
//DirectWrite
IDWriteFactory*dWriteFactory\ux;
IDXGISwapChain*swapChain_2;;
ID3D11RenderTargetView*backBufferTarget;
};
}
}
#恩迪夫

//文件:GraphicsDevice.cpp
#包括“GraphicsDevice.h”
#包括“Game.h”
#包括“GraphicsDeviceNativeWrapper.h”
使用命名空间BSGameFramework::Graphics;
使用名称空间框架;
内嵌图形设备::图形设备(游戏^Game):驱动器类型(D3D\U驱动器类型\U NULL),功能级别(D3D\U功能级别\U 11\U 0),
d3dDevice(0)、d3dContext(0)、swapChain(0)、backBufferTarget(0)
{
游戏=游戏;
BlendFactor=颜色::白色;
创建d3d11资源();
}
内联GraphicsDevice::~GraphicsDevice()
{
if(backBufferTarget_u2;)
{
backBufferTarget_uuzy->Release();
}
如果(交换链)
{
交换链->释放();
}
如果(d3dContext)
{
d3dContext->Release();
}
如果(D3D设备)
{
D3D设备->释放();
}
backBufferTarget_u0;
交换链=0;
D3D上下文=0;
d3dDevice=0;
// FILE: GraphicsDevice.cpp

#include "GraphicsDevice.h"
#include "Game.h"
#include "GraphicsDeviceNativeWrapper.h"

using namespace BSGameFramework::Graphics;
using namespace BSGameFramework;

inline GraphicsDevice::GraphicsDevice(Game^ game) : driverType_( D3D_DRIVER_TYPE_NULL ),     featureLevel_( D3D_FEATURE_LEVEL_11_0 ),
                            d3dDevice_( 0 ), d3dContext_( 0 ), swapChain_( 0 ), backBufferTarget_( 0 )
{
game_ = game;
BlendFactor = Color::White;

CreateD3D11Resources();
}

inline GraphicsDevice::~GraphicsDevice()
{
if (backBufferTarget_)
{
    backBufferTarget_->Release();
}

if (swapChain_)
{
    swapChain_->Release();
}

if (d3dContext_)
{
    d3dContext_->Release();
}

if (d3dDevice_)
{
    d3dDevice_->Release();
}

backBufferTarget_ = 0;
swapChain_ = 0;
d3dContext_ = 0;
d3dDevice_ = 0;
}

inline void GraphicsDevice::Clear(Color color)
{
if (d3dContext_ == 0)
{
    return;
}

float clearColor[4];
Vec4 convertedColor = Utilities::ColorToVec4(color);
clearColor[0] = convertedColor.values[0];
clearColor[1] = convertedColor.values[1];
clearColor[2] = convertedColor.values[2];
clearColor[3] = convertedColor.values[3];

d3dContext_->ClearRenderTargetView(backBufferTarget_, clearColor);
}

inline void GraphicsDevice::Render()
{
swapChain_->Present(0, 0);
}

inline void GraphicsDevice::FullScreen(bool isFullScreen)
{
swapChain_->SetFullscreenState(isFullScreen, NULL);
}

inline int GraphicsDevice::GetWindowWidth()
{
return game_->WindowWidth;
}

inline int GraphicsDevice::GetWindowHeight()
{
return game_->WindowHeight;
}

inline HWND GraphicsDevice::GetWindow()
{
return game_->Window;
}

#pragma region CreateD3D11Resources

inline void GraphicsDevice::CreateD3D11Resources()
{
HRESULT result;

RECT dimensions;
GetClientRect(Window, &dimensions);

unsigned int width = dimensions.right - dimensions.left;
unsigned int height = dimensions.bottom - dimensions.top;

D3D_DRIVER_TYPE driverTypes[] =
{
    D3D_DRIVER_TYPE_HARDWARE,
    D3D_DRIVER_TYPE_WARP,
    D3D_DRIVER_TYPE_REFERENCE,
    D3D_DRIVER_TYPE_SOFTWARE
};

unsigned int totalDriverTypes = ARRAYSIZE(driverTypes);

D3D_FEATURE_LEVEL featureLevels[] =
{
    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
};

unsigned int totalFeatureLevels = ARRAYSIZE(featureLevels);

DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 2;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = game_->Window;
swapChainDesc.Windowed = true;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;

unsigned int creationFlags = 0;

#ifdef _DEBUG
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

unsigned int driver = 0;

pin_ptr<IDXGISwapChain*> swapChainPointer;
swapChainPointer = &swapChain_;

pin_ptr<ID3D11Device*> d3dDevicePointer;
d3dDevicePointer = &d3dDevice_;

pin_ptr<D3D_FEATURE_LEVEL> featureLevelPointer;
featureLevelPointer = &featureLevel_;

pin_ptr<ID3D11DeviceContext*> d3dContextPointer;
d3dContextPointer = &d3dContext_;

for (driver = 0; driver < totalDriverTypes; ++driver)
{
    result = D3D11CreateDeviceAndSwapChain(0, driverTypes[driver], 0, creationFlags, featureLevels, totalFeatureLevels,
        D3D11_SDK_VERSION, &swapChainDesc, swapChainPointer,
        d3dDevicePointer, featureLevelPointer, d3dContextPointer);

    if (SUCCEEDED(result))
    {
        driverType_ = driverTypes[driver];
        break;
    }
}

if (FAILED(result))
{
    DXTRACE_MSG("Failed to create the Direct3D device!");
    return;
}

ID3D11Texture2D* backBufferTexture;

result = swapChain_->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferTexture);

if (FAILED(result))
{
    DXTRACE_MSG("Failed to get the swap chain back buffer!");
    return;
}

pin_ptr<ID3D11RenderTargetView*> backBufferTargetPointer;
backBufferTargetPointer = &backBufferTarget_;

result = d3dDevice_->CreateRenderTargetView(backBufferTexture, 0, backBufferTargetPointer);

if (FAILED(result))
{
    DXTRACE_MSG("Failed to create the render target view!");
    return;
}

d3dContext_->OMSetRenderTargets(1, backBufferTargetPointer, 0);

D3D11_VIEWPORT viewport;
viewport.Width = static_cast<float>(width);
viewport.Height = static_cast<float>(height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;

d3dContext_->RSSetViewports(1, &viewport);

CreateD3D10Resources(backBufferTexture);
}

#pragma endregion

#pragma region CreateD3D10Resources

inline void GraphicsDevice::CreateD3D10Resources(ID3D11Texture2D* d3d11Texture)
{
//Load D3D10.DLL
HMODULE d3d10_1 = LoadLibrary("D3D10_1.dll");

// Get adapter of the current D3D11 device. Our D3D10 will run on the same adapter.
IDXGIDevice* dxgiDevice;
IDXGIAdapter* dxgiAdapter;

d3dDevice_->QueryInterface<IDXGIDevice>(&dxgiDevice);
dxgiDevice->GetAdapter(&dxgiAdapter);
SafeRelease<IDXGIDevice>(&dxgiDevice);

//Get address of the function D3D10CreateDevice1 dynamically.
typedef HRESULT (WINAPI* FN_D3D10CreateDevice1)(
       IDXGIAdapter *pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software,
       UINT Flags, D3D10_FEATURE_LEVEL1 HardwareLevel, UINT SDKVersion, ID3D10Device1 **ppDevice );

FN_D3D10CreateDevice1 fnCreate = (FN_D3D10CreateDevice1)GetProcAddress(d3d10_1, "D3D10CreateDevice1");

//Call D3D10CreateDevice1 dynamically.
pin_ptr<ID3D10Device1*> d3dDevice10_1Ptr = &d3dDevice10_1_;

fnCreate(dxgiAdapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT | D3D10_CREATE_DEVICE_DEBUG, D3D10_FEATURE_LEVEL_10_1, D3D10_1_SDK_VERSION, d3dDevice10_1Ptr);

//Create a D3D10.1 render target texture and share it with our D3D11.
D3D10_TEXTURE2D_DESC tDesc;
tDesc.Width = game_->WindowWidth;
tDesc.Height = game_->WindowHeight;
tDesc.MipLevels = 1;
tDesc.ArraySize = 1;
tDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
tDesc.SampleDesc.Count = 1;
tDesc.SampleDesc.Quality = 0;
tDesc.Usage = D3D10_USAGE_DEFAULT;
//EVEN IF YOU WON'T USE AS SHADER RESOURCE, SET THIS BIND FLAGS:
tDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
tDesc.CPUAccessFlags = 0;
tDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED;

//Create the RT texture on D3D10
ID3D10Texture2D* texture;
d3dDevice10_1_->CreateTexture2D(&tDesc, NULL, &texture);

//Get DXGI Resource and retrieve the sharing handle.
IDXGISurface* dxgiSurface;
IDXGIResource* dxgiResource;
HANDLE shareHandle;

texture->QueryInterface<IDXGISurface>(&dxgiSurface);
dxgiSurface->QueryInterface<IDXGIResource>(&dxgiResource);
dxgiResource->GetSharedHandle(&shareHandle);
SafeRelease(&dxgiResource);
SafeRelease(&dxgiSurface);

//Call D3D 11 to open shared resource.
ID3D11Resource* d3d11Resource;

d3dDevice_->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource), (void**)&d3d11Resource);
d3d11Resource->QueryInterface<ID3D11Texture2D>(&d3d11Texture);
SafeRelease(&d3d11Resource);

if (d3d11Texture)
{
    d3d11Texture->Release();
}

CreateD2D1Resources(texture);
}

#pragma endregion

#pragma region CreateD2D1Resources

inline void GraphicsDevice::CreateD2D1Resources(ID3D10Texture2D* d3d10Texture)
{
pin_ptr<ID2D1Factory*> d2dFactoryPtr = &d2dFactory_;
pin_ptr<IDWriteFactory*> dWriteFactoryPtr = &dWriteFactory_;
//pin_ptr<ID2D1HwndRenderTarget*> d2dRenderTargetPtr = &d2dRenderTarget_;
//pin_ptr<ID2D1SolidColorBrush*> D2DSolidColorBrushPtr = &d2dSolidColorBrush_;

GraphicsDeviceNativeWrapper::CreateFactories(Window, d2dFactoryPtr, dWriteFactoryPtr);

//Get DXGI Surface from the created render target.
IDXGISurface1* pRT10;
d3d10Texture->QueryInterface<IDXGISurface1>(&pRT10);

FLOAT dpiX;
FLOAT dpiY;
d2dFactory_->GetDesktopDpi(&dpiX, &dpiY);

// Create a DC render target.
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE),
static_cast<float>(dpiX),
static_cast<float>(dpiY)
);

// Create a Direct2D render target.
// Assuming m_pD2DFactory was previously created with:
//D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), NULL,
//   (void**)(&m_pD2DFactory));
pin_ptr<ID2D1RenderTarget*> renderTargetPtr = &d2dRenderTarget_;

d2dFactory_->CreateDxgiSurfaceRenderTarget(pRT10, (const D2D1_RENDER_TARGET_PROPERTIES *)&props, renderTargetPtr);

pin_ptr<ID2D1SolidColorBrush*> solidColorBrushPtr = &d2dSolidColorBrush_;
d2dRenderTarget_->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), solidColorBrushPtr);
}

#pragma endregion
// File GraphicsDeviceNativeWrapper.h

#pragma once

#ifndef _GRAPHICSDEVICENATIVEWRAPPER_H_
#define _GRAPHICSDEVICENATIVEWRAPPER_H_

#ifndef _DWRITE_H_
#include "DWrite.h"
#endif

#pragma managed(push, false)

namespace BSGameFramework
{
namespace Graphics
{
    class GraphicsDeviceNativeWrapper abstract sealed
    {
        public:

            static void CreateFactories(HWND window, ID2D1Factory** d2dFactory, IDWriteFactory** dWriteFactory/*,ID2D1RenderTarget** d2dRenderTarget, ID2D1SolidColorBrush** d2dSolidColorBrush*/)
            {
                HRESULT result;

                result = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,__uuidof(ID2D1Factory), NULL, (void**)d2dFactory);

                if (SUCCEEDED(result))
                {
                    result = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(dWriteFactory));
                }

                RECT rc;
                GetClientRect(window, &rc);

                D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);

            }

            static void CreateTextFormat(const wchar_t* font, IDWriteFactory* factory, IDWriteTextFormat** format)
            {
                factory->CreateTextFormat(font, NULL, DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 72.0f, L"en-us", format);

                (*format)->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
                (*format)->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
            }
    };
}
}

#pragma managed(pop)

#endif
// File: SpriteBatch.h

#pragma once

#ifndef _SPRITEBATCH_H_
#define _SPRITEBATCH_H_

#ifndef _DEFINES_H_
#include "Defines.h"
#endif
#ifndef _GRAPHICRESOURCE_H_
#include "GraphicResource.h"
#endif
#ifndef _TEXTURE2D_H_
#include "Texture2D.h"
#endif
#ifndef _GRAPHICSDEVICE_H_
#include "GraphicsDevice.h"
#endif
#ifndef _SPRITESORTMODE_H_
#include "SpriteSortMode.h"
#endif
#ifndef _BLENDSTATE_H_
#include "BlendState.h"
#endif
#ifndef _NATIVESPRITEBATCH_H_
#include "NativeSpritebatch.h"
#endif
#ifndef _SPRITEEFFECT_H_
#include "SpriteEffect.h"
#endif
#ifndef _IDRAWABLECOMPONENT_H_
#include "IDrawableComponent.h"
#endif
#ifndef _SPRITEFONT_H_
#include "SpriteFont.h"
#endif

using namespace BSGameFramework::GameBase;

namespace BSGameFramework
{
namespace Graphics
{
    public ref class SpriteBatch : GraphicResource
    {
        public:

            SpriteBatch(GraphicsDevice^ graphicsDevice);
            ~SpriteBatch();

            void Begin();
            void Begin(SpriteSortMode sortMode, BlendState^ blendState);
            void Draw(IDrawableComponent^ component);
            void DrawString(SpriteFont^ font, System::String^ text, Vector2 position);
            void End();

        private:

            bool CompileD3DShader(char* filePath, char* entry, char* shaderModel, ID3DBlob** buffer);
            void SortByDepth();

            SpriteSortMode sortMode_;
            BlendState ^blendState_;
            System::Collections::Generic::List<IDrawableComponent^>^ componentList_;
            bool beginInvoked_;

            ID3D11VertexShader* solidColorVS_;
            ID3D11PixelShader* solidColorPS_;

            ID3D11InputLayout* inputLayout_;
            ID3D11Buffer* vertexBuffer_;

            ID3D11BlendState* alphaBlendState_;

            NativeSpritebatch* spriteBatch;
    };
}
}

#endif
// File: SpriteBatch.cpp

#include "SpriteBatch.h"
#ifndef _SPRITEBATCHBEGINENDEXCEPTION_H_
#include "SpriteBatchBeginEndException.h"
#endif

using namespace BSGameFramework::Graphics;
using namespace BSGameFramework::Exception;

inline SpriteBatch::SpriteBatch(GraphicsDevice^ graphicsDevice) : alphaBlendState_( 0 )
{
graphicDevice_ = graphicsDevice;
sortMode_ = SpriteSortMode::Deferred;
blendState_ = BlendState::AlphaBlend;

// ID3DBlob contiene un puntatore ad un dato di lunghezza qualsiasi, GetBufferPointer restituisce il puntatore e GetBufferSize la grandezza
ID3DBlob* vsBuffer = 0;
// Compila lo shader e salva il risultato nel buffer
bool compileResult = CompileD3DShader("TextureMap.fx", "VS_Main", "vs_4_0", &vsBuffer);

if (compileResult == false)
{
    DXTRACE_MSG("Error compiling the vertex shader!");
    return;
}

HRESULT d3dResult;

pin_ptr<ID3D11VertexShader*> solidColorVSPointer;
solidColorVSPointer = &solidColorVS_;
// Crea il vertex shader e lo salva in solidColorVS_ di tipo ID3D11VertexShader*
d3dResult = Device->D3DDevice->CreateVertexShader(vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), 0, solidColorVSPointer);

if (FAILED(d3dResult))
{
    DXTRACE_MSG("Error creating the vertex shader!");

    if (vsBuffer)
    {
        vsBuffer->Release();
    }

    return;
}

D3D11_INPUT_ELEMENT_DESC solidColorLayout[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};

unsigned int totalLayoutElements = ARRAYSIZE(solidColorLayout);

pin_ptr<ID3D11InputLayout*> inputLayoutPointer;
inputLayoutPointer = &inputLayout_;
// Crea l'input layout e lo salva in inputLayout di tipo ID3D11InputLayout*
d3dResult = Device->D3DDevice->CreateInputLayout(solidColorLayout, totalLayoutElements, vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), inputLayoutPointer);

vsBuffer->Release();

if (FAILED(d3dResult))
{
    DXTRACE_MSG("Error creating the input layout!");
    return;
}

ID3DBlob* psBuffer = 0;
// Compila il pixel shader e salva il risultato in psBuffer
compileResult = CompileD3DShader("TextureMap.fx", "PS_Main", "ps_4_0", &psBuffer);

if (compileResult == false)
{
    DXTRACE_MSG("Error compiling pixel shader!");
    return;
}

pin_ptr<ID3D11PixelShader*> solidColorPSPointer;
solidColorPSPointer = &solidColorPS_;
// Crea il pixel shader e lo salva in solidColorPS_ di tipo ID3D11PixelShader*
d3dResult = Device->D3DDevice->CreatePixelShader(psBuffer->GetBufferPointer(), psBuffer->GetBufferSize(), 0, solidColorPSPointer);;

psBuffer->Release();

if (FAILED(d3dResult))
{
    DXTRACE_MSG("Error creating pixel shader!");
    return;
}

spriteBatch = new NativeSpritebatch(Device->D3DDevice);

// Spostare nel Begin successivamente
D3D11_BLEND_DESC blendDesc;
ZeroMemory(&blendDesc, sizeof(D3D11_BLEND_DESC));
blendDesc.AlphaToCoverageEnable = FALSE;
blendDesc.IndependentBlendEnable = FALSE;        
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };

pin_ptr<ID3D11BlendState*> alphaBlendStatePointer;
alphaBlendStatePointer = &alphaBlendState_;

Device->D3DDevice->CreateBlendState(&blendDesc, alphaBlendStatePointer);
Device->D3DContext->OMSetBlendState(alphaBlendState_, blendFactor, 0xFFFFFFFF);
}

inline SpriteBatch::~SpriteBatch()
{
}

inline void SpriteBatch::Begin()
{
if (beginInvoked_)
{
    throw gcnew SpriteBatchBeginEndException("Beetween two SpriteBatch begin methods you must call SpriteBacth End method!");
}

beginInvoked_ = true;

Device->D2DRenderTarget->BeginDraw();
Device->D2DRenderTarget->SetTransform(D2D1::IdentityMatrix());

if (componentList_ == nullptr)
{
    componentList_ = gcnew System::Collections::Generic::List<IDrawableComponent^>();
}
}

inline void SpriteBatch::Begin(SpriteSortMode sortMode, BlendState^ blendState)
{
Begin();

sortMode_ = sortMode;
}

inline void SpriteBatch::Draw(IDrawableComponent^ component)
{
if (component == nullptr)
{
    throw gcnew ArgumentNullException("Component argument is null, please ensure to initialize all components correctly!");
}
else
{
    componentList_->Add(component);
}
}

inline void SpriteBatch::DrawString(SpriteFont^ font, System::String^ text, Vector2 position)
{
RECT rc;
GetClientRect(Device->Window, &rc);

// Create a D2D rect that is the same size as the window.

D2D1_RECT_F layoutRect = D2D1::RectF(
    static_cast<FLOAT>(rc.left) / font->DpiScaleX,
    static_cast<FLOAT>(rc.top) / font->DpiScaleY,
    static_cast<FLOAT>(rc.right - rc.left) / font->DpiScaleX,
    static_cast<FLOAT>(rc.bottom - rc.top) / font->DpiScaleY
    );

// Use the DrawText method of the D2D render target interface to draw.

WCHAR textUnicode = Utilities::StringToWCHAR(text);
UINT32 cTextLength_ = (UINT32) wcslen(&textUnicode);

Device->D2DSolidColorBrush->SetColor(D2D1::ColorF(0,0,0,1));
Device->D2DSolidColorBrush->SetColor(D2D1::ColorF(255, 255, 255, 255));
Device->D2DRenderTarget->DrawText(&textUnicode, cTextLength_, font->DWriteTextFormat, layoutRect, Device->D2DSolidColorBrush);  
}

inline void SpriteBatch::End()
{
if (componentList_->Count)
{
    if (sortMode_ == SpriteSortMode::BackToFront)
    {
        SortByDepth();
    }

    for (int i = 0; i < componentList_->Count; i++)
    {
        Texture* text = componentList_[i]->Texture->TextureInfo;
        unsigned int stride = sizeof(VertexPos);
        unsigned int offset = 0;

        Device->D3DContext->IASetInputLayout(inputLayout_);

        if (componentList_[i]->Effect != SpriteEffect::None)
        {
            ID3D11Buffer* vertexBuffer;
            float width = (float)text->textureDesc_.Width;
            float height = (float)text->textureDesc_.Height;
            D3D11_BUFFER_DESC vertexDesc;
            ZeroMemory(&vertexDesc, sizeof(vertexDesc));
            vertexDesc.Usage = D3D11_USAGE_DYNAMIC;
            vertexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
            vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
            vertexDesc.ByteWidth = sizeof(VertexPos) * 6;
            D3D11_SUBRESOURCE_DATA resourceData;
            ZeroMemory(&resourceData, sizeof(resourceData));
            pin_ptr<ID3D11Buffer*> vertexBufferPointer;
            vertexBufferPointer = &vertexBuffer;

            switch (componentList_[i]->Effect)
            {
                case BSGameFramework::Graphics::SpriteEffect::FlipHorizontally:
                {
                    VertexPos verticesOne[] =
                    {
                        { XMFLOAT3(width,  height, 1.0f), XMFLOAT2(0.0f, 0.0f) },
                        { XMFLOAT3(width, 0.0f, 1.0f), XMFLOAT2(0.0f, 1.0f) },
                        { XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 1.0f) },

                        { XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 1.0f) },
                        { XMFLOAT3(0.0f, height, 1.0f), XMFLOAT2(1.0f, 0.0f) },
                        { XMFLOAT3(width, height, 1.0f), XMFLOAT2(0.0f, 0.0f) },
                    };

                    resourceData.pSysMem = verticesOne;

                    Device->D3DDevice->CreateBuffer(&vertexDesc, &resourceData, vertexBufferPointer);

                    Device->D3DContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);

                    break;
                }

                case BSGameFramework::Graphics::SpriteEffect::FlipVertically:
                {
                    VertexPos verticesTwo[] =
                    {
                        { XMFLOAT3(width,  height, 1.0f), XMFLOAT2(1.0f, 1.0f) },
                        { XMFLOAT3(width, 0.0f, 1.0f), XMFLOAT2(1.0f, 0.0f) },
                        { XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(0.0f, 0.0f) },

                        { XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(0.0f, 0.0f) },
                        { XMFLOAT3(0.0f, height, 1.0f), XMFLOAT2(0.0f, 1.0f) },
                        { XMFLOAT3(width, height, 1.0f), XMFLOAT2(1.0f, 1.0f) },
                    };

                    resourceData.pSysMem = verticesTwo;

                    Device->D3DDevice->CreateBuffer(&vertexDesc, &resourceData, vertexBufferPointer);

                    Device->D3DContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);

                    break;
                }
            }
        }
        else
        {
            Device->D3DContext->IASetVertexBuffers(0, 1, &text->vertexBuffer_, &stride, &offset);
        }

        Device->D3DContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

        Device->D3DContext->VSSetShader(solidColorVS_, 0, 0);
        Device->D3DContext->PSSetShader(solidColorPS_, 0, 0);
        Device->D3DContext->PSSetShaderResources(0, 1, &text->colorMap_);
        Device->D3DContext->PSSetSamplers(0, 1, &text->colorMapSampler_);

        spriteBatch->SetTranspose(Device->D3DContext, text, Device->WindowWidth, Device->WindowHeight, componentList_[i]->Position.X, componentList_[i]->Position.Y,
            componentList_[i]->Scale.X, componentList_[i]->Scale.Y, componentList_[i]->Rotation);

        Device->D3DContext->Draw(6, 0);
    }
}

Device->D2DRenderTarget->EndDraw();
componentList_->Clear();
beginInvoked_ = false;
sortMode_ = SpriteSortMode::Deferred;
}

inline bool SpriteBatch::CompileD3DShader(char* filePath, char* entry, char* shaderModel, ID3DBlob** buffer)
{
DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;

#if defined(DEBUG) || defined(_DEBUG)
shaderFlags |= D3DCOMPILE_DEBUG;
#endif

ID3DBlob* errorBuffer = 0;
HRESULT result;

result = D3DX11CompileFromFile(filePath, 0, 0, entry, shaderModel, shaderFlags, 0, 0, buffer, &errorBuffer, 0);

if (FAILED(result))
{
    if (errorBuffer != 0)
    {
        OutputDebugStringA((char*)errorBuffer->GetBufferPointer());
        errorBuffer->Release();
    }

    return false;
}

if (errorBuffer != 0)
{
    errorBuffer->Release();
}

return true;
}

inline void SpriteBatch::SortByDepth()
{
for (int i = 0; i < componentList_->Count - 1; i++)
{
    for (int j = 1; j < componentList_->Count; j++)
    {
        if (componentList_[i]->ZIndex < componentList_[j]->ZIndex)
        {
            IDrawableComponent^ component = componentList_[i];
            componentList_[i] = componentList_[j];
            componentList_[j] = component;
        }
    }
}
}
tDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
texture->QueryInterface<IDXGISurface>(&dxgiSurface);
dxgiSurface->QueryInterface<IDXGIResource>(&dxgiResource);