From 873bcbfecf7243523e64f544f6062d94c5ae7f08 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2023 00:04:45 -0700 Subject: [PATCH] Added SDL_GetTextureDXGIResource() to get the DXGI resource associated with a render texture. Also switched the D3D11 and D3D12 renderers to use real NV12 textures for NV12 data. The combination of these two changes allows us to implement 0-copy video decode and playback for D3D11 in testffmpeg without any access to the renderer internals. --- include/SDL3/SDL_render.h | 17 +++ src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/render/SDL_render.c | 13 ++ src/render/SDL_sysrender.h | 2 + src/render/direct3d11/SDL_render_d3d11.c | 187 ++++++++++++++++++----- src/render/direct3d12/SDL_render_d3d12.c | 138 +++++++++-------- test/testffmpeg.c | 166 ++++---------------- test/testoverlay.c | 77 +++++++--- 10 files changed, 337 insertions(+), 266 deletions(-) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index d38484a1c2327..bbd4516b782be 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -404,6 +404,23 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, U */ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface); +typedef struct IDXGIResource IDXGIResource; +/** + * Get the DXGI resource associated with a texture. + * + * This is available when using the direct3d11 and direct3d12 renderers. + * + * Once you are done using the resource, you should release it to avoid a + * resource leak. + * + * \param texture the texture from which to get the associated resource + * \returns the DXGI resource associated with given texture or NULL if it is + * not available; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC IDXGIResource* SDLCALL SDL_GetTextureDXGIResource(SDL_Texture *texture); + /** * Query the attributes of a texture. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 54467c5f5161b..89bf3aff6e5fe 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -907,6 +907,7 @@ SDL3_0.0.0 { SDL_SetAudioStreamFrequencyRatio; SDL_SetAudioPostmixCallback; SDL_GetAudioStreamQueued; + SDL_GetTextureDXGIResource; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index da300e291329c..e7b16789b90da 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -932,3 +932,4 @@ #define SDL_SetAudioStreamFrequencyRatio SDL_SetAudioStreamFrequencyRatio_REAL #define SDL_SetAudioPostmixCallback SDL_SetAudioPostmixCallback_REAL #define SDL_GetAudioStreamQueued SDL_GetAudioStreamQueued_REAL +#define SDL_GetTextureDXGIResource SDL_GetTextureDXGIResource_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index a4ffe8d12c677..6bb5f63da287f 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -978,3 +978,4 @@ SDL_DYNAPI_PROC(float,SDL_GetAudioStreamFrequencyRatio,(SDL_AudioStream *a),(a), SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFrequencyRatio,(SDL_AudioStream *a, float b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetAudioPostmixCallback,(SDL_AudioDeviceID a, SDL_AudioPostmixCallback b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetAudioStreamQueued,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(IDXGIResource*,SDL_GetTextureDXGIResource,(SDL_Texture *a),(a),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 1df0349806d3d..9e9fc1629bdf7 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -4186,6 +4186,19 @@ void *SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer) return NULL; } +IDXGIResource *SDL_GetTextureDXGIResource(SDL_Texture *texture) +{ + SDL_Renderer *renderer; + + CHECK_TEXTURE_MAGIC(texture, NULL); + renderer = texture->renderer; + if (renderer && renderer->GetTextureDXGIResource) { + return renderer->GetTextureDXGIResource(texture); + } + SDL_Unsupported(); + return NULL; +} + static SDL_BlendMode SDL_GetShortBlendMode(SDL_BlendMode blendMode) { if (blendMode == SDL_BLENDMODE_NONE_FULL) { diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index c7033f8f26cf3..b1cb2e8e29e1d 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -212,6 +212,8 @@ struct SDL_Renderer void *(*GetMetalLayer)(SDL_Renderer *renderer); void *(*GetMetalCommandEncoder)(SDL_Renderer *renderer); + IDXGIResource *(*GetTextureDXGIResource)(SDL_Texture *texture); + /* The current renderer info */ SDL_RendererInfo info; diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 5e1b825b9eb6f..5df9049e065a7 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -102,7 +102,6 @@ typedef struct /* NV12 texture support */ SDL_bool nv12; - ID3D11Texture2D *mainTextureNV; ID3D11ShaderResourceView *mainTextureResourceViewNV; Uint8 *pixels; @@ -187,6 +186,7 @@ static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0 #if defined(__WINRT__) && NTDDI_VERSION > NTDDI_WIN8 static const GUID SDL_IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } }; #endif +static const GUID SDL_IID_IDXGIResource = { 0x035f3ab4, 0x482e, 0x4e50, { 0xb4, 0x1f, 0x8a, 0x7f, 0x8b, 0xd8, 0x96, 0x0b } }; static const GUID SDL_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } }; static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } }; static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } }; @@ -208,7 +208,7 @@ Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) } } -static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat) +static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 sdlFormat) { switch (sdlFormat) { case SDL_PIXELFORMAT_ARGB8888: @@ -217,8 +217,26 @@ static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat) return DXGI_FORMAT_B8G8R8X8_UNORM; case SDL_PIXELFORMAT_YV12: case SDL_PIXELFORMAT_IYUV: - case SDL_PIXELFORMAT_NV12: /* For the Y texture */ - case SDL_PIXELFORMAT_NV21: /* For the Y texture */ + return DXGI_FORMAT_R8_UNORM; + case SDL_PIXELFORMAT_NV12: + case SDL_PIXELFORMAT_NV21: + return DXGI_FORMAT_NV12; + default: + return DXGI_FORMAT_UNKNOWN; + } +} + +static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 sdlFormat) +{ + switch (sdlFormat) { + case SDL_PIXELFORMAT_ARGB8888: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case SDL_PIXELFORMAT_XRGB8888: + return DXGI_FORMAT_B8G8R8X8_UNORM; + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + case SDL_PIXELFORMAT_NV12: /* For the Y texture */ + case SDL_PIXELFORMAT_NV21: /* For the Y texture */ return DXGI_FORMAT_R8_UNORM; default: return DXGI_FORMAT_UNKNOWN; @@ -850,8 +868,7 @@ static void D3D11_ReleaseMainRenderTargetView(SDL_Renderer *renderer) static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer); -HRESULT -D3D11_HandleDeviceLost(SDL_Renderer *renderer) +static HRESULT D3D11_HandleDeviceLost(SDL_Renderer *renderer) { HRESULT result = S_OK; @@ -1055,7 +1072,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData; HRESULT result; - DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format); + DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format); D3D11_TEXTURE2D_DESC textureDesc; D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; @@ -1131,29 +1148,13 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } } - if (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21) { - D3D11_TEXTURE2D_DESC nvTextureDesc = textureDesc; - textureData->nv12 = SDL_TRUE; - - nvTextureDesc.Format = DXGI_FORMAT_R8G8_UNORM; - nvTextureDesc.Width = (textureDesc.Width + 1) / 2; - nvTextureDesc.Height = (textureDesc.Height + 1) / 2; - - result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, - &nvTextureDesc, - NULL, - &textureData->mainTextureNV); - if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); - } } #endif /* SDL_HAVE_YUV */ SDL_zero(resourceViewDesc); - resourceViewDesc.Format = textureDesc.Format; + resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format); resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; resourceViewDesc.Texture2D.MostDetailedMip = 0; resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels; @@ -1191,7 +1192,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM; result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice, - (ID3D11Resource *)textureData->mainTextureNV, + (ID3D11Resource *)textureData->mainTexture, &nvResourceViewDesc, &textureData->mainTextureResourceViewNV); if (FAILED(result)) { @@ -1239,7 +1240,6 @@ static void D3D11_DestroyTexture(SDL_Renderer *renderer, SAFE_RELEASE(data->mainTextureResourceViewU); SAFE_RELEASE(data->mainTextureV); SAFE_RELEASE(data->mainTextureResourceViewV); - SAFE_RELEASE(data->mainTextureNV); SAFE_RELEASE(data->mainTextureResourceViewNV); SDL_free(data->pixels); #endif @@ -1286,6 +1286,11 @@ static int D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Tex return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result); } + if (stagingTextureDesc.Format == DXGI_FORMAT_NV12) { + /* Copy the UV plane as well */ + h += (h + 1) / 2; + } + src = (const Uint8 *)pixels; dst = textureMemory.pData; length = w * bpp; @@ -1355,15 +1360,6 @@ static int D3D11_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, return -1; } } - - if (textureData->nv12) { - /* Skip to the correct offset into the next texture */ - srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch); - - if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, srcPixels, 2 * ((srcPitch + 1) / 2)) < 0) { - return -1; - } - } #endif /* SDL_HAVE_YUV */ return 0; } @@ -1401,18 +1397,110 @@ static int D3D11_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture, { D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; + ID3D11Texture2D *stagingTexture; + const Uint8 *src; + Uint8 *dst; + int w, h, row; + UINT length; + HRESULT result; + D3D11_TEXTURE2D_DESC stagingTextureDesc; + D3D11_MAPPED_SUBRESOURCE textureMemory; if (textureData == NULL) { return SDL_SetError("Texture is not currently available"); } - if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) { - return -1; + w = rect->w; + h = rect->h; + + /* Create a 'staging' texture, which will be used to write to a portion of the main texture. */ + ID3D11Texture2D_GetDesc(textureData->mainTexture, &stagingTextureDesc); + stagingTextureDesc.Width = w; + stagingTextureDesc.Height = h; + stagingTextureDesc.BindFlags = 0; + stagingTextureDesc.MiscFlags = 0; + stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + stagingTextureDesc.Usage = D3D11_USAGE_STAGING; + result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, + &stagingTextureDesc, + NULL, + &stagingTexture); + if (FAILED(result)) { + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result); } - if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, UVplane, UVpitch) < 0) { - return -1; + /* Get a write-only pointer to data in the staging texture: */ + result = ID3D11DeviceContext_Map(rendererData->d3dContext, + (ID3D11Resource *)stagingTexture, + 0, + D3D11_MAP_WRITE, + 0, + &textureMemory); + if (FAILED(result)) { + SAFE_RELEASE(stagingTexture); + return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result); + } + + src = Yplane; + dst = textureMemory.pData; + length = w; + if (length == (UINT)Ypitch && length == textureMemory.RowPitch) { + SDL_memcpy(dst, src, (size_t)length * rect->h); + dst += length * rect->h; + } else { + if (length > (UINT)Ypitch) { + length = Ypitch; + } + if (length > textureMemory.RowPitch) { + length = textureMemory.RowPitch; + } + for (row = 0; row < h; ++row) { + SDL_memcpy(dst, src, length); + src += Ypitch; + dst += textureMemory.RowPitch; + } + } + + /* Adjust dimensions for the UV plane */ + w = ((w + 1) / 2) * 2; + h = ((h + 1) / 2); + + src = UVplane; + length = w; + if (length == (UINT)UVpitch && length == textureMemory.RowPitch) { + SDL_memcpy(dst, src, (size_t)length * h); + } else { + if (length > (UINT)UVpitch) { + length = UVpitch; + } + if (length > textureMemory.RowPitch) { + length = textureMemory.RowPitch; + } + for (row = 0; row < h; ++row) { + SDL_memcpy(dst, src, length); + src += UVpitch; + dst += textureMemory.RowPitch; + } } + + /* Commit the pixel buffer's changes back to the staging texture: */ + ID3D11DeviceContext_Unmap(rendererData->d3dContext, + (ID3D11Resource *)stagingTexture, + 0); + + /* Copy the staging texture's contents back to the texture: */ + ID3D11DeviceContext_CopySubresourceRegion(rendererData->d3dContext, + (ID3D11Resource *)textureData->mainTexture, + 0, + rect->x, + rect->y, + 0, + (ID3D11Resource *)stagingTexture, + 0, + NULL); + + SAFE_RELEASE(stagingTexture); + return 0; } #endif @@ -1548,6 +1636,26 @@ static void D3D11_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR; } +static IDXGIResource *D3D11_GetTextureDXGIResource(SDL_Texture *texture) +{ + D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; + IDXGIResource *resource = NULL; + HRESULT result; + + if (textureData == NULL || textureData->mainTexture == NULL) { + SDL_SetError("Texture is not currently available"); + return NULL; + } + + + result = ID3D11Texture2D_QueryInterface(textureData->mainTexture, &SDL_IID_IDXGIResource, (void **)&resource); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("GetTextureDXGIResource"), result); + return NULL; + } + return resource; +} + static int D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; @@ -2324,6 +2432,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->LockTexture = D3D11_LockTexture; renderer->UnlockTexture = D3D11_UnlockTexture; renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode; + renderer->GetTextureDXGIResource = D3D11_GetTextureDXGIResource; renderer->SetRenderTarget = D3D11_SetRenderTarget; renderer->QueueSetViewport = D3D11_QueueSetViewport; renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index 43ce78b4c2e0d..161bc700bd210 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -123,9 +123,7 @@ typedef struct /* NV12 texture support */ SDL_bool nv12; - ID3D12Resource *mainTextureNV; D3D12_CPU_DESCRIPTOR_HANDLE mainTextureResourceViewNV; - D3D12_RESOURCE_STATES mainResourceStateNV; SIZE_T mainSRVIndexNV; Uint8 *pixels; @@ -257,6 +255,7 @@ static const GUID SDL_IID_ID3D12DescriptorHeap = { 0x8efb471d, 0x616c, 0x4f49, { static const GUID SDL_IID_ID3D12CommandAllocator = { 0x6102dee4, 0xaf59, 0x4b09, { 0xb9, 0x99, 0xb4, 0x4d, 0x73, 0xf0, 0x9b, 0x24 } }; static const GUID SDL_IID_ID3D12GraphicsCommandList2 = { 0x38C3E585, 0xFF17, 0x412C, { 0x91, 0x50, 0x4F, 0xC6, 0xF9, 0xD7, 0x2A, 0x28 } }; static const GUID SDL_IID_ID3D12Fence = { 0x0a753dcf, 0xc4d8, 0x4b91, { 0xad, 0xf6, 0xbe, 0x5a, 0x60, 0xd9, 0x5a, 0x76 } }; +static const GUID SDL_IID_IDXGIResource = { 0x035f3ab4, 0x482e, 0x4e50, { 0xb4, 0x1f, 0x8a, 0x7f, 0x8b, 0xd8, 0x96, 0x0b } }; static const GUID SDL_IID_ID3D12Resource = { 0x696442be, 0xa72e, 0x4059, { 0xbc, 0x79, 0x5b, 0x5c, 0x98, 0x04, 0x0f, 0xad } }; static const GUID SDL_IID_ID3D12RootSignature = { 0xc54a6b66, 0x72df, 0x4ee8, { 0x8b, 0xe5, 0xa9, 0x46, 0xa1, 0x42, 0x92, 0x14 } }; static const GUID SDL_IID_ID3D12PipelineState = { 0x765a30f3, 0xf624, 0x4c6f, { 0xa8, 0x28, 0xac, 0xe9, 0x48, 0x62, 0x24, 0x45 } }; @@ -284,7 +283,25 @@ Uint32 D3D12_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) } } -static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat) +static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 sdlFormat) +{ + switch (sdlFormat) { + case SDL_PIXELFORMAT_ARGB8888: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case SDL_PIXELFORMAT_XRGB8888: + return DXGI_FORMAT_B8G8R8X8_UNORM; + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + return DXGI_FORMAT_R8_UNORM; + case SDL_PIXELFORMAT_NV12: + case SDL_PIXELFORMAT_NV21: + return DXGI_FORMAT_NV12; + default: + return DXGI_FORMAT_UNKNOWN; + } +} + +static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 sdlFormat) { switch (sdlFormat) { case SDL_PIXELFORMAT_ARGB8888: @@ -703,7 +720,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) HRESULT result = S_OK; UINT creationFlags = 0; int i, j, k, l; - SDL_bool createDebug = SDL_FALSE; + SDL_bool createDebug; D3D12_COMMAND_QUEUE_DESC queueDesc; D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc; @@ -1417,7 +1434,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; D3D12_TextureData *textureData; HRESULT result; - DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format); + DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format); D3D12_RESOURCE_DESC textureDesc; D3D12_HEAP_PROPERTIES heapProps; D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; @@ -1508,34 +1525,13 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) if (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21) { - D3D12_RESOURCE_DESC nvTextureDesc = textureDesc; - textureData->nv12 = SDL_TRUE; - - nvTextureDesc.Format = DXGI_FORMAT_R8G8_UNORM; - nvTextureDesc.Width = (textureDesc.Width + 1) / 2; - nvTextureDesc.Height = (textureDesc.Height + 1) / 2; - - result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource, - &heapProps, - D3D12_HEAP_FLAG_NONE, - &nvTextureDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - NULL, - D3D_GUID(SDL_IID_ID3D12Resource), - (void **)&textureData->mainTextureNV); - textureData->mainResourceStateNV = D3D12_RESOURCE_STATE_COPY_DEST; - if (FAILED(result)) { - D3D12_DestroyTexture(renderer, texture); - return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateTexture2D"), result); - } } #endif /* SDL_HAVE_YUV */ SDL_zero(resourceViewDesc); resourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - resourceViewDesc.Format = textureDesc.Format; + resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format); resourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - resourceViewDesc.Texture2D.MostDetailedMip = 0; resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels; textureData->mainSRVIndex = D3D12_GetAvailableSRVIndex(renderer); @@ -1569,12 +1565,13 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) D3D12_SHADER_RESOURCE_VIEW_DESC nvResourceViewDesc = resourceViewDesc; nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM; + nvResourceViewDesc.Texture2D.PlaneSlice = 1; D3D_CALL_RET(rendererData->srvDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &textureData->mainTextureResourceViewNV); textureData->mainSRVIndexNV = D3D12_GetAvailableSRVIndex(renderer); textureData->mainTextureResourceViewNV.ptr += textureData->mainSRVIndexNV * rendererData->srvDescriptorSize; D3D_CALL(rendererData->d3dDevice, CreateShaderResourceView, - textureData->mainTextureNV, + textureData->mainTexture, &nvResourceViewDesc, textureData->mainTextureResourceViewNV); } @@ -1623,8 +1620,7 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer, D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexU); D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexV); } - SAFE_RELEASE(textureData->mainTextureNV); - if (textureData->yuv) { + if (textureData->nv12) { D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexNV); } SDL_free(textureData->pixels); @@ -1633,22 +1629,22 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer, texture->driverdata = NULL; } -static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Resource *texture, int bpp, int x, int y, int w, int h, const void *pixels, int pitch, D3D12_RESOURCE_STATES *resourceState) +static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Resource *texture, int plane, int x, int y, int w, int h, const void *pixels, int pitch, D3D12_RESOURCE_STATES *resourceState) { const Uint8 *src; Uint8 *dst; - int row; UINT length; HRESULT result; D3D12_RESOURCE_DESC textureDesc; D3D12_RESOURCE_DESC uploadDesc; D3D12_HEAP_PROPERTIES heapProps; - D3D12_SUBRESOURCE_FOOTPRINT pitchedDesc; D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedTextureDesc; D3D12_TEXTURE_COPY_LOCATION srcLocation; D3D12_TEXTURE_COPY_LOCATION dstLocation; BYTE *textureMemory; ID3D12Resource *uploadBuffer; + UINT row, NumRows, RowPitch; + UINT64 RowLength; /* Create an upload buffer, which will be used to write to the main texture. */ SDL_zero(textureDesc); @@ -1671,13 +1667,14 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res /* Figure out how much we need to allocate for the upload buffer */ D3D_CALL(rendererData->d3dDevice, GetCopyableFootprints, &textureDesc, - 0, + plane, 1, 0, - NULL, - NULL, - NULL, + &placedTextureDesc, + &NumRows, + &RowLength, &uploadDesc.Width); + RowPitch = placedTextureDesc.Footprint.RowPitch; SDL_zero(heapProps); heapProps.Type = D3D12_HEAP_TYPE_UPLOAD; @@ -1708,33 +1705,22 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Resource::Map [map staging texture]"), result); } - SDL_zero(pitchedDesc); - pitchedDesc.Format = textureDesc.Format; - pitchedDesc.Width = w; - pitchedDesc.Height = h; - pitchedDesc.Depth = 1; - pitchedDesc.RowPitch = D3D12_Align(w * bpp, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - - SDL_zero(placedTextureDesc); - placedTextureDesc.Offset = 0; - placedTextureDesc.Footprint = pitchedDesc; - src = (const Uint8 *)pixels; dst = textureMemory; - length = w * bpp; - if (length == (UINT)pitch && length == pitchedDesc.RowPitch) { - SDL_memcpy(dst, src, (size_t)length * h); + length = RowLength; + if (length == (UINT)pitch && length == RowPitch) { + SDL_memcpy(dst, src, (size_t)length * NumRows); } else { if (length > (UINT)pitch) { length = pitch; } - if (length > pitchedDesc.RowPitch) { - length = pitchedDesc.RowPitch; + if (length > RowPitch) { + length = RowPitch; } - for (row = 0; row < h; ++row) { + for (row = NumRows; row--; ) { SDL_memcpy(dst, src, length); src += pitch; - dst += pitchedDesc.RowPitch; + dst += RowPitch; } } @@ -1748,7 +1734,7 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res SDL_zero(dstLocation); dstLocation.pResource = texture; dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - dstLocation.SubresourceIndex = 0; + dstLocation.SubresourceIndex = plane; SDL_zero(srcLocation); srcLocation.pResource = rendererData->uploadBuffers[rendererData->currentUploadBuffer]; @@ -1787,7 +1773,7 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, return SDL_SetError("Texture is not currently available"); } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceState) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceState) < 0) { return -1; } #if SDL_HAVE_YUV @@ -1795,13 +1781,13 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, /* Skip to the correct offset into the next texture */ srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch); - if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU) < 0) { return -1; } /* Skip to the correct offset into the next texture */ srcPixels = (const void *)((const Uint8 *)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1) / 2)); - if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV) < 0) { return -1; } } @@ -1810,7 +1796,7 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, /* Skip to the correct offset into the next texture */ srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch); - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, srcPixels, 2 * ((srcPitch + 1) / 2), &textureData->mainResourceStateNV) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 1, rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceState) < 0) { return -1; } } @@ -1832,13 +1818,13 @@ static int D3D12_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture, return SDL_SetError("Texture is not currently available"); } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) { return -1; } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch, &textureData->mainResourceStateU) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch, &textureData->mainResourceStateU) < 0) { return -1; } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainResourceStateV) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainResourceStateV) < 0) { return -1; } return 0; @@ -1856,11 +1842,11 @@ static int D3D12_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture, return SDL_SetError("Texture is not currently available"); } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) { return -1; } - if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, UVplane, UVpitch, &textureData->mainResourceStateNV) < 0) { + if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 1, rect->x, rect->y, rect->w, rect->h, UVplane, UVpitch, &textureData->mainResourceState) < 0) { return -1; } return 0; @@ -2078,6 +2064,25 @@ static void D3D12_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR; } +static IDXGIResource *D3D12_GetTextureDXGIResource(SDL_Texture *texture) +{ + D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata; + IDXGIResource *resource = NULL; + HRESULT result; + + if (textureData == NULL || textureData->mainTexture == NULL) { + SDL_SetError("Texture is not currently available"); + return NULL; + } + + result = D3D_CALL(textureData->mainTexture, QueryInterface, D3D_GUID(SDL_IID_IDXGIResource), (void **)&resource); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("GetTextureDXGIResource"), result); + return NULL; + } + return resource; +} + static int D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata; @@ -2550,8 +2555,6 @@ static int D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c /* Make sure each texture is in the correct state to be accessed by the pixel shader. */ D3D12_TransitionResource(rendererData, textureData->mainTexture, textureData->mainResourceState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); textureData->mainResourceState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - D3D12_TransitionResource(rendererData, textureData->mainTextureNV, textureData->mainResourceStateNV, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - textureData->mainResourceStateNV = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; return D3D12_SetDrawState(renderer, cmd, shader, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix); @@ -2979,6 +2982,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->LockTexture = D3D12_LockTexture; renderer->UnlockTexture = D3D12_UnlockTexture; renderer->SetTextureScaleMode = D3D12_SetTextureScaleMode; + renderer->GetTextureDXGIResource = D3D12_GetTextureDXGIResource; renderer->SetRenderTarget = D3D12_SetRenderTarget; renderer->QueueSetViewport = D3D12_QueueSetViewport; renderer->QueueSetDrawColor = D3D12_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/test/testffmpeg.c b/test/testffmpeg.c index 5150a4306da63..e7cc1b89e434e 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -20,11 +20,18 @@ #include #include +#include +#include +#include +#include + #ifdef HAVE_EGL #include #include #include +#include + #ifndef fourcc_code #define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) #endif @@ -42,86 +49,8 @@ #ifdef __WIN32__ #define COBJMACROS -#include - -struct D3D11_TextureData -{ - ID3D11Texture2D *mainTexture; - ID3D11ShaderResourceView *mainTextureResourceView; - ID3D11RenderTargetView *mainTextureRenderTargetView; - ID3D11Texture2D *stagingTexture; - int lockedTexturePositionX; - int lockedTexturePositionY; - D3D11_FILTER scaleMode; - - /* YV12 texture support */ - SDL_bool yuv; - ID3D11Texture2D *mainTextureU; - ID3D11ShaderResourceView *mainTextureResourceViewU; - ID3D11Texture2D *mainTextureV; - ID3D11ShaderResourceView *mainTextureResourceViewV; - - /* NV12 texture support */ - SDL_bool nv12; - ID3D11Texture2D *mainTextureNV; - ID3D11ShaderResourceView *mainTextureResourceViewNV; - - Uint8 *pixels; - int pitch; - SDL_Rect locked_rect; -}; - -/* Rendering view state */ -typedef struct SDL_RenderViewState -{ - int pixel_w; - int pixel_h; - SDL_Rect viewport; - SDL_Rect clip_rect; - SDL_bool clipping_enabled; - SDL_FPoint scale; - -} SDL_RenderViewState; - -struct SDL_Texture -{ - const void *magic; - Uint32 format; /**< The pixel format of the texture */ - int access; /**< SDL_TextureAccess */ - int w; /**< The width of the texture */ - int h; /**< The height of the texture */ - int modMode; /**< The texture modulation mode */ - SDL_BlendMode blendMode; /**< The texture blend mode */ - SDL_ScaleMode scaleMode; /**< The texture scale mode */ - SDL_Color color; /**< Texture modulation values */ - SDL_RenderViewState view; /**< Target texture view state */ - - SDL_Renderer *renderer; - - /* Support for formats not supported directly by the renderer */ - SDL_Texture *native; - void /*SDL_SW_YUVTexture*/ *yuv; - void *pixels; - int pitch; - SDL_Rect locked_rect; - SDL_Surface *locked_surface; /**< Locked region exposed as a SDL surface */ - - Uint32 last_command_generation; /* last command queue generation this texture was in. */ - - struct D3D11_TextureData /*void*/ *driverdata; /**< Driver specific texture representation */ - void *userdata; - - SDL_Texture *prev; - SDL_Texture *next; -}; -#endif /* __WIN32__ */ - -#include -#include -#include #include -#include -#include +#endif /* __WIN32__ */ #include "icon.h" @@ -152,6 +81,7 @@ static SDL_bool has_videotoolbox_output; #ifdef __WIN32__ static ID3D11Device *d3d11_device; static ID3D11DeviceContext *d3d11_context; +static const GUID SDL_IID_ID3D11Resource = { 0xdc8e63f3, 0xd12b, 0x4952, { 0xb4, 0x7b, 0x5e, 0x45, 0x02, 0x6a, 0x86, 0x2d } }; #endif static int done; @@ -406,6 +336,7 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV continue; } +#ifdef __WIN32__ if (type == AV_HWDEVICE_TYPE_D3D11VA) { AVD3D11VADeviceContext *device_context; @@ -423,7 +354,9 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV } else { SDL_Log("Using %s hardware acceleration with pixel format %s\n", av_hwdevice_get_type_name(config->device_type), av_get_pix_fmt_name(config->pix_fmt)); } - } else { + } else +#endif + { result = av_hwdevice_ctx_create(&context->hw_device_ctx, type, NULL, NULL, 0); if (result < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create hardware device context: %s", av_err2str(result)); @@ -598,6 +531,7 @@ static SDL_bool GetTextureForVAAPIFrame(AVFrame *frame, SDL_Texture **texture) static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) { #ifdef __WIN32__ + int texture_width = 0, texture_height = 0; ID3D11Texture2D *pTexture = (ID3D11Texture2D *)frame->data[0]; UINT iSliceIndex = (UINT)(uintptr_t)frame->data[1]; @@ -609,7 +543,10 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) return SDL_FALSE; } - if (!*texture || (UINT)(*texture)->w != desc.Width || (UINT)(*texture)->h != desc.Height) { + if (*texture) { + SDL_QueryTexture(*texture, NULL, NULL, &texture_width, &texture_height); + } + if (!*texture || (UINT)texture_width != desc.Width || (UINT)texture_height != desc.Height) { if (*texture) { SDL_DestroyTexture(*texture); } else { @@ -621,64 +558,23 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) if (!*texture) { return SDL_FALSE; } + } - /* Set up the resource views for this texture */ - struct D3D11_TextureData *pTextureData = (*texture)->driverdata; - if (pTextureData->mainTexture) { - ID3D11Texture2D_Release(pTextureData->mainTexture); - pTextureData->mainTexture = NULL; - } - if (pTextureData->mainTextureResourceView) { - ID3D11ShaderResourceView_Release(pTextureData->mainTextureResourceView); - pTextureData->mainTextureResourceView = NULL; - } - if (pTextureData->mainTextureNV) { - ID3D11Texture2D_Release(pTextureData->mainTextureNV); - pTextureData->mainTextureNV = NULL; - } - if (pTextureData->mainTextureResourceViewNV) { - ID3D11ShaderResourceView_Release(pTextureData->mainTextureResourceViewNV); - pTextureData->mainTextureResourceViewNV = NULL; - } - - desc.ArraySize = 1; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - - HRESULT result = ID3D11Device_CreateTexture2D(d3d11_device, &desc, NULL, &pTextureData->mainTexture); - if (FAILED(result)) { - SDL_SetError("Couldn't create main texture: 0x%x", result); - return SDL_FALSE; - } - - pTextureData->mainTextureNV = pTextureData->mainTexture; - ID3D11Texture2D_AddRef(pTextureData->mainTextureNV); - - D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; - resourceViewDesc.Format = DXGI_FORMAT_R8_UNORM; - resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - resourceViewDesc.Texture2D.MostDetailedMip = 0; - resourceViewDesc.Texture2D.MipLevels = 1; - result = ID3D11Device_CreateShaderResourceView(d3d11_device, - (ID3D11Resource *)pTextureData->mainTexture, - &resourceViewDesc, - &pTextureData->mainTextureResourceView); - if (FAILED(result)) { - SDL_SetError("Couldn't create main texture view: 0x%x", result); - return SDL_FALSE; - } + IDXGIResource *dxgi_resource = SDL_GetTextureDXGIResource(*texture); + if (!dxgi_resource) { + return SDL_FALSE; + } - resourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM; - result = ID3D11Device_CreateShaderResourceView(d3d11_device, - (ID3D11Resource *)pTextureData->mainTexture, - &resourceViewDesc, - &pTextureData->mainTextureResourceViewNV); - if (FAILED(result)) { - SDL_SetError("Couldn't create secondary texture view: 0x%x", result); - return SDL_FALSE; - } + ID3D11Resource *dx11_resource = NULL; + HRESULT result = IDXGIResource_QueryInterface(dxgi_resource, &SDL_IID_ID3D11Resource, (void **)&dx11_resource); + IDXGIResource_Release(dxgi_resource); + if (FAILED(result)) { + SDL_SetError("Couldn't get texture ID3D11Resource interface: 0x%x", result); + return SDL_FALSE; } + ID3D11DeviceContext_CopySubresourceRegion(d3d11_context, dx11_resource, 0, 0, 0, 0, (ID3D11Resource *)pTexture, iSliceIndex, NULL); + ID3D11Resource_Release(dx11_resource); - ID3D11DeviceContext_CopySubresourceRegion(d3d11_context, (ID3D11Resource *)(*texture)->driverdata->mainTexture, 0, 0, 0, 0, (ID3D11Resource *)pTexture, iSliceIndex, NULL); return SDL_TRUE; #else return SDL_FALSE; diff --git a/test/testoverlay.c b/test/testoverlay.c index abd97c40ab178..5d42efc74d7f9 100644 --- a/test/testoverlay.c +++ b/test/testoverlay.c @@ -147,6 +147,7 @@ static Uint64 next_fps_check; static Uint32 frames; static const Uint32 fps_check_delay = 5000; +static Uint32 yuv_format = SDL_PIXELFORMAT_YV12; static SDL_Surface *MooseYUVSurfaces[MOOSEFRAMES_COUNT]; static SDL_Texture *MooseTexture = NULL; static SDL_FRect displayrect; @@ -187,31 +188,58 @@ static void MoveSprites(SDL_Renderer *renderer) static int i = 0; if (streaming) { - if (!paused) { - i = (i + 1) % MOOSEFRAMES_COUNT; - SDL_UpdateTexture(MooseTexture, NULL, MooseYUVSurfaces[i]->pixels, MooseYUVSurfaces[i]->pitch); - } - SDL_RenderClear(renderer); - SDL_RenderTexture(renderer, MooseTexture, NULL, &displayrect); - SDL_RenderPresent(renderer); + if (!paused) { + i = (i + 1) % MOOSEFRAMES_COUNT; + /* Test both upload paths for NV12/NV21 formats */ + if ((yuv_format == SDL_PIXELFORMAT_NV12 || yuv_format == SDL_PIXELFORMAT_NV21) && + (i % 2) == 0) { +#ifdef TEST_RECT_UPDATE + SDL_Rect rect; + + if (i == 0) { + rect.x = 0; + rect.y = 0; + rect.w = MOOSEPIC_W; + rect.h = MOOSEPIC_H; + } else { + rect.x = MOOSEPIC_W / 4; + rect.y = MOOSEPIC_H / 4; + rect.w = MOOSEPIC_W / 2; + rect.h = MOOSEPIC_H / 2; + } + SDL_UpdateNVTexture(MooseTexture, &rect, + (Uint8 *)MooseYUVSurfaces[i]->pixels + rect.y * MooseYUVSurfaces[i]->pitch + rect.x, MooseYUVSurfaces[i]->pitch, + (Uint8 *)MooseYUVSurfaces[i]->pixels + MOOSEFRAME_SIZE + (rect.y + 1) / 2 * MooseYUVSurfaces[i]->pitch + (rect.x + 1) / 2, MooseYUVSurfaces[i]->pitch); +#else + SDL_UpdateNVTexture(MooseTexture, NULL, + MooseYUVSurfaces[i]->pixels, MooseYUVSurfaces[i]->pitch, + (Uint8 *)MooseYUVSurfaces[i]->pixels + MOOSEFRAME_SIZE, MooseYUVSurfaces[i]->pitch); +#endif + } else { + SDL_UpdateTexture(MooseTexture, NULL, MooseYUVSurfaces[i]->pixels, MooseYUVSurfaces[i]->pitch); + } + } + SDL_RenderClear(renderer); + SDL_RenderTexture(renderer, MooseTexture, NULL, &displayrect); + SDL_RenderPresent(renderer); } else { - SDL_Texture *tmp; - - /* Test SDL_CreateTextureFromSurface */ - if (!paused) { - i = (i + 1) % MOOSEFRAMES_COUNT; - } - - tmp = SDL_CreateTextureFromSurface(renderer, MooseYUVSurfaces[i]); - if (tmp == NULL) { - SDL_Log("Error %s", SDL_GetError()); - quit(7); - } - - SDL_RenderClear(renderer); - SDL_RenderTexture(renderer, tmp, NULL, &displayrect); - SDL_RenderPresent(renderer); - SDL_DestroyTexture(tmp); + SDL_Texture *tmp; + + /* Test SDL_CreateTextureFromSurface */ + if (!paused) { + i = (i + 1) % MOOSEFRAMES_COUNT; + } + + tmp = SDL_CreateTextureFromSurface(renderer, MooseYUVSurfaces[i]); + if (tmp == NULL) { + SDL_Log("Error %s", SDL_GetError()); + quit(7); + } + + SDL_RenderClear(renderer); + SDL_RenderTexture(renderer, tmp, NULL, &displayrect); + SDL_RenderPresent(renderer); + SDL_DestroyTexture(tmp); } } @@ -295,7 +323,6 @@ int main(int argc, char **argv) int nodelay = 0; int scale = 5; char *filename = NULL; - int yuv_format = SDL_PIXELFORMAT_YV12; /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);