ver: Use the 16-bit resource function in GetFileVersionInfo16().
[wine.git] / dlls / quartz / vmr9.c
blobbc2a905650ca6312e83cb9ff725dad815b6a91ef
1 /*
2 * Video Mixing Renderer for dx9
4 * Copyright 2004 Christian Costa
5 * Copyright 2008 Maarten Lankhorst
6 * Copyright 2012 Aric Stewart
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "quartz_private.h"
25 #include "uuids.h"
26 #include "vfwmsgs.h"
27 #include "amvideo.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "dshow.h"
31 #include "evcode.h"
32 #include "strmif.h"
33 #include "ddraw.h"
34 #include "dvdmedia.h"
35 #include "d3d9.h"
36 #include "vmr9.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
42 struct quartz_vmr
44 struct strmbase_renderer renderer;
45 BaseControlWindow baseControlWindow;
46 BaseControlVideo baseControlVideo;
48 IAMCertifiedOutputProtection IAMCertifiedOutputProtection_iface;
49 IAMFilterMiscFlags IAMFilterMiscFlags_iface;
50 IVMRFilterConfig IVMRFilterConfig_iface;
51 IVMRFilterConfig9 IVMRFilterConfig9_iface;
52 IVMRMonitorConfig IVMRMonitorConfig_iface;
53 IVMRMonitorConfig9 IVMRMonitorConfig9_iface;
54 IVMRSurfaceAllocatorNotify IVMRSurfaceAllocatorNotify_iface;
55 IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface;
56 IVMRWindowlessControl IVMRWindowlessControl_iface;
57 IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
59 IOverlay IOverlay_iface;
61 IVMRSurfaceAllocatorEx9 *allocator;
62 IVMRImagePresenter9 *presenter;
63 BOOL allocator_is_ex;
66 * The Video Mixing Renderer supports 3 modes, renderless, windowless and windowed
67 * What I do is implement windowless as a special case of renderless, and then
68 * windowed also as a special case of windowless. This is probably the easiest way.
70 VMR9Mode mode;
71 BITMAPINFOHEADER bmiheader;
73 HMODULE hD3d9;
75 /* Presentation related members */
76 IDirect3DDevice9 *allocator_d3d9_dev;
77 HMONITOR allocator_mon;
78 DWORD num_surfaces;
79 DWORD cur_surface;
80 DWORD_PTR cookie;
82 /* for Windowless Mode */
83 HWND hWndClippingWindow;
85 RECT source_rect;
86 RECT target_rect;
87 LONG VideoWidth;
88 LONG VideoHeight;
90 HANDLE run_event;
93 static inline struct quartz_vmr *impl_from_BaseWindow(BaseWindow *wnd)
95 return CONTAINING_RECORD(wnd, struct quartz_vmr, baseControlWindow.baseWindow);
98 static inline struct quartz_vmr *impl_from_BaseControlVideo(BaseControlVideo *cvid)
100 return CONTAINING_RECORD(cvid, struct quartz_vmr, baseControlVideo);
103 static inline struct quartz_vmr *impl_from_IAMCertifiedOutputProtection(IAMCertifiedOutputProtection *iface)
105 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMCertifiedOutputProtection_iface);
108 static inline struct quartz_vmr *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
110 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMFilterMiscFlags_iface);
113 static inline struct quartz_vmr *impl_from_IVMRFilterConfig(IVMRFilterConfig *iface)
115 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig_iface);
118 static inline struct quartz_vmr *impl_from_IVMRFilterConfig9(IVMRFilterConfig9 *iface)
120 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig9_iface);
123 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig(IVMRMonitorConfig *iface)
125 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig_iface);
128 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig9(IVMRMonitorConfig9 *iface)
130 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig9_iface);
133 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify(IVMRSurfaceAllocatorNotify *iface)
135 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify_iface);
138 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify9(IVMRSurfaceAllocatorNotify9 *iface)
140 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify9_iface);
143 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl(IVMRWindowlessControl *iface)
145 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl_iface);
148 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl9(IVMRWindowlessControl9 *iface)
150 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl9_iface);
153 typedef struct
155 IVMRImagePresenter9 IVMRImagePresenter9_iface;
156 IVMRSurfaceAllocatorEx9 IVMRSurfaceAllocatorEx9_iface;
158 LONG refCount;
160 IDirect3DDevice9 *d3d9_dev;
161 IDirect3D9 *d3d9_ptr;
162 IDirect3DSurface9 **d3d9_surfaces;
163 IDirect3DVertexBuffer9 *d3d9_vertex;
164 HMONITOR hMon;
165 DWORD num_surfaces;
167 BOOL reset;
168 VMR9AllocationInfo info;
170 struct quartz_vmr* pVMR9;
171 IVMRSurfaceAllocatorNotify9 *SurfaceAllocatorNotify;
172 } VMR9DefaultAllocatorPresenterImpl;
174 static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRImagePresenter9( IVMRImagePresenter9 *iface)
176 return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRImagePresenter9_iface);
179 static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRSurfaceAllocatorEx9( IVMRSurfaceAllocatorEx9 *iface)
181 return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRSurfaceAllocatorEx9_iface);
184 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(struct quartz_vmr *parent, LPVOID * ppv);
186 static inline struct quartz_vmr *impl_from_IBaseFilter(IBaseFilter *iface)
188 return CONTAINING_RECORD(iface, struct quartz_vmr, renderer.filter.IBaseFilter_iface);
191 static DWORD VMR9_SendSampleData(struct quartz_vmr *This, VMR9PresentationInfo *info, LPBYTE data,
192 DWORD size)
194 AM_MEDIA_TYPE *amt;
195 HRESULT hr = S_OK;
196 int width;
197 int height;
198 BITMAPINFOHEADER *bmiHeader;
199 D3DLOCKED_RECT lock;
201 TRACE("%p %p %d\n", This, data, size);
203 amt = &This->renderer.sink.pin.mt;
205 if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
207 bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
209 else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
211 bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
213 else
215 FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
216 return VFW_E_RUNTIME_ERROR;
219 width = bmiHeader->biWidth;
220 height = bmiHeader->biHeight;
222 TRACE("Src Rect: %s\n", wine_dbgstr_rect(&This->source_rect));
223 TRACE("Dst Rect: %s\n", wine_dbgstr_rect(&This->target_rect));
225 hr = IDirect3DSurface9_LockRect(info->lpSurf, &lock, NULL, D3DLOCK_DISCARD);
226 if (FAILED(hr))
228 ERR("IDirect3DSurface9_LockRect failed (%x)\n",hr);
229 return hr;
232 if (height > 0) {
233 /* Bottom up image needs inverting */
234 lock.pBits = (char *)lock.pBits + (height * lock.Pitch);
235 while (height--)
237 lock.pBits = (char *)lock.pBits - lock.Pitch;
238 memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8);
239 data = data + width * bmiHeader->biBitCount / 8;
242 else if (lock.Pitch != width * bmiHeader->biBitCount / 8)
244 WARN("Slow path! %u/%u\n", lock.Pitch, width * bmiHeader->biBitCount/8);
246 while (height--)
248 memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8);
249 data = data + width * bmiHeader->biBitCount / 8;
250 lock.pBits = (char *)lock.pBits + lock.Pitch;
253 else memcpy(lock.pBits, data, size);
255 IDirect3DSurface9_UnlockRect(info->lpSurf);
257 hr = IVMRImagePresenter9_PresentImage(This->presenter, This->cookie, info);
258 return hr;
261 static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMediaSample *pSample)
263 struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
264 const HANDLE events[2] = {This->run_event, This->renderer.flush_event};
265 LPBYTE pbSrcStream = NULL;
266 long cbSrcStream = 0;
267 REFERENCE_TIME tStart, tStop;
268 VMR9PresentationInfo info;
269 HRESULT hr;
271 TRACE("%p %p\n", iface, pSample);
273 /* It is possible that there is no device at this point */
275 if (!This->allocator || !This->presenter)
277 ERR("NO PRESENTER!!\n");
278 return S_FALSE;
281 hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
282 if (FAILED(hr))
283 info.dwFlags = VMR9Sample_SrcDstRectsValid;
284 else
285 info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
287 if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
288 info.dwFlags |= VMR9Sample_Discontinuity;
290 if (IMediaSample_IsPreroll(pSample) == S_OK)
291 info.dwFlags |= VMR9Sample_Preroll;
293 if (IMediaSample_IsSyncPoint(pSample) == S_OK)
294 info.dwFlags |= VMR9Sample_SyncPoint;
296 /* If we render ourselves, and this is a preroll sample, discard it */
297 if (info.dwFlags & VMR9Sample_Preroll)
299 return S_OK;
302 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
303 if (FAILED(hr))
305 ERR("Cannot get pointer to sample data (%x)\n", hr);
306 return hr;
309 cbSrcStream = IMediaSample_GetActualDataLength(pSample);
311 info.rtStart = tStart;
312 info.rtEnd = tStop;
313 info.szAspectRatio.cx = This->bmiheader.biWidth;
314 info.szAspectRatio.cy = This->bmiheader.biHeight;
316 hr = IVMRSurfaceAllocatorEx9_GetSurface(This->allocator, This->cookie, (++This->cur_surface)%This->num_surfaces, 0, &info.lpSurf);
318 if (FAILED(hr))
319 return hr;
321 VMR9_SendSampleData(This, &info, pbSrcStream, cbSrcStream);
322 IDirect3DSurface9_Release(info.lpSurf);
324 if (This->renderer.filter.state == State_Paused)
326 LeaveCriticalSection(&This->renderer.csRenderLock);
327 WaitForMultipleObjects(2, events, FALSE, INFINITE);
328 EnterCriticalSection(&This->renderer.csRenderLock);
331 return hr;
334 static HRESULT WINAPI VMR9_CheckMediaType(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
336 const VIDEOINFOHEADER *vih;
338 if (!IsEqualIID(&mt->majortype, &MEDIATYPE_Video) || !mt->pbFormat)
339 return S_FALSE;
341 if (!IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo)
342 && !IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo2))
343 return S_FALSE;
345 vih = (VIDEOINFOHEADER *)mt->pbFormat;
347 if (vih->bmiHeader.biCompression != BI_RGB)
348 return S_FALSE;
349 return S_OK;
352 static HRESULT VMR9_maybe_init(struct quartz_vmr *This, BOOL force)
354 VMR9AllocationInfo info;
355 DWORD buffers;
356 HRESULT hr;
358 TRACE("my mode: %u, my window: %p, my last window: %p\n", This->mode, This->baseControlWindow.baseWindow.hWnd, This->hWndClippingWindow);
359 if (This->num_surfaces)
360 return S_OK;
362 if (This->mode == VMR9Mode_Windowless && !This->hWndClippingWindow)
363 return (force ? VFW_E_RUNTIME_ERROR : S_OK);
365 TRACE("Initializing\n");
366 info.dwFlags = VMR9AllocFlag_TextureSurface;
367 info.dwHeight = This->source_rect.bottom;
368 info.dwWidth = This->source_rect.right;
369 info.Pool = D3DPOOL_DEFAULT;
370 info.MinBuffers = 2;
371 FIXME("Reduce ratio to least common denominator\n");
372 info.szAspectRatio.cx = info.dwWidth;
373 info.szAspectRatio.cy = info.dwHeight;
374 info.szNativeSize.cx = This->bmiheader.biWidth;
375 info.szNativeSize.cy = This->bmiheader.biHeight;
376 buffers = 2;
378 switch (This->bmiheader.biBitCount)
380 case 8: info.Format = D3DFMT_R3G3B2; break;
381 case 15: info.Format = D3DFMT_X1R5G5B5; break;
382 case 16: info.Format = D3DFMT_R5G6B5; break;
383 case 24: info.Format = D3DFMT_R8G8B8; break;
384 case 32: info.Format = D3DFMT_X8R8G8B8; break;
385 default:
386 FIXME("Unknown bpp %u\n", This->bmiheader.biBitCount);
387 hr = E_INVALIDARG;
390 This->cur_surface = 0;
391 if (This->num_surfaces)
393 ERR("num_surfaces or d3d9_surfaces not 0\n");
394 return E_FAIL;
397 hr = IVMRSurfaceAllocatorEx9_InitializeDevice(This->allocator, This->cookie, &info, &buffers);
398 if (SUCCEEDED(hr))
400 SetRect(&This->source_rect, 0, 0, This->bmiheader.biWidth, This->bmiheader.biHeight);
402 This->num_surfaces = buffers;
404 return hr;
407 static void vmr_start_stream(struct strmbase_renderer *iface)
409 struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
411 TRACE("(%p)\n", This);
413 if (This->renderer.sink.pin.peer)
414 VMR9_maybe_init(This, TRUE);
415 IVMRImagePresenter9_StartPresenting(This->presenter, This->cookie);
416 SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
417 This->source_rect.left,
418 This->source_rect.top,
419 This->source_rect.right - This->source_rect.left,
420 This->source_rect.bottom - This->source_rect.top,
421 SWP_NOZORDER|SWP_NOMOVE|SWP_DEFERERASE);
422 ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_SHOW);
423 GetClientRect(This->baseControlWindow.baseWindow.hWnd, &This->target_rect);
424 SetEvent(This->run_event);
427 static void vmr_stop_stream(struct strmbase_renderer *iface)
429 struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
431 TRACE("(%p)\n", This);
433 if (This->renderer.filter.state == State_Running)
434 IVMRImagePresenter9_StopPresenting(This->presenter, This->cookie);
435 ResetEvent(This->run_event);
438 static HRESULT WINAPI VMR9_ShouldDrawSampleNow(struct strmbase_renderer *iface,
439 IMediaSample *pSample, REFERENCE_TIME *start, REFERENCE_TIME *end)
441 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
442 if (IMediaSample_IsPreroll(pSample) == S_OK)
443 return E_FAIL;
444 return S_FALSE;
447 static HRESULT vmr_connect(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
449 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
450 HRESULT hr;
452 if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
454 VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)mt->pbFormat;
456 filter->bmiheader = format->bmiHeader;
457 filter->VideoWidth = format->bmiHeader.biWidth;
458 filter->VideoHeight = format->bmiHeader.biHeight;
459 SetRect(&filter->source_rect, 0, 0, filter->VideoWidth, filter->VideoHeight);
461 else if (IsEqualIID(&mt->formattype, &FORMAT_VideoInfo2))
463 VIDEOINFOHEADER2 *format = (VIDEOINFOHEADER2 *)mt->pbFormat;
465 filter->bmiheader = format->bmiHeader;
466 filter->VideoWidth = format->bmiHeader.biWidth;
467 filter->VideoHeight = format->bmiHeader.biHeight;
468 SetRect(&filter->source_rect, 0, 0, filter->VideoWidth, filter->VideoHeight);
471 if (filter->mode
472 || SUCCEEDED(hr = IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, VMR9Mode_Windowed)))
473 hr = VMR9_maybe_init(filter, FALSE);
475 return hr;
478 static HRESULT WINAPI VMR9_BreakConnect(struct strmbase_renderer *This)
480 struct quartz_vmr *pVMR9 = impl_from_IBaseFilter(&This->filter.IBaseFilter_iface);
481 HRESULT hr = S_OK;
483 if (!pVMR9->mode)
484 return S_FALSE;
485 if (This->sink.pin.peer && pVMR9->allocator && pVMR9->presenter)
487 if (pVMR9->renderer.filter.state != State_Stopped)
489 ERR("Disconnecting while not stopped! UNTESTED!!\n");
491 if (pVMR9->renderer.filter.state == State_Running)
492 hr = IVMRImagePresenter9_StopPresenting(pVMR9->presenter, pVMR9->cookie);
493 IVMRSurfaceAllocatorEx9_TerminateDevice(pVMR9->allocator, pVMR9->cookie);
494 pVMR9->num_surfaces = 0;
496 return hr;
499 static void vmr_destroy(struct strmbase_renderer *iface)
501 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
503 BaseControlWindow_Destroy(&filter->baseControlWindow);
505 if (filter->allocator)
506 IVMRSurfaceAllocatorEx9_Release(filter->allocator);
507 if (filter->presenter)
508 IVMRImagePresenter9_Release(filter->presenter);
510 filter->num_surfaces = 0;
511 if (filter->allocator_d3d9_dev)
513 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
514 filter->allocator_d3d9_dev = NULL;
517 CloseHandle(filter->run_event);
518 FreeLibrary(filter->hD3d9);
519 BaseControlWindow_Destroy(&filter->baseControlWindow);
520 strmbase_renderer_cleanup(&filter->renderer);
521 CoTaskMemFree(filter);
524 static HRESULT vmr_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
526 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
528 if (IsEqualGUID(iid, &IID_IVideoWindow))
529 *out = &filter->baseControlWindow.IVideoWindow_iface;
530 else if (IsEqualGUID(iid, &IID_IBasicVideo))
531 *out = &filter->baseControlVideo.IBasicVideo_iface;
532 else if (IsEqualGUID(iid, &IID_IAMCertifiedOutputProtection))
533 *out = &filter->IAMCertifiedOutputProtection_iface;
534 else if (IsEqualGUID(iid, &IID_IAMFilterMiscFlags))
535 *out = &filter->IAMFilterMiscFlags_iface;
536 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig))
537 *out = &filter->IVMRFilterConfig_iface;
538 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig9))
539 *out = &filter->IVMRFilterConfig9_iface;
540 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig))
541 *out = &filter->IVMRMonitorConfig_iface;
542 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig9))
543 *out = &filter->IVMRMonitorConfig9_iface;
544 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify) && filter->mode == (VMR9Mode)VMRMode_Renderless)
545 *out = &filter->IVMRSurfaceAllocatorNotify_iface;
546 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify9) && filter->mode == VMR9Mode_Renderless)
547 *out = &filter->IVMRSurfaceAllocatorNotify9_iface;
548 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl) && filter->mode == (VMR9Mode)VMRMode_Windowless)
549 *out = &filter->IVMRWindowlessControl_iface;
550 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl9) && filter->mode == VMR9Mode_Windowless)
551 *out = &filter->IVMRWindowlessControl9_iface;
552 else
553 return E_NOINTERFACE;
555 IUnknown_AddRef((IUnknown *)*out);
556 return S_OK;
559 static HRESULT vmr_pin_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
561 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
563 if (IsEqualGUID(iid, &IID_IOverlay))
564 *out = &filter->IOverlay_iface;
565 else
566 return E_NOINTERFACE;
568 IUnknown_AddRef((IUnknown *)*out);
569 return S_OK;
572 static const struct strmbase_renderer_ops renderer_ops =
574 .pfnCheckMediaType = VMR9_CheckMediaType,
575 .pfnDoRenderSample = VMR9_DoRenderSample,
576 .renderer_start_stream = vmr_start_stream,
577 .renderer_stop_stream = vmr_stop_stream,
578 .pfnShouldDrawSampleNow = VMR9_ShouldDrawSampleNow,
579 .renderer_connect = vmr_connect,
580 .pfnBreakConnect = VMR9_BreakConnect,
581 .renderer_destroy = vmr_destroy,
582 .renderer_query_interface = vmr_query_interface,
583 .renderer_pin_query_interface = vmr_pin_query_interface,
586 static RECT WINAPI VMR9_GetDefaultRect(BaseWindow *This)
588 struct quartz_vmr* pVMR9 = impl_from_BaseWindow(This);
589 static RECT defRect;
591 SetRect(&defRect, 0, 0, pVMR9->VideoWidth, pVMR9->VideoHeight);
593 return defRect;
596 static BOOL WINAPI VMR9_OnSize(BaseWindow *This, LONG Width, LONG Height)
598 struct quartz_vmr* pVMR9 = impl_from_BaseWindow(This);
600 TRACE("WM_SIZE %d %d\n", Width, Height);
601 GetClientRect(This->hWnd, &pVMR9->target_rect);
602 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
603 pVMR9->target_rect.left,
604 pVMR9->target_rect.top,
605 pVMR9->target_rect.right - pVMR9->target_rect.left,
606 pVMR9->target_rect.bottom - pVMR9->target_rect.top);
608 return TRUE;
611 static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
612 VMR9_GetDefaultRect,
613 VMR9_OnSize,
616 static HRESULT WINAPI VMR9_GetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
618 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
619 CopyRect(pSourceRect,&pVMR9->source_rect);
620 return S_OK;
623 static HRESULT WINAPI VMR9_GetStaticImage(BaseControlVideo *iface, LONG *size, LONG *image)
625 struct quartz_vmr *filter = impl_from_BaseControlVideo(iface);
626 const AM_MEDIA_TYPE *mt = &filter->renderer.sink.pin.mt;
627 IDirect3DSurface9 *rt = NULL, *surface = NULL;
628 D3DLOCKED_RECT locked_rect;
629 IDirect3DDevice9 *device;
630 unsigned int row_size;
631 BITMAPINFOHEADER bih;
632 LONG i, size_left;
633 char *dst;
634 HRESULT hr;
636 TRACE("filter %p, size %d, image %p.\n", filter, *size, image);
638 EnterCriticalSection(&filter->renderer.csRenderLock);
639 device = filter->allocator_d3d9_dev;
641 if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
642 bih = ((VIDEOINFOHEADER *)mt->pbFormat)->bmiHeader;
643 else if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo2))
644 bih = ((VIDEOINFOHEADER2 *)mt->pbFormat)->bmiHeader;
645 bih.biSizeImage = bih.biWidth * bih.biHeight * bih.biBitCount / 8;
647 if (!image)
649 *size = sizeof(BITMAPINFOHEADER) + bih.biSizeImage;
650 LeaveCriticalSection(&filter->renderer.csRenderLock);
651 return S_OK;
654 if (FAILED(hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt)))
655 goto out;
657 if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, bih.biWidth,
658 bih.biHeight, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL)))
659 goto out;
661 if (FAILED(hr = IDirect3DDevice9_GetRenderTargetData(device, rt, surface)))
662 goto out;
664 if (FAILED(hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_READONLY)))
665 goto out;
667 size_left = *size;
668 memcpy(image, &bih, min(size_left, sizeof(BITMAPINFOHEADER)));
669 size_left -= sizeof(BITMAPINFOHEADER);
671 dst = (char *)image + sizeof(BITMAPINFOHEADER);
672 row_size = bih.biWidth * bih.biBitCount / 8;
674 for (i = 0; i < bih.biHeight && size_left > 0; ++i)
676 memcpy(dst, (char *)locked_rect.pBits + (i * locked_rect.Pitch), min(row_size, size_left));
677 dst += row_size;
678 size_left -= row_size;
681 IDirect3DSurface9_UnlockRect(surface);
683 out:
684 if (surface) IDirect3DSurface9_Release(surface);
685 if (rt) IDirect3DSurface9_Release(rt);
686 LeaveCriticalSection(&filter->renderer.csRenderLock);
687 return hr;
690 static HRESULT WINAPI VMR9_GetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
692 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
693 CopyRect(pTargetRect,&pVMR9->target_rect);
694 return S_OK;
697 static VIDEOINFOHEADER* WINAPI VMR9_GetVideoFormat(BaseControlVideo* This)
699 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
700 AM_MEDIA_TYPE *pmt;
702 TRACE("(%p/%p)\n", pVMR9, This);
704 pmt = &pVMR9->renderer.sink.pin.mt;
705 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
706 return (VIDEOINFOHEADER*)pmt->pbFormat;
707 } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
708 static VIDEOINFOHEADER vih;
709 VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
710 memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
711 memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
712 return &vih;
713 } else {
714 ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
715 return NULL;
719 static HRESULT WINAPI VMR9_IsDefaultSourceRect(BaseControlVideo* This)
721 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
722 FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
724 return S_OK;
727 static HRESULT WINAPI VMR9_IsDefaultTargetRect(BaseControlVideo* This)
729 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
730 FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
732 return S_OK;
735 static HRESULT WINAPI VMR9_SetDefaultSourceRect(BaseControlVideo* This)
737 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
739 SetRect(&pVMR9->source_rect, 0, 0, pVMR9->VideoWidth, pVMR9->VideoHeight);
741 return S_OK;
744 static HRESULT WINAPI VMR9_SetDefaultTargetRect(BaseControlVideo* This)
746 RECT rect;
747 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
749 if (!GetClientRect(pVMR9->baseControlWindow.baseWindow.hWnd, &rect))
750 return E_FAIL;
752 SetRect(&pVMR9->target_rect, 0, 0, rect.right, rect.bottom);
754 return S_OK;
757 static HRESULT WINAPI VMR9_SetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
759 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
760 CopyRect(&pVMR9->source_rect,pSourceRect);
761 return S_OK;
764 static HRESULT WINAPI VMR9_SetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
766 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
767 CopyRect(&pVMR9->target_rect,pTargetRect);
768 return S_OK;
771 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
772 VMR9_GetSourceRect,
773 VMR9_GetStaticImage,
774 VMR9_GetTargetRect,
775 VMR9_GetVideoFormat,
776 VMR9_IsDefaultSourceRect,
777 VMR9_IsDefaultTargetRect,
778 VMR9_SetDefaultSourceRect,
779 VMR9_SetDefaultTargetRect,
780 VMR9_SetSourceRect,
781 VMR9_SetTargetRect
784 static const IVideoWindowVtbl IVideoWindow_VTable =
786 BaseControlWindowImpl_QueryInterface,
787 BaseControlWindowImpl_AddRef,
788 BaseControlWindowImpl_Release,
789 BaseControlWindowImpl_GetTypeInfoCount,
790 BaseControlWindowImpl_GetTypeInfo,
791 BaseControlWindowImpl_GetIDsOfNames,
792 BaseControlWindowImpl_Invoke,
793 BaseControlWindowImpl_put_Caption,
794 BaseControlWindowImpl_get_Caption,
795 BaseControlWindowImpl_put_WindowStyle,
796 BaseControlWindowImpl_get_WindowStyle,
797 BaseControlWindowImpl_put_WindowStyleEx,
798 BaseControlWindowImpl_get_WindowStyleEx,
799 BaseControlWindowImpl_put_AutoShow,
800 BaseControlWindowImpl_get_AutoShow,
801 BaseControlWindowImpl_put_WindowState,
802 BaseControlWindowImpl_get_WindowState,
803 BaseControlWindowImpl_put_BackgroundPalette,
804 BaseControlWindowImpl_get_BackgroundPalette,
805 BaseControlWindowImpl_put_Visible,
806 BaseControlWindowImpl_get_Visible,
807 BaseControlWindowImpl_put_Left,
808 BaseControlWindowImpl_get_Left,
809 BaseControlWindowImpl_put_Width,
810 BaseControlWindowImpl_get_Width,
811 BaseControlWindowImpl_put_Top,
812 BaseControlWindowImpl_get_Top,
813 BaseControlWindowImpl_put_Height,
814 BaseControlWindowImpl_get_Height,
815 BaseControlWindowImpl_put_Owner,
816 BaseControlWindowImpl_get_Owner,
817 BaseControlWindowImpl_put_MessageDrain,
818 BaseControlWindowImpl_get_MessageDrain,
819 BaseControlWindowImpl_get_BorderColor,
820 BaseControlWindowImpl_put_BorderColor,
821 BaseControlWindowImpl_get_FullScreenMode,
822 BaseControlWindowImpl_put_FullScreenMode,
823 BaseControlWindowImpl_SetWindowForeground,
824 BaseControlWindowImpl_NotifyOwnerMessage,
825 BaseControlWindowImpl_SetWindowPosition,
826 BaseControlWindowImpl_GetWindowPosition,
827 BaseControlWindowImpl_GetMinIdealImageSize,
828 BaseControlWindowImpl_GetMaxIdealImageSize,
829 BaseControlWindowImpl_GetRestorePosition,
830 BaseControlWindowImpl_HideCursor,
831 BaseControlWindowImpl_IsCursorHidden
834 static HRESULT WINAPI AMCertifiedOutputProtection_QueryInterface(IAMCertifiedOutputProtection *iface,
835 REFIID riid, void **ppv)
837 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
838 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
841 static ULONG WINAPI AMCertifiedOutputProtection_AddRef(IAMCertifiedOutputProtection *iface)
843 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
844 return IUnknown_AddRef(This->renderer.filter.outer_unk);
847 static ULONG WINAPI AMCertifiedOutputProtection_Release(IAMCertifiedOutputProtection *iface)
849 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
850 return IUnknown_Release(This->renderer.filter.outer_unk);
853 static HRESULT WINAPI AMCertifiedOutputProtection_KeyExchange(IAMCertifiedOutputProtection *iface,
854 GUID* pRandom, BYTE** VarLenCertGH,
855 DWORD* pdwLengthCertGH)
857 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
859 FIXME("(%p/%p)->(%p, %p, %p) stub\n", iface, This, pRandom, VarLenCertGH, pdwLengthCertGH);
860 return VFW_E_NO_COPP_HW;
863 static HRESULT WINAPI AMCertifiedOutputProtection_SessionSequenceStart(IAMCertifiedOutputProtection *iface,
864 AMCOPPSignature* pSig)
866 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
868 FIXME("(%p/%p)->(%p) stub\n", iface, This, pSig);
869 return VFW_E_NO_COPP_HW;
872 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionCommand(IAMCertifiedOutputProtection *iface,
873 const AMCOPPCommand* cmd)
875 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
877 FIXME("(%p/%p)->(%p) stub\n", iface, This, cmd);
878 return VFW_E_NO_COPP_HW;
881 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionStatus(IAMCertifiedOutputProtection *iface,
882 const AMCOPPStatusInput* pStatusInput,
883 AMCOPPStatusOutput* pStatusOutput)
885 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
887 FIXME("(%p/%p)->(%p, %p) stub\n", iface, This, pStatusInput, pStatusOutput);
888 return VFW_E_NO_COPP_HW;
891 static const IAMCertifiedOutputProtectionVtbl IAMCertifiedOutputProtection_Vtbl =
893 AMCertifiedOutputProtection_QueryInterface,
894 AMCertifiedOutputProtection_AddRef,
895 AMCertifiedOutputProtection_Release,
896 AMCertifiedOutputProtection_KeyExchange,
897 AMCertifiedOutputProtection_SessionSequenceStart,
898 AMCertifiedOutputProtection_ProtectionCommand,
899 AMCertifiedOutputProtection_ProtectionStatus
902 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
903 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
904 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
907 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
908 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
909 return IUnknown_AddRef(This->renderer.filter.outer_unk);
912 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
913 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
914 return IUnknown_Release(This->renderer.filter.outer_unk);
917 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
918 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
921 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
922 AMFilterMiscFlags_QueryInterface,
923 AMFilterMiscFlags_AddRef,
924 AMFilterMiscFlags_Release,
925 AMFilterMiscFlags_GetMiscFlags
928 static HRESULT WINAPI VMR7FilterConfig_QueryInterface(IVMRFilterConfig *iface, REFIID riid,
929 void** ppv)
931 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
932 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
935 static ULONG WINAPI VMR7FilterConfig_AddRef(IVMRFilterConfig *iface)
937 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
938 return IUnknown_AddRef(This->renderer.filter.outer_unk);
941 static ULONG WINAPI VMR7FilterConfig_Release(IVMRFilterConfig *iface)
943 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
944 return IUnknown_Release(This->renderer.filter.outer_unk);
947 static HRESULT WINAPI VMR7FilterConfig_SetImageCompositor(IVMRFilterConfig *iface,
948 IVMRImageCompositor *compositor)
950 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
952 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
953 return E_NOTIMPL;
956 static HRESULT WINAPI VMR7FilterConfig_SetNumberOfStreams(IVMRFilterConfig *iface, DWORD max)
958 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
960 FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
961 return E_NOTIMPL;
964 static HRESULT WINAPI VMR7FilterConfig_GetNumberOfStreams(IVMRFilterConfig *iface, DWORD *max)
966 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
968 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
969 return E_NOTIMPL;
972 static HRESULT WINAPI VMR7FilterConfig_SetRenderingPrefs(IVMRFilterConfig *iface, DWORD renderflags)
974 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
976 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
977 return E_NOTIMPL;
980 static HRESULT WINAPI VMR7FilterConfig_GetRenderingPrefs(IVMRFilterConfig *iface, DWORD *renderflags)
982 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
984 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
985 return E_NOTIMPL;
988 static HRESULT WINAPI VMR7FilterConfig_SetRenderingMode(IVMRFilterConfig *iface, DWORD mode)
990 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
992 TRACE("iface %p, mode %#x.\n", iface, mode);
994 return IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, mode);
997 static HRESULT WINAPI VMR7FilterConfig_GetRenderingMode(IVMRFilterConfig *iface, DWORD *mode)
999 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1001 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
1002 if (!mode) return E_POINTER;
1004 if (This->mode)
1005 *mode = This->mode;
1006 else
1007 *mode = VMRMode_Windowed;
1009 return S_OK;
1012 static const IVMRFilterConfigVtbl VMR7_FilterConfig_Vtbl =
1014 VMR7FilterConfig_QueryInterface,
1015 VMR7FilterConfig_AddRef,
1016 VMR7FilterConfig_Release,
1017 VMR7FilterConfig_SetImageCompositor,
1018 VMR7FilterConfig_SetNumberOfStreams,
1019 VMR7FilterConfig_GetNumberOfStreams,
1020 VMR7FilterConfig_SetRenderingPrefs,
1021 VMR7FilterConfig_GetRenderingPrefs,
1022 VMR7FilterConfig_SetRenderingMode,
1023 VMR7FilterConfig_GetRenderingMode
1026 struct get_available_monitors_args
1028 VMRMONITORINFO *info7;
1029 VMR9MonitorInfo *info9;
1030 DWORD arraysize;
1031 DWORD numdev;
1034 static BOOL CALLBACK get_available_monitors_proc(HMONITOR hmon, HDC hdc, LPRECT lprc, LPARAM lparam)
1036 struct get_available_monitors_args *args = (struct get_available_monitors_args *)lparam;
1037 MONITORINFOEXW mi;
1039 if (args->info7 || args->info9)
1042 if (!args->arraysize)
1043 return FALSE;
1045 mi.cbSize = sizeof(mi);
1046 if (!GetMonitorInfoW(hmon, (MONITORINFO*)&mi))
1047 return TRUE;
1049 /* fill VMRMONITORINFO struct */
1050 if (args->info7)
1052 VMRMONITORINFO *info = args->info7++;
1053 memset(info, 0, sizeof(*info));
1055 if (args->numdev > 0)
1057 info->guid.pGUID = &info->guid.GUID;
1058 info->guid.GUID.Data4[7] = args->numdev;
1060 else
1061 info->guid.pGUID = NULL;
1063 info->rcMonitor = mi.rcMonitor;
1064 info->hMon = hmon;
1065 info->dwFlags = mi.dwFlags;
1067 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1069 /* FIXME: how to get these values? */
1070 info->szDescription[0] = 0;
1073 /* fill VMR9MonitorInfo struct */
1074 if (args->info9)
1076 VMR9MonitorInfo *info = args->info9++;
1077 memset(info, 0, sizeof(*info));
1079 info->uDevID = 0; /* FIXME */
1080 info->rcMonitor = mi.rcMonitor;
1081 info->hMon = hmon;
1082 info->dwFlags = mi.dwFlags;
1084 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1086 /* FIXME: how to get these values? */
1087 info->szDescription[0] = 0;
1088 info->dwVendorId = 0;
1089 info->dwDeviceId = 0;
1090 info->dwSubSysId = 0;
1091 info->dwRevision = 0;
1094 args->arraysize--;
1097 args->numdev++;
1098 return TRUE;
1101 static HRESULT WINAPI VMR7MonitorConfig_QueryInterface(IVMRMonitorConfig *iface, REFIID riid,
1102 LPVOID * ppv)
1104 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1105 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1108 static ULONG WINAPI VMR7MonitorConfig_AddRef(IVMRMonitorConfig *iface)
1110 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1111 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1114 static ULONG WINAPI VMR7MonitorConfig_Release(IVMRMonitorConfig *iface)
1116 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1117 return IUnknown_Release(This->renderer.filter.outer_unk);
1120 static HRESULT WINAPI VMR7MonitorConfig_SetMonitor(IVMRMonitorConfig *iface, const VMRGUID *pGUID)
1122 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1124 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1126 if (!pGUID)
1127 return E_POINTER;
1129 return S_OK;
1132 static HRESULT WINAPI VMR7MonitorConfig_GetMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1134 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1136 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1138 if (!pGUID)
1139 return E_POINTER;
1141 pGUID->pGUID = NULL; /* default DirectDraw device */
1142 return S_OK;
1145 static HRESULT WINAPI VMR7MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig *iface,
1146 const VMRGUID *pGUID)
1148 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1150 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1152 if (!pGUID)
1153 return E_POINTER;
1155 return S_OK;
1158 static HRESULT WINAPI VMR7MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1160 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1162 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1164 if (!pGUID)
1165 return E_POINTER;
1167 pGUID->pGUID = NULL; /* default DirectDraw device */
1168 return S_OK;
1171 static HRESULT WINAPI VMR7MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig *iface,
1172 VMRMONITORINFO *info, DWORD arraysize,
1173 DWORD *numdev)
1175 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1176 struct get_available_monitors_args args;
1178 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1180 if (!numdev)
1181 return E_POINTER;
1183 if (info && arraysize == 0)
1184 return E_INVALIDARG;
1186 args.info7 = info;
1187 args.info9 = NULL;
1188 args.arraysize = arraysize;
1189 args.numdev = 0;
1190 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1192 *numdev = args.numdev;
1193 return S_OK;
1196 static const IVMRMonitorConfigVtbl VMR7_MonitorConfig_Vtbl =
1198 VMR7MonitorConfig_QueryInterface,
1199 VMR7MonitorConfig_AddRef,
1200 VMR7MonitorConfig_Release,
1201 VMR7MonitorConfig_SetMonitor,
1202 VMR7MonitorConfig_GetMonitor,
1203 VMR7MonitorConfig_SetDefaultMonitor,
1204 VMR7MonitorConfig_GetDefaultMonitor,
1205 VMR7MonitorConfig_GetAvailableMonitors
1208 static HRESULT WINAPI VMR9MonitorConfig_QueryInterface(IVMRMonitorConfig9 *iface, REFIID riid,
1209 LPVOID * ppv)
1211 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1212 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1215 static ULONG WINAPI VMR9MonitorConfig_AddRef(IVMRMonitorConfig9 *iface)
1217 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1218 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1221 static ULONG WINAPI VMR9MonitorConfig_Release(IVMRMonitorConfig9 *iface)
1223 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1224 return IUnknown_Release(This->renderer.filter.outer_unk);
1227 static HRESULT WINAPI VMR9MonitorConfig_SetMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1229 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1231 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1233 return S_OK;
1236 static HRESULT WINAPI VMR9MonitorConfig_GetMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1238 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1240 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1242 if (!uDev)
1243 return E_POINTER;
1245 *uDev = 0;
1246 return S_OK;
1249 static HRESULT WINAPI VMR9MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1251 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1253 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1255 return S_OK;
1258 static HRESULT WINAPI VMR9MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1260 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1262 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1264 if (!uDev)
1265 return E_POINTER;
1267 *uDev = 0;
1268 return S_OK;
1271 static HRESULT WINAPI VMR9MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig9 *iface,
1272 VMR9MonitorInfo *info, DWORD arraysize,
1273 DWORD *numdev)
1275 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1276 struct get_available_monitors_args args;
1278 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1280 if (!numdev)
1281 return E_POINTER;
1283 if (info && arraysize == 0)
1284 return E_INVALIDARG;
1286 args.info7 = NULL;
1287 args.info9 = info;
1288 args.arraysize = arraysize;
1289 args.numdev = 0;
1290 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1292 *numdev = args.numdev;
1293 return S_OK;
1296 static const IVMRMonitorConfig9Vtbl VMR9_MonitorConfig_Vtbl =
1298 VMR9MonitorConfig_QueryInterface,
1299 VMR9MonitorConfig_AddRef,
1300 VMR9MonitorConfig_Release,
1301 VMR9MonitorConfig_SetMonitor,
1302 VMR9MonitorConfig_GetMonitor,
1303 VMR9MonitorConfig_SetDefaultMonitor,
1304 VMR9MonitorConfig_GetDefaultMonitor,
1305 VMR9MonitorConfig_GetAvailableMonitors
1308 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
1310 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1311 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1314 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
1316 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1317 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1320 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
1322 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1323 return IUnknown_Release(This->renderer.filter.outer_unk);
1326 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
1328 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1330 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
1331 return E_NOTIMPL;
1334 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD count)
1336 FIXME("iface %p, count %u, stub!\n", iface, count);
1337 if (count == 1)
1338 return S_OK;
1339 return E_NOTIMPL;
1342 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *max)
1344 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1346 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
1347 return E_NOTIMPL;
1350 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
1352 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1354 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
1355 return E_NOTIMPL;
1358 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
1360 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1362 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
1363 return E_NOTIMPL;
1366 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
1368 HRESULT hr = S_OK;
1369 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1371 TRACE("(%p/%p)->(%u)\n", iface, This, mode);
1373 EnterCriticalSection(&This->renderer.filter.csFilter);
1374 if (This->mode)
1376 LeaveCriticalSection(&This->renderer.filter.csFilter);
1377 return VFW_E_WRONG_STATE;
1380 if (This->allocator)
1381 IVMRSurfaceAllocatorEx9_Release(This->allocator);
1382 if (This->presenter)
1383 IVMRImagePresenter9_Release(This->presenter);
1385 This->allocator = NULL;
1386 This->presenter = NULL;
1388 switch (mode)
1390 case VMR9Mode_Windowed:
1391 case VMR9Mode_Windowless:
1392 This->allocator_is_ex = 0;
1393 This->cookie = ~0;
1395 hr = VMR9DefaultAllocatorPresenterImpl_create(This, (LPVOID*)&This->presenter);
1396 if (SUCCEEDED(hr))
1397 hr = IVMRImagePresenter9_QueryInterface(This->presenter, &IID_IVMRSurfaceAllocatorEx9, (LPVOID*)&This->allocator);
1398 if (FAILED(hr))
1400 ERR("Unable to find Presenter interface\n");
1401 IVMRImagePresenter9_Release(This->presenter);
1402 This->allocator = NULL;
1403 This->presenter = NULL;
1405 else
1406 hr = IVMRSurfaceAllocatorEx9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
1407 break;
1408 case VMR9Mode_Renderless:
1409 break;
1410 default:
1411 LeaveCriticalSection(&This->renderer.filter.csFilter);
1412 return E_INVALIDARG;
1415 This->mode = mode;
1416 LeaveCriticalSection(&This->renderer.filter.csFilter);
1417 return hr;
1420 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
1422 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1424 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
1425 if (!mode)
1426 return E_POINTER;
1428 if (This->mode)
1429 *mode = This->mode;
1430 else
1431 *mode = VMR9Mode_Windowed;
1433 return S_OK;
1436 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
1438 VMR9FilterConfig_QueryInterface,
1439 VMR9FilterConfig_AddRef,
1440 VMR9FilterConfig_Release,
1441 VMR9FilterConfig_SetImageCompositor,
1442 VMR9FilterConfig_SetNumberOfStreams,
1443 VMR9FilterConfig_GetNumberOfStreams,
1444 VMR9FilterConfig_SetRenderingPrefs,
1445 VMR9FilterConfig_GetRenderingPrefs,
1446 VMR9FilterConfig_SetRenderingMode,
1447 VMR9FilterConfig_GetRenderingMode
1450 static HRESULT WINAPI VMR7WindowlessControl_QueryInterface(IVMRWindowlessControl *iface, REFIID riid,
1451 LPVOID * ppv)
1453 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1454 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1457 static ULONG WINAPI VMR7WindowlessControl_AddRef(IVMRWindowlessControl *iface)
1459 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1460 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1463 static ULONG WINAPI VMR7WindowlessControl_Release(IVMRWindowlessControl *iface)
1465 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1466 return IUnknown_Release(This->renderer.filter.outer_unk);
1469 static HRESULT WINAPI VMR7WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl *iface,
1470 LONG *width, LONG *height,
1471 LONG *arwidth, LONG *arheight)
1473 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1474 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
1476 if (!width || !height || !arwidth || !arheight)
1478 ERR("Got no pointer\n");
1479 return E_POINTER;
1482 *width = This->bmiheader.biWidth;
1483 *height = This->bmiheader.biHeight;
1484 *arwidth = This->bmiheader.biWidth;
1485 *arheight = This->bmiheader.biHeight;
1487 return S_OK;
1490 static HRESULT WINAPI VMR7WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl *iface,
1491 LONG *width, LONG *height)
1493 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1495 FIXME("(%p/%p)->(...) stub\n", iface, This);
1496 return E_NOTIMPL;
1499 static HRESULT WINAPI VMR7WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl *iface,
1500 LONG *width, LONG *height)
1502 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1504 FIXME("(%p/%p)->(...) stub\n", iface, This);
1505 return E_NOTIMPL;
1508 static HRESULT WINAPI VMR7WindowlessControl_SetVideoPosition(IVMRWindowlessControl *iface,
1509 const RECT *source, const RECT *dest)
1511 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1513 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1515 EnterCriticalSection(&This->renderer.filter.csFilter);
1517 if (source)
1518 This->source_rect = *source;
1519 if (dest)
1521 This->target_rect = *dest;
1522 FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest));
1523 SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
1524 dest->left, dest->top, dest->right - dest->left, dest->bottom-dest->top,
1525 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW);
1528 LeaveCriticalSection(&This->renderer.filter.csFilter);
1530 return S_OK;
1533 static HRESULT WINAPI VMR7WindowlessControl_GetVideoPosition(IVMRWindowlessControl *iface,
1534 RECT *source, RECT *dest)
1536 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1538 if (source)
1539 *source = This->source_rect;
1541 if (dest)
1542 *dest = This->target_rect;
1544 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1545 return S_OK;
1548 static HRESULT WINAPI VMR7WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl *iface,
1549 DWORD *mode)
1551 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1553 FIXME("(%p/%p)->(...) stub\n", iface, This);
1554 return E_NOTIMPL;
1557 static HRESULT WINAPI VMR7WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl *iface,
1558 DWORD mode)
1560 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1562 FIXME("(%p/%p)->(...) stub\n", iface, This);
1563 return E_NOTIMPL;
1566 static HRESULT WINAPI VMR7WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl *iface, HWND window)
1568 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1570 TRACE("iface %p, window %p.\n", iface, window);
1572 return IVMRWindowlessControl9_SetVideoClippingWindow(&filter->IVMRWindowlessControl9_iface, window);
1575 static HRESULT WINAPI VMR7WindowlessControl_RepaintVideo(IVMRWindowlessControl *iface,
1576 HWND hwnd, HDC hdc)
1578 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1580 FIXME("(%p/%p)->(...) stub\n", iface, This);
1581 return E_NOTIMPL;
1584 static HRESULT WINAPI VMR7WindowlessControl_DisplayModeChanged(IVMRWindowlessControl *iface)
1586 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1588 FIXME("(%p/%p)->(...) stub\n", iface, This);
1589 return E_NOTIMPL;
1592 static HRESULT WINAPI VMR7WindowlessControl_GetCurrentImage(IVMRWindowlessControl *iface,
1593 BYTE **dib)
1595 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1597 FIXME("(%p/%p)->(...) stub\n", iface, This);
1598 return E_NOTIMPL;
1601 static HRESULT WINAPI VMR7WindowlessControl_SetBorderColor(IVMRWindowlessControl *iface,
1602 COLORREF color)
1604 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1606 FIXME("(%p/%p)->(...) stub\n", iface, This);
1607 return E_NOTIMPL;
1610 static HRESULT WINAPI VMR7WindowlessControl_GetBorderColor(IVMRWindowlessControl *iface,
1611 COLORREF *color)
1613 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1615 FIXME("(%p/%p)->(...) stub\n", iface, This);
1616 return E_NOTIMPL;
1619 static HRESULT WINAPI VMR7WindowlessControl_SetColorKey(IVMRWindowlessControl *iface, COLORREF color)
1621 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1623 FIXME("(%p/%p)->(...) stub\n", iface, This);
1624 return E_NOTIMPL;
1627 static HRESULT WINAPI VMR7WindowlessControl_GetColorKey(IVMRWindowlessControl *iface, COLORREF *color)
1629 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1631 FIXME("(%p/%p)->(...) stub\n", iface, This);
1632 return E_NOTIMPL;
1635 static const IVMRWindowlessControlVtbl VMR7_WindowlessControl_Vtbl =
1637 VMR7WindowlessControl_QueryInterface,
1638 VMR7WindowlessControl_AddRef,
1639 VMR7WindowlessControl_Release,
1640 VMR7WindowlessControl_GetNativeVideoSize,
1641 VMR7WindowlessControl_GetMinIdealVideoSize,
1642 VMR7WindowlessControl_GetMaxIdealVideoSize,
1643 VMR7WindowlessControl_SetVideoPosition,
1644 VMR7WindowlessControl_GetVideoPosition,
1645 VMR7WindowlessControl_GetAspectRatioMode,
1646 VMR7WindowlessControl_SetAspectRatioMode,
1647 VMR7WindowlessControl_SetVideoClippingWindow,
1648 VMR7WindowlessControl_RepaintVideo,
1649 VMR7WindowlessControl_DisplayModeChanged,
1650 VMR7WindowlessControl_GetCurrentImage,
1651 VMR7WindowlessControl_SetBorderColor,
1652 VMR7WindowlessControl_GetBorderColor,
1653 VMR7WindowlessControl_SetColorKey,
1654 VMR7WindowlessControl_GetColorKey
1657 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
1659 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1660 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1663 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
1665 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1666 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1669 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
1671 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1672 return IUnknown_Release(This->renderer.filter.outer_unk);
1675 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height, LONG *arwidth, LONG *arheight)
1677 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1678 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
1680 if (!width || !height || !arwidth || !arheight)
1682 ERR("Got no pointer\n");
1683 return E_POINTER;
1686 *width = This->bmiheader.biWidth;
1687 *height = This->bmiheader.biHeight;
1688 *arwidth = This->bmiheader.biWidth;
1689 *arheight = This->bmiheader.biHeight;
1691 return S_OK;
1694 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1696 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1698 FIXME("(%p/%p)->(...) stub\n", iface, This);
1699 return E_NOTIMPL;
1702 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1704 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1706 FIXME("(%p/%p)->(...) stub\n", iface, This);
1707 return E_NOTIMPL;
1710 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface, const RECT *source, const RECT *dest)
1712 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1714 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1716 EnterCriticalSection(&This->renderer.filter.csFilter);
1718 if (source)
1719 This->source_rect = *source;
1720 if (dest)
1722 This->target_rect = *dest;
1723 FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest));
1724 SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
1725 dest->left, dest->top, dest->right - dest->left, dest->bottom - dest->top,
1726 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW);
1729 LeaveCriticalSection(&This->renderer.filter.csFilter);
1731 return S_OK;
1734 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *source, RECT *dest)
1736 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1738 if (source)
1739 *source = This->source_rect;
1741 if (dest)
1742 *dest = This->target_rect;
1744 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1745 return S_OK;
1748 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1750 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1752 FIXME("(%p/%p)->(...) stub\n", iface, This);
1753 return E_NOTIMPL;
1756 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1758 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1760 FIXME("(%p/%p)->(...) stub\n", iface, This);
1761 return E_NOTIMPL;
1764 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND hwnd)
1766 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1768 TRACE("(%p/%p)->(%p)\n", iface, This, hwnd);
1770 EnterCriticalSection(&This->renderer.filter.csFilter);
1771 This->hWndClippingWindow = hwnd;
1772 if (This->renderer.sink.pin.peer)
1773 VMR9_maybe_init(This, FALSE);
1774 if (!hwnd)
1775 IVMRSurfaceAllocatorEx9_TerminateDevice(This->allocator, This->cookie);
1776 LeaveCriticalSection(&This->renderer.filter.csFilter);
1777 return S_OK;
1780 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1782 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1783 HRESULT hr;
1785 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1787 EnterCriticalSection(&This->renderer.filter.csFilter);
1788 if (hwnd != This->hWndClippingWindow && hwnd != This->baseControlWindow.baseWindow.hWnd)
1790 ERR("Not handling changing windows yet!!!\n");
1791 LeaveCriticalSection(&This->renderer.filter.csFilter);
1792 return S_OK;
1795 if (!This->allocator_d3d9_dev)
1797 ERR("No d3d9 device!\n");
1798 LeaveCriticalSection(&This->renderer.filter.csFilter);
1799 return VFW_E_WRONG_STATE;
1802 /* Windowless extension */
1803 hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, This->baseControlWindow.baseWindow.hWnd, NULL);
1804 LeaveCriticalSection(&This->renderer.filter.csFilter);
1806 return hr;
1809 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1811 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1813 FIXME("(%p/%p)->(...) stub\n", iface, This);
1814 return E_NOTIMPL;
1817 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1819 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1821 FIXME("(%p/%p)->(...) stub\n", iface, This);
1822 return E_NOTIMPL;
1825 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1827 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1829 FIXME("(%p/%p)->(...) stub\n", iface, This);
1830 return E_NOTIMPL;
1833 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1835 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1837 FIXME("(%p/%p)->(...) stub\n", iface, This);
1838 return E_NOTIMPL;
1841 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1843 VMR9WindowlessControl_QueryInterface,
1844 VMR9WindowlessControl_AddRef,
1845 VMR9WindowlessControl_Release,
1846 VMR9WindowlessControl_GetNativeVideoSize,
1847 VMR9WindowlessControl_GetMinIdealVideoSize,
1848 VMR9WindowlessControl_GetMaxIdealVideoSize,
1849 VMR9WindowlessControl_SetVideoPosition,
1850 VMR9WindowlessControl_GetVideoPosition,
1851 VMR9WindowlessControl_GetAspectRatioMode,
1852 VMR9WindowlessControl_SetAspectRatioMode,
1853 VMR9WindowlessControl_SetVideoClippingWindow,
1854 VMR9WindowlessControl_RepaintVideo,
1855 VMR9WindowlessControl_DisplayModeChanged,
1856 VMR9WindowlessControl_GetCurrentImage,
1857 VMR9WindowlessControl_SetBorderColor,
1858 VMR9WindowlessControl_GetBorderColor
1861 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify *iface,
1862 REFIID riid, LPVOID * ppv)
1864 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1865 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1868 static ULONG WINAPI VMR7SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify *iface)
1870 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1871 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1874 static ULONG WINAPI VMR7SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify *iface)
1876 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1877 return IUnknown_Release(This->renderer.filter.outer_unk);
1880 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify *iface,
1881 DWORD_PTR id,
1882 IVMRSurfaceAllocator *alloc)
1884 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1886 FIXME("(%p/%p)->(...) stub\n", iface, This);
1887 return E_NOTIMPL;
1890 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1891 IDirectDraw7 *device, HMONITOR monitor)
1893 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1895 FIXME("(%p/%p)->(...) stub\n", iface, This);
1896 return E_NOTIMPL;
1899 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_ChangeDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1900 IDirectDraw7 *device, HMONITOR monitor)
1902 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1904 FIXME("(%p/%p)->(...) stub\n", iface, This);
1905 return E_NOTIMPL;
1908 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces(IVMRSurfaceAllocatorNotify *iface)
1910 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1912 FIXME("(%p/%p)->(...) stub\n", iface, This);
1913 return E_NOTIMPL;
1916 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify *iface, LONG code,
1917 LONG_PTR param1, LONG_PTR param2)
1919 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1921 FIXME("(%p/%p)->(...) stub\n", iface, This);
1922 return E_NOTIMPL;
1925 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetBorderColor(IVMRSurfaceAllocatorNotify *iface,
1926 COLORREF clrBorder)
1928 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1930 FIXME("(%p/%p)->(...) stub\n", iface, This);
1931 return E_NOTIMPL;
1934 static const IVMRSurfaceAllocatorNotifyVtbl VMR7_SurfaceAllocatorNotify_Vtbl =
1936 VMR7SurfaceAllocatorNotify_QueryInterface,
1937 VMR7SurfaceAllocatorNotify_AddRef,
1938 VMR7SurfaceAllocatorNotify_Release,
1939 VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1940 VMR7SurfaceAllocatorNotify_SetDDrawDevice,
1941 VMR7SurfaceAllocatorNotify_ChangeDDrawDevice,
1942 VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces,
1943 VMR7SurfaceAllocatorNotify_NotifyEvent,
1944 VMR7SurfaceAllocatorNotify_SetBorderColor
1947 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1949 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1950 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1953 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1955 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1956 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1959 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1961 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1962 return IUnknown_Release(This->renderer.filter.outer_unk);
1965 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR id, IVMRSurfaceAllocator9 *alloc)
1967 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1969 /* FIXME: This code is not tested!!! */
1970 FIXME("(%p/%p)->(...) stub\n", iface, This);
1971 This->cookie = id;
1973 if (This->presenter)
1974 return VFW_E_WRONG_STATE;
1976 if (FAILED(IVMRSurfaceAllocator9_QueryInterface(alloc, &IID_IVMRImagePresenter9, (void **)&This->presenter)))
1977 return E_NOINTERFACE;
1979 if (SUCCEEDED(IVMRSurfaceAllocator9_QueryInterface(alloc, &IID_IVMRSurfaceAllocatorEx9, (void **)&This->allocator)))
1980 This->allocator_is_ex = 1;
1981 else
1983 This->allocator = (IVMRSurfaceAllocatorEx9 *)alloc;
1984 IVMRSurfaceAllocator9_AddRef(alloc);
1985 This->allocator_is_ex = 0;
1988 return S_OK;
1991 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
1993 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1995 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1996 if (This->allocator_d3d9_dev)
1997 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
1998 This->allocator_d3d9_dev = device;
1999 IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
2000 This->allocator_mon = monitor;
2002 return S_OK;
2005 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
2007 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2009 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
2010 if (This->allocator_d3d9_dev)
2011 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
2012 This->allocator_d3d9_dev = device;
2013 IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
2014 This->allocator_mon = monitor;
2016 return S_OK;
2019 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
2021 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2022 DWORD i;
2023 HRESULT hr = S_OK;
2025 FIXME("(%p/%p)->(%p, %p => %u, %p) semi-stub\n", iface, This, allocinfo, numbuffers, (numbuffers ? *numbuffers : 0), surface);
2027 if (!allocinfo || !numbuffers || !surface)
2028 return E_POINTER;
2030 if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
2032 ERR("Invalid number of buffers?\n");
2033 return E_INVALIDARG;
2036 if (!This->allocator_d3d9_dev)
2038 ERR("No direct3d device when requested to allocate a surface!\n");
2039 return VFW_E_WRONG_STATE;
2042 if (allocinfo->dwFlags & VMR9AllocFlag_OffscreenSurface)
2044 ERR("Creating offscreen surface\n");
2045 for (i = 0; i < *numbuffers; ++i)
2047 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight,
2048 allocinfo->Format, allocinfo->Pool, &surface[i], NULL);
2049 if (FAILED(hr))
2050 break;
2053 else if (allocinfo->dwFlags & VMR9AllocFlag_TextureSurface)
2055 TRACE("Creating texture surface\n");
2056 for (i = 0; i < *numbuffers; ++i)
2058 IDirect3DTexture9 *texture;
2060 hr = IDirect3DDevice9_CreateTexture(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, 1, 0,
2061 allocinfo->Format, allocinfo->Pool, &texture, NULL);
2062 if (FAILED(hr))
2063 break;
2064 IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface[i]);
2065 IDirect3DTexture9_Release(texture);
2068 else
2070 FIXME("Could not allocate for type %08x\n", allocinfo->dwFlags);
2071 return E_NOTIMPL;
2074 if (i >= allocinfo->MinBuffers)
2076 hr = S_OK;
2077 *numbuffers = i;
2079 else
2081 for ( ; i > 0; --i) IDirect3DSurface9_Release(surface[i - 1]);
2082 *numbuffers = 0;
2084 return hr;
2087 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
2089 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2091 FIXME("(%p/%p)->(...) stub\n", iface, This);
2092 return E_NOTIMPL;
2095 static const IVMRSurfaceAllocatorNotify9Vtbl VMR9_SurfaceAllocatorNotify_Vtbl =
2097 VMR9SurfaceAllocatorNotify_QueryInterface,
2098 VMR9SurfaceAllocatorNotify_AddRef,
2099 VMR9SurfaceAllocatorNotify_Release,
2100 VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
2101 VMR9SurfaceAllocatorNotify_SetD3DDevice,
2102 VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
2103 VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
2104 VMR9SurfaceAllocatorNotify_NotifyEvent
2107 static inline struct quartz_vmr *impl_from_IOverlay(IOverlay *iface)
2109 return CONTAINING_RECORD(iface, struct quartz_vmr, IOverlay_iface);
2112 static HRESULT WINAPI overlay_QueryInterface(IOverlay *iface, REFIID iid, void **out)
2114 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2115 return IPin_QueryInterface(&filter->renderer.sink.pin.IPin_iface, iid, out);
2118 static ULONG WINAPI overlay_AddRef(IOverlay *iface)
2120 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2121 return IPin_AddRef(&filter->renderer.sink.pin.IPin_iface);
2124 static ULONG WINAPI overlay_Release(IOverlay *iface)
2126 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2127 return IPin_Release(&filter->renderer.sink.pin.IPin_iface);
2130 static HRESULT WINAPI overlay_GetPalette(IOverlay *iface, DWORD *count, PALETTEENTRY **palette)
2132 FIXME("iface %p, count %p, palette %p, stub!\n", iface, count, palette);
2133 return E_NOTIMPL;
2136 static HRESULT WINAPI overlay_SetPalette(IOverlay *iface, DWORD count, PALETTEENTRY *palette)
2138 FIXME("iface %p, count %u, palette %p, stub!\n", iface, count, palette);
2139 return E_NOTIMPL;
2142 static HRESULT WINAPI overlay_GetDefaultColorKey(IOverlay *iface, COLORKEY *key)
2144 FIXME("iface %p, key %p, stub!\n", iface, key);
2145 return E_NOTIMPL;
2148 static HRESULT WINAPI overlay_GetColorKey(IOverlay *iface, COLORKEY *key)
2150 FIXME("iface %p, key %p, stub!\n", iface, key);
2151 return E_NOTIMPL;
2154 static HRESULT WINAPI overlay_SetColorKey(IOverlay *iface, COLORKEY *key)
2156 FIXME("iface %p, key %p, stub!\n", iface, key);
2157 return E_NOTIMPL;
2160 static HRESULT WINAPI overlay_GetWindowHandle(IOverlay *iface, HWND *window)
2162 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2164 TRACE("filter %p, window %p.\n", filter, window);
2166 *window = filter->baseControlWindow.baseWindow.hWnd;
2167 return S_OK;
2170 static HRESULT WINAPI overlay_GetClipList(IOverlay *iface, RECT *source, RECT *dest, RGNDATA **region)
2172 FIXME("iface %p, source %p, dest %p, region %p, stub!\n", iface, source, dest, region);
2173 return E_NOTIMPL;
2176 static HRESULT WINAPI overlay_GetVideoPosition(IOverlay *iface, RECT *source, RECT *dest)
2178 FIXME("iface %p, source %p, dest %p, stub!\n", iface, source, dest);
2179 return E_NOTIMPL;
2182 static HRESULT WINAPI overlay_Advise(IOverlay *iface, IOverlayNotify *sink, DWORD flags)
2184 FIXME("iface %p, sink %p, flags %#x, stub!\n", iface, sink, flags);
2185 return E_NOTIMPL;
2188 static HRESULT WINAPI overlay_Unadvise(IOverlay *iface)
2190 FIXME("iface %p, stub!\n", iface);
2191 return E_NOTIMPL;
2194 static const IOverlayVtbl overlay_vtbl =
2196 overlay_QueryInterface,
2197 overlay_AddRef,
2198 overlay_Release,
2199 overlay_GetPalette,
2200 overlay_SetPalette,
2201 overlay_GetDefaultColorKey,
2202 overlay_GetColorKey,
2203 overlay_SetColorKey,
2204 overlay_GetWindowHandle,
2205 overlay_GetClipList,
2206 overlay_GetVideoPosition,
2207 overlay_Advise,
2208 overlay_Unadvise,
2211 static HRESULT vmr_create(IUnknown *outer, void **out, const CLSID *clsid)
2213 HRESULT hr;
2214 struct quartz_vmr* pVMR;
2216 *out = NULL;
2218 pVMR = CoTaskMemAlloc(sizeof(struct quartz_vmr));
2220 pVMR->hD3d9 = LoadLibraryA("d3d9.dll");
2221 if (!pVMR->hD3d9 )
2223 WARN("Could not load d3d9.dll\n");
2224 CoTaskMemFree(pVMR);
2225 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2228 pVMR->IAMCertifiedOutputProtection_iface.lpVtbl = &IAMCertifiedOutputProtection_Vtbl;
2229 pVMR->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
2231 pVMR->mode = 0;
2232 pVMR->allocator_d3d9_dev = NULL;
2233 pVMR->allocator_mon= NULL;
2234 pVMR->num_surfaces = pVMR->cur_surface = 0;
2235 pVMR->allocator = NULL;
2236 pVMR->presenter = NULL;
2237 pVMR->hWndClippingWindow = NULL;
2238 pVMR->IVMRFilterConfig_iface.lpVtbl = &VMR7_FilterConfig_Vtbl;
2239 pVMR->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
2240 pVMR->IVMRMonitorConfig_iface.lpVtbl = &VMR7_MonitorConfig_Vtbl;
2241 pVMR->IVMRMonitorConfig9_iface.lpVtbl = &VMR9_MonitorConfig_Vtbl;
2242 pVMR->IVMRSurfaceAllocatorNotify_iface.lpVtbl = &VMR7_SurfaceAllocatorNotify_Vtbl;
2243 pVMR->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &VMR9_SurfaceAllocatorNotify_Vtbl;
2244 pVMR->IVMRWindowlessControl_iface.lpVtbl = &VMR7_WindowlessControl_Vtbl;
2245 pVMR->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
2246 pVMR->IOverlay_iface.lpVtbl = &overlay_vtbl;
2248 hr = strmbase_renderer_init(&pVMR->renderer, outer, clsid, L"VMR Input0", &renderer_ops);
2249 if (FAILED(hr))
2250 goto fail;
2252 hr = strmbase_window_init(&pVMR->baseControlWindow, &IVideoWindow_VTable,
2253 &pVMR->renderer.filter, &pVMR->renderer.sink.pin, &renderer_BaseWindowFuncTable);
2254 if (FAILED(hr))
2255 goto fail;
2257 if (FAILED(hr = BaseWindowImpl_PrepareWindow(&pVMR->baseControlWindow.baseWindow)))
2258 goto fail;
2260 hr = strmbase_video_init(&pVMR->baseControlVideo, &pVMR->renderer.filter,
2261 &pVMR->renderer.sink.pin, &renderer_BaseControlVideoFuncTable);
2262 if (FAILED(hr))
2263 goto fail;
2265 pVMR->run_event = CreateEventW(NULL, TRUE, FALSE, NULL);
2267 *out = &pVMR->renderer.filter.IUnknown_inner;
2268 ZeroMemory(&pVMR->source_rect, sizeof(RECT));
2269 ZeroMemory(&pVMR->target_rect, sizeof(RECT));
2270 TRACE("Created at %p\n", pVMR);
2271 return hr;
2273 fail:
2274 BaseWindowImpl_DoneWithWindow(&pVMR->baseControlWindow.baseWindow);
2275 strmbase_renderer_cleanup(&pVMR->renderer);
2276 FreeLibrary(pVMR->hD3d9);
2277 CoTaskMemFree(pVMR);
2278 return hr;
2281 HRESULT VMR7Impl_create(IUnknown *outer_unk, LPVOID *ppv)
2283 return vmr_create(outer_unk, ppv, &CLSID_VideoMixingRenderer);
2286 HRESULT VMR9Impl_create(IUnknown *outer_unk, LPVOID *ppv)
2288 return vmr_create(outer_unk, ppv, &CLSID_VideoMixingRenderer9);
2292 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, void **ppv)
2294 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2295 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
2297 *ppv = NULL;
2299 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IVMRImagePresenter9))
2300 *ppv = &This->IVMRImagePresenter9_iface;
2301 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorEx9))
2302 *ppv = &This->IVMRSurfaceAllocatorEx9_iface;
2304 if (*ppv)
2306 IUnknown_AddRef((IUnknown *)(*ppv));
2307 return S_OK;
2310 FIXME("No interface for %s\n", debugstr_guid(riid));
2312 return E_NOINTERFACE;
2315 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
2317 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2318 ULONG refCount = InterlockedIncrement(&This->refCount);
2320 TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
2322 return refCount;
2325 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
2327 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2328 ULONG refCount = InterlockedDecrement(&This->refCount);
2330 TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
2332 if (!refCount)
2334 DWORD i;
2335 TRACE("Destroying\n");
2336 IDirect3D9_Release(This->d3d9_ptr);
2338 TRACE("Number of surfaces: %u\n", This->num_surfaces);
2339 for (i = 0; i < This->num_surfaces; ++i)
2341 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2342 TRACE("Releasing surface %p\n", surface);
2343 if (surface)
2344 IDirect3DSurface9_Release(surface);
2347 CoTaskMemFree(This->d3d9_surfaces);
2348 This->d3d9_surfaces = NULL;
2349 This->num_surfaces = 0;
2350 if (This->d3d9_vertex)
2352 IDirect3DVertexBuffer9_Release(This->d3d9_vertex);
2353 This->d3d9_vertex = NULL;
2355 CoTaskMemFree(This);
2356 return 0;
2358 return refCount;
2361 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
2363 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2365 TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
2366 return S_OK;
2369 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
2371 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2373 TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
2374 return S_OK;
2377 #define USED_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)
2378 struct VERTEX { float x, y, z, rhw, u, v; };
2380 static HRESULT VMR9_ImagePresenter_PresentTexture(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
2382 IDirect3DTexture9 *texture = NULL;
2383 HRESULT hr;
2385 hr = IDirect3DDevice9_SetFVF(This->d3d9_dev, USED_FVF);
2386 if (FAILED(hr))
2388 FIXME("SetFVF: %08x\n", hr);
2389 return hr;
2392 hr = IDirect3DDevice9_SetStreamSource(This->d3d9_dev, 0, This->d3d9_vertex, 0, sizeof(struct VERTEX));
2393 if (FAILED(hr))
2395 FIXME("SetStreamSource: %08x\n", hr);
2396 return hr;
2399 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **) &texture);
2400 if (FAILED(hr))
2402 FIXME("IDirect3DSurface9_GetContainer failed\n");
2403 return hr;
2405 hr = IDirect3DDevice9_SetTexture(This->d3d9_dev, 0, (IDirect3DBaseTexture9 *)texture);
2406 IDirect3DTexture9_Release(texture);
2407 if (FAILED(hr))
2409 FIXME("SetTexture: %08x\n", hr);
2410 return hr;
2413 hr = IDirect3DDevice9_DrawPrimitive(This->d3d9_dev, D3DPT_TRIANGLESTRIP, 0, 2);
2414 if (FAILED(hr))
2416 FIXME("DrawPrimitive: %08x\n", hr);
2417 return hr;
2420 return S_OK;
2423 static HRESULT VMR9_ImagePresenter_PresentOffscreenSurface(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
2425 HRESULT hr;
2426 IDirect3DSurface9 *target = NULL;
2427 RECT target_rect;
2429 hr = IDirect3DDevice9_GetBackBuffer(This->d3d9_dev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &target);
2430 if (FAILED(hr))
2432 ERR("IDirect3DDevice9_GetBackBuffer -- %08x\n", hr);
2433 return hr;
2436 /* Move rect to origin and flip it */
2437 SetRect(&target_rect, 0, This->pVMR9->target_rect.bottom - This->pVMR9->target_rect.top,
2438 This->pVMR9->target_rect.right - This->pVMR9->target_rect.left, 0);
2440 hr = IDirect3DDevice9_StretchRect(This->d3d9_dev, surface, &This->pVMR9->source_rect, target, &target_rect, D3DTEXF_LINEAR);
2441 if (FAILED(hr))
2442 ERR("IDirect3DDevice9_StretchRect -- %08x\n", hr);
2443 IDirect3DSurface9_Release(target);
2445 return hr;
2448 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface, DWORD_PTR id, VMR9PresentationInfo *info)
2450 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2451 HRESULT hr;
2452 RECT output;
2453 BOOL render = FALSE;
2455 TRACE("(%p/%p/%p)->(...) stub\n", iface, This, This->pVMR9);
2456 GetWindowRect(This->pVMR9->baseControlWindow.baseWindow.hWnd, &output);
2457 TRACE("Output rectangle: %s\n", wine_dbgstr_rect(&output));
2459 /* This might happen if we don't have active focus (eg on a different virtual desktop) */
2460 if (!This->d3d9_dev)
2461 return S_OK;
2463 /* Display image here */
2464 hr = IDirect3DDevice9_Clear(This->d3d9_dev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
2465 if (FAILED(hr))
2466 FIXME("hr: %08x\n", hr);
2467 hr = IDirect3DDevice9_BeginScene(This->d3d9_dev);
2468 if (SUCCEEDED(hr))
2470 if (This->d3d9_vertex)
2471 hr = VMR9_ImagePresenter_PresentTexture(This, info->lpSurf);
2472 else
2473 hr = VMR9_ImagePresenter_PresentOffscreenSurface(This, info->lpSurf);
2474 render = SUCCEEDED(hr);
2476 else
2477 FIXME("BeginScene: %08x\n", hr);
2478 hr = IDirect3DDevice9_EndScene(This->d3d9_dev);
2479 if (render && SUCCEEDED(hr))
2481 hr = IDirect3DDevice9_Present(This->d3d9_dev, NULL, NULL, This->pVMR9->baseControlWindow.baseWindow.hWnd, NULL);
2482 if (FAILED(hr))
2483 FIXME("Presenting image: %08x\n", hr);
2486 return S_OK;
2489 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
2491 VMR9_ImagePresenter_QueryInterface,
2492 VMR9_ImagePresenter_AddRef,
2493 VMR9_ImagePresenter_Release,
2494 VMR9_ImagePresenter_StartPresenting,
2495 VMR9_ImagePresenter_StopPresenting,
2496 VMR9_ImagePresenter_PresentImage
2499 static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocatorEx9 *iface, REFIID riid, LPVOID * ppv)
2501 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2503 return VMR9_ImagePresenter_QueryInterface(&This->IVMRImagePresenter9_iface, riid, ppv);
2506 static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocatorEx9 *iface)
2508 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2510 return VMR9_ImagePresenter_AddRef(&This->IVMRImagePresenter9_iface);
2513 static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocatorEx9 *iface)
2515 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2517 return VMR9_ImagePresenter_Release(&This->IVMRImagePresenter9_iface);
2520 static HRESULT VMR9_SurfaceAllocator_SetAllocationSettings(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *allocinfo)
2522 D3DCAPS9 caps;
2523 UINT width, height;
2524 HRESULT hr;
2526 if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface))
2527 /* Only needed for texture surfaces */
2528 return S_OK;
2530 hr = IDirect3DDevice9_GetDeviceCaps(This->d3d9_dev, &caps);
2531 if (FAILED(hr))
2532 return hr;
2534 if (!(caps.TextureCaps & D3DPTEXTURECAPS_POW2) || (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY))
2536 width = allocinfo->dwWidth;
2537 height = allocinfo->dwHeight;
2539 else
2541 width = height = 1;
2542 while (width < allocinfo->dwWidth)
2543 width *= 2;
2545 while (height < allocinfo->dwHeight)
2546 height *= 2;
2547 FIXME("NPOW2 support missing, not using proper surfaces!\n");
2550 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
2552 if (height > width)
2553 width = height;
2554 else
2555 height = width;
2556 FIXME("Square texture support required..\n");
2559 hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF, allocinfo->Pool, &This->d3d9_vertex, NULL);
2560 if (FAILED(hr))
2562 ERR("Couldn't create vertex buffer: %08x\n", hr);
2563 return hr;
2566 This->reset = TRUE;
2567 allocinfo->dwHeight = height;
2568 allocinfo->dwWidth = width;
2570 return hr;
2573 static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
2575 UINT d3d9_adapter;
2576 HMONITOR mon;
2578 mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
2579 if (!mon)
2580 d3d9_adapter = 0;
2581 else
2583 for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
2585 if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
2586 break;
2588 if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
2589 d3d9_adapter = 0;
2591 if (mon_out)
2592 *mon_out = mon;
2593 return d3d9_adapter;
2596 static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *info, DWORD *numbuffers)
2598 D3DPRESENT_PARAMETERS d3dpp;
2599 DWORD d3d9_adapter;
2600 HRESULT hr;
2602 TRACE("(%p)->()\n", This);
2604 /* Obtain a monitor and d3d9 device */
2605 d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon);
2607 /* Now try to create the d3d9 device */
2608 ZeroMemory(&d3dpp, sizeof(d3dpp));
2609 d3dpp.Windowed = TRUE;
2610 d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd;
2611 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2612 d3dpp.BackBufferHeight = This->pVMR9->target_rect.bottom - This->pVMR9->target_rect.top;
2613 d3dpp.BackBufferWidth = This->pVMR9->target_rect.right - This->pVMR9->target_rect.left;
2615 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
2616 if (FAILED(hr))
2618 ERR("Could not create device: %08x\n", hr);
2619 return FALSE;
2621 IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2623 This->d3d9_surfaces = CoTaskMemAlloc(*numbuffers * sizeof(IDirect3DSurface9 *));
2624 ZeroMemory(This->d3d9_surfaces, *numbuffers * sizeof(IDirect3DSurface9 *));
2626 hr = VMR9_SurfaceAllocator_SetAllocationSettings(This, info);
2627 if (FAILED(hr))
2628 ERR("Setting allocation settings failed: %08x\n", hr);
2630 if (SUCCEEDED(hr))
2632 hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, info, numbuffers, This->d3d9_surfaces);
2633 if (FAILED(hr))
2634 ERR("Allocating surfaces failed: %08x\n", hr);
2637 if (FAILED(hr))
2639 IVMRSurfaceAllocatorEx9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
2640 return FALSE;
2643 This->num_surfaces = *numbuffers;
2645 return TRUE;
2648 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, VMR9AllocationInfo *allocinfo, DWORD *numbuffers)
2650 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2652 if (This->pVMR9->mode != VMR9Mode_Windowed && !This->pVMR9->hWndClippingWindow)
2654 ERR("No window set\n");
2655 return VFW_E_WRONG_STATE;
2658 This->info = *allocinfo;
2660 if (!CreateRenderingWindow(This, allocinfo, numbuffers))
2662 ERR("Failed to create rendering window, expect no output!\n");
2663 return VFW_E_WRONG_STATE;
2666 return S_OK;
2669 static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id)
2671 TRACE("iface %p, id %#lx.\n", iface, id);
2673 return S_OK;
2676 /* Recreate all surfaces (If allocated as D3DPOOL_DEFAULT) and survive! */
2677 static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(VMR9DefaultAllocatorPresenterImpl *This)
2679 struct VERTEX t_vert[4];
2680 UINT width, height;
2681 unsigned int i;
2682 void *bits = NULL;
2683 D3DPRESENT_PARAMETERS d3dpp;
2684 HRESULT hr;
2686 if (!This->d3d9_surfaces || !This->reset)
2687 return S_OK;
2689 This->reset = FALSE;
2690 TRACE("RESETTING\n");
2691 if (This->d3d9_vertex)
2693 IDirect3DVertexBuffer9_Release(This->d3d9_vertex);
2694 This->d3d9_vertex = NULL;
2697 for (i = 0; i < This->num_surfaces; ++i)
2699 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2700 TRACE("Releasing surface %p\n", surface);
2701 if (surface)
2702 IDirect3DSurface9_Release(surface);
2704 ZeroMemory(This->d3d9_surfaces, sizeof(IDirect3DSurface9 *) * This->num_surfaces);
2706 /* Now try to create the d3d9 device */
2707 ZeroMemory(&d3dpp, sizeof(d3dpp));
2708 d3dpp.Windowed = TRUE;
2709 d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd;
2710 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2712 if (This->d3d9_dev)
2713 IDirect3DDevice9_Release(This->d3d9_dev);
2714 This->d3d9_dev = NULL;
2715 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon), D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
2716 if (FAILED(hr))
2718 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon), D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
2719 if (FAILED(hr))
2721 ERR("--> Creating device: %08x\n", hr);
2722 return S_OK;
2725 IVMRSurfaceAllocatorNotify9_ChangeD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2727 IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, &This->info, &This->num_surfaces, This->d3d9_surfaces);
2729 This->reset = FALSE;
2731 if (!(This->info.dwFlags & VMR9AllocFlag_TextureSurface))
2732 return S_OK;
2734 hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF,
2735 This->info.Pool, &This->d3d9_vertex, NULL);
2737 width = This->info.dwWidth;
2738 height = This->info.dwHeight;
2740 for (i = 0; i < ARRAY_SIZE(t_vert); ++i)
2742 if (i % 2)
2744 t_vert[i].x = (float)This->pVMR9->target_rect.right - (float)This->pVMR9->target_rect.left - 0.5f;
2745 t_vert[i].u = (float)This->pVMR9->source_rect.right / (float)width;
2747 else
2749 t_vert[i].x = -0.5f;
2750 t_vert[i].u = (float)This->pVMR9->source_rect.left / (float)width;
2753 if (i % 4 < 2)
2755 t_vert[i].y = -0.5f;
2756 t_vert[i].v = (float)This->pVMR9->source_rect.bottom / (float)height;
2758 else
2760 t_vert[i].y = (float)This->pVMR9->target_rect.bottom - (float)This->pVMR9->target_rect.top - 0.5f;
2761 t_vert[i].v = (float)This->pVMR9->source_rect.top / (float)height;
2763 t_vert[i].z = 0.0f;
2764 t_vert[i].rhw = 1.0f;
2767 FIXME("Vertex rectangle:\n");
2768 FIXME("X, Y: %f, %f\n", t_vert[0].x, t_vert[0].y);
2769 FIXME("X, Y: %f, %f\n", t_vert[3].x, t_vert[3].y);
2770 FIXME("TOP, LEFT: %f, %f\n", t_vert[0].u, t_vert[0].v);
2771 FIXME("DOWN, BOTTOM: %f, %f\n", t_vert[3].u, t_vert[3].v);
2773 IDirect3DVertexBuffer9_Lock(This->d3d9_vertex, 0, sizeof(t_vert), &bits, 0);
2774 memcpy(bits, t_vert, sizeof(t_vert));
2775 IDirect3DVertexBuffer9_Unlock(This->d3d9_vertex);
2777 return S_OK;
2780 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
2782 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2784 /* Update everything first, this is needed because the surface might be destroyed in the reset */
2785 if (!This->d3d9_dev)
2787 TRACE("Device has left me!\n");
2788 return E_FAIL;
2791 VMR9_SurfaceAllocator_UpdateDeviceReset(This);
2793 if (surfaceindex >= This->num_surfaces)
2795 ERR("surfaceindex is greater than num_surfaces\n");
2796 return E_FAIL;
2798 *surface = This->d3d9_surfaces[surfaceindex];
2799 IDirect3DSurface9_AddRef(*surface);
2801 return S_OK;
2804 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocatorEx9 *iface, IVMRSurfaceAllocatorNotify9 *allocnotify)
2806 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2808 TRACE("(%p/%p)->(...)\n", iface, This);
2810 /* No AddRef taken here or the base VMR9 filter would never be destroyed */
2811 This->SurfaceAllocatorNotify = allocnotify;
2812 return S_OK;
2815 static const IVMRSurfaceAllocatorEx9Vtbl VMR9_SurfaceAllocator =
2817 VMR9_SurfaceAllocator_QueryInterface,
2818 VMR9_SurfaceAllocator_AddRef,
2819 VMR9_SurfaceAllocator_Release,
2820 VMR9_SurfaceAllocator_InitializeDevice,
2821 VMR9_SurfaceAllocator_TerminateDevice,
2822 VMR9_SurfaceAllocator_GetSurface,
2823 VMR9_SurfaceAllocator_AdviseNotify,
2824 NULL /* This isn't the SurfaceAllocatorEx type yet, working on it */
2827 static IDirect3D9 *init_d3d9(HMODULE d3d9_handle)
2829 IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion);
2831 d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
2832 if (!d3d9_create) return NULL;
2834 return d3d9_create(D3D_SDK_VERSION);
2837 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(struct quartz_vmr *parent, LPVOID * ppv)
2839 HRESULT hr = S_OK;
2840 int i;
2841 VMR9DefaultAllocatorPresenterImpl* This;
2843 This = CoTaskMemAlloc(sizeof(VMR9DefaultAllocatorPresenterImpl));
2844 if (!This)
2845 return E_OUTOFMEMORY;
2847 This->d3d9_ptr = init_d3d9(parent->hD3d9);
2848 if (!This->d3d9_ptr)
2850 WARN("Could not initialize d3d9.dll\n");
2851 CoTaskMemFree(This);
2852 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2855 i = 0;
2858 D3DDISPLAYMODE mode;
2860 hr = IDirect3D9_EnumAdapterModes(This->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode);
2861 if (hr == D3DERR_INVALIDCALL) break; /* out of adapters */
2862 } while (FAILED(hr));
2863 if (FAILED(hr))
2864 ERR("HR: %08x\n", hr);
2865 if (hr == D3DERR_NOTAVAILABLE)
2867 ERR("Format not supported\n");
2868 IDirect3D9_Release(This->d3d9_ptr);
2869 CoTaskMemFree(This);
2870 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2873 This->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
2874 This->IVMRSurfaceAllocatorEx9_iface.lpVtbl = &VMR9_SurfaceAllocator;
2876 This->refCount = 1;
2877 This->pVMR9 = parent;
2878 This->d3d9_surfaces = NULL;
2879 This->d3d9_dev = NULL;
2880 This->hMon = 0;
2881 This->d3d9_vertex = NULL;
2882 This->num_surfaces = 0;
2883 This->SurfaceAllocatorNotify = NULL;
2884 This->reset = FALSE;
2886 *ppv = &This->IVMRImagePresenter9_iface;
2887 return S_OK;