WinRT: implemented SDL_RenderReadPixels in Direct3D 11.1

This commit is contained in:
David Ludwig 2013-04-01 21:34:47 -04:00
parent df42edd5e1
commit 33ab98ccee

View file

@ -76,8 +76,8 @@ static int D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
//static int D3D11_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
// const SDL_Rect * srcrect, const SDL_FRect * dstrect,
// const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip);
//static int D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
// Uint32 format, void * pixels, int pitch);
static int D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch);
static void D3D11_RenderPresent(SDL_Renderer * renderer);
static void D3D11_DestroyTexture(SDL_Renderer * renderer,
SDL_Texture * texture);
@ -105,6 +105,32 @@ extern "C" SDL_RenderDriver D3D11_RenderDriver = {
};
static Uint32
DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) {
switch (dxgiFormat) {
case DXGI_FORMAT_B8G8R8A8_UNORM:
return SDL_PIXELFORMAT_ARGB8888;
case DXGI_FORMAT_B8G8R8X8_UNORM:
return SDL_PIXELFORMAT_RGB888;
default:
return SDL_PIXELFORMAT_UNKNOWN;
}
}
static DXGI_FORMAT
SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
{
switch (sdlFormat) {
case SDL_PIXELFORMAT_ARGB8888:
return DXGI_FORMAT_B8G8R8A8_UNORM;
case SDL_PIXELFORMAT_RGB888:
return DXGI_FORMAT_B8G8R8X8_UNORM;
default:
return DXGI_FORMAT_UNKNOWN;
}
}
//typedef struct
//{
// float x, y, z;
@ -148,7 +174,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->RenderFillRects = D3D11_RenderFillRects;
renderer->RenderCopy = D3D11_RenderCopy;
//renderer->RenderCopyEx = D3D11_RenderCopyEx;
//renderer->RenderReadPixels = D3D11_RenderReadPixels;
renderer->RenderReadPixels = D3D11_RenderReadPixels;
renderer->RenderPresent = D3D11_RenderPresent;
renderer->DestroyTexture = D3D11_DestroyTexture;
renderer->DestroyRenderer = D3D11_DestroyRenderer;
@ -206,10 +232,10 @@ D3D11_ReadShaderContents(const wstring & shaderName, vector<char> & out)
wstring fileName;
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
fileName = SDL_WinRTGetFileSystemPath(SDL_WINRT_PATH_INSTALLED_LOCATION);
fileName = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_INSTALLED_LOCATION);
fileName += L"\\SDL_VS2012_WinRT\\";
#elif WINAPI_FAMILY == WINAPI_PHONE_APP
fileName = SDL_WinRTGetFileSystemPath(SDL_WINRT_PATH_INSTALLED_LOCATION);
fileName = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_INSTALLED_LOCATION);
fileName += L"\\";
#endif
// WinRT, TODO: test Direct3D 11.1 shader loading on Win32
@ -811,19 +837,11 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
D3D11_TextureData *textureData;
HRESULT result;
DXGI_FORMAT textureFormat = DXGI_FORMAT_UNKNOWN;
switch (texture->format) {
case SDL_PIXELFORMAT_ARGB8888:
textureFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
break;
case SDL_PIXELFORMAT_RGB888:
textureFormat = DXGI_FORMAT_B8G8R8X8_UNORM;
break;
default:
SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
__FUNCTION__, texture->format);
return -1;
DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
if (textureFormat == SDL_PIXELFORMAT_UNKNOWN) {
SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
__FUNCTION__, texture->format);
return -1;
}
textureData = new D3D11_TextureData;
@ -1460,6 +1478,101 @@ D3D11_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
return 0;
}
static int
D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch)
{
D3D11_RenderData * data = (D3D11_RenderData *) renderer->driverdata;
HRESULT result = S_OK;
// Retrieve a pointer to the back buffer:
ComPtr<ID3D11Texture2D> backBuffer;
result = data->swapChain->GetBuffer(
0,
__uuidof(ID3D11Texture2D),
&backBuffer
);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", Get Back Buffer", result);
return -1;
}
// Create a staging texture to copy the screen's data to:
ComPtr<ID3D11Texture2D> stagingTexture;
D3D11_TEXTURE2D_DESC stagingTextureDesc;
backBuffer->GetDesc(&stagingTextureDesc);
stagingTextureDesc.Width = rect->w;
stagingTextureDesc.Height = rect->h;
stagingTextureDesc.BindFlags = 0;
stagingTextureDesc.MiscFlags = 0;
stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
result = data->d3dDevice->CreateTexture2D(
&stagingTextureDesc,
NULL,
&stagingTexture);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", Create Staging Texture", result);
return -1;
}
// Copy the desired portion of the back buffer to the staging texture:
D3D11_BOX srcBox;
srcBox.left = rect->x;
srcBox.right = rect->x + rect->w;
srcBox.top = rect->y;
srcBox.bottom = rect->y + rect->h;
srcBox.front = 0;
srcBox.back = 1;
data->d3dContext->CopySubresourceRegion(
stagingTexture.Get(),
D3D11CalcSubresource(0, 0, 0),
0, 0, 0,
backBuffer.Get(),
D3D11CalcSubresource(0, 0, 0),
&srcBox);
// Map the staging texture's data to CPU-accessible memory:
D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
result = data->d3dContext->Map(
stagingTexture.Get(),
D3D11CalcSubresource(0, 0, 0),
D3D11_MAP_READ,
0,
&textureMemory);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(__FUNCTION__ ", Map Staging Texture to CPU Memory", result);
return -1;
}
// Copy the data into the desired buffer, converting pixels to the
// desired format at the same time:
if (SDL_ConvertPixels(
rect->w, rect->h,
DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
textureMemory.pData,
textureMemory.RowPitch,
format,
pixels,
pitch) != 0)
{
// When SDL_ConvertPixels fails, it'll have already set the format.
// Get the error message, and attach some extra data to it.
std::string errorMessage = string(__FUNCTION__ ", Convert Pixels failed: ") + SDL_GetError();
SDL_SetError(errorMessage.c_str());
return -1;
}
// Unmap the texture:
data->d3dContext->Unmap(
stagingTexture.Get(),
D3D11CalcSubresource(0, 0, 0));
// All done. The staging texture will be cleaned up in it's container
// ComPtr<>'s destructor.
return 0;
}
static void
D3D11_RenderPresent(SDL_Renderer * renderer)
{