mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-16 17:58:27 +00:00
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.
This commit is contained in:
parent
a842446f62
commit
2bd478ae65
10 changed files with 336 additions and 265 deletions
|
@ -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);
|
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.
|
* Query the attributes of a texture.
|
||||||
*
|
*
|
||||||
|
|
|
@ -907,6 +907,7 @@ SDL3_0.0.0 {
|
||||||
SDL_SetAudioStreamFrequencyRatio;
|
SDL_SetAudioStreamFrequencyRatio;
|
||||||
SDL_SetAudioPostmixCallback;
|
SDL_SetAudioPostmixCallback;
|
||||||
SDL_GetAudioStreamQueued;
|
SDL_GetAudioStreamQueued;
|
||||||
|
SDL_GetTextureDXGIResource;
|
||||||
# extra symbols go here (don't modify this line)
|
# extra symbols go here (don't modify this line)
|
||||||
local: *;
|
local: *;
|
||||||
};
|
};
|
||||||
|
|
|
@ -932,3 +932,4 @@
|
||||||
#define SDL_SetAudioStreamFrequencyRatio SDL_SetAudioStreamFrequencyRatio_REAL
|
#define SDL_SetAudioStreamFrequencyRatio SDL_SetAudioStreamFrequencyRatio_REAL
|
||||||
#define SDL_SetAudioPostmixCallback SDL_SetAudioPostmixCallback_REAL
|
#define SDL_SetAudioPostmixCallback SDL_SetAudioPostmixCallback_REAL
|
||||||
#define SDL_GetAudioStreamQueued SDL_GetAudioStreamQueued_REAL
|
#define SDL_GetAudioStreamQueued SDL_GetAudioStreamQueued_REAL
|
||||||
|
#define SDL_GetTextureDXGIResource SDL_GetTextureDXGIResource_REAL
|
||||||
|
|
|
@ -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_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_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(int,SDL_GetAudioStreamQueued,(SDL_AudioStream *a),(a),return)
|
||||||
|
SDL_DYNAPI_PROC(IDXGIResource*,SDL_GetTextureDXGIResource,(SDL_Texture *a),(a),return)
|
||||||
|
|
|
@ -4186,6 +4186,19 @@ void *SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer)
|
||||||
return NULL;
|
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)
|
static SDL_BlendMode SDL_GetShortBlendMode(SDL_BlendMode blendMode)
|
||||||
{
|
{
|
||||||
if (blendMode == SDL_BLENDMODE_NONE_FULL) {
|
if (blendMode == SDL_BLENDMODE_NONE_FULL) {
|
||||||
|
|
|
@ -212,6 +212,8 @@ struct SDL_Renderer
|
||||||
void *(*GetMetalLayer)(SDL_Renderer *renderer);
|
void *(*GetMetalLayer)(SDL_Renderer *renderer);
|
||||||
void *(*GetMetalCommandEncoder)(SDL_Renderer *renderer);
|
void *(*GetMetalCommandEncoder)(SDL_Renderer *renderer);
|
||||||
|
|
||||||
|
IDXGIResource *(*GetTextureDXGIResource)(SDL_Texture *texture);
|
||||||
|
|
||||||
/* The current renderer info */
|
/* The current renderer info */
|
||||||
SDL_RendererInfo info;
|
SDL_RendererInfo info;
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,6 @@ typedef struct
|
||||||
|
|
||||||
/* NV12 texture support */
|
/* NV12 texture support */
|
||||||
SDL_bool nv12;
|
SDL_bool nv12;
|
||||||
ID3D11Texture2D *mainTextureNV;
|
|
||||||
ID3D11ShaderResourceView *mainTextureResourceViewNV;
|
ID3D11ShaderResourceView *mainTextureResourceViewNV;
|
||||||
|
|
||||||
Uint8 *pixels;
|
Uint8 *pixels;
|
||||||
|
@ -187,6 +186,7 @@ static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0
|
||||||
#if defined(__WINRT__) && NTDDI_VERSION > NTDDI_WIN8
|
#if defined(__WINRT__) && NTDDI_VERSION > NTDDI_WIN8
|
||||||
static const GUID SDL_IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } };
|
static const GUID SDL_IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } };
|
||||||
#endif
|
#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_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_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 } };
|
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) {
|
switch (sdlFormat) {
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
@ -217,8 +217,26 @@ static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
|
||||||
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||||
case SDL_PIXELFORMAT_YV12:
|
case SDL_PIXELFORMAT_YV12:
|
||||||
case SDL_PIXELFORMAT_IYUV:
|
case SDL_PIXELFORMAT_IYUV:
|
||||||
case SDL_PIXELFORMAT_NV12: /* For the Y texture */
|
return DXGI_FORMAT_R8_UNORM;
|
||||||
case SDL_PIXELFORMAT_NV21: /* For the Y texture */
|
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;
|
return DXGI_FORMAT_R8_UNORM;
|
||||||
default:
|
default:
|
||||||
return DXGI_FORMAT_UNKNOWN;
|
return DXGI_FORMAT_UNKNOWN;
|
||||||
|
@ -850,8 +868,7 @@ static void D3D11_ReleaseMainRenderTargetView(SDL_Renderer *renderer)
|
||||||
|
|
||||||
static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer);
|
static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer);
|
||||||
|
|
||||||
HRESULT
|
static HRESULT D3D11_HandleDeviceLost(SDL_Renderer *renderer)
|
||||||
D3D11_HandleDeviceLost(SDL_Renderer *renderer)
|
|
||||||
{
|
{
|
||||||
HRESULT result = S_OK;
|
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_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
|
||||||
D3D11_TextureData *textureData;
|
D3D11_TextureData *textureData;
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
|
DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format);
|
||||||
D3D11_TEXTURE2D_DESC textureDesc;
|
D3D11_TEXTURE2D_DESC textureDesc;
|
||||||
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
|
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);
|
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||||
texture->format == SDL_PIXELFORMAT_NV21) {
|
texture->format == SDL_PIXELFORMAT_NV21) {
|
||||||
D3D11_TEXTURE2D_DESC nvTextureDesc = textureDesc;
|
|
||||||
|
|
||||||
textureData->nv12 = SDL_TRUE;
|
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 */
|
#endif /* SDL_HAVE_YUV */
|
||||||
SDL_zero(resourceViewDesc);
|
SDL_zero(resourceViewDesc);
|
||||||
resourceViewDesc.Format = textureDesc.Format;
|
resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format);
|
||||||
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||||
resourceViewDesc.Texture2D.MostDetailedMip = 0;
|
resourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||||
resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
|
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;
|
nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM;
|
||||||
|
|
||||||
result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
|
result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
|
||||||
(ID3D11Resource *)textureData->mainTextureNV,
|
(ID3D11Resource *)textureData->mainTexture,
|
||||||
&nvResourceViewDesc,
|
&nvResourceViewDesc,
|
||||||
&textureData->mainTextureResourceViewNV);
|
&textureData->mainTextureResourceViewNV);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
|
@ -1239,7 +1240,6 @@ static void D3D11_DestroyTexture(SDL_Renderer *renderer,
|
||||||
SAFE_RELEASE(data->mainTextureResourceViewU);
|
SAFE_RELEASE(data->mainTextureResourceViewU);
|
||||||
SAFE_RELEASE(data->mainTextureV);
|
SAFE_RELEASE(data->mainTextureV);
|
||||||
SAFE_RELEASE(data->mainTextureResourceViewV);
|
SAFE_RELEASE(data->mainTextureResourceViewV);
|
||||||
SAFE_RELEASE(data->mainTextureNV);
|
|
||||||
SAFE_RELEASE(data->mainTextureResourceViewNV);
|
SAFE_RELEASE(data->mainTextureResourceViewNV);
|
||||||
SDL_free(data->pixels);
|
SDL_free(data->pixels);
|
||||||
#endif
|
#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);
|
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;
|
src = (const Uint8 *)pixels;
|
||||||
dst = textureMemory.pData;
|
dst = textureMemory.pData;
|
||||||
length = w * bpp;
|
length = w * bpp;
|
||||||
|
@ -1355,15 +1360,6 @@ static int D3D11_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||||
return -1;
|
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 */
|
#endif /* SDL_HAVE_YUV */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1401,18 +1397,110 @@ static int D3D11_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||||
{
|
{
|
||||||
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
|
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
|
||||||
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->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) {
|
if (textureData == NULL) {
|
||||||
return SDL_SetError("Texture is not currently available");
|
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) {
|
w = rect->w;
|
||||||
return -1;
|
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) {
|
/* Get a write-only pointer to data in the staging texture: */
|
||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
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)
|
static int D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
|
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->LockTexture = D3D11_LockTexture;
|
||||||
renderer->UnlockTexture = D3D11_UnlockTexture;
|
renderer->UnlockTexture = D3D11_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode;
|
renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode;
|
||||||
|
renderer->GetTextureDXGIResource = D3D11_GetTextureDXGIResource;
|
||||||
renderer->SetRenderTarget = D3D11_SetRenderTarget;
|
renderer->SetRenderTarget = D3D11_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = D3D11_QueueSetViewport;
|
renderer->QueueSetViewport = D3D11_QueueSetViewport;
|
||||||
renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
|
renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
|
||||||
|
|
|
@ -123,9 +123,7 @@ typedef struct
|
||||||
|
|
||||||
/* NV12 texture support */
|
/* NV12 texture support */
|
||||||
SDL_bool nv12;
|
SDL_bool nv12;
|
||||||
ID3D12Resource *mainTextureNV;
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE mainTextureResourceViewNV;
|
D3D12_CPU_DESCRIPTOR_HANDLE mainTextureResourceViewNV;
|
||||||
D3D12_RESOURCE_STATES mainResourceStateNV;
|
|
||||||
SIZE_T mainSRVIndexNV;
|
SIZE_T mainSRVIndexNV;
|
||||||
|
|
||||||
Uint8 *pixels;
|
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_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_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_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_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_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 } };
|
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) {
|
switch (sdlFormat) {
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
@ -703,7 +720,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
|
||||||
HRESULT result = S_OK;
|
HRESULT result = S_OK;
|
||||||
UINT creationFlags = 0;
|
UINT creationFlags = 0;
|
||||||
int i, j, k, l;
|
int i, j, k, l;
|
||||||
SDL_bool createDebug = SDL_FALSE;
|
SDL_bool createDebug;
|
||||||
|
|
||||||
D3D12_COMMAND_QUEUE_DESC queueDesc;
|
D3D12_COMMAND_QUEUE_DESC queueDesc;
|
||||||
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc;
|
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_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata;
|
||||||
D3D12_TextureData *textureData;
|
D3D12_TextureData *textureData;
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
|
DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format);
|
||||||
D3D12_RESOURCE_DESC textureDesc;
|
D3D12_RESOURCE_DESC textureDesc;
|
||||||
D3D12_HEAP_PROPERTIES heapProps;
|
D3D12_HEAP_PROPERTIES heapProps;
|
||||||
D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
|
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 ||
|
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||||
texture->format == SDL_PIXELFORMAT_NV21) {
|
texture->format == SDL_PIXELFORMAT_NV21) {
|
||||||
D3D12_RESOURCE_DESC nvTextureDesc = textureDesc;
|
|
||||||
|
|
||||||
textureData->nv12 = SDL_TRUE;
|
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 */
|
#endif /* SDL_HAVE_YUV */
|
||||||
SDL_zero(resourceViewDesc);
|
SDL_zero(resourceViewDesc);
|
||||||
resourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
resourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||||
resourceViewDesc.Format = textureDesc.Format;
|
resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format);
|
||||||
resourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
resourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||||
resourceViewDesc.Texture2D.MostDetailedMip = 0;
|
|
||||||
resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
|
resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
|
||||||
|
|
||||||
textureData->mainSRVIndex = D3D12_GetAvailableSRVIndex(renderer);
|
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;
|
D3D12_SHADER_RESOURCE_VIEW_DESC nvResourceViewDesc = resourceViewDesc;
|
||||||
|
|
||||||
nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM;
|
nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM;
|
||||||
|
nvResourceViewDesc.Texture2D.PlaneSlice = 1;
|
||||||
|
|
||||||
D3D_CALL_RET(rendererData->srvDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &textureData->mainTextureResourceViewNV);
|
D3D_CALL_RET(rendererData->srvDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &textureData->mainTextureResourceViewNV);
|
||||||
textureData->mainSRVIndexNV = D3D12_GetAvailableSRVIndex(renderer);
|
textureData->mainSRVIndexNV = D3D12_GetAvailableSRVIndex(renderer);
|
||||||
textureData->mainTextureResourceViewNV.ptr += textureData->mainSRVIndexNV * rendererData->srvDescriptorSize;
|
textureData->mainTextureResourceViewNV.ptr += textureData->mainSRVIndexNV * rendererData->srvDescriptorSize;
|
||||||
D3D_CALL(rendererData->d3dDevice, CreateShaderResourceView,
|
D3D_CALL(rendererData->d3dDevice, CreateShaderResourceView,
|
||||||
textureData->mainTextureNV,
|
textureData->mainTexture,
|
||||||
&nvResourceViewDesc,
|
&nvResourceViewDesc,
|
||||||
textureData->mainTextureResourceViewNV);
|
textureData->mainTextureResourceViewNV);
|
||||||
}
|
}
|
||||||
|
@ -1623,8 +1620,7 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer,
|
||||||
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexU);
|
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexU);
|
||||||
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexV);
|
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexV);
|
||||||
}
|
}
|
||||||
SAFE_RELEASE(textureData->mainTextureNV);
|
if (textureData->nv12) {
|
||||||
if (textureData->yuv) {
|
|
||||||
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexNV);
|
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexNV);
|
||||||
}
|
}
|
||||||
SDL_free(textureData->pixels);
|
SDL_free(textureData->pixels);
|
||||||
|
@ -1633,22 +1629,22 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer,
|
||||||
texture->driverdata = NULL;
|
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;
|
const Uint8 *src;
|
||||||
Uint8 *dst;
|
Uint8 *dst;
|
||||||
int row;
|
|
||||||
UINT length;
|
UINT length;
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
D3D12_RESOURCE_DESC textureDesc;
|
D3D12_RESOURCE_DESC textureDesc;
|
||||||
D3D12_RESOURCE_DESC uploadDesc;
|
D3D12_RESOURCE_DESC uploadDesc;
|
||||||
D3D12_HEAP_PROPERTIES heapProps;
|
D3D12_HEAP_PROPERTIES heapProps;
|
||||||
D3D12_SUBRESOURCE_FOOTPRINT pitchedDesc;
|
|
||||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedTextureDesc;
|
D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedTextureDesc;
|
||||||
D3D12_TEXTURE_COPY_LOCATION srcLocation;
|
D3D12_TEXTURE_COPY_LOCATION srcLocation;
|
||||||
D3D12_TEXTURE_COPY_LOCATION dstLocation;
|
D3D12_TEXTURE_COPY_LOCATION dstLocation;
|
||||||
BYTE *textureMemory;
|
BYTE *textureMemory;
|
||||||
ID3D12Resource *uploadBuffer;
|
ID3D12Resource *uploadBuffer;
|
||||||
|
UINT row, NumRows, RowPitch;
|
||||||
|
UINT64 RowLength;
|
||||||
|
|
||||||
/* Create an upload buffer, which will be used to write to the main texture. */
|
/* Create an upload buffer, which will be used to write to the main texture. */
|
||||||
SDL_zero(textureDesc);
|
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 */
|
/* Figure out how much we need to allocate for the upload buffer */
|
||||||
D3D_CALL(rendererData->d3dDevice, GetCopyableFootprints,
|
D3D_CALL(rendererData->d3dDevice, GetCopyableFootprints,
|
||||||
&textureDesc,
|
&textureDesc,
|
||||||
0,
|
plane,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
NULL,
|
&placedTextureDesc,
|
||||||
NULL,
|
&NumRows,
|
||||||
NULL,
|
&RowLength,
|
||||||
&uploadDesc.Width);
|
&uploadDesc.Width);
|
||||||
|
RowPitch = placedTextureDesc.Footprint.RowPitch;
|
||||||
|
|
||||||
SDL_zero(heapProps);
|
SDL_zero(heapProps);
|
||||||
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
|
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);
|
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;
|
src = (const Uint8 *)pixels;
|
||||||
dst = textureMemory;
|
dst = textureMemory;
|
||||||
length = w * bpp;
|
length = RowLength;
|
||||||
if (length == (UINT)pitch && length == pitchedDesc.RowPitch) {
|
if (length == (UINT)pitch && length == RowPitch) {
|
||||||
SDL_memcpy(dst, src, (size_t)length * h);
|
SDL_memcpy(dst, src, (size_t)length * NumRows);
|
||||||
} else {
|
} else {
|
||||||
if (length > (UINT)pitch) {
|
if (length > (UINT)pitch) {
|
||||||
length = pitch;
|
length = pitch;
|
||||||
}
|
}
|
||||||
if (length > pitchedDesc.RowPitch) {
|
if (length > RowPitch) {
|
||||||
length = pitchedDesc.RowPitch;
|
length = RowPitch;
|
||||||
}
|
}
|
||||||
for (row = 0; row < h; ++row) {
|
for (row = NumRows; row--; ) {
|
||||||
SDL_memcpy(dst, src, length);
|
SDL_memcpy(dst, src, length);
|
||||||
src += pitch;
|
src += pitch;
|
||||||
dst += pitchedDesc.RowPitch;
|
dst += RowPitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1748,7 +1734,7 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res
|
||||||
SDL_zero(dstLocation);
|
SDL_zero(dstLocation);
|
||||||
dstLocation.pResource = texture;
|
dstLocation.pResource = texture;
|
||||||
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
dstLocation.SubresourceIndex = 0;
|
dstLocation.SubresourceIndex = plane;
|
||||||
|
|
||||||
SDL_zero(srcLocation);
|
SDL_zero(srcLocation);
|
||||||
srcLocation.pResource = rendererData->uploadBuffers[rendererData->currentUploadBuffer];
|
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");
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
#if SDL_HAVE_YUV
|
#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 */
|
/* Skip to the correct offset into the next texture */
|
||||||
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip to the correct offset into the next texture */
|
/* Skip to the correct offset into the next texture */
|
||||||
srcPixels = (const void *)((const Uint8 *)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1) / 2));
|
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;
|
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 */
|
/* Skip to the correct offset into the next texture */
|
||||||
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1832,13 +1818,13 @@ static int D3D12_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||||
return SDL_SetError("Texture is not currently available");
|
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;
|
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;
|
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 -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1856,11 +1842,11 @@ static int D3D12_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||||
return SDL_SetError("Texture is not currently available");
|
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;
|
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 -1;
|
||||||
}
|
}
|
||||||
return 0;
|
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;
|
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)
|
static int D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
{
|
{
|
||||||
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata;
|
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. */
|
/* 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);
|
D3D12_TransitionResource(rendererData, textureData->mainTexture, textureData->mainResourceState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||||
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,
|
return D3D12_SetDrawState(renderer, cmd, shader, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, SDL_arraysize(shaderResources), shaderResources,
|
||||||
textureSampler, matrix);
|
textureSampler, matrix);
|
||||||
|
@ -2979,6 +2982,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags)
|
||||||
renderer->LockTexture = D3D12_LockTexture;
|
renderer->LockTexture = D3D12_LockTexture;
|
||||||
renderer->UnlockTexture = D3D12_UnlockTexture;
|
renderer->UnlockTexture = D3D12_UnlockTexture;
|
||||||
renderer->SetTextureScaleMode = D3D12_SetTextureScaleMode;
|
renderer->SetTextureScaleMode = D3D12_SetTextureScaleMode;
|
||||||
|
renderer->GetTextureDXGIResource = D3D12_GetTextureDXGIResource;
|
||||||
renderer->SetRenderTarget = D3D12_SetRenderTarget;
|
renderer->SetRenderTarget = D3D12_SetRenderTarget;
|
||||||
renderer->QueueSetViewport = D3D12_QueueSetViewport;
|
renderer->QueueSetViewport = D3D12_QueueSetViewport;
|
||||||
renderer->QueueSetDrawColor = D3D12_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
|
renderer->QueueSetDrawColor = D3D12_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
|
||||||
|
|
|
@ -20,11 +20,18 @@
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3/SDL_main.h>
|
#include <SDL3/SDL_main.h>
|
||||||
|
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
#include <libavutil/pixdesc.h>
|
||||||
|
|
||||||
#ifdef HAVE_EGL
|
#ifdef HAVE_EGL
|
||||||
#include <SDL3/SDL_opengl.h>
|
#include <SDL3/SDL_opengl.h>
|
||||||
#include <SDL3/SDL_opengles2.h>
|
#include <SDL3/SDL_opengles2.h>
|
||||||
#include <SDL3/SDL_egl.h>
|
#include <SDL3/SDL_egl.h>
|
||||||
|
|
||||||
|
#include <libavutil/hwcontext_drm.h>
|
||||||
|
|
||||||
#ifndef fourcc_code
|
#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))
|
#define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,86 +49,8 @@
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
#include <d3d11.h>
|
|
||||||
|
|
||||||
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 <libavcodec/avcodec.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
#include <libavutil/avutil.h>
|
|
||||||
#include <libavutil/hwcontext_d3d11va.h>
|
#include <libavutil/hwcontext_d3d11va.h>
|
||||||
#include <libavutil/hwcontext_drm.h>
|
#endif /* __WIN32__ */
|
||||||
#include <libavutil/pixdesc.h>
|
|
||||||
|
|
||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
|
|
||||||
|
@ -152,6 +81,7 @@ static SDL_bool has_videotoolbox_output;
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
static ID3D11Device *d3d11_device;
|
static ID3D11Device *d3d11_device;
|
||||||
static ID3D11DeviceContext *d3d11_context;
|
static ID3D11DeviceContext *d3d11_context;
|
||||||
|
static const GUID SDL_IID_ID3D11Resource = { 0xdc8e63f3, 0xd12b, 0x4952, { 0xb4, 0x7b, 0x5e, 0x45, 0x02, 0x6a, 0x86, 0x2d } };
|
||||||
#endif
|
#endif
|
||||||
static int done;
|
static int done;
|
||||||
|
|
||||||
|
@ -406,6 +336,7 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
if (type == AV_HWDEVICE_TYPE_D3D11VA) {
|
if (type == AV_HWDEVICE_TYPE_D3D11VA) {
|
||||||
AVD3D11VADeviceContext *device_context;
|
AVD3D11VADeviceContext *device_context;
|
||||||
|
|
||||||
|
@ -423,7 +354,9 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV
|
||||||
} else {
|
} 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));
|
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);
|
result = av_hwdevice_ctx_create(&context->hw_device_ctx, type, NULL, NULL, 0);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create hardware device context: %s", av_err2str(result));
|
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)
|
static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
|
||||||
{
|
{
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
|
int texture_width = 0, texture_height = 0;
|
||||||
ID3D11Texture2D *pTexture = (ID3D11Texture2D *)frame->data[0];
|
ID3D11Texture2D *pTexture = (ID3D11Texture2D *)frame->data[0];
|
||||||
UINT iSliceIndex = (UINT)(uintptr_t)frame->data[1];
|
UINT iSliceIndex = (UINT)(uintptr_t)frame->data[1];
|
||||||
|
|
||||||
|
@ -609,7 +543,10 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
|
||||||
return SDL_FALSE;
|
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) {
|
if (*texture) {
|
||||||
SDL_DestroyTexture(*texture);
|
SDL_DestroyTexture(*texture);
|
||||||
} else {
|
} else {
|
||||||
|
@ -621,64 +558,23 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
|
||||||
if (!*texture) {
|
if (!*texture) {
|
||||||
return SDL_FALSE;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D11DeviceContext_CopySubresourceRegion(d3d11_context, (ID3D11Resource *)(*texture)->driverdata->mainTexture, 0, 0, 0, 0, (ID3D11Resource *)pTexture, iSliceIndex, NULL);
|
IDXGIResource *dxgi_resource = SDL_GetTextureDXGIResource(*texture);
|
||||||
|
if (!dxgi_resource) {
|
||||||
|
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);
|
||||||
|
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
#else
|
#else
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
|
|
@ -147,6 +147,7 @@ static Uint64 next_fps_check;
|
||||||
static Uint32 frames;
|
static Uint32 frames;
|
||||||
static const Uint32 fps_check_delay = 5000;
|
static const Uint32 fps_check_delay = 5000;
|
||||||
|
|
||||||
|
static Uint32 yuv_format = SDL_PIXELFORMAT_YV12;
|
||||||
static SDL_Surface *MooseYUVSurfaces[MOOSEFRAMES_COUNT];
|
static SDL_Surface *MooseYUVSurfaces[MOOSEFRAMES_COUNT];
|
||||||
static SDL_Texture *MooseTexture = NULL;
|
static SDL_Texture *MooseTexture = NULL;
|
||||||
static SDL_FRect displayrect;
|
static SDL_FRect displayrect;
|
||||||
|
@ -187,31 +188,58 @@ static void MoveSprites(SDL_Renderer *renderer)
|
||||||
static int i = 0;
|
static int i = 0;
|
||||||
|
|
||||||
if (streaming) {
|
if (streaming) {
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
i = (i + 1) % MOOSEFRAMES_COUNT;
|
i = (i + 1) % MOOSEFRAMES_COUNT;
|
||||||
SDL_UpdateTexture(MooseTexture, NULL, MooseYUVSurfaces[i]->pixels, MooseYUVSurfaces[i]->pitch);
|
/* Test both upload paths for NV12/NV21 formats */
|
||||||
}
|
if ((yuv_format == SDL_PIXELFORMAT_NV12 || yuv_format == SDL_PIXELFORMAT_NV21) &&
|
||||||
SDL_RenderClear(renderer);
|
(i % 2) == 0) {
|
||||||
SDL_RenderTexture(renderer, MooseTexture, NULL, &displayrect);
|
#ifdef TEST_RECT_UPDATE
|
||||||
SDL_RenderPresent(renderer);
|
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 {
|
} else {
|
||||||
SDL_Texture *tmp;
|
SDL_Texture *tmp;
|
||||||
|
|
||||||
/* Test SDL_CreateTextureFromSurface */
|
/* Test SDL_CreateTextureFromSurface */
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
i = (i + 1) % MOOSEFRAMES_COUNT;
|
i = (i + 1) % MOOSEFRAMES_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = SDL_CreateTextureFromSurface(renderer, MooseYUVSurfaces[i]);
|
tmp = SDL_CreateTextureFromSurface(renderer, MooseYUVSurfaces[i]);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
SDL_Log("Error %s", SDL_GetError());
|
SDL_Log("Error %s", SDL_GetError());
|
||||||
quit(7);
|
quit(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
SDL_RenderTexture(renderer, tmp, NULL, &displayrect);
|
SDL_RenderTexture(renderer, tmp, NULL, &displayrect);
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
SDL_DestroyTexture(tmp);
|
SDL_DestroyTexture(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +323,6 @@ int main(int argc, char **argv)
|
||||||
int nodelay = 0;
|
int nodelay = 0;
|
||||||
int scale = 5;
|
int scale = 5;
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
int yuv_format = SDL_PIXELFORMAT_YV12;
|
|
||||||
|
|
||||||
/* Initialize test framework */
|
/* Initialize test framework */
|
||||||
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
|
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue