[PATCH 1/5] mfplat: Implement Lock2D()/Unlock2D() for d3d11 buffer.
Nikolay Sivov
nsivov at codeweavers.com
Thu Mar 25 04:40:31 CDT 2021
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfplat/buffer.c | 127 ++++++++++++++++++++++++++++++++++---
dlls/mfplat/tests/mfplat.c | 72 +++++++++++++++++++++
2 files changed, 190 insertions(+), 9 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index cf9ead7d809..fbd3b7786b6 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -64,7 +64,9 @@ struct memory_buffer
struct
{
ID3D11Texture2D *texture;
- unsigned int subresource;
+ unsigned int sub_resource_idx;
+ ID3D11Texture2D *rb_texture;
+ D3D11_MAPPED_SUBRESOURCE map_desc;
struct attributes attributes;
} dxgi_surface;
@@ -134,6 +136,8 @@ static ULONG WINAPI memory_buffer_Release(IMFMediaBuffer *iface)
if (buffer->dxgi_surface.texture)
{
ID3D11Texture2D_Release(buffer->dxgi_surface.texture);
+ if (buffer->dxgi_surface.rb_texture)
+ ID3D11Texture2D_Release(buffer->dxgi_surface.rb_texture);
clear_attributes_object(&buffer->dxgi_surface.attributes);
}
DeleteCriticalSection(&buffer->cs);
@@ -834,6 +838,75 @@ static HRESULT WINAPI dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer *iface, RE
return S_OK;
}
+static HRESULT dxgi_surface_buffer_create_readback_texture(struct memory_buffer *buffer)
+{
+ D3D11_TEXTURE2D_DESC texture_desc;
+ ID3D11Device *device;
+ HRESULT hr;
+
+ if (buffer->dxgi_surface.rb_texture)
+ return S_OK;
+
+ ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
+
+ ID3D11Texture2D_GetDesc(buffer->dxgi_surface.texture, &texture_desc);
+ texture_desc.Usage = D3D11_USAGE_STAGING;
+ texture_desc.BindFlags = 0;
+ texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ texture_desc.MiscFlags = 0;
+ texture_desc.MipLevels = 1;
+ if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &buffer->dxgi_surface.rb_texture)))
+ WARN("Failed to create readback texture, hr %#x.\n", hr);
+
+ ID3D11Device_Release(device);
+
+ return hr;
+}
+
+static HRESULT dxgi_surface_buffer_map(struct memory_buffer *buffer)
+{
+ ID3D11DeviceContext *immediate_context;
+ ID3D11Device *device;
+ HRESULT hr;
+
+ if (FAILED(hr = dxgi_surface_buffer_create_readback_texture(buffer)))
+ return hr;
+
+ ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
+ ID3D11Device_GetImmediateContext(device, &immediate_context);
+ ID3D11DeviceContext_CopySubresourceRegion(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture,
+ 0, 0, 0, 0, (ID3D11Resource *)buffer->dxgi_surface.texture, buffer->dxgi_surface.sub_resource_idx, NULL);
+
+ memset(&buffer->dxgi_surface.map_desc, 0, sizeof(buffer->dxgi_surface.map_desc));
+ if (FAILED(hr = ID3D11DeviceContext_Map(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture,
+ 0, D3D11_MAP_READ_WRITE, 0, &buffer->dxgi_surface.map_desc)))
+ {
+ WARN("Failed to map readback texture, hr %#x.\n", hr);
+ }
+
+ ID3D11DeviceContext_Release(immediate_context);
+ ID3D11Device_Release(device);
+
+ return hr;
+}
+
+static void dxgi_surface_buffer_unmap(struct memory_buffer *buffer)
+{
+ ID3D11DeviceContext *immediate_context;
+ ID3D11Device *device;
+
+ ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
+ ID3D11Device_GetImmediateContext(device, &immediate_context);
+ ID3D11DeviceContext_Unmap(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture, 0);
+ memset(&buffer->dxgi_surface.map_desc, 0, sizeof(buffer->dxgi_surface.map_desc));
+
+ ID3D11DeviceContext_CopySubresourceRegion(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.texture,
+ buffer->dxgi_surface.sub_resource_idx, 0, 0, 0, (ID3D11Resource *)buffer->dxgi_surface.rb_texture, 0, NULL);
+
+ ID3D11DeviceContext_Release(immediate_context);
+ ID3D11Device_Release(device);
+}
+
static HRESULT WINAPI dxgi_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length,
DWORD *current_length)
{
@@ -862,16 +935,52 @@ static HRESULT WINAPI dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface
static HRESULT WINAPI dxgi_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
{
- FIXME("%p, %p, %p.\n", iface, scanline0, pitch);
+ struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
+
+ if (!scanline0 || !pitch)
+ return E_POINTER;
+
+ EnterCriticalSection(&buffer->cs);
+
+ if (buffer->_2d.linear_buffer)
+ hr = MF_E_UNEXPECTED;
+ else if (!buffer->_2d.locks++)
+ hr = dxgi_surface_buffer_map(buffer);
+
+ if (SUCCEEDED(hr))
+ {
+ *scanline0 = buffer->dxgi_surface.map_desc.pData;
+ *pitch = buffer->dxgi_surface.map_desc.RowPitch;
+ }
+
+ LeaveCriticalSection(&buffer->cs);
+
+ return hr;
}
static HRESULT WINAPI dxgi_surface_buffer_Unlock2D(IMF2DBuffer2 *iface)
{
- FIXME("%p.\n", iface);
+ struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p.\n", iface);
+
+ EnterCriticalSection(&buffer->cs);
+
+ if (buffer->_2d.locks)
+ {
+ if (!--buffer->_2d.locks)
+ dxgi_surface_buffer_unmap(buffer);
+ }
+ else
+ hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
+
+ LeaveCriticalSection(&buffer->cs);
+
+ return hr;
}
static HRESULT WINAPI dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
@@ -925,7 +1034,7 @@ static HRESULT WINAPI dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer *iface, UINT
if (!index)
return E_POINTER;
- *index = buffer->dxgi_surface.subresource;
+ *index = buffer->dxgi_surface.sub_resource_idx;
return S_OK;
}
@@ -1165,8 +1274,8 @@ static HRESULT create_d3d9_surface_buffer(IUnknown *surface, BOOL bottom_up, IMF
return S_OK;
}
-static HRESULT create_dxgi_surface_buffer(IUnknown *surface, UINT subresource, BOOL bottom_up,
- IMFMediaBuffer **buffer)
+static HRESULT create_dxgi_surface_buffer(IUnknown *surface, unsigned int sub_resource_idx,
+ BOOL bottom_up, IMFMediaBuffer **buffer)
{
struct memory_buffer *object;
D3D11_TEXTURE2D_DESC desc;
@@ -1208,7 +1317,7 @@ static HRESULT create_dxgi_surface_buffer(IUnknown *surface, UINT subresource, B
object->refcount = 1;
InitializeCriticalSection(&object->cs);
object->dxgi_surface.texture = texture;
- object->dxgi_surface.subresource = subresource;
+ object->dxgi_surface.sub_resource_idx = sub_resource_idx;
MFGetPlaneSize(format, desc.Width, desc.Height, &object->_2d.plane_size);
object->_2d.width = stride;
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index b2b595b8fe7..dacad924ae9 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -6320,6 +6320,22 @@ static ID3D11Device *create_d3d11_device(void)
return NULL;
}
+static void update_d3d11_texture(ID3D11Texture2D *texture, unsigned int sub_resource_idx,
+ const BYTE *data, unsigned int src_pitch)
+{
+ ID3D11DeviceContext *immediate_context;
+ ID3D11Device *device;
+
+ ID3D11Texture2D_GetDevice(texture, &device);
+ ID3D11Device_GetImmediateContext(device, &immediate_context);
+
+ ID3D11DeviceContext_UpdateSubresource(immediate_context, (ID3D11Resource *)texture,
+ sub_resource_idx, NULL, data, src_pitch, 0);
+
+ ID3D11DeviceContext_Release(immediate_context);
+ ID3D11Device_Release(device);
+}
+
static void test_dxgi_surface_buffer(void)
{
DWORD max_length, cur_length, length, color;
@@ -6329,10 +6345,12 @@ static void test_dxgi_surface_buffer(void)
IMF2DBuffer *_2d_buffer;
IMFMediaBuffer *buffer;
ID3D11Device *device;
+ BYTE buff[64 * 64 * 4];
UINT index, size;
IUnknown *obj;
HRESULT hr;
BYTE *data;
+ LONG pitch;
if (!pMFCreateDXGISurfaceBuffer)
{
@@ -6463,6 +6481,60 @@ todo_wine
todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ /* Lock2D()/Unlock2D() */
+ hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer, (void **)&_2d_buffer);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMF2DBuffer_Lock2D(_2d_buffer, &data, &pitch);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!!data && pitch == desc.Width * 4, "Unexpected pitch %d.\n", pitch);
+
+ hr = IMF2DBuffer_Lock2D(_2d_buffer, &data, &pitch);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!!data && pitch == desc.Width * 4, "Unexpected pitch %d.\n", pitch);
+
+ hr = IMFMediaBuffer_Lock(buffer, &data, &max_length, &cur_length);
+todo_wine
+ ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr);
+
+ hr = IMF2DBuffer_Unlock2D(_2d_buffer);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMF2DBuffer_Unlock2D(_2d_buffer);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMF2DBuffer_Unlock2D(_2d_buffer);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED), "Unexpected hr %#x.\n", hr);
+
+ IMF2DBuffer_Release(_2d_buffer);
+ IMFMediaBuffer_Release(buffer);
+
+ ID3D11Texture2D_Release(texture);
+
+ /* Subresource index 1. */
+ hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture);
+ ok(hr == S_OK, "Failed to create a texture, hr %#x.\n", hr);
+
+ hr = pMFCreateDXGISurfaceBuffer(&IID_ID3D11Texture2D, (IUnknown *)texture, 1, FALSE, &buffer);
+ ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
+
+ hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer, (void **)&_2d_buffer);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ /* Pitch reflects top level. */
+ memset(buff, 0, sizeof(buff));
+ *(DWORD *)buff = 0xff00ff00;
+ update_d3d11_texture(texture, 1, buff, 64 * 4);
+
+ hr = IMF2DBuffer_Lock2D(_2d_buffer, &data, &pitch);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(pitch == desc.Width * 4, "Unexpected pitch %d.\n", pitch);
+ ok(*(DWORD *)data == 0xff00ff00, "Unexpected color %#x.\n", *(DWORD *)data);
+
+ hr = IMF2DBuffer_Unlock2D(_2d_buffer);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ IMF2DBuffer_Release(_2d_buffer);
IMFMediaBuffer_Release(buffer);
ID3D11Texture2D_Release(texture);
--
2.30.2
More information about the wine-devel
mailing list