From: Zebediah Figura zfigura@codeweavers.com
--- dlls/quartz/tests/vmr7.c | 7 +- dlls/quartz/vmr7.c | 753 ++++----------------------------------- 2 files changed, 77 insertions(+), 683 deletions(-)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index fda4c6d46d8..7cb94338126 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -1288,7 +1288,9 @@ static void test_current_image(IBaseFilter *filter, IMemInputPin *input,
size = sizeof(buffer); hr = IBasicVideo_GetCurrentImage(video, &size, buffer); - ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr != S_OK) + goto out; ok(size == sizeof(buffer), "Got size %ld.\n", size); ok(!memcmp(bih, &expect_bih, sizeof(BITMAPINFOHEADER)), "Bitmap headers didn't match.\n"); /* The contents seem to reflect the last frame rendered. */ @@ -1339,6 +1341,7 @@ static void test_current_image(IBaseFilter *filter, IMemInputPin *input, hr = IMediaControl_Stop(control); ok(hr == S_OK, "Got hr %#lx.\n", hr);
+out: IBasicVideo_Release(video); }
@@ -1495,7 +1498,7 @@ static void test_connect_pin(void)
vih.bmiHeader.biBitCount = 16; hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt); - ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr); + todo_wine ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
vih.bmiHeader.biBitCount = 32; hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt); diff --git a/dlls/quartz/vmr7.c b/dlls/quartz/vmr7.c index 4770543b614..5b1b13b7436 100644 --- a/dlls/quartz/vmr7.c +++ b/dlls/quartz/vmr7.c @@ -63,18 +63,14 @@ struct vmr7 IAMVideoAccelerator IAMVideoAccelerator_iface; IOverlay IOverlay_iface;
- IVMRSurfaceAllocator9 *allocator; - IVMRImagePresenter9 *presenter; - DWORD stream_count; DWORD mixing_prefs;
VMRMode mode;
- HMODULE d3d9_module; - - IDirect3DDevice9 *device; - IDirect3DSurface9 **surfaces; + IVMRSurfaceAllocator *allocator; + IVMRImagePresenter *presenter; + IDirectDrawSurface7 **surfaces; DWORD surface_count; DWORD surface_index; DWORD_PTR cookie; @@ -124,36 +120,6 @@ static struct vmr7 *impl_from_IVMRWindowlessControl(IVMRWindowlessControl *iface return CONTAINING_RECORD(iface, struct vmr7, IVMRWindowlessControl_iface); }
-struct default_presenter -{ - IVMRImagePresenter9 IVMRImagePresenter9_iface; - IVMRSurfaceAllocator9 IVMRSurfaceAllocator9_iface; - - LONG refcount; - - IDirect3DDevice9 *device; - IDirect3D9 *d3d9; - IDirect3DSurface9 **surfaces; - HMONITOR monitor; - DWORD surface_count; - - VMR9AllocationInfo info; - - struct vmr7 *vmr; -}; - -static struct default_presenter *impl_from_IVMRImagePresenter9(IVMRImagePresenter9 *iface) -{ - return CONTAINING_RECORD(iface, struct default_presenter, IVMRImagePresenter9_iface); -} - -static struct default_presenter *impl_from_IVMRSurfaceAllocator9(IVMRSurfaceAllocator9 *iface) -{ - return CONTAINING_RECORD(iface, struct default_presenter, IVMRSurfaceAllocator9_iface); -} - -static HRESULT default_presenter_create(struct vmr7 *parent, struct default_presenter **presenter); - static struct vmr7 *impl_from_IBaseFilter(IBaseFilter *iface) { return CONTAINING_RECORD(iface, struct vmr7, renderer.filter.IBaseFilter_iface); @@ -165,8 +131,8 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) unsigned int data_size, width, depth, src_pitch; const BITMAPINFOHEADER *bitmap_header; REFERENCE_TIME start_time, end_time; - VMR9PresentationInfo info = {0}; - D3DLOCKED_RECT locked_rect; + VMRPRESENTATIONINFO info = {0}; + DDSURFACEDESC2 surface_desc; BYTE *data = NULL; HRESULT hr; int height; @@ -199,6 +165,7 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) return hr; } data_size = IMediaSample_GetActualDataLength(sample); + TRACE("Sample size %u.\n", data_size);
bitmap_header = get_filter_bitmap_header(filter); width = bitmap_header->biWidth; @@ -210,13 +177,20 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) else /* packed YUV (UYVY or YUY2) or RGB */ src_pitch = ((width * depth / 8) + 3) & ~3;
+ info.dwFlags = VMRSample_TimeValid; info.rtStart = start_time; info.rtEnd = end_time; info.szAspectRatio.cx = width; info.szAspectRatio.cy = height; - info.lpSurf = filter->surfaces[(++filter->surface_index) % filter->surface_count]; + info.lpSurf = filter->surfaces[(--filter->surface_index) % filter->surface_count];
- if (FAILED(hr = IDirect3DSurface9_LockRect(info.lpSurf, &locked_rect, NULL, D3DLOCK_DISCARD))) + hr = IVMRSurfaceAllocator_PrepareSurface(filter->allocator, filter->cookie, info.lpSurf, 0); + if (hr != S_OK) + ERR("PrepareSurface() returned %#lx.\n", hr); + + surface_desc.dwSize = sizeof(surface_desc); + if (FAILED(hr = IDirectDrawSurface7_Lock(info.lpSurf, NULL, + &surface_desc, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL))) { ERR("Failed to lock surface, hr %#lx.\n", hr); return hr; @@ -224,43 +198,43 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample)
if (height > 0 && bitmap_header->biCompression == BI_RGB) { - BYTE *dst = (BYTE *)locked_rect.pBits + (height * locked_rect.Pitch); + BYTE *dst = (BYTE *)surface_desc.lpSurface + (height * surface_desc.lPitch); const BYTE *src = data;
TRACE("Inverting image.\n");
while (height--) { - dst -= locked_rect.Pitch; + dst -= surface_desc.lPitch; memcpy(dst, src, width * depth / 8); src += src_pitch; } } - else if (locked_rect.Pitch != src_pitch) + else if (surface_desc.lPitch != src_pitch) { - BYTE *dst = locked_rect.pBits; + BYTE *dst = surface_desc.lpSurface; const BYTE *src = data;
height = abs(height);
- TRACE("Source pitch %u does not match dest pitch %u; copying manually.\n", - src_pitch, locked_rect.Pitch); + TRACE("Source pitch %u does not match dest pitch %lu; copying manually.\n", + src_pitch, surface_desc.lPitch);
while (height--) { memcpy(dst, src, width * depth / 8); src += src_pitch; - dst += locked_rect.Pitch; + dst += surface_desc.lPitch; } } else { - memcpy(locked_rect.pBits, data, data_size); + memcpy(surface_desc.lpSurface, data, data_size); }
- IDirect3DSurface9_UnlockRect(info.lpSurf); + IDirectDrawSurface7_Unlock(info.lpSurf, NULL);
- return IVMRImagePresenter9_PresentImage(filter->presenter, filter->cookie, &info); + return IVMRImagePresenter_PresentImage(filter->presenter, filter->cookie, &info); }
static HRESULT vmr_query_accept(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt) @@ -275,26 +249,43 @@ static HRESULT vmr_query_accept(struct strmbase_renderer *iface, const AM_MEDIA_ return S_OK; }
-static HRESULT initialize_device(struct vmr7 *filter, VMR9AllocationInfo *info, DWORD count) +static HRESULT initialize_device(struct vmr7 *filter, VMRALLOCATIONINFO *info, DWORD count) { + IDirectDrawSurface7 *frontbuffer, *prev; + IVMRWindowlessControl *control; HRESULT hr;
- if (FAILED(hr = IVMRSurfaceAllocator9_InitializeDevice(filter->allocator, - filter->cookie, info, &count))) + if (FAILED(hr = IVMRSurfaceAllocator_AllocateSurface(filter->allocator, + filter->cookie, info, &count, &frontbuffer))) { - WARN("Failed to initialize device (flags %#lx), hr %#lx.\n", info->dwFlags, hr); + WARN("Failed to allocate surface, hr %#lx.\n", hr); return hr; }
+ if (filter->mode != VMRMode_Renderless) + { + IVMRSurfaceAllocator_QueryInterface(filter->allocator, &IID_IVMRWindowlessControl, (void **)&control); + IVMRWindowlessControl_SetVideoClippingWindow(control, + filter->mode == VMRMode_Windowed ? filter->window.hwnd : filter->clipping_window); + IVMRWindowlessControl_Release(control); + } + + if (!(filter->surfaces = calloc(count, sizeof(IDirectDrawSurface7 *)))) + return E_OUTOFMEMORY; + filter->surface_count = count; + filter->surface_index = 0; + + prev = frontbuffer; for (DWORD i = 0; i < count; ++i) { - if (FAILED(hr = IVMRSurfaceAllocator9_GetSurface(filter->allocator, - filter->cookie, i, 0, &filter->surfaces[i]))) + DDSCAPS2 caps = {.dwCaps = DDSCAPS_FLIP}; + + if (FAILED(hr = IDirectDrawSurface7_GetAttachedSurface(prev, &caps, &filter->surfaces[i]))) { ERR("Failed to get surface %lu, hr %#lx.\n", i, hr); while (i--) - IDirect3DSurface9_Release(filter->surfaces[i]); - IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie); + IDirectDrawSurface7_Release(filter->surfaces[i]); + IVMRSurfaceAllocator_FreeSurface(filter->allocator, filter->cookie); return hr; } } @@ -304,8 +295,8 @@ static HRESULT initialize_device(struct vmr7 *filter, VMR9AllocationInfo *info,
static HRESULT allocate_surfaces(struct vmr7 *filter, const AM_MEDIA_TYPE *mt) { - const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(mt); - VMR9AllocationInfo info = {0}; + BITMAPINFOHEADER bitmap_header = *get_bitmap_header(mt); + VMRALLOCATIONINFO info = {0}; HRESULT hr = E_FAIL; DWORD count = 1;
@@ -315,45 +306,12 @@ static HRESULT allocate_surfaces(struct vmr7 *filter, const AM_MEDIA_TYPE *mt) if (filter->mode == VMRMode_Windowless && !filter->clipping_window) return S_OK;
- info.Pool = D3DPOOL_DEFAULT; - info.MinBuffers = count; - info.dwWidth = info.szAspectRatio.cx = info.szNativeSize.cx = bitmap_header->biWidth; - info.dwHeight = info.szAspectRatio.cy = info.szNativeSize.cy = bitmap_header->biHeight; + info.dwFlags = AMAP_DIRECTED_FLIP | AMAP_ALLOW_SYSMEM; + info.lpHdr = &bitmap_header; + info.dwMinBuffers = info.dwMaxBuffers = count; + info.szAspectRatio.cx = info.szNativeSize.cx = bitmap_header.biWidth; + info.szAspectRatio.cy = info.szNativeSize.cy = bitmap_header.biHeight;
- if (!(filter->surfaces = calloc(count, sizeof(IDirect3DSurface9 *)))) - return E_OUTOFMEMORY; - filter->surface_count = count; - filter->surface_index = 0; - - switch (bitmap_header->biCompression) - { - case BI_RGB: - switch (bitmap_header->biBitCount) - { - case 24: info.Format = D3DFMT_R8G8B8; break; - case 32: info.Format = D3DFMT_X8R8G8B8; break; - default: - FIXME("Unhandled bit depth %u.\n", bitmap_header->biBitCount); - free(filter->surfaces); - return VFW_E_TYPE_NOT_ACCEPTED; - } - - info.dwFlags = VMR9AllocFlag_TextureSurface; - break; - - case mmioFOURCC('N','V','1','2'): - case mmioFOURCC('U','Y','V','Y'): - case mmioFOURCC('Y','U','Y','2'): - case mmioFOURCC('Y','V','1','2'): - info.Format = bitmap_header->biCompression; - info.dwFlags = VMR9AllocFlag_OffscreenSurface; - break; - - default: - WARN("Unhandled video compression %#lx.\n", bitmap_header->biCompression); - free(filter->surfaces); - return VFW_E_TYPE_NOT_ACCEPTED; - } if (FAILED(hr = initialize_device(filter, &info, count))) free(filter->surfaces); return hr; @@ -371,7 +329,7 @@ static void vmr_start_stream(struct strmbase_renderer *iface) { struct vmr7 *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
- IVMRImagePresenter9_StartPresenting(filter->presenter, filter->cookie); + IVMRImagePresenter_StartPresenting(filter->presenter, filter->cookie); }
static void vmr_stop_stream(struct strmbase_renderer *iface) @@ -379,7 +337,7 @@ static void vmr_stop_stream(struct strmbase_renderer *iface) struct vmr7 *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
if (filter->renderer.filter.state == State_Running) - IVMRImagePresenter9_StopPresenting(filter->presenter, filter->cookie); + IVMRImagePresenter_StopPresenting(filter->presenter, filter->cookie); }
static HRESULT vmr_connect(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt) @@ -411,10 +369,10 @@ static void deallocate_surfaces(struct vmr7 *filter) if (filter->mode && filter->allocator && filter->presenter) { for (DWORD i = 0; i < filter->surface_count; ++i) - IDirect3DSurface9_Release(filter->surfaces[i]); + IDirectDrawSurface7_Release(filter->surfaces[i]); free(filter->surfaces);
- IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie); + IVMRSurfaceAllocator_FreeSurface(filter->allocator, filter->cookie); filter->surface_count = 0; } } @@ -434,20 +392,15 @@ static void vmr_destroy(struct strmbase_renderer *iface)
if (filter->allocator) { - IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie); - IVMRSurfaceAllocator9_Release(filter->allocator); + if (filter->surface_count) + IVMRSurfaceAllocator_FreeSurface(filter->allocator, filter->cookie); + IVMRSurfaceAllocator_Release(filter->allocator); } if (filter->presenter) - IVMRImagePresenter9_Release(filter->presenter); + IVMRImagePresenter_Release(filter->presenter);
filter->surface_count = 0; - if (filter->device) - { - IDirect3DDevice9_Release(filter->device); - filter->device = NULL; - }
- FreeLibrary(filter->d3d9_module); strmbase_renderer_cleanup(&filter->renderer); free(filter); } @@ -518,65 +471,8 @@ static void vmr_get_default_rect(struct video_window *iface, RECT *rect)
static HRESULT vmr_get_current_image(struct video_window *iface, LONG *size, LONG *image) { - struct vmr7 *filter = impl_from_video_window(iface); - IDirect3DSurface9 *rt = NULL, *surface = NULL; - D3DLOCKED_RECT locked_rect; - IDirect3DDevice9 *device; - unsigned int row_size; - BITMAPINFOHEADER bih; - LONG size_left; - HRESULT hr; - char *dst; - - EnterCriticalSection(&filter->renderer.filter.stream_cs); - device = filter->device; - - bih = *get_filter_bitmap_header(filter); - bih.biSizeImage = bih.biWidth * bih.biHeight * bih.biBitCount / 8; - - if (!image) - { - *size = sizeof(BITMAPINFOHEADER) + bih.biSizeImage; - LeaveCriticalSection(&filter->renderer.filter.stream_cs); - return S_OK; - } - - if (FAILED(hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt))) - goto out; - - if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, bih.biWidth, - bih.biHeight, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL))) - goto out; - - if (FAILED(hr = IDirect3DDevice9_GetRenderTargetData(device, rt, surface))) - goto out; - - if (FAILED(hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_READONLY))) - goto out; - - size_left = *size; - memcpy(image, &bih, min(size_left, sizeof(BITMAPINFOHEADER))); - size_left -= sizeof(BITMAPINFOHEADER); - - dst = (char *)image + sizeof(BITMAPINFOHEADER); - row_size = bih.biWidth * bih.biBitCount / 8; - - for (LONG i = 0; i < bih.biHeight && size_left > 0; ++i) - { - memcpy(dst, (char *)locked_rect.pBits + (i * locked_rect.Pitch), min(row_size, size_left)); - dst += row_size; - size_left -= row_size; - } - - IDirect3DSurface9_UnlockRect(surface); - -out: - if (surface) - IDirect3DSurface9_Release(surface); - if (rt) - IDirect3DSurface9_Release(rt); - LeaveCriticalSection(&filter->renderer.filter.stream_cs); - return hr; + FIXME("stub!\n"); + return E_NOTIMPL; }
static const struct video_window_ops window_ops = @@ -806,7 +702,7 @@ static HRESULT WINAPI filter_config_GetRenderingPrefs(IVMRFilterConfig *iface, D static HRESULT WINAPI filter_config_SetRenderingMode(IVMRFilterConfig *iface, DWORD mode) { struct vmr7 *filter = impl_from_IVMRFilterConfig(iface); - struct default_presenter *default_presenter; + IUnknown *default_presenter; HRESULT hr = S_OK;
TRACE("filter %p, mode %lu.\n", filter, mode); @@ -823,15 +719,15 @@ static HRESULT WINAPI filter_config_SetRenderingMode(IVMRFilterConfig *iface, DW { case VMRMode_Windowed: case VMRMode_Windowless: - if (FAILED(hr = default_presenter_create(filter, &default_presenter))) + if (FAILED(hr = vmr7_presenter_create(NULL, &default_presenter))) { ERR("Failed to create default presenter, hr %#lx.\n", hr); LeaveCriticalSection(&filter->renderer.filter.filter_cs); return hr; } - filter->allocator = &default_presenter->IVMRSurfaceAllocator9_iface; - filter->presenter = &default_presenter->IVMRImagePresenter9_iface; - IVMRImagePresenter9_AddRef(filter->presenter); + IUnknown_QueryInterface(default_presenter, &IID_IVMRSurfaceAllocator, (void **)&filter->allocator); + IUnknown_QueryInterface(default_presenter, &IID_IVMRImagePresenter, (void **)&filter->presenter); + IUnknown_Release(default_presenter); break;
case VMRMode_Renderless: @@ -1331,116 +1227,6 @@ static const IVMRSurfaceAllocatorNotifyVtbl surface_allocator_notify_vtbl = surface_allocator_notify_SetBorderColor, };
-static void vmr_set_d3d_device(struct vmr7 *filter, IDirect3DDevice9 *device, HMONITOR monitor) -{ - if (filter->device) - IDirect3DDevice9_Release(filter->device); - filter->device = device; - IDirect3DDevice9_AddRef(device); -} - -static HRESULT vmr_allocate_d3d9_surfaces(struct vmr7 *filter, - VMR9AllocationInfo *info, DWORD *count, IDirect3DSurface9 **surfaces) -{ - HRESULT hr = S_OK; - DWORD i; - - TRACE("filter %p, info %p, count %p, surfaces %p.\n", filter, count, info, surfaces); - - if (!info || !count || !surfaces) - return E_POINTER; - - TRACE("Flags %#lx, size %lux%lu, format %u (%#x), pool %u, minimum buffers %lu.\n", - info->dwFlags, info->dwWidth, info->dwHeight, - info->Format, info->Format, info->Pool, info->MinBuffers); - - if ((info->dwFlags & VMR9AllocFlag_TextureSurface) - && (info->dwFlags & VMR9AllocFlag_OffscreenSurface)) - { - WARN("Invalid flags specified; returning E_INVALIDARG.\n"); - return E_INVALIDARG; - } - - if (!info->Format) - { - IDirect3DSurface9 *backbuffer; - D3DSURFACE_DESC desc; - - IDirect3DDevice9_GetBackBuffer(filter->device, 0, 0, - D3DBACKBUFFER_TYPE_MONO, &backbuffer); - IDirect3DSurface9_GetDesc(backbuffer, &desc); - IDirect3DSurface9_Release(backbuffer); - info->Format = desc.Format; - } - - if (!*count || *count < info->MinBuffers) - { - WARN("%lu surfaces requested (minimum %lu); returning E_INVALIDARG.\n", - *count, info->MinBuffers); - return E_INVALIDARG; - } - - if (!filter->device) - { - WARN("No Direct3D device; returning VFW_E_WRONG_STATE.\n"); - return VFW_E_WRONG_STATE; - } - - if (info->dwFlags == VMR9AllocFlag_OffscreenSurface) - { - for (i = 0; i < *count; ++i) - { - if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(filter->device, - info->dwWidth, info->dwHeight, info->Format, info->Pool, &surfaces[i], NULL))) - break; - } - } - else if (info->dwFlags == VMR9AllocFlag_TextureSurface) - { - for (i = 0; i < *count; ++i) - { - IDirect3DTexture9 *texture; - - if (FAILED(hr = IDirect3DDevice9_CreateTexture(filter->device, info->dwWidth, - info->dwHeight, 1, D3DUSAGE_DYNAMIC, info->Format, info->Pool, &texture, NULL))) - break; - IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surfaces[i]); - IDirect3DTexture9_Release(texture); - } - } - else if (info->dwFlags == VMR9AllocFlag_3DRenderTarget) - { - for (i = 0; i < *count; ++i) - { - if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(filter->device, - info->dwWidth, info->dwHeight, info->Format, - D3DMULTISAMPLE_NONE, 0, FALSE, &surfaces[i], NULL))) - break; - } - } - else - { - FIXME("Unhandled flags %#lx.\n", info->dwFlags); - return E_NOTIMPL; - } - - if (FAILED(hr)) - WARN("%lu/%lu surfaces allocated, hr %#lx.\n", i, *count, hr); - - if (i >= info->MinBuffers) - { - hr = S_OK; - *count = i; - } - else - { - for (; i > 0; --i) - IDirect3DSurface9_Release(surfaces[i - 1]); - *count = 0; - } - return hr; -} - static struct vmr7 *impl_from_IAMVideoAccelerator(IAMVideoAccelerator *iface) { return CONTAINING_RECORD(iface, struct vmr7, IAMVideoAccelerator_iface); @@ -1695,14 +1481,6 @@ HRESULT vmr7_create(IUnknown *outer, IUnknown **out) if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY;
- object->d3d9_module = LoadLibraryA("d3d9.dll"); - if (!object->d3d9_module) - { - WARN("Could not load d3d9.dll\n"); - free(object); - return VFW_E_DDRAW_CAPS_NOT_SUITABLE; - } - strmbase_renderer_init(&object->renderer, outer, &CLSID_VideoMixingRenderer, L"VMR Input0", &renderer_ops); object->IAMCertifiedOutputProtection_iface.lpVtbl = &certified_output_protection_vtbl; object->IAMFilterMiscFlags_iface.lpVtbl = &misc_flags_vtbl; @@ -1721,7 +1499,6 @@ HRESULT vmr7_create(IUnknown *outer, IUnknown **out) { video_window_cleanup(&object->window); strmbase_renderer_cleanup(&object->renderer); - FreeLibrary(object->d3d9_module); free(object); return hr; } @@ -1733,389 +1510,3 @@ HRESULT vmr7_create(IUnknown *outer, IUnknown **out) *out = &object->renderer.filter.IUnknown_inner; return S_OK; } - -static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID iid, void **out) -{ - struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface); - - TRACE("presenter %p, iid %s, out %p.\n", presenter, debugstr_guid(iid), out); - - if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IVMRImagePresenter9)) - *out = &presenter->IVMRImagePresenter9_iface; - else if (IsEqualIID(iid, &IID_IVMRSurfaceAllocator9)) - *out = &presenter->IVMRSurfaceAllocator9_iface; - else - { - *out = NULL; - WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown *)*out); - return S_OK; -} - -static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface) -{ - struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface); - ULONG refcount = InterlockedIncrement(&presenter->refcount); - - TRACE("%p increasing refcount to %lu.\n", presenter, refcount); - - return refcount; -} - -static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface) -{ - struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface); - ULONG refcount = InterlockedDecrement(&presenter->refcount); - - TRACE("%p decreasing refcount to %lu.\n", presenter, refcount); - - if (!refcount) - { - IDirect3D9_Release(presenter->d3d9); - - for (DWORD i = 0; i < presenter->surface_count; ++i) - { - IDirect3DSurface9 *surface = presenter->surfaces[i]; - - if (surface) - IDirect3DSurface9_Release(surface); - } - - if (presenter->device) - IDirect3DDevice9_Release(presenter->device); - free(presenter->surfaces); - presenter->surfaces = NULL; - presenter->surface_count = 0; - free(presenter); - return 0; - } - return refcount; -} - -static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie) -{ - struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface); - - TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie); - - return S_OK; -} - -static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie) -{ - struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface); - - TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie); - - return S_OK; -} - -static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface, - DWORD_PTR cookie, VMR9PresentationInfo *info) -{ - struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface); - IDirect3DDevice9 *device = presenter->device; - const struct vmr7 *filter = presenter->vmr; - const RECT src = filter->window.src; - IDirect3DSurface9 *backbuffer; - RECT dst = filter->window.dst; - HRESULT hr; - - TRACE("presenter %p, cookie %#Ix, info %p.\n", presenter, cookie, info); - - /* presenter might happen if we don't have active focus (eg on a different virtual desktop) */ - if (!device) - return S_OK; - - if (FAILED(hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, - D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0))) - ERR("Failed to clear, hr %#lx.\n", hr); - - if (FAILED(hr = IDirect3DDevice9_BeginScene(device))) - ERR("Failed to begin scene, hr %#lx.\n", hr); - - if (FAILED(hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer))) - { - ERR("Failed to get backbuffer, hr %#lx.\n", hr); - return hr; - } - - if (FAILED(hr = IDirect3DDevice9_StretchRect(device, info->lpSurf, NULL, backbuffer, NULL, D3DTEXF_POINT))) - ERR("Failed to blit image, hr %#lx.\n", hr); - IDirect3DSurface9_Release(backbuffer); - - if (FAILED(hr = IDirect3DDevice9_EndScene(device))) - ERR("Failed to end scene, hr %#lx.\n", hr); - - if (filter->aspect_mode == VMR9ARMode_LetterBox) - { - unsigned int src_width = src.right - src.left, src_height = src.bottom - src.top; - unsigned int dst_width = dst.right - dst.left, dst_height = dst.bottom - dst.top; - - if (src_width * dst_height > dst_width * src_height) - { - /* src is "wider" than dst. */ - unsigned int dst_center = (dst.top + dst.bottom) / 2; - unsigned int scaled_height = src_height * dst_width / src_width; - - dst.top = dst_center - scaled_height / 2; - dst.bottom = dst.top + scaled_height; - } - else if (src_width * dst_height < dst_width * src_height) - { - /* src is "taller" than dst. */ - unsigned int dst_center = (dst.left + dst.right) / 2; - unsigned int scaled_width = src_width * dst_height / src_height; - - dst.left = dst_center - scaled_width / 2; - dst.right = dst.left + scaled_width; - } - } - - if (FAILED(hr = IDirect3DDevice9_Present(device, &src, &dst, NULL, NULL))) - ERR("Failed to present, hr %#lx.\n", hr); - - return S_OK; -} - -static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter = -{ - VMR9_ImagePresenter_QueryInterface, - VMR9_ImagePresenter_AddRef, - VMR9_ImagePresenter_Release, - VMR9_ImagePresenter_StartPresenting, - VMR9_ImagePresenter_StopPresenting, - VMR9_ImagePresenter_PresentImage -}; - -static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocator9 *iface, REFIID iid, void **out) -{ - struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface); - - return IVMRImagePresenter9_QueryInterface(&presenter->IVMRImagePresenter9_iface, iid, out); -} - -static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocator9 *iface) -{ - struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface); - - return IVMRImagePresenter9_AddRef(&presenter->IVMRImagePresenter9_iface); -} - -static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocator9 *iface) -{ - struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface); - - return IVMRImagePresenter9_Release(&presenter->IVMRImagePresenter9_iface); -} - -static void adjust_surface_size(const D3DCAPS9 *caps, VMR9AllocationInfo *info) -{ - unsigned int width, height; - - /* There are no restrictions on the size of offscreen surfaces. */ - if (!(info->dwFlags & VMR9AllocFlag_TextureSurface)) - return; - - if (!(caps->TextureCaps & D3DPTEXTURECAPS_POW2) || (caps->TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)) - { - width = info->dwWidth; - height = info->dwHeight; - } - else - { - width = height = 1; - while (width < info->dwWidth) - width *= 2; - - while (height < info->dwHeight) - height *= 2; - FIXME("Non-power-of-two textures are not supported.\n"); - } - - if (caps->TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) - { - if (height > width) - width = height; - else - height = width; - FIXME("Rectangular textures are not supported.\n"); - } - - info->dwHeight = height; - info->dwWidth = width; -} - -static UINT adapter_index_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *ret_monitor) -{ - UINT adapter_index; - HMONITOR monitor; - - monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL); - if (!monitor) - adapter_index = 0; - else - { - for (adapter_index = 0; adapter_index < IDirect3D9_GetAdapterCount(d3d9); ++adapter_index) - { - if (monitor == IDirect3D9_GetAdapterMonitor(d3d9, adapter_index)) - break; - } - if (adapter_index >= IDirect3D9_GetAdapterCount(d3d9)) - adapter_index = 0; - } - if (ret_monitor) - *ret_monitor = monitor; - return adapter_index; -} - -static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocator9 *iface, - DWORD_PTR cookie, VMR9AllocationInfo *info, DWORD *count) -{ - struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface); - D3DPRESENT_PARAMETERS present_parameters = {0}; - IDirect3DDevice9 *device; - DWORD adapter_index; - D3DCAPS9 caps; - HWND window; - HRESULT hr; - - TRACE("presenter %p, cookie %#Ix, info %p, count %p.\n", presenter, cookie, info, count); - - presenter->info = *info; - - if (presenter->vmr->mode == VMRMode_Windowed) - window = presenter->vmr->window.hwnd; - else - window = presenter->vmr->clipping_window; - - adapter_index = adapter_index_from_hwnd(presenter->d3d9, window, &presenter->monitor); - - present_parameters.Windowed = TRUE; - present_parameters.hDeviceWindow = window; - present_parameters.SwapEffect = D3DSWAPEFFECT_COPY; - present_parameters.BackBufferWidth = info->dwWidth; - present_parameters.BackBufferHeight = info->dwHeight; - - hr = IDirect3D9_CreateDevice(presenter->d3d9, adapter_index, D3DDEVTYPE_HAL, - NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &present_parameters, &device); - if (FAILED(hr)) - { - ERR("Failed to create device, hr %#lx.\n", hr); - return hr; - } - - IDirect3DDevice9_GetDeviceCaps(device, &caps); - if (!(caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES)) - { - WARN("Device does not support blitting from textures.\n"); - IDirect3DDevice9_Release(device); - return VFW_E_DDRAW_CAPS_NOT_SUITABLE; - } - - presenter->device = device; - vmr_set_d3d_device(presenter->vmr, presenter->device, presenter->monitor); - - if (!(presenter->surfaces = calloc(*count, sizeof(IDirect3DSurface9 *)))) - return E_OUTOFMEMORY; - - adjust_surface_size(&caps, info); - - if (FAILED(hr = vmr_allocate_d3d9_surfaces(presenter->vmr, info, count, presenter->surfaces))) - { - ERR("Failed to allocate surfaces, hr %#lx.\n", hr); - IVMRSurfaceAllocator9_TerminateDevice(presenter->vmr->allocator, presenter->vmr->cookie); - return hr; - } - - presenter->surface_count = *count; - - return S_OK; -} - -static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocator9 *iface, DWORD_PTR cookie) -{ - TRACE("iface %p, cookie %#Ix.\n", iface, cookie); - - return S_OK; -} - -static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocator9 *iface, - DWORD_PTR cookie, DWORD index, DWORD flags, IDirect3DSurface9 **surface) -{ - struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface); - - if (!presenter->device) - { - ERR("No device.\n"); - return E_FAIL; - } - - if (index >= presenter->surface_count) - { - ERR("Index %lu exceeds surface count %lu.\n", index, presenter->surface_count); - return E_FAIL; - } - *surface = presenter->surfaces[index]; - IDirect3DSurface9_AddRef(*surface); - - return S_OK; -} - -static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocator9 *iface, - IVMRSurfaceAllocatorNotify9 *notify) -{ - ERR("Unexpected call.\n"); - return S_OK; -} - -static const IVMRSurfaceAllocator9Vtbl VMR9_SurfaceAllocator = -{ - VMR9_SurfaceAllocator_QueryInterface, - VMR9_SurfaceAllocator_AddRef, - VMR9_SurfaceAllocator_Release, - VMR9_SurfaceAllocator_InitializeDevice, - VMR9_SurfaceAllocator_TerminateDevice, - VMR9_SurfaceAllocator_GetSurface, - VMR9_SurfaceAllocator_AdviseNotify, -}; - -static IDirect3D9 *init_d3d9(HMODULE d3d9_handle) -{ - IDirect3D9 * (__stdcall *d3d9_create)(UINT version); - - d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9"); - if (!d3d9_create) - return NULL; - - return d3d9_create(D3D_SDK_VERSION); -} - -static HRESULT default_presenter_create(struct vmr7 *parent, struct default_presenter **presenter) -{ - struct default_presenter *object; - - if (!(object = calloc(1, sizeof(*object)))) - return E_OUTOFMEMORY; - - object->d3d9 = init_d3d9(parent->d3d9_module); - if (!object->d3d9) - { - WARN("Could not initialize d3d9.dll\n"); - free(object); - return VFW_E_DDRAW_CAPS_NOT_SUITABLE; - } - - object->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter; - object->IVMRSurfaceAllocator9_iface.lpVtbl = &VMR9_SurfaceAllocator; - - object->refcount = 1; - object->vmr = parent; - - TRACE("Created default presenter %p.\n", object); - *presenter = object; - return S_OK; -}