WinRT: added render-to-texture support for D3D 11.1, via SDL_SetRenderTarget
This commit is contained in:
parent
b74856f7b7
commit
e40e111591
2 changed files with 98 additions and 38 deletions
|
@ -57,12 +57,12 @@ static void D3D11_WindowEvent(SDL_Renderer * renderer,
|
||||||
const SDL_WindowEvent *event);
|
const SDL_WindowEvent *event);
|
||||||
static int D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
static int D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
static int D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
static int D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * rect, const void *pixels,
|
const SDL_Rect * rect, const void *srcPixels,
|
||||||
int pitch);
|
int srcPitch);
|
||||||
static int D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
static int D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * rect, void **pixels, int *pitch);
|
const SDL_Rect * rect, void **pixels, int *pitch);
|
||||||
static void D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
static void D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
//static int D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
|
static int D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
static int D3D11_UpdateViewport(SDL_Renderer * renderer);
|
static int D3D11_UpdateViewport(SDL_Renderer * renderer);
|
||||||
static int D3D11_RenderClear(SDL_Renderer * renderer);
|
static int D3D11_RenderClear(SDL_Renderer * renderer);
|
||||||
static int D3D11_RenderDrawPoints(SDL_Renderer * renderer,
|
static int D3D11_RenderDrawPoints(SDL_Renderer * renderer,
|
||||||
|
@ -93,7 +93,11 @@ extern "C" SDL_RenderDriver D3D11_RenderDriver = {
|
||||||
D3D11_CreateRenderer,
|
D3D11_CreateRenderer,
|
||||||
{
|
{
|
||||||
"direct3d 11.1",
|
"direct3d 11.1",
|
||||||
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), // flags. see SDL_RendererFlags
|
(
|
||||||
|
SDL_RENDERER_ACCELERATED |
|
||||||
|
SDL_RENDERER_PRESENTVSYNC |
|
||||||
|
SDL_RENDERER_TARGETTEXTURE
|
||||||
|
), // flags. see SDL_RendererFlags
|
||||||
2, // num_texture_formats
|
2, // num_texture_formats
|
||||||
{ // texture_formats
|
{ // texture_formats
|
||||||
SDL_PIXELFORMAT_RGB888,
|
SDL_PIXELFORMAT_RGB888,
|
||||||
|
@ -165,7 +169,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->UpdateTexture = D3D11_UpdateTexture;
|
renderer->UpdateTexture = D3D11_UpdateTexture;
|
||||||
renderer->LockTexture = D3D11_LockTexture;
|
renderer->LockTexture = D3D11_LockTexture;
|
||||||
renderer->UnlockTexture = D3D11_UnlockTexture;
|
renderer->UnlockTexture = D3D11_UnlockTexture;
|
||||||
//renderer->SetRenderTarget = D3D11_SetRenderTarget;
|
renderer->SetRenderTarget = D3D11_SetRenderTarget;
|
||||||
renderer->UpdateViewport = D3D11_UpdateViewport;
|
renderer->UpdateViewport = D3D11_UpdateViewport;
|
||||||
renderer->RenderClear = D3D11_RenderClear;
|
renderer->RenderClear = D3D11_RenderClear;
|
||||||
renderer->RenderDrawPoints = D3D11_RenderDrawPoints;
|
renderer->RenderDrawPoints = D3D11_RenderDrawPoints;
|
||||||
|
@ -178,7 +182,6 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
renderer->DestroyTexture = D3D11_DestroyTexture;
|
renderer->DestroyTexture = D3D11_DestroyTexture;
|
||||||
renderer->DestroyRenderer = D3D11_DestroyRenderer;
|
renderer->DestroyRenderer = D3D11_DestroyRenderer;
|
||||||
renderer->info = D3D11_RenderDriver.info;
|
renderer->info = D3D11_RenderDriver.info;
|
||||||
renderer->info.flags = SDL_RENDERER_ACCELERATED;
|
|
||||||
renderer->driverdata = data;
|
renderer->driverdata = data;
|
||||||
|
|
||||||
// HACK: make sure the SDL_Renderer references the SDL_Window data now, in
|
// HACK: make sure the SDL_Renderer references the SDL_Window data now, in
|
||||||
|
@ -752,7 +755,7 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
|
||||||
result = data->d3dDevice->CreateRenderTargetView(
|
result = data->d3dDevice->CreateRenderTargetView(
|
||||||
backBuffer.Get(),
|
backBuffer.Get(),
|
||||||
nullptr,
|
nullptr,
|
||||||
&data->renderTargetView
|
&data->mainRenderTargetView
|
||||||
);
|
);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
WIN_SetErrorFromHRESULT(__FUNCTION__, result);
|
WIN_SetErrorFromHRESULT(__FUNCTION__, result);
|
||||||
|
@ -781,7 +784,7 @@ D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
ID3D11RenderTargetView* nullViews[] = {nullptr};
|
ID3D11RenderTargetView* nullViews[] = {nullptr};
|
||||||
data->d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
|
data->d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
|
||||||
data->renderTargetView = nullptr;
|
data->mainRenderTargetView = nullptr;
|
||||||
data->d3dContext->Flush();
|
data->d3dContext->Flush();
|
||||||
result = D3D11_CreateWindowSizeDependentResources(renderer);
|
result = D3D11_CreateWindowSizeDependentResources(renderer);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
|
@ -860,11 +863,22 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
textureDesc.Format = textureFormat;
|
textureDesc.Format = textureFormat;
|
||||||
textureDesc.SampleDesc.Count = 1;
|
textureDesc.SampleDesc.Count = 1;
|
||||||
textureDesc.SampleDesc.Quality = 0;
|
textureDesc.SampleDesc.Quality = 0;
|
||||||
textureDesc.Usage = D3D11_USAGE_DYNAMIC;
|
|
||||||
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
||||||
textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
|
||||||
textureDesc.MiscFlags = 0;
|
textureDesc.MiscFlags = 0;
|
||||||
|
|
||||||
|
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
|
||||||
|
textureDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
|
textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||||
|
} else {
|
||||||
|
textureDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
textureDesc.CPUAccessFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
|
||||||
|
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||||
|
} else {
|
||||||
|
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Fill the texture with a non-black color, for debugging purposes:
|
// Fill the texture with a non-black color, for debugging purposes:
|
||||||
const int numPixels = textureDesc.Width * textureDesc.Height;
|
const int numPixels = textureDesc.Width * textureDesc.Height;
|
||||||
|
@ -893,6 +907,23 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (texture->access & SDL_TEXTUREACCESS_TARGET) {
|
||||||
|
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||||
|
renderTargetViewDesc.Format = textureDesc.Format;
|
||||||
|
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||||
|
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||||
|
|
||||||
|
result = rendererData->d3dDevice->CreateRenderTargetView(
|
||||||
|
textureData->mainTexture.Get(),
|
||||||
|
&renderTargetViewDesc,
|
||||||
|
&textureData->mainTextureRenderTargetView);
|
||||||
|
if (FAILED(result)) {
|
||||||
|
D3D11_DestroyTexture(renderer, texture);
|
||||||
|
WIN_SetErrorFromHRESULT(__FUNCTION__, result);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
|
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
|
||||||
resourceViewDesc.Format = textureDesc.Format;
|
resourceViewDesc.Format = textureDesc.Format;
|
||||||
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
@ -931,40 +962,33 @@ D3D11_DestroyTexture(SDL_Renderer * renderer,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * rect, const void *pixels,
|
const SDL_Rect * rect, const void * srcPixels,
|
||||||
int pitch)
|
int srcPitch)
|
||||||
{
|
{
|
||||||
D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
|
// Lock the texture, retrieving a buffer to write pixel data to:
|
||||||
D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
|
void * destPixels = NULL;
|
||||||
HRESULT result = S_OK;
|
int destPitch = 0;
|
||||||
|
if (D3D11_LockTexture(renderer, texture, rect, &destPixels, &destPitch) != 0) {
|
||||||
D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
|
// An error is already set. Attach some info to it, then return to
|
||||||
result = rendererData->d3dContext->Map(
|
// the caller.
|
||||||
textureData->mainTexture.Get(),
|
std::string errorMessage = string(__FUNCTION__ ", Lock Texture Failed: ") + SDL_GetError();
|
||||||
0,
|
SDL_SetError(errorMessage.c_str());
|
||||||
D3D11_MAP_WRITE_DISCARD,
|
|
||||||
0,
|
|
||||||
&textureMemory
|
|
||||||
);
|
|
||||||
if (FAILED(result)) {
|
|
||||||
WIN_SetErrorFromHRESULT(__FUNCTION__, result);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy pixel data to the locked texture's memory:
|
// Copy pixel data to the locked texture's memory:
|
||||||
for (int y = 0; y < rect->h; ++y) {
|
for (int y = 0; y < rect->h; ++y) {
|
||||||
memcpy(
|
memcpy(
|
||||||
((Uint8 *)textureMemory.pData) + (textureMemory.RowPitch * y),
|
((Uint8 *)destPixels) + (destPitch * y),
|
||||||
((Uint8 *)pixels) + (pitch * y),
|
((Uint8 *)srcPixels) + (srcPitch * y),
|
||||||
pitch
|
srcPitch
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up a bit, then commit the texture's memory back to Direct3D:
|
// Commit the texture's memory back to Direct3D:
|
||||||
rendererData->d3dContext->Unmap(
|
D3D11_UnlockTexture(renderer, texture);
|
||||||
textureData->mainTexture.Get(),
|
|
||||||
0);
|
|
||||||
|
|
||||||
|
// Return to the caller:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,6 +1080,29 @@ D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
textureData->lockedTexturePosition = XMINT2(0, 0);
|
textureData->lockedTexturePosition = XMINT2(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
|
{
|
||||||
|
D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
|
||||||
|
|
||||||
|
if (texture == NULL) {
|
||||||
|
rendererData->currentOffscreenRenderTargetView = nullptr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11_TextureData *textureData = (D3D11_TextureData *) texture->driverdata;
|
||||||
|
|
||||||
|
if (!textureData->mainTextureRenderTargetView) {
|
||||||
|
std::string errorMessage = string(__FUNCTION__) + ": specified texture is not a render target";
|
||||||
|
SDL_SetError(errorMessage.c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rendererData->currentOffscreenRenderTargetView = textureData->mainTextureRenderTargetView;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
D3D11_UpdateViewport(SDL_Renderer * renderer)
|
D3D11_UpdateViewport(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
|
@ -1177,6 +1224,17 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ComPtr<ID3D11RenderTargetView> &
|
||||||
|
D3D11_GetCurrentRenderTargetView(SDL_Renderer * renderer)
|
||||||
|
{
|
||||||
|
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
|
||||||
|
if (data->currentOffscreenRenderTargetView) {
|
||||||
|
return data->currentOffscreenRenderTargetView;
|
||||||
|
} else {
|
||||||
|
return data->mainRenderTargetView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
D3D11_RenderClear(SDL_Renderer * renderer)
|
D3D11_RenderClear(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
|
@ -1188,7 +1246,7 @@ D3D11_RenderClear(SDL_Renderer * renderer)
|
||||||
(renderer->a / 255.0f)
|
(renderer->a / 255.0f)
|
||||||
};
|
};
|
||||||
data->d3dContext->ClearRenderTargetView(
|
data->d3dContext->ClearRenderTargetView(
|
||||||
data->renderTargetView.Get(),
|
D3D11_GetCurrentRenderTargetView(renderer).Get(),
|
||||||
colorRGBA
|
colorRGBA
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1250,7 +1308,7 @@ D3D11_RenderStartDrawOp(SDL_Renderer * renderer)
|
||||||
|
|
||||||
rendererData->d3dContext->OMSetRenderTargets(
|
rendererData->d3dContext->OMSetRenderTargets(
|
||||||
1,
|
1,
|
||||||
rendererData->renderTargetView.GetAddressOf(),
|
D3D11_GetCurrentRenderTargetView(renderer).GetAddressOf(),
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1695,7 +1753,7 @@ D3D11_RenderPresent(SDL_Renderer * renderer)
|
||||||
// Discard the contents of the render target.
|
// Discard the contents of the render target.
|
||||||
// This is a valid operation only when the existing contents will be entirely
|
// This is a valid operation only when the existing contents will be entirely
|
||||||
// overwritten. If dirty or scroll rects are used, this call should be removed.
|
// overwritten. If dirty or scroll rects are used, this call should be removed.
|
||||||
data->d3dContext->DiscardView(data->renderTargetView.Get());
|
data->d3dContext->DiscardView(data->mainRenderTargetView.Get());
|
||||||
|
|
||||||
// If the device was removed either by a disconnect or a driver upgrade, we
|
// If the device was removed either by a disconnect or a driver upgrade, we
|
||||||
// must recreate all device resources.
|
// must recreate all device resources.
|
||||||
|
|
|
@ -37,7 +37,8 @@ typedef struct
|
||||||
Microsoft::WRL::ComPtr<ID3D11Device1> d3dDevice;
|
Microsoft::WRL::ComPtr<ID3D11Device1> d3dDevice;
|
||||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext1> d3dContext;
|
Microsoft::WRL::ComPtr<ID3D11DeviceContext1> d3dContext;
|
||||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
|
Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
|
||||||
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> renderTargetView;
|
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> mainRenderTargetView;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> currentOffscreenRenderTargetView;
|
||||||
Microsoft::WRL::ComPtr<ID3D11InputLayout> inputLayout;
|
Microsoft::WRL::ComPtr<ID3D11InputLayout> inputLayout;
|
||||||
Microsoft::WRL::ComPtr<ID3D11Buffer> vertexBuffer;
|
Microsoft::WRL::ComPtr<ID3D11Buffer> vertexBuffer;
|
||||||
Microsoft::WRL::ComPtr<ID3D11VertexShader> vertexShader;
|
Microsoft::WRL::ComPtr<ID3D11VertexShader> vertexShader;
|
||||||
|
@ -67,6 +68,7 @@ typedef struct
|
||||||
{
|
{
|
||||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> mainTexture;
|
Microsoft::WRL::ComPtr<ID3D11Texture2D> mainTexture;
|
||||||
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> mainTextureResourceView;
|
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> mainTextureResourceView;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> mainTextureRenderTargetView;
|
||||||
SDL_PixelFormat * pixelFormat;
|
SDL_PixelFormat * pixelFormat;
|
||||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
|
Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
|
||||||
DirectX::XMINT2 lockedTexturePosition;
|
DirectX::XMINT2 lockedTexturePosition;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue