libport: Remove support for PPC32.
[wine.git] / dlls / quartz / vmr9.c
blob6b653e56092f45a7023413b8b9340edc98e667a2
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 static inline const char *debugstr_normalized_rect(const VMR9NormalizedRect *rect)
44 if (!rect) return "(null)";
45 return wine_dbg_sprintf("(%.8e,%.8e)-(%.8e,%.8e)", rect->left, rect->top, rect->right, rect->bottom);
48 static const BITMAPINFOHEADER *get_bitmap_header(const AM_MEDIA_TYPE *mt)
50 if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
51 return &((VIDEOINFOHEADER *)mt->pbFormat)->bmiHeader;
52 else
53 return &((VIDEOINFOHEADER2 *)mt->pbFormat)->bmiHeader;
56 struct quartz_vmr
58 struct strmbase_renderer renderer;
59 struct video_window window;
61 IAMCertifiedOutputProtection IAMCertifiedOutputProtection_iface;
62 IAMFilterMiscFlags IAMFilterMiscFlags_iface;
63 IVMRFilterConfig IVMRFilterConfig_iface;
64 IVMRFilterConfig9 IVMRFilterConfig9_iface;
65 IVMRMixerBitmap9 IVMRMixerBitmap9_iface;
66 IVMRMixerControl9 IVMRMixerControl9_iface;
67 IVMRMonitorConfig IVMRMonitorConfig_iface;
68 IVMRMonitorConfig9 IVMRMonitorConfig9_iface;
69 IVMRSurfaceAllocatorNotify IVMRSurfaceAllocatorNotify_iface;
70 IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface;
71 IVMRWindowlessControl IVMRWindowlessControl_iface;
72 IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
74 /* Devil May Cry 3 releases the last IBaseFilter reference while still
75 * holding an IVMRSurfaceAllocatorNotify9 reference, and depends on
76 * IVMRSurfaceAllocator9::TerminateDevice() being called as a result.
77 * Native uses a separate reference count for IVMRSurfaceAllocatorNotify9. */
78 LONG IVMRSurfaceAllocatorNotify9_refcount;
80 IOverlay IOverlay_iface;
82 IVMRSurfaceAllocator9 *allocator;
83 IVMRImagePresenter9 *presenter;
85 DWORD stream_count;
86 DWORD mixing_prefs;
89 * The Video Mixing Renderer supports 3 modes, renderless, windowless and windowed
90 * What I do is implement windowless as a special case of renderless, and then
91 * windowed also as a special case of windowless. This is probably the easiest way.
93 VMR9Mode mode;
94 BITMAPINFOHEADER bmiheader;
96 HMODULE hD3d9;
98 /* Presentation related members */
99 IDirect3DDevice9 *allocator_d3d9_dev;
100 IDirect3DSurface9 **surfaces;
101 DWORD num_surfaces;
102 DWORD cur_surface;
103 DWORD_PTR cookie;
105 HWND clipping_window;
107 LONG VideoWidth;
108 LONG VideoHeight;
109 VMR9AspectRatioMode aspect_mode;
111 HANDLE run_event;
114 static inline BOOL is_vmr9(const struct quartz_vmr *filter)
116 return IsEqualGUID(&filter->renderer.filter.clsid, &CLSID_VideoMixingRenderer9);
119 static inline struct quartz_vmr *impl_from_video_window(struct video_window *iface)
121 return CONTAINING_RECORD(iface, struct quartz_vmr, window);
124 static inline struct quartz_vmr *impl_from_IAMCertifiedOutputProtection(IAMCertifiedOutputProtection *iface)
126 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMCertifiedOutputProtection_iface);
129 static inline struct quartz_vmr *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
131 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMFilterMiscFlags_iface);
134 static inline struct quartz_vmr *impl_from_IVMRFilterConfig(IVMRFilterConfig *iface)
136 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig_iface);
139 static inline struct quartz_vmr *impl_from_IVMRFilterConfig9(IVMRFilterConfig9 *iface)
141 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig9_iface);
144 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig(IVMRMonitorConfig *iface)
146 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig_iface);
149 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig9(IVMRMonitorConfig9 *iface)
151 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig9_iface);
154 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify(IVMRSurfaceAllocatorNotify *iface)
156 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify_iface);
159 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify9(IVMRSurfaceAllocatorNotify9 *iface)
161 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify9_iface);
164 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl(IVMRWindowlessControl *iface)
166 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl_iface);
169 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl9(IVMRWindowlessControl9 *iface)
171 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl9_iface);
174 struct default_presenter
176 IVMRImagePresenter9 IVMRImagePresenter9_iface;
177 IVMRSurfaceAllocator9 IVMRSurfaceAllocator9_iface;
179 LONG refCount;
181 IDirect3DDevice9 *d3d9_dev;
182 IDirect3D9 *d3d9_ptr;
183 IDirect3DSurface9 **d3d9_surfaces;
184 HMONITOR hMon;
185 DWORD num_surfaces;
187 VMR9AllocationInfo info;
189 struct quartz_vmr* pVMR9;
190 IVMRSurfaceAllocatorNotify9 *SurfaceAllocatorNotify;
193 static inline struct default_presenter *impl_from_IVMRImagePresenter9(IVMRImagePresenter9 *iface)
195 return CONTAINING_RECORD(iface, struct default_presenter, IVMRImagePresenter9_iface);
198 static inline struct default_presenter *impl_from_IVMRSurfaceAllocator9(IVMRSurfaceAllocator9 *iface)
200 return CONTAINING_RECORD(iface, struct default_presenter, IVMRSurfaceAllocator9_iface);
203 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(struct quartz_vmr *parent, LPVOID * ppv);
205 static inline struct quartz_vmr *impl_from_IBaseFilter(IBaseFilter *iface)
207 return CONTAINING_RECORD(iface, struct quartz_vmr, renderer.filter.IBaseFilter_iface);
210 static DWORD VMR9_SendSampleData(struct quartz_vmr *This, VMR9PresentationInfo *info, LPBYTE data,
211 DWORD size)
213 const BITMAPINFOHEADER *bmiHeader = get_bitmap_header(&This->renderer.sink.pin.mt);
214 HRESULT hr = S_OK;
215 int width;
216 int height;
217 D3DLOCKED_RECT lock;
219 TRACE("%p %p %d\n", This, data, size);
221 width = bmiHeader->biWidth;
222 height = bmiHeader->biHeight;
224 hr = IDirect3DSurface9_LockRect(info->lpSurf, &lock, NULL, D3DLOCK_DISCARD);
225 if (FAILED(hr))
227 ERR("IDirect3DSurface9_LockRect failed (%x)\n",hr);
228 return hr;
231 if (height > 0) {
232 /* Bottom up image needs inverting */
233 lock.pBits = (char *)lock.pBits + (height * lock.Pitch);
234 while (height--)
236 lock.pBits = (char *)lock.pBits - lock.Pitch;
237 memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8);
238 data = data + width * bmiHeader->biBitCount / 8;
241 else if (lock.Pitch != width * bmiHeader->biBitCount / 8)
243 WARN("Slow path! %u/%u\n", lock.Pitch, width * bmiHeader->biBitCount/8);
245 while (height--)
247 memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8);
248 data = data + width * bmiHeader->biBitCount / 8;
249 lock.pBits = (char *)lock.pBits + lock.Pitch;
252 else memcpy(lock.pBits, data, size);
254 IDirect3DSurface9_UnlockRect(info->lpSurf);
256 hr = IVMRImagePresenter9_PresentImage(This->presenter, This->cookie, info);
257 return hr;
260 static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMediaSample *pSample)
262 struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
263 const HANDLE events[2] = {This->run_event, This->renderer.flush_event};
264 VMR9PresentationInfo info = {};
265 LPBYTE pbSrcStream = NULL;
266 long cbSrcStream = 0;
267 REFERENCE_TIME tStart, tStop;
268 HRESULT hr;
270 TRACE("%p %p\n", iface, pSample);
272 /* It is possible that there is no device at this point */
274 if (!This->allocator || !This->presenter)
276 ERR("NO PRESENTER!!\n");
277 return S_FALSE;
280 hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
281 if (FAILED(hr))
282 info.dwFlags = VMR9Sample_SrcDstRectsValid;
283 else
284 info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
286 if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
287 info.dwFlags |= VMR9Sample_Discontinuity;
289 if (IMediaSample_IsPreroll(pSample) == S_OK)
290 info.dwFlags |= VMR9Sample_Preroll;
292 if (IMediaSample_IsSyncPoint(pSample) == S_OK)
293 info.dwFlags |= VMR9Sample_SyncPoint;
295 /* If we render ourselves, and this is a preroll sample, discard it */
296 if (info.dwFlags & VMR9Sample_Preroll)
298 return S_OK;
301 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
302 if (FAILED(hr))
304 ERR("Cannot get pointer to sample data (%x)\n", hr);
305 return hr;
308 cbSrcStream = IMediaSample_GetActualDataLength(pSample);
310 info.rtStart = tStart;
311 info.rtEnd = tStop;
312 info.szAspectRatio.cx = This->bmiheader.biWidth;
313 info.szAspectRatio.cy = This->bmiheader.biHeight;
314 info.lpSurf = This->surfaces[(++This->cur_surface) % This->num_surfaces];
316 VMR9_SendSampleData(This, &info, pbSrcStream, cbSrcStream);
318 if (This->renderer.filter.state == State_Paused)
320 LeaveCriticalSection(&This->renderer.csRenderLock);
321 WaitForMultipleObjects(2, events, FALSE, INFINITE);
322 EnterCriticalSection(&This->renderer.csRenderLock);
325 return hr;
328 static HRESULT WINAPI VMR9_CheckMediaType(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
330 if (!IsEqualIID(&mt->majortype, &MEDIATYPE_Video) || !mt->pbFormat)
331 return S_FALSE;
333 if (!IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo)
334 && !IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo2))
335 return S_FALSE;
337 if (get_bitmap_header(mt)->biCompression != BI_RGB)
338 return S_FALSE;
339 return S_OK;
342 static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *info, DWORD count)
344 HRESULT hr;
345 DWORD i;
347 if (FAILED(hr = IVMRSurfaceAllocator9_InitializeDevice(filter->allocator,
348 filter->cookie, info, &count)))
350 WARN("Failed to initialize device (flags %#x), hr %#x.\n", info->dwFlags, hr);
351 return hr;
354 for (i = 0; i < count; ++i)
356 if (FAILED(hr = IVMRSurfaceAllocator9_GetSurface(filter->allocator,
357 filter->cookie, i, 0, &filter->surfaces[i])))
359 ERR("Failed to get surface %u, hr %#x.\n", i, hr);
360 while (i--)
361 IDirect3DSurface9_Release(filter->surfaces[i]);
362 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
363 return hr;
367 return hr;
370 static HRESULT allocate_surfaces(struct quartz_vmr *filter, const AM_MEDIA_TYPE *mt)
372 VMR9AllocationInfo info = {};
373 HRESULT hr = E_FAIL;
374 DWORD count = 1;
375 unsigned int i;
377 static const struct
379 const GUID *subtype;
380 D3DFORMAT format;
381 DWORD flags;
383 formats[] =
385 {&MEDIASUBTYPE_ARGB1555, D3DFMT_A1R5G5B5, VMR9AllocFlag_TextureSurface},
386 {&MEDIASUBTYPE_ARGB32, D3DFMT_A8R8G8B8, VMR9AllocFlag_TextureSurface},
387 {&MEDIASUBTYPE_ARGB4444, D3DFMT_A4R4G4B4, VMR9AllocFlag_TextureSurface},
389 {&MEDIASUBTYPE_RGB24, D3DFMT_R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
390 {&MEDIASUBTYPE_RGB32, D3DFMT_X8R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
391 {&MEDIASUBTYPE_RGB555, D3DFMT_X1R5G5B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
392 {&MEDIASUBTYPE_RGB565, D3DFMT_R5G6B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
394 {&MEDIASUBTYPE_NV12, MAKEFOURCC('N','V','1','2'), VMR9AllocFlag_OffscreenSurface},
395 {&MEDIASUBTYPE_UYVY, D3DFMT_UYVY, VMR9AllocFlag_OffscreenSurface},
396 {&MEDIASUBTYPE_YUY2, D3DFMT_YUY2, VMR9AllocFlag_OffscreenSurface},
397 {&MEDIASUBTYPE_YV12, MAKEFOURCC('Y','V','1','2'), VMR9AllocFlag_OffscreenSurface},
400 TRACE("Initializing in mode %u, our window %p, clipping window %p.\n",
401 filter->mode, filter->window.hwnd, filter->clipping_window);
403 if (filter->mode == VMR9Mode_Windowless && !filter->clipping_window)
404 return S_OK;
406 info.Pool = D3DPOOL_DEFAULT;
407 info.MinBuffers = count;
408 info.dwWidth = info.szAspectRatio.cx = info.szNativeSize.cx = filter->bmiheader.biWidth;
409 info.dwHeight = info.szAspectRatio.cy = info.szNativeSize.cy = filter->bmiheader.biHeight;
411 if (!(filter->surfaces = calloc(count, sizeof(IDirect3DSurface9 *))))
412 return E_OUTOFMEMORY;
413 filter->num_surfaces = count;
414 filter->cur_surface = 0;
416 if (!is_vmr9(filter))
418 switch (filter->bmiheader.biBitCount)
420 case 8: info.Format = D3DFMT_R3G3B2; break;
421 case 15: info.Format = D3DFMT_X1R5G5B5; break;
422 case 16: info.Format = D3DFMT_R5G6B5; break;
423 case 24: info.Format = D3DFMT_R8G8B8; break;
424 case 32: info.Format = D3DFMT_X8R8G8B8; break;
425 default:
426 FIXME("Unhandled bit depth %u.\n", filter->bmiheader.biBitCount);
427 return E_INVALIDARG;
430 info.dwFlags = VMR9AllocFlag_TextureSurface;
431 return initialize_device(filter, &info, count);
434 for (i = 0; i < ARRAY_SIZE(formats); ++i)
436 if (IsEqualGUID(&mt->subtype, formats[i].subtype))
438 info.Format = formats[i].format;
440 if (formats[i].flags & VMR9AllocFlag_TextureSurface)
442 info.dwFlags = VMR9AllocFlag_TextureSurface;
443 if (SUCCEEDED(hr = initialize_device(filter, &info, count)))
444 return hr;
447 if (formats[i].flags & VMR9AllocFlag_OffscreenSurface)
449 info.dwFlags = VMR9AllocFlag_OffscreenSurface;
450 if (SUCCEEDED(hr = initialize_device(filter, &info, count)))
451 return hr;
456 return hr;
459 static void vmr_start_stream(struct strmbase_renderer *iface)
461 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
463 IVMRImagePresenter9_StartPresenting(filter->presenter, filter->cookie);
464 if (filter->window.hwnd)
465 ShowWindow(filter->window.hwnd, SW_SHOW);
466 SetEvent(filter->run_event);
469 static void vmr_stop_stream(struct strmbase_renderer *iface)
471 struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
473 TRACE("(%p)\n", This);
475 if (This->renderer.filter.state == State_Running)
476 IVMRImagePresenter9_StopPresenting(This->presenter, This->cookie);
477 ResetEvent(This->run_event);
480 static HRESULT WINAPI VMR9_ShouldDrawSampleNow(struct strmbase_renderer *iface,
481 IMediaSample *pSample, REFERENCE_TIME *start, REFERENCE_TIME *end)
483 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
484 if (IMediaSample_IsPreroll(pSample) == S_OK)
485 return E_FAIL;
486 return S_FALSE;
489 static HRESULT vmr_connect(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
491 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
492 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(mt);
493 HWND window = filter->window.hwnd;
494 HRESULT hr;
495 RECT rect;
497 filter->bmiheader = *bitmap_header;
498 filter->VideoWidth = bitmap_header->biWidth;
499 filter->VideoHeight = bitmap_header->biHeight;
500 SetRect(&rect, 0, 0, filter->VideoWidth, filter->VideoHeight);
501 filter->window.src = filter->window.dst = rect;
503 AdjustWindowRectEx(&rect, GetWindowLongW(window, GWL_STYLE), FALSE,
504 GetWindowLongW(window, GWL_EXSTYLE));
505 SetWindowPos(window, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
506 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
508 if (filter->mode
509 || SUCCEEDED(hr = IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, VMR9Mode_Windowed)))
510 hr = allocate_surfaces(filter, mt);
512 return hr;
515 static HRESULT WINAPI VMR9_BreakConnect(struct strmbase_renderer *This)
517 struct quartz_vmr *pVMR9 = impl_from_IBaseFilter(&This->filter.IBaseFilter_iface);
518 HRESULT hr = S_OK;
519 DWORD i;
521 if (!pVMR9->mode)
522 return S_FALSE;
523 if (This->sink.pin.peer && pVMR9->allocator && pVMR9->presenter)
525 if (pVMR9->renderer.filter.state != State_Stopped)
527 ERR("Disconnecting while not stopped! UNTESTED!!\n");
529 if (pVMR9->renderer.filter.state == State_Running)
530 hr = IVMRImagePresenter9_StopPresenting(pVMR9->presenter, pVMR9->cookie);
532 for (i = 0; i < pVMR9->num_surfaces; ++i)
533 IDirect3DSurface9_Release(pVMR9->surfaces[i]);
534 free(pVMR9->surfaces);
535 IVMRSurfaceAllocator9_TerminateDevice(pVMR9->allocator, pVMR9->cookie);
536 pVMR9->num_surfaces = 0;
538 return hr;
541 static void vmr_free(struct quartz_vmr *filter)
543 free(filter);
544 InterlockedDecrement(&object_locks);
547 static void vmr_destroy(struct strmbase_renderer *iface)
549 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
551 video_window_cleanup(&filter->window);
553 /* Devil May Cry 3 releases the IVMRSurfaceAllocatorNotify9 interface from
554 * TerminateDevice(). Artificially increase the reference count so that we
555 * don't free the filter yet. */
556 InterlockedIncrement(&filter->renderer.filter.refcount);
558 if (filter->allocator)
560 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
561 IVMRSurfaceAllocator9_Release(filter->allocator);
563 if (filter->presenter)
564 IVMRImagePresenter9_Release(filter->presenter);
566 filter->num_surfaces = 0;
567 if (filter->allocator_d3d9_dev)
569 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
570 filter->allocator_d3d9_dev = NULL;
573 CloseHandle(filter->run_event);
574 FreeLibrary(filter->hD3d9);
575 strmbase_renderer_cleanup(&filter->renderer);
576 if (!filter->IVMRSurfaceAllocatorNotify9_refcount)
577 vmr_free(filter);
580 static HRESULT vmr_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
582 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
584 if (IsEqualGUID(iid, &IID_IVideoWindow))
585 *out = &filter->window.IVideoWindow_iface;
586 else if (IsEqualGUID(iid, &IID_IBasicVideo))
587 *out = &filter->window.IBasicVideo_iface;
588 else if (IsEqualGUID(iid, &IID_IAMCertifiedOutputProtection))
589 *out = &filter->IAMCertifiedOutputProtection_iface;
590 else if (IsEqualGUID(iid, &IID_IAMFilterMiscFlags))
591 *out = &filter->IAMFilterMiscFlags_iface;
592 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig))
593 *out = &filter->IVMRFilterConfig_iface;
594 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig9))
595 *out = &filter->IVMRFilterConfig9_iface;
596 else if (IsEqualGUID(iid, &IID_IVMRMixerBitmap9) && is_vmr9(filter))
597 *out = &filter->IVMRMixerBitmap9_iface;
598 else if (IsEqualGUID(iid, &IID_IVMRMixerControl9) && is_vmr9(filter) && filter->stream_count)
599 *out = &filter->IVMRMixerControl9_iface;
600 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig))
601 *out = &filter->IVMRMonitorConfig_iface;
602 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig9))
603 *out = &filter->IVMRMonitorConfig9_iface;
604 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify)
605 && filter->mode == (VMR9Mode)VMRMode_Renderless && !is_vmr9(filter))
606 *out = &filter->IVMRSurfaceAllocatorNotify_iface;
607 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify9)
608 && filter->mode == VMR9Mode_Renderless && is_vmr9(filter))
609 *out = &filter->IVMRSurfaceAllocatorNotify9_iface;
610 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl)
611 && filter->mode == (VMR9Mode)VMRMode_Windowless && !is_vmr9(filter))
612 *out = &filter->IVMRWindowlessControl_iface;
613 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl9)
614 && filter->mode == VMR9Mode_Windowless && is_vmr9(filter))
615 *out = &filter->IVMRWindowlessControl9_iface;
616 else
617 return E_NOINTERFACE;
619 IUnknown_AddRef((IUnknown *)*out);
620 return S_OK;
623 static HRESULT vmr_pin_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
625 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
627 if (IsEqualGUID(iid, &IID_IOverlay))
628 *out = &filter->IOverlay_iface;
629 else
630 return E_NOINTERFACE;
632 IUnknown_AddRef((IUnknown *)*out);
633 return S_OK;
636 static const struct strmbase_renderer_ops renderer_ops =
638 .pfnCheckMediaType = VMR9_CheckMediaType,
639 .pfnDoRenderSample = VMR9_DoRenderSample,
640 .renderer_start_stream = vmr_start_stream,
641 .renderer_stop_stream = vmr_stop_stream,
642 .pfnShouldDrawSampleNow = VMR9_ShouldDrawSampleNow,
643 .renderer_connect = vmr_connect,
644 .pfnBreakConnect = VMR9_BreakConnect,
645 .renderer_destroy = vmr_destroy,
646 .renderer_query_interface = vmr_query_interface,
647 .renderer_pin_query_interface = vmr_pin_query_interface,
650 static RECT vmr_get_default_rect(struct video_window *This)
652 struct quartz_vmr *pVMR9 = impl_from_video_window(This);
653 static RECT defRect;
655 SetRect(&defRect, 0, 0, pVMR9->VideoWidth, pVMR9->VideoHeight);
657 return defRect;
660 static HRESULT vmr_get_current_image(struct video_window *iface, LONG *size, LONG *image)
662 struct quartz_vmr *filter = impl_from_video_window(iface);
663 IDirect3DSurface9 *rt = NULL, *surface = NULL;
664 D3DLOCKED_RECT locked_rect;
665 IDirect3DDevice9 *device;
666 unsigned int row_size;
667 BITMAPINFOHEADER bih;
668 LONG i, size_left;
669 char *dst;
670 HRESULT hr;
672 EnterCriticalSection(&filter->renderer.csRenderLock);
673 device = filter->allocator_d3d9_dev;
675 bih = *get_bitmap_header(&filter->renderer.sink.pin.mt);
676 bih.biSizeImage = bih.biWidth * bih.biHeight * bih.biBitCount / 8;
678 if (!image)
680 *size = sizeof(BITMAPINFOHEADER) + bih.biSizeImage;
681 LeaveCriticalSection(&filter->renderer.csRenderLock);
682 return S_OK;
685 if (FAILED(hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt)))
686 goto out;
688 if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, bih.biWidth,
689 bih.biHeight, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL)))
690 goto out;
692 if (FAILED(hr = IDirect3DDevice9_GetRenderTargetData(device, rt, surface)))
693 goto out;
695 if (FAILED(hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_READONLY)))
696 goto out;
698 size_left = *size;
699 memcpy(image, &bih, min(size_left, sizeof(BITMAPINFOHEADER)));
700 size_left -= sizeof(BITMAPINFOHEADER);
702 dst = (char *)image + sizeof(BITMAPINFOHEADER);
703 row_size = bih.biWidth * bih.biBitCount / 8;
705 for (i = 0; i < bih.biHeight && size_left > 0; ++i)
707 memcpy(dst, (char *)locked_rect.pBits + (i * locked_rect.Pitch), min(row_size, size_left));
708 dst += row_size;
709 size_left -= row_size;
712 IDirect3DSurface9_UnlockRect(surface);
714 out:
715 if (surface) IDirect3DSurface9_Release(surface);
716 if (rt) IDirect3DSurface9_Release(rt);
717 LeaveCriticalSection(&filter->renderer.csRenderLock);
718 return hr;
721 static const struct video_window_ops window_ops =
723 .get_default_rect = vmr_get_default_rect,
724 .get_current_image = vmr_get_current_image,
727 static const IVideoWindowVtbl IVideoWindow_VTable =
729 BaseControlWindowImpl_QueryInterface,
730 BaseControlWindowImpl_AddRef,
731 BaseControlWindowImpl_Release,
732 BaseControlWindowImpl_GetTypeInfoCount,
733 BaseControlWindowImpl_GetTypeInfo,
734 BaseControlWindowImpl_GetIDsOfNames,
735 BaseControlWindowImpl_Invoke,
736 BaseControlWindowImpl_put_Caption,
737 BaseControlWindowImpl_get_Caption,
738 BaseControlWindowImpl_put_WindowStyle,
739 BaseControlWindowImpl_get_WindowStyle,
740 BaseControlWindowImpl_put_WindowStyleEx,
741 BaseControlWindowImpl_get_WindowStyleEx,
742 BaseControlWindowImpl_put_AutoShow,
743 BaseControlWindowImpl_get_AutoShow,
744 BaseControlWindowImpl_put_WindowState,
745 BaseControlWindowImpl_get_WindowState,
746 BaseControlWindowImpl_put_BackgroundPalette,
747 BaseControlWindowImpl_get_BackgroundPalette,
748 BaseControlWindowImpl_put_Visible,
749 BaseControlWindowImpl_get_Visible,
750 BaseControlWindowImpl_put_Left,
751 BaseControlWindowImpl_get_Left,
752 BaseControlWindowImpl_put_Width,
753 BaseControlWindowImpl_get_Width,
754 BaseControlWindowImpl_put_Top,
755 BaseControlWindowImpl_get_Top,
756 BaseControlWindowImpl_put_Height,
757 BaseControlWindowImpl_get_Height,
758 BaseControlWindowImpl_put_Owner,
759 BaseControlWindowImpl_get_Owner,
760 BaseControlWindowImpl_put_MessageDrain,
761 BaseControlWindowImpl_get_MessageDrain,
762 BaseControlWindowImpl_get_BorderColor,
763 BaseControlWindowImpl_put_BorderColor,
764 BaseControlWindowImpl_get_FullScreenMode,
765 BaseControlWindowImpl_put_FullScreenMode,
766 BaseControlWindowImpl_SetWindowForeground,
767 BaseControlWindowImpl_NotifyOwnerMessage,
768 BaseControlWindowImpl_SetWindowPosition,
769 BaseControlWindowImpl_GetWindowPosition,
770 BaseControlWindowImpl_GetMinIdealImageSize,
771 BaseControlWindowImpl_GetMaxIdealImageSize,
772 BaseControlWindowImpl_GetRestorePosition,
773 BaseControlWindowImpl_HideCursor,
774 BaseControlWindowImpl_IsCursorHidden
777 static HRESULT WINAPI AMCertifiedOutputProtection_QueryInterface(IAMCertifiedOutputProtection *iface,
778 REFIID riid, void **ppv)
780 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
781 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
784 static ULONG WINAPI AMCertifiedOutputProtection_AddRef(IAMCertifiedOutputProtection *iface)
786 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
787 return IUnknown_AddRef(This->renderer.filter.outer_unk);
790 static ULONG WINAPI AMCertifiedOutputProtection_Release(IAMCertifiedOutputProtection *iface)
792 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
793 return IUnknown_Release(This->renderer.filter.outer_unk);
796 static HRESULT WINAPI AMCertifiedOutputProtection_KeyExchange(IAMCertifiedOutputProtection *iface,
797 GUID* pRandom, BYTE** VarLenCertGH,
798 DWORD* pdwLengthCertGH)
800 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
802 FIXME("(%p/%p)->(%p, %p, %p) stub\n", iface, This, pRandom, VarLenCertGH, pdwLengthCertGH);
803 return VFW_E_NO_COPP_HW;
806 static HRESULT WINAPI AMCertifiedOutputProtection_SessionSequenceStart(IAMCertifiedOutputProtection *iface,
807 AMCOPPSignature* pSig)
809 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
811 FIXME("(%p/%p)->(%p) stub\n", iface, This, pSig);
812 return VFW_E_NO_COPP_HW;
815 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionCommand(IAMCertifiedOutputProtection *iface,
816 const AMCOPPCommand* cmd)
818 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
820 FIXME("(%p/%p)->(%p) stub\n", iface, This, cmd);
821 return VFW_E_NO_COPP_HW;
824 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionStatus(IAMCertifiedOutputProtection *iface,
825 const AMCOPPStatusInput* pStatusInput,
826 AMCOPPStatusOutput* pStatusOutput)
828 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
830 FIXME("(%p/%p)->(%p, %p) stub\n", iface, This, pStatusInput, pStatusOutput);
831 return VFW_E_NO_COPP_HW;
834 static const IAMCertifiedOutputProtectionVtbl IAMCertifiedOutputProtection_Vtbl =
836 AMCertifiedOutputProtection_QueryInterface,
837 AMCertifiedOutputProtection_AddRef,
838 AMCertifiedOutputProtection_Release,
839 AMCertifiedOutputProtection_KeyExchange,
840 AMCertifiedOutputProtection_SessionSequenceStart,
841 AMCertifiedOutputProtection_ProtectionCommand,
842 AMCertifiedOutputProtection_ProtectionStatus
845 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
846 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
847 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
850 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
851 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
852 return IUnknown_AddRef(This->renderer.filter.outer_unk);
855 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
856 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
857 return IUnknown_Release(This->renderer.filter.outer_unk);
860 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
861 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
864 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
865 AMFilterMiscFlags_QueryInterface,
866 AMFilterMiscFlags_AddRef,
867 AMFilterMiscFlags_Release,
868 AMFilterMiscFlags_GetMiscFlags
871 static HRESULT WINAPI VMR7FilterConfig_QueryInterface(IVMRFilterConfig *iface, REFIID riid,
872 void** ppv)
874 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
875 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
878 static ULONG WINAPI VMR7FilterConfig_AddRef(IVMRFilterConfig *iface)
880 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
881 return IUnknown_AddRef(This->renderer.filter.outer_unk);
884 static ULONG WINAPI VMR7FilterConfig_Release(IVMRFilterConfig *iface)
886 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
887 return IUnknown_Release(This->renderer.filter.outer_unk);
890 static HRESULT WINAPI VMR7FilterConfig_SetImageCompositor(IVMRFilterConfig *iface,
891 IVMRImageCompositor *compositor)
893 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
895 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
896 return E_NOTIMPL;
899 static HRESULT WINAPI VMR7FilterConfig_SetNumberOfStreams(IVMRFilterConfig *iface, DWORD max)
901 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
903 FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
904 return E_NOTIMPL;
907 static HRESULT WINAPI VMR7FilterConfig_GetNumberOfStreams(IVMRFilterConfig *iface, DWORD *max)
909 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
911 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
912 return E_NOTIMPL;
915 static HRESULT WINAPI VMR7FilterConfig_SetRenderingPrefs(IVMRFilterConfig *iface, DWORD renderflags)
917 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
919 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
920 return E_NOTIMPL;
923 static HRESULT WINAPI VMR7FilterConfig_GetRenderingPrefs(IVMRFilterConfig *iface, DWORD *renderflags)
925 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
927 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
928 return E_NOTIMPL;
931 static HRESULT WINAPI VMR7FilterConfig_SetRenderingMode(IVMRFilterConfig *iface, DWORD mode)
933 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
935 TRACE("iface %p, mode %#x.\n", iface, mode);
937 return IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, mode);
940 static HRESULT WINAPI VMR7FilterConfig_GetRenderingMode(IVMRFilterConfig *iface, DWORD *mode)
942 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
944 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
945 if (!mode) return E_POINTER;
947 if (This->mode)
948 *mode = This->mode;
949 else
950 *mode = VMRMode_Windowed;
952 return S_OK;
955 static const IVMRFilterConfigVtbl VMR7_FilterConfig_Vtbl =
957 VMR7FilterConfig_QueryInterface,
958 VMR7FilterConfig_AddRef,
959 VMR7FilterConfig_Release,
960 VMR7FilterConfig_SetImageCompositor,
961 VMR7FilterConfig_SetNumberOfStreams,
962 VMR7FilterConfig_GetNumberOfStreams,
963 VMR7FilterConfig_SetRenderingPrefs,
964 VMR7FilterConfig_GetRenderingPrefs,
965 VMR7FilterConfig_SetRenderingMode,
966 VMR7FilterConfig_GetRenderingMode
969 struct get_available_monitors_args
971 VMRMONITORINFO *info7;
972 VMR9MonitorInfo *info9;
973 DWORD arraysize;
974 DWORD numdev;
977 static BOOL CALLBACK get_available_monitors_proc(HMONITOR hmon, HDC hdc, LPRECT lprc, LPARAM lparam)
979 struct get_available_monitors_args *args = (struct get_available_monitors_args *)lparam;
980 MONITORINFOEXW mi;
982 if (args->info7 || args->info9)
985 if (!args->arraysize)
986 return FALSE;
988 mi.cbSize = sizeof(mi);
989 if (!GetMonitorInfoW(hmon, (MONITORINFO*)&mi))
990 return TRUE;
992 /* fill VMRMONITORINFO struct */
993 if (args->info7)
995 VMRMONITORINFO *info = args->info7++;
996 memset(info, 0, sizeof(*info));
998 if (args->numdev > 0)
1000 info->guid.pGUID = &info->guid.GUID;
1001 info->guid.GUID.Data4[7] = args->numdev;
1003 else
1004 info->guid.pGUID = NULL;
1006 info->rcMonitor = mi.rcMonitor;
1007 info->hMon = hmon;
1008 info->dwFlags = mi.dwFlags;
1010 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1012 /* FIXME: how to get these values? */
1013 info->szDescription[0] = 0;
1016 /* fill VMR9MonitorInfo struct */
1017 if (args->info9)
1019 VMR9MonitorInfo *info = args->info9++;
1020 memset(info, 0, sizeof(*info));
1022 info->uDevID = 0; /* FIXME */
1023 info->rcMonitor = mi.rcMonitor;
1024 info->hMon = hmon;
1025 info->dwFlags = mi.dwFlags;
1027 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1029 /* FIXME: how to get these values? */
1030 info->szDescription[0] = 0;
1031 info->dwVendorId = 0;
1032 info->dwDeviceId = 0;
1033 info->dwSubSysId = 0;
1034 info->dwRevision = 0;
1037 args->arraysize--;
1040 args->numdev++;
1041 return TRUE;
1044 static HRESULT WINAPI VMR7MonitorConfig_QueryInterface(IVMRMonitorConfig *iface, REFIID riid,
1045 LPVOID * ppv)
1047 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1048 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1051 static ULONG WINAPI VMR7MonitorConfig_AddRef(IVMRMonitorConfig *iface)
1053 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1054 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1057 static ULONG WINAPI VMR7MonitorConfig_Release(IVMRMonitorConfig *iface)
1059 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1060 return IUnknown_Release(This->renderer.filter.outer_unk);
1063 static HRESULT WINAPI VMR7MonitorConfig_SetMonitor(IVMRMonitorConfig *iface, const VMRGUID *pGUID)
1065 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1067 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1069 if (!pGUID)
1070 return E_POINTER;
1072 return S_OK;
1075 static HRESULT WINAPI VMR7MonitorConfig_GetMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1077 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1079 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1081 if (!pGUID)
1082 return E_POINTER;
1084 pGUID->pGUID = NULL; /* default DirectDraw device */
1085 return S_OK;
1088 static HRESULT WINAPI VMR7MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig *iface,
1089 const VMRGUID *pGUID)
1091 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1093 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1095 if (!pGUID)
1096 return E_POINTER;
1098 return S_OK;
1101 static HRESULT WINAPI VMR7MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1103 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1105 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1107 if (!pGUID)
1108 return E_POINTER;
1110 pGUID->pGUID = NULL; /* default DirectDraw device */
1111 return S_OK;
1114 static HRESULT WINAPI VMR7MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig *iface,
1115 VMRMONITORINFO *info, DWORD arraysize,
1116 DWORD *numdev)
1118 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1119 struct get_available_monitors_args args;
1121 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1123 if (!numdev)
1124 return E_POINTER;
1126 if (info && arraysize == 0)
1127 return E_INVALIDARG;
1129 args.info7 = info;
1130 args.info9 = NULL;
1131 args.arraysize = arraysize;
1132 args.numdev = 0;
1133 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1135 *numdev = args.numdev;
1136 return S_OK;
1139 static const IVMRMonitorConfigVtbl VMR7_MonitorConfig_Vtbl =
1141 VMR7MonitorConfig_QueryInterface,
1142 VMR7MonitorConfig_AddRef,
1143 VMR7MonitorConfig_Release,
1144 VMR7MonitorConfig_SetMonitor,
1145 VMR7MonitorConfig_GetMonitor,
1146 VMR7MonitorConfig_SetDefaultMonitor,
1147 VMR7MonitorConfig_GetDefaultMonitor,
1148 VMR7MonitorConfig_GetAvailableMonitors
1151 static HRESULT WINAPI VMR9MonitorConfig_QueryInterface(IVMRMonitorConfig9 *iface, REFIID riid,
1152 LPVOID * ppv)
1154 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1155 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1158 static ULONG WINAPI VMR9MonitorConfig_AddRef(IVMRMonitorConfig9 *iface)
1160 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1161 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1164 static ULONG WINAPI VMR9MonitorConfig_Release(IVMRMonitorConfig9 *iface)
1166 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1167 return IUnknown_Release(This->renderer.filter.outer_unk);
1170 static HRESULT WINAPI VMR9MonitorConfig_SetMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1172 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1174 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1176 return S_OK;
1179 static HRESULT WINAPI VMR9MonitorConfig_GetMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1181 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1183 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1185 if (!uDev)
1186 return E_POINTER;
1188 *uDev = 0;
1189 return S_OK;
1192 static HRESULT WINAPI VMR9MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1194 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1196 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1198 return S_OK;
1201 static HRESULT WINAPI VMR9MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1203 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1205 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1207 if (!uDev)
1208 return E_POINTER;
1210 *uDev = 0;
1211 return S_OK;
1214 static HRESULT WINAPI VMR9MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig9 *iface,
1215 VMR9MonitorInfo *info, DWORD arraysize,
1216 DWORD *numdev)
1218 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1219 struct get_available_monitors_args args;
1221 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1223 if (!numdev)
1224 return E_POINTER;
1226 if (info && arraysize == 0)
1227 return E_INVALIDARG;
1229 args.info7 = NULL;
1230 args.info9 = info;
1231 args.arraysize = arraysize;
1232 args.numdev = 0;
1233 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1235 *numdev = args.numdev;
1236 return S_OK;
1239 static const IVMRMonitorConfig9Vtbl VMR9_MonitorConfig_Vtbl =
1241 VMR9MonitorConfig_QueryInterface,
1242 VMR9MonitorConfig_AddRef,
1243 VMR9MonitorConfig_Release,
1244 VMR9MonitorConfig_SetMonitor,
1245 VMR9MonitorConfig_GetMonitor,
1246 VMR9MonitorConfig_SetDefaultMonitor,
1247 VMR9MonitorConfig_GetDefaultMonitor,
1248 VMR9MonitorConfig_GetAvailableMonitors
1251 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
1253 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1254 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1257 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
1259 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1260 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1263 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
1265 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1266 return IUnknown_Release(This->renderer.filter.outer_unk);
1269 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
1271 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1273 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
1274 return E_NOTIMPL;
1277 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD count)
1279 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1281 FIXME("iface %p, count %u, stub!\n", iface, count);
1283 if (!count)
1285 WARN("Application requested zero streams; returning E_INVALIDARG.\n");
1286 return E_INVALIDARG;
1289 EnterCriticalSection(&filter->renderer.filter.csFilter);
1291 if (filter->stream_count)
1293 LeaveCriticalSection(&filter->renderer.filter.csFilter);
1294 WARN("Stream count is already set; returning VFW_E_WRONG_STATE.\n");
1295 return VFW_E_WRONG_STATE;
1298 filter->stream_count = count;
1300 LeaveCriticalSection(&filter->renderer.filter.csFilter);
1301 return S_OK;
1304 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *count)
1306 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1308 TRACE("filter %p, count %p.\n", filter, count);
1310 EnterCriticalSection(&filter->renderer.filter.csFilter);
1312 if (!filter->stream_count)
1314 LeaveCriticalSection(&filter->renderer.filter.csFilter);
1315 return VFW_E_VMR_NOT_IN_MIXER_MODE;
1318 *count = filter->stream_count;
1320 LeaveCriticalSection(&filter->renderer.filter.csFilter);
1321 return S_OK;
1324 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
1326 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1328 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
1329 return E_NOTIMPL;
1332 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
1334 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1336 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
1337 return E_NOTIMPL;
1340 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
1342 HRESULT hr = S_OK;
1343 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1345 TRACE("(%p/%p)->(%u)\n", iface, This, mode);
1347 EnterCriticalSection(&This->renderer.filter.csFilter);
1348 if (This->mode)
1350 LeaveCriticalSection(&This->renderer.filter.csFilter);
1351 return VFW_E_WRONG_STATE;
1354 if (This->allocator)
1355 IVMRSurfaceAllocator9_Release(This->allocator);
1356 if (This->presenter)
1357 IVMRImagePresenter9_Release(This->presenter);
1359 This->allocator = NULL;
1360 This->presenter = NULL;
1362 switch (mode)
1364 case VMR9Mode_Windowed:
1365 case VMR9Mode_Windowless:
1366 This->cookie = ~0;
1368 hr = VMR9DefaultAllocatorPresenterImpl_create(This, (LPVOID*)&This->presenter);
1369 if (SUCCEEDED(hr))
1370 hr = IVMRImagePresenter9_QueryInterface(This->presenter,
1371 &IID_IVMRSurfaceAllocator9, (void **)&This->allocator);
1372 if (FAILED(hr))
1374 ERR("Unable to find Presenter interface\n");
1375 IVMRImagePresenter9_Release(This->presenter);
1376 This->allocator = NULL;
1377 This->presenter = NULL;
1379 else
1380 hr = IVMRSurfaceAllocator9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
1381 break;
1382 case VMR9Mode_Renderless:
1383 break;
1384 default:
1385 LeaveCriticalSection(&This->renderer.filter.csFilter);
1386 return E_INVALIDARG;
1389 if (mode != VMR9Mode_Windowed)
1390 video_window_cleanup(&This->window);
1392 This->mode = mode;
1393 LeaveCriticalSection(&This->renderer.filter.csFilter);
1394 return hr;
1397 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
1399 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1401 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
1402 if (!mode)
1403 return E_POINTER;
1405 if (This->mode)
1406 *mode = This->mode;
1407 else
1408 *mode = VMR9Mode_Windowed;
1410 return S_OK;
1413 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
1415 VMR9FilterConfig_QueryInterface,
1416 VMR9FilterConfig_AddRef,
1417 VMR9FilterConfig_Release,
1418 VMR9FilterConfig_SetImageCompositor,
1419 VMR9FilterConfig_SetNumberOfStreams,
1420 VMR9FilterConfig_GetNumberOfStreams,
1421 VMR9FilterConfig_SetRenderingPrefs,
1422 VMR9FilterConfig_GetRenderingPrefs,
1423 VMR9FilterConfig_SetRenderingMode,
1424 VMR9FilterConfig_GetRenderingMode
1427 static HRESULT WINAPI VMR7WindowlessControl_QueryInterface(IVMRWindowlessControl *iface, REFIID riid,
1428 LPVOID * ppv)
1430 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1431 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1434 static ULONG WINAPI VMR7WindowlessControl_AddRef(IVMRWindowlessControl *iface)
1436 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1437 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1440 static ULONG WINAPI VMR7WindowlessControl_Release(IVMRWindowlessControl *iface)
1442 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1443 return IUnknown_Release(This->renderer.filter.outer_unk);
1446 static HRESULT WINAPI VMR7WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl *iface,
1447 LONG *width, LONG *height,
1448 LONG *arwidth, LONG *arheight)
1450 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1451 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
1453 if (!width || !height || !arwidth || !arheight)
1455 ERR("Got no pointer\n");
1456 return E_POINTER;
1459 *width = This->bmiheader.biWidth;
1460 *height = This->bmiheader.biHeight;
1461 *arwidth = This->bmiheader.biWidth;
1462 *arheight = This->bmiheader.biHeight;
1464 return S_OK;
1467 static HRESULT WINAPI VMR7WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl *iface,
1468 LONG *width, LONG *height)
1470 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1472 FIXME("(%p/%p)->(...) stub\n", iface, This);
1473 return E_NOTIMPL;
1476 static HRESULT WINAPI VMR7WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl *iface,
1477 LONG *width, LONG *height)
1479 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1481 FIXME("(%p/%p)->(...) stub\n", iface, This);
1482 return E_NOTIMPL;
1485 static HRESULT WINAPI VMR7WindowlessControl_SetVideoPosition(IVMRWindowlessControl *iface,
1486 const RECT *source, const RECT *dest)
1488 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1490 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1492 EnterCriticalSection(&This->renderer.filter.csFilter);
1494 if (source)
1495 This->window.src = *source;
1496 if (dest)
1497 This->window.dst = *dest;
1499 LeaveCriticalSection(&This->renderer.filter.csFilter);
1501 return S_OK;
1504 static HRESULT WINAPI VMR7WindowlessControl_GetVideoPosition(IVMRWindowlessControl *iface,
1505 RECT *source, RECT *dest)
1507 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1509 if (source)
1510 *source = This->window.src;
1512 if (dest)
1513 *dest = This->window.dst;
1515 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1516 return S_OK;
1519 static HRESULT WINAPI VMR7WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl *iface,
1520 DWORD *mode)
1522 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1524 FIXME("(%p/%p)->(...) stub\n", iface, This);
1525 return E_NOTIMPL;
1528 static HRESULT WINAPI VMR7WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl *iface,
1529 DWORD mode)
1531 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1533 FIXME("(%p/%p)->(...) stub\n", iface, This);
1534 return E_NOTIMPL;
1537 static HRESULT WINAPI VMR7WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl *iface, HWND window)
1539 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1541 TRACE("iface %p, window %p.\n", iface, window);
1543 return IVMRWindowlessControl9_SetVideoClippingWindow(&filter->IVMRWindowlessControl9_iface, window);
1546 static HRESULT WINAPI VMR7WindowlessControl_RepaintVideo(IVMRWindowlessControl *iface,
1547 HWND hwnd, HDC hdc)
1549 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1551 FIXME("(%p/%p)->(...) stub\n", iface, This);
1552 return E_NOTIMPL;
1555 static HRESULT WINAPI VMR7WindowlessControl_DisplayModeChanged(IVMRWindowlessControl *iface)
1557 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1559 FIXME("(%p/%p)->(...) stub\n", iface, This);
1560 return E_NOTIMPL;
1563 static HRESULT WINAPI VMR7WindowlessControl_GetCurrentImage(IVMRWindowlessControl *iface,
1564 BYTE **dib)
1566 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1568 FIXME("(%p/%p)->(...) stub\n", iface, This);
1569 return E_NOTIMPL;
1572 static HRESULT WINAPI VMR7WindowlessControl_SetBorderColor(IVMRWindowlessControl *iface,
1573 COLORREF color)
1575 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1577 FIXME("(%p/%p)->(...) stub\n", iface, This);
1578 return E_NOTIMPL;
1581 static HRESULT WINAPI VMR7WindowlessControl_GetBorderColor(IVMRWindowlessControl *iface,
1582 COLORREF *color)
1584 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1586 FIXME("(%p/%p)->(...) stub\n", iface, This);
1587 return E_NOTIMPL;
1590 static HRESULT WINAPI VMR7WindowlessControl_SetColorKey(IVMRWindowlessControl *iface, COLORREF color)
1592 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1594 FIXME("(%p/%p)->(...) stub\n", iface, This);
1595 return E_NOTIMPL;
1598 static HRESULT WINAPI VMR7WindowlessControl_GetColorKey(IVMRWindowlessControl *iface, COLORREF *color)
1600 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1602 FIXME("(%p/%p)->(...) stub\n", iface, This);
1603 return E_NOTIMPL;
1606 static const IVMRWindowlessControlVtbl VMR7_WindowlessControl_Vtbl =
1608 VMR7WindowlessControl_QueryInterface,
1609 VMR7WindowlessControl_AddRef,
1610 VMR7WindowlessControl_Release,
1611 VMR7WindowlessControl_GetNativeVideoSize,
1612 VMR7WindowlessControl_GetMinIdealVideoSize,
1613 VMR7WindowlessControl_GetMaxIdealVideoSize,
1614 VMR7WindowlessControl_SetVideoPosition,
1615 VMR7WindowlessControl_GetVideoPosition,
1616 VMR7WindowlessControl_GetAspectRatioMode,
1617 VMR7WindowlessControl_SetAspectRatioMode,
1618 VMR7WindowlessControl_SetVideoClippingWindow,
1619 VMR7WindowlessControl_RepaintVideo,
1620 VMR7WindowlessControl_DisplayModeChanged,
1621 VMR7WindowlessControl_GetCurrentImage,
1622 VMR7WindowlessControl_SetBorderColor,
1623 VMR7WindowlessControl_GetBorderColor,
1624 VMR7WindowlessControl_SetColorKey,
1625 VMR7WindowlessControl_GetColorKey
1628 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
1630 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1631 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1634 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
1636 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1637 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1640 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
1642 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1643 return IUnknown_Release(This->renderer.filter.outer_unk);
1646 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface,
1647 LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height)
1649 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1651 TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n",
1652 filter, width, height, aspect_width, aspect_height);
1654 if (!width || !height)
1655 return E_POINTER;
1657 *width = filter->bmiheader.biWidth;
1658 *height = filter->bmiheader.biHeight;
1659 if (aspect_width)
1660 *aspect_width = filter->bmiheader.biWidth;
1661 if (aspect_height)
1662 *aspect_height = filter->bmiheader.biHeight;
1664 return S_OK;
1667 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1669 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1671 FIXME("(%p/%p)->(...) stub\n", iface, This);
1672 return E_NOTIMPL;
1675 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1677 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1679 FIXME("(%p/%p)->(...) stub\n", iface, This);
1680 return E_NOTIMPL;
1683 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface,
1684 const RECT *src, const RECT *dst)
1686 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1688 TRACE("filter %p, src %s, dst %s.\n", filter, wine_dbgstr_rect(src), wine_dbgstr_rect(dst));
1690 EnterCriticalSection(&filter->renderer.filter.csFilter);
1692 if (src)
1693 filter->window.src = *src;
1694 if (dst)
1695 filter->window.dst = *dst;
1697 LeaveCriticalSection(&filter->renderer.filter.csFilter);
1699 return S_OK;
1702 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *src, RECT *dst)
1704 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1706 TRACE("filter %p, src %p, dst %p.\n", filter, src, dst);
1708 if (src)
1709 *src = filter->window.src;
1711 if (dst)
1712 *dst = filter->window.dst;
1714 return S_OK;
1717 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1719 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1721 TRACE("filter %p, mode %p.\n", filter, mode);
1723 EnterCriticalSection(&filter->renderer.filter.csFilter);
1724 *mode = filter->aspect_mode;
1725 LeaveCriticalSection(&filter->renderer.filter.csFilter);
1726 return S_OK;
1729 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1731 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1733 TRACE("filter %p, mode %u.\n", filter, mode);
1735 EnterCriticalSection(&filter->renderer.filter.csFilter);
1736 filter->aspect_mode = mode;
1737 LeaveCriticalSection(&filter->renderer.filter.csFilter);
1738 return S_OK;
1741 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND window)
1743 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1744 HRESULT hr;
1746 TRACE("filter %p, window %p.\n", filter, window);
1748 if (!IsWindow(window))
1750 WARN("Invalid window %p, returning E_INVALIDARG.\n", window);
1751 return E_INVALIDARG;
1754 EnterCriticalSection(&filter->renderer.filter.csFilter);
1756 if (filter->renderer.sink.pin.peer)
1758 LeaveCriticalSection(&filter->renderer.filter.csFilter);
1759 WARN("Attempt to set the clipping window while connected; returning VFW_E_WRONG_STATE.\n");
1760 return VFW_E_WRONG_STATE;
1763 filter->clipping_window = window;
1765 hr = IVMRFilterConfig9_SetNumberOfStreams(&filter->IVMRFilterConfig9_iface, 4);
1767 LeaveCriticalSection(&filter->renderer.filter.csFilter);
1768 return hr;
1771 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1773 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1774 HRESULT hr;
1776 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1778 EnterCriticalSection(&This->renderer.filter.csFilter);
1779 if (hwnd != This->clipping_window)
1781 ERR("Not handling changing windows yet!!!\n");
1782 LeaveCriticalSection(&This->renderer.filter.csFilter);
1783 return S_OK;
1786 if (!This->allocator_d3d9_dev)
1788 ERR("No d3d9 device!\n");
1789 LeaveCriticalSection(&This->renderer.filter.csFilter);
1790 return VFW_E_WRONG_STATE;
1793 /* Windowless extension */
1794 hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, NULL, NULL);
1795 LeaveCriticalSection(&This->renderer.filter.csFilter);
1797 return hr;
1800 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1802 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1804 FIXME("(%p/%p)->(...) stub\n", iface, This);
1805 return E_NOTIMPL;
1808 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1810 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1812 FIXME("(%p/%p)->(...) stub\n", iface, This);
1813 return E_NOTIMPL;
1816 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1818 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1820 FIXME("(%p/%p)->(...) stub\n", iface, This);
1821 return E_NOTIMPL;
1824 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1826 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1828 FIXME("(%p/%p)->(...) stub\n", iface, This);
1829 return E_NOTIMPL;
1832 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1834 VMR9WindowlessControl_QueryInterface,
1835 VMR9WindowlessControl_AddRef,
1836 VMR9WindowlessControl_Release,
1837 VMR9WindowlessControl_GetNativeVideoSize,
1838 VMR9WindowlessControl_GetMinIdealVideoSize,
1839 VMR9WindowlessControl_GetMaxIdealVideoSize,
1840 VMR9WindowlessControl_SetVideoPosition,
1841 VMR9WindowlessControl_GetVideoPosition,
1842 VMR9WindowlessControl_GetAspectRatioMode,
1843 VMR9WindowlessControl_SetAspectRatioMode,
1844 VMR9WindowlessControl_SetVideoClippingWindow,
1845 VMR9WindowlessControl_RepaintVideo,
1846 VMR9WindowlessControl_DisplayModeChanged,
1847 VMR9WindowlessControl_GetCurrentImage,
1848 VMR9WindowlessControl_SetBorderColor,
1849 VMR9WindowlessControl_GetBorderColor
1852 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify *iface,
1853 REFIID riid, LPVOID * ppv)
1855 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1856 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1859 static ULONG WINAPI VMR7SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify *iface)
1861 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1862 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1865 static ULONG WINAPI VMR7SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify *iface)
1867 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1868 return IUnknown_Release(This->renderer.filter.outer_unk);
1871 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify *iface,
1872 DWORD_PTR id,
1873 IVMRSurfaceAllocator *alloc)
1875 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1877 FIXME("(%p/%p)->(...) stub\n", iface, This);
1878 return E_NOTIMPL;
1881 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1882 IDirectDraw7 *device, HMONITOR monitor)
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_ChangeDDrawDevice(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_RestoreDDrawSurfaces(IVMRSurfaceAllocatorNotify *iface)
1901 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1903 FIXME("(%p/%p)->(...) stub\n", iface, This);
1904 return E_NOTIMPL;
1907 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify *iface, LONG code,
1908 LONG_PTR param1, LONG_PTR param2)
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_SetBorderColor(IVMRSurfaceAllocatorNotify *iface,
1917 COLORREF clrBorder)
1919 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1921 FIXME("(%p/%p)->(...) stub\n", iface, This);
1922 return E_NOTIMPL;
1925 static const IVMRSurfaceAllocatorNotifyVtbl VMR7_SurfaceAllocatorNotify_Vtbl =
1927 VMR7SurfaceAllocatorNotify_QueryInterface,
1928 VMR7SurfaceAllocatorNotify_AddRef,
1929 VMR7SurfaceAllocatorNotify_Release,
1930 VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1931 VMR7SurfaceAllocatorNotify_SetDDrawDevice,
1932 VMR7SurfaceAllocatorNotify_ChangeDDrawDevice,
1933 VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces,
1934 VMR7SurfaceAllocatorNotify_NotifyEvent,
1935 VMR7SurfaceAllocatorNotify_SetBorderColor
1938 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1940 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1941 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1944 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1946 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1947 ULONG refcount = InterlockedIncrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1949 TRACE("%p increasing refcount to %u.\n", iface, refcount);
1951 return refcount;
1954 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1956 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1957 ULONG refcount = InterlockedDecrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1959 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
1961 if (!refcount && !filter->renderer.filter.refcount)
1962 vmr_free(filter);
1964 return refcount;
1967 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(
1968 IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR cookie, IVMRSurfaceAllocator9 *allocator)
1970 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1972 TRACE("filter %p, cookie %#Ix, allocator %p.\n", filter, cookie, allocator);
1974 filter->cookie = cookie;
1976 if (filter->presenter)
1977 return VFW_E_WRONG_STATE;
1979 if (FAILED(IVMRSurfaceAllocator9_QueryInterface(allocator, &IID_IVMRImagePresenter9, (void **)&filter->presenter)))
1980 return E_NOINTERFACE;
1982 filter->allocator = allocator;
1983 IVMRSurfaceAllocator9_AddRef(allocator);
1985 return S_OK;
1988 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface,
1989 IDirect3DDevice9 *device, HMONITOR monitor)
1991 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1993 TRACE("filter %p, device %p, monitor %p.\n", filter, device, monitor);
1995 if (filter->allocator_d3d9_dev)
1996 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
1997 filter->allocator_d3d9_dev = device;
1998 IDirect3DDevice9_AddRef(device);
2000 return S_OK;
2003 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
2005 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2007 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
2008 if (This->allocator_d3d9_dev)
2009 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
2010 This->allocator_d3d9_dev = device;
2011 IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
2013 return S_OK;
2016 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
2018 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2019 DWORD i;
2020 HRESULT hr = S_OK;
2022 TRACE("filter %p, allocinfo %p, numbuffers %p, surface %p.\n", This, numbuffers, allocinfo, surface);
2024 if (!allocinfo || !numbuffers || !surface)
2025 return E_POINTER;
2027 TRACE("Flags %#x, size %ux%u, format %u (%#x), pool %u, minimum buffers %u.\n",
2028 allocinfo->dwFlags, allocinfo->dwWidth, allocinfo->dwHeight,
2029 allocinfo->Format, allocinfo->Format, allocinfo->Pool, allocinfo->MinBuffers);
2031 if (!allocinfo->Format)
2033 IDirect3DSurface9 *backbuffer;
2034 D3DSURFACE_DESC desc;
2036 IDirect3DDevice9_GetBackBuffer(This->allocator_d3d9_dev, 0, 0,
2037 D3DBACKBUFFER_TYPE_MONO, &backbuffer);
2038 IDirect3DSurface9_GetDesc(backbuffer, &desc);
2039 IDirect3DSurface9_Release(backbuffer);
2040 allocinfo->Format = desc.Format;
2043 if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
2045 WARN("%u surfaces requested (minimum %u); returning E_INVALIDARG.\n",
2046 *numbuffers, allocinfo->MinBuffers);
2047 return E_INVALIDARG;
2050 if (!This->allocator_d3d9_dev)
2052 WARN("No Direct3D device; returning VFW_E_WRONG_STATE.\n");
2053 return VFW_E_WRONG_STATE;
2056 if (allocinfo->dwFlags == VMR9AllocFlag_OffscreenSurface)
2058 for (i = 0; i < *numbuffers; ++i)
2060 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight,
2061 allocinfo->Format, allocinfo->Pool, &surface[i], NULL);
2062 if (FAILED(hr))
2063 break;
2066 else if (allocinfo->dwFlags == VMR9AllocFlag_TextureSurface)
2068 for (i = 0; i < *numbuffers; ++i)
2070 IDirect3DTexture9 *texture;
2072 hr = IDirect3DDevice9_CreateTexture(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, 1, D3DUSAGE_DYNAMIC,
2073 allocinfo->Format, allocinfo->Pool, &texture, NULL);
2074 if (FAILED(hr))
2075 break;
2076 IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface[i]);
2077 IDirect3DTexture9_Release(texture);
2080 else if (allocinfo->dwFlags == VMR9AllocFlag_3DRenderTarget)
2082 for (i = 0; i < *numbuffers; ++i)
2084 if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(This->allocator_d3d9_dev,
2085 allocinfo->dwWidth, allocinfo->dwHeight, allocinfo->Format,
2086 D3DMULTISAMPLE_NONE, 0, FALSE, &surface[i], NULL)))
2087 break;
2090 else
2092 FIXME("Unhandled flags %#x.\n", allocinfo->dwFlags);
2093 return E_NOTIMPL;
2096 if (FAILED(hr))
2097 WARN("%u/%u surfaces allocated, hr %#x.\n", i, *numbuffers, hr);
2099 if (i >= allocinfo->MinBuffers)
2101 hr = S_OK;
2102 *numbuffers = i;
2104 else
2106 for ( ; i > 0; --i) IDirect3DSurface9_Release(surface[i - 1]);
2107 *numbuffers = 0;
2109 return hr;
2112 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
2114 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2116 FIXME("(%p/%p)->(...) stub\n", iface, This);
2117 return E_NOTIMPL;
2120 static const IVMRSurfaceAllocatorNotify9Vtbl VMR9_SurfaceAllocatorNotify_Vtbl =
2122 VMR9SurfaceAllocatorNotify_QueryInterface,
2123 VMR9SurfaceAllocatorNotify_AddRef,
2124 VMR9SurfaceAllocatorNotify_Release,
2125 VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
2126 VMR9SurfaceAllocatorNotify_SetD3DDevice,
2127 VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
2128 VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
2129 VMR9SurfaceAllocatorNotify_NotifyEvent
2132 static inline struct quartz_vmr *impl_from_IVMRMixerControl9(IVMRMixerControl9 *iface)
2134 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerControl9_iface);
2137 static HRESULT WINAPI mixer_control9_QueryInterface(IVMRMixerControl9 *iface, REFIID iid, void **out)
2139 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2140 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2143 static ULONG WINAPI mixer_control9_AddRef(IVMRMixerControl9 *iface)
2145 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2146 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2149 static ULONG WINAPI mixer_control9_Release(IVMRMixerControl9 *iface)
2151 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2152 return IUnknown_Release(filter->renderer.filter.outer_unk);
2155 static HRESULT WINAPI mixer_control9_SetAlpha(IVMRMixerControl9 *iface, DWORD stream, float alpha)
2157 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2159 FIXME("filter %p, stream %u, alpha %.8e, stub!\n", filter, stream, alpha);
2161 return E_NOTIMPL;
2164 static HRESULT WINAPI mixer_control9_GetAlpha(IVMRMixerControl9 *iface, DWORD stream, float *alpha)
2166 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2168 FIXME("filter %p, stream %u, alpha %p, stub!\n", filter, stream, alpha);
2170 return E_NOTIMPL;
2173 static HRESULT WINAPI mixer_control9_SetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD z)
2175 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2177 FIXME("filter %p, stream %u, z %u, stub!\n", filter, stream, z);
2179 return E_NOTIMPL;
2182 static HRESULT WINAPI mixer_control9_GetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD *z)
2184 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2186 FIXME("filter %p, stream %u, z %p, stub!\n", filter, stream, z);
2188 return E_NOTIMPL;
2191 static HRESULT WINAPI mixer_control9_SetOutputRect(IVMRMixerControl9 *iface,
2192 DWORD stream, const VMR9NormalizedRect *rect)
2194 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2196 FIXME("filter %p, stream %u, rect %s, stub!\n", filter, stream, debugstr_normalized_rect(rect));
2198 return E_NOTIMPL;
2201 static HRESULT WINAPI mixer_control9_GetOutputRect(IVMRMixerControl9 *iface,
2202 DWORD stream, VMR9NormalizedRect *rect)
2204 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2206 FIXME("filter %p, stream %u, rect %p, stub!\n", filter, stream, rect);
2208 return E_NOTIMPL;
2211 static HRESULT WINAPI mixer_control9_SetBackgroundClr(IVMRMixerControl9 *iface, COLORREF color)
2213 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2215 FIXME("filter %p, color #%06x, stub!\n", filter, color);
2217 return E_NOTIMPL;
2220 static HRESULT WINAPI mixer_control9_GetBackgroundClr(IVMRMixerControl9 *iface, COLORREF *color)
2222 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2224 FIXME("filter %p, color %p, stub!\n", filter, color);
2226 return E_NOTIMPL;
2229 static HRESULT WINAPI mixer_control9_SetMixingPrefs(IVMRMixerControl9 *iface, DWORD flags)
2231 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2233 FIXME("filter %p, flags %#x, stub!\n", filter, flags);
2235 EnterCriticalSection(&filter->renderer.filter.csFilter);
2236 filter->mixing_prefs = flags;
2237 LeaveCriticalSection(&filter->renderer.filter.csFilter);
2238 return S_OK;
2241 static HRESULT WINAPI mixer_control9_GetMixingPrefs(IVMRMixerControl9 *iface, DWORD *flags)
2243 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2245 FIXME("filter %p, flags %p, stub!\n", filter, flags);
2247 EnterCriticalSection(&filter->renderer.filter.csFilter);
2248 *flags = filter->mixing_prefs;
2249 LeaveCriticalSection(&filter->renderer.filter.csFilter);
2250 return S_OK;
2253 static HRESULT WINAPI mixer_control9_SetProcAmpControl(IVMRMixerControl9 *iface,
2254 DWORD stream, VMR9ProcAmpControl *settings)
2256 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2258 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2260 return E_NOTIMPL;
2263 static HRESULT WINAPI mixer_control9_GetProcAmpControl(IVMRMixerControl9 *iface,
2264 DWORD stream, VMR9ProcAmpControl *settings)
2266 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2268 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2270 return E_NOTIMPL;
2273 static HRESULT WINAPI mixer_control9_GetProcAmpControlRange(IVMRMixerControl9 *iface,
2274 DWORD stream, VMR9ProcAmpControlRange *settings)
2276 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2278 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2280 return E_NOTIMPL;
2283 static const IVMRMixerControl9Vtbl mixer_control9_vtbl =
2285 mixer_control9_QueryInterface,
2286 mixer_control9_AddRef,
2287 mixer_control9_Release,
2288 mixer_control9_SetAlpha,
2289 mixer_control9_GetAlpha,
2290 mixer_control9_SetZOrder,
2291 mixer_control9_GetZOrder,
2292 mixer_control9_SetOutputRect,
2293 mixer_control9_GetOutputRect,
2294 mixer_control9_SetBackgroundClr,
2295 mixer_control9_GetBackgroundClr,
2296 mixer_control9_SetMixingPrefs,
2297 mixer_control9_GetMixingPrefs,
2298 mixer_control9_SetProcAmpControl,
2299 mixer_control9_GetProcAmpControl,
2300 mixer_control9_GetProcAmpControlRange,
2303 static inline struct quartz_vmr *impl_from_IVMRMixerBitmap9(IVMRMixerBitmap9 *iface)
2305 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerBitmap9_iface);
2308 static HRESULT WINAPI mixer_bitmap9_QueryInterface(IVMRMixerBitmap9 *iface, REFIID iid, void **out)
2310 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2311 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2314 static ULONG WINAPI mixer_bitmap9_AddRef(IVMRMixerBitmap9 *iface)
2316 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2317 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2320 static ULONG WINAPI mixer_bitmap9_Release(IVMRMixerBitmap9 *iface)
2322 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2323 return IUnknown_Release(filter->renderer.filter.outer_unk);
2326 static HRESULT WINAPI mixer_bitmap9_SetAlphaBitmap(IVMRMixerBitmap9 *iface,
2327 const VMR9AlphaBitmap *bitmap)
2329 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2330 TRACE("dwFlags %#x, hdc %p, pDDS %p, rSrc %s, rDest %s, fAlpha %.8e, clrSrcKey #%06x, dwFilterMode %#x.\n",
2331 bitmap->dwFlags, bitmap->hdc, bitmap->pDDS, wine_dbgstr_rect(&bitmap->rSrc),
2332 debugstr_normalized_rect(&bitmap->rDest), bitmap->fAlpha, bitmap->clrSrcKey, bitmap->dwFilterMode);
2333 return E_NOTIMPL;
2336 static HRESULT WINAPI mixer_bitmap9_UpdateAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2337 const VMR9AlphaBitmap *bitmap)
2339 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2340 return E_NOTIMPL;
2343 static HRESULT WINAPI mixer_bitmap9_GetAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2344 VMR9AlphaBitmap *bitmap)
2346 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2347 return E_NOTIMPL;
2350 static const IVMRMixerBitmap9Vtbl mixer_bitmap9_vtbl =
2352 mixer_bitmap9_QueryInterface,
2353 mixer_bitmap9_AddRef,
2354 mixer_bitmap9_Release,
2355 mixer_bitmap9_SetAlphaBitmap,
2356 mixer_bitmap9_UpdateAlphaBitmapParameters,
2357 mixer_bitmap9_GetAlphaBitmapParameters,
2360 static inline struct quartz_vmr *impl_from_IOverlay(IOverlay *iface)
2362 return CONTAINING_RECORD(iface, struct quartz_vmr, IOverlay_iface);
2365 static HRESULT WINAPI overlay_QueryInterface(IOverlay *iface, REFIID iid, void **out)
2367 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2368 return IPin_QueryInterface(&filter->renderer.sink.pin.IPin_iface, iid, out);
2371 static ULONG WINAPI overlay_AddRef(IOverlay *iface)
2373 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2374 return IPin_AddRef(&filter->renderer.sink.pin.IPin_iface);
2377 static ULONG WINAPI overlay_Release(IOverlay *iface)
2379 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2380 return IPin_Release(&filter->renderer.sink.pin.IPin_iface);
2383 static HRESULT WINAPI overlay_GetPalette(IOverlay *iface, DWORD *count, PALETTEENTRY **palette)
2385 FIXME("iface %p, count %p, palette %p, stub!\n", iface, count, palette);
2386 return E_NOTIMPL;
2389 static HRESULT WINAPI overlay_SetPalette(IOverlay *iface, DWORD count, PALETTEENTRY *palette)
2391 FIXME("iface %p, count %u, palette %p, stub!\n", iface, count, palette);
2392 return E_NOTIMPL;
2395 static HRESULT WINAPI overlay_GetDefaultColorKey(IOverlay *iface, COLORKEY *key)
2397 FIXME("iface %p, key %p, stub!\n", iface, key);
2398 return E_NOTIMPL;
2401 static HRESULT WINAPI overlay_GetColorKey(IOverlay *iface, COLORKEY *key)
2403 FIXME("iface %p, key %p, stub!\n", iface, key);
2404 return E_NOTIMPL;
2407 static HRESULT WINAPI overlay_SetColorKey(IOverlay *iface, COLORKEY *key)
2409 FIXME("iface %p, key %p, stub!\n", iface, key);
2410 return E_NOTIMPL;
2413 static HRESULT WINAPI overlay_GetWindowHandle(IOverlay *iface, HWND *window)
2415 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2417 TRACE("filter %p, window %p.\n", filter, window);
2419 if (!filter->window.hwnd)
2420 return VFW_E_WRONG_STATE;
2422 *window = filter->window.hwnd;
2423 return S_OK;
2426 static HRESULT WINAPI overlay_GetClipList(IOverlay *iface, RECT *source, RECT *dest, RGNDATA **region)
2428 FIXME("iface %p, source %p, dest %p, region %p, stub!\n", iface, source, dest, region);
2429 return E_NOTIMPL;
2432 static HRESULT WINAPI overlay_GetVideoPosition(IOverlay *iface, RECT *source, RECT *dest)
2434 FIXME("iface %p, source %p, dest %p, stub!\n", iface, source, dest);
2435 return E_NOTIMPL;
2438 static HRESULT WINAPI overlay_Advise(IOverlay *iface, IOverlayNotify *sink, DWORD flags)
2440 FIXME("iface %p, sink %p, flags %#x, stub!\n", iface, sink, flags);
2441 return E_NOTIMPL;
2444 static HRESULT WINAPI overlay_Unadvise(IOverlay *iface)
2446 FIXME("iface %p, stub!\n", iface);
2447 return E_NOTIMPL;
2450 static const IOverlayVtbl overlay_vtbl =
2452 overlay_QueryInterface,
2453 overlay_AddRef,
2454 overlay_Release,
2455 overlay_GetPalette,
2456 overlay_SetPalette,
2457 overlay_GetDefaultColorKey,
2458 overlay_GetColorKey,
2459 overlay_SetColorKey,
2460 overlay_GetWindowHandle,
2461 overlay_GetClipList,
2462 overlay_GetVideoPosition,
2463 overlay_Advise,
2464 overlay_Unadvise,
2467 static HRESULT vmr_create(IUnknown *outer, IUnknown **out, const CLSID *clsid)
2469 struct quartz_vmr *object;
2470 HRESULT hr;
2472 if (!(object = calloc(1, sizeof(*object))))
2473 return E_OUTOFMEMORY;
2475 object->hD3d9 = LoadLibraryA("d3d9.dll");
2476 if (!object->hD3d9)
2478 WARN("Could not load d3d9.dll\n");
2479 free(object);
2480 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2483 strmbase_renderer_init(&object->renderer, outer, clsid, L"VMR Input0", &renderer_ops);
2484 object->IAMCertifiedOutputProtection_iface.lpVtbl = &IAMCertifiedOutputProtection_Vtbl;
2485 object->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
2486 object->IVMRFilterConfig_iface.lpVtbl = &VMR7_FilterConfig_Vtbl;
2487 object->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
2488 object->IVMRMixerBitmap9_iface.lpVtbl = &mixer_bitmap9_vtbl;
2489 object->IVMRMixerControl9_iface.lpVtbl = &mixer_control9_vtbl;
2490 object->IVMRMonitorConfig_iface.lpVtbl = &VMR7_MonitorConfig_Vtbl;
2491 object->IVMRMonitorConfig9_iface.lpVtbl = &VMR9_MonitorConfig_Vtbl;
2492 object->IVMRSurfaceAllocatorNotify_iface.lpVtbl = &VMR7_SurfaceAllocatorNotify_Vtbl;
2493 object->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &VMR9_SurfaceAllocatorNotify_Vtbl;
2494 object->IVMRWindowlessControl_iface.lpVtbl = &VMR7_WindowlessControl_Vtbl;
2495 object->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
2496 object->IOverlay_iface.lpVtbl = &overlay_vtbl;
2498 video_window_init(&object->window, &IVideoWindow_VTable,
2499 &object->renderer.filter, &object->renderer.sink.pin, &window_ops);
2501 if (FAILED(hr = video_window_create_window(&object->window)))
2503 video_window_cleanup(&object->window);
2504 strmbase_renderer_cleanup(&object->renderer);
2505 FreeLibrary(object->hD3d9);
2506 free(object);
2507 return hr;
2510 object->run_event = CreateEventW(NULL, TRUE, FALSE, NULL);
2512 object->mixing_prefs = MixerPref9_NoDecimation | MixerPref9_ARAdjustXorY
2513 | MixerPref9_BiLinearFiltering | MixerPref9_RenderTargetRGB;
2515 TRACE("Created VMR %p.\n", object);
2516 *out = &object->renderer.filter.IUnknown_inner;
2517 return S_OK;
2520 HRESULT vmr7_create(IUnknown *outer, IUnknown **out)
2522 return vmr_create(outer, out, &CLSID_VideoMixingRenderer);
2525 HRESULT vmr9_create(IUnknown *outer, IUnknown **out)
2527 return vmr_create(outer, out, &CLSID_VideoMixingRenderer9);
2531 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, void **ppv)
2533 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2535 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
2537 *ppv = NULL;
2539 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IVMRImagePresenter9))
2540 *ppv = &This->IVMRImagePresenter9_iface;
2541 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocator9))
2542 *ppv = &This->IVMRSurfaceAllocator9_iface;
2544 if (*ppv)
2546 IUnknown_AddRef((IUnknown *)(*ppv));
2547 return S_OK;
2550 FIXME("No interface for %s\n", debugstr_guid(riid));
2552 return E_NOINTERFACE;
2555 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
2557 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2558 ULONG refCount = InterlockedIncrement(&This->refCount);
2560 TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
2562 return refCount;
2565 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
2567 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2568 ULONG refCount = InterlockedDecrement(&This->refCount);
2570 TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
2572 if (!refCount)
2574 DWORD i;
2575 TRACE("Destroying\n");
2576 IDirect3D9_Release(This->d3d9_ptr);
2578 TRACE("Number of surfaces: %u\n", This->num_surfaces);
2579 for (i = 0; i < This->num_surfaces; ++i)
2581 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2582 TRACE("Releasing surface %p\n", surface);
2583 if (surface)
2584 IDirect3DSurface9_Release(surface);
2587 free(This->d3d9_surfaces);
2588 This->d3d9_surfaces = NULL;
2589 This->num_surfaces = 0;
2590 free(This);
2591 return 0;
2593 return refCount;
2596 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2598 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2600 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2602 return S_OK;
2605 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2607 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2609 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2611 return S_OK;
2614 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface,
2615 DWORD_PTR cookie, VMR9PresentationInfo *info)
2617 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2618 const struct quartz_vmr *filter = presenter->pVMR9;
2619 IDirect3DDevice9 *device = presenter->d3d9_dev;
2620 const RECT src = filter->window.src;
2621 IDirect3DSurface9 *backbuffer;
2622 RECT dst = filter->window.dst;
2623 HRESULT hr;
2625 TRACE("presenter %p, cookie %#Ix, info %p.\n", presenter, cookie, info);
2627 /* This might happen if we don't have active focus (eg on a different virtual desktop) */
2628 if (!device)
2629 return S_OK;
2631 if (FAILED(hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET,
2632 D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0)))
2633 ERR("Failed to clear, hr %#x.\n", hr);
2635 if (FAILED(hr = IDirect3DDevice9_BeginScene(device)))
2636 ERR("Failed to begin scene, hr %#x.\n", hr);
2638 if (FAILED(hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer)))
2640 ERR("Failed to get backbuffer, hr %#x.\n", hr);
2641 return hr;
2644 if (FAILED(hr = IDirect3DDevice9_StretchRect(device, info->lpSurf, NULL, backbuffer, NULL, D3DTEXF_POINT)))
2645 ERR("Failed to blit image, hr %#x.\n", hr);
2646 IDirect3DSurface9_Release(backbuffer);
2648 if (FAILED(hr = IDirect3DDevice9_EndScene(device)))
2649 ERR("Failed to end scene, hr %#x.\n", hr);
2651 if (filter->aspect_mode == VMR9ARMode_LetterBox)
2653 unsigned int src_width = src.right - src.left, src_height = src.bottom - src.top;
2654 unsigned int dst_width = dst.right - dst.left, dst_height = dst.bottom - dst.top;
2656 if (src_width * dst_height > dst_width * src_height)
2658 /* src is "wider" than dst. */
2659 unsigned int dst_center = (dst.top + dst.bottom) / 2;
2660 unsigned int scaled_height = src_height * dst_width / src_width;
2662 dst.top = dst_center - scaled_height / 2;
2663 dst.bottom = dst.top + scaled_height;
2665 else if (src_width * dst_height < dst_width * src_height)
2667 /* src is "taller" than dst. */
2668 unsigned int dst_center = (dst.left + dst.right) / 2;
2669 unsigned int scaled_width = src_width * dst_height / src_height;
2671 dst.left = dst_center - scaled_width / 2;
2672 dst.right = dst.left + scaled_width;
2676 if (FAILED(hr = IDirect3DDevice9_Present(device, &src, &dst, NULL, NULL)))
2677 ERR("Failed to present, hr %#x.\n", hr);
2679 return S_OK;
2682 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
2684 VMR9_ImagePresenter_QueryInterface,
2685 VMR9_ImagePresenter_AddRef,
2686 VMR9_ImagePresenter_Release,
2687 VMR9_ImagePresenter_StartPresenting,
2688 VMR9_ImagePresenter_StopPresenting,
2689 VMR9_ImagePresenter_PresentImage
2692 static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocator9 *iface, REFIID iid, void **out)
2694 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2695 return IVMRImagePresenter9_QueryInterface(&presenter->IVMRImagePresenter9_iface, iid, out);
2698 static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocator9 *iface)
2700 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2701 return IVMRImagePresenter9_AddRef(&presenter->IVMRImagePresenter9_iface);
2704 static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocator9 *iface)
2706 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2707 return IVMRImagePresenter9_Release(&presenter->IVMRImagePresenter9_iface);
2710 static HRESULT VMR9_SurfaceAllocator_SetAllocationSettings(struct default_presenter *This, VMR9AllocationInfo *allocinfo)
2712 D3DCAPS9 caps;
2713 UINT width, height;
2714 HRESULT hr;
2716 if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface))
2717 /* Only needed for texture surfaces */
2718 return S_OK;
2720 hr = IDirect3DDevice9_GetDeviceCaps(This->d3d9_dev, &caps);
2721 if (FAILED(hr))
2722 return hr;
2724 if (!(caps.TextureCaps & D3DPTEXTURECAPS_POW2) || (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY))
2726 width = allocinfo->dwWidth;
2727 height = allocinfo->dwHeight;
2729 else
2731 width = height = 1;
2732 while (width < allocinfo->dwWidth)
2733 width *= 2;
2735 while (height < allocinfo->dwHeight)
2736 height *= 2;
2737 FIXME("NPOW2 support missing, not using proper surfaces!\n");
2740 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
2742 if (height > width)
2743 width = height;
2744 else
2745 height = width;
2746 FIXME("Square texture support required..\n");
2749 allocinfo->dwHeight = height;
2750 allocinfo->dwWidth = width;
2752 return hr;
2755 static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
2757 UINT d3d9_adapter;
2758 HMONITOR mon;
2760 mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
2761 if (!mon)
2762 d3d9_adapter = 0;
2763 else
2765 for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
2767 if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
2768 break;
2770 if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
2771 d3d9_adapter = 0;
2773 if (mon_out)
2774 *mon_out = mon;
2775 return d3d9_adapter;
2778 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocator9 *iface,
2779 DWORD_PTR cookie, VMR9AllocationInfo *info, DWORD *numbuffers)
2781 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
2782 D3DPRESENT_PARAMETERS d3dpp;
2783 IDirect3DDevice9 *device;
2784 DWORD d3d9_adapter;
2785 D3DCAPS9 caps;
2786 HWND window;
2787 HRESULT hr;
2789 TRACE("presenter %p, cookie %#Ix, info %p, numbuffers %p.\n", This, cookie, info, numbuffers);
2791 This->info = *info;
2793 if (This->pVMR9->mode == VMR9Mode_Windowed)
2794 window = This->pVMR9->window.hwnd;
2795 else
2796 window = This->pVMR9->clipping_window;
2798 /* Obtain a monitor and d3d9 device */
2799 d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, window, &This->hMon);
2801 /* Now try to create the d3d9 device */
2802 ZeroMemory(&d3dpp, sizeof(d3dpp));
2803 d3dpp.Windowed = TRUE;
2804 d3dpp.hDeviceWindow = window;
2805 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
2806 d3dpp.BackBufferWidth = info->dwWidth;
2807 d3dpp.BackBufferHeight = info->dwHeight;
2809 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL,
2810 NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2811 if (FAILED(hr))
2813 ERR("Could not create device: %08x\n", hr);
2814 return hr;
2817 IDirect3DDevice9_GetDeviceCaps(device, &caps);
2818 if (!(caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES))
2820 WARN("Device does not support blitting from textures.\n");
2821 IDirect3DDevice9_Release(device);
2822 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2825 This->d3d9_dev = device;
2826 IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2828 if (!(This->d3d9_surfaces = calloc(*numbuffers, sizeof(IDirect3DSurface9 *))))
2829 return E_OUTOFMEMORY;
2831 hr = VMR9_SurfaceAllocator_SetAllocationSettings(This, info);
2832 if (FAILED(hr))
2833 ERR("Setting allocation settings failed: %08x\n", hr);
2835 if (SUCCEEDED(hr))
2837 hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, info, numbuffers, This->d3d9_surfaces);
2838 if (FAILED(hr))
2839 ERR("Allocating surfaces failed: %08x\n", hr);
2842 if (FAILED(hr))
2844 IVMRSurfaceAllocator9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
2845 return hr;
2848 This->num_surfaces = *numbuffers;
2850 return S_OK;
2853 static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocator9 *iface, DWORD_PTR cookie)
2855 TRACE("iface %p, cookie %#lx.\n", iface, cookie);
2857 return S_OK;
2860 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocator9 *iface,
2861 DWORD_PTR cookie, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
2863 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
2865 /* Update everything first, this is needed because the surface might be destroyed in the reset */
2866 if (!This->d3d9_dev)
2868 TRACE("Device has left me!\n");
2869 return E_FAIL;
2872 if (surfaceindex >= This->num_surfaces)
2874 ERR("surfaceindex is greater than num_surfaces\n");
2875 return E_FAIL;
2877 *surface = This->d3d9_surfaces[surfaceindex];
2878 IDirect3DSurface9_AddRef(*surface);
2880 return S_OK;
2883 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocator9 *iface,
2884 IVMRSurfaceAllocatorNotify9 *notify)
2886 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2888 TRACE("presenter %p, notify %p.\n", presenter, notify);
2890 /* No AddRef taken here or the base VMR9 filter would never be destroyed */
2891 presenter->SurfaceAllocatorNotify = notify;
2892 return S_OK;
2895 static const IVMRSurfaceAllocator9Vtbl VMR9_SurfaceAllocator =
2897 VMR9_SurfaceAllocator_QueryInterface,
2898 VMR9_SurfaceAllocator_AddRef,
2899 VMR9_SurfaceAllocator_Release,
2900 VMR9_SurfaceAllocator_InitializeDevice,
2901 VMR9_SurfaceAllocator_TerminateDevice,
2902 VMR9_SurfaceAllocator_GetSurface,
2903 VMR9_SurfaceAllocator_AdviseNotify,
2906 static IDirect3D9 *init_d3d9(HMODULE d3d9_handle)
2908 IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion);
2910 d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
2911 if (!d3d9_create) return NULL;
2913 return d3d9_create(D3D_SDK_VERSION);
2916 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(struct quartz_vmr *parent, LPVOID * ppv)
2918 struct default_presenter *object;
2919 HRESULT hr = S_OK;
2920 int i;
2922 if (!(object = calloc(1, sizeof(*object))))
2923 return E_OUTOFMEMORY;
2925 object->d3d9_ptr = init_d3d9(parent->hD3d9);
2926 if (!object->d3d9_ptr)
2928 WARN("Could not initialize d3d9.dll\n");
2929 free(object);
2930 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2933 i = 0;
2936 D3DDISPLAYMODE mode;
2938 hr = IDirect3D9_EnumAdapterModes(object->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode);
2939 if (hr == D3DERR_INVALIDCALL) break; /* out of adapters */
2940 } while (FAILED(hr));
2941 if (FAILED(hr))
2942 ERR("HR: %08x\n", hr);
2943 if (hr == D3DERR_NOTAVAILABLE)
2945 ERR("Format not supported\n");
2946 IDirect3D9_Release(object->d3d9_ptr);
2947 free(object);
2948 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2951 object->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
2952 object->IVMRSurfaceAllocator9_iface.lpVtbl = &VMR9_SurfaceAllocator;
2954 object->refCount = 1;
2955 object->pVMR9 = parent;
2957 TRACE("Created default presenter %p.\n", object);
2958 *ppv = &object->IVMRImagePresenter9_iface;
2959 return S_OK;