winemac.drv: Don't filter non active displays out.
[wine/zf.git] / dlls / quartz / vmr9.c
blob2562b74932a8c6957cf33f476c9cf62eea198142
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_free(struct quartz_vmr *filter)
533 free(filter);
534 InterlockedDecrement(&object_locks);
537 static void vmr_destroy(struct strmbase_renderer *iface)
539 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
541 video_window_cleanup(&filter->window);
543 /* Devil May Cry 3 releases the IVMRSurfaceAllocatorNotify9 interface from
544 * TerminateDevice(). Artificially increase the reference count so that we
545 * don't free the filter yet. */
546 InterlockedIncrement(&filter->renderer.filter.refcount);
548 if (filter->allocator)
550 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
551 IVMRSurfaceAllocator9_Release(filter->allocator);
553 if (filter->presenter)
554 IVMRImagePresenter9_Release(filter->presenter);
556 filter->num_surfaces = 0;
557 if (filter->allocator_d3d9_dev)
559 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
560 filter->allocator_d3d9_dev = NULL;
563 FreeLibrary(filter->hD3d9);
564 strmbase_renderer_cleanup(&filter->renderer);
565 if (!filter->IVMRSurfaceAllocatorNotify9_refcount)
566 vmr_free(filter);
569 static HRESULT vmr_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
571 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
573 if (IsEqualGUID(iid, &IID_IVideoWindow))
574 *out = &filter->window.IVideoWindow_iface;
575 else if (IsEqualGUID(iid, &IID_IBasicVideo))
576 *out = &filter->window.IBasicVideo_iface;
577 else if (IsEqualGUID(iid, &IID_IAMCertifiedOutputProtection))
578 *out = &filter->IAMCertifiedOutputProtection_iface;
579 else if (IsEqualGUID(iid, &IID_IAMFilterMiscFlags))
580 *out = &filter->IAMFilterMiscFlags_iface;
581 else if (IsEqualGUID(iid, &IID_IVMRAspectRatioControl9) && is_vmr9(filter))
582 *out = &filter->IVMRAspectRatioControl9_iface;
583 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig) && !is_vmr9(filter))
584 *out = &filter->IVMRFilterConfig_iface;
585 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig9) && is_vmr9(filter))
586 *out = &filter->IVMRFilterConfig9_iface;
587 else if (IsEqualGUID(iid, &IID_IVMRMixerBitmap9) && is_vmr9(filter))
588 *out = &filter->IVMRMixerBitmap9_iface;
589 else if (IsEqualGUID(iid, &IID_IVMRMixerControl9) && is_vmr9(filter) && filter->stream_count)
590 *out = &filter->IVMRMixerControl9_iface;
591 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig) && !is_vmr9(filter))
592 *out = &filter->IVMRMonitorConfig_iface;
593 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig9)
594 && filter->mode != VMR9Mode_Renderless && is_vmr9(filter))
595 *out = &filter->IVMRMonitorConfig9_iface;
596 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify)
597 && filter->mode == (VMR9Mode)VMRMode_Renderless && !is_vmr9(filter))
598 *out = &filter->IVMRSurfaceAllocatorNotify_iface;
599 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify9)
600 && filter->mode == VMR9Mode_Renderless && is_vmr9(filter))
601 *out = &filter->IVMRSurfaceAllocatorNotify9_iface;
602 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl)
603 && filter->mode == (VMR9Mode)VMRMode_Windowless && !is_vmr9(filter))
604 *out = &filter->IVMRWindowlessControl_iface;
605 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl9)
606 && filter->mode == VMR9Mode_Windowless && is_vmr9(filter))
607 *out = &filter->IVMRWindowlessControl9_iface;
608 else
609 return E_NOINTERFACE;
611 IUnknown_AddRef((IUnknown *)*out);
612 return S_OK;
615 static HRESULT vmr_pin_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
617 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
619 if (IsEqualGUID(iid, &IID_IOverlay))
620 *out = &filter->IOverlay_iface;
621 else
622 return E_NOINTERFACE;
624 IUnknown_AddRef((IUnknown *)*out);
625 return S_OK;
628 static const struct strmbase_renderer_ops renderer_ops =
630 .renderer_query_accept = vmr_query_accept,
631 .renderer_render = vmr_render,
632 .renderer_init_stream = vmr_init_stream,
633 .renderer_start_stream = vmr_start_stream,
634 .renderer_stop_stream = vmr_stop_stream,
635 .renderer_connect = vmr_connect,
636 .renderer_disconnect = vmr_disconnect,
637 .renderer_destroy = vmr_destroy,
638 .renderer_query_interface = vmr_query_interface,
639 .renderer_pin_query_interface = vmr_pin_query_interface,
642 static RECT vmr_get_default_rect(struct video_window *This)
644 struct quartz_vmr *pVMR9 = impl_from_video_window(This);
645 static RECT defRect;
647 SetRect(&defRect, 0, 0, pVMR9->VideoWidth, pVMR9->VideoHeight);
649 return defRect;
652 static HRESULT vmr_get_current_image(struct video_window *iface, LONG *size, LONG *image)
654 struct quartz_vmr *filter = impl_from_video_window(iface);
655 IDirect3DSurface9 *rt = NULL, *surface = NULL;
656 D3DLOCKED_RECT locked_rect;
657 IDirect3DDevice9 *device;
658 unsigned int row_size;
659 BITMAPINFOHEADER bih;
660 LONG i, size_left;
661 char *dst;
662 HRESULT hr;
664 EnterCriticalSection(&filter->renderer.filter.stream_cs);
665 device = filter->allocator_d3d9_dev;
667 bih = *get_bitmap_header(&filter->renderer.sink.pin.mt);
668 bih.biSizeImage = bih.biWidth * bih.biHeight * bih.biBitCount / 8;
670 if (!image)
672 *size = sizeof(BITMAPINFOHEADER) + bih.biSizeImage;
673 LeaveCriticalSection(&filter->renderer.filter.stream_cs);
674 return S_OK;
677 if (FAILED(hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt)))
678 goto out;
680 if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, bih.biWidth,
681 bih.biHeight, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL)))
682 goto out;
684 if (FAILED(hr = IDirect3DDevice9_GetRenderTargetData(device, rt, surface)))
685 goto out;
687 if (FAILED(hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_READONLY)))
688 goto out;
690 size_left = *size;
691 memcpy(image, &bih, min(size_left, sizeof(BITMAPINFOHEADER)));
692 size_left -= sizeof(BITMAPINFOHEADER);
694 dst = (char *)image + sizeof(BITMAPINFOHEADER);
695 row_size = bih.biWidth * bih.biBitCount / 8;
697 for (i = 0; i < bih.biHeight && size_left > 0; ++i)
699 memcpy(dst, (char *)locked_rect.pBits + (i * locked_rect.Pitch), min(row_size, size_left));
700 dst += row_size;
701 size_left -= row_size;
704 IDirect3DSurface9_UnlockRect(surface);
706 out:
707 if (surface) IDirect3DSurface9_Release(surface);
708 if (rt) IDirect3DSurface9_Release(rt);
709 LeaveCriticalSection(&filter->renderer.filter.stream_cs);
710 return hr;
713 static const struct video_window_ops window_ops =
715 .get_default_rect = vmr_get_default_rect,
716 .get_current_image = vmr_get_current_image,
719 static const IVideoWindowVtbl IVideoWindow_VTable =
721 BaseControlWindowImpl_QueryInterface,
722 BaseControlWindowImpl_AddRef,
723 BaseControlWindowImpl_Release,
724 BaseControlWindowImpl_GetTypeInfoCount,
725 BaseControlWindowImpl_GetTypeInfo,
726 BaseControlWindowImpl_GetIDsOfNames,
727 BaseControlWindowImpl_Invoke,
728 BaseControlWindowImpl_put_Caption,
729 BaseControlWindowImpl_get_Caption,
730 BaseControlWindowImpl_put_WindowStyle,
731 BaseControlWindowImpl_get_WindowStyle,
732 BaseControlWindowImpl_put_WindowStyleEx,
733 BaseControlWindowImpl_get_WindowStyleEx,
734 BaseControlWindowImpl_put_AutoShow,
735 BaseControlWindowImpl_get_AutoShow,
736 BaseControlWindowImpl_put_WindowState,
737 BaseControlWindowImpl_get_WindowState,
738 BaseControlWindowImpl_put_BackgroundPalette,
739 BaseControlWindowImpl_get_BackgroundPalette,
740 BaseControlWindowImpl_put_Visible,
741 BaseControlWindowImpl_get_Visible,
742 BaseControlWindowImpl_put_Left,
743 BaseControlWindowImpl_get_Left,
744 BaseControlWindowImpl_put_Width,
745 BaseControlWindowImpl_get_Width,
746 BaseControlWindowImpl_put_Top,
747 BaseControlWindowImpl_get_Top,
748 BaseControlWindowImpl_put_Height,
749 BaseControlWindowImpl_get_Height,
750 BaseControlWindowImpl_put_Owner,
751 BaseControlWindowImpl_get_Owner,
752 BaseControlWindowImpl_put_MessageDrain,
753 BaseControlWindowImpl_get_MessageDrain,
754 BaseControlWindowImpl_get_BorderColor,
755 BaseControlWindowImpl_put_BorderColor,
756 BaseControlWindowImpl_get_FullScreenMode,
757 BaseControlWindowImpl_put_FullScreenMode,
758 BaseControlWindowImpl_SetWindowForeground,
759 BaseControlWindowImpl_NotifyOwnerMessage,
760 BaseControlWindowImpl_SetWindowPosition,
761 BaseControlWindowImpl_GetWindowPosition,
762 BaseControlWindowImpl_GetMinIdealImageSize,
763 BaseControlWindowImpl_GetMaxIdealImageSize,
764 BaseControlWindowImpl_GetRestorePosition,
765 BaseControlWindowImpl_HideCursor,
766 BaseControlWindowImpl_IsCursorHidden
769 static HRESULT WINAPI AMCertifiedOutputProtection_QueryInterface(IAMCertifiedOutputProtection *iface,
770 REFIID riid, void **ppv)
772 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
773 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
776 static ULONG WINAPI AMCertifiedOutputProtection_AddRef(IAMCertifiedOutputProtection *iface)
778 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
779 return IUnknown_AddRef(This->renderer.filter.outer_unk);
782 static ULONG WINAPI AMCertifiedOutputProtection_Release(IAMCertifiedOutputProtection *iface)
784 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
785 return IUnknown_Release(This->renderer.filter.outer_unk);
788 static HRESULT WINAPI AMCertifiedOutputProtection_KeyExchange(IAMCertifiedOutputProtection *iface,
789 GUID* pRandom, BYTE** VarLenCertGH,
790 DWORD* pdwLengthCertGH)
792 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
794 FIXME("(%p/%p)->(%p, %p, %p) stub\n", iface, This, pRandom, VarLenCertGH, pdwLengthCertGH);
795 return VFW_E_NO_COPP_HW;
798 static HRESULT WINAPI AMCertifiedOutputProtection_SessionSequenceStart(IAMCertifiedOutputProtection *iface,
799 AMCOPPSignature* pSig)
801 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
803 FIXME("(%p/%p)->(%p) stub\n", iface, This, pSig);
804 return VFW_E_NO_COPP_HW;
807 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionCommand(IAMCertifiedOutputProtection *iface,
808 const AMCOPPCommand* cmd)
810 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
812 FIXME("(%p/%p)->(%p) stub\n", iface, This, cmd);
813 return VFW_E_NO_COPP_HW;
816 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionStatus(IAMCertifiedOutputProtection *iface,
817 const AMCOPPStatusInput* pStatusInput,
818 AMCOPPStatusOutput* pStatusOutput)
820 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
822 FIXME("(%p/%p)->(%p, %p) stub\n", iface, This, pStatusInput, pStatusOutput);
823 return VFW_E_NO_COPP_HW;
826 static const IAMCertifiedOutputProtectionVtbl IAMCertifiedOutputProtection_Vtbl =
828 AMCertifiedOutputProtection_QueryInterface,
829 AMCertifiedOutputProtection_AddRef,
830 AMCertifiedOutputProtection_Release,
831 AMCertifiedOutputProtection_KeyExchange,
832 AMCertifiedOutputProtection_SessionSequenceStart,
833 AMCertifiedOutputProtection_ProtectionCommand,
834 AMCertifiedOutputProtection_ProtectionStatus
837 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
838 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
839 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
842 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
843 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
844 return IUnknown_AddRef(This->renderer.filter.outer_unk);
847 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
848 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
849 return IUnknown_Release(This->renderer.filter.outer_unk);
852 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
853 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
856 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
857 AMFilterMiscFlags_QueryInterface,
858 AMFilterMiscFlags_AddRef,
859 AMFilterMiscFlags_Release,
860 AMFilterMiscFlags_GetMiscFlags
863 static HRESULT WINAPI VMR7FilterConfig_QueryInterface(IVMRFilterConfig *iface, REFIID riid,
864 void** ppv)
866 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
867 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
870 static ULONG WINAPI VMR7FilterConfig_AddRef(IVMRFilterConfig *iface)
872 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
873 return IUnknown_AddRef(This->renderer.filter.outer_unk);
876 static ULONG WINAPI VMR7FilterConfig_Release(IVMRFilterConfig *iface)
878 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
879 return IUnknown_Release(This->renderer.filter.outer_unk);
882 static HRESULT WINAPI VMR7FilterConfig_SetImageCompositor(IVMRFilterConfig *iface,
883 IVMRImageCompositor *compositor)
885 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
887 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
888 return E_NOTIMPL;
891 static HRESULT WINAPI VMR7FilterConfig_SetNumberOfStreams(IVMRFilterConfig *iface, DWORD max)
893 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
895 FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
896 return E_NOTIMPL;
899 static HRESULT WINAPI VMR7FilterConfig_GetNumberOfStreams(IVMRFilterConfig *iface, DWORD *max)
901 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
903 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
904 return E_NOTIMPL;
907 static HRESULT WINAPI VMR7FilterConfig_SetRenderingPrefs(IVMRFilterConfig *iface, DWORD renderflags)
909 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
911 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
912 return E_NOTIMPL;
915 static HRESULT WINAPI VMR7FilterConfig_GetRenderingPrefs(IVMRFilterConfig *iface, DWORD *renderflags)
917 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
919 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
920 return E_NOTIMPL;
923 static HRESULT WINAPI VMR7FilterConfig_SetRenderingMode(IVMRFilterConfig *iface, DWORD mode)
925 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
927 TRACE("iface %p, mode %#x.\n", iface, mode);
929 return IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, mode);
932 static HRESULT WINAPI VMR7FilterConfig_GetRenderingMode(IVMRFilterConfig *iface, DWORD *mode)
934 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
936 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
937 if (!mode) return E_POINTER;
939 if (This->mode)
940 *mode = This->mode;
941 else
942 *mode = VMRMode_Windowed;
944 return S_OK;
947 static const IVMRFilterConfigVtbl VMR7_FilterConfig_Vtbl =
949 VMR7FilterConfig_QueryInterface,
950 VMR7FilterConfig_AddRef,
951 VMR7FilterConfig_Release,
952 VMR7FilterConfig_SetImageCompositor,
953 VMR7FilterConfig_SetNumberOfStreams,
954 VMR7FilterConfig_GetNumberOfStreams,
955 VMR7FilterConfig_SetRenderingPrefs,
956 VMR7FilterConfig_GetRenderingPrefs,
957 VMR7FilterConfig_SetRenderingMode,
958 VMR7FilterConfig_GetRenderingMode
961 struct get_available_monitors_args
963 VMRMONITORINFO *info7;
964 VMR9MonitorInfo *info9;
965 DWORD arraysize;
966 DWORD numdev;
969 static BOOL CALLBACK get_available_monitors_proc(HMONITOR hmon, HDC hdc, LPRECT lprc, LPARAM lparam)
971 struct get_available_monitors_args *args = (struct get_available_monitors_args *)lparam;
972 MONITORINFOEXW mi;
974 if (args->info7 || args->info9)
977 if (!args->arraysize)
978 return FALSE;
980 mi.cbSize = sizeof(mi);
981 if (!GetMonitorInfoW(hmon, (MONITORINFO*)&mi))
982 return TRUE;
984 /* fill VMRMONITORINFO struct */
985 if (args->info7)
987 VMRMONITORINFO *info = args->info7++;
988 memset(info, 0, sizeof(*info));
990 if (args->numdev > 0)
992 info->guid.pGUID = &info->guid.GUID;
993 info->guid.GUID.Data4[7] = args->numdev;
995 else
996 info->guid.pGUID = NULL;
998 info->rcMonitor = mi.rcMonitor;
999 info->hMon = hmon;
1000 info->dwFlags = mi.dwFlags;
1002 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1004 /* FIXME: how to get these values? */
1005 info->szDescription[0] = 0;
1008 /* fill VMR9MonitorInfo struct */
1009 if (args->info9)
1011 VMR9MonitorInfo *info = args->info9++;
1012 memset(info, 0, sizeof(*info));
1014 info->uDevID = 0; /* FIXME */
1015 info->rcMonitor = mi.rcMonitor;
1016 info->hMon = hmon;
1017 info->dwFlags = mi.dwFlags;
1019 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1021 /* FIXME: how to get these values? */
1022 info->szDescription[0] = 0;
1023 info->dwVendorId = 0;
1024 info->dwDeviceId = 0;
1025 info->dwSubSysId = 0;
1026 info->dwRevision = 0;
1029 args->arraysize--;
1032 args->numdev++;
1033 return TRUE;
1036 static HRESULT WINAPI VMR7MonitorConfig_QueryInterface(IVMRMonitorConfig *iface, REFIID riid,
1037 LPVOID * ppv)
1039 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1040 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1043 static ULONG WINAPI VMR7MonitorConfig_AddRef(IVMRMonitorConfig *iface)
1045 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1046 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1049 static ULONG WINAPI VMR7MonitorConfig_Release(IVMRMonitorConfig *iface)
1051 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1052 return IUnknown_Release(This->renderer.filter.outer_unk);
1055 static HRESULT WINAPI VMR7MonitorConfig_SetMonitor(IVMRMonitorConfig *iface, const VMRGUID *pGUID)
1057 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1059 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1061 if (!pGUID)
1062 return E_POINTER;
1064 return S_OK;
1067 static HRESULT WINAPI VMR7MonitorConfig_GetMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1069 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1071 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1073 if (!pGUID)
1074 return E_POINTER;
1076 pGUID->pGUID = NULL; /* default DirectDraw device */
1077 return S_OK;
1080 static HRESULT WINAPI VMR7MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig *iface,
1081 const VMRGUID *pGUID)
1083 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1085 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1087 if (!pGUID)
1088 return E_POINTER;
1090 return S_OK;
1093 static HRESULT WINAPI VMR7MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1095 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1097 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1099 if (!pGUID)
1100 return E_POINTER;
1102 pGUID->pGUID = NULL; /* default DirectDraw device */
1103 return S_OK;
1106 static HRESULT WINAPI VMR7MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig *iface,
1107 VMRMONITORINFO *info, DWORD arraysize,
1108 DWORD *numdev)
1110 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1111 struct get_available_monitors_args args;
1113 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1115 if (!numdev)
1116 return E_POINTER;
1118 if (info && arraysize == 0)
1119 return E_INVALIDARG;
1121 args.info7 = info;
1122 args.info9 = NULL;
1123 args.arraysize = arraysize;
1124 args.numdev = 0;
1125 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1127 *numdev = args.numdev;
1128 return S_OK;
1131 static const IVMRMonitorConfigVtbl VMR7_MonitorConfig_Vtbl =
1133 VMR7MonitorConfig_QueryInterface,
1134 VMR7MonitorConfig_AddRef,
1135 VMR7MonitorConfig_Release,
1136 VMR7MonitorConfig_SetMonitor,
1137 VMR7MonitorConfig_GetMonitor,
1138 VMR7MonitorConfig_SetDefaultMonitor,
1139 VMR7MonitorConfig_GetDefaultMonitor,
1140 VMR7MonitorConfig_GetAvailableMonitors
1143 static HRESULT WINAPI VMR9MonitorConfig_QueryInterface(IVMRMonitorConfig9 *iface, REFIID riid,
1144 LPVOID * ppv)
1146 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1147 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1150 static ULONG WINAPI VMR9MonitorConfig_AddRef(IVMRMonitorConfig9 *iface)
1152 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1153 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1156 static ULONG WINAPI VMR9MonitorConfig_Release(IVMRMonitorConfig9 *iface)
1158 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1159 return IUnknown_Release(This->renderer.filter.outer_unk);
1162 static HRESULT WINAPI VMR9MonitorConfig_SetMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1164 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1166 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1168 return S_OK;
1171 static HRESULT WINAPI VMR9MonitorConfig_GetMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1173 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1175 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1177 if (!uDev)
1178 return E_POINTER;
1180 *uDev = 0;
1181 return S_OK;
1184 static HRESULT WINAPI VMR9MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1186 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1188 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1190 return S_OK;
1193 static HRESULT WINAPI VMR9MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1195 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1197 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1199 if (!uDev)
1200 return E_POINTER;
1202 *uDev = 0;
1203 return S_OK;
1206 static HRESULT WINAPI VMR9MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig9 *iface,
1207 VMR9MonitorInfo *info, DWORD arraysize,
1208 DWORD *numdev)
1210 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1211 struct get_available_monitors_args args;
1213 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1215 if (!numdev)
1216 return E_POINTER;
1218 if (info && arraysize == 0)
1219 return E_INVALIDARG;
1221 args.info7 = NULL;
1222 args.info9 = info;
1223 args.arraysize = arraysize;
1224 args.numdev = 0;
1225 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1227 *numdev = args.numdev;
1228 return S_OK;
1231 static const IVMRMonitorConfig9Vtbl VMR9_MonitorConfig_Vtbl =
1233 VMR9MonitorConfig_QueryInterface,
1234 VMR9MonitorConfig_AddRef,
1235 VMR9MonitorConfig_Release,
1236 VMR9MonitorConfig_SetMonitor,
1237 VMR9MonitorConfig_GetMonitor,
1238 VMR9MonitorConfig_SetDefaultMonitor,
1239 VMR9MonitorConfig_GetDefaultMonitor,
1240 VMR9MonitorConfig_GetAvailableMonitors
1243 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
1245 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1246 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1249 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
1251 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1252 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1255 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
1257 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1258 return IUnknown_Release(This->renderer.filter.outer_unk);
1261 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
1263 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1265 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
1266 return E_NOTIMPL;
1269 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD count)
1271 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1273 FIXME("iface %p, count %u, stub!\n", iface, count);
1275 if (!count)
1277 WARN("Application requested zero streams; returning E_INVALIDARG.\n");
1278 return E_INVALIDARG;
1281 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1283 if (filter->stream_count)
1285 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1286 WARN("Stream count is already set; returning VFW_E_WRONG_STATE.\n");
1287 return VFW_E_WRONG_STATE;
1290 filter->stream_count = count;
1292 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1293 return S_OK;
1296 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *count)
1298 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1300 TRACE("filter %p, count %p.\n", filter, count);
1302 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1304 if (!filter->stream_count)
1306 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1307 return VFW_E_VMR_NOT_IN_MIXER_MODE;
1310 *count = filter->stream_count;
1312 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1313 return S_OK;
1316 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
1318 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1320 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
1321 return E_NOTIMPL;
1324 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
1326 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1328 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
1329 return E_NOTIMPL;
1332 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
1334 HRESULT hr = S_OK;
1335 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1337 TRACE("(%p/%p)->(%u)\n", iface, This, mode);
1339 EnterCriticalSection(&This->renderer.filter.filter_cs);
1340 if (This->mode)
1342 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1343 return VFW_E_WRONG_STATE;
1346 if (This->allocator)
1347 IVMRSurfaceAllocator9_Release(This->allocator);
1348 if (This->presenter)
1349 IVMRImagePresenter9_Release(This->presenter);
1351 This->allocator = NULL;
1352 This->presenter = NULL;
1354 switch (mode)
1356 case VMR9Mode_Windowed:
1357 case VMR9Mode_Windowless:
1358 This->cookie = ~0;
1360 if (FAILED(hr = VMR9DefaultAllocatorPresenterImpl_create(This, (void **)&This->presenter)))
1362 ERR("Failed to create default presenter, hr %#x.\n", hr);
1363 break;
1366 if (FAILED(hr = IVMRImagePresenter9_QueryInterface(This->presenter,
1367 &IID_IVMRSurfaceAllocator9, (void **)&This->allocator)))
1369 ERR("Failed to query for IVMRSurfaceAllocator9, hr %#x.\n", hr);
1370 IVMRImagePresenter9_Release(This->presenter);
1371 This->allocator = NULL;
1372 This->presenter = NULL;
1373 break;
1376 hr = IVMRSurfaceAllocator9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
1377 break;
1378 case VMR9Mode_Renderless:
1379 break;
1380 default:
1381 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1382 return E_INVALIDARG;
1385 if (mode != VMR9Mode_Windowed)
1386 video_window_cleanup(&This->window);
1388 This->mode = mode;
1389 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1390 return hr;
1393 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
1395 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1397 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
1398 if (!mode)
1399 return E_POINTER;
1401 if (This->mode)
1402 *mode = This->mode;
1403 else
1404 *mode = VMR9Mode_Windowed;
1406 return S_OK;
1409 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
1411 VMR9FilterConfig_QueryInterface,
1412 VMR9FilterConfig_AddRef,
1413 VMR9FilterConfig_Release,
1414 VMR9FilterConfig_SetImageCompositor,
1415 VMR9FilterConfig_SetNumberOfStreams,
1416 VMR9FilterConfig_GetNumberOfStreams,
1417 VMR9FilterConfig_SetRenderingPrefs,
1418 VMR9FilterConfig_GetRenderingPrefs,
1419 VMR9FilterConfig_SetRenderingMode,
1420 VMR9FilterConfig_GetRenderingMode
1423 static HRESULT WINAPI VMR7WindowlessControl_QueryInterface(IVMRWindowlessControl *iface, REFIID riid,
1424 LPVOID * ppv)
1426 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1427 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1430 static ULONG WINAPI VMR7WindowlessControl_AddRef(IVMRWindowlessControl *iface)
1432 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1433 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1436 static ULONG WINAPI VMR7WindowlessControl_Release(IVMRWindowlessControl *iface)
1438 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1439 return IUnknown_Release(This->renderer.filter.outer_unk);
1442 static HRESULT WINAPI VMR7WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl *iface,
1443 LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height)
1445 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1447 TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n",
1448 filter, width, height, aspect_width, aspect_height);
1450 if (!width || !height)
1451 return E_POINTER;
1453 *width = filter->bmiheader.biWidth;
1454 *height = filter->bmiheader.biHeight;
1455 if (aspect_width)
1456 *aspect_width = filter->bmiheader.biWidth;
1457 if (aspect_height)
1458 *aspect_height = filter->bmiheader.biHeight;
1460 return S_OK;
1463 static HRESULT WINAPI VMR7WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl *iface,
1464 LONG *width, LONG *height)
1466 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1468 FIXME("(%p/%p)->(...) stub\n", iface, This);
1469 return E_NOTIMPL;
1472 static HRESULT WINAPI VMR7WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl *iface,
1473 LONG *width, LONG *height)
1475 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1477 FIXME("(%p/%p)->(...) stub\n", iface, This);
1478 return E_NOTIMPL;
1481 static HRESULT WINAPI VMR7WindowlessControl_SetVideoPosition(IVMRWindowlessControl *iface,
1482 const RECT *source, const RECT *dest)
1484 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1486 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1488 EnterCriticalSection(&This->renderer.filter.filter_cs);
1490 if (source)
1491 This->window.src = *source;
1492 if (dest)
1493 This->window.dst = *dest;
1495 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1497 return S_OK;
1500 static HRESULT WINAPI VMR7WindowlessControl_GetVideoPosition(IVMRWindowlessControl *iface,
1501 RECT *source, RECT *dest)
1503 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1505 if (source)
1506 *source = This->window.src;
1508 if (dest)
1509 *dest = This->window.dst;
1511 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1512 return S_OK;
1515 static HRESULT WINAPI VMR7WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl *iface,
1516 DWORD *mode)
1518 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1520 FIXME("(%p/%p)->(...) stub\n", iface, This);
1521 return E_NOTIMPL;
1524 static HRESULT WINAPI VMR7WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl *iface,
1525 DWORD mode)
1527 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1529 FIXME("(%p/%p)->(...) stub\n", iface, This);
1530 return E_NOTIMPL;
1533 static HRESULT WINAPI VMR7WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl *iface, HWND window)
1535 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1537 TRACE("iface %p, window %p.\n", iface, window);
1539 return IVMRWindowlessControl9_SetVideoClippingWindow(&filter->IVMRWindowlessControl9_iface, window);
1542 static HRESULT WINAPI VMR7WindowlessControl_RepaintVideo(IVMRWindowlessControl *iface,
1543 HWND hwnd, HDC hdc)
1545 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1547 FIXME("(%p/%p)->(...) stub\n", iface, This);
1548 return E_NOTIMPL;
1551 static HRESULT WINAPI VMR7WindowlessControl_DisplayModeChanged(IVMRWindowlessControl *iface)
1553 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1555 FIXME("(%p/%p)->(...) stub\n", iface, This);
1556 return E_NOTIMPL;
1559 static HRESULT WINAPI VMR7WindowlessControl_GetCurrentImage(IVMRWindowlessControl *iface,
1560 BYTE **dib)
1562 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1564 FIXME("(%p/%p)->(...) stub\n", iface, This);
1565 return E_NOTIMPL;
1568 static HRESULT WINAPI VMR7WindowlessControl_SetBorderColor(IVMRWindowlessControl *iface,
1569 COLORREF color)
1571 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1573 FIXME("(%p/%p)->(...) stub\n", iface, This);
1574 return E_NOTIMPL;
1577 static HRESULT WINAPI VMR7WindowlessControl_GetBorderColor(IVMRWindowlessControl *iface,
1578 COLORREF *color)
1580 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1582 FIXME("(%p/%p)->(...) stub\n", iface, This);
1583 return E_NOTIMPL;
1586 static HRESULT WINAPI VMR7WindowlessControl_SetColorKey(IVMRWindowlessControl *iface, COLORREF color)
1588 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1590 FIXME("(%p/%p)->(...) stub\n", iface, This);
1591 return E_NOTIMPL;
1594 static HRESULT WINAPI VMR7WindowlessControl_GetColorKey(IVMRWindowlessControl *iface, COLORREF *color)
1596 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1598 FIXME("(%p/%p)->(...) stub\n", iface, This);
1599 return E_NOTIMPL;
1602 static const IVMRWindowlessControlVtbl VMR7_WindowlessControl_Vtbl =
1604 VMR7WindowlessControl_QueryInterface,
1605 VMR7WindowlessControl_AddRef,
1606 VMR7WindowlessControl_Release,
1607 VMR7WindowlessControl_GetNativeVideoSize,
1608 VMR7WindowlessControl_GetMinIdealVideoSize,
1609 VMR7WindowlessControl_GetMaxIdealVideoSize,
1610 VMR7WindowlessControl_SetVideoPosition,
1611 VMR7WindowlessControl_GetVideoPosition,
1612 VMR7WindowlessControl_GetAspectRatioMode,
1613 VMR7WindowlessControl_SetAspectRatioMode,
1614 VMR7WindowlessControl_SetVideoClippingWindow,
1615 VMR7WindowlessControl_RepaintVideo,
1616 VMR7WindowlessControl_DisplayModeChanged,
1617 VMR7WindowlessControl_GetCurrentImage,
1618 VMR7WindowlessControl_SetBorderColor,
1619 VMR7WindowlessControl_GetBorderColor,
1620 VMR7WindowlessControl_SetColorKey,
1621 VMR7WindowlessControl_GetColorKey
1624 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
1626 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1627 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1630 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
1632 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1633 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1636 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
1638 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1639 return IUnknown_Release(This->renderer.filter.outer_unk);
1642 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface,
1643 LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height)
1645 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1647 TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n",
1648 filter, width, height, aspect_width, aspect_height);
1650 if (!width || !height)
1651 return E_POINTER;
1653 *width = filter->bmiheader.biWidth;
1654 *height = filter->bmiheader.biHeight;
1655 if (aspect_width)
1656 *aspect_width = filter->bmiheader.biWidth;
1657 if (aspect_height)
1658 *aspect_height = filter->bmiheader.biHeight;
1660 return S_OK;
1663 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1665 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1667 FIXME("(%p/%p)->(...) stub\n", iface, This);
1668 return E_NOTIMPL;
1671 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1673 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1675 FIXME("(%p/%p)->(...) stub\n", iface, This);
1676 return E_NOTIMPL;
1679 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface,
1680 const RECT *src, const RECT *dst)
1682 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1684 TRACE("filter %p, src %s, dst %s.\n", filter, wine_dbgstr_rect(src), wine_dbgstr_rect(dst));
1686 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1688 if (src)
1689 filter->window.src = *src;
1690 if (dst)
1691 filter->window.dst = *dst;
1693 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1695 return S_OK;
1698 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *src, RECT *dst)
1700 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1702 TRACE("filter %p, src %p, dst %p.\n", filter, src, dst);
1704 if (src)
1705 *src = filter->window.src;
1707 if (dst)
1708 *dst = filter->window.dst;
1710 return S_OK;
1713 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1715 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1717 TRACE("filter %p, mode %p.\n", filter, mode);
1719 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1720 *mode = filter->aspect_mode;
1721 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1722 return S_OK;
1725 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1727 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1729 TRACE("filter %p, mode %u.\n", filter, mode);
1731 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1732 filter->aspect_mode = mode;
1733 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1734 return S_OK;
1737 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND window)
1739 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1740 HRESULT hr;
1742 TRACE("filter %p, window %p.\n", filter, window);
1744 if (!IsWindow(window))
1746 WARN("Invalid window %p, returning E_INVALIDARG.\n", window);
1747 return E_INVALIDARG;
1750 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1752 if (filter->renderer.sink.pin.peer)
1754 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1755 WARN("Attempt to set the clipping window while connected; returning VFW_E_WRONG_STATE.\n");
1756 return VFW_E_WRONG_STATE;
1759 filter->clipping_window = window;
1761 hr = IVMRFilterConfig9_SetNumberOfStreams(&filter->IVMRFilterConfig9_iface, 4);
1763 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1764 return hr;
1767 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1769 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1770 HRESULT hr;
1772 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1774 EnterCriticalSection(&This->renderer.filter.filter_cs);
1775 if (hwnd != This->clipping_window)
1777 ERR("Not handling changing windows yet!!!\n");
1778 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1779 return S_OK;
1782 if (!This->allocator_d3d9_dev)
1784 ERR("No d3d9 device!\n");
1785 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1786 return VFW_E_WRONG_STATE;
1789 /* Windowless extension */
1790 hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, NULL, NULL);
1791 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1793 return hr;
1796 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1798 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1800 FIXME("(%p/%p)->(...) stub\n", iface, This);
1801 return E_NOTIMPL;
1804 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1806 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1808 FIXME("(%p/%p)->(...) stub\n", iface, This);
1809 return E_NOTIMPL;
1812 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1814 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1816 FIXME("(%p/%p)->(...) stub\n", iface, This);
1817 return E_NOTIMPL;
1820 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1822 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1824 FIXME("(%p/%p)->(...) stub\n", iface, This);
1825 return E_NOTIMPL;
1828 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1830 VMR9WindowlessControl_QueryInterface,
1831 VMR9WindowlessControl_AddRef,
1832 VMR9WindowlessControl_Release,
1833 VMR9WindowlessControl_GetNativeVideoSize,
1834 VMR9WindowlessControl_GetMinIdealVideoSize,
1835 VMR9WindowlessControl_GetMaxIdealVideoSize,
1836 VMR9WindowlessControl_SetVideoPosition,
1837 VMR9WindowlessControl_GetVideoPosition,
1838 VMR9WindowlessControl_GetAspectRatioMode,
1839 VMR9WindowlessControl_SetAspectRatioMode,
1840 VMR9WindowlessControl_SetVideoClippingWindow,
1841 VMR9WindowlessControl_RepaintVideo,
1842 VMR9WindowlessControl_DisplayModeChanged,
1843 VMR9WindowlessControl_GetCurrentImage,
1844 VMR9WindowlessControl_SetBorderColor,
1845 VMR9WindowlessControl_GetBorderColor
1848 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify *iface,
1849 REFIID riid, LPVOID * ppv)
1851 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1852 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1855 static ULONG WINAPI VMR7SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify *iface)
1857 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1858 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1861 static ULONG WINAPI VMR7SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify *iface)
1863 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1864 return IUnknown_Release(This->renderer.filter.outer_unk);
1867 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify *iface,
1868 DWORD_PTR id,
1869 IVMRSurfaceAllocator *alloc)
1871 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1873 FIXME("(%p/%p)->(...) stub\n", iface, This);
1874 return E_NOTIMPL;
1877 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1878 IDirectDraw7 *device, HMONITOR monitor)
1880 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1882 FIXME("(%p/%p)->(...) stub\n", iface, This);
1883 return E_NOTIMPL;
1886 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_ChangeDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1887 IDirectDraw7 *device, HMONITOR monitor)
1889 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1891 FIXME("(%p/%p)->(...) stub\n", iface, This);
1892 return E_NOTIMPL;
1895 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces(IVMRSurfaceAllocatorNotify *iface)
1897 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1899 FIXME("(%p/%p)->(...) stub\n", iface, This);
1900 return E_NOTIMPL;
1903 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify *iface, LONG code,
1904 LONG_PTR param1, LONG_PTR param2)
1906 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1908 FIXME("(%p/%p)->(...) stub\n", iface, This);
1909 return E_NOTIMPL;
1912 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetBorderColor(IVMRSurfaceAllocatorNotify *iface,
1913 COLORREF clrBorder)
1915 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1917 FIXME("(%p/%p)->(...) stub\n", iface, This);
1918 return E_NOTIMPL;
1921 static const IVMRSurfaceAllocatorNotifyVtbl VMR7_SurfaceAllocatorNotify_Vtbl =
1923 VMR7SurfaceAllocatorNotify_QueryInterface,
1924 VMR7SurfaceAllocatorNotify_AddRef,
1925 VMR7SurfaceAllocatorNotify_Release,
1926 VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1927 VMR7SurfaceAllocatorNotify_SetDDrawDevice,
1928 VMR7SurfaceAllocatorNotify_ChangeDDrawDevice,
1929 VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces,
1930 VMR7SurfaceAllocatorNotify_NotifyEvent,
1931 VMR7SurfaceAllocatorNotify_SetBorderColor
1934 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1936 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1937 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1940 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1942 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1943 ULONG refcount = InterlockedIncrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1945 TRACE("%p increasing refcount to %u.\n", iface, refcount);
1947 return refcount;
1950 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1952 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1953 ULONG refcount = InterlockedDecrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1955 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
1957 if (!refcount && !filter->renderer.filter.refcount)
1958 vmr_free(filter);
1960 return refcount;
1963 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(
1964 IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR cookie, IVMRSurfaceAllocator9 *allocator)
1966 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1967 IVMRImagePresenter9 *presenter;
1969 TRACE("filter %p, cookie %#Ix, allocator %p.\n", filter, cookie, allocator);
1971 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1973 filter->cookie = cookie;
1975 if (filter->renderer.sink.pin.peer)
1977 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1978 WARN("Attempt to set allocator while connected; returning VFW_E_WRONG_STATE.\n");
1979 return VFW_E_WRONG_STATE;
1982 if (FAILED(IVMRSurfaceAllocator9_QueryInterface(allocator, &IID_IVMRImagePresenter9, (void **)&presenter)))
1984 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1985 return E_NOINTERFACE;
1988 if (filter->allocator)
1990 IVMRImagePresenter9_Release(filter->presenter);
1991 IVMRSurfaceAllocator9_Release(filter->allocator);
1993 filter->allocator = allocator;
1994 filter->presenter = presenter;
1995 IVMRSurfaceAllocator9_AddRef(allocator);
1997 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1998 return S_OK;
2001 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface,
2002 IDirect3DDevice9 *device, HMONITOR monitor)
2004 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2006 TRACE("filter %p, device %p, monitor %p.\n", filter, device, monitor);
2008 if (filter->allocator_d3d9_dev)
2009 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
2010 filter->allocator_d3d9_dev = device;
2011 IDirect3DDevice9_AddRef(device);
2013 return S_OK;
2016 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
2018 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2020 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
2021 if (This->allocator_d3d9_dev)
2022 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
2023 This->allocator_d3d9_dev = device;
2024 IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
2026 return S_OK;
2029 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
2031 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2032 DWORD i;
2033 HRESULT hr = S_OK;
2035 TRACE("filter %p, allocinfo %p, numbuffers %p, surface %p.\n", This, numbuffers, allocinfo, surface);
2037 if (!allocinfo || !numbuffers || !surface)
2038 return E_POINTER;
2040 TRACE("Flags %#x, size %ux%u, format %u (%#x), pool %u, minimum buffers %u.\n",
2041 allocinfo->dwFlags, allocinfo->dwWidth, allocinfo->dwHeight,
2042 allocinfo->Format, allocinfo->Format, allocinfo->Pool, allocinfo->MinBuffers);
2044 if ((allocinfo->dwFlags & VMR9AllocFlag_TextureSurface)
2045 && (allocinfo->dwFlags & VMR9AllocFlag_OffscreenSurface))
2047 WARN("Invalid flags specified; returning E_INVALIDARG.\n");
2048 return E_INVALIDARG;
2051 if (!allocinfo->Format)
2053 IDirect3DSurface9 *backbuffer;
2054 D3DSURFACE_DESC desc;
2056 IDirect3DDevice9_GetBackBuffer(This->allocator_d3d9_dev, 0, 0,
2057 D3DBACKBUFFER_TYPE_MONO, &backbuffer);
2058 IDirect3DSurface9_GetDesc(backbuffer, &desc);
2059 IDirect3DSurface9_Release(backbuffer);
2060 allocinfo->Format = desc.Format;
2063 if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
2065 WARN("%u surfaces requested (minimum %u); returning E_INVALIDARG.\n",
2066 *numbuffers, allocinfo->MinBuffers);
2067 return E_INVALIDARG;
2070 if (!This->allocator_d3d9_dev)
2072 WARN("No Direct3D device; returning VFW_E_WRONG_STATE.\n");
2073 return VFW_E_WRONG_STATE;
2076 if (allocinfo->dwFlags == VMR9AllocFlag_OffscreenSurface)
2078 for (i = 0; i < *numbuffers; ++i)
2080 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight,
2081 allocinfo->Format, allocinfo->Pool, &surface[i], NULL);
2082 if (FAILED(hr))
2083 break;
2086 else if (allocinfo->dwFlags == VMR9AllocFlag_TextureSurface)
2088 for (i = 0; i < *numbuffers; ++i)
2090 IDirect3DTexture9 *texture;
2092 hr = IDirect3DDevice9_CreateTexture(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, 1, D3DUSAGE_DYNAMIC,
2093 allocinfo->Format, allocinfo->Pool, &texture, NULL);
2094 if (FAILED(hr))
2095 break;
2096 IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface[i]);
2097 IDirect3DTexture9_Release(texture);
2100 else if (allocinfo->dwFlags == VMR9AllocFlag_3DRenderTarget)
2102 for (i = 0; i < *numbuffers; ++i)
2104 if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(This->allocator_d3d9_dev,
2105 allocinfo->dwWidth, allocinfo->dwHeight, allocinfo->Format,
2106 D3DMULTISAMPLE_NONE, 0, FALSE, &surface[i], NULL)))
2107 break;
2110 else
2112 FIXME("Unhandled flags %#x.\n", allocinfo->dwFlags);
2113 return E_NOTIMPL;
2116 if (FAILED(hr))
2117 WARN("%u/%u surfaces allocated, hr %#x.\n", i, *numbuffers, hr);
2119 if (i >= allocinfo->MinBuffers)
2121 hr = S_OK;
2122 *numbuffers = i;
2124 else
2126 for ( ; i > 0; --i) IDirect3DSurface9_Release(surface[i - 1]);
2127 *numbuffers = 0;
2129 return hr;
2132 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
2134 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2136 FIXME("(%p/%p)->(...) stub\n", iface, This);
2137 return E_NOTIMPL;
2140 static const IVMRSurfaceAllocatorNotify9Vtbl VMR9_SurfaceAllocatorNotify_Vtbl =
2142 VMR9SurfaceAllocatorNotify_QueryInterface,
2143 VMR9SurfaceAllocatorNotify_AddRef,
2144 VMR9SurfaceAllocatorNotify_Release,
2145 VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
2146 VMR9SurfaceAllocatorNotify_SetD3DDevice,
2147 VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
2148 VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
2149 VMR9SurfaceAllocatorNotify_NotifyEvent
2152 static inline struct quartz_vmr *impl_from_IVMRMixerControl9(IVMRMixerControl9 *iface)
2154 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerControl9_iface);
2157 static HRESULT WINAPI mixer_control9_QueryInterface(IVMRMixerControl9 *iface, REFIID iid, void **out)
2159 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2160 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2163 static ULONG WINAPI mixer_control9_AddRef(IVMRMixerControl9 *iface)
2165 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2166 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2169 static ULONG WINAPI mixer_control9_Release(IVMRMixerControl9 *iface)
2171 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2172 return IUnknown_Release(filter->renderer.filter.outer_unk);
2175 static HRESULT WINAPI mixer_control9_SetAlpha(IVMRMixerControl9 *iface, DWORD stream, float alpha)
2177 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2179 FIXME("filter %p, stream %u, alpha %.8e, stub!\n", filter, stream, alpha);
2181 return E_NOTIMPL;
2184 static HRESULT WINAPI mixer_control9_GetAlpha(IVMRMixerControl9 *iface, DWORD stream, float *alpha)
2186 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2188 FIXME("filter %p, stream %u, alpha %p, stub!\n", filter, stream, alpha);
2190 return E_NOTIMPL;
2193 static HRESULT WINAPI mixer_control9_SetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD z)
2195 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2197 FIXME("filter %p, stream %u, z %u, stub!\n", filter, stream, z);
2199 return E_NOTIMPL;
2202 static HRESULT WINAPI mixer_control9_GetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD *z)
2204 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2206 FIXME("filter %p, stream %u, z %p, stub!\n", filter, stream, z);
2208 return E_NOTIMPL;
2211 static HRESULT WINAPI mixer_control9_SetOutputRect(IVMRMixerControl9 *iface,
2212 DWORD stream, const VMR9NormalizedRect *rect)
2214 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2216 FIXME("filter %p, stream %u, rect %s, stub!\n", filter, stream, debugstr_normalized_rect(rect));
2218 return E_NOTIMPL;
2221 static HRESULT WINAPI mixer_control9_GetOutputRect(IVMRMixerControl9 *iface,
2222 DWORD stream, VMR9NormalizedRect *rect)
2224 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2226 FIXME("filter %p, stream %u, rect %p, stub!\n", filter, stream, rect);
2228 return E_NOTIMPL;
2231 static HRESULT WINAPI mixer_control9_SetBackgroundClr(IVMRMixerControl9 *iface, COLORREF color)
2233 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2235 FIXME("filter %p, color #%06x, stub!\n", filter, color);
2237 return E_NOTIMPL;
2240 static HRESULT WINAPI mixer_control9_GetBackgroundClr(IVMRMixerControl9 *iface, COLORREF *color)
2242 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2244 FIXME("filter %p, color %p, stub!\n", filter, color);
2246 return E_NOTIMPL;
2249 static HRESULT WINAPI mixer_control9_SetMixingPrefs(IVMRMixerControl9 *iface, DWORD flags)
2251 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2253 FIXME("filter %p, flags %#x, stub!\n", filter, flags);
2255 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2256 filter->mixing_prefs = flags;
2257 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2258 return S_OK;
2261 static HRESULT WINAPI mixer_control9_GetMixingPrefs(IVMRMixerControl9 *iface, DWORD *flags)
2263 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2265 FIXME("filter %p, flags %p, stub!\n", filter, flags);
2267 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2268 *flags = filter->mixing_prefs;
2269 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2270 return S_OK;
2273 static HRESULT WINAPI mixer_control9_SetProcAmpControl(IVMRMixerControl9 *iface,
2274 DWORD stream, VMR9ProcAmpControl *settings)
2276 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2278 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2280 return E_NOTIMPL;
2283 static HRESULT WINAPI mixer_control9_GetProcAmpControl(IVMRMixerControl9 *iface,
2284 DWORD stream, VMR9ProcAmpControl *settings)
2286 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2288 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2290 return E_NOTIMPL;
2293 static HRESULT WINAPI mixer_control9_GetProcAmpControlRange(IVMRMixerControl9 *iface,
2294 DWORD stream, VMR9ProcAmpControlRange *settings)
2296 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2298 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2300 return E_NOTIMPL;
2303 static const IVMRMixerControl9Vtbl mixer_control9_vtbl =
2305 mixer_control9_QueryInterface,
2306 mixer_control9_AddRef,
2307 mixer_control9_Release,
2308 mixer_control9_SetAlpha,
2309 mixer_control9_GetAlpha,
2310 mixer_control9_SetZOrder,
2311 mixer_control9_GetZOrder,
2312 mixer_control9_SetOutputRect,
2313 mixer_control9_GetOutputRect,
2314 mixer_control9_SetBackgroundClr,
2315 mixer_control9_GetBackgroundClr,
2316 mixer_control9_SetMixingPrefs,
2317 mixer_control9_GetMixingPrefs,
2318 mixer_control9_SetProcAmpControl,
2319 mixer_control9_GetProcAmpControl,
2320 mixer_control9_GetProcAmpControlRange,
2323 static inline struct quartz_vmr *impl_from_IVMRMixerBitmap9(IVMRMixerBitmap9 *iface)
2325 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerBitmap9_iface);
2328 static HRESULT WINAPI mixer_bitmap9_QueryInterface(IVMRMixerBitmap9 *iface, REFIID iid, void **out)
2330 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2331 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2334 static ULONG WINAPI mixer_bitmap9_AddRef(IVMRMixerBitmap9 *iface)
2336 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2337 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2340 static ULONG WINAPI mixer_bitmap9_Release(IVMRMixerBitmap9 *iface)
2342 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2343 return IUnknown_Release(filter->renderer.filter.outer_unk);
2346 static HRESULT WINAPI mixer_bitmap9_SetAlphaBitmap(IVMRMixerBitmap9 *iface,
2347 const VMR9AlphaBitmap *bitmap)
2349 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2350 TRACE("dwFlags %#x, hdc %p, pDDS %p, rSrc %s, rDest %s, fAlpha %.8e, clrSrcKey #%06x, dwFilterMode %#x.\n",
2351 bitmap->dwFlags, bitmap->hdc, bitmap->pDDS, wine_dbgstr_rect(&bitmap->rSrc),
2352 debugstr_normalized_rect(&bitmap->rDest), bitmap->fAlpha, bitmap->clrSrcKey, bitmap->dwFilterMode);
2353 return E_NOTIMPL;
2356 static HRESULT WINAPI mixer_bitmap9_UpdateAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2357 const VMR9AlphaBitmap *bitmap)
2359 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2360 return E_NOTIMPL;
2363 static HRESULT WINAPI mixer_bitmap9_GetAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2364 VMR9AlphaBitmap *bitmap)
2366 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2367 return E_NOTIMPL;
2370 static const IVMRMixerBitmap9Vtbl mixer_bitmap9_vtbl =
2372 mixer_bitmap9_QueryInterface,
2373 mixer_bitmap9_AddRef,
2374 mixer_bitmap9_Release,
2375 mixer_bitmap9_SetAlphaBitmap,
2376 mixer_bitmap9_UpdateAlphaBitmapParameters,
2377 mixer_bitmap9_GetAlphaBitmapParameters,
2380 static inline struct quartz_vmr *impl_from_IVMRAspectRatioControl9(IVMRAspectRatioControl9 *iface)
2382 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRAspectRatioControl9_iface);
2385 static HRESULT WINAPI aspect_ratio_control9_QueryInterface(IVMRAspectRatioControl9 *iface, REFIID iid, void **out)
2387 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2388 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2391 static ULONG WINAPI aspect_ratio_control9_AddRef(IVMRAspectRatioControl9 *iface)
2393 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2394 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2397 static ULONG WINAPI aspect_ratio_control9_Release(IVMRAspectRatioControl9 *iface)
2399 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2400 return IUnknown_Release(filter->renderer.filter.outer_unk);
2403 static HRESULT WINAPI aspect_ratio_control9_GetAspectRatioMode(IVMRAspectRatioControl9 *iface, DWORD *mode)
2405 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2407 TRACE("filter %p, mode %p.\n", filter, mode);
2409 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2410 *mode = filter->aspect_mode;
2411 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2412 return S_OK;
2415 static HRESULT WINAPI aspect_ratio_control9_SetAspectRatioMode(IVMRAspectRatioControl9 *iface, DWORD mode)
2417 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2419 TRACE("filter %p, mode %u.\n", filter, mode);
2421 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2422 filter->aspect_mode = mode;
2423 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2424 return S_OK;
2427 static const IVMRAspectRatioControl9Vtbl aspect_ratio_control9_vtbl =
2429 aspect_ratio_control9_QueryInterface,
2430 aspect_ratio_control9_AddRef,
2431 aspect_ratio_control9_Release,
2432 aspect_ratio_control9_GetAspectRatioMode,
2433 aspect_ratio_control9_SetAspectRatioMode,
2436 static inline struct quartz_vmr *impl_from_IOverlay(IOverlay *iface)
2438 return CONTAINING_RECORD(iface, struct quartz_vmr, IOverlay_iface);
2441 static HRESULT WINAPI overlay_QueryInterface(IOverlay *iface, REFIID iid, void **out)
2443 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2444 return IPin_QueryInterface(&filter->renderer.sink.pin.IPin_iface, iid, out);
2447 static ULONG WINAPI overlay_AddRef(IOverlay *iface)
2449 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2450 return IPin_AddRef(&filter->renderer.sink.pin.IPin_iface);
2453 static ULONG WINAPI overlay_Release(IOverlay *iface)
2455 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2456 return IPin_Release(&filter->renderer.sink.pin.IPin_iface);
2459 static HRESULT WINAPI overlay_GetPalette(IOverlay *iface, DWORD *count, PALETTEENTRY **palette)
2461 FIXME("iface %p, count %p, palette %p, stub!\n", iface, count, palette);
2462 return E_NOTIMPL;
2465 static HRESULT WINAPI overlay_SetPalette(IOverlay *iface, DWORD count, PALETTEENTRY *palette)
2467 FIXME("iface %p, count %u, palette %p, stub!\n", iface, count, palette);
2468 return E_NOTIMPL;
2471 static HRESULT WINAPI overlay_GetDefaultColorKey(IOverlay *iface, COLORKEY *key)
2473 FIXME("iface %p, key %p, stub!\n", iface, key);
2474 return E_NOTIMPL;
2477 static HRESULT WINAPI overlay_GetColorKey(IOverlay *iface, COLORKEY *key)
2479 FIXME("iface %p, key %p, stub!\n", iface, key);
2480 return E_NOTIMPL;
2483 static HRESULT WINAPI overlay_SetColorKey(IOverlay *iface, COLORKEY *key)
2485 FIXME("iface %p, key %p, stub!\n", iface, key);
2486 return E_NOTIMPL;
2489 static HRESULT WINAPI overlay_GetWindowHandle(IOverlay *iface, HWND *window)
2491 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2493 TRACE("filter %p, window %p.\n", filter, window);
2495 if (!filter->window.hwnd)
2496 return VFW_E_WRONG_STATE;
2498 *window = filter->window.hwnd;
2499 return S_OK;
2502 static HRESULT WINAPI overlay_GetClipList(IOverlay *iface, RECT *source, RECT *dest, RGNDATA **region)
2504 FIXME("iface %p, source %p, dest %p, region %p, stub!\n", iface, source, dest, region);
2505 return E_NOTIMPL;
2508 static HRESULT WINAPI overlay_GetVideoPosition(IOverlay *iface, RECT *source, RECT *dest)
2510 FIXME("iface %p, source %p, dest %p, stub!\n", iface, source, dest);
2511 return E_NOTIMPL;
2514 static HRESULT WINAPI overlay_Advise(IOverlay *iface, IOverlayNotify *sink, DWORD flags)
2516 FIXME("iface %p, sink %p, flags %#x, stub!\n", iface, sink, flags);
2517 return E_NOTIMPL;
2520 static HRESULT WINAPI overlay_Unadvise(IOverlay *iface)
2522 FIXME("iface %p, stub!\n", iface);
2523 return E_NOTIMPL;
2526 static const IOverlayVtbl overlay_vtbl =
2528 overlay_QueryInterface,
2529 overlay_AddRef,
2530 overlay_Release,
2531 overlay_GetPalette,
2532 overlay_SetPalette,
2533 overlay_GetDefaultColorKey,
2534 overlay_GetColorKey,
2535 overlay_SetColorKey,
2536 overlay_GetWindowHandle,
2537 overlay_GetClipList,
2538 overlay_GetVideoPosition,
2539 overlay_Advise,
2540 overlay_Unadvise,
2543 static HRESULT vmr_create(IUnknown *outer, IUnknown **out, const CLSID *clsid)
2545 struct quartz_vmr *object;
2546 HRESULT hr;
2548 if (!(object = calloc(1, sizeof(*object))))
2549 return E_OUTOFMEMORY;
2551 object->hD3d9 = LoadLibraryA("d3d9.dll");
2552 if (!object->hD3d9)
2554 WARN("Could not load d3d9.dll\n");
2555 free(object);
2556 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2559 strmbase_renderer_init(&object->renderer, outer, clsid, L"VMR Input0", &renderer_ops);
2560 object->IAMCertifiedOutputProtection_iface.lpVtbl = &IAMCertifiedOutputProtection_Vtbl;
2561 object->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
2562 object->IVMRAspectRatioControl9_iface.lpVtbl = &aspect_ratio_control9_vtbl;
2563 object->IVMRFilterConfig_iface.lpVtbl = &VMR7_FilterConfig_Vtbl;
2564 object->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
2565 object->IVMRMixerBitmap9_iface.lpVtbl = &mixer_bitmap9_vtbl;
2566 object->IVMRMixerControl9_iface.lpVtbl = &mixer_control9_vtbl;
2567 object->IVMRMonitorConfig_iface.lpVtbl = &VMR7_MonitorConfig_Vtbl;
2568 object->IVMRMonitorConfig9_iface.lpVtbl = &VMR9_MonitorConfig_Vtbl;
2569 object->IVMRSurfaceAllocatorNotify_iface.lpVtbl = &VMR7_SurfaceAllocatorNotify_Vtbl;
2570 object->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &VMR9_SurfaceAllocatorNotify_Vtbl;
2571 object->IVMRWindowlessControl_iface.lpVtbl = &VMR7_WindowlessControl_Vtbl;
2572 object->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
2573 object->IOverlay_iface.lpVtbl = &overlay_vtbl;
2575 video_window_init(&object->window, &IVideoWindow_VTable,
2576 &object->renderer.filter, &object->renderer.sink.pin, &window_ops);
2578 if (FAILED(hr = video_window_create_window(&object->window)))
2580 video_window_cleanup(&object->window);
2581 strmbase_renderer_cleanup(&object->renderer);
2582 FreeLibrary(object->hD3d9);
2583 free(object);
2584 return hr;
2587 object->mixing_prefs = MixerPref9_NoDecimation | MixerPref9_ARAdjustXorY
2588 | MixerPref9_BiLinearFiltering | MixerPref9_RenderTargetRGB;
2590 TRACE("Created VMR %p.\n", object);
2591 *out = &object->renderer.filter.IUnknown_inner;
2592 return S_OK;
2595 HRESULT vmr7_create(IUnknown *outer, IUnknown **out)
2597 return vmr_create(outer, out, &CLSID_VideoMixingRenderer);
2600 HRESULT vmr9_create(IUnknown *outer, IUnknown **out)
2602 return vmr_create(outer, out, &CLSID_VideoMixingRenderer9);
2606 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, void **ppv)
2608 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2610 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
2612 *ppv = NULL;
2614 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IVMRImagePresenter9))
2615 *ppv = &This->IVMRImagePresenter9_iface;
2616 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocator9))
2617 *ppv = &This->IVMRSurfaceAllocator9_iface;
2619 if (*ppv)
2621 IUnknown_AddRef((IUnknown *)(*ppv));
2622 return S_OK;
2625 FIXME("No interface for %s\n", debugstr_guid(riid));
2627 return E_NOINTERFACE;
2630 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
2632 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2633 ULONG refCount = InterlockedIncrement(&This->refCount);
2635 TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
2637 return refCount;
2640 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
2642 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2643 ULONG refCount = InterlockedDecrement(&This->refCount);
2645 TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
2647 if (!refCount)
2649 DWORD i;
2650 TRACE("Destroying\n");
2651 IDirect3D9_Release(This->d3d9_ptr);
2653 TRACE("Number of surfaces: %u\n", This->num_surfaces);
2654 for (i = 0; i < This->num_surfaces; ++i)
2656 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2657 TRACE("Releasing surface %p\n", surface);
2658 if (surface)
2659 IDirect3DSurface9_Release(surface);
2662 if (This->d3d9_dev)
2663 IDirect3DDevice9_Release(This->d3d9_dev);
2664 free(This->d3d9_surfaces);
2665 This->d3d9_surfaces = NULL;
2666 This->num_surfaces = 0;
2667 free(This);
2668 return 0;
2670 return refCount;
2673 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2675 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2677 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2679 return S_OK;
2682 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2684 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2686 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2688 return S_OK;
2691 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface,
2692 DWORD_PTR cookie, VMR9PresentationInfo *info)
2694 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2695 const struct quartz_vmr *filter = presenter->pVMR9;
2696 IDirect3DDevice9 *device = presenter->d3d9_dev;
2697 const RECT src = filter->window.src;
2698 IDirect3DSurface9 *backbuffer;
2699 RECT dst = filter->window.dst;
2700 HRESULT hr;
2702 TRACE("presenter %p, cookie %#Ix, info %p.\n", presenter, cookie, info);
2704 /* This might happen if we don't have active focus (eg on a different virtual desktop) */
2705 if (!device)
2706 return S_OK;
2708 if (FAILED(hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET,
2709 D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0)))
2710 ERR("Failed to clear, hr %#x.\n", hr);
2712 if (FAILED(hr = IDirect3DDevice9_BeginScene(device)))
2713 ERR("Failed to begin scene, hr %#x.\n", hr);
2715 if (FAILED(hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer)))
2717 ERR("Failed to get backbuffer, hr %#x.\n", hr);
2718 return hr;
2721 if (FAILED(hr = IDirect3DDevice9_StretchRect(device, info->lpSurf, NULL, backbuffer, NULL, D3DTEXF_POINT)))
2722 ERR("Failed to blit image, hr %#x.\n", hr);
2723 IDirect3DSurface9_Release(backbuffer);
2725 if (FAILED(hr = IDirect3DDevice9_EndScene(device)))
2726 ERR("Failed to end scene, hr %#x.\n", hr);
2728 if (filter->aspect_mode == VMR9ARMode_LetterBox)
2730 unsigned int src_width = src.right - src.left, src_height = src.bottom - src.top;
2731 unsigned int dst_width = dst.right - dst.left, dst_height = dst.bottom - dst.top;
2733 if (src_width * dst_height > dst_width * src_height)
2735 /* src is "wider" than dst. */
2736 unsigned int dst_center = (dst.top + dst.bottom) / 2;
2737 unsigned int scaled_height = src_height * dst_width / src_width;
2739 dst.top = dst_center - scaled_height / 2;
2740 dst.bottom = dst.top + scaled_height;
2742 else if (src_width * dst_height < dst_width * src_height)
2744 /* src is "taller" than dst. */
2745 unsigned int dst_center = (dst.left + dst.right) / 2;
2746 unsigned int scaled_width = src_width * dst_height / src_height;
2748 dst.left = dst_center - scaled_width / 2;
2749 dst.right = dst.left + scaled_width;
2753 if (FAILED(hr = IDirect3DDevice9_Present(device, &src, &dst, NULL, NULL)))
2754 ERR("Failed to present, hr %#x.\n", hr);
2756 return S_OK;
2759 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
2761 VMR9_ImagePresenter_QueryInterface,
2762 VMR9_ImagePresenter_AddRef,
2763 VMR9_ImagePresenter_Release,
2764 VMR9_ImagePresenter_StartPresenting,
2765 VMR9_ImagePresenter_StopPresenting,
2766 VMR9_ImagePresenter_PresentImage
2769 static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocator9 *iface, REFIID iid, void **out)
2771 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2772 return IVMRImagePresenter9_QueryInterface(&presenter->IVMRImagePresenter9_iface, iid, out);
2775 static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocator9 *iface)
2777 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2778 return IVMRImagePresenter9_AddRef(&presenter->IVMRImagePresenter9_iface);
2781 static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocator9 *iface)
2783 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2784 return IVMRImagePresenter9_Release(&presenter->IVMRImagePresenter9_iface);
2787 static HRESULT VMR9_SurfaceAllocator_SetAllocationSettings(struct default_presenter *This, VMR9AllocationInfo *allocinfo)
2789 D3DCAPS9 caps;
2790 UINT width, height;
2791 HRESULT hr;
2793 if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface))
2794 /* Only needed for texture surfaces */
2795 return S_OK;
2797 hr = IDirect3DDevice9_GetDeviceCaps(This->d3d9_dev, &caps);
2798 if (FAILED(hr))
2799 return hr;
2801 if (!(caps.TextureCaps & D3DPTEXTURECAPS_POW2) || (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY))
2803 width = allocinfo->dwWidth;
2804 height = allocinfo->dwHeight;
2806 else
2808 width = height = 1;
2809 while (width < allocinfo->dwWidth)
2810 width *= 2;
2812 while (height < allocinfo->dwHeight)
2813 height *= 2;
2814 FIXME("NPOW2 support missing, not using proper surfaces!\n");
2817 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
2819 if (height > width)
2820 width = height;
2821 else
2822 height = width;
2823 FIXME("Square texture support required..\n");
2826 allocinfo->dwHeight = height;
2827 allocinfo->dwWidth = width;
2829 return hr;
2832 static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
2834 UINT d3d9_adapter;
2835 HMONITOR mon;
2837 mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
2838 if (!mon)
2839 d3d9_adapter = 0;
2840 else
2842 for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
2844 if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
2845 break;
2847 if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
2848 d3d9_adapter = 0;
2850 if (mon_out)
2851 *mon_out = mon;
2852 return d3d9_adapter;
2855 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocator9 *iface,
2856 DWORD_PTR cookie, VMR9AllocationInfo *info, DWORD *numbuffers)
2858 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
2859 D3DPRESENT_PARAMETERS d3dpp;
2860 IDirect3DDevice9 *device;
2861 DWORD d3d9_adapter;
2862 D3DCAPS9 caps;
2863 HWND window;
2864 HRESULT hr;
2866 TRACE("presenter %p, cookie %#Ix, info %p, numbuffers %p.\n", This, cookie, info, numbuffers);
2868 This->info = *info;
2870 if (This->pVMR9->mode == VMR9Mode_Windowed)
2871 window = This->pVMR9->window.hwnd;
2872 else
2873 window = This->pVMR9->clipping_window;
2875 /* Obtain a monitor and d3d9 device */
2876 d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, window, &This->hMon);
2878 /* Now try to create the d3d9 device */
2879 ZeroMemory(&d3dpp, sizeof(d3dpp));
2880 d3dpp.Windowed = TRUE;
2881 d3dpp.hDeviceWindow = window;
2882 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
2883 d3dpp.BackBufferWidth = info->dwWidth;
2884 d3dpp.BackBufferHeight = info->dwHeight;
2886 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL,
2887 NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
2888 if (FAILED(hr))
2890 ERR("Could not create device: %08x\n", hr);
2891 return hr;
2894 IDirect3DDevice9_GetDeviceCaps(device, &caps);
2895 if (!(caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES))
2897 WARN("Device does not support blitting from textures.\n");
2898 IDirect3DDevice9_Release(device);
2899 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2902 This->d3d9_dev = device;
2903 IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2905 if (!(This->d3d9_surfaces = calloc(*numbuffers, sizeof(IDirect3DSurface9 *))))
2906 return E_OUTOFMEMORY;
2908 hr = VMR9_SurfaceAllocator_SetAllocationSettings(This, info);
2909 if (FAILED(hr))
2910 ERR("Setting allocation settings failed: %08x\n", hr);
2912 if (SUCCEEDED(hr))
2914 hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, info, numbuffers, This->d3d9_surfaces);
2915 if (FAILED(hr))
2916 ERR("Allocating surfaces failed: %08x\n", hr);
2919 if (FAILED(hr))
2921 IVMRSurfaceAllocator9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
2922 return hr;
2925 This->num_surfaces = *numbuffers;
2927 return S_OK;
2930 static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocator9 *iface, DWORD_PTR cookie)
2932 TRACE("iface %p, cookie %#lx.\n", iface, cookie);
2934 return S_OK;
2937 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocator9 *iface,
2938 DWORD_PTR cookie, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
2940 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
2942 /* Update everything first, this is needed because the surface might be destroyed in the reset */
2943 if (!This->d3d9_dev)
2945 TRACE("Device has left me!\n");
2946 return E_FAIL;
2949 if (surfaceindex >= This->num_surfaces)
2951 ERR("surfaceindex is greater than num_surfaces\n");
2952 return E_FAIL;
2954 *surface = This->d3d9_surfaces[surfaceindex];
2955 IDirect3DSurface9_AddRef(*surface);
2957 return S_OK;
2960 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocator9 *iface,
2961 IVMRSurfaceAllocatorNotify9 *notify)
2963 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2965 TRACE("presenter %p, notify %p.\n", presenter, notify);
2967 /* No AddRef taken here or the base VMR9 filter would never be destroyed */
2968 presenter->SurfaceAllocatorNotify = notify;
2969 return S_OK;
2972 static const IVMRSurfaceAllocator9Vtbl VMR9_SurfaceAllocator =
2974 VMR9_SurfaceAllocator_QueryInterface,
2975 VMR9_SurfaceAllocator_AddRef,
2976 VMR9_SurfaceAllocator_Release,
2977 VMR9_SurfaceAllocator_InitializeDevice,
2978 VMR9_SurfaceAllocator_TerminateDevice,
2979 VMR9_SurfaceAllocator_GetSurface,
2980 VMR9_SurfaceAllocator_AdviseNotify,
2983 static IDirect3D9 *init_d3d9(HMODULE d3d9_handle)
2985 IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion);
2987 d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
2988 if (!d3d9_create) return NULL;
2990 return d3d9_create(D3D_SDK_VERSION);
2993 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(struct quartz_vmr *parent, LPVOID * ppv)
2995 struct default_presenter *object;
2996 HRESULT hr = S_OK;
2997 int i;
2999 if (!(object = calloc(1, sizeof(*object))))
3000 return E_OUTOFMEMORY;
3002 object->d3d9_ptr = init_d3d9(parent->hD3d9);
3003 if (!object->d3d9_ptr)
3005 WARN("Could not initialize d3d9.dll\n");
3006 free(object);
3007 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3010 i = 0;
3013 D3DDISPLAYMODE mode;
3015 hr = IDirect3D9_EnumAdapterModes(object->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode);
3016 if (hr == D3DERR_INVALIDCALL) break; /* out of adapters */
3017 } while (FAILED(hr));
3018 if (FAILED(hr))
3019 ERR("HR: %08x\n", hr);
3020 if (hr == D3DERR_NOTAVAILABLE)
3022 ERR("Format not supported\n");
3023 IDirect3D9_Release(object->d3d9_ptr);
3024 free(object);
3025 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3028 object->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
3029 object->IVMRSurfaceAllocator9_iface.lpVtbl = &VMR9_SurfaceAllocator;
3031 object->refCount = 1;
3032 object->pVMR9 = parent;
3034 TRACE("Created default presenter %p.\n", object);
3035 *ppv = &object->IVMRImagePresenter9_iface;
3036 return S_OK;