From: Brendan McGrath bmcgrath@codeweavers.com
Using IMF2DBuffer2_Lock2DSize with LockFlags_Write dramatically improves performance over IMFMediaBuffer_Lock when using a DXGI buffer.
IMFMediaBuffer_Lock does not know that this buffer will not be read and therefore performs an unnecessary transfer of the texture from GPU to CPU before it is overwritten. --- dlls/winegstreamer/wg_sample.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c index 116dbb1f3ec..08acc650b46 100644 --- a/dlls/winegstreamer/wg_sample.c +++ b/dlls/winegstreamer/wg_sample.c @@ -52,6 +52,7 @@ struct sample { IMFSample *sample; IMFMediaBuffer *buffer; + IMF2DBuffer2 *buffer2d2; } mf; struct { @@ -79,7 +80,15 @@ static void mf_sample_destroy(struct wg_sample *wg_sample)
TRACE_(mfplat)("wg_sample %p.\n", wg_sample);
- IMFMediaBuffer_Unlock(sample->u.mf.buffer); + if (sample->u.mf.buffer2d2) + { + IMF2DBuffer2_Unlock2D(sample->u.mf.buffer2d2); + IMF2DBuffer2_Release(sample->u.mf.buffer2d2); + } + else + { + IMFMediaBuffer_Unlock(sample->u.mf.buffer); + } IMFMediaBuffer_Release(sample->u.mf.buffer); IMFSample_Release(sample->u.mf.sample); } @@ -92,15 +101,25 @@ static const struct wg_sample_ops mf_sample_ops = HRESULT wg_sample_create_mf(IMFSample *mf_sample, struct wg_sample **out) { DWORD current_length, max_length; + LONG pitch; struct sample *sample; - BYTE *buffer; + BYTE *buffer, *scanline; HRESULT hr;
if (!(sample = calloc(1, sizeof(*sample)))) return E_OUTOFMEMORY; if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(mf_sample, &sample->u.mf.buffer))) goto fail; - if (FAILED(hr = IMFMediaBuffer_Lock(sample->u.mf.buffer, &buffer, &max_length, ¤t_length))) + if (SUCCEEDED(hr = IMFMediaBuffer_QueryInterface(sample->u.mf.buffer, &IID_IMF2DBuffer2, (void**)&sample->u.mf.buffer2d2)) && + FAILED(hr = IMF2DBuffer2_Lock2DSize(sample->u.mf.buffer2d2, MF2DBuffer_LockFlags_Write, &scanline, &pitch, &buffer, &max_length))) + { + IMF2DBuffer2_Release(sample->u.mf.buffer2d2); + sample->u.mf.buffer2d2 = NULL; + } + + if (SUCCEEDED(hr)) + current_length = max_length; + else if (FAILED(hr = IMFMediaBuffer_Lock(sample->u.mf.buffer, &buffer, &max_length, ¤t_length))) goto fail;
IMFSample_AddRef((sample->u.mf.sample = mf_sample));