From: Conor McCarthy cmccarthy@codeweavers.com
Windows supports this. Media engine apparently performs a format conversion, because the session engine does not support R10G10B10A2 output. --- dlls/mfmediaengine/tests/mfmediaengine.c | 125 +++++++++++++++++++++-- 1 file changed, 116 insertions(+), 9 deletions(-)
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index fbaeff50710..699729b388f 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -164,6 +164,88 @@ static DWORD check_rgb32_data_(int line, const WCHAR *filename, const BYTE *data return compare_rgb32(data, &length, &size, rect, expect_data); }
+static void copy_incompatible_texture(ID3D11Device *device, ID3D11Texture2D *dst_texture, ID3D11Texture2D *src_texture) +{ + static const DWORD vs_code[] = + { +#if 0 + float4 main(uint id : SV_VertexID) : SV_Position + { + float2 coords = float2((id << 1) & 2, id & 2); + return float4(coords * float2(2, -2) + float2(-1, 1), 0, 1); + } +#endif + 0x43425844, 0xc043b4bc, 0x0b0f81de, 0xa321bd68, 0x20a77cda, 0x00000001, 0x0000018c, 0x00000003, + 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, + 0x00000000, 0x00000006, 0x00000001, 0x00000000, 0x00000101, 0x565f5653, 0x65747265, 0x00444978, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, + 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x58454853, 0x000000f0, 0x00010050, + 0x0000003c, 0x0100086a, 0x04000060, 0x00101012, 0x00000000, 0x00000006, 0x04000067, 0x001020f2, + 0x00000000, 0x00000001, 0x02000068, 0x00000001, 0x0b00008c, 0x00100012, 0x00000000, 0x00004001, + 0x00000001, 0x00004001, 0x00000001, 0x0010100a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, + 0x00100042, 0x00000000, 0x0010100a, 0x00000000, 0x00004001, 0x00000002, 0x05000056, 0x00100032, + 0x00000000, 0x00100086, 0x00000000, 0x0f000032, 0x00102032, 0x00000000, 0x00100046, 0x00000000, + 0x00004002, 0x40000000, 0xc0000000, 0x00000000, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, + 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x0100003e, + }; + static const DWORD ps_code[] = + { +#if 0 + Texture2D t; + + float4 main(float4 position : SV_Position) : SV_Target + { + return t.Load(int3(position.xy - float2(0.5, 0.5), 0)); + } +#endif + 0x43425844, 0x87384727, 0x8580bfc0, 0x79c76629, 0x139879c6, 0x00000001, 0x00000160, 0x00000003, + 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, + 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x58454853, 0x000000c4, 0x00000050, + 0x00000031, 0x0100086a, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, + 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000000, + 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0xbf000000, 0xbf000000, 0x00000000, + 0x00000000, 0x0500001b, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x08000036, 0x001000c2, + 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8900002d, 0x800000c2, + 0x00155543, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, 0x00000000, 0x0100003e, + }; + ID3D11ShaderResourceView *srv; + ID3D11DeviceContext *context; + ID3D11RenderTargetView *rtv; + ID3D11VertexShader *vs; + ID3D11PixelShader *ps; + HRESULT hr; + + hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)src_texture, NULL, &srv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)dst_texture, NULL, &rtv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + ID3D11Device_GetImmediateContext(device, &context); + + ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0); + ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); + ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); + ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); + + ID3D11DeviceContext_Draw(context, 4, 0); + + ID3D11ShaderResourceView_Release(srv); + ID3D11RenderTargetView_Release(rtv); + ID3D11VertexShader_Release(vs); + ID3D11PixelShader_Release(ps); + ID3D11DeviceContext_Release(context); +} + static void init_functions(void) { HMODULE mod; @@ -1228,7 +1310,8 @@ static HRESULT WINAPI test_transfer_notify_EventNotify(IMFMediaEngineNotify *ifa break;
case MF_MEDIA_ENGINE_EVENT_ERROR: - ok(broken(param2 == MF_E_UNSUPPORTED_BYTESTREAM_TYPE), "Unexpected error %#lx\n", param2); + ok(broken(param2 == MF_E_UNSUPPORTED_BYTESTREAM_TYPE || param2 == MF_E_INVALIDMEDIATYPE), + "Unexpected error %#lx\n", param2); notify->error = param2; /* fallthrough */ case MF_MEDIA_ENGINE_EVENT_FIRSTFRAMEREADY: @@ -1266,10 +1349,11 @@ static struct test_transfer_notify *create_transfer_notify(void) return object; }
-static void test_TransferVideoFrame(void) +static void test_TransferVideoFrame(DXGI_FORMAT format) { struct test_transfer_notify *notify; - ID3D11Texture2D *texture = NULL, *rb_texture; + BOOL needs_copy = format == DXGI_FORMAT_R10G10B10A2_UNORM; + ID3D11Texture2D *texture = NULL, *frame_texture, *rb_texture; D3D11_MAPPED_SUBRESOURCE map_desc; IMFMediaEngineEx *media_engine = NULL; IMFDXGIDeviceManager *manager; @@ -1284,6 +1368,8 @@ static void test_TransferVideoFrame(void) BSTR url; LONGLONG pts;
+ winetest_push_context(format == DXGI_FORMAT_R10G10B10A2_UNORM ? "R10G10B10A2" : "B8G8R8X8"); + stream = load_resource(L"i420-64x64.avi", L"video/avi");
notify = create_transfer_notify(); @@ -1299,7 +1385,7 @@ static void test_TransferVideoFrame(void) hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)device, token); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- create_media_engine(¬ify->IMFMediaEngineNotify_iface, manager, DXGI_FORMAT_B8G8R8X8_UNORM, + create_media_engine(¬ify->IMFMediaEngineNotify_iface, manager, format, &IID_IMFMediaEngineEx, (void **)&media_engine);
IMFDXGIDeviceManager_Release(manager); @@ -1311,11 +1397,22 @@ static void test_TransferVideoFrame(void) desc.Width = 64; desc.Height = 64; desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_B8G8R8X8_UNORM; - desc.BindFlags = D3D11_BIND_RENDER_TARGET; + desc.Format = format; + desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; desc.SampleDesc.Count = 1; hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (needs_copy) + { + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + desc.BindFlags = D3D11_BIND_RENDER_TARGET; + hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &frame_texture); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } + else + { + frame_texture = texture; + }
url = SysAllocString(L"i420-64x64.avi"); hr = IMFMediaEngineEx_SetSourceFromByteStream(media_engine, stream, url); @@ -1348,7 +1445,7 @@ static void test_TransferVideoFrame(void) hr = IMFMediaEngineEx_TransferVideoFrame(notify->media_engine, (IUnknown *)texture, NULL, &dst_rect, NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- ID3D11Texture2D_GetDesc(texture, &desc); + ID3D11Texture2D_GetDesc(frame_texture, &desc); desc.Usage = D3D11_USAGE_STAGING; desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; @@ -1356,9 +1453,13 @@ static void test_TransferVideoFrame(void) hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &rb_texture); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ if (needs_copy) + /* R10G10B10A2 equivalents in openGL and Vulkan are not binary compatible with R10G10B10A2 */ + copy_incompatible_texture(device, frame_texture, texture); + ID3D11Device_GetImmediateContext(device, &context); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)rb_texture, - 0, 0, 0, 0, (ID3D11Resource *)texture, 0, NULL); + 0, 0, 0, 0, (ID3D11Resource *)frame_texture, 0, NULL);
memset(&map_desc, 0, sizeof(map_desc)); hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)rb_texture, 0, D3D11_MAP_READ, 0, &map_desc); @@ -1367,6 +1468,7 @@ static void test_TransferVideoFrame(void) ok(map_desc.DepthPitch == 16384, "got DepthPitch %u\n", map_desc.DepthPitch); ok(map_desc.RowPitch == desc.Width * 4, "got RowPitch %u\n", map_desc.RowPitch); res = check_rgb32_data(L"rgb32frame.bmp", map_desc.pData, map_desc.RowPitch * desc.Height, &dst_rect); + todo_wine_if(needs_copy) ok(res == 0, "Unexpected %lu%% diff\n", res); ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)rb_texture, 0);
@@ -1382,10 +1484,14 @@ done:
if (texture) ID3D11Texture2D_Release(texture); + if (needs_copy) + ID3D11Texture2D_Release(frame_texture); if (device) ID3D11Device_Release(device);
IMFMediaEngineNotify_Release(¬ify->IMFMediaEngineNotify_iface); + + winetest_pop_context(); }
struct test_transform @@ -2712,7 +2818,8 @@ START_TEST(mfmediaengine) test_time_range(); test_SetSourceFromByteStream(); test_audio_configuration(); - test_TransferVideoFrame(); + test_TransferVideoFrame(DXGI_FORMAT_B8G8R8X8_UNORM); + test_TransferVideoFrame(DXGI_FORMAT_R10G10B10A2_UNORM); test_effect(); test_GetDuration(); test_GetSeekable();