quartz: Recreate surfaces in VMR9SurfaceAllocatorNotify_ChangeD3DDevice.
[wine.git] / dlls / quartz / vmr9.c
blob6efc626f6f69579adc6b97510ce07d469d8befb4
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 "videoacc.h"
37 #include "vmr9.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
43 static inline const char *debugstr_normalized_rect(const VMR9NormalizedRect *rect)
45 if (!rect) return "(null)";
46 return wine_dbg_sprintf("(%.8e,%.8e)-(%.8e,%.8e)", rect->left, rect->top, rect->right, rect->bottom);
49 static const BITMAPINFOHEADER *get_bitmap_header(const AM_MEDIA_TYPE *mt)
51 if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
52 return &((VIDEOINFOHEADER *)mt->pbFormat)->bmiHeader;
53 else
54 return &((VIDEOINFOHEADER2 *)mt->pbFormat)->bmiHeader;
57 struct quartz_vmr
59 struct strmbase_renderer renderer;
60 struct video_window window;
62 IAMCertifiedOutputProtection IAMCertifiedOutputProtection_iface;
63 IAMFilterMiscFlags IAMFilterMiscFlags_iface;
64 IVMRAspectRatioControl9 IVMRAspectRatioControl9_iface;
65 IVMRFilterConfig IVMRFilterConfig_iface;
66 IVMRFilterConfig9 IVMRFilterConfig9_iface;
67 IVMRMixerBitmap9 IVMRMixerBitmap9_iface;
68 IVMRMixerControl9 IVMRMixerControl9_iface;
69 IVMRMonitorConfig IVMRMonitorConfig_iface;
70 IVMRMonitorConfig9 IVMRMonitorConfig9_iface;
71 IVMRSurfaceAllocatorNotify IVMRSurfaceAllocatorNotify_iface;
72 IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface;
73 IVMRWindowlessControl IVMRWindowlessControl_iface;
74 IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
76 /* Devil May Cry 3 releases the last IBaseFilter reference while still
77 * holding an IVMRSurfaceAllocatorNotify9 reference, and depends on
78 * IVMRSurfaceAllocator9::TerminateDevice() being called as a result.
79 * Native uses a separate reference count for IVMRSurfaceAllocatorNotify9. */
80 LONG IVMRSurfaceAllocatorNotify9_refcount;
82 IAMVideoAccelerator IAMVideoAccelerator_iface;
83 IOverlay IOverlay_iface;
85 IVMRSurfaceAllocator9 *allocator;
86 IVMRImagePresenter9 *presenter;
88 DWORD stream_count;
89 DWORD mixing_prefs;
92 * The Video Mixing Renderer supports 3 modes, renderless, windowless and windowed
93 * What I do is implement windowless as a special case of renderless, and then
94 * windowed also as a special case of windowless. This is probably the easiest way.
96 VMR9Mode mode;
97 BITMAPINFOHEADER bmiheader;
99 HMODULE hD3d9;
101 /* Presentation related members */
102 IDirect3DDevice9 *allocator_d3d9_dev;
103 IDirect3DSurface9 **surfaces;
104 DWORD num_surfaces;
105 DWORD cur_surface;
106 DWORD_PTR cookie;
108 HWND clipping_window;
110 LONG VideoWidth;
111 LONG VideoHeight;
112 VMR9AspectRatioMode aspect_mode;
115 static inline BOOL is_vmr9(const struct quartz_vmr *filter)
117 return IsEqualGUID(&filter->renderer.filter.clsid, &CLSID_VideoMixingRenderer9);
120 static inline struct quartz_vmr *impl_from_video_window(struct video_window *iface)
122 return CONTAINING_RECORD(iface, struct quartz_vmr, window);
125 static inline struct quartz_vmr *impl_from_IAMCertifiedOutputProtection(IAMCertifiedOutputProtection *iface)
127 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMCertifiedOutputProtection_iface);
130 static inline struct quartz_vmr *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
132 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMFilterMiscFlags_iface);
135 static inline struct quartz_vmr *impl_from_IVMRFilterConfig(IVMRFilterConfig *iface)
137 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig_iface);
140 static inline struct quartz_vmr *impl_from_IVMRFilterConfig9(IVMRFilterConfig9 *iface)
142 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig9_iface);
145 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig(IVMRMonitorConfig *iface)
147 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig_iface);
150 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig9(IVMRMonitorConfig9 *iface)
152 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig9_iface);
155 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify(IVMRSurfaceAllocatorNotify *iface)
157 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify_iface);
160 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify9(IVMRSurfaceAllocatorNotify9 *iface)
162 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify9_iface);
165 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl(IVMRWindowlessControl *iface)
167 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl_iface);
170 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl9(IVMRWindowlessControl9 *iface)
172 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl9_iface);
175 struct default_presenter
177 IVMRImagePresenter9 IVMRImagePresenter9_iface;
178 IVMRSurfaceAllocator9 IVMRSurfaceAllocator9_iface;
180 LONG refCount;
182 IDirect3DDevice9 *d3d9_dev;
183 IDirect3D9 *d3d9_ptr;
184 IDirect3DSurface9 **d3d9_surfaces;
185 HMONITOR hMon;
186 DWORD num_surfaces;
188 VMR9AllocationInfo info;
190 struct quartz_vmr* pVMR9;
191 IVMRSurfaceAllocatorNotify9 *SurfaceAllocatorNotify;
194 static inline struct default_presenter *impl_from_IVMRImagePresenter9(IVMRImagePresenter9 *iface)
196 return CONTAINING_RECORD(iface, struct default_presenter, IVMRImagePresenter9_iface);
199 static inline struct default_presenter *impl_from_IVMRSurfaceAllocator9(IVMRSurfaceAllocator9 *iface)
201 return CONTAINING_RECORD(iface, struct default_presenter, IVMRSurfaceAllocator9_iface);
204 static HRESULT default_presenter_create(struct quartz_vmr *parent, struct default_presenter **presenter);
206 static inline struct quartz_vmr *impl_from_IBaseFilter(IBaseFilter *iface)
208 return CONTAINING_RECORD(iface, struct quartz_vmr, renderer.filter.IBaseFilter_iface);
211 static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample)
213 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
214 unsigned int data_size, width, depth, src_pitch;
215 const BITMAPINFOHEADER *bitmap_header;
216 REFERENCE_TIME start_time, end_time;
217 VMR9PresentationInfo info = {};
218 D3DLOCKED_RECT locked_rect;
219 BYTE *data = NULL;
220 HRESULT hr;
221 int height;
223 TRACE("filter %p, sample %p.\n", filter, sample);
225 /* It is possible that there is no device at this point */
227 if (!filter->allocator || !filter->presenter)
229 ERR("NO PRESENTER!!\n");
230 return S_FALSE;
233 info.dwFlags = VMR9Sample_SrcDstRectsValid;
235 if (SUCCEEDED(hr = IMediaSample_GetTime(sample, &start_time, &end_time)))
236 info.dwFlags |= VMR9Sample_TimeValid;
238 if (IMediaSample_IsDiscontinuity(sample) == S_OK)
239 info.dwFlags |= VMR9Sample_Discontinuity;
241 if (IMediaSample_IsPreroll(sample) == S_OK)
242 info.dwFlags |= VMR9Sample_Preroll;
244 if (IMediaSample_IsSyncPoint(sample) == S_OK)
245 info.dwFlags |= VMR9Sample_SyncPoint;
247 if (FAILED(hr = IMediaSample_GetPointer(sample, &data)))
249 ERR("Failed to get pointer to sample data, hr %#lx.\n", hr);
250 return hr;
252 data_size = IMediaSample_GetActualDataLength(sample);
254 bitmap_header = get_bitmap_header(&filter->renderer.sink.pin.mt);
255 width = bitmap_header->biWidth;
256 height = bitmap_header->biHeight;
257 depth = bitmap_header->biBitCount;
258 if (bitmap_header->biCompression == mmioFOURCC('N','V','1','2')
259 || bitmap_header->biCompression == mmioFOURCC('Y','V','1','2'))
260 src_pitch = width;
261 else /* packed YUV (UYVY or YUY2) or RGB */
262 src_pitch = ((width * depth / 8) + 3) & ~3;
264 info.rtStart = start_time;
265 info.rtEnd = end_time;
266 info.szAspectRatio.cx = width;
267 info.szAspectRatio.cy = height;
268 info.lpSurf = filter->surfaces[(++filter->cur_surface) % filter->num_surfaces];
270 if (FAILED(hr = IDirect3DSurface9_LockRect(info.lpSurf, &locked_rect, NULL, D3DLOCK_DISCARD)))
272 ERR("Failed to lock surface, hr %#lx.\n", hr);
273 return hr;
276 if (height > 0 && bitmap_header->biCompression == BI_RGB)
278 BYTE *dst = (BYTE *)locked_rect.pBits + (height * locked_rect.Pitch);
279 const BYTE *src = data;
281 TRACE("Inverting image.\n");
283 while (height--)
285 dst -= locked_rect.Pitch;
286 memcpy(dst, src, width * depth / 8);
287 src += src_pitch;
290 else if (locked_rect.Pitch != src_pitch)
292 BYTE *dst = locked_rect.pBits;
293 const BYTE *src = data;
295 height = abs(height);
297 TRACE("Source pitch %u does not match dest pitch %u; copying manually.\n",
298 src_pitch, locked_rect.Pitch);
300 while (height--)
302 memcpy(dst, src, width * depth / 8);
303 src += src_pitch;
304 dst += locked_rect.Pitch;
307 else
309 memcpy(locked_rect.pBits, data, data_size);
312 IDirect3DSurface9_UnlockRect(info.lpSurf);
314 return IVMRImagePresenter9_PresentImage(filter->presenter, filter->cookie, &info);
317 static HRESULT vmr_query_accept(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
319 if (!IsEqualIID(&mt->majortype, &MEDIATYPE_Video) || !mt->pbFormat)
320 return S_FALSE;
322 if (!IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo)
323 && !IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo2))
324 return S_FALSE;
326 return S_OK;
329 static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *info, DWORD count)
331 HRESULT hr;
332 DWORD i;
334 if (FAILED(hr = IVMRSurfaceAllocator9_InitializeDevice(filter->allocator,
335 filter->cookie, info, &count)))
337 WARN("Failed to initialize device (flags %#lx), hr %#lx.\n", info->dwFlags, hr);
338 return hr;
341 for (i = 0; i < count; ++i)
343 if (FAILED(hr = IVMRSurfaceAllocator9_GetSurface(filter->allocator,
344 filter->cookie, i, 0, &filter->surfaces[i])))
346 ERR("Failed to get surface %lu, hr %#lx.\n", i, hr);
347 while (i--)
348 IDirect3DSurface9_Release(filter->surfaces[i]);
349 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
350 return hr;
354 return hr;
357 static HRESULT allocate_surfaces(struct quartz_vmr *filter, const AM_MEDIA_TYPE *mt)
359 VMR9AllocationInfo info = {};
360 HRESULT hr = E_FAIL;
361 DWORD count = 1;
362 unsigned int i;
364 static const struct
366 const GUID *subtype;
367 D3DFORMAT format;
368 DWORD flags;
370 formats[] =
372 {&MEDIASUBTYPE_ARGB1555, D3DFMT_A1R5G5B5, VMR9AllocFlag_TextureSurface},
373 {&MEDIASUBTYPE_ARGB32, D3DFMT_A8R8G8B8, VMR9AllocFlag_TextureSurface},
374 {&MEDIASUBTYPE_ARGB4444, D3DFMT_A4R4G4B4, VMR9AllocFlag_TextureSurface},
376 {&MEDIASUBTYPE_RGB24, D3DFMT_R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
377 {&MEDIASUBTYPE_RGB32, D3DFMT_X8R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
378 {&MEDIASUBTYPE_RGB555, D3DFMT_X1R5G5B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
379 {&MEDIASUBTYPE_RGB565, D3DFMT_R5G6B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
381 {&MEDIASUBTYPE_NV12, MAKEFOURCC('N','V','1','2'), VMR9AllocFlag_OffscreenSurface},
382 {&MEDIASUBTYPE_UYVY, D3DFMT_UYVY, VMR9AllocFlag_OffscreenSurface},
383 {&MEDIASUBTYPE_YUY2, D3DFMT_YUY2, VMR9AllocFlag_OffscreenSurface},
384 {&MEDIASUBTYPE_YV12, MAKEFOURCC('Y','V','1','2'), VMR9AllocFlag_OffscreenSurface},
387 TRACE("Initializing in mode %u, our window %p, clipping window %p.\n",
388 filter->mode, filter->window.hwnd, filter->clipping_window);
390 if (filter->mode == VMR9Mode_Windowless && !filter->clipping_window)
391 return S_OK;
393 info.Pool = D3DPOOL_DEFAULT;
394 info.MinBuffers = count;
395 info.dwWidth = info.szAspectRatio.cx = info.szNativeSize.cx = filter->bmiheader.biWidth;
396 info.dwHeight = info.szAspectRatio.cy = info.szNativeSize.cy = filter->bmiheader.biHeight;
398 if (!(filter->surfaces = calloc(count, sizeof(IDirect3DSurface9 *))))
399 return E_OUTOFMEMORY;
400 filter->num_surfaces = count;
401 filter->cur_surface = 0;
403 if (!is_vmr9(filter))
405 switch (filter->bmiheader.biCompression)
407 case BI_RGB:
408 switch (filter->bmiheader.biBitCount)
410 case 24: info.Format = D3DFMT_R8G8B8; break;
411 case 32: info.Format = D3DFMT_X8R8G8B8; break;
412 default:
413 FIXME("Unhandled bit depth %u.\n", filter->bmiheader.biBitCount);
414 free(filter->surfaces);
415 return VFW_E_TYPE_NOT_ACCEPTED;
418 info.dwFlags = VMR9AllocFlag_TextureSurface;
419 break;
421 case mmioFOURCC('N','V','1','2'):
422 case mmioFOURCC('U','Y','V','Y'):
423 case mmioFOURCC('Y','U','Y','2'):
424 case mmioFOURCC('Y','V','1','2'):
425 info.Format = filter->bmiheader.biCompression;
426 info.dwFlags = VMR9AllocFlag_OffscreenSurface;
427 break;
429 default:
430 WARN("Unhandled video compression %#lx.\n", filter->bmiheader.biCompression);
431 free(filter->surfaces);
432 return VFW_E_TYPE_NOT_ACCEPTED;
434 if (FAILED(hr = initialize_device(filter, &info, count)))
435 free(filter->surfaces);
436 return hr;
439 for (i = 0; i < ARRAY_SIZE(formats); ++i)
441 if (IsEqualGUID(&mt->subtype, formats[i].subtype))
443 info.Format = formats[i].format;
445 if (formats[i].flags & VMR9AllocFlag_TextureSurface)
447 info.dwFlags = VMR9AllocFlag_TextureSurface;
448 if (SUCCEEDED(hr = initialize_device(filter, &info, count)))
449 return hr;
452 if (formats[i].flags & VMR9AllocFlag_OffscreenSurface)
454 info.dwFlags = VMR9AllocFlag_OffscreenSurface;
455 if (SUCCEEDED(hr = initialize_device(filter, &info, count)))
456 return hr;
461 free(filter->surfaces);
462 return VFW_E_TYPE_NOT_ACCEPTED;
465 static void vmr_init_stream(struct strmbase_renderer *iface)
467 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
469 if (filter->window.hwnd && filter->window.AutoShow)
470 ShowWindow(filter->window.hwnd, SW_SHOW);
473 static void vmr_start_stream(struct strmbase_renderer *iface)
475 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
477 IVMRImagePresenter9_StartPresenting(filter->presenter, filter->cookie);
480 static void vmr_stop_stream(struct strmbase_renderer *iface)
482 struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
484 TRACE("(%p)\n", This);
486 if (This->renderer.filter.state == State_Running)
487 IVMRImagePresenter9_StopPresenting(This->presenter, This->cookie);
490 static HRESULT vmr_connect(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
492 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
493 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(mt);
494 HWND window = filter->window.hwnd;
495 HRESULT hr;
496 RECT rect;
498 filter->bmiheader = *bitmap_header;
499 filter->VideoWidth = bitmap_header->biWidth;
500 filter->VideoHeight = bitmap_header->biHeight;
501 SetRect(&rect, 0, 0, filter->VideoWidth, filter->VideoHeight);
502 filter->window.src = rect;
504 AdjustWindowRectEx(&rect, GetWindowLongW(window, GWL_STYLE), FALSE,
505 GetWindowLongW(window, GWL_EXSTYLE));
506 SetWindowPos(window, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
507 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
508 GetClientRect(window, &filter->window.dst);
510 if (filter->mode
511 || SUCCEEDED(hr = IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, VMR9Mode_Windowed)))
512 hr = allocate_surfaces(filter, mt);
514 return hr;
517 static void deallocate_surfaces(struct quartz_vmr *filter)
519 DWORD i;
521 if (filter->mode && filter->allocator && filter->presenter)
523 for (i = 0; i < filter->num_surfaces; ++i)
524 IDirect3DSurface9_Release(filter->surfaces[i]);
525 free(filter->surfaces);
527 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
528 filter->num_surfaces = 0;
532 static void vmr_disconnect(struct strmbase_renderer *This)
534 struct quartz_vmr *filter = impl_from_IBaseFilter(&This->filter.IBaseFilter_iface);
535 deallocate_surfaces(filter);
538 static void vmr_destroy(struct strmbase_renderer *iface)
540 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
542 video_window_cleanup(&filter->window);
544 /* Devil May Cry 3 releases the IVMRSurfaceAllocatorNotify9 interface from
545 * TerminateDevice(). Artificially increase the reference count so that we
546 * don't free the filter yet. */
547 InterlockedIncrement(&filter->renderer.filter.refcount);
549 if (filter->allocator)
551 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
552 IVMRSurfaceAllocator9_Release(filter->allocator);
554 if (filter->presenter)
555 IVMRImagePresenter9_Release(filter->presenter);
557 filter->num_surfaces = 0;
558 if (filter->allocator_d3d9_dev)
560 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
561 filter->allocator_d3d9_dev = NULL;
564 FreeLibrary(filter->hD3d9);
565 strmbase_renderer_cleanup(&filter->renderer);
566 if (!filter->IVMRSurfaceAllocatorNotify9_refcount)
567 free(filter);
570 static HRESULT vmr_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
572 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
574 if (IsEqualGUID(iid, &IID_IVideoWindow))
575 *out = &filter->window.IVideoWindow_iface;
576 else if (IsEqualGUID(iid, &IID_IBasicVideo))
577 *out = &filter->window.IBasicVideo_iface;
578 else if (IsEqualGUID(iid, &IID_IAMCertifiedOutputProtection))
579 *out = &filter->IAMCertifiedOutputProtection_iface;
580 else if (IsEqualGUID(iid, &IID_IAMFilterMiscFlags))
581 *out = &filter->IAMFilterMiscFlags_iface;
582 else if (IsEqualGUID(iid, &IID_IVMRAspectRatioControl9) && is_vmr9(filter))
583 *out = &filter->IVMRAspectRatioControl9_iface;
584 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig) && !is_vmr9(filter))
585 *out = &filter->IVMRFilterConfig_iface;
586 else if (IsEqualGUID(iid, &IID_IVMRFilterConfig9) && is_vmr9(filter))
587 *out = &filter->IVMRFilterConfig9_iface;
588 else if (IsEqualGUID(iid, &IID_IVMRMixerBitmap9) && is_vmr9(filter))
589 *out = &filter->IVMRMixerBitmap9_iface;
590 else if (IsEqualGUID(iid, &IID_IVMRMixerControl9) && is_vmr9(filter) && filter->stream_count)
591 *out = &filter->IVMRMixerControl9_iface;
592 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig) && !is_vmr9(filter))
593 *out = &filter->IVMRMonitorConfig_iface;
594 else if (IsEqualGUID(iid, &IID_IVMRMonitorConfig9)
595 && filter->mode != VMR9Mode_Renderless && is_vmr9(filter))
596 *out = &filter->IVMRMonitorConfig9_iface;
597 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify)
598 && filter->mode == (VMR9Mode)VMRMode_Renderless && !is_vmr9(filter))
599 *out = &filter->IVMRSurfaceAllocatorNotify_iface;
600 else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorNotify9)
601 && filter->mode == VMR9Mode_Renderless && is_vmr9(filter))
602 *out = &filter->IVMRSurfaceAllocatorNotify9_iface;
603 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl)
604 && filter->mode == (VMR9Mode)VMRMode_Windowless && !is_vmr9(filter))
605 *out = &filter->IVMRWindowlessControl_iface;
606 else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl9)
607 && filter->mode == VMR9Mode_Windowless && is_vmr9(filter))
608 *out = &filter->IVMRWindowlessControl9_iface;
609 else
610 return E_NOINTERFACE;
612 IUnknown_AddRef((IUnknown *)*out);
613 return S_OK;
616 static HRESULT vmr_pin_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
618 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
620 if (IsEqualGUID(iid, &IID_IAMVideoAccelerator))
621 *out = &filter->IAMVideoAccelerator_iface;
622 else if (IsEqualGUID(iid, &IID_IOverlay))
623 *out = &filter->IOverlay_iface;
624 else
625 return E_NOINTERFACE;
627 IUnknown_AddRef((IUnknown *)*out);
628 return S_OK;
631 static const struct strmbase_renderer_ops renderer_ops =
633 .renderer_query_accept = vmr_query_accept,
634 .renderer_render = vmr_render,
635 .renderer_init_stream = vmr_init_stream,
636 .renderer_start_stream = vmr_start_stream,
637 .renderer_stop_stream = vmr_stop_stream,
638 .renderer_connect = vmr_connect,
639 .renderer_disconnect = vmr_disconnect,
640 .renderer_destroy = vmr_destroy,
641 .renderer_query_interface = vmr_query_interface,
642 .renderer_pin_query_interface = vmr_pin_query_interface,
645 static RECT vmr_get_default_rect(struct video_window *This)
647 struct quartz_vmr *pVMR9 = impl_from_video_window(This);
648 static RECT defRect;
650 SetRect(&defRect, 0, 0, pVMR9->VideoWidth, pVMR9->VideoHeight);
652 return defRect;
655 static HRESULT vmr_get_current_image(struct video_window *iface, LONG *size, LONG *image)
657 struct quartz_vmr *filter = impl_from_video_window(iface);
658 IDirect3DSurface9 *rt = NULL, *surface = NULL;
659 D3DLOCKED_RECT locked_rect;
660 IDirect3DDevice9 *device;
661 unsigned int row_size;
662 BITMAPINFOHEADER bih;
663 LONG i, size_left;
664 char *dst;
665 HRESULT hr;
667 EnterCriticalSection(&filter->renderer.filter.stream_cs);
668 device = filter->allocator_d3d9_dev;
670 bih = *get_bitmap_header(&filter->renderer.sink.pin.mt);
671 bih.biSizeImage = bih.biWidth * bih.biHeight * bih.biBitCount / 8;
673 if (!image)
675 *size = sizeof(BITMAPINFOHEADER) + bih.biSizeImage;
676 LeaveCriticalSection(&filter->renderer.filter.stream_cs);
677 return S_OK;
680 if (FAILED(hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt)))
681 goto out;
683 if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, bih.biWidth,
684 bih.biHeight, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL)))
685 goto out;
687 if (FAILED(hr = IDirect3DDevice9_GetRenderTargetData(device, rt, surface)))
688 goto out;
690 if (FAILED(hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_READONLY)))
691 goto out;
693 size_left = *size;
694 memcpy(image, &bih, min(size_left, sizeof(BITMAPINFOHEADER)));
695 size_left -= sizeof(BITMAPINFOHEADER);
697 dst = (char *)image + sizeof(BITMAPINFOHEADER);
698 row_size = bih.biWidth * bih.biBitCount / 8;
700 for (i = 0; i < bih.biHeight && size_left > 0; ++i)
702 memcpy(dst, (char *)locked_rect.pBits + (i * locked_rect.Pitch), min(row_size, size_left));
703 dst += row_size;
704 size_left -= row_size;
707 IDirect3DSurface9_UnlockRect(surface);
709 out:
710 if (surface) IDirect3DSurface9_Release(surface);
711 if (rt) IDirect3DSurface9_Release(rt);
712 LeaveCriticalSection(&filter->renderer.filter.stream_cs);
713 return hr;
716 static const struct video_window_ops window_ops =
718 .get_default_rect = vmr_get_default_rect,
719 .get_current_image = vmr_get_current_image,
722 static const IVideoWindowVtbl IVideoWindow_VTable =
724 BaseControlWindowImpl_QueryInterface,
725 BaseControlWindowImpl_AddRef,
726 BaseControlWindowImpl_Release,
727 BaseControlWindowImpl_GetTypeInfoCount,
728 BaseControlWindowImpl_GetTypeInfo,
729 BaseControlWindowImpl_GetIDsOfNames,
730 BaseControlWindowImpl_Invoke,
731 BaseControlWindowImpl_put_Caption,
732 BaseControlWindowImpl_get_Caption,
733 BaseControlWindowImpl_put_WindowStyle,
734 BaseControlWindowImpl_get_WindowStyle,
735 BaseControlWindowImpl_put_WindowStyleEx,
736 BaseControlWindowImpl_get_WindowStyleEx,
737 BaseControlWindowImpl_put_AutoShow,
738 BaseControlWindowImpl_get_AutoShow,
739 BaseControlWindowImpl_put_WindowState,
740 BaseControlWindowImpl_get_WindowState,
741 BaseControlWindowImpl_put_BackgroundPalette,
742 BaseControlWindowImpl_get_BackgroundPalette,
743 BaseControlWindowImpl_put_Visible,
744 BaseControlWindowImpl_get_Visible,
745 BaseControlWindowImpl_put_Left,
746 BaseControlWindowImpl_get_Left,
747 BaseControlWindowImpl_put_Width,
748 BaseControlWindowImpl_get_Width,
749 BaseControlWindowImpl_put_Top,
750 BaseControlWindowImpl_get_Top,
751 BaseControlWindowImpl_put_Height,
752 BaseControlWindowImpl_get_Height,
753 BaseControlWindowImpl_put_Owner,
754 BaseControlWindowImpl_get_Owner,
755 BaseControlWindowImpl_put_MessageDrain,
756 BaseControlWindowImpl_get_MessageDrain,
757 BaseControlWindowImpl_get_BorderColor,
758 BaseControlWindowImpl_put_BorderColor,
759 BaseControlWindowImpl_get_FullScreenMode,
760 BaseControlWindowImpl_put_FullScreenMode,
761 BaseControlWindowImpl_SetWindowForeground,
762 BaseControlWindowImpl_NotifyOwnerMessage,
763 BaseControlWindowImpl_SetWindowPosition,
764 BaseControlWindowImpl_GetWindowPosition,
765 BaseControlWindowImpl_GetMinIdealImageSize,
766 BaseControlWindowImpl_GetMaxIdealImageSize,
767 BaseControlWindowImpl_GetRestorePosition,
768 BaseControlWindowImpl_HideCursor,
769 BaseControlWindowImpl_IsCursorHidden
772 static HRESULT WINAPI AMCertifiedOutputProtection_QueryInterface(IAMCertifiedOutputProtection *iface,
773 REFIID riid, void **ppv)
775 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
776 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
779 static ULONG WINAPI AMCertifiedOutputProtection_AddRef(IAMCertifiedOutputProtection *iface)
781 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
782 return IUnknown_AddRef(This->renderer.filter.outer_unk);
785 static ULONG WINAPI AMCertifiedOutputProtection_Release(IAMCertifiedOutputProtection *iface)
787 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
788 return IUnknown_Release(This->renderer.filter.outer_unk);
791 static HRESULT WINAPI AMCertifiedOutputProtection_KeyExchange(IAMCertifiedOutputProtection *iface,
792 GUID* pRandom, BYTE** VarLenCertGH,
793 DWORD* pdwLengthCertGH)
795 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
797 FIXME("(%p/%p)->(%p, %p, %p) stub\n", iface, This, pRandom, VarLenCertGH, pdwLengthCertGH);
798 return VFW_E_NO_COPP_HW;
801 static HRESULT WINAPI AMCertifiedOutputProtection_SessionSequenceStart(IAMCertifiedOutputProtection *iface,
802 AMCOPPSignature* pSig)
804 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
806 FIXME("(%p/%p)->(%p) stub\n", iface, This, pSig);
807 return VFW_E_NO_COPP_HW;
810 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionCommand(IAMCertifiedOutputProtection *iface,
811 const AMCOPPCommand* cmd)
813 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
815 FIXME("(%p/%p)->(%p) stub\n", iface, This, cmd);
816 return VFW_E_NO_COPP_HW;
819 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionStatus(IAMCertifiedOutputProtection *iface,
820 const AMCOPPStatusInput* pStatusInput,
821 AMCOPPStatusOutput* pStatusOutput)
823 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
825 FIXME("(%p/%p)->(%p, %p) stub\n", iface, This, pStatusInput, pStatusOutput);
826 return VFW_E_NO_COPP_HW;
829 static const IAMCertifiedOutputProtectionVtbl IAMCertifiedOutputProtection_Vtbl =
831 AMCertifiedOutputProtection_QueryInterface,
832 AMCertifiedOutputProtection_AddRef,
833 AMCertifiedOutputProtection_Release,
834 AMCertifiedOutputProtection_KeyExchange,
835 AMCertifiedOutputProtection_SessionSequenceStart,
836 AMCertifiedOutputProtection_ProtectionCommand,
837 AMCertifiedOutputProtection_ProtectionStatus
840 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
841 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
842 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
845 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
846 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
847 return IUnknown_AddRef(This->renderer.filter.outer_unk);
850 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
851 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
852 return IUnknown_Release(This->renderer.filter.outer_unk);
855 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
856 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
859 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
860 AMFilterMiscFlags_QueryInterface,
861 AMFilterMiscFlags_AddRef,
862 AMFilterMiscFlags_Release,
863 AMFilterMiscFlags_GetMiscFlags
866 static HRESULT WINAPI VMR7FilterConfig_QueryInterface(IVMRFilterConfig *iface, REFIID riid,
867 void** ppv)
869 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
870 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
873 static ULONG WINAPI VMR7FilterConfig_AddRef(IVMRFilterConfig *iface)
875 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
876 return IUnknown_AddRef(This->renderer.filter.outer_unk);
879 static ULONG WINAPI VMR7FilterConfig_Release(IVMRFilterConfig *iface)
881 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
882 return IUnknown_Release(This->renderer.filter.outer_unk);
885 static HRESULT WINAPI VMR7FilterConfig_SetImageCompositor(IVMRFilterConfig *iface,
886 IVMRImageCompositor *compositor)
888 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
890 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
891 return E_NOTIMPL;
894 static HRESULT WINAPI VMR7FilterConfig_SetNumberOfStreams(IVMRFilterConfig *iface, DWORD count)
896 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
898 FIXME("filter %p, count %lu, stub!\n", filter, count);
900 return E_NOTIMPL;
903 static HRESULT WINAPI VMR7FilterConfig_GetNumberOfStreams(IVMRFilterConfig *iface, DWORD *max)
905 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
907 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
908 return E_NOTIMPL;
911 static HRESULT WINAPI VMR7FilterConfig_SetRenderingPrefs(IVMRFilterConfig *iface, DWORD flags)
913 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
915 FIXME("filter %p, flags %#lx, stub!\n", filter, flags);
917 return E_NOTIMPL;
920 static HRESULT WINAPI VMR7FilterConfig_GetRenderingPrefs(IVMRFilterConfig *iface, DWORD *renderflags)
922 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
924 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
925 return E_NOTIMPL;
928 static HRESULT WINAPI VMR7FilterConfig_SetRenderingMode(IVMRFilterConfig *iface, DWORD mode)
930 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
932 TRACE("iface %p, mode %#lx.\n", iface, mode);
934 return IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, mode);
937 static HRESULT WINAPI VMR7FilterConfig_GetRenderingMode(IVMRFilterConfig *iface, DWORD *mode)
939 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
941 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
942 if (!mode) return E_POINTER;
944 if (This->mode)
945 *mode = This->mode;
946 else
947 *mode = VMRMode_Windowed;
949 return S_OK;
952 static const IVMRFilterConfigVtbl VMR7_FilterConfig_Vtbl =
954 VMR7FilterConfig_QueryInterface,
955 VMR7FilterConfig_AddRef,
956 VMR7FilterConfig_Release,
957 VMR7FilterConfig_SetImageCompositor,
958 VMR7FilterConfig_SetNumberOfStreams,
959 VMR7FilterConfig_GetNumberOfStreams,
960 VMR7FilterConfig_SetRenderingPrefs,
961 VMR7FilterConfig_GetRenderingPrefs,
962 VMR7FilterConfig_SetRenderingMode,
963 VMR7FilterConfig_GetRenderingMode
966 struct get_available_monitors_args
968 VMRMONITORINFO *info7;
969 VMR9MonitorInfo *info9;
970 DWORD arraysize;
971 DWORD numdev;
974 static BOOL CALLBACK get_available_monitors_proc(HMONITOR hmon, HDC hdc, LPRECT lprc, LPARAM lparam)
976 struct get_available_monitors_args *args = (struct get_available_monitors_args *)lparam;
977 MONITORINFOEXW mi;
979 if (args->info7 || args->info9)
982 if (!args->arraysize)
983 return FALSE;
985 mi.cbSize = sizeof(mi);
986 if (!GetMonitorInfoW(hmon, (MONITORINFO*)&mi))
987 return TRUE;
989 /* fill VMRMONITORINFO struct */
990 if (args->info7)
992 VMRMONITORINFO *info = args->info7++;
993 memset(info, 0, sizeof(*info));
995 if (args->numdev > 0)
997 info->guid.pGUID = &info->guid.GUID;
998 info->guid.GUID.Data4[7] = args->numdev;
1000 else
1001 info->guid.pGUID = NULL;
1003 info->rcMonitor = mi.rcMonitor;
1004 info->hMon = hmon;
1005 info->dwFlags = mi.dwFlags;
1007 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1009 /* FIXME: how to get these values? */
1010 info->szDescription[0] = 0;
1013 /* fill VMR9MonitorInfo struct */
1014 if (args->info9)
1016 VMR9MonitorInfo *info = args->info9++;
1017 memset(info, 0, sizeof(*info));
1019 info->uDevID = 0; /* FIXME */
1020 info->rcMonitor = mi.rcMonitor;
1021 info->hMon = hmon;
1022 info->dwFlags = mi.dwFlags;
1024 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1026 /* FIXME: how to get these values? */
1027 info->szDescription[0] = 0;
1028 info->dwVendorId = 0;
1029 info->dwDeviceId = 0;
1030 info->dwSubSysId = 0;
1031 info->dwRevision = 0;
1034 args->arraysize--;
1037 args->numdev++;
1038 return TRUE;
1041 static HRESULT WINAPI VMR7MonitorConfig_QueryInterface(IVMRMonitorConfig *iface, REFIID riid,
1042 LPVOID * ppv)
1044 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1045 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1048 static ULONG WINAPI VMR7MonitorConfig_AddRef(IVMRMonitorConfig *iface)
1050 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1051 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1054 static ULONG WINAPI VMR7MonitorConfig_Release(IVMRMonitorConfig *iface)
1056 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1057 return IUnknown_Release(This->renderer.filter.outer_unk);
1060 static HRESULT WINAPI VMR7MonitorConfig_SetMonitor(IVMRMonitorConfig *iface, const VMRGUID *pGUID)
1062 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1064 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1066 if (!pGUID)
1067 return E_POINTER;
1069 return S_OK;
1072 static HRESULT WINAPI VMR7MonitorConfig_GetMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1074 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1076 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1078 if (!pGUID)
1079 return E_POINTER;
1081 pGUID->pGUID = NULL; /* default DirectDraw device */
1082 return S_OK;
1085 static HRESULT WINAPI VMR7MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig *iface,
1086 const VMRGUID *pGUID)
1088 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1090 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1092 if (!pGUID)
1093 return E_POINTER;
1095 return S_OK;
1098 static HRESULT WINAPI VMR7MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1100 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1102 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1104 if (!pGUID)
1105 return E_POINTER;
1107 pGUID->pGUID = NULL; /* default DirectDraw device */
1108 return S_OK;
1111 static HRESULT WINAPI VMR7MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig *iface,
1112 VMRMONITORINFO *info, DWORD arraysize,
1113 DWORD *numdev)
1115 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1116 struct get_available_monitors_args args;
1118 TRACE("filter %p, info %p, arraysize %lu, numdev %p.\n", This, info, arraysize, numdev);
1120 if (!numdev)
1121 return E_POINTER;
1123 if (info && arraysize == 0)
1124 return E_INVALIDARG;
1126 args.info7 = info;
1127 args.info9 = NULL;
1128 args.arraysize = arraysize;
1129 args.numdev = 0;
1130 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1132 *numdev = args.numdev;
1133 return S_OK;
1136 static const IVMRMonitorConfigVtbl VMR7_MonitorConfig_Vtbl =
1138 VMR7MonitorConfig_QueryInterface,
1139 VMR7MonitorConfig_AddRef,
1140 VMR7MonitorConfig_Release,
1141 VMR7MonitorConfig_SetMonitor,
1142 VMR7MonitorConfig_GetMonitor,
1143 VMR7MonitorConfig_SetDefaultMonitor,
1144 VMR7MonitorConfig_GetDefaultMonitor,
1145 VMR7MonitorConfig_GetAvailableMonitors
1148 static HRESULT WINAPI VMR9MonitorConfig_QueryInterface(IVMRMonitorConfig9 *iface, REFIID riid,
1149 LPVOID * ppv)
1151 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1152 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1155 static ULONG WINAPI VMR9MonitorConfig_AddRef(IVMRMonitorConfig9 *iface)
1157 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1158 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1161 static ULONG WINAPI VMR9MonitorConfig_Release(IVMRMonitorConfig9 *iface)
1163 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1164 return IUnknown_Release(This->renderer.filter.outer_unk);
1167 static HRESULT WINAPI VMR9MonitorConfig_SetMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1169 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1171 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1173 return S_OK;
1176 static HRESULT WINAPI VMR9MonitorConfig_GetMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1178 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1180 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1182 if (!uDev)
1183 return E_POINTER;
1185 *uDev = 0;
1186 return S_OK;
1189 static HRESULT WINAPI VMR9MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1191 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1193 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1195 return S_OK;
1198 static HRESULT WINAPI VMR9MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1200 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1202 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1204 if (!uDev)
1205 return E_POINTER;
1207 *uDev = 0;
1208 return S_OK;
1211 static HRESULT WINAPI VMR9MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig9 *iface,
1212 VMR9MonitorInfo *info, DWORD arraysize,
1213 DWORD *numdev)
1215 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1216 struct get_available_monitors_args args;
1218 TRACE("filter %p, info %p, arraysize %lu, numdev %p.\n", This, info, arraysize, numdev);
1220 if (!numdev)
1221 return E_POINTER;
1223 if (info && arraysize == 0)
1224 return E_INVALIDARG;
1226 args.info7 = NULL;
1227 args.info9 = info;
1228 args.arraysize = arraysize;
1229 args.numdev = 0;
1230 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1232 *numdev = args.numdev;
1233 return S_OK;
1236 static const IVMRMonitorConfig9Vtbl VMR9_MonitorConfig_Vtbl =
1238 VMR9MonitorConfig_QueryInterface,
1239 VMR9MonitorConfig_AddRef,
1240 VMR9MonitorConfig_Release,
1241 VMR9MonitorConfig_SetMonitor,
1242 VMR9MonitorConfig_GetMonitor,
1243 VMR9MonitorConfig_SetDefaultMonitor,
1244 VMR9MonitorConfig_GetDefaultMonitor,
1245 VMR9MonitorConfig_GetAvailableMonitors
1248 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
1250 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1251 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1254 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
1256 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1257 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1260 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
1262 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1263 return IUnknown_Release(This->renderer.filter.outer_unk);
1266 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
1268 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1270 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
1271 return E_NOTIMPL;
1274 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD count)
1276 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1278 FIXME("iface %p, count %lu, stub!\n", iface, count);
1280 if (!count)
1282 WARN("Application requested zero streams; returning E_INVALIDARG.\n");
1283 return E_INVALIDARG;
1286 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1288 if (filter->stream_count)
1290 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1291 WARN("Stream count is already set; returning VFW_E_WRONG_STATE.\n");
1292 return VFW_E_WRONG_STATE;
1295 filter->stream_count = count;
1297 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1298 return S_OK;
1301 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *count)
1303 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1305 TRACE("filter %p, count %p.\n", filter, count);
1307 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1309 if (!filter->stream_count)
1311 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1312 return VFW_E_VMR_NOT_IN_MIXER_MODE;
1315 *count = filter->stream_count;
1317 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1318 return S_OK;
1321 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD flags)
1323 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1325 TRACE("filter %p, flags %#lx.\n", filter, flags);
1327 return E_NOTIMPL;
1330 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
1332 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1334 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
1335 return E_NOTIMPL;
1338 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
1340 struct default_presenter *default_presenter;
1341 HRESULT hr = S_OK;
1342 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1344 TRACE("filter %p, mode %lu.\n", This, mode);
1346 EnterCriticalSection(&This->renderer.filter.filter_cs);
1347 if (This->mode)
1349 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1350 return VFW_E_WRONG_STATE;
1353 switch (mode)
1355 case VMR9Mode_Windowed:
1356 case VMR9Mode_Windowless:
1357 if (FAILED(hr = default_presenter_create(This, &default_presenter)))
1359 ERR("Failed to create default presenter, hr %#lx.\n", hr);
1360 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1361 return hr;
1363 This->allocator = &default_presenter->IVMRSurfaceAllocator9_iface;
1364 This->presenter = &default_presenter->IVMRImagePresenter9_iface;
1365 IVMRImagePresenter9_AddRef(This->presenter);
1367 IVMRSurfaceAllocator9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
1368 break;
1369 case VMR9Mode_Renderless:
1370 break;
1371 default:
1372 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1373 return E_INVALIDARG;
1376 if (mode != VMR9Mode_Windowed)
1377 video_window_cleanup(&This->window);
1379 This->mode = mode;
1380 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1381 return hr;
1384 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
1386 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1388 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
1389 if (!mode)
1390 return E_POINTER;
1392 if (This->mode)
1393 *mode = This->mode;
1394 else
1395 *mode = VMR9Mode_Windowed;
1397 return S_OK;
1400 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
1402 VMR9FilterConfig_QueryInterface,
1403 VMR9FilterConfig_AddRef,
1404 VMR9FilterConfig_Release,
1405 VMR9FilterConfig_SetImageCompositor,
1406 VMR9FilterConfig_SetNumberOfStreams,
1407 VMR9FilterConfig_GetNumberOfStreams,
1408 VMR9FilterConfig_SetRenderingPrefs,
1409 VMR9FilterConfig_GetRenderingPrefs,
1410 VMR9FilterConfig_SetRenderingMode,
1411 VMR9FilterConfig_GetRenderingMode
1414 static HRESULT WINAPI VMR7WindowlessControl_QueryInterface(IVMRWindowlessControl *iface, REFIID riid,
1415 LPVOID * ppv)
1417 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1418 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1421 static ULONG WINAPI VMR7WindowlessControl_AddRef(IVMRWindowlessControl *iface)
1423 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1424 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1427 static ULONG WINAPI VMR7WindowlessControl_Release(IVMRWindowlessControl *iface)
1429 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1430 return IUnknown_Release(This->renderer.filter.outer_unk);
1433 static HRESULT WINAPI VMR7WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl *iface,
1434 LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height)
1436 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1438 TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n",
1439 filter, width, height, aspect_width, aspect_height);
1441 if (!width || !height)
1442 return E_POINTER;
1444 *width = filter->bmiheader.biWidth;
1445 *height = filter->bmiheader.biHeight;
1446 if (aspect_width)
1447 *aspect_width = filter->bmiheader.biWidth;
1448 if (aspect_height)
1449 *aspect_height = filter->bmiheader.biHeight;
1451 return S_OK;
1454 static HRESULT WINAPI VMR7WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl *iface,
1455 LONG *width, LONG *height)
1457 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1459 FIXME("(%p/%p)->(...) stub\n", iface, This);
1460 return E_NOTIMPL;
1463 static HRESULT WINAPI VMR7WindowlessControl_GetMaxIdealVideoSize(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_SetVideoPosition(IVMRWindowlessControl *iface,
1473 const RECT *source, const RECT *dest)
1475 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1477 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1479 EnterCriticalSection(&This->renderer.filter.filter_cs);
1481 if (source)
1482 This->window.src = *source;
1483 if (dest)
1484 This->window.dst = *dest;
1486 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1488 return S_OK;
1491 static HRESULT WINAPI VMR7WindowlessControl_GetVideoPosition(IVMRWindowlessControl *iface,
1492 RECT *source, RECT *dest)
1494 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1496 if (source)
1497 *source = This->window.src;
1499 if (dest)
1500 *dest = This->window.dst;
1502 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1503 return S_OK;
1506 static HRESULT WINAPI VMR7WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl *iface,
1507 DWORD *mode)
1509 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1511 FIXME("(%p/%p)->(...) stub\n", iface, This);
1512 return E_NOTIMPL;
1515 static HRESULT WINAPI VMR7WindowlessControl_SetAspectRatioMode(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_SetVideoClippingWindow(IVMRWindowlessControl *iface, HWND window)
1526 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1528 TRACE("iface %p, window %p.\n", iface, window);
1530 return IVMRWindowlessControl9_SetVideoClippingWindow(&filter->IVMRWindowlessControl9_iface, window);
1533 static HRESULT WINAPI VMR7WindowlessControl_RepaintVideo(IVMRWindowlessControl *iface,
1534 HWND hwnd, HDC hdc)
1536 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1538 FIXME("(%p/%p)->(...) stub\n", iface, This);
1539 return E_NOTIMPL;
1542 static HRESULT WINAPI VMR7WindowlessControl_DisplayModeChanged(IVMRWindowlessControl *iface)
1544 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1546 FIXME("(%p/%p)->(...) stub\n", iface, This);
1547 return E_NOTIMPL;
1550 static HRESULT WINAPI VMR7WindowlessControl_GetCurrentImage(IVMRWindowlessControl *iface,
1551 BYTE **dib)
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_SetBorderColor(IVMRWindowlessControl *iface,
1560 COLORREF color)
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_GetBorderColor(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_SetColorKey(IVMRWindowlessControl *iface, COLORREF color)
1579 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1581 FIXME("(%p/%p)->(...) stub\n", iface, This);
1582 return E_NOTIMPL;
1585 static HRESULT WINAPI VMR7WindowlessControl_GetColorKey(IVMRWindowlessControl *iface, COLORREF *color)
1587 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1589 FIXME("(%p/%p)->(...) stub\n", iface, This);
1590 return E_NOTIMPL;
1593 static const IVMRWindowlessControlVtbl VMR7_WindowlessControl_Vtbl =
1595 VMR7WindowlessControl_QueryInterface,
1596 VMR7WindowlessControl_AddRef,
1597 VMR7WindowlessControl_Release,
1598 VMR7WindowlessControl_GetNativeVideoSize,
1599 VMR7WindowlessControl_GetMinIdealVideoSize,
1600 VMR7WindowlessControl_GetMaxIdealVideoSize,
1601 VMR7WindowlessControl_SetVideoPosition,
1602 VMR7WindowlessControl_GetVideoPosition,
1603 VMR7WindowlessControl_GetAspectRatioMode,
1604 VMR7WindowlessControl_SetAspectRatioMode,
1605 VMR7WindowlessControl_SetVideoClippingWindow,
1606 VMR7WindowlessControl_RepaintVideo,
1607 VMR7WindowlessControl_DisplayModeChanged,
1608 VMR7WindowlessControl_GetCurrentImage,
1609 VMR7WindowlessControl_SetBorderColor,
1610 VMR7WindowlessControl_GetBorderColor,
1611 VMR7WindowlessControl_SetColorKey,
1612 VMR7WindowlessControl_GetColorKey
1615 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
1617 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1618 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1621 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
1623 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1624 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1627 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
1629 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1630 return IUnknown_Release(This->renderer.filter.outer_unk);
1633 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface,
1634 LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height)
1636 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1638 TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n",
1639 filter, width, height, aspect_width, aspect_height);
1641 if (!width || !height)
1642 return E_POINTER;
1644 *width = filter->bmiheader.biWidth;
1645 *height = filter->bmiheader.biHeight;
1646 if (aspect_width)
1647 *aspect_width = filter->bmiheader.biWidth;
1648 if (aspect_height)
1649 *aspect_height = filter->bmiheader.biHeight;
1651 return S_OK;
1654 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1656 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1658 FIXME("(%p/%p)->(...) stub\n", iface, This);
1659 return E_NOTIMPL;
1662 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1664 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1666 FIXME("(%p/%p)->(...) stub\n", iface, This);
1667 return E_NOTIMPL;
1670 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface,
1671 const RECT *src, const RECT *dst)
1673 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1675 TRACE("filter %p, src %s, dst %s.\n", filter, wine_dbgstr_rect(src), wine_dbgstr_rect(dst));
1677 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1679 if (src)
1680 filter->window.src = *src;
1681 if (dst)
1682 filter->window.dst = *dst;
1684 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1686 return S_OK;
1689 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *src, RECT *dst)
1691 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1693 TRACE("filter %p, src %p, dst %p.\n", filter, src, dst);
1695 if (src)
1696 *src = filter->window.src;
1698 if (dst)
1699 *dst = filter->window.dst;
1701 return S_OK;
1704 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1706 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1708 TRACE("filter %p, mode %p.\n", filter, mode);
1710 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1711 *mode = filter->aspect_mode;
1712 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1713 return S_OK;
1716 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1718 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1720 TRACE("filter %p, mode %lu.\n", filter, mode);
1722 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1723 filter->aspect_mode = mode;
1724 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1725 return S_OK;
1728 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND window)
1730 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1731 HRESULT hr;
1733 TRACE("filter %p, window %p.\n", filter, window);
1735 if (!IsWindow(window))
1737 WARN("Invalid window %p, returning E_INVALIDARG.\n", window);
1738 return E_INVALIDARG;
1741 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1743 if (filter->renderer.sink.pin.peer)
1745 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1746 WARN("Attempt to set the clipping window while connected; returning VFW_E_WRONG_STATE.\n");
1747 return VFW_E_WRONG_STATE;
1750 filter->clipping_window = window;
1752 hr = IVMRFilterConfig9_SetNumberOfStreams(&filter->IVMRFilterConfig9_iface, 4);
1754 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1755 return hr;
1758 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1760 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1761 HRESULT hr;
1763 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1765 EnterCriticalSection(&This->renderer.filter.filter_cs);
1766 if (hwnd != This->clipping_window)
1768 ERR("Not handling changing windows yet!!!\n");
1769 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1770 return S_OK;
1773 if (!This->allocator_d3d9_dev)
1775 ERR("No d3d9 device!\n");
1776 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1777 return VFW_E_WRONG_STATE;
1780 /* Windowless extension */
1781 hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, NULL, NULL);
1782 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1784 return hr;
1787 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1789 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1791 FIXME("(%p/%p)->(...) stub\n", iface, This);
1792 return E_NOTIMPL;
1795 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1797 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1799 FIXME("(%p/%p)->(...) stub\n", iface, This);
1800 return E_NOTIMPL;
1803 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1805 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1807 FIXME("(%p/%p)->(...) stub\n", iface, This);
1808 return E_NOTIMPL;
1811 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1813 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1815 FIXME("(%p/%p)->(...) stub\n", iface, This);
1816 return E_NOTIMPL;
1819 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1821 VMR9WindowlessControl_QueryInterface,
1822 VMR9WindowlessControl_AddRef,
1823 VMR9WindowlessControl_Release,
1824 VMR9WindowlessControl_GetNativeVideoSize,
1825 VMR9WindowlessControl_GetMinIdealVideoSize,
1826 VMR9WindowlessControl_GetMaxIdealVideoSize,
1827 VMR9WindowlessControl_SetVideoPosition,
1828 VMR9WindowlessControl_GetVideoPosition,
1829 VMR9WindowlessControl_GetAspectRatioMode,
1830 VMR9WindowlessControl_SetAspectRatioMode,
1831 VMR9WindowlessControl_SetVideoClippingWindow,
1832 VMR9WindowlessControl_RepaintVideo,
1833 VMR9WindowlessControl_DisplayModeChanged,
1834 VMR9WindowlessControl_GetCurrentImage,
1835 VMR9WindowlessControl_SetBorderColor,
1836 VMR9WindowlessControl_GetBorderColor
1839 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify *iface,
1840 REFIID riid, LPVOID * ppv)
1842 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1843 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1846 static ULONG WINAPI VMR7SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify *iface)
1848 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1849 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1852 static ULONG WINAPI VMR7SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify *iface)
1854 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1855 return IUnknown_Release(This->renderer.filter.outer_unk);
1858 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify *iface,
1859 DWORD_PTR id,
1860 IVMRSurfaceAllocator *alloc)
1862 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1864 FIXME("(%p/%p)->(...) stub\n", iface, This);
1865 return E_NOTIMPL;
1868 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1869 IDirectDraw7 *device, HMONITOR monitor)
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_ChangeDDrawDevice(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_RestoreDDrawSurfaces(IVMRSurfaceAllocatorNotify *iface)
1888 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1890 FIXME("(%p/%p)->(...) stub\n", iface, This);
1891 return E_NOTIMPL;
1894 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify *iface, LONG code,
1895 LONG_PTR param1, LONG_PTR param2)
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_SetBorderColor(IVMRSurfaceAllocatorNotify *iface,
1904 COLORREF clrBorder)
1906 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1908 FIXME("(%p/%p)->(...) stub\n", iface, This);
1909 return E_NOTIMPL;
1912 static const IVMRSurfaceAllocatorNotifyVtbl VMR7_SurfaceAllocatorNotify_Vtbl =
1914 VMR7SurfaceAllocatorNotify_QueryInterface,
1915 VMR7SurfaceAllocatorNotify_AddRef,
1916 VMR7SurfaceAllocatorNotify_Release,
1917 VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1918 VMR7SurfaceAllocatorNotify_SetDDrawDevice,
1919 VMR7SurfaceAllocatorNotify_ChangeDDrawDevice,
1920 VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces,
1921 VMR7SurfaceAllocatorNotify_NotifyEvent,
1922 VMR7SurfaceAllocatorNotify_SetBorderColor
1925 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1927 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1928 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1931 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1933 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1934 ULONG refcount = InterlockedIncrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1936 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
1938 return refcount;
1941 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1943 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1944 ULONG refcount = InterlockedDecrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1946 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
1948 if (!refcount && !filter->renderer.filter.refcount)
1949 free(filter);
1951 return refcount;
1954 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(
1955 IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR cookie, IVMRSurfaceAllocator9 *allocator)
1957 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1958 IVMRImagePresenter9 *presenter;
1960 TRACE("filter %p, cookie %#Ix, allocator %p.\n", filter, cookie, allocator);
1962 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1964 filter->cookie = cookie;
1966 if (filter->renderer.sink.pin.peer)
1968 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1969 WARN("Attempt to set allocator while connected; returning VFW_E_WRONG_STATE.\n");
1970 return VFW_E_WRONG_STATE;
1973 if (FAILED(IVMRSurfaceAllocator9_QueryInterface(allocator, &IID_IVMRImagePresenter9, (void **)&presenter)))
1975 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1976 return E_NOINTERFACE;
1979 if (filter->allocator)
1981 IVMRImagePresenter9_Release(filter->presenter);
1982 IVMRSurfaceAllocator9_Release(filter->allocator);
1984 filter->allocator = allocator;
1985 filter->presenter = presenter;
1986 IVMRSurfaceAllocator9_AddRef(allocator);
1988 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1989 return S_OK;
1992 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface,
1993 IDirect3DDevice9 *device, HMONITOR monitor)
1995 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1997 TRACE("filter %p, device %p, monitor %p.\n", filter, device, monitor);
1999 if (filter->allocator_d3d9_dev)
2000 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
2001 filter->allocator_d3d9_dev = device;
2002 IDirect3DDevice9_AddRef(device);
2004 return S_OK;
2007 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface,
2008 IDirect3DDevice9 *device, HMONITOR monitor)
2010 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2012 TRACE("(%p/%p)->(...).\n", iface, This);
2014 if (This->allocator_d3d9_dev)
2015 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
2016 This->allocator_d3d9_dev = device;
2017 IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
2019 if (This->mode && This->allocator && This->presenter)
2021 deallocate_surfaces(This);
2022 allocate_surfaces(This, &This->renderer.sink.pin.mt);
2025 return S_OK;
2028 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
2030 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2031 DWORD i;
2032 HRESULT hr = S_OK;
2034 TRACE("filter %p, allocinfo %p, numbuffers %p, surface %p.\n", This, numbuffers, allocinfo, surface);
2036 if (!allocinfo || !numbuffers || !surface)
2037 return E_POINTER;
2039 TRACE("Flags %#lx, size %lux%lu, format %u (%#x), pool %u, minimum buffers %lu.\n",
2040 allocinfo->dwFlags, allocinfo->dwWidth, allocinfo->dwHeight,
2041 allocinfo->Format, allocinfo->Format, allocinfo->Pool, allocinfo->MinBuffers);
2043 if ((allocinfo->dwFlags & VMR9AllocFlag_TextureSurface)
2044 && (allocinfo->dwFlags & VMR9AllocFlag_OffscreenSurface))
2046 WARN("Invalid flags specified; returning E_INVALIDARG.\n");
2047 return E_INVALIDARG;
2050 if (!allocinfo->Format)
2052 IDirect3DSurface9 *backbuffer;
2053 D3DSURFACE_DESC desc;
2055 IDirect3DDevice9_GetBackBuffer(This->allocator_d3d9_dev, 0, 0,
2056 D3DBACKBUFFER_TYPE_MONO, &backbuffer);
2057 IDirect3DSurface9_GetDesc(backbuffer, &desc);
2058 IDirect3DSurface9_Release(backbuffer);
2059 allocinfo->Format = desc.Format;
2062 if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
2064 WARN("%lu surfaces requested (minimum %lu); returning E_INVALIDARG.\n",
2065 *numbuffers, allocinfo->MinBuffers);
2066 return E_INVALIDARG;
2069 if (!This->allocator_d3d9_dev)
2071 WARN("No Direct3D device; returning VFW_E_WRONG_STATE.\n");
2072 return VFW_E_WRONG_STATE;
2075 if (allocinfo->dwFlags == VMR9AllocFlag_OffscreenSurface)
2077 for (i = 0; i < *numbuffers; ++i)
2079 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight,
2080 allocinfo->Format, allocinfo->Pool, &surface[i], NULL);
2081 if (FAILED(hr))
2082 break;
2085 else if (allocinfo->dwFlags == VMR9AllocFlag_TextureSurface)
2087 for (i = 0; i < *numbuffers; ++i)
2089 IDirect3DTexture9 *texture;
2091 hr = IDirect3DDevice9_CreateTexture(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, 1, D3DUSAGE_DYNAMIC,
2092 allocinfo->Format, allocinfo->Pool, &texture, NULL);
2093 if (FAILED(hr))
2094 break;
2095 IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface[i]);
2096 IDirect3DTexture9_Release(texture);
2099 else if (allocinfo->dwFlags == VMR9AllocFlag_3DRenderTarget)
2101 for (i = 0; i < *numbuffers; ++i)
2103 if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(This->allocator_d3d9_dev,
2104 allocinfo->dwWidth, allocinfo->dwHeight, allocinfo->Format,
2105 D3DMULTISAMPLE_NONE, 0, FALSE, &surface[i], NULL)))
2106 break;
2109 else
2111 FIXME("Unhandled flags %#lx.\n", allocinfo->dwFlags);
2112 return E_NOTIMPL;
2115 if (FAILED(hr))
2116 WARN("%lu/%lu surfaces allocated, hr %#lx.\n", i, *numbuffers, hr);
2118 if (i >= allocinfo->MinBuffers)
2120 hr = S_OK;
2121 *numbuffers = i;
2123 else
2125 for ( ; i > 0; --i) IDirect3DSurface9_Release(surface[i - 1]);
2126 *numbuffers = 0;
2128 return hr;
2131 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
2133 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2134 IMediaEventSink *sink;
2135 HRESULT hr;
2137 TRACE("filter %p, code %#lx, param1 %#Ix, param2 %#Ix.\n", This, code, param1, param2);
2139 hr = IFilterGraph_QueryInterface(This->renderer.filter.graph, &IID_IMediaEventSink, (void **)&sink);
2140 if (FAILED(hr))
2141 return hr;
2142 hr = IMediaEventSink_Notify(sink, code, param1, param2);
2143 IMediaEventSink_Release(sink);
2144 return hr;
2147 static const IVMRSurfaceAllocatorNotify9Vtbl VMR9_SurfaceAllocatorNotify_Vtbl =
2149 VMR9SurfaceAllocatorNotify_QueryInterface,
2150 VMR9SurfaceAllocatorNotify_AddRef,
2151 VMR9SurfaceAllocatorNotify_Release,
2152 VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
2153 VMR9SurfaceAllocatorNotify_SetD3DDevice,
2154 VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
2155 VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
2156 VMR9SurfaceAllocatorNotify_NotifyEvent
2159 static inline struct quartz_vmr *impl_from_IVMRMixerControl9(IVMRMixerControl9 *iface)
2161 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerControl9_iface);
2164 static HRESULT WINAPI mixer_control9_QueryInterface(IVMRMixerControl9 *iface, REFIID iid, void **out)
2166 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2167 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2170 static ULONG WINAPI mixer_control9_AddRef(IVMRMixerControl9 *iface)
2172 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2173 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2176 static ULONG WINAPI mixer_control9_Release(IVMRMixerControl9 *iface)
2178 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2179 return IUnknown_Release(filter->renderer.filter.outer_unk);
2182 static HRESULT WINAPI mixer_control9_SetAlpha(IVMRMixerControl9 *iface, DWORD stream, float alpha)
2184 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2186 FIXME("filter %p, stream %lu, alpha %.8e, stub!\n", filter, stream, alpha);
2188 return E_NOTIMPL;
2191 static HRESULT WINAPI mixer_control9_GetAlpha(IVMRMixerControl9 *iface, DWORD stream, float *alpha)
2193 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2195 FIXME("filter %p, stream %lu, alpha %p, stub!\n", filter, stream, alpha);
2197 return E_NOTIMPL;
2200 static HRESULT WINAPI mixer_control9_SetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD z)
2202 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2204 FIXME("filter %p, stream %lu, z %lu, stub!\n", filter, stream, z);
2206 return E_NOTIMPL;
2209 static HRESULT WINAPI mixer_control9_GetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD *z)
2211 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2213 FIXME("filter %p, stream %lu, z %p, stub!\n", filter, stream, z);
2215 return E_NOTIMPL;
2218 static HRESULT WINAPI mixer_control9_SetOutputRect(IVMRMixerControl9 *iface,
2219 DWORD stream, const VMR9NormalizedRect *rect)
2221 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2223 FIXME("filter %p, stream %lu, rect %s, stub!\n", filter, stream, debugstr_normalized_rect(rect));
2225 return E_NOTIMPL;
2228 static HRESULT WINAPI mixer_control9_GetOutputRect(IVMRMixerControl9 *iface,
2229 DWORD stream, VMR9NormalizedRect *rect)
2231 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2233 FIXME("filter %p, stream %lu, rect %p, stub!\n", filter, stream, rect);
2235 return E_NOTIMPL;
2238 static HRESULT WINAPI mixer_control9_SetBackgroundClr(IVMRMixerControl9 *iface, COLORREF color)
2240 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2242 FIXME("filter %p, color #%06lx, stub!\n", filter, color);
2244 return E_NOTIMPL;
2247 static HRESULT WINAPI mixer_control9_GetBackgroundClr(IVMRMixerControl9 *iface, COLORREF *color)
2249 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2251 FIXME("filter %p, color %p, stub!\n", filter, color);
2253 return E_NOTIMPL;
2256 static HRESULT WINAPI mixer_control9_SetMixingPrefs(IVMRMixerControl9 *iface, DWORD flags)
2258 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2260 FIXME("filter %p, flags %#lx, stub!\n", filter, flags);
2262 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2263 filter->mixing_prefs = flags;
2264 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2265 return S_OK;
2268 static HRESULT WINAPI mixer_control9_GetMixingPrefs(IVMRMixerControl9 *iface, DWORD *flags)
2270 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2272 FIXME("filter %p, flags %p, stub!\n", filter, flags);
2274 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2275 *flags = filter->mixing_prefs;
2276 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2277 return S_OK;
2280 static HRESULT WINAPI mixer_control9_SetProcAmpControl(IVMRMixerControl9 *iface,
2281 DWORD stream, VMR9ProcAmpControl *settings)
2283 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2285 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2287 return E_NOTIMPL;
2290 static HRESULT WINAPI mixer_control9_GetProcAmpControl(IVMRMixerControl9 *iface,
2291 DWORD stream, VMR9ProcAmpControl *settings)
2293 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2295 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2297 return E_NOTIMPL;
2300 static HRESULT WINAPI mixer_control9_GetProcAmpControlRange(IVMRMixerControl9 *iface,
2301 DWORD stream, VMR9ProcAmpControlRange *settings)
2303 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2305 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2307 return E_NOTIMPL;
2310 static const IVMRMixerControl9Vtbl mixer_control9_vtbl =
2312 mixer_control9_QueryInterface,
2313 mixer_control9_AddRef,
2314 mixer_control9_Release,
2315 mixer_control9_SetAlpha,
2316 mixer_control9_GetAlpha,
2317 mixer_control9_SetZOrder,
2318 mixer_control9_GetZOrder,
2319 mixer_control9_SetOutputRect,
2320 mixer_control9_GetOutputRect,
2321 mixer_control9_SetBackgroundClr,
2322 mixer_control9_GetBackgroundClr,
2323 mixer_control9_SetMixingPrefs,
2324 mixer_control9_GetMixingPrefs,
2325 mixer_control9_SetProcAmpControl,
2326 mixer_control9_GetProcAmpControl,
2327 mixer_control9_GetProcAmpControlRange,
2330 static inline struct quartz_vmr *impl_from_IVMRMixerBitmap9(IVMRMixerBitmap9 *iface)
2332 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerBitmap9_iface);
2335 static HRESULT WINAPI mixer_bitmap9_QueryInterface(IVMRMixerBitmap9 *iface, REFIID iid, void **out)
2337 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2338 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2341 static ULONG WINAPI mixer_bitmap9_AddRef(IVMRMixerBitmap9 *iface)
2343 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2344 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2347 static ULONG WINAPI mixer_bitmap9_Release(IVMRMixerBitmap9 *iface)
2349 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2350 return IUnknown_Release(filter->renderer.filter.outer_unk);
2353 static HRESULT WINAPI mixer_bitmap9_SetAlphaBitmap(IVMRMixerBitmap9 *iface,
2354 const VMR9AlphaBitmap *bitmap)
2356 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2357 TRACE("dwFlags %#lx, hdc %p, pDDS %p, rSrc %s, rDest %s, fAlpha %.8e, clrSrcKey #%06lx, dwFilterMode %#lx.\n",
2358 bitmap->dwFlags, bitmap->hdc, bitmap->pDDS, wine_dbgstr_rect(&bitmap->rSrc),
2359 debugstr_normalized_rect(&bitmap->rDest), bitmap->fAlpha, bitmap->clrSrcKey, bitmap->dwFilterMode);
2360 return E_NOTIMPL;
2363 static HRESULT WINAPI mixer_bitmap9_UpdateAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2364 const VMR9AlphaBitmap *bitmap)
2366 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2367 return E_NOTIMPL;
2370 static HRESULT WINAPI mixer_bitmap9_GetAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2371 VMR9AlphaBitmap *bitmap)
2373 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2374 return E_NOTIMPL;
2377 static const IVMRMixerBitmap9Vtbl mixer_bitmap9_vtbl =
2379 mixer_bitmap9_QueryInterface,
2380 mixer_bitmap9_AddRef,
2381 mixer_bitmap9_Release,
2382 mixer_bitmap9_SetAlphaBitmap,
2383 mixer_bitmap9_UpdateAlphaBitmapParameters,
2384 mixer_bitmap9_GetAlphaBitmapParameters,
2387 static inline struct quartz_vmr *impl_from_IVMRAspectRatioControl9(IVMRAspectRatioControl9 *iface)
2389 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRAspectRatioControl9_iface);
2392 static HRESULT WINAPI aspect_ratio_control9_QueryInterface(IVMRAspectRatioControl9 *iface, REFIID iid, void **out)
2394 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2395 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2398 static ULONG WINAPI aspect_ratio_control9_AddRef(IVMRAspectRatioControl9 *iface)
2400 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2401 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2404 static ULONG WINAPI aspect_ratio_control9_Release(IVMRAspectRatioControl9 *iface)
2406 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2407 return IUnknown_Release(filter->renderer.filter.outer_unk);
2410 static HRESULT WINAPI aspect_ratio_control9_GetAspectRatioMode(IVMRAspectRatioControl9 *iface, DWORD *mode)
2412 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2414 TRACE("filter %p, mode %p.\n", filter, mode);
2416 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2417 *mode = filter->aspect_mode;
2418 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2419 return S_OK;
2422 static HRESULT WINAPI aspect_ratio_control9_SetAspectRatioMode(IVMRAspectRatioControl9 *iface, DWORD mode)
2424 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2426 TRACE("filter %p, mode %lu.\n", filter, mode);
2428 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2429 filter->aspect_mode = mode;
2430 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2431 return S_OK;
2434 static const IVMRAspectRatioControl9Vtbl aspect_ratio_control9_vtbl =
2436 aspect_ratio_control9_QueryInterface,
2437 aspect_ratio_control9_AddRef,
2438 aspect_ratio_control9_Release,
2439 aspect_ratio_control9_GetAspectRatioMode,
2440 aspect_ratio_control9_SetAspectRatioMode,
2443 static struct quartz_vmr *impl_from_IAMVideoAccelerator(IAMVideoAccelerator *iface)
2445 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMVideoAccelerator_iface);
2448 static HRESULT WINAPI video_accelerator_QueryInterface(IAMVideoAccelerator *iface, REFIID iid, void **out)
2450 struct quartz_vmr *filter = impl_from_IAMVideoAccelerator(iface);
2451 return IPin_QueryInterface(&filter->renderer.sink.pin.IPin_iface, iid, out);
2454 static ULONG WINAPI video_accelerator_AddRef(IAMVideoAccelerator *iface)
2456 struct quartz_vmr *filter = impl_from_IAMVideoAccelerator(iface);
2457 return IPin_AddRef(&filter->renderer.sink.pin.IPin_iface);
2460 static ULONG WINAPI video_accelerator_Release(IAMVideoAccelerator *iface)
2462 struct quartz_vmr *filter = impl_from_IAMVideoAccelerator(iface);
2463 return IPin_Release(&filter->renderer.sink.pin.IPin_iface);
2466 static HRESULT WINAPI video_accelerator_GetVideoAcceleratorGUIDs(
2467 IAMVideoAccelerator *iface, DWORD *count, GUID *accelerators)
2469 FIXME("iface %p, count %p, accelerators %p, stub!\n", iface, count, accelerators);
2470 return E_NOTIMPL;
2473 static HRESULT WINAPI video_accelerator_GetUncompFormatsSupported(IAMVideoAccelerator *iface,
2474 const GUID *accelerator, DWORD *count, DDPIXELFORMAT *formats)
2476 FIXME("iface %p, accelerator %s, count %p, formats %p, stub!\n",
2477 iface, debugstr_guid(accelerator), count, formats);
2478 return E_NOTIMPL;
2481 static HRESULT WINAPI video_accelerator_GetInternalMemInfo(IAMVideoAccelerator *iface,
2482 const GUID *accelerator, const AMVAUncompDataInfo *format_info, AMVAInternalMemInfo *mem_info)
2484 FIXME("iface %p, accelerator %s, format_info %p, mem_info %p, stub!\n",
2485 iface, debugstr_guid(accelerator), format_info, mem_info);
2486 return E_NOTIMPL;
2489 static HRESULT WINAPI video_accelerator_GetCompBufferInfo(IAMVideoAccelerator *iface,
2490 const GUID *accelerator, const AMVAUncompDataInfo *uncompressed_info,
2491 DWORD *compressed_info_count, AMVACompBufferInfo *compressed_infos)
2493 FIXME("iface %p, accelerator %s, uncompressed_info %p, compressed_info_count %p, compressed_infos %p, stub!\n",
2494 iface, debugstr_guid(accelerator), uncompressed_info, compressed_info_count, compressed_infos);
2495 return E_NOTIMPL;
2498 static HRESULT WINAPI video_accelerator_GetInternalCompBufferInfo(
2499 IAMVideoAccelerator *iface, DWORD *count, AMVACompBufferInfo *infos)
2501 FIXME("iface %p, count %p, infos %p, stub!\n", iface, count, infos);
2502 return E_NOTIMPL;
2505 static HRESULT WINAPI video_accelerator_BeginFrame(IAMVideoAccelerator *iface, const AMVABeginFrameInfo *info)
2507 FIXME("iface %p, info %p, stub!\n", iface, info);
2508 return E_NOTIMPL;
2511 static HRESULT WINAPI video_accelerator_EndFrame(IAMVideoAccelerator *iface, const AMVAEndFrameInfo *info)
2513 FIXME("iface %p, info %p, stub!\n", iface, info);
2514 return E_NOTIMPL;
2517 static HRESULT WINAPI video_accelerator_GetBuffer(IAMVideoAccelerator *iface,
2518 DWORD type_index, DWORD buffer_index, BOOL read_only, void **buffer, LONG *stride)
2520 FIXME("iface %p, type_index %lu, buffer_index %lu, read_only %d, buffer %p, stride %p, stub!\n",
2521 iface, type_index, buffer_index, read_only, buffer, stride);
2522 return E_NOTIMPL;
2525 static HRESULT WINAPI video_accelerator_ReleaseBuffer(
2526 IAMVideoAccelerator *iface, DWORD type_index, DWORD buffer_index)
2528 FIXME("iface %p, type_index %lu, buffer_index %lu, stub!\n", iface, type_index, buffer_index);
2529 return E_NOTIMPL;
2532 static HRESULT WINAPI video_accelerator_Execute(IAMVideoAccelerator *iface,
2533 DWORD function, void *in_data, DWORD in_size, void *out_data,
2534 DWORD out_size, DWORD buffer_count, const AMVABUFFERINFO *buffers)
2536 FIXME("iface %p, function %#lx, in_data %p, in_size %lu,"
2537 " out_data %p, out_size %lu, buffer_count %lu, buffers %p, stub!\n",
2538 iface, function, in_data, in_size, out_data, out_size, buffer_count, buffers);
2539 return E_NOTIMPL;
2542 static HRESULT WINAPI video_accelerator_QueryRenderStatus(IAMVideoAccelerator *iface,
2543 DWORD type_index, DWORD buffer_index, DWORD flags)
2545 FIXME("iface %p, type_index %lu, buffer_index %lu, flags %#lx, stub!\n",
2546 iface, type_index, buffer_index, flags);
2547 return E_NOTIMPL;
2550 static HRESULT WINAPI video_accelerator_DisplayFrame(
2551 IAMVideoAccelerator *iface, DWORD index, IMediaSample *sample)
2553 FIXME("iface %p, index %lu, sample %p, stub!\n", iface, index, sample);
2554 return E_NOTIMPL;
2557 static const IAMVideoAcceleratorVtbl video_accelerator_vtbl =
2559 video_accelerator_QueryInterface,
2560 video_accelerator_AddRef,
2561 video_accelerator_Release,
2562 video_accelerator_GetVideoAcceleratorGUIDs,
2563 video_accelerator_GetUncompFormatsSupported,
2564 video_accelerator_GetInternalMemInfo,
2565 video_accelerator_GetCompBufferInfo,
2566 video_accelerator_GetInternalCompBufferInfo,
2567 video_accelerator_BeginFrame,
2568 video_accelerator_EndFrame,
2569 video_accelerator_GetBuffer,
2570 video_accelerator_ReleaseBuffer,
2571 video_accelerator_Execute,
2572 video_accelerator_QueryRenderStatus,
2573 video_accelerator_DisplayFrame,
2576 static inline struct quartz_vmr *impl_from_IOverlay(IOverlay *iface)
2578 return CONTAINING_RECORD(iface, struct quartz_vmr, IOverlay_iface);
2581 static HRESULT WINAPI overlay_QueryInterface(IOverlay *iface, REFIID iid, void **out)
2583 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2584 return IPin_QueryInterface(&filter->renderer.sink.pin.IPin_iface, iid, out);
2587 static ULONG WINAPI overlay_AddRef(IOverlay *iface)
2589 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2590 return IPin_AddRef(&filter->renderer.sink.pin.IPin_iface);
2593 static ULONG WINAPI overlay_Release(IOverlay *iface)
2595 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2596 return IPin_Release(&filter->renderer.sink.pin.IPin_iface);
2599 static HRESULT WINAPI overlay_GetPalette(IOverlay *iface, DWORD *count, PALETTEENTRY **palette)
2601 FIXME("iface %p, count %p, palette %p, stub!\n", iface, count, palette);
2602 return E_NOTIMPL;
2605 static HRESULT WINAPI overlay_SetPalette(IOverlay *iface, DWORD count, PALETTEENTRY *palette)
2607 FIXME("iface %p, count %lu, palette %p, stub!\n", iface, count, palette);
2608 return E_NOTIMPL;
2611 static HRESULT WINAPI overlay_GetDefaultColorKey(IOverlay *iface, COLORKEY *key)
2613 FIXME("iface %p, key %p, stub!\n", iface, key);
2614 return E_NOTIMPL;
2617 static HRESULT WINAPI overlay_GetColorKey(IOverlay *iface, COLORKEY *key)
2619 FIXME("iface %p, key %p, stub!\n", iface, key);
2620 return E_NOTIMPL;
2623 static HRESULT WINAPI overlay_SetColorKey(IOverlay *iface, COLORKEY *key)
2625 FIXME("iface %p, key %p, stub!\n", iface, key);
2626 return E_NOTIMPL;
2629 static HRESULT WINAPI overlay_GetWindowHandle(IOverlay *iface, HWND *window)
2631 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2633 TRACE("filter %p, window %p.\n", filter, window);
2635 if (!filter->window.hwnd)
2636 return VFW_E_WRONG_STATE;
2638 *window = filter->window.hwnd;
2639 return S_OK;
2642 static HRESULT WINAPI overlay_GetClipList(IOverlay *iface, RECT *source, RECT *dest, RGNDATA **region)
2644 FIXME("iface %p, source %p, dest %p, region %p, stub!\n", iface, source, dest, region);
2645 return E_NOTIMPL;
2648 static HRESULT WINAPI overlay_GetVideoPosition(IOverlay *iface, RECT *source, RECT *dest)
2650 FIXME("iface %p, source %p, dest %p, stub!\n", iface, source, dest);
2651 return E_NOTIMPL;
2654 static HRESULT WINAPI overlay_Advise(IOverlay *iface, IOverlayNotify *sink, DWORD flags)
2656 FIXME("iface %p, sink %p, flags %#lx, stub!\n", iface, sink, flags);
2657 return E_NOTIMPL;
2660 static HRESULT WINAPI overlay_Unadvise(IOverlay *iface)
2662 FIXME("iface %p, stub!\n", iface);
2663 return E_NOTIMPL;
2666 static const IOverlayVtbl overlay_vtbl =
2668 overlay_QueryInterface,
2669 overlay_AddRef,
2670 overlay_Release,
2671 overlay_GetPalette,
2672 overlay_SetPalette,
2673 overlay_GetDefaultColorKey,
2674 overlay_GetColorKey,
2675 overlay_SetColorKey,
2676 overlay_GetWindowHandle,
2677 overlay_GetClipList,
2678 overlay_GetVideoPosition,
2679 overlay_Advise,
2680 overlay_Unadvise,
2683 static HRESULT vmr_create(IUnknown *outer, IUnknown **out, const CLSID *clsid)
2685 struct quartz_vmr *object;
2686 HRESULT hr;
2688 if (!(object = calloc(1, sizeof(*object))))
2689 return E_OUTOFMEMORY;
2691 object->hD3d9 = LoadLibraryA("d3d9.dll");
2692 if (!object->hD3d9)
2694 WARN("Could not load d3d9.dll\n");
2695 free(object);
2696 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2699 strmbase_renderer_init(&object->renderer, outer, clsid, L"VMR Input0", &renderer_ops);
2700 object->IAMCertifiedOutputProtection_iface.lpVtbl = &IAMCertifiedOutputProtection_Vtbl;
2701 object->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
2702 object->IVMRAspectRatioControl9_iface.lpVtbl = &aspect_ratio_control9_vtbl;
2703 object->IVMRFilterConfig_iface.lpVtbl = &VMR7_FilterConfig_Vtbl;
2704 object->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
2705 object->IVMRMixerBitmap9_iface.lpVtbl = &mixer_bitmap9_vtbl;
2706 object->IVMRMixerControl9_iface.lpVtbl = &mixer_control9_vtbl;
2707 object->IVMRMonitorConfig_iface.lpVtbl = &VMR7_MonitorConfig_Vtbl;
2708 object->IVMRMonitorConfig9_iface.lpVtbl = &VMR9_MonitorConfig_Vtbl;
2709 object->IVMRSurfaceAllocatorNotify_iface.lpVtbl = &VMR7_SurfaceAllocatorNotify_Vtbl;
2710 object->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &VMR9_SurfaceAllocatorNotify_Vtbl;
2711 object->IVMRWindowlessControl_iface.lpVtbl = &VMR7_WindowlessControl_Vtbl;
2712 object->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
2714 object->IAMVideoAccelerator_iface.lpVtbl = &video_accelerator_vtbl;
2715 object->IOverlay_iface.lpVtbl = &overlay_vtbl;
2717 video_window_init(&object->window, &IVideoWindow_VTable,
2718 &object->renderer.filter, &object->renderer.sink.pin, &window_ops);
2720 if (FAILED(hr = video_window_create_window(&object->window)))
2722 video_window_cleanup(&object->window);
2723 strmbase_renderer_cleanup(&object->renderer);
2724 FreeLibrary(object->hD3d9);
2725 free(object);
2726 return hr;
2729 object->mixing_prefs = MixerPref9_NoDecimation | MixerPref9_ARAdjustXorY
2730 | MixerPref9_BiLinearFiltering | MixerPref9_RenderTargetRGB;
2732 TRACE("Created VMR %p.\n", object);
2733 *out = &object->renderer.filter.IUnknown_inner;
2734 return S_OK;
2737 HRESULT vmr7_create(IUnknown *outer, IUnknown **out)
2739 return vmr_create(outer, out, &CLSID_VideoMixingRenderer);
2742 HRESULT vmr9_create(IUnknown *outer, IUnknown **out)
2744 return vmr_create(outer, out, &CLSID_VideoMixingRenderer9);
2748 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, void **ppv)
2750 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2752 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
2754 *ppv = NULL;
2756 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IVMRImagePresenter9))
2757 *ppv = &This->IVMRImagePresenter9_iface;
2758 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocator9))
2759 *ppv = &This->IVMRSurfaceAllocator9_iface;
2761 if (*ppv)
2763 IUnknown_AddRef((IUnknown *)(*ppv));
2764 return S_OK;
2767 FIXME("No interface for %s\n", debugstr_guid(riid));
2769 return E_NOINTERFACE;
2772 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
2774 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2775 ULONG refcount = InterlockedIncrement(&presenter->refCount);
2777 TRACE("%p increasing refcount to %lu.\n", presenter, refcount);
2779 return refcount;
2782 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
2784 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2785 ULONG refcount = InterlockedDecrement(&This->refCount);
2787 TRACE("%p decreasing refcount to %lu.\n", This, refcount);
2789 if (!refcount)
2791 DWORD i;
2793 IDirect3D9_Release(This->d3d9_ptr);
2795 for (i = 0; i < This->num_surfaces; ++i)
2797 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2798 if (surface)
2799 IDirect3DSurface9_Release(surface);
2802 if (This->d3d9_dev)
2803 IDirect3DDevice9_Release(This->d3d9_dev);
2804 free(This->d3d9_surfaces);
2805 This->d3d9_surfaces = NULL;
2806 This->num_surfaces = 0;
2807 free(This);
2808 return 0;
2810 return refcount;
2813 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2815 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2817 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2819 return S_OK;
2822 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2824 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2826 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2828 return S_OK;
2831 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface,
2832 DWORD_PTR cookie, VMR9PresentationInfo *info)
2834 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2835 const struct quartz_vmr *filter = presenter->pVMR9;
2836 IDirect3DDevice9 *device = presenter->d3d9_dev;
2837 const RECT src = filter->window.src;
2838 IDirect3DSurface9 *backbuffer;
2839 RECT dst = filter->window.dst;
2840 HRESULT hr;
2842 TRACE("presenter %p, cookie %#Ix, info %p.\n", presenter, cookie, info);
2844 /* This might happen if we don't have active focus (eg on a different virtual desktop) */
2845 if (!device)
2846 return S_OK;
2848 if (FAILED(hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET,
2849 D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0)))
2850 ERR("Failed to clear, hr %#lx.\n", hr);
2852 if (FAILED(hr = IDirect3DDevice9_BeginScene(device)))
2853 ERR("Failed to begin scene, hr %#lx.\n", hr);
2855 if (FAILED(hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer)))
2857 ERR("Failed to get backbuffer, hr %#lx.\n", hr);
2858 return hr;
2861 if (FAILED(hr = IDirect3DDevice9_StretchRect(device, info->lpSurf, NULL, backbuffer, NULL, D3DTEXF_POINT)))
2862 ERR("Failed to blit image, hr %#lx.\n", hr);
2863 IDirect3DSurface9_Release(backbuffer);
2865 if (FAILED(hr = IDirect3DDevice9_EndScene(device)))
2866 ERR("Failed to end scene, hr %#lx.\n", hr);
2868 if (filter->aspect_mode == VMR9ARMode_LetterBox)
2870 unsigned int src_width = src.right - src.left, src_height = src.bottom - src.top;
2871 unsigned int dst_width = dst.right - dst.left, dst_height = dst.bottom - dst.top;
2873 if (src_width * dst_height > dst_width * src_height)
2875 /* src is "wider" than dst. */
2876 unsigned int dst_center = (dst.top + dst.bottom) / 2;
2877 unsigned int scaled_height = src_height * dst_width / src_width;
2879 dst.top = dst_center - scaled_height / 2;
2880 dst.bottom = dst.top + scaled_height;
2882 else if (src_width * dst_height < dst_width * src_height)
2884 /* src is "taller" than dst. */
2885 unsigned int dst_center = (dst.left + dst.right) / 2;
2886 unsigned int scaled_width = src_width * dst_height / src_height;
2888 dst.left = dst_center - scaled_width / 2;
2889 dst.right = dst.left + scaled_width;
2893 if (FAILED(hr = IDirect3DDevice9_Present(device, &src, &dst, NULL, NULL)))
2894 ERR("Failed to present, hr %#lx.\n", hr);
2896 return S_OK;
2899 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
2901 VMR9_ImagePresenter_QueryInterface,
2902 VMR9_ImagePresenter_AddRef,
2903 VMR9_ImagePresenter_Release,
2904 VMR9_ImagePresenter_StartPresenting,
2905 VMR9_ImagePresenter_StopPresenting,
2906 VMR9_ImagePresenter_PresentImage
2909 static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocator9 *iface, REFIID iid, void **out)
2911 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2912 return IVMRImagePresenter9_QueryInterface(&presenter->IVMRImagePresenter9_iface, iid, out);
2915 static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocator9 *iface)
2917 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2918 return IVMRImagePresenter9_AddRef(&presenter->IVMRImagePresenter9_iface);
2921 static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocator9 *iface)
2923 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2924 return IVMRImagePresenter9_Release(&presenter->IVMRImagePresenter9_iface);
2927 static void adjust_surface_size(const D3DCAPS9 *caps, VMR9AllocationInfo *allocinfo)
2929 UINT width, height;
2931 /* There are no restrictions on the size of offscreen surfaces. */
2932 if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface))
2933 return;
2935 if (!(caps->TextureCaps & D3DPTEXTURECAPS_POW2) || (caps->TextureCaps & D3DPTEXTURECAPS_SQUAREONLY))
2937 width = allocinfo->dwWidth;
2938 height = allocinfo->dwHeight;
2940 else
2942 width = height = 1;
2943 while (width < allocinfo->dwWidth)
2944 width *= 2;
2946 while (height < allocinfo->dwHeight)
2947 height *= 2;
2948 FIXME("NPOW2 support missing, not using proper surfaces!\n");
2951 if (caps->TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
2953 if (height > width)
2954 width = height;
2955 else
2956 height = width;
2957 FIXME("Square texture support required..\n");
2960 allocinfo->dwHeight = height;
2961 allocinfo->dwWidth = width;
2964 static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
2966 UINT d3d9_adapter;
2967 HMONITOR mon;
2969 mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
2970 if (!mon)
2971 d3d9_adapter = 0;
2972 else
2974 for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
2976 if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
2977 break;
2979 if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
2980 d3d9_adapter = 0;
2982 if (mon_out)
2983 *mon_out = mon;
2984 return d3d9_adapter;
2987 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocator9 *iface,
2988 DWORD_PTR cookie, VMR9AllocationInfo *info, DWORD *numbuffers)
2990 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
2991 D3DPRESENT_PARAMETERS d3dpp;
2992 IDirect3DDevice9 *device;
2993 DWORD d3d9_adapter;
2994 D3DCAPS9 caps;
2995 HWND window;
2996 HRESULT hr;
2998 TRACE("presenter %p, cookie %#Ix, info %p, numbuffers %p.\n", This, cookie, info, numbuffers);
3000 This->info = *info;
3002 if (This->pVMR9->mode == VMR9Mode_Windowed)
3003 window = This->pVMR9->window.hwnd;
3004 else
3005 window = This->pVMR9->clipping_window;
3007 /* Obtain a monitor and d3d9 device */
3008 d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, window, &This->hMon);
3010 /* Now try to create the d3d9 device */
3011 ZeroMemory(&d3dpp, sizeof(d3dpp));
3012 d3dpp.Windowed = TRUE;
3013 d3dpp.hDeviceWindow = window;
3014 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
3015 d3dpp.BackBufferWidth = info->dwWidth;
3016 d3dpp.BackBufferHeight = info->dwHeight;
3018 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL,
3019 NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
3020 if (FAILED(hr))
3022 ERR("Failed to create device, hr %#lx.\n", hr);
3023 return hr;
3026 IDirect3DDevice9_GetDeviceCaps(device, &caps);
3027 if (!(caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES))
3029 WARN("Device does not support blitting from textures.\n");
3030 IDirect3DDevice9_Release(device);
3031 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3034 This->d3d9_dev = device;
3035 IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
3037 if (!(This->d3d9_surfaces = calloc(*numbuffers, sizeof(IDirect3DSurface9 *))))
3038 return E_OUTOFMEMORY;
3040 adjust_surface_size(&caps, info);
3042 hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify,
3043 info, numbuffers, This->d3d9_surfaces);
3044 if (FAILED(hr))
3046 ERR("Failed to allocate surfaces, hr %#lx.\n", hr);
3047 IVMRSurfaceAllocator9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
3048 return hr;
3051 This->num_surfaces = *numbuffers;
3053 return S_OK;
3056 static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocator9 *iface, DWORD_PTR cookie)
3058 TRACE("iface %p, cookie %#Ix.\n", iface, cookie);
3060 return S_OK;
3063 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocator9 *iface,
3064 DWORD_PTR cookie, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
3066 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
3068 /* Update everything first, this is needed because the surface might be destroyed in the reset */
3069 if (!This->d3d9_dev)
3071 TRACE("Device has left me!\n");
3072 return E_FAIL;
3075 if (surfaceindex >= This->num_surfaces)
3077 ERR("surfaceindex is greater than num_surfaces\n");
3078 return E_FAIL;
3080 *surface = This->d3d9_surfaces[surfaceindex];
3081 IDirect3DSurface9_AddRef(*surface);
3083 return S_OK;
3086 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocator9 *iface,
3087 IVMRSurfaceAllocatorNotify9 *notify)
3089 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
3091 TRACE("presenter %p, notify %p.\n", presenter, notify);
3093 /* No AddRef taken here or the base VMR9 filter would never be destroyed */
3094 presenter->SurfaceAllocatorNotify = notify;
3095 return S_OK;
3098 static const IVMRSurfaceAllocator9Vtbl VMR9_SurfaceAllocator =
3100 VMR9_SurfaceAllocator_QueryInterface,
3101 VMR9_SurfaceAllocator_AddRef,
3102 VMR9_SurfaceAllocator_Release,
3103 VMR9_SurfaceAllocator_InitializeDevice,
3104 VMR9_SurfaceAllocator_TerminateDevice,
3105 VMR9_SurfaceAllocator_GetSurface,
3106 VMR9_SurfaceAllocator_AdviseNotify,
3109 static IDirect3D9 *init_d3d9(HMODULE d3d9_handle)
3111 IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion);
3113 d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
3114 if (!d3d9_create) return NULL;
3116 return d3d9_create(D3D_SDK_VERSION);
3119 static HRESULT default_presenter_create(struct quartz_vmr *parent, struct default_presenter **presenter)
3121 struct default_presenter *object;
3123 if (!(object = calloc(1, sizeof(*object))))
3124 return E_OUTOFMEMORY;
3126 object->d3d9_ptr = init_d3d9(parent->hD3d9);
3127 if (!object->d3d9_ptr)
3129 WARN("Could not initialize d3d9.dll\n");
3130 free(object);
3131 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3134 object->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
3135 object->IVMRSurfaceAllocator9_iface.lpVtbl = &VMR9_SurfaceAllocator;
3137 object->refCount = 1;
3138 object->pVMR9 = parent;
3140 TRACE("Created default presenter %p.\n", object);
3141 *presenter = object;
3142 return S_OK;