mfplat: Implement Lock2D()/Unlock2D() for d3d11 buffer.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e7b42deaf2
commit
9932a1943b
|
@ -64,7 +64,9 @@ struct memory_buffer
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
ID3D11Texture2D *texture;
|
ID3D11Texture2D *texture;
|
||||||
unsigned int subresource;
|
unsigned int sub_resource_idx;
|
||||||
|
ID3D11Texture2D *rb_texture;
|
||||||
|
D3D11_MAPPED_SUBRESOURCE map_desc;
|
||||||
struct attributes attributes;
|
struct attributes attributes;
|
||||||
} dxgi_surface;
|
} dxgi_surface;
|
||||||
|
|
||||||
|
@ -134,6 +136,8 @@ static ULONG WINAPI memory_buffer_Release(IMFMediaBuffer *iface)
|
||||||
if (buffer->dxgi_surface.texture)
|
if (buffer->dxgi_surface.texture)
|
||||||
{
|
{
|
||||||
ID3D11Texture2D_Release(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);
|
clear_attributes_object(&buffer->dxgi_surface.attributes);
|
||||||
}
|
}
|
||||||
DeleteCriticalSection(&buffer->cs);
|
DeleteCriticalSection(&buffer->cs);
|
||||||
|
@ -834,6 +838,75 @@ static HRESULT WINAPI dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer *iface, RE
|
||||||
return S_OK;
|
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,
|
static HRESULT WINAPI dxgi_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length,
|
||||||
DWORD *current_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)
|
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)
|
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)
|
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)
|
if (!index)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
*index = buffer->dxgi_surface.subresource;
|
*index = buffer->dxgi_surface.sub_resource_idx;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1165,8 +1274,8 @@ static HRESULT create_d3d9_surface_buffer(IUnknown *surface, BOOL bottom_up, IMF
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT create_dxgi_surface_buffer(IUnknown *surface, UINT subresource, BOOL bottom_up,
|
static HRESULT create_dxgi_surface_buffer(IUnknown *surface, unsigned int sub_resource_idx,
|
||||||
IMFMediaBuffer **buffer)
|
BOOL bottom_up, IMFMediaBuffer **buffer)
|
||||||
{
|
{
|
||||||
struct memory_buffer *object;
|
struct memory_buffer *object;
|
||||||
D3D11_TEXTURE2D_DESC desc;
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
@ -1208,7 +1317,7 @@ static HRESULT create_dxgi_surface_buffer(IUnknown *surface, UINT subresource, B
|
||||||
object->refcount = 1;
|
object->refcount = 1;
|
||||||
InitializeCriticalSection(&object->cs);
|
InitializeCriticalSection(&object->cs);
|
||||||
object->dxgi_surface.texture = texture;
|
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);
|
MFGetPlaneSize(format, desc.Width, desc.Height, &object->_2d.plane_size);
|
||||||
object->_2d.width = stride;
|
object->_2d.width = stride;
|
||||||
|
|
|
@ -6320,6 +6320,22 @@ static ID3D11Device *create_d3d11_device(void)
|
||||||
return NULL;
|
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)
|
static void test_dxgi_surface_buffer(void)
|
||||||
{
|
{
|
||||||
DWORD max_length, cur_length, length, color;
|
DWORD max_length, cur_length, length, color;
|
||||||
|
@ -6329,10 +6345,12 @@ static void test_dxgi_surface_buffer(void)
|
||||||
IMF2DBuffer *_2d_buffer;
|
IMF2DBuffer *_2d_buffer;
|
||||||
IMFMediaBuffer *buffer;
|
IMFMediaBuffer *buffer;
|
||||||
ID3D11Device *device;
|
ID3D11Device *device;
|
||||||
|
BYTE buff[64 * 64 * 4];
|
||||||
UINT index, size;
|
UINT index, size;
|
||||||
IUnknown *obj;
|
IUnknown *obj;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
BYTE *data;
|
BYTE *data;
|
||||||
|
LONG pitch;
|
||||||
|
|
||||||
if (!pMFCreateDXGISurfaceBuffer)
|
if (!pMFCreateDXGISurfaceBuffer)
|
||||||
{
|
{
|
||||||
|
@ -6463,6 +6481,60 @@ todo_wine
|
||||||
todo_wine
|
todo_wine
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
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);
|
IMFMediaBuffer_Release(buffer);
|
||||||
|
|
||||||
ID3D11Texture2D_Release(texture);
|
ID3D11Texture2D_Release(texture);
|
||||||
|
|
Loading…
Reference in New Issue