mfmediaengine: Remove unnecessary import library.
[wine.git] / dlls / quartz / vmr9.c
blob4bde811c6d782a774ecd292e440805ec26b1fe94
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 IVMRAspectRatioControl9 IVMRAspectRatioControl9_iface;
64 IVMRFilterConfig IVMRFilterConfig_iface;
65 IVMRFilterConfig9 IVMRFilterConfig9_iface;
66 IVMRMixerBitmap9 IVMRMixerBitmap9_iface;
67 IVMRMixerControl9 IVMRMixerControl9_iface;
68 IVMRMonitorConfig IVMRMonitorConfig_iface;
69 IVMRMonitorConfig9 IVMRMonitorConfig9_iface;
70 IVMRSurfaceAllocatorNotify IVMRSurfaceAllocatorNotify_iface;
71 IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface;
72 IVMRWindowlessControl IVMRWindowlessControl_iface;
73 IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
75 /* Devil May Cry 3 releases the last IBaseFilter reference while still
76 * holding an IVMRSurfaceAllocatorNotify9 reference, and depends on
77 * IVMRSurfaceAllocator9::TerminateDevice() being called as a result.
78 * Native uses a separate reference count for IVMRSurfaceAllocatorNotify9. */
79 LONG IVMRSurfaceAllocatorNotify9_refcount;
81 IOverlay IOverlay_iface;
83 IVMRSurfaceAllocator9 *allocator;
84 IVMRImagePresenter9 *presenter;
86 DWORD stream_count;
87 DWORD mixing_prefs;
90 * The Video Mixing Renderer supports 3 modes, renderless, windowless and windowed
91 * What I do is implement windowless as a special case of renderless, and then
92 * windowed also as a special case of windowless. This is probably the easiest way.
94 VMR9Mode mode;
95 BITMAPINFOHEADER bmiheader;
97 HMODULE hD3d9;
99 /* Presentation related members */
100 IDirect3DDevice9 *allocator_d3d9_dev;
101 IDirect3DSurface9 **surfaces;
102 DWORD num_surfaces;
103 DWORD cur_surface;
104 DWORD_PTR cookie;
106 HWND clipping_window;
108 LONG VideoWidth;
109 LONG VideoHeight;
110 VMR9AspectRatioMode aspect_mode;
113 static inline BOOL is_vmr9(const struct quartz_vmr *filter)
115 return IsEqualGUID(&filter->renderer.filter.clsid, &CLSID_VideoMixingRenderer9);
118 static inline struct quartz_vmr *impl_from_video_window(struct video_window *iface)
120 return CONTAINING_RECORD(iface, struct quartz_vmr, window);
123 static inline struct quartz_vmr *impl_from_IAMCertifiedOutputProtection(IAMCertifiedOutputProtection *iface)
125 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMCertifiedOutputProtection_iface);
128 static inline struct quartz_vmr *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
130 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMFilterMiscFlags_iface);
133 static inline struct quartz_vmr *impl_from_IVMRFilterConfig(IVMRFilterConfig *iface)
135 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig_iface);
138 static inline struct quartz_vmr *impl_from_IVMRFilterConfig9(IVMRFilterConfig9 *iface)
140 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig9_iface);
143 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig(IVMRMonitorConfig *iface)
145 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig_iface);
148 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig9(IVMRMonitorConfig9 *iface)
150 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig9_iface);
153 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify(IVMRSurfaceAllocatorNotify *iface)
155 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify_iface);
158 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify9(IVMRSurfaceAllocatorNotify9 *iface)
160 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify9_iface);
163 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl(IVMRWindowlessControl *iface)
165 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl_iface);
168 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl9(IVMRWindowlessControl9 *iface)
170 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl9_iface);
173 struct default_presenter
175 IVMRImagePresenter9 IVMRImagePresenter9_iface;
176 IVMRSurfaceAllocator9 IVMRSurfaceAllocator9_iface;
178 LONG refCount;
180 IDirect3DDevice9 *d3d9_dev;
181 IDirect3D9 *d3d9_ptr;
182 IDirect3DSurface9 **d3d9_surfaces;
183 HMONITOR hMon;
184 DWORD num_surfaces;
186 VMR9AllocationInfo info;
188 struct quartz_vmr* pVMR9;
189 IVMRSurfaceAllocatorNotify9 *SurfaceAllocatorNotify;
192 static inline struct default_presenter *impl_from_IVMRImagePresenter9(IVMRImagePresenter9 *iface)
194 return CONTAINING_RECORD(iface, struct default_presenter, IVMRImagePresenter9_iface);
197 static inline struct default_presenter *impl_from_IVMRSurfaceAllocator9(IVMRSurfaceAllocator9 *iface)
199 return CONTAINING_RECORD(iface, struct default_presenter, IVMRSurfaceAllocator9_iface);
202 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(struct quartz_vmr *parent, LPVOID * ppv);
204 static inline struct quartz_vmr *impl_from_IBaseFilter(IBaseFilter *iface)
206 return CONTAINING_RECORD(iface, struct quartz_vmr, renderer.filter.IBaseFilter_iface);
209 static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample)
211 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
212 unsigned int data_size, width, depth, src_pitch;
213 const BITMAPINFOHEADER *bitmap_header;
214 REFERENCE_TIME start_time, end_time;
215 VMR9PresentationInfo info = {};
216 D3DLOCKED_RECT locked_rect;
217 BYTE *data = NULL;
218 HRESULT hr;
219 int height;
221 TRACE("filter %p, sample %p.\n", filter, sample);
223 /* It is possible that there is no device at this point */
225 if (!filter->allocator || !filter->presenter)
227 ERR("NO PRESENTER!!\n");
228 return S_FALSE;
231 info.dwFlags = VMR9Sample_SrcDstRectsValid;
233 if (SUCCEEDED(hr = IMediaSample_GetTime(sample, &start_time, &end_time)))
234 info.dwFlags |= VMR9Sample_TimeValid;
236 if (IMediaSample_IsDiscontinuity(sample) == S_OK)
237 info.dwFlags |= VMR9Sample_Discontinuity;
239 if (IMediaSample_IsPreroll(sample) == S_OK)
240 info.dwFlags |= VMR9Sample_Preroll;
242 if (IMediaSample_IsSyncPoint(sample) == S_OK)
243 info.dwFlags |= VMR9Sample_SyncPoint;
245 if (FAILED(hr = IMediaSample_GetPointer(sample, &data)))
247 ERR("Failed to get pointer to sample data, hr %#x.\n", hr);
248 return hr;
250 data_size = IMediaSample_GetActualDataLength(sample);
252 bitmap_header = get_bitmap_header(&filter->renderer.sink.pin.mt);
253 width = bitmap_header->biWidth;
254 height = bitmap_header->biHeight;
255 depth = bitmap_header->biBitCount;
256 if (bitmap_header->biCompression == mmioFOURCC('N','V','1','2')
257 || bitmap_header->biCompression == mmioFOURCC('Y','V','1','2'))
258 src_pitch = width;
259 else /* packed YUV (UYVY or YUY2) or RGB */
260 src_pitch = ((width * depth / 8) + 3) & ~3;
262 info.rtStart = start_time;
263 info.rtEnd = end_time;
264 info.szAspectRatio.cx = width;
265 info.szAspectRatio.cy = height;
266 info.lpSurf = filter->surfaces[(++filter->cur_surface) % filter->num_surfaces];
268 if (FAILED(hr = IDirect3DSurface9_LockRect(info.lpSurf, &locked_rect, NULL, D3DLOCK_DISCARD)))
270 ERR("Failed to lock surface, hr %#x.\n", hr);
271 return hr;
274 if (height > 0 && bitmap_header->biCompression == BI_RGB)
276 BYTE *dst = (BYTE *)locked_rect.pBits + (height * locked_rect.Pitch);
277 const BYTE *src = data;
279 TRACE("Inverting image.\n");
281 while (height--)
283 dst -= locked_rect.Pitch;
284 memcpy(dst, src, width * depth / 8);
285 src += src_pitch;
288 else if (locked_rect.Pitch != src_pitch)
290 BYTE *dst = locked_rect.pBits;
291 const BYTE *src = data;
293 height = abs(height);
295 TRACE("Source pitch %u does not match dest pitch %u; copying manually.\n",
296 src_pitch, locked_rect.Pitch);
298 while (height--)
300 memcpy(dst, src, width * depth / 8);
301 src += src_pitch;
302 dst += locked_rect.Pitch;
305 else
307 memcpy(locked_rect.pBits, data, data_size);
310 IDirect3DSurface9_UnlockRect(info.lpSurf);
312 return IVMRImagePresenter9_PresentImage(filter->presenter, filter->cookie, &info);
315 static HRESULT vmr_query_accept(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
317 if (!IsEqualIID(&mt->majortype, &MEDIATYPE_Video) || !mt->pbFormat)
318 return S_FALSE;
320 if (!IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo)
321 && !IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo2))
322 return S_FALSE;
324 return S_OK;
327 static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *info, DWORD count)
329 HRESULT hr;
330 DWORD i;
332 if (FAILED(hr = IVMRSurfaceAllocator9_InitializeDevice(filter->allocator,
333 filter->cookie, info, &count)))
335 WARN("Failed to initialize device (flags %#x), hr %#x.\n", info->dwFlags, hr);
336 return hr;
339 for (i = 0; i < count; ++i)
341 if (FAILED(hr = IVMRSurfaceAllocator9_GetSurface(filter->allocator,
342 filter->cookie, i, 0, &filter->surfaces[i])))
344 ERR("Failed to get surface %u, hr %#x.\n", i, hr);
345 while (i--)
346 IDirect3DSurface9_Release(filter->surfaces[i]);
347 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
348 return hr;
352 return hr;
355 static HRESULT allocate_surfaces(struct quartz_vmr *filter, const AM_MEDIA_TYPE *mt)
357 VMR9AllocationInfo info = {};
358 HRESULT hr = E_FAIL;
359 DWORD count = 1;
360 unsigned int i;
362 static const struct
364 const GUID *subtype;
365 D3DFORMAT format;
366 DWORD flags;
368 formats[] =
370 {&MEDIASUBTYPE_ARGB1555, D3DFMT_A1R5G5B5, VMR9AllocFlag_TextureSurface},
371 {&MEDIASUBTYPE_ARGB32, D3DFMT_A8R8G8B8, VMR9AllocFlag_TextureSurface},
372 {&MEDIASUBTYPE_ARGB4444, D3DFMT_A4R4G4B4, VMR9AllocFlag_TextureSurface},
374 {&MEDIASUBTYPE_RGB24, D3DFMT_R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
375 {&MEDIASUBTYPE_RGB32, D3DFMT_X8R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
376 {&MEDIASUBTYPE_RGB555, D3DFMT_X1R5G5B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
377 {&MEDIASUBTYPE_RGB565, D3DFMT_R5G6B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
379 {&MEDIASUBTYPE_NV12, MAKEFOURCC('N','V','1','2'), VMR9AllocFlag_OffscreenSurface},
380 {&MEDIASUBTYPE_UYVY, D3DFMT_UYVY, VMR9AllocFlag_OffscreenSurface},
381 {&MEDIASUBTYPE_YUY2, D3DFMT_YUY2, VMR9AllocFlag_OffscreenSurface},
382 {&MEDIASUBTYPE_YV12, MAKEFOURCC('Y','V','1','2'), VMR9AllocFlag_OffscreenSurface},
385 TRACE("Initializing in mode %u, our window %p, clipping window %p.\n",
386 filter->mode, filter->window.hwnd, filter->clipping_window);
388 if (filter->mode == VMR9Mode_Windowless && !filter->clipping_window)
389 return S_OK;
391 info.Pool = D3DPOOL_DEFAULT;
392 info.MinBuffers = count;
393 info.dwWidth = info.szAspectRatio.cx = info.szNativeSize.cx = filter->bmiheader.biWidth;
394 info.dwHeight = info.szAspectRatio.cy = info.szNativeSize.cy = filter->bmiheader.biHeight;
396 if (!(filter->surfaces = calloc(count, sizeof(IDirect3DSurface9 *))))
397 return E_OUTOFMEMORY;
398 filter->num_surfaces = count;
399 filter->cur_surface = 0;
401 if (!is_vmr9(filter))
403 switch (filter->bmiheader.biCompression)
405 case BI_RGB:
406 switch (filter->bmiheader.biBitCount)
408 case 24: info.Format = D3DFMT_R8G8B8; break;
409 case 32: info.Format = D3DFMT_X8R8G8B8; break;
410 default:
411 FIXME("Unhandled bit depth %u.\n", filter->bmiheader.biBitCount);
412 free(filter->surfaces);
413 return VFW_E_TYPE_NOT_ACCEPTED;
416 info.dwFlags = VMR9AllocFlag_TextureSurface;
417 break;
419 case mmioFOURCC('N','V','1','2'):
420 case mmioFOURCC('U','Y','V','Y'):
421 case mmioFOURCC('Y','U','Y','2'):
422 case mmioFOURCC('Y','V','1','2'):
423 info.Format = filter->bmiheader.biCompression;
424 info.dwFlags = VMR9AllocFlag_OffscreenSurface;
425 break;
427 default:
428 WARN("Unhandled video compression %#x.\n", filter->bmiheader.biCompression);
429 free(filter->surfaces);
430 return VFW_E_TYPE_NOT_ACCEPTED;
432 if (FAILED(hr = initialize_device(filter, &info, count)))
433 free(filter->surfaces);
434 return hr;
437 for (i = 0; i < ARRAY_SIZE(formats); ++i)
439 if (IsEqualGUID(&mt->subtype, formats[i].subtype))
441 info.Format = formats[i].format;
443 if (formats[i].flags & VMR9AllocFlag_TextureSurface)
445 info.dwFlags = VMR9AllocFlag_TextureSurface;
446 if (SUCCEEDED(hr = initialize_device(filter, &info, count)))
447 return hr;
450 if (formats[i].flags & VMR9AllocFlag_OffscreenSurface)
452 info.dwFlags = VMR9AllocFlag_OffscreenSurface;
453 if (SUCCEEDED(hr = initialize_device(filter, &info, count)))
454 return hr;
459 free(filter->surfaces);
460 return VFW_E_TYPE_NOT_ACCEPTED;
463 static void vmr_init_stream(struct strmbase_renderer *iface)
465 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
467 if (filter->window.hwnd && filter->window.AutoShow)
468 ShowWindow(filter->window.hwnd, SW_SHOW);
471 static void vmr_start_stream(struct strmbase_renderer *iface)
473 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
475 IVMRImagePresenter9_StartPresenting(filter->presenter, filter->cookie);
478 static void vmr_stop_stream(struct strmbase_renderer *iface)
480 struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
482 TRACE("(%p)\n", This);
484 if (This->renderer.filter.state == State_Running)
485 IVMRImagePresenter9_StopPresenting(This->presenter, This->cookie);
488 static HRESULT vmr_connect(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
490 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
491 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(mt);
492 HWND window = filter->window.hwnd;
493 HRESULT hr;
494 RECT rect;
496 filter->bmiheader = *bitmap_header;
497 filter->VideoWidth = bitmap_header->biWidth;
498 filter->VideoHeight = bitmap_header->biHeight;
499 SetRect(&rect, 0, 0, filter->VideoWidth, filter->VideoHeight);
500 filter->window.src = rect;
502 AdjustWindowRectEx(&rect, GetWindowLongW(window, GWL_STYLE), FALSE,
503 GetWindowLongW(window, GWL_EXSTYLE));
504 SetWindowPos(window, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
505 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
506 GetClientRect(window, &filter->window.dst);
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 void vmr_disconnect(struct strmbase_renderer *This)
517 struct quartz_vmr *filter = impl_from_IBaseFilter(&This->filter.IBaseFilter_iface);
518 DWORD i;
520 if (filter->mode && filter->allocator && filter->presenter)
522 for (i = 0; i < filter->num_surfaces; ++i)
523 IDirect3DSurface9_Release(filter->surfaces[i]);
524 free(filter->surfaces);
526 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
527 filter->num_surfaces = 0;
531 static void vmr_destroy(struct strmbase_renderer *iface)
533 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
535 video_window_cleanup(&filter->window);
537 /* Devil May Cry 3 releases the IVMRSurfaceAllocatorNotify9 interface from
538 * TerminateDevice(). Artificially increase the reference count so that we
539 * don't free the filter yet. */
540 InterlockedIncrement(&filter->renderer.filter.refcount);
542 if (filter->allocator)
544 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
545 IVMRSurfaceAllocator9_Release(filter->allocator);
547 if (filter->presenter)
548 IVMRImagePresenter9_Release(filter->presenter);
550 filter->num_surfaces = 0;
551 if (filter->allocator_d3d9_dev)
553 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
554 filter->allocator_d3d9_dev = NULL;
557 FreeLibrary(filter->hD3d9);
558 strmbase_renderer_cleanup(&filter->renderer);
559 if (!filter->IVMRSurfaceAllocatorNotify9_refcount)
560 free(filter);
563 static HRESULT vmr_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
565 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
567 if (IsEqualGUID(iid, &IID_IVideoWindow))
568 *out = &filter->window.IVideoWindow_iface;
569 else if (IsEqualGUID(iid, &IID_IBasicVideo))
570 *out = &filter->window.IBasicVideo_iface;
571 else if (IsEqualGUID(iid, &IID_IAMCertifiedOutputProtection))
572 *out = &filter->IAMCertifiedOutputProtection_iface;
573 else if (IsEqualGUID(iid, &IID_IAMFilterMiscFlags))
574 *out = &filter->IAMFilterMiscFlags_iface;
575 else if (IsEqualGUID(iid, &IID_IVMRAspectRatioControl9) && is_vmr9(filter))
576 *out = &filter->IVMRAspectRatioControl9_iface;
577 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig) && !is_vmr9(filter))
578 *out = &filter->IVMRFilterConfig_iface;
579 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig9) && is_vmr9(filter))
580 *out = &filter->IVMRFilterConfig9_iface;
581 else if (IsEqualGUID(iid, &IID_IVMRMixerBitmap9) && is_vmr9(filter))
582 *out = &filter->IVMRMixerBitmap9_iface;
583 else if (IsEqualGUID(iid, &IID_IVMRMixerControl9) && is_vmr9(filter) && filter->stream_count)
584 *out = &filter->IVMRMixerControl9_iface;
585 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig) && !is_vmr9(filter))
586 *out = &filter->IVMRMonitorConfig_iface;
587 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig9)
588 && filter->mode != VMR9Mode_Renderless && is_vmr9(filter))
589 *out = &filter->IVMRMonitorConfig9_iface;
590 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify)
591 && filter->mode == (VMR9Mode)VMRMode_Renderless && !is_vmr9(filter))
592 *out = &filter->IVMRSurfaceAllocatorNotify_iface;
593 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify9)
594 && filter->mode == VMR9Mode_Renderless && is_vmr9(filter))
595 *out = &filter->IVMRSurfaceAllocatorNotify9_iface;
596 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl)
597 && filter->mode == (VMR9Mode)VMRMode_Windowless && !is_vmr9(filter))
598 *out = &filter->IVMRWindowlessControl_iface;
599 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl9)
600 && filter->mode == VMR9Mode_Windowless && is_vmr9(filter))
601 *out = &filter->IVMRWindowlessControl9_iface;
602 else
603 return E_NOINTERFACE;
605 IUnknown_AddRef((IUnknown *)*out);
606 return S_OK;
609 static HRESULT vmr_pin_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
611 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
613 if (IsEqualGUID(iid, &IID_IOverlay))
614 *out = &filter->IOverlay_iface;
615 else
616 return E_NOINTERFACE;
618 IUnknown_AddRef((IUnknown *)*out);
619 return S_OK;
622 static const struct strmbase_renderer_ops renderer_ops =
624 .renderer_query_accept = vmr_query_accept,
625 .renderer_render = vmr_render,
626 .renderer_init_stream = vmr_init_stream,
627 .renderer_start_stream = vmr_start_stream,
628 .renderer_stop_stream = vmr_stop_stream,
629 .renderer_connect = vmr_connect,
630 .renderer_disconnect = vmr_disconnect,
631 .renderer_destroy = vmr_destroy,
632 .renderer_query_interface = vmr_query_interface,
633 .renderer_pin_query_interface = vmr_pin_query_interface,
636 static RECT vmr_get_default_rect(struct video_window *This)
638 struct quartz_vmr *pVMR9 = impl_from_video_window(This);
639 static RECT defRect;
641 SetRect(&defRect, 0, 0, pVMR9->VideoWidth, pVMR9->VideoHeight);
643 return defRect;
646 static HRESULT vmr_get_current_image(struct video_window *iface, LONG *size, LONG *image)
648 struct quartz_vmr *filter = impl_from_video_window(iface);
649 IDirect3DSurface9 *rt = NULL, *surface = NULL;
650 D3DLOCKED_RECT locked_rect;
651 IDirect3DDevice9 *device;
652 unsigned int row_size;
653 BITMAPINFOHEADER bih;
654 LONG i, size_left;
655 char *dst;
656 HRESULT hr;
658 EnterCriticalSection(&filter->renderer.filter.stream_cs);
659 device = filter->allocator_d3d9_dev;
661 bih = *get_bitmap_header(&filter->renderer.sink.pin.mt);
662 bih.biSizeImage = bih.biWidth * bih.biHeight * bih.biBitCount / 8;
664 if (!image)
666 *size = sizeof(BITMAPINFOHEADER) + bih.biSizeImage;
667 LeaveCriticalSection(&filter->renderer.filter.stream_cs);
668 return S_OK;
671 if (FAILED(hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt)))
672 goto out;
674 if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, bih.biWidth,
675 bih.biHeight, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL)))
676 goto out;
678 if (FAILED(hr = IDirect3DDevice9_GetRenderTargetData(device, rt, surface)))
679 goto out;
681 if (FAILED(hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_READONLY)))
682 goto out;
684 size_left = *size;
685 memcpy(image, &bih, min(size_left, sizeof(BITMAPINFOHEADER)));
686 size_left -= sizeof(BITMAPINFOHEADER);
688 dst = (char *)image + sizeof(BITMAPINFOHEADER);
689 row_size = bih.biWidth * bih.biBitCount / 8;
691 for (i = 0; i < bih.biHeight && size_left > 0; ++i)
693 memcpy(dst, (char *)locked_rect.pBits + (i * locked_rect.Pitch), min(row_size, size_left));
694 dst += row_size;
695 size_left -= row_size;
698 IDirect3DSurface9_UnlockRect(surface);
700 out:
701 if (surface) IDirect3DSurface9_Release(surface);
702 if (rt) IDirect3DSurface9_Release(rt);
703 LeaveCriticalSection(&filter->renderer.filter.stream_cs);
704 return hr;
707 static const struct video_window_ops window_ops =
709 .get_default_rect = vmr_get_default_rect,
710 .get_current_image = vmr_get_current_image,
713 static const IVideoWindowVtbl IVideoWindow_VTable =
715 BaseControlWindowImpl_QueryInterface,
716 BaseControlWindowImpl_AddRef,
717 BaseControlWindowImpl_Release,
718 BaseControlWindowImpl_GetTypeInfoCount,
719 BaseControlWindowImpl_GetTypeInfo,
720 BaseControlWindowImpl_GetIDsOfNames,
721 BaseControlWindowImpl_Invoke,
722 BaseControlWindowImpl_put_Caption,
723 BaseControlWindowImpl_get_Caption,
724 BaseControlWindowImpl_put_WindowStyle,
725 BaseControlWindowImpl_get_WindowStyle,
726 BaseControlWindowImpl_put_WindowStyleEx,
727 BaseControlWindowImpl_get_WindowStyleEx,
728 BaseControlWindowImpl_put_AutoShow,
729 BaseControlWindowImpl_get_AutoShow,
730 BaseControlWindowImpl_put_WindowState,
731 BaseControlWindowImpl_get_WindowState,
732 BaseControlWindowImpl_put_BackgroundPalette,
733 BaseControlWindowImpl_get_BackgroundPalette,
734 BaseControlWindowImpl_put_Visible,
735 BaseControlWindowImpl_get_Visible,
736 BaseControlWindowImpl_put_Left,
737 BaseControlWindowImpl_get_Left,
738 BaseControlWindowImpl_put_Width,
739 BaseControlWindowImpl_get_Width,
740 BaseControlWindowImpl_put_Top,
741 BaseControlWindowImpl_get_Top,
742 BaseControlWindowImpl_put_Height,
743 BaseControlWindowImpl_get_Height,
744 BaseControlWindowImpl_put_Owner,
745 BaseControlWindowImpl_get_Owner,
746 BaseControlWindowImpl_put_MessageDrain,
747 BaseControlWindowImpl_get_MessageDrain,
748 BaseControlWindowImpl_get_BorderColor,
749 BaseControlWindowImpl_put_BorderColor,
750 BaseControlWindowImpl_get_FullScreenMode,
751 BaseControlWindowImpl_put_FullScreenMode,
752 BaseControlWindowImpl_SetWindowForeground,
753 BaseControlWindowImpl_NotifyOwnerMessage,
754 BaseControlWindowImpl_SetWindowPosition,
755 BaseControlWindowImpl_GetWindowPosition,
756 BaseControlWindowImpl_GetMinIdealImageSize,
757 BaseControlWindowImpl_GetMaxIdealImageSize,
758 BaseControlWindowImpl_GetRestorePosition,
759 BaseControlWindowImpl_HideCursor,
760 BaseControlWindowImpl_IsCursorHidden
763 static HRESULT WINAPI AMCertifiedOutputProtection_QueryInterface(IAMCertifiedOutputProtection *iface,
764 REFIID riid, void **ppv)
766 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
767 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
770 static ULONG WINAPI AMCertifiedOutputProtection_AddRef(IAMCertifiedOutputProtection *iface)
772 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
773 return IUnknown_AddRef(This->renderer.filter.outer_unk);
776 static ULONG WINAPI AMCertifiedOutputProtection_Release(IAMCertifiedOutputProtection *iface)
778 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
779 return IUnknown_Release(This->renderer.filter.outer_unk);
782 static HRESULT WINAPI AMCertifiedOutputProtection_KeyExchange(IAMCertifiedOutputProtection *iface,
783 GUID* pRandom, BYTE** VarLenCertGH,
784 DWORD* pdwLengthCertGH)
786 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
788 FIXME("(%p/%p)->(%p, %p, %p) stub\n", iface, This, pRandom, VarLenCertGH, pdwLengthCertGH);
789 return VFW_E_NO_COPP_HW;
792 static HRESULT WINAPI AMCertifiedOutputProtection_SessionSequenceStart(IAMCertifiedOutputProtection *iface,
793 AMCOPPSignature* pSig)
795 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
797 FIXME("(%p/%p)->(%p) stub\n", iface, This, pSig);
798 return VFW_E_NO_COPP_HW;
801 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionCommand(IAMCertifiedOutputProtection *iface,
802 const AMCOPPCommand* cmd)
804 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
806 FIXME("(%p/%p)->(%p) stub\n", iface, This, cmd);
807 return VFW_E_NO_COPP_HW;
810 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionStatus(IAMCertifiedOutputProtection *iface,
811 const AMCOPPStatusInput* pStatusInput,
812 AMCOPPStatusOutput* pStatusOutput)
814 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
816 FIXME("(%p/%p)->(%p, %p) stub\n", iface, This, pStatusInput, pStatusOutput);
817 return VFW_E_NO_COPP_HW;
820 static const IAMCertifiedOutputProtectionVtbl IAMCertifiedOutputProtection_Vtbl =
822 AMCertifiedOutputProtection_QueryInterface,
823 AMCertifiedOutputProtection_AddRef,
824 AMCertifiedOutputProtection_Release,
825 AMCertifiedOutputProtection_KeyExchange,
826 AMCertifiedOutputProtection_SessionSequenceStart,
827 AMCertifiedOutputProtection_ProtectionCommand,
828 AMCertifiedOutputProtection_ProtectionStatus
831 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
832 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
833 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
836 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
837 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
838 return IUnknown_AddRef(This->renderer.filter.outer_unk);
841 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
842 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
843 return IUnknown_Release(This->renderer.filter.outer_unk);
846 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
847 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
850 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
851 AMFilterMiscFlags_QueryInterface,
852 AMFilterMiscFlags_AddRef,
853 AMFilterMiscFlags_Release,
854 AMFilterMiscFlags_GetMiscFlags
857 static HRESULT WINAPI VMR7FilterConfig_QueryInterface(IVMRFilterConfig *iface, REFIID riid,
858 void** ppv)
860 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
861 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
864 static ULONG WINAPI VMR7FilterConfig_AddRef(IVMRFilterConfig *iface)
866 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
867 return IUnknown_AddRef(This->renderer.filter.outer_unk);
870 static ULONG WINAPI VMR7FilterConfig_Release(IVMRFilterConfig *iface)
872 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
873 return IUnknown_Release(This->renderer.filter.outer_unk);
876 static HRESULT WINAPI VMR7FilterConfig_SetImageCompositor(IVMRFilterConfig *iface,
877 IVMRImageCompositor *compositor)
879 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
881 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
882 return E_NOTIMPL;
885 static HRESULT WINAPI VMR7FilterConfig_SetNumberOfStreams(IVMRFilterConfig *iface, DWORD max)
887 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
889 FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
890 return E_NOTIMPL;
893 static HRESULT WINAPI VMR7FilterConfig_GetNumberOfStreams(IVMRFilterConfig *iface, DWORD *max)
895 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
897 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
898 return E_NOTIMPL;
901 static HRESULT WINAPI VMR7FilterConfig_SetRenderingPrefs(IVMRFilterConfig *iface, DWORD renderflags)
903 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
905 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
906 return E_NOTIMPL;
909 static HRESULT WINAPI VMR7FilterConfig_GetRenderingPrefs(IVMRFilterConfig *iface, DWORD *renderflags)
911 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
913 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
914 return E_NOTIMPL;
917 static HRESULT WINAPI VMR7FilterConfig_SetRenderingMode(IVMRFilterConfig *iface, DWORD mode)
919 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
921 TRACE("iface %p, mode %#x.\n", iface, mode);
923 return IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, mode);
926 static HRESULT WINAPI VMR7FilterConfig_GetRenderingMode(IVMRFilterConfig *iface, DWORD *mode)
928 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
930 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
931 if (!mode) return E_POINTER;
933 if (This->mode)
934 *mode = This->mode;
935 else
936 *mode = VMRMode_Windowed;
938 return S_OK;
941 static const IVMRFilterConfigVtbl VMR7_FilterConfig_Vtbl =
943 VMR7FilterConfig_QueryInterface,
944 VMR7FilterConfig_AddRef,
945 VMR7FilterConfig_Release,
946 VMR7FilterConfig_SetImageCompositor,
947 VMR7FilterConfig_SetNumberOfStreams,
948 VMR7FilterConfig_GetNumberOfStreams,
949 VMR7FilterConfig_SetRenderingPrefs,
950 VMR7FilterConfig_GetRenderingPrefs,
951 VMR7FilterConfig_SetRenderingMode,
952 VMR7FilterConfig_GetRenderingMode
955 struct get_available_monitors_args
957 VMRMONITORINFO *info7;
958 VMR9MonitorInfo *info9;
959 DWORD arraysize;
960 DWORD numdev;
963 static BOOL CALLBACK get_available_monitors_proc(HMONITOR hmon, HDC hdc, LPRECT lprc, LPARAM lparam)
965 struct get_available_monitors_args *args = (struct get_available_monitors_args *)lparam;
966 MONITORINFOEXW mi;
968 if (args->info7 || args->info9)
971 if (!args->arraysize)
972 return FALSE;
974 mi.cbSize = sizeof(mi);
975 if (!GetMonitorInfoW(hmon, (MONITORINFO*)&mi))
976 return TRUE;
978 /* fill VMRMONITORINFO struct */
979 if (args->info7)
981 VMRMONITORINFO *info = args->info7++;
982 memset(info, 0, sizeof(*info));
984 if (args->numdev > 0)
986 info->guid.pGUID = &info->guid.GUID;
987 info->guid.GUID.Data4[7] = args->numdev;
989 else
990 info->guid.pGUID = NULL;
992 info->rcMonitor = mi.rcMonitor;
993 info->hMon = hmon;
994 info->dwFlags = mi.dwFlags;
996 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
998 /* FIXME: how to get these values? */
999 info->szDescription[0] = 0;
1002 /* fill VMR9MonitorInfo struct */
1003 if (args->info9)
1005 VMR9MonitorInfo *info = args->info9++;
1006 memset(info, 0, sizeof(*info));
1008 info->uDevID = 0; /* FIXME */
1009 info->rcMonitor = mi.rcMonitor;
1010 info->hMon = hmon;
1011 info->dwFlags = mi.dwFlags;
1013 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1015 /* FIXME: how to get these values? */
1016 info->szDescription[0] = 0;
1017 info->dwVendorId = 0;
1018 info->dwDeviceId = 0;
1019 info->dwSubSysId = 0;
1020 info->dwRevision = 0;
1023 args->arraysize--;
1026 args->numdev++;
1027 return TRUE;
1030 static HRESULT WINAPI VMR7MonitorConfig_QueryInterface(IVMRMonitorConfig *iface, REFIID riid,
1031 LPVOID * ppv)
1033 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1034 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1037 static ULONG WINAPI VMR7MonitorConfig_AddRef(IVMRMonitorConfig *iface)
1039 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1040 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1043 static ULONG WINAPI VMR7MonitorConfig_Release(IVMRMonitorConfig *iface)
1045 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1046 return IUnknown_Release(This->renderer.filter.outer_unk);
1049 static HRESULT WINAPI VMR7MonitorConfig_SetMonitor(IVMRMonitorConfig *iface, const VMRGUID *pGUID)
1051 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1053 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1055 if (!pGUID)
1056 return E_POINTER;
1058 return S_OK;
1061 static HRESULT WINAPI VMR7MonitorConfig_GetMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1063 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1065 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1067 if (!pGUID)
1068 return E_POINTER;
1070 pGUID->pGUID = NULL; /* default DirectDraw device */
1071 return S_OK;
1074 static HRESULT WINAPI VMR7MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig *iface,
1075 const 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 return S_OK;
1087 static HRESULT WINAPI VMR7MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1089 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1091 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1093 if (!pGUID)
1094 return E_POINTER;
1096 pGUID->pGUID = NULL; /* default DirectDraw device */
1097 return S_OK;
1100 static HRESULT WINAPI VMR7MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig *iface,
1101 VMRMONITORINFO *info, DWORD arraysize,
1102 DWORD *numdev)
1104 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1105 struct get_available_monitors_args args;
1107 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1109 if (!numdev)
1110 return E_POINTER;
1112 if (info && arraysize == 0)
1113 return E_INVALIDARG;
1115 args.info7 = info;
1116 args.info9 = NULL;
1117 args.arraysize = arraysize;
1118 args.numdev = 0;
1119 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1121 *numdev = args.numdev;
1122 return S_OK;
1125 static const IVMRMonitorConfigVtbl VMR7_MonitorConfig_Vtbl =
1127 VMR7MonitorConfig_QueryInterface,
1128 VMR7MonitorConfig_AddRef,
1129 VMR7MonitorConfig_Release,
1130 VMR7MonitorConfig_SetMonitor,
1131 VMR7MonitorConfig_GetMonitor,
1132 VMR7MonitorConfig_SetDefaultMonitor,
1133 VMR7MonitorConfig_GetDefaultMonitor,
1134 VMR7MonitorConfig_GetAvailableMonitors
1137 static HRESULT WINAPI VMR9MonitorConfig_QueryInterface(IVMRMonitorConfig9 *iface, REFIID riid,
1138 LPVOID * ppv)
1140 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1141 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1144 static ULONG WINAPI VMR9MonitorConfig_AddRef(IVMRMonitorConfig9 *iface)
1146 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1147 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1150 static ULONG WINAPI VMR9MonitorConfig_Release(IVMRMonitorConfig9 *iface)
1152 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1153 return IUnknown_Release(This->renderer.filter.outer_unk);
1156 static HRESULT WINAPI VMR9MonitorConfig_SetMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1158 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1160 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1162 return S_OK;
1165 static HRESULT WINAPI VMR9MonitorConfig_GetMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1167 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1169 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1171 if (!uDev)
1172 return E_POINTER;
1174 *uDev = 0;
1175 return S_OK;
1178 static HRESULT WINAPI VMR9MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1180 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1182 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1184 return S_OK;
1187 static HRESULT WINAPI VMR9MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1189 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1191 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1193 if (!uDev)
1194 return E_POINTER;
1196 *uDev = 0;
1197 return S_OK;
1200 static HRESULT WINAPI VMR9MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig9 *iface,
1201 VMR9MonitorInfo *info, DWORD arraysize,
1202 DWORD *numdev)
1204 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1205 struct get_available_monitors_args args;
1207 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1209 if (!numdev)
1210 return E_POINTER;
1212 if (info && arraysize == 0)
1213 return E_INVALIDARG;
1215 args.info7 = NULL;
1216 args.info9 = info;
1217 args.arraysize = arraysize;
1218 args.numdev = 0;
1219 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1221 *numdev = args.numdev;
1222 return S_OK;
1225 static const IVMRMonitorConfig9Vtbl VMR9_MonitorConfig_Vtbl =
1227 VMR9MonitorConfig_QueryInterface,
1228 VMR9MonitorConfig_AddRef,
1229 VMR9MonitorConfig_Release,
1230 VMR9MonitorConfig_SetMonitor,
1231 VMR9MonitorConfig_GetMonitor,
1232 VMR9MonitorConfig_SetDefaultMonitor,
1233 VMR9MonitorConfig_GetDefaultMonitor,
1234 VMR9MonitorConfig_GetAvailableMonitors
1237 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
1239 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1240 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1243 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
1245 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1246 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1249 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
1251 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1252 return IUnknown_Release(This->renderer.filter.outer_unk);
1255 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
1257 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1259 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
1260 return E_NOTIMPL;
1263 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD count)
1265 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1267 FIXME("iface %p, count %u, stub!\n", iface, count);
1269 if (!count)
1271 WARN("Application requested zero streams; returning E_INVALIDARG.\n");
1272 return E_INVALIDARG;
1275 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1277 if (filter->stream_count)
1279 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1280 WARN("Stream count is already set; returning VFW_E_WRONG_STATE.\n");
1281 return VFW_E_WRONG_STATE;
1284 filter->stream_count = count;
1286 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1287 return S_OK;
1290 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *count)
1292 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1294 TRACE("filter %p, count %p.\n", filter, count);
1296 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1298 if (!filter->stream_count)
1300 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1301 return VFW_E_VMR_NOT_IN_MIXER_MODE;
1304 *count = filter->stream_count;
1306 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1307 return S_OK;
1310 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
1312 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1314 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
1315 return E_NOTIMPL;
1318 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
1320 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1322 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
1323 return E_NOTIMPL;
1326 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
1328 HRESULT hr = S_OK;
1329 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1331 TRACE("(%p/%p)->(%u)\n", iface, This, mode);
1333 EnterCriticalSection(&This->renderer.filter.filter_cs);
1334 if (This->mode)
1336 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1337 return VFW_E_WRONG_STATE;
1340 if (This->allocator)
1341 IVMRSurfaceAllocator9_Release(This->allocator);
1342 if (This->presenter)
1343 IVMRImagePresenter9_Release(This->presenter);
1345 This->allocator = NULL;
1346 This->presenter = NULL;
1348 switch (mode)
1350 case VMR9Mode_Windowed:
1351 case VMR9Mode_Windowless:
1352 This->cookie = ~0;
1354 if (FAILED(hr = VMR9DefaultAllocatorPresenterImpl_create(This, (void **)&This->presenter)))
1356 ERR("Failed to create default presenter, hr %#x.\n", hr);
1357 break;
1360 if (FAILED(hr = IVMRImagePresenter9_QueryInterface(This->presenter,
1361 &IID_IVMRSurfaceAllocator9, (void **)&This->allocator)))
1363 ERR("Failed to query for IVMRSurfaceAllocator9, hr %#x.\n", hr);
1364 IVMRImagePresenter9_Release(This->presenter);
1365 This->allocator = NULL;
1366 This->presenter = NULL;
1367 break;
1370 hr = IVMRSurfaceAllocator9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
1371 break;
1372 case VMR9Mode_Renderless:
1373 break;
1374 default:
1375 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1376 return E_INVALIDARG;
1379 if (mode != VMR9Mode_Windowed)
1380 video_window_cleanup(&This->window);
1382 This->mode = mode;
1383 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1384 return hr;
1387 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
1389 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1391 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
1392 if (!mode)
1393 return E_POINTER;
1395 if (This->mode)
1396 *mode = This->mode;
1397 else
1398 *mode = VMR9Mode_Windowed;
1400 return S_OK;
1403 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
1405 VMR9FilterConfig_QueryInterface,
1406 VMR9FilterConfig_AddRef,
1407 VMR9FilterConfig_Release,
1408 VMR9FilterConfig_SetImageCompositor,
1409 VMR9FilterConfig_SetNumberOfStreams,
1410 VMR9FilterConfig_GetNumberOfStreams,
1411 VMR9FilterConfig_SetRenderingPrefs,
1412 VMR9FilterConfig_GetRenderingPrefs,
1413 VMR9FilterConfig_SetRenderingMode,
1414 VMR9FilterConfig_GetRenderingMode
1417 static HRESULT WINAPI VMR7WindowlessControl_QueryInterface(IVMRWindowlessControl *iface, REFIID riid,
1418 LPVOID * ppv)
1420 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1421 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1424 static ULONG WINAPI VMR7WindowlessControl_AddRef(IVMRWindowlessControl *iface)
1426 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1427 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1430 static ULONG WINAPI VMR7WindowlessControl_Release(IVMRWindowlessControl *iface)
1432 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1433 return IUnknown_Release(This->renderer.filter.outer_unk);
1436 static HRESULT WINAPI VMR7WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl *iface,
1437 LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height)
1439 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1441 TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n",
1442 filter, width, height, aspect_width, aspect_height);
1444 if (!width || !height)
1445 return E_POINTER;
1447 *width = filter->bmiheader.biWidth;
1448 *height = filter->bmiheader.biHeight;
1449 if (aspect_width)
1450 *aspect_width = filter->bmiheader.biWidth;
1451 if (aspect_height)
1452 *aspect_height = filter->bmiheader.biHeight;
1454 return S_OK;
1457 static HRESULT WINAPI VMR7WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl *iface,
1458 LONG *width, LONG *height)
1460 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1462 FIXME("(%p/%p)->(...) stub\n", iface, This);
1463 return E_NOTIMPL;
1466 static HRESULT WINAPI VMR7WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl *iface,
1467 LONG *width, LONG *height)
1469 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1471 FIXME("(%p/%p)->(...) stub\n", iface, This);
1472 return E_NOTIMPL;
1475 static HRESULT WINAPI VMR7WindowlessControl_SetVideoPosition(IVMRWindowlessControl *iface,
1476 const RECT *source, const RECT *dest)
1478 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1480 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1482 EnterCriticalSection(&This->renderer.filter.filter_cs);
1484 if (source)
1485 This->window.src = *source;
1486 if (dest)
1487 This->window.dst = *dest;
1489 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1491 return S_OK;
1494 static HRESULT WINAPI VMR7WindowlessControl_GetVideoPosition(IVMRWindowlessControl *iface,
1495 RECT *source, RECT *dest)
1497 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1499 if (source)
1500 *source = This->window.src;
1502 if (dest)
1503 *dest = This->window.dst;
1505 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1506 return S_OK;
1509 static HRESULT WINAPI VMR7WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl *iface,
1510 DWORD *mode)
1512 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1514 FIXME("(%p/%p)->(...) stub\n", iface, This);
1515 return E_NOTIMPL;
1518 static HRESULT WINAPI VMR7WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl *iface,
1519 DWORD mode)
1521 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1523 FIXME("(%p/%p)->(...) stub\n", iface, This);
1524 return E_NOTIMPL;
1527 static HRESULT WINAPI VMR7WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl *iface, HWND window)
1529 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1531 TRACE("iface %p, window %p.\n", iface, window);
1533 return IVMRWindowlessControl9_SetVideoClippingWindow(&filter->IVMRWindowlessControl9_iface, window);
1536 static HRESULT WINAPI VMR7WindowlessControl_RepaintVideo(IVMRWindowlessControl *iface,
1537 HWND hwnd, HDC hdc)
1539 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1541 FIXME("(%p/%p)->(...) stub\n", iface, This);
1542 return E_NOTIMPL;
1545 static HRESULT WINAPI VMR7WindowlessControl_DisplayModeChanged(IVMRWindowlessControl *iface)
1547 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1549 FIXME("(%p/%p)->(...) stub\n", iface, This);
1550 return E_NOTIMPL;
1553 static HRESULT WINAPI VMR7WindowlessControl_GetCurrentImage(IVMRWindowlessControl *iface,
1554 BYTE **dib)
1556 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1558 FIXME("(%p/%p)->(...) stub\n", iface, This);
1559 return E_NOTIMPL;
1562 static HRESULT WINAPI VMR7WindowlessControl_SetBorderColor(IVMRWindowlessControl *iface,
1563 COLORREF color)
1565 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1567 FIXME("(%p/%p)->(...) stub\n", iface, This);
1568 return E_NOTIMPL;
1571 static HRESULT WINAPI VMR7WindowlessControl_GetBorderColor(IVMRWindowlessControl *iface,
1572 COLORREF *color)
1574 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1576 FIXME("(%p/%p)->(...) stub\n", iface, This);
1577 return E_NOTIMPL;
1580 static HRESULT WINAPI VMR7WindowlessControl_SetColorKey(IVMRWindowlessControl *iface, COLORREF color)
1582 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1584 FIXME("(%p/%p)->(...) stub\n", iface, This);
1585 return E_NOTIMPL;
1588 static HRESULT WINAPI VMR7WindowlessControl_GetColorKey(IVMRWindowlessControl *iface, COLORREF *color)
1590 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1592 FIXME("(%p/%p)->(...) stub\n", iface, This);
1593 return E_NOTIMPL;
1596 static const IVMRWindowlessControlVtbl VMR7_WindowlessControl_Vtbl =
1598 VMR7WindowlessControl_QueryInterface,
1599 VMR7WindowlessControl_AddRef,
1600 VMR7WindowlessControl_Release,
1601 VMR7WindowlessControl_GetNativeVideoSize,
1602 VMR7WindowlessControl_GetMinIdealVideoSize,
1603 VMR7WindowlessControl_GetMaxIdealVideoSize,
1604 VMR7WindowlessControl_SetVideoPosition,
1605 VMR7WindowlessControl_GetVideoPosition,
1606 VMR7WindowlessControl_GetAspectRatioMode,
1607 VMR7WindowlessControl_SetAspectRatioMode,
1608 VMR7WindowlessControl_SetVideoClippingWindow,
1609 VMR7WindowlessControl_RepaintVideo,
1610 VMR7WindowlessControl_DisplayModeChanged,
1611 VMR7WindowlessControl_GetCurrentImage,
1612 VMR7WindowlessControl_SetBorderColor,
1613 VMR7WindowlessControl_GetBorderColor,
1614 VMR7WindowlessControl_SetColorKey,
1615 VMR7WindowlessControl_GetColorKey
1618 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
1620 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1621 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1624 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
1626 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1627 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1630 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
1632 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1633 return IUnknown_Release(This->renderer.filter.outer_unk);
1636 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface,
1637 LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height)
1639 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1641 TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n",
1642 filter, width, height, aspect_width, aspect_height);
1644 if (!width || !height)
1645 return E_POINTER;
1647 *width = filter->bmiheader.biWidth;
1648 *height = filter->bmiheader.biHeight;
1649 if (aspect_width)
1650 *aspect_width = filter->bmiheader.biWidth;
1651 if (aspect_height)
1652 *aspect_height = filter->bmiheader.biHeight;
1654 return S_OK;
1657 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1659 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1661 FIXME("(%p/%p)->(...) stub\n", iface, This);
1662 return E_NOTIMPL;
1665 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1667 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1669 FIXME("(%p/%p)->(...) stub\n", iface, This);
1670 return E_NOTIMPL;
1673 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface,
1674 const RECT *src, const RECT *dst)
1676 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1678 TRACE("filter %p, src %s, dst %s.\n", filter, wine_dbgstr_rect(src), wine_dbgstr_rect(dst));
1680 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1682 if (src)
1683 filter->window.src = *src;
1684 if (dst)
1685 filter->window.dst = *dst;
1687 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1689 return S_OK;
1692 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *src, RECT *dst)
1694 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1696 TRACE("filter %p, src %p, dst %p.\n", filter, src, dst);
1698 if (src)
1699 *src = filter->window.src;
1701 if (dst)
1702 *dst = filter->window.dst;
1704 return S_OK;
1707 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1709 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1711 TRACE("filter %p, mode %p.\n", filter, mode);
1713 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1714 *mode = filter->aspect_mode;
1715 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1716 return S_OK;
1719 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1721 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1723 TRACE("filter %p, mode %u.\n", filter, mode);
1725 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1726 filter->aspect_mode = mode;
1727 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1728 return S_OK;
1731 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND window)
1733 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1734 HRESULT hr;
1736 TRACE("filter %p, window %p.\n", filter, window);
1738 if (!IsWindow(window))
1740 WARN("Invalid window %p, returning E_INVALIDARG.\n", window);
1741 return E_INVALIDARG;
1744 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1746 if (filter->renderer.sink.pin.peer)
1748 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1749 WARN("Attempt to set the clipping window while connected; returning VFW_E_WRONG_STATE.\n");
1750 return VFW_E_WRONG_STATE;
1753 filter->clipping_window = window;
1755 hr = IVMRFilterConfig9_SetNumberOfStreams(&filter->IVMRFilterConfig9_iface, 4);
1757 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1758 return hr;
1761 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1763 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1764 HRESULT hr;
1766 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1768 EnterCriticalSection(&This->renderer.filter.filter_cs);
1769 if (hwnd != This->clipping_window)
1771 ERR("Not handling changing windows yet!!!\n");
1772 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1773 return S_OK;
1776 if (!This->allocator_d3d9_dev)
1778 ERR("No d3d9 device!\n");
1779 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1780 return VFW_E_WRONG_STATE;
1783 /* Windowless extension */
1784 hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, NULL, NULL);
1785 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1787 return hr;
1790 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1792 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1794 FIXME("(%p/%p)->(...) stub\n", iface, This);
1795 return E_NOTIMPL;
1798 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1800 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1802 FIXME("(%p/%p)->(...) stub\n", iface, This);
1803 return E_NOTIMPL;
1806 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1808 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1810 FIXME("(%p/%p)->(...) stub\n", iface, This);
1811 return E_NOTIMPL;
1814 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1816 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1818 FIXME("(%p/%p)->(...) stub\n", iface, This);
1819 return E_NOTIMPL;
1822 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1824 VMR9WindowlessControl_QueryInterface,
1825 VMR9WindowlessControl_AddRef,
1826 VMR9WindowlessControl_Release,
1827 VMR9WindowlessControl_GetNativeVideoSize,
1828 VMR9WindowlessControl_GetMinIdealVideoSize,
1829 VMR9WindowlessControl_GetMaxIdealVideoSize,
1830 VMR9WindowlessControl_SetVideoPosition,
1831 VMR9WindowlessControl_GetVideoPosition,
1832 VMR9WindowlessControl_GetAspectRatioMode,
1833 VMR9WindowlessControl_SetAspectRatioMode,
1834 VMR9WindowlessControl_SetVideoClippingWindow,
1835 VMR9WindowlessControl_RepaintVideo,
1836 VMR9WindowlessControl_DisplayModeChanged,
1837 VMR9WindowlessControl_GetCurrentImage,
1838 VMR9WindowlessControl_SetBorderColor,
1839 VMR9WindowlessControl_GetBorderColor
1842 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify *iface,
1843 REFIID riid, LPVOID * ppv)
1845 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1846 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1849 static ULONG WINAPI VMR7SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify *iface)
1851 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1852 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1855 static ULONG WINAPI VMR7SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify *iface)
1857 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1858 return IUnknown_Release(This->renderer.filter.outer_unk);
1861 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify *iface,
1862 DWORD_PTR id,
1863 IVMRSurfaceAllocator *alloc)
1865 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1867 FIXME("(%p/%p)->(...) stub\n", iface, This);
1868 return E_NOTIMPL;
1871 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1872 IDirectDraw7 *device, HMONITOR monitor)
1874 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1876 FIXME("(%p/%p)->(...) stub\n", iface, This);
1877 return E_NOTIMPL;
1880 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_ChangeDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1881 IDirectDraw7 *device, HMONITOR monitor)
1883 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1885 FIXME("(%p/%p)->(...) stub\n", iface, This);
1886 return E_NOTIMPL;
1889 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces(IVMRSurfaceAllocatorNotify *iface)
1891 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1893 FIXME("(%p/%p)->(...) stub\n", iface, This);
1894 return E_NOTIMPL;
1897 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify *iface, LONG code,
1898 LONG_PTR param1, LONG_PTR param2)
1900 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1902 FIXME("(%p/%p)->(...) stub\n", iface, This);
1903 return E_NOTIMPL;
1906 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetBorderColor(IVMRSurfaceAllocatorNotify *iface,
1907 COLORREF clrBorder)
1909 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1911 FIXME("(%p/%p)->(...) stub\n", iface, This);
1912 return E_NOTIMPL;
1915 static const IVMRSurfaceAllocatorNotifyVtbl VMR7_SurfaceAllocatorNotify_Vtbl =
1917 VMR7SurfaceAllocatorNotify_QueryInterface,
1918 VMR7SurfaceAllocatorNotify_AddRef,
1919 VMR7SurfaceAllocatorNotify_Release,
1920 VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1921 VMR7SurfaceAllocatorNotify_SetDDrawDevice,
1922 VMR7SurfaceAllocatorNotify_ChangeDDrawDevice,
1923 VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces,
1924 VMR7SurfaceAllocatorNotify_NotifyEvent,
1925 VMR7SurfaceAllocatorNotify_SetBorderColor
1928 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1930 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1931 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1934 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1936 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1937 ULONG refcount = InterlockedIncrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1939 TRACE("%p increasing refcount to %u.\n", iface, refcount);
1941 return refcount;
1944 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1946 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1947 ULONG refcount = InterlockedDecrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1949 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
1951 if (!refcount && !filter->renderer.filter.refcount)
1952 free(filter);
1954 return refcount;
1957 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(
1958 IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR cookie, IVMRSurfaceAllocator9 *allocator)
1960 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1961 IVMRImagePresenter9 *presenter;
1963 TRACE("filter %p, cookie %#Ix, allocator %p.\n", filter, cookie, allocator);
1965 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1967 filter->cookie = cookie;
1969 if (filter->renderer.sink.pin.peer)
1971 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1972 WARN("Attempt to set allocator while connected; returning VFW_E_WRONG_STATE.\n");
1973 return VFW_E_WRONG_STATE;
1976 if (FAILED(IVMRSurfaceAllocator9_QueryInterface(allocator, &IID_IVMRImagePresenter9, (void **)&presenter)))
1978 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1979 return E_NOINTERFACE;
1982 if (filter->allocator)
1984 IVMRImagePresenter9_Release(filter->presenter);
1985 IVMRSurfaceAllocator9_Release(filter->allocator);
1987 filter->allocator = allocator;
1988 filter->presenter = presenter;
1989 IVMRSurfaceAllocator9_AddRef(allocator);
1991 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1992 return S_OK;
1995 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface,
1996 IDirect3DDevice9 *device, HMONITOR monitor)
1998 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2000 TRACE("filter %p, device %p, monitor %p.\n", filter, device, monitor);
2002 if (filter->allocator_d3d9_dev)
2003 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
2004 filter->allocator_d3d9_dev = device;
2005 IDirect3DDevice9_AddRef(device);
2007 return S_OK;
2010 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
2012 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2014 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
2015 if (This->allocator_d3d9_dev)
2016 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
2017 This->allocator_d3d9_dev = device;
2018 IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
2020 return S_OK;
2023 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
2025 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2026 DWORD i;
2027 HRESULT hr = S_OK;
2029 TRACE("filter %p, allocinfo %p, numbuffers %p, surface %p.\n", This, numbuffers, allocinfo, surface);
2031 if (!allocinfo || !numbuffers || !surface)
2032 return E_POINTER;
2034 TRACE("Flags %#x, size %ux%u, format %u (%#x), pool %u, minimum buffers %u.\n",
2035 allocinfo->dwFlags, allocinfo->dwWidth, allocinfo->dwHeight,
2036 allocinfo->Format, allocinfo->Format, allocinfo->Pool, allocinfo->MinBuffers);
2038 if ((allocinfo->dwFlags & VMR9AllocFlag_TextureSurface)
2039 && (allocinfo->dwFlags & VMR9AllocFlag_OffscreenSurface))
2041 WARN("Invalid flags specified; returning E_INVALIDARG.\n");
2042 return E_INVALIDARG;
2045 if (!allocinfo->Format)
2047 IDirect3DSurface9 *backbuffer;
2048 D3DSURFACE_DESC desc;
2050 IDirect3DDevice9_GetBackBuffer(This->allocator_d3d9_dev, 0, 0,
2051 D3DBACKBUFFER_TYPE_MONO, &backbuffer);
2052 IDirect3DSurface9_GetDesc(backbuffer, &desc);
2053 IDirect3DSurface9_Release(backbuffer);
2054 allocinfo->Format = desc.Format;
2057 if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
2059 WARN("%u surfaces requested (minimum %u); returning E_INVALIDARG.\n",
2060 *numbuffers, allocinfo->MinBuffers);
2061 return E_INVALIDARG;
2064 if (!This->allocator_d3d9_dev)
2066 WARN("No Direct3D device; returning VFW_E_WRONG_STATE.\n");
2067 return VFW_E_WRONG_STATE;
2070 if (allocinfo->dwFlags == VMR9AllocFlag_OffscreenSurface)
2072 for (i = 0; i < *numbuffers; ++i)
2074 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight,
2075 allocinfo->Format, allocinfo->Pool, &surface[i], NULL);
2076 if (FAILED(hr))
2077 break;
2080 else if (allocinfo->dwFlags == VMR9AllocFlag_TextureSurface)
2082 for (i = 0; i < *numbuffers; ++i)
2084 IDirect3DTexture9 *texture;
2086 hr = IDirect3DDevice9_CreateTexture(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, 1, D3DUSAGE_DYNAMIC,
2087 allocinfo->Format, allocinfo->Pool, &texture, NULL);
2088 if (FAILED(hr))
2089 break;
2090 IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface[i]);
2091 IDirect3DTexture9_Release(texture);
2094 else if (allocinfo->dwFlags == VMR9AllocFlag_3DRenderTarget)
2096 for (i = 0; i < *numbuffers; ++i)
2098 if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(This->allocator_d3d9_dev,
2099 allocinfo->dwWidth, allocinfo->dwHeight, allocinfo->Format,
2100 D3DMULTISAMPLE_NONE, 0, FALSE, &surface[i], NULL)))
2101 break;
2104 else
2106 FIXME("Unhandled flags %#x.\n", allocinfo->dwFlags);
2107 return E_NOTIMPL;
2110 if (FAILED(hr))
2111 WARN("%u/%u surfaces allocated, hr %#x.\n", i, *numbuffers, hr);
2113 if (i >= allocinfo->MinBuffers)
2115 hr = S_OK;
2116 *numbuffers = i;
2118 else
2120 for ( ; i > 0; --i) IDirect3DSurface9_Release(surface[i - 1]);
2121 *numbuffers = 0;
2123 return hr;
2126 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
2128 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2130 FIXME("(%p/%p)->(...) stub\n", iface, This);
2131 return E_NOTIMPL;
2134 static const IVMRSurfaceAllocatorNotify9Vtbl VMR9_SurfaceAllocatorNotify_Vtbl =
2136 VMR9SurfaceAllocatorNotify_QueryInterface,
2137 VMR9SurfaceAllocatorNotify_AddRef,
2138 VMR9SurfaceAllocatorNotify_Release,
2139 VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
2140 VMR9SurfaceAllocatorNotify_SetD3DDevice,
2141 VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
2142 VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
2143 VMR9SurfaceAllocatorNotify_NotifyEvent
2146 static inline struct quartz_vmr *impl_from_IVMRMixerControl9(IVMRMixerControl9 *iface)
2148 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerControl9_iface);
2151 static HRESULT WINAPI mixer_control9_QueryInterface(IVMRMixerControl9 *iface, REFIID iid, void **out)
2153 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2154 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2157 static ULONG WINAPI mixer_control9_AddRef(IVMRMixerControl9 *iface)
2159 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2160 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2163 static ULONG WINAPI mixer_control9_Release(IVMRMixerControl9 *iface)
2165 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2166 return IUnknown_Release(filter->renderer.filter.outer_unk);
2169 static HRESULT WINAPI mixer_control9_SetAlpha(IVMRMixerControl9 *iface, DWORD stream, float alpha)
2171 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2173 FIXME("filter %p, stream %u, alpha %.8e, stub!\n", filter, stream, alpha);
2175 return E_NOTIMPL;
2178 static HRESULT WINAPI mixer_control9_GetAlpha(IVMRMixerControl9 *iface, DWORD stream, float *alpha)
2180 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2182 FIXME("filter %p, stream %u, alpha %p, stub!\n", filter, stream, alpha);
2184 return E_NOTIMPL;
2187 static HRESULT WINAPI mixer_control9_SetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD z)
2189 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2191 FIXME("filter %p, stream %u, z %u, stub!\n", filter, stream, z);
2193 return E_NOTIMPL;
2196 static HRESULT WINAPI mixer_control9_GetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD *z)
2198 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2200 FIXME("filter %p, stream %u, z %p, stub!\n", filter, stream, z);
2202 return E_NOTIMPL;
2205 static HRESULT WINAPI mixer_control9_SetOutputRect(IVMRMixerControl9 *iface,
2206 DWORD stream, const VMR9NormalizedRect *rect)
2208 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2210 FIXME("filter %p, stream %u, rect %s, stub!\n", filter, stream, debugstr_normalized_rect(rect));
2212 return E_NOTIMPL;
2215 static HRESULT WINAPI mixer_control9_GetOutputRect(IVMRMixerControl9 *iface,
2216 DWORD stream, VMR9NormalizedRect *rect)
2218 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2220 FIXME("filter %p, stream %u, rect %p, stub!\n", filter, stream, rect);
2222 return E_NOTIMPL;
2225 static HRESULT WINAPI mixer_control9_SetBackgroundClr(IVMRMixerControl9 *iface, COLORREF color)
2227 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2229 FIXME("filter %p, color #%06x, stub!\n", filter, color);
2231 return E_NOTIMPL;
2234 static HRESULT WINAPI mixer_control9_GetBackgroundClr(IVMRMixerControl9 *iface, COLORREF *color)
2236 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2238 FIXME("filter %p, color %p, stub!\n", filter, color);
2240 return E_NOTIMPL;
2243 static HRESULT WINAPI mixer_control9_SetMixingPrefs(IVMRMixerControl9 *iface, DWORD flags)
2245 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2247 FIXME("filter %p, flags %#x, stub!\n", filter, flags);
2249 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2250 filter->mixing_prefs = flags;
2251 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2252 return S_OK;
2255 static HRESULT WINAPI mixer_control9_GetMixingPrefs(IVMRMixerControl9 *iface, DWORD *flags)
2257 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2259 FIXME("filter %p, flags %p, stub!\n", filter, flags);
2261 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2262 *flags = filter->mixing_prefs;
2263 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2264 return S_OK;
2267 static HRESULT WINAPI mixer_control9_SetProcAmpControl(IVMRMixerControl9 *iface,
2268 DWORD stream, VMR9ProcAmpControl *settings)
2270 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2272 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2274 return E_NOTIMPL;
2277 static HRESULT WINAPI mixer_control9_GetProcAmpControl(IVMRMixerControl9 *iface,
2278 DWORD stream, VMR9ProcAmpControl *settings)
2280 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2282 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2284 return E_NOTIMPL;
2287 static HRESULT WINAPI mixer_control9_GetProcAmpControlRange(IVMRMixerControl9 *iface,
2288 DWORD stream, VMR9ProcAmpControlRange *settings)
2290 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2292 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2294 return E_NOTIMPL;
2297 static const IVMRMixerControl9Vtbl mixer_control9_vtbl =
2299 mixer_control9_QueryInterface,
2300 mixer_control9_AddRef,
2301 mixer_control9_Release,
2302 mixer_control9_SetAlpha,
2303 mixer_control9_GetAlpha,
2304 mixer_control9_SetZOrder,
2305 mixer_control9_GetZOrder,
2306 mixer_control9_SetOutputRect,
2307 mixer_control9_GetOutputRect,
2308 mixer_control9_SetBackgroundClr,
2309 mixer_control9_GetBackgroundClr,
2310 mixer_control9_SetMixingPrefs,
2311 mixer_control9_GetMixingPrefs,
2312 mixer_control9_SetProcAmpControl,
2313 mixer_control9_GetProcAmpControl,
2314 mixer_control9_GetProcAmpControlRange,
2317 static inline struct quartz_vmr *impl_from_IVMRMixerBitmap9(IVMRMixerBitmap9 *iface)
2319 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerBitmap9_iface);
2322 static HRESULT WINAPI mixer_bitmap9_QueryInterface(IVMRMixerBitmap9 *iface, REFIID iid, void **out)
2324 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2325 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2328 static ULONG WINAPI mixer_bitmap9_AddRef(IVMRMixerBitmap9 *iface)
2330 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2331 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2334 static ULONG WINAPI mixer_bitmap9_Release(IVMRMixerBitmap9 *iface)
2336 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2337 return IUnknown_Release(filter->renderer.filter.outer_unk);
2340 static HRESULT WINAPI mixer_bitmap9_SetAlphaBitmap(IVMRMixerBitmap9 *iface,
2341 const VMR9AlphaBitmap *bitmap)
2343 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2344 TRACE("dwFlags %#x, hdc %p, pDDS %p, rSrc %s, rDest %s, fAlpha %.8e, clrSrcKey #%06x, dwFilterMode %#x.\n",
2345 bitmap->dwFlags, bitmap->hdc, bitmap->pDDS, wine_dbgstr_rect(&bitmap->rSrc),
2346 debugstr_normalized_rect(&bitmap->rDest), bitmap->fAlpha, bitmap->clrSrcKey, bitmap->dwFilterMode);
2347 return E_NOTIMPL;
2350 static HRESULT WINAPI mixer_bitmap9_UpdateAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2351 const VMR9AlphaBitmap *bitmap)
2353 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2354 return E_NOTIMPL;
2357 static HRESULT WINAPI mixer_bitmap9_GetAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2358 VMR9AlphaBitmap *bitmap)
2360 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2361 return E_NOTIMPL;
2364 static const IVMRMixerBitmap9Vtbl mixer_bitmap9_vtbl =
2366 mixer_bitmap9_QueryInterface,
2367 mixer_bitmap9_AddRef,
2368 mixer_bitmap9_Release,
2369 mixer_bitmap9_SetAlphaBitmap,
2370 mixer_bitmap9_UpdateAlphaBitmapParameters,
2371 mixer_bitmap9_GetAlphaBitmapParameters,
2374 static inline struct quartz_vmr *impl_from_IVMRAspectRatioControl9(IVMRAspectRatioControl9 *iface)
2376 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRAspectRatioControl9_iface);
2379 static HRESULT WINAPI aspect_ratio_control9_QueryInterface(IVMRAspectRatioControl9 *iface, REFIID iid, void **out)
2381 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2382 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2385 static ULONG WINAPI aspect_ratio_control9_AddRef(IVMRAspectRatioControl9 *iface)
2387 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2388 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2391 static ULONG WINAPI aspect_ratio_control9_Release(IVMRAspectRatioControl9 *iface)
2393 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2394 return IUnknown_Release(filter->renderer.filter.outer_unk);
2397 static HRESULT WINAPI aspect_ratio_control9_GetAspectRatioMode(IVMRAspectRatioControl9 *iface, DWORD *mode)
2399 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2401 TRACE("filter %p, mode %p.\n", filter, mode);
2403 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2404 *mode = filter->aspect_mode;
2405 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2406 return S_OK;
2409 static HRESULT WINAPI aspect_ratio_control9_SetAspectRatioMode(IVMRAspectRatioControl9 *iface, DWORD mode)
2411 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2413 TRACE("filter %p, mode %u.\n", filter, mode);
2415 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2416 filter->aspect_mode = mode;
2417 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2418 return S_OK;
2421 static const IVMRAspectRatioControl9Vtbl aspect_ratio_control9_vtbl =
2423 aspect_ratio_control9_QueryInterface,
2424 aspect_ratio_control9_AddRef,
2425 aspect_ratio_control9_Release,
2426 aspect_ratio_control9_GetAspectRatioMode,
2427 aspect_ratio_control9_SetAspectRatioMode,
2430 static inline struct quartz_vmr *impl_from_IOverlay(IOverlay *iface)
2432 return CONTAINING_RECORD(iface, struct quartz_vmr, IOverlay_iface);
2435 static HRESULT WINAPI overlay_QueryInterface(IOverlay *iface, REFIID iid, void **out)
2437 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2438 return IPin_QueryInterface(&filter->renderer.sink.pin.IPin_iface, iid, out);
2441 static ULONG WINAPI overlay_AddRef(IOverlay *iface)
2443 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2444 return IPin_AddRef(&filter->renderer.sink.pin.IPin_iface);
2447 static ULONG WINAPI overlay_Release(IOverlay *iface)
2449 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2450 return IPin_Release(&filter->renderer.sink.pin.IPin_iface);
2453 static HRESULT WINAPI overlay_GetPalette(IOverlay *iface, DWORD *count, PALETTEENTRY **palette)
2455 FIXME("iface %p, count %p, palette %p, stub!\n", iface, count, palette);
2456 return E_NOTIMPL;
2459 static HRESULT WINAPI overlay_SetPalette(IOverlay *iface, DWORD count, PALETTEENTRY *palette)
2461 FIXME("iface %p, count %u, palette %p, stub!\n", iface, count, palette);
2462 return E_NOTIMPL;
2465 static HRESULT WINAPI overlay_GetDefaultColorKey(IOverlay *iface, COLORKEY *key)
2467 FIXME("iface %p, key %p, stub!\n", iface, key);
2468 return E_NOTIMPL;
2471 static HRESULT WINAPI overlay_GetColorKey(IOverlay *iface, COLORKEY *key)
2473 FIXME("iface %p, key %p, stub!\n", iface, key);
2474 return E_NOTIMPL;
2477 static HRESULT WINAPI overlay_SetColorKey(IOverlay *iface, COLORKEY *key)
2479 FIXME("iface %p, key %p, stub!\n", iface, key);
2480 return E_NOTIMPL;
2483 static HRESULT WINAPI overlay_GetWindowHandle(IOverlay *iface, HWND *window)
2485 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2487 TRACE("filter %p, window %p.\n", filter, window);
2489 if (!filter->window.hwnd)
2490 return VFW_E_WRONG_STATE;
2492 *window = filter->window.hwnd;
2493 return S_OK;
2496 static HRESULT WINAPI overlay_GetClipList(IOverlay *iface, RECT *source, RECT *dest, RGNDATA **region)
2498 FIXME("iface %p, source %p, dest %p, region %p, stub!\n", iface, source, dest, region);
2499 return E_NOTIMPL;
2502 static HRESULT WINAPI overlay_GetVideoPosition(IOverlay *iface, RECT *source, RECT *dest)
2504 FIXME("iface %p, source %p, dest %p, stub!\n", iface, source, dest);
2505 return E_NOTIMPL;
2508 static HRESULT WINAPI overlay_Advise(IOverlay *iface, IOverlayNotify *sink, DWORD flags)
2510 FIXME("iface %p, sink %p, flags %#x, stub!\n", iface, sink, flags);
2511 return E_NOTIMPL;
2514 static HRESULT WINAPI overlay_Unadvise(IOverlay *iface)
2516 FIXME("iface %p, stub!\n", iface);
2517 return E_NOTIMPL;
2520 static const IOverlayVtbl overlay_vtbl =
2522 overlay_QueryInterface,
2523 overlay_AddRef,
2524 overlay_Release,
2525 overlay_GetPalette,
2526 overlay_SetPalette,
2527 overlay_GetDefaultColorKey,
2528 overlay_GetColorKey,
2529 overlay_SetColorKey,
2530 overlay_GetWindowHandle,
2531 overlay_GetClipList,
2532 overlay_GetVideoPosition,
2533 overlay_Advise,
2534 overlay_Unadvise,
2537 static HRESULT vmr_create(IUnknown *outer, IUnknown **out, const CLSID *clsid)
2539 struct quartz_vmr *object;
2540 HRESULT hr;
2542 if (!(object = calloc(1, sizeof(*object))))
2543 return E_OUTOFMEMORY;
2545 object->hD3d9 = LoadLibraryA("d3d9.dll");
2546 if (!object->hD3d9)
2548 WARN("Could not load d3d9.dll\n");
2549 free(object);
2550 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2553 strmbase_renderer_init(&object->renderer, outer, clsid, L"VMR Input0", &renderer_ops);
2554 object->IAMCertifiedOutputProtection_iface.lpVtbl = &IAMCertifiedOutputProtection_Vtbl;
2555 object->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
2556 object->IVMRAspectRatioControl9_iface.lpVtbl = &aspect_ratio_control9_vtbl;
2557 object->IVMRFilterConfig_iface.lpVtbl = &VMR7_FilterConfig_Vtbl;
2558 object->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
2559 object->IVMRMixerBitmap9_iface.lpVtbl = &mixer_bitmap9_vtbl;
2560 object->IVMRMixerControl9_iface.lpVtbl = &mixer_control9_vtbl;
2561 object->IVMRMonitorConfig_iface.lpVtbl = &VMR7_MonitorConfig_Vtbl;
2562 object->IVMRMonitorConfig9_iface.lpVtbl = &VMR9_MonitorConfig_Vtbl;
2563 object->IVMRSurfaceAllocatorNotify_iface.lpVtbl = &VMR7_SurfaceAllocatorNotify_Vtbl;
2564 object->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &VMR9_SurfaceAllocatorNotify_Vtbl;
2565 object->IVMRWindowlessControl_iface.lpVtbl = &VMR7_WindowlessControl_Vtbl;
2566 object->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
2567 object->IOverlay_iface.lpVtbl = &overlay_vtbl;
2569 video_window_init(&object->window, &IVideoWindow_VTable,
2570 &object->renderer.filter, &object->renderer.sink.pin, &window_ops);
2572 if (FAILED(hr = video_window_create_window(&object->window)))
2574 video_window_cleanup(&object->window);
2575 strmbase_renderer_cleanup(&object->renderer);
2576 FreeLibrary(object->hD3d9);
2577 free(object);
2578 return hr;
2581 object->mixing_prefs = MixerPref9_NoDecimation | MixerPref9_ARAdjustXorY
2582 | MixerPref9_BiLinearFiltering | MixerPref9_RenderTargetRGB;
2584 TRACE("Created VMR %p.\n", object);
2585 *out = &object->renderer.filter.IUnknown_inner;
2586 return S_OK;
2589 HRESULT vmr7_create(IUnknown *outer, IUnknown **out)
2591 return vmr_create(outer, out, &CLSID_VideoMixingRenderer);
2594 HRESULT vmr9_create(IUnknown *outer, IUnknown **out)
2596 return vmr_create(outer, out, &CLSID_VideoMixingRenderer9);
2600 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, void **ppv)
2602 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2604 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
2606 *ppv = NULL;
2608 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IVMRImagePresenter9))
2609 *ppv = &This->IVMRImagePresenter9_iface;
2610 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocator9))
2611 *ppv = &This->IVMRSurfaceAllocator9_iface;
2613 if (*ppv)
2615 IUnknown_AddRef((IUnknown *)(*ppv));
2616 return S_OK;
2619 FIXME("No interface for %s\n", debugstr_guid(riid));
2621 return E_NOINTERFACE;
2624 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
2626 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2627 ULONG refCount = InterlockedIncrement(&This->refCount);
2629 TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
2631 return refCount;
2634 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
2636 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2637 ULONG refCount = InterlockedDecrement(&This->refCount);
2639 TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
2641 if (!refCount)
2643 DWORD i;
2644 TRACE("Destroying\n");
2645 IDirect3D9_Release(This->d3d9_ptr);
2647 TRACE("Number of surfaces: %u\n", This->num_surfaces);
2648 for (i = 0; i < This->num_surfaces; ++i)
2650 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2651 TRACE("Releasing surface %p\n", surface);
2652 if (surface)
2653 IDirect3DSurface9_Release(surface);
2656 if (This->d3d9_dev)
2657 IDirect3DDevice9_Release(This->d3d9_dev);
2658 free(This->d3d9_surfaces);
2659 This->d3d9_surfaces = NULL;
2660 This->num_surfaces = 0;
2661 free(This);
2662 return 0;
2664 return refCount;
2667 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2669 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2671 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2673 return S_OK;
2676 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2678 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2680 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2682 return S_OK;
2685 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface,
2686 DWORD_PTR cookie, VMR9PresentationInfo *info)
2688 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2689 const struct quartz_vmr *filter = presenter->pVMR9;
2690 IDirect3DDevice9 *device = presenter->d3d9_dev;
2691 const RECT src = filter->window.src;
2692 IDirect3DSurface9 *backbuffer;
2693 RECT dst = filter->window.dst;
2694 HRESULT hr;
2696 TRACE("presenter %p, cookie %#Ix, info %p.\n", presenter, cookie, info);
2698 /* This might happen if we don't have active focus (eg on a different virtual desktop) */
2699 if (!device)
2700 return S_OK;
2702 if (FAILED(hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET,
2703 D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0)))
2704 ERR("Failed to clear, hr %#x.\n", hr);
2706 if (FAILED(hr = IDirect3DDevice9_BeginScene(device)))
2707 ERR("Failed to begin scene, hr %#x.\n", hr);
2709 if (FAILED(hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer)))
2711 ERR("Failed to get backbuffer, hr %#x.\n", hr);
2712 return hr;
2715 if (FAILED(hr = IDirect3DDevice9_StretchRect(device, info->lpSurf, NULL, backbuffer, NULL, D3DTEXF_POINT)))
2716 ERR("Failed to blit image, hr %#x.\n", hr);
2717 IDirect3DSurface9_Release(backbuffer);
2719 if (FAILED(hr = IDirect3DDevice9_EndScene(device)))
2720 ERR("Failed to end scene, hr %#x.\n", hr);
2722 if (filter->aspect_mode == VMR9ARMode_LetterBox)
2724 unsigned int src_width = src.right - src.left, src_height = src.bottom - src.top;
2725 unsigned int dst_width = dst.right - dst.left, dst_height = dst.bottom - dst.top;
2727 if (src_width * dst_height > dst_width * src_height)
2729 /* src is "wider" than dst. */
2730 unsigned int dst_center = (dst.top + dst.bottom) / 2;
2731 unsigned int scaled_height = src_height * dst_width / src_width;
2733 dst.top = dst_center - scaled_height / 2;
2734 dst.bottom = dst.top + scaled_height;
2736 else if (src_width * dst_height < dst_width * src_height)
2738 /* src is "taller" than dst. */
2739 unsigned int dst_center = (dst.left + dst.right) / 2;
2740 unsigned int scaled_width = src_width * dst_height / src_height;
2742 dst.left = dst_center - scaled_width / 2;
2743 dst.right = dst.left + scaled_width;
2747 if (FAILED(hr = IDirect3DDevice9_Present(device, &src, &dst, NULL, NULL)))
2748 ERR("Failed to present, hr %#x.\n", hr);
2750 return S_OK;
2753 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
2755 VMR9_ImagePresenter_QueryInterface,
2756 VMR9_ImagePresenter_AddRef,
2757 VMR9_ImagePresenter_Release,
2758 VMR9_ImagePresenter_StartPresenting,
2759 VMR9_ImagePresenter_StopPresenting,
2760 VMR9_ImagePresenter_PresentImage
2763 static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocator9 *iface, REFIID iid, void **out)
2765 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2766 return IVMRImagePresenter9_QueryInterface(&presenter->IVMRImagePresenter9_iface, iid, out);
2769 static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocator9 *iface)
2771 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2772 return IVMRImagePresenter9_AddRef(&presenter->IVMRImagePresenter9_iface);
2775 static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocator9 *iface)
2777 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2778 return IVMRImagePresenter9_Release(&presenter->IVMRImagePresenter9_iface);
2781 static HRESULT VMR9_SurfaceAllocator_SetAllocationSettings(struct default_presenter *This, VMR9AllocationInfo *allocinfo)
2783 D3DCAPS9 caps;
2784 UINT width, height;
2785 HRESULT hr;
2787 if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface))
2788 /* Only needed for texture surfaces */
2789 return S_OK;
2791 hr = IDirect3DDevice9_GetDeviceCaps(This->d3d9_dev, &caps);
2792 if (FAILED(hr))
2793 return hr;
2795 if (!(caps.TextureCaps & D3DPTEXTURECAPS_POW2) || (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY))
2797 width = allocinfo->dwWidth;
2798 height = allocinfo->dwHeight;
2800 else
2802 width = height = 1;
2803 while (width < allocinfo->dwWidth)
2804 width *= 2;
2806 while (height < allocinfo->dwHeight)
2807 height *= 2;
2808 FIXME("NPOW2 support missing, not using proper surfaces!\n");
2811 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
2813 if (height > width)
2814 width = height;
2815 else
2816 height = width;
2817 FIXME("Square texture support required..\n");
2820 allocinfo->dwHeight = height;
2821 allocinfo->dwWidth = width;
2823 return hr;
2826 static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
2828 UINT d3d9_adapter;
2829 HMONITOR mon;
2831 mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
2832 if (!mon)
2833 d3d9_adapter = 0;
2834 else
2836 for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
2838 if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
2839 break;
2841 if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
2842 d3d9_adapter = 0;
2844 if (mon_out)
2845 *mon_out = mon;
2846 return d3d9_adapter;
2849 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocator9 *iface,
2850 DWORD_PTR cookie, VMR9AllocationInfo *info, DWORD *numbuffers)
2852 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
2853 D3DPRESENT_PARAMETERS d3dpp;
2854 IDirect3DDevice9 *device;
2855 DWORD d3d9_adapter;
2856 D3DCAPS9 caps;
2857 HWND window;
2858 HRESULT hr;
2860 TRACE("presenter %p, cookie %#Ix, info %p, numbuffers %p.\n", This, cookie, info, numbuffers);
2862 This->info = *info;
2864 if (This->pVMR9->mode == VMR9Mode_Windowed)
2865 window = This->pVMR9->window.hwnd;
2866 else
2867 window = This->pVMR9->clipping_window;
2869 /* Obtain a monitor and d3d9 device */
2870 d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, window, &This->hMon);
2872 /* Now try to create the d3d9 device */
2873 ZeroMemory(&d3dpp, sizeof(d3dpp));
2874 d3dpp.Windowed = TRUE;
2875 d3dpp.hDeviceWindow = window;
2876 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
2877 d3dpp.BackBufferWidth = info->dwWidth;
2878 d3dpp.BackBufferHeight = info->dwHeight;
2880 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL,
2881 NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2882 if (FAILED(hr))
2884 ERR("Could not create device: %08x\n", hr);
2885 return hr;
2888 IDirect3DDevice9_GetDeviceCaps(device, &caps);
2889 if (!(caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES))
2891 WARN("Device does not support blitting from textures.\n");
2892 IDirect3DDevice9_Release(device);
2893 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2896 This->d3d9_dev = device;
2897 IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2899 if (!(This->d3d9_surfaces = calloc(*numbuffers, sizeof(IDirect3DSurface9 *))))
2900 return E_OUTOFMEMORY;
2902 hr = VMR9_SurfaceAllocator_SetAllocationSettings(This, info);
2903 if (FAILED(hr))
2904 ERR("Setting allocation settings failed: %08x\n", hr);
2906 if (SUCCEEDED(hr))
2908 hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, info, numbuffers, This->d3d9_surfaces);
2909 if (FAILED(hr))
2910 ERR("Allocating surfaces failed: %08x\n", hr);
2913 if (FAILED(hr))
2915 IVMRSurfaceAllocator9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
2916 return hr;
2919 This->num_surfaces = *numbuffers;
2921 return S_OK;
2924 static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocator9 *iface, DWORD_PTR cookie)
2926 TRACE("iface %p, cookie %#lx.\n", iface, cookie);
2928 return S_OK;
2931 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocator9 *iface,
2932 DWORD_PTR cookie, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
2934 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
2936 /* Update everything first, this is needed because the surface might be destroyed in the reset */
2937 if (!This->d3d9_dev)
2939 TRACE("Device has left me!\n");
2940 return E_FAIL;
2943 if (surfaceindex >= This->num_surfaces)
2945 ERR("surfaceindex is greater than num_surfaces\n");
2946 return E_FAIL;
2948 *surface = This->d3d9_surfaces[surfaceindex];
2949 IDirect3DSurface9_AddRef(*surface);
2951 return S_OK;
2954 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocator9 *iface,
2955 IVMRSurfaceAllocatorNotify9 *notify)
2957 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2959 TRACE("presenter %p, notify %p.\n", presenter, notify);
2961 /* No AddRef taken here or the base VMR9 filter would never be destroyed */
2962 presenter->SurfaceAllocatorNotify = notify;
2963 return S_OK;
2966 static const IVMRSurfaceAllocator9Vtbl VMR9_SurfaceAllocator =
2968 VMR9_SurfaceAllocator_QueryInterface,
2969 VMR9_SurfaceAllocator_AddRef,
2970 VMR9_SurfaceAllocator_Release,
2971 VMR9_SurfaceAllocator_InitializeDevice,
2972 VMR9_SurfaceAllocator_TerminateDevice,
2973 VMR9_SurfaceAllocator_GetSurface,
2974 VMR9_SurfaceAllocator_AdviseNotify,
2977 static IDirect3D9 *init_d3d9(HMODULE d3d9_handle)
2979 IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion);
2981 d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
2982 if (!d3d9_create) return NULL;
2984 return d3d9_create(D3D_SDK_VERSION);
2987 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(struct quartz_vmr *parent, LPVOID * ppv)
2989 struct default_presenter *object;
2990 HRESULT hr = S_OK;
2991 int i;
2993 if (!(object = calloc(1, sizeof(*object))))
2994 return E_OUTOFMEMORY;
2996 object->d3d9_ptr = init_d3d9(parent->hD3d9);
2997 if (!object->d3d9_ptr)
2999 WARN("Could not initialize d3d9.dll\n");
3000 free(object);
3001 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3004 i = 0;
3007 D3DDISPLAYMODE mode;
3009 hr = IDirect3D9_EnumAdapterModes(object->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode);
3010 if (hr == D3DERR_INVALIDCALL) break; /* out of adapters */
3011 } while (FAILED(hr));
3012 if (FAILED(hr))
3013 ERR("HR: %08x\n", hr);
3014 if (hr == D3DERR_NOTAVAILABLE)
3016 ERR("Format not supported\n");
3017 IDirect3D9_Release(object->d3d9_ptr);
3018 free(object);
3019 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3022 object->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
3023 object->IVMRSurfaceAllocator9_iface.lpVtbl = &VMR9_SurfaceAllocator;
3025 object->refCount = 1;
3026 object->pVMR9 = parent;
3028 TRACE("Created default presenter %p.\n", object);
3029 *ppv = &object->IVMRImagePresenter9_iface;
3030 return S_OK;