Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/tests/mfplat.c | 138 +++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index fdfcf8a5d4b..879240ae1a4 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -93,6 +93,109 @@ static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOO IUnknown_Release(unk); }
+struct d3d11_resource_readback +{ + ID3D11Resource *resource; + D3D11_MAPPED_SUBRESOURCE map_desc; + ID3D11DeviceContext *immediate_context; + unsigned int width, height, depth, sub_resource_idx; +}; + +static void init_d3d11_resource_readback(ID3D11Resource *resource, ID3D11Resource *readback_resource, + unsigned int width, unsigned int height, unsigned int depth, unsigned int sub_resource_idx, + ID3D11Device *device, struct d3d11_resource_readback *rb) +{ + HRESULT hr; + + rb->resource = readback_resource; + rb->width = width; + rb->height = height; + rb->depth = depth; + rb->sub_resource_idx = sub_resource_idx; + + ID3D11Device_GetImmediateContext(device, &rb->immediate_context); + + ID3D11DeviceContext_CopyResource(rb->immediate_context, rb->resource, resource); + if (FAILED(hr = ID3D11DeviceContext_Map(rb->immediate_context, + rb->resource, sub_resource_idx, D3D11_MAP_READ, 0, &rb->map_desc))) + { + trace("Failed to map resource, hr %#x.\n", hr); + ID3D11Resource_Release(rb->resource); + rb->resource = NULL; + ID3D11DeviceContext_Release(rb->immediate_context); + rb->immediate_context = NULL; + } +} + +static void get_d3d11_texture2d_readback(ID3D11Texture2D *texture, unsigned int sub_resource_idx, + struct d3d11_resource_readback *rb) +{ + D3D11_TEXTURE2D_DESC texture_desc; + ID3D11Resource *rb_texture; + unsigned int miplevel; + ID3D11Device *device; + HRESULT hr; + + memset(rb, 0, sizeof(*rb)); + + ID3D11Texture2D_GetDevice(texture, &device); + + ID3D11Texture2D_GetDesc(texture, &texture_desc); + texture_desc.Usage = D3D11_USAGE_STAGING; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + texture_desc.MiscFlags = 0; + if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&rb_texture))) + { + trace("Failed to create texture, hr %#x.\n", hr); + ID3D11Device_Release(device); + return; + } + + miplevel = sub_resource_idx % texture_desc.MipLevels; + init_d3d11_resource_readback((ID3D11Resource *)texture, rb_texture, + max(1, texture_desc.Width >> miplevel), + max(1, texture_desc.Height >> miplevel), + 1, sub_resource_idx, device, rb); + + ID3D11Device_Release(device); +} + +static void release_d3d11_resource_readback(struct d3d11_resource_readback *rb) +{ + ID3D11DeviceContext_Unmap(rb->immediate_context, rb->resource, rb->sub_resource_idx); + ID3D11Resource_Release(rb->resource); + ID3D11DeviceContext_Release(rb->immediate_context); +} + +static void *get_d3d11_readback_data(struct d3d11_resource_readback *rb, + unsigned int x, unsigned int y, unsigned int z, unsigned byte_width) +{ + return (BYTE *)rb->map_desc.pData + z * rb->map_desc.DepthPitch + y * rb->map_desc.RowPitch + x * byte_width; +} + +static DWORD get_d3d11_readback_u32(struct d3d11_resource_readback *rb, unsigned int x, unsigned int y, unsigned int z) +{ + return *(DWORD *)get_d3d11_readback_data(rb, x, y, z, sizeof(DWORD)); +} + +static DWORD get_d3d11_readback_color(struct d3d11_resource_readback *rb, unsigned int x, unsigned int y, unsigned int z) +{ + return get_d3d11_readback_u32(rb, x, y, z); +} + +static DWORD get_d3d11_texture_color(ID3D11Texture2D *texture, unsigned int x, unsigned int y) +{ + struct d3d11_resource_readback rb; + DWORD color; + + get_d3d11_texture2d_readback(texture, 0, &rb); + color = get_d3d11_readback_color(&rb, x, y, 0); + release_d3d11_resource_readback(&rb); + + return color; +} + static HRESULT (WINAPI *pD3D11CreateDevice)(IDXGIAdapter *adapter, D3D_DRIVER_TYPE driver_type, HMODULE swrast, UINT flags, const D3D_FEATURE_LEVEL *feature_levels, UINT levels, UINT sdk_version, ID3D11Device **device_out, D3D_FEATURE_LEVEL *obtained_feature_level, ID3D11DeviceContext **immediate_context); @@ -6201,6 +6304,7 @@ static ID3D11Device *create_d3d11_device(void)
static void test_dxgi_surface_buffer(void) { + DWORD max_length, cur_length, color; IMFDXGIBuffer *dxgi_buffer; D3D11_TEXTURE2D_DESC desc; ID3D11Texture2D *texture; @@ -6280,6 +6384,40 @@ static void test_dxgi_surface_buffer(void)
IMFDXGIBuffer_Release(dxgi_buffer);
+ /* Texture updates. */ + color = get_d3d11_texture_color(texture, 0, 0); + ok(!color, "Unexpected texture color %#x.\n", color); + + max_length = cur_length = 0; + data = NULL; + hr = IMFMediaBuffer_Lock(buffer, &data, &max_length, &cur_length); +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(max_length && max_length == cur_length, "Unexpected length %u.\n", max_length); +} + if (data) *(DWORD *)data = ~0u; + + color = get_d3d11_texture_color(texture, 0, 0); + ok(!color, "Unexpected texture color %#x.\n", color); + + hr = IMFMediaBuffer_Unlock(buffer); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + color = get_d3d11_texture_color(texture, 0, 0); +todo_wine + ok(color == ~0u, "Unexpected texture color %#x.\n", color); + + hr = IMFMediaBuffer_Lock(buffer, &data, &max_length, &cur_length); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + ok(*(DWORD *)data == ~0u, "Unexpected buffer %#x.\n", *(DWORD *)data); + + hr = IMFMediaBuffer_Unlock(buffer); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IMFMediaBuffer_Release(buffer);
ID3D11Texture2D_Release(texture);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 13 ++++++++++++- dlls/mfplat/tests/mfplat.c | 18 +++++++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 6a4f4605450..8dd076c1e9f 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -406,6 +406,17 @@ static HRESULT WINAPI d3d9_surface_buffer_Unlock(IMFMediaBuffer *iface) return hr; }
+static HRESULT WINAPI d3d9_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length) +{ + struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface); + + TRACE("%p, %u.\n", iface, current_length); + + buffer->current_length = current_length; + + return S_OK; +} + static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl = { memory_1d_2d_buffer_QueryInterface, @@ -414,7 +425,7 @@ static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl = d3d9_surface_buffer_Lock, d3d9_surface_buffer_Unlock, memory_buffer_GetCurrentLength, - memory_buffer_SetCurrentLength, + d3d9_surface_buffer_SetCurrentLength, memory_buffer_GetMaxLength, };
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 879240ae1a4..8355be18b9f 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -5852,6 +5852,7 @@ static void test_MFCreateDXSurfaceBuffer(void) { IDirect3DSurface9 *backbuffer = NULL, *surface; IDirect3DSwapChain9 *swapchain; + DWORD length, max_length; IDirect3DDevice9 *device; IMF2DBuffer2 *_2dbuffer2; IMFMediaBuffer *buffer; @@ -5859,7 +5860,6 @@ static void test_MFCreateDXSurfaceBuffer(void) BYTE *data, *data2; IMFGetService *gs; IDirect3D9 *d3d; - DWORD length; HWND window; HRESULT hr; LONG pitch; @@ -5904,17 +5904,25 @@ static void test_MFCreateDXSurfaceBuffer(void) IDirect3DSurface9_Release(surface); IMFGetService_Release(gs);
- length = 0; - hr = IMFMediaBuffer_GetMaxLength(buffer, &length); + max_length = 0; + hr = IMFMediaBuffer_GetMaxLength(buffer, &max_length); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - ok(!!length, "Unexpected length %u.\n", length); + ok(!!max_length, "Unexpected length %u.\n", max_length);
hr = IMFMediaBuffer_GetCurrentLength(buffer, &length); ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); ok(!length, "Unexpected length %u.\n", length);
- hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL); + hr = IMFMediaBuffer_SetCurrentLength(buffer, 2 * max_length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + + hr = IMFMediaBuffer_GetCurrentLength(buffer, &length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + ok(length == 2 * max_length, "Unexpected length %u.\n", length); + + hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(length == max_length, "Unexpected length.\n");
/* Unlock twice. */ hr = IMFMediaBuffer_Unlock(buffer);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 13 ++++++++++++- dlls/mfplat/tests/mfplat.c | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 8dd076c1e9f..3710843fd52 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -856,6 +856,17 @@ static HRESULT WINAPI dxgi_surface_buffer_Unlock(IMFMediaBuffer *iface) return E_NOTIMPL; }
+static HRESULT WINAPI dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length) +{ + struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface); + + TRACE("%p, %u.\n", iface, current_length); + + buffer->current_length = current_length; + + return S_OK; +} + static HRESULT WINAPI dxgi_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch) { FIXME("%p, %p, %p.\n", iface, scanline0, pitch); @@ -977,7 +988,7 @@ static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl = dxgi_surface_buffer_Lock, dxgi_surface_buffer_Unlock, memory_buffer_GetCurrentLength, - memory_buffer_SetCurrentLength, + dxgi_surface_buffer_SetCurrentLength, memory_buffer_GetMaxLength, };
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 8355be18b9f..1c236bdb655 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -6350,6 +6350,22 @@ static void test_dxgi_surface_buffer(void) check_interface(buffer, &IID_IMFDXGIBuffer, TRUE); check_interface(buffer, &IID_IMFGetService, FALSE);
+ max_length = 0; + hr = IMFMediaBuffer_GetMaxLength(buffer, &max_length); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!max_length, "Unexpected length %u.\n", max_length); + + hr = IMFMediaBuffer_GetCurrentLength(buffer, &cur_length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + ok(!cur_length, "Unexpected length %u.\n", cur_length); + + hr = IMFMediaBuffer_SetCurrentLength(buffer, 2 * max_length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + + hr = IMFMediaBuffer_GetCurrentLength(buffer, &cur_length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + ok(cur_length == 2 * max_length, "Unexpected length %u.\n", cur_length); + hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMFDXGIBuffer, (void **)&dxgi_buffer); ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 9 +-------- dlls/mfplat/tests/mfplat.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 3710843fd52..3c0f02709ee 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -888,13 +888,6 @@ static HRESULT WINAPI dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *ifa return E_NOTIMPL; }
-static HRESULT WINAPI dxgi_surface_buffer_GetContiguousLength(IMF2DBuffer2 *iface, DWORD *length) -{ - FIXME("%p, %p.\n", iface, length); - - return E_NOTIMPL; -} - static HRESULT WINAPI dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0, LONG *pitch, BYTE **buffer_start, DWORD *buffer_length) { @@ -1001,7 +994,7 @@ static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl = dxgi_surface_buffer_Unlock2D, dxgi_surface_buffer_GetScanline0AndPitch, memory_2d_buffer_IsContiguousFormat, - dxgi_surface_buffer_GetContiguousLength, + memory_2d_buffer_GetContiguousLength, memory_2d_buffer_ContiguousCopyTo, memory_2d_buffer_ContiguousCopyFrom, dxgi_surface_buffer_Lock2DSize, diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 1c236bdb655..aa6c0e28da6 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -6312,10 +6312,11 @@ static ID3D11Device *create_d3d11_device(void)
static void test_dxgi_surface_buffer(void) { - DWORD max_length, cur_length, color; + DWORD max_length, cur_length, length, color; IMFDXGIBuffer *dxgi_buffer; D3D11_TEXTURE2D_DESC desc; ID3D11Texture2D *texture; + IMF2DBuffer *_2d_buffer; IMFMediaBuffer *buffer; ID3D11Device *device; UINT index, size; @@ -6366,6 +6367,16 @@ static void test_dxgi_surface_buffer(void) ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); ok(cur_length == 2 * max_length, "Unexpected length %u.\n", cur_length);
+ hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer, (void **)&_2d_buffer); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_GetContiguousLength(_2d_buffer, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + hr = IMF2DBuffer_GetContiguousLength(_2d_buffer, &length); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(length == max_length, "Unexpected length %u.\n", length); + IMF2DBuffer_Release(_2d_buffer); + hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMFDXGIBuffer, (void **)&dxgi_buffer); ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 9 +-------- dlls/mfplat/tests/mfplat.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 3c0f02709ee..abfb3e738d7 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -697,13 +697,6 @@ static HRESULT WINAPI d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *ifa return hr; }
-static HRESULT WINAPI d3d9_surface_buffer_GetContiguousLength(IMF2DBuffer2 *iface, DWORD *length) -{ - FIXME("%p, %p.\n", iface, length); - - return E_NOTIMPL; -} - static HRESULT WINAPI d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0, LONG *pitch, BYTE **buffer_start, DWORD *buffer_length) { @@ -748,7 +741,7 @@ static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl = d3d9_surface_buffer_Unlock2D, d3d9_surface_buffer_GetScanline0AndPitch, memory_2d_buffer_IsContiguousFormat, - d3d9_surface_buffer_GetContiguousLength, + memory_2d_buffer_GetContiguousLength, memory_2d_buffer_ContiguousCopyTo, memory_2d_buffer_ContiguousCopyFrom, d3d9_surface_buffer_Lock2DSize, diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index aa6c0e28da6..b2b595b8fe7 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -5895,6 +5895,10 @@ static void test_MFCreateDXSurfaceBuffer(void) hr = pMFCreateDXSurfaceBuffer(&IID_IDirect3DSurface9, (IUnknown *)backbuffer, FALSE, &buffer); ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
+ check_interface(buffer, &IID_IMF2DBuffer, TRUE); + check_interface(buffer, &IID_IMF2DBuffer2, TRUE); + check_interface(buffer, &IID_IMFGetService, TRUE); + /* Surface is accessible. */ hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMFGetService, (void **)&gs); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); @@ -5977,6 +5981,12 @@ static void test_MFCreateDXSurfaceBuffer(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(!value, "Unexpected return value %d.\n", value);
+ hr = IMF2DBuffer_GetContiguousLength(_2dbuffer, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + hr = IMF2DBuffer_GetContiguousLength(_2dbuffer, &length); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(length == max_length, "Unexpected length %u.\n", length); + IMF2DBuffer_Release(_2dbuffer);
hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer2, (void **)&_2dbuffer2);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index abfb3e738d7..cf9ead7d809 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -63,7 +63,7 @@ struct memory_buffer } d3d9_surface; struct { - IUnknown *surface; + ID3D11Texture2D *texture; unsigned int subresource; struct attributes attributes; } dxgi_surface; @@ -131,9 +131,9 @@ static ULONG WINAPI memory_buffer_Release(IMFMediaBuffer *iface) { if (buffer->d3d9_surface.surface) IDirect3DSurface9_Release(buffer->d3d9_surface.surface); - if (buffer->dxgi_surface.surface) + if (buffer->dxgi_surface.texture) { - IUnknown_Release(buffer->dxgi_surface.surface); + ID3D11Texture2D_Release(buffer->dxgi_surface.texture); clear_attributes_object(&buffer->dxgi_surface.attributes); } DeleteCriticalSection(&buffer->cs); @@ -913,7 +913,7 @@ static HRESULT WINAPI dxgi_buffer_GetResource(IMFDXGIBuffer *iface, REFIID riid,
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
- return IUnknown_QueryInterface(buffer->dxgi_surface.surface, riid, obj); + return ID3D11Texture2D_QueryInterface(buffer->dxgi_surface.texture, riid, obj); }
static HRESULT WINAPI dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer *iface, UINT *index) @@ -1170,32 +1170,44 @@ static HRESULT create_dxgi_surface_buffer(IUnknown *surface, UINT subresource, B { struct memory_buffer *object; D3D11_TEXTURE2D_DESC desc; + ID3D11Texture2D *texture; unsigned int stride; D3DFORMAT format; GUID subtype; BOOL is_yuv; HRESULT hr;
- ID3D11Texture2D_GetDesc((ID3D11Texture2D *)surface, &desc); + if (FAILED(hr = IUnknown_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture))) + { + WARN("Failed to get texture interface, hr %#x.\n", hr); + return hr; + } + + ID3D11Texture2D_GetDesc(texture, &desc); TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype)); subtype.Data1 = format = MFMapDXGIFormatToDX9Format(desc.Format);
if (!(stride = mf_format_get_stride(&subtype, desc.Width, &is_yuv))) + { + ID3D11Texture2D_Release(texture); return MF_E_INVALIDMEDIATYPE; + }
object = heap_alloc_zero(sizeof(*object)); if (!object) + { + ID3D11Texture2D_Release(texture); return E_OUTOFMEMORY; + }
object->IMFMediaBuffer_iface.lpVtbl = &dxgi_surface_1d_buffer_vtbl; object->IMF2DBuffer2_iface.lpVtbl = &dxgi_surface_buffer_vtbl; object->IMFDXGIBuffer_iface.lpVtbl = &dxgi_buffer_vtbl; object->refcount = 1; InitializeCriticalSection(&object->cs); - object->dxgi_surface.surface = surface; - IUnknown_AddRef(surface); + object->dxgi_surface.texture = texture; object->dxgi_surface.subresource = subresource;
MFGetPlaneSize(format, desc.Width, desc.Height, &object->_2d.plane_size);