d3d8/tests: Do not test sysmem textures in test_mipmap_upload().
[wine.git] / dlls / quartz / vmr9.c
blob27ebe68e69aaf95147f836d45315b62957bd36f5
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;
98 HMODULE hD3d9;
100 /* Presentation related members */
101 IDirect3DDevice9 *allocator_d3d9_dev;
102 IDirect3DSurface9 **surfaces;
103 DWORD num_surfaces;
104 DWORD cur_surface;
105 DWORD_PTR cookie;
107 HWND clipping_window;
109 VMR9AspectRatioMode aspect_mode;
112 static const BITMAPINFOHEADER *get_filter_bitmap_header(const struct quartz_vmr *filter)
114 return get_bitmap_header(&filter->renderer.sink.pin.mt);
117 static inline BOOL is_vmr9(const struct quartz_vmr *filter)
119 return IsEqualGUID(&filter->renderer.filter.clsid, &CLSID_VideoMixingRenderer9);
122 static inline struct quartz_vmr *impl_from_video_window(struct video_window *iface)
124 return CONTAINING_RECORD(iface, struct quartz_vmr, window);
127 static inline struct quartz_vmr *impl_from_IAMCertifiedOutputProtection(IAMCertifiedOutputProtection *iface)
129 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMCertifiedOutputProtection_iface);
132 static inline struct quartz_vmr *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
134 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMFilterMiscFlags_iface);
137 static inline struct quartz_vmr *impl_from_IVMRFilterConfig(IVMRFilterConfig *iface)
139 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig_iface);
142 static inline struct quartz_vmr *impl_from_IVMRFilterConfig9(IVMRFilterConfig9 *iface)
144 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig9_iface);
147 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig(IVMRMonitorConfig *iface)
149 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig_iface);
152 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig9(IVMRMonitorConfig9 *iface)
154 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig9_iface);
157 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify(IVMRSurfaceAllocatorNotify *iface)
159 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify_iface);
162 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify9(IVMRSurfaceAllocatorNotify9 *iface)
164 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify9_iface);
167 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl(IVMRWindowlessControl *iface)
169 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl_iface);
172 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl9(IVMRWindowlessControl9 *iface)
174 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl9_iface);
177 struct default_presenter
179 IVMRImagePresenter9 IVMRImagePresenter9_iface;
180 IVMRSurfaceAllocator9 IVMRSurfaceAllocator9_iface;
182 LONG refCount;
184 IDirect3DDevice9 *d3d9_dev;
185 IDirect3D9 *d3d9_ptr;
186 IDirect3DSurface9 **d3d9_surfaces;
187 HMONITOR hMon;
188 DWORD num_surfaces;
190 VMR9AllocationInfo info;
192 struct quartz_vmr* pVMR9;
193 IVMRSurfaceAllocatorNotify9 *SurfaceAllocatorNotify;
196 static inline struct default_presenter *impl_from_IVMRImagePresenter9(IVMRImagePresenter9 *iface)
198 return CONTAINING_RECORD(iface, struct default_presenter, IVMRImagePresenter9_iface);
201 static inline struct default_presenter *impl_from_IVMRSurfaceAllocator9(IVMRSurfaceAllocator9 *iface)
203 return CONTAINING_RECORD(iface, struct default_presenter, IVMRSurfaceAllocator9_iface);
206 static HRESULT default_presenter_create(struct quartz_vmr *parent, struct default_presenter **presenter);
208 static inline struct quartz_vmr *impl_from_IBaseFilter(IBaseFilter *iface)
210 return CONTAINING_RECORD(iface, struct quartz_vmr, renderer.filter.IBaseFilter_iface);
213 static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample)
215 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
216 unsigned int data_size, width, depth, src_pitch;
217 const BITMAPINFOHEADER *bitmap_header;
218 REFERENCE_TIME start_time, end_time;
219 VMR9PresentationInfo info = {};
220 D3DLOCKED_RECT locked_rect;
221 BYTE *data = NULL;
222 HRESULT hr;
223 int height;
225 TRACE("filter %p, sample %p.\n", filter, sample);
227 /* It is possible that there is no device at this point */
229 if (!filter->allocator || !filter->presenter)
231 ERR("NO PRESENTER!!\n");
232 return S_FALSE;
235 info.dwFlags = VMR9Sample_SrcDstRectsValid;
237 if (SUCCEEDED(hr = IMediaSample_GetTime(sample, &start_time, &end_time)))
238 info.dwFlags |= VMR9Sample_TimeValid;
240 if (IMediaSample_IsDiscontinuity(sample) == S_OK)
241 info.dwFlags |= VMR9Sample_Discontinuity;
243 if (IMediaSample_IsPreroll(sample) == S_OK)
244 info.dwFlags |= VMR9Sample_Preroll;
246 if (IMediaSample_IsSyncPoint(sample) == S_OK)
247 info.dwFlags |= VMR9Sample_SyncPoint;
249 if (FAILED(hr = IMediaSample_GetPointer(sample, &data)))
251 ERR("Failed to get pointer to sample data, hr %#lx.\n", hr);
252 return hr;
254 data_size = IMediaSample_GetActualDataLength(sample);
256 bitmap_header = get_filter_bitmap_header(filter);
257 width = bitmap_header->biWidth;
258 height = bitmap_header->biHeight;
259 depth = bitmap_header->biBitCount;
260 if (bitmap_header->biCompression == mmioFOURCC('N','V','1','2')
261 || bitmap_header->biCompression == mmioFOURCC('Y','V','1','2'))
262 src_pitch = width;
263 else /* packed YUV (UYVY or YUY2) or RGB */
264 src_pitch = ((width * depth / 8) + 3) & ~3;
266 info.rtStart = start_time;
267 info.rtEnd = end_time;
268 info.szAspectRatio.cx = width;
269 info.szAspectRatio.cy = height;
270 info.lpSurf = filter->surfaces[(++filter->cur_surface) % filter->num_surfaces];
272 if (FAILED(hr = IDirect3DSurface9_LockRect(info.lpSurf, &locked_rect, NULL, D3DLOCK_DISCARD)))
274 ERR("Failed to lock surface, hr %#lx.\n", hr);
275 return hr;
278 if (height > 0 && bitmap_header->biCompression == BI_RGB)
280 BYTE *dst = (BYTE *)locked_rect.pBits + (height * locked_rect.Pitch);
281 const BYTE *src = data;
283 TRACE("Inverting image.\n");
285 while (height--)
287 dst -= locked_rect.Pitch;
288 memcpy(dst, src, width * depth / 8);
289 src += src_pitch;
292 else if (locked_rect.Pitch != src_pitch)
294 BYTE *dst = locked_rect.pBits;
295 const BYTE *src = data;
297 height = abs(height);
299 TRACE("Source pitch %u does not match dest pitch %u; copying manually.\n",
300 src_pitch, locked_rect.Pitch);
302 while (height--)
304 memcpy(dst, src, width * depth / 8);
305 src += src_pitch;
306 dst += locked_rect.Pitch;
309 else
311 memcpy(locked_rect.pBits, data, data_size);
314 IDirect3DSurface9_UnlockRect(info.lpSurf);
316 return IVMRImagePresenter9_PresentImage(filter->presenter, filter->cookie, &info);
319 static HRESULT vmr_query_accept(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
321 if (!IsEqualIID(&mt->majortype, &MEDIATYPE_Video) || !mt->pbFormat)
322 return S_FALSE;
324 if (!IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo)
325 && !IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo2))
326 return S_FALSE;
328 return S_OK;
331 static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *info, DWORD count)
333 HRESULT hr;
334 DWORD i;
336 if (FAILED(hr = IVMRSurfaceAllocator9_InitializeDevice(filter->allocator,
337 filter->cookie, info, &count)))
339 WARN("Failed to initialize device (flags %#lx), hr %#lx.\n", info->dwFlags, hr);
340 return hr;
343 for (i = 0; i < count; ++i)
345 if (FAILED(hr = IVMRSurfaceAllocator9_GetSurface(filter->allocator,
346 filter->cookie, i, 0, &filter->surfaces[i])))
348 ERR("Failed to get surface %lu, hr %#lx.\n", i, hr);
349 while (i--)
350 IDirect3DSurface9_Release(filter->surfaces[i]);
351 IVMRSurfaceAllocator9_TerminateDevice(filter->allocator, filter->cookie);
352 return hr;
356 return hr;
359 static HRESULT allocate_surfaces(struct quartz_vmr *filter, const AM_MEDIA_TYPE *mt)
361 VMR9AllocationInfo info = {};
362 HRESULT hr = E_FAIL;
363 DWORD count = 1;
364 unsigned int i;
365 const BITMAPINFOHEADER *bmiheader = get_bitmap_header(mt);
367 static const struct
369 const GUID *subtype;
370 D3DFORMAT format;
371 DWORD flags;
373 formats[] =
375 {&MEDIASUBTYPE_ARGB1555, D3DFMT_A1R5G5B5, VMR9AllocFlag_TextureSurface},
376 {&MEDIASUBTYPE_ARGB32, D3DFMT_A8R8G8B8, VMR9AllocFlag_TextureSurface},
377 {&MEDIASUBTYPE_ARGB4444, D3DFMT_A4R4G4B4, VMR9AllocFlag_TextureSurface},
379 {&MEDIASUBTYPE_RGB24, D3DFMT_R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
380 {&MEDIASUBTYPE_RGB32, D3DFMT_X8R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
381 {&MEDIASUBTYPE_RGB555, D3DFMT_X1R5G5B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
382 {&MEDIASUBTYPE_RGB565, D3DFMT_R5G6B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface},
384 {&MEDIASUBTYPE_NV12, MAKEFOURCC('N','V','1','2'), VMR9AllocFlag_OffscreenSurface},
385 {&MEDIASUBTYPE_UYVY, D3DFMT_UYVY, VMR9AllocFlag_OffscreenSurface},
386 {&MEDIASUBTYPE_YUY2, D3DFMT_YUY2, VMR9AllocFlag_OffscreenSurface},
387 {&MEDIASUBTYPE_YV12, MAKEFOURCC('Y','V','1','2'), VMR9AllocFlag_OffscreenSurface},
390 TRACE("Initializing in mode %u, our window %p, clipping window %p.\n",
391 filter->mode, filter->window.hwnd, filter->clipping_window);
393 if (filter->mode == VMR9Mode_Windowless && !filter->clipping_window)
394 return S_OK;
396 info.Pool = D3DPOOL_DEFAULT;
397 info.MinBuffers = count;
398 info.dwWidth = info.szAspectRatio.cx = info.szNativeSize.cx = bmiheader->biWidth;
399 info.dwHeight = info.szAspectRatio.cy = info.szNativeSize.cy = bmiheader->biHeight;
401 if (!(filter->surfaces = calloc(count, sizeof(IDirect3DSurface9 *))))
402 return E_OUTOFMEMORY;
403 filter->num_surfaces = count;
404 filter->cur_surface = 0;
406 if (!is_vmr9(filter))
408 switch (bmiheader->biCompression)
410 case BI_RGB:
411 switch (bmiheader->biBitCount)
413 case 24: info.Format = D3DFMT_R8G8B8; break;
414 case 32: info.Format = D3DFMT_X8R8G8B8; break;
415 default:
416 FIXME("Unhandled bit depth %u.\n", bmiheader->biBitCount);
417 free(filter->surfaces);
418 return VFW_E_TYPE_NOT_ACCEPTED;
421 info.dwFlags = VMR9AllocFlag_TextureSurface;
422 break;
424 case mmioFOURCC('N','V','1','2'):
425 case mmioFOURCC('U','Y','V','Y'):
426 case mmioFOURCC('Y','U','Y','2'):
427 case mmioFOURCC('Y','V','1','2'):
428 info.Format = bmiheader->biCompression;
429 info.dwFlags = VMR9AllocFlag_OffscreenSurface;
430 break;
432 default:
433 WARN("Unhandled video compression %#lx.\n", bmiheader->biCompression);
434 free(filter->surfaces);
435 return VFW_E_TYPE_NOT_ACCEPTED;
437 if (FAILED(hr = initialize_device(filter, &info, count)))
438 free(filter->surfaces);
439 return hr;
442 for (i = 0; i < ARRAY_SIZE(formats); ++i)
444 if (IsEqualGUID(&mt->subtype, formats[i].subtype))
446 info.Format = formats[i].format;
448 if (formats[i].flags & VMR9AllocFlag_TextureSurface)
450 info.dwFlags = VMR9AllocFlag_TextureSurface;
451 if (SUCCEEDED(hr = initialize_device(filter, &info, count)))
452 return hr;
455 if (formats[i].flags & VMR9AllocFlag_OffscreenSurface)
457 info.dwFlags = VMR9AllocFlag_OffscreenSurface;
458 if (SUCCEEDED(hr = initialize_device(filter, &info, count)))
459 return hr;
464 free(filter->surfaces);
465 return VFW_E_TYPE_NOT_ACCEPTED;
468 static void vmr_init_stream(struct strmbase_renderer *iface)
470 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
472 if (filter->window.hwnd && filter->window.AutoShow)
473 ShowWindow(filter->window.hwnd, SW_SHOW);
476 static void vmr_start_stream(struct strmbase_renderer *iface)
478 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
480 IVMRImagePresenter9_StartPresenting(filter->presenter, filter->cookie);
483 static void vmr_stop_stream(struct strmbase_renderer *iface)
485 struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
487 TRACE("(%p)\n", This);
489 if (This->renderer.filter.state == State_Running)
490 IVMRImagePresenter9_StopPresenting(This->presenter, This->cookie);
493 static HRESULT vmr_connect(struct strmbase_renderer *iface, const AM_MEDIA_TYPE *mt)
495 struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
496 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(mt);
497 HWND window = filter->window.hwnd;
498 HRESULT hr;
499 RECT rect;
501 SetRect(&rect, 0, 0, bitmap_header->biWidth, bitmap_header->biHeight);
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 const BITMAPINFOHEADER *bmiheader = get_filter_bitmap_header(pVMR9);
649 static RECT defRect;
651 SetRect(&defRect, 0, 0, bmiheader->biWidth, bmiheader->biHeight);
653 return defRect;
656 static HRESULT vmr_get_current_image(struct video_window *iface, LONG *size, LONG *image)
658 struct quartz_vmr *filter = impl_from_video_window(iface);
659 IDirect3DSurface9 *rt = NULL, *surface = NULL;
660 D3DLOCKED_RECT locked_rect;
661 IDirect3DDevice9 *device;
662 unsigned int row_size;
663 BITMAPINFOHEADER bih;
664 LONG i, size_left;
665 char *dst;
666 HRESULT hr;
668 EnterCriticalSection(&filter->renderer.filter.stream_cs);
669 device = filter->allocator_d3d9_dev;
671 bih = *get_filter_bitmap_header(filter);
672 bih.biSizeImage = bih.biWidth * bih.biHeight * bih.biBitCount / 8;
674 if (!image)
676 *size = sizeof(BITMAPINFOHEADER) + bih.biSizeImage;
677 LeaveCriticalSection(&filter->renderer.filter.stream_cs);
678 return S_OK;
681 if (FAILED(hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt)))
682 goto out;
684 if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, bih.biWidth,
685 bih.biHeight, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL)))
686 goto out;
688 if (FAILED(hr = IDirect3DDevice9_GetRenderTargetData(device, rt, surface)))
689 goto out;
691 if (FAILED(hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_READONLY)))
692 goto out;
694 size_left = *size;
695 memcpy(image, &bih, min(size_left, sizeof(BITMAPINFOHEADER)));
696 size_left -= sizeof(BITMAPINFOHEADER);
698 dst = (char *)image + sizeof(BITMAPINFOHEADER);
699 row_size = bih.biWidth * bih.biBitCount / 8;
701 for (i = 0; i < bih.biHeight && size_left > 0; ++i)
703 memcpy(dst, (char *)locked_rect.pBits + (i * locked_rect.Pitch), min(row_size, size_left));
704 dst += row_size;
705 size_left -= row_size;
708 IDirect3DSurface9_UnlockRect(surface);
710 out:
711 if (surface) IDirect3DSurface9_Release(surface);
712 if (rt) IDirect3DSurface9_Release(rt);
713 LeaveCriticalSection(&filter->renderer.filter.stream_cs);
714 return hr;
717 static const struct video_window_ops window_ops =
719 .get_default_rect = vmr_get_default_rect,
720 .get_current_image = vmr_get_current_image,
723 static const IVideoWindowVtbl IVideoWindow_VTable =
725 BaseControlWindowImpl_QueryInterface,
726 BaseControlWindowImpl_AddRef,
727 BaseControlWindowImpl_Release,
728 BaseControlWindowImpl_GetTypeInfoCount,
729 BaseControlWindowImpl_GetTypeInfo,
730 BaseControlWindowImpl_GetIDsOfNames,
731 BaseControlWindowImpl_Invoke,
732 BaseControlWindowImpl_put_Caption,
733 BaseControlWindowImpl_get_Caption,
734 BaseControlWindowImpl_put_WindowStyle,
735 BaseControlWindowImpl_get_WindowStyle,
736 BaseControlWindowImpl_put_WindowStyleEx,
737 BaseControlWindowImpl_get_WindowStyleEx,
738 BaseControlWindowImpl_put_AutoShow,
739 BaseControlWindowImpl_get_AutoShow,
740 BaseControlWindowImpl_put_WindowState,
741 BaseControlWindowImpl_get_WindowState,
742 BaseControlWindowImpl_put_BackgroundPalette,
743 BaseControlWindowImpl_get_BackgroundPalette,
744 BaseControlWindowImpl_put_Visible,
745 BaseControlWindowImpl_get_Visible,
746 BaseControlWindowImpl_put_Left,
747 BaseControlWindowImpl_get_Left,
748 BaseControlWindowImpl_put_Width,
749 BaseControlWindowImpl_get_Width,
750 BaseControlWindowImpl_put_Top,
751 BaseControlWindowImpl_get_Top,
752 BaseControlWindowImpl_put_Height,
753 BaseControlWindowImpl_get_Height,
754 BaseControlWindowImpl_put_Owner,
755 BaseControlWindowImpl_get_Owner,
756 BaseControlWindowImpl_put_MessageDrain,
757 BaseControlWindowImpl_get_MessageDrain,
758 BaseControlWindowImpl_get_BorderColor,
759 BaseControlWindowImpl_put_BorderColor,
760 BaseControlWindowImpl_get_FullScreenMode,
761 BaseControlWindowImpl_put_FullScreenMode,
762 BaseControlWindowImpl_SetWindowForeground,
763 BaseControlWindowImpl_NotifyOwnerMessage,
764 BaseControlWindowImpl_SetWindowPosition,
765 BaseControlWindowImpl_GetWindowPosition,
766 BaseControlWindowImpl_GetMinIdealImageSize,
767 BaseControlWindowImpl_GetMaxIdealImageSize,
768 BaseControlWindowImpl_GetRestorePosition,
769 BaseControlWindowImpl_HideCursor,
770 BaseControlWindowImpl_IsCursorHidden
773 static HRESULT WINAPI AMCertifiedOutputProtection_QueryInterface(IAMCertifiedOutputProtection *iface,
774 REFIID riid, void **ppv)
776 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
777 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
780 static ULONG WINAPI AMCertifiedOutputProtection_AddRef(IAMCertifiedOutputProtection *iface)
782 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
783 return IUnknown_AddRef(This->renderer.filter.outer_unk);
786 static ULONG WINAPI AMCertifiedOutputProtection_Release(IAMCertifiedOutputProtection *iface)
788 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
789 return IUnknown_Release(This->renderer.filter.outer_unk);
792 static HRESULT WINAPI AMCertifiedOutputProtection_KeyExchange(IAMCertifiedOutputProtection *iface,
793 GUID* pRandom, BYTE** VarLenCertGH,
794 DWORD* pdwLengthCertGH)
796 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
798 FIXME("(%p/%p)->(%p, %p, %p) stub\n", iface, This, pRandom, VarLenCertGH, pdwLengthCertGH);
799 return VFW_E_NO_COPP_HW;
802 static HRESULT WINAPI AMCertifiedOutputProtection_SessionSequenceStart(IAMCertifiedOutputProtection *iface,
803 AMCOPPSignature* pSig)
805 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
807 FIXME("(%p/%p)->(%p) stub\n", iface, This, pSig);
808 return VFW_E_NO_COPP_HW;
811 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionCommand(IAMCertifiedOutputProtection *iface,
812 const AMCOPPCommand* cmd)
814 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
816 FIXME("(%p/%p)->(%p) stub\n", iface, This, cmd);
817 return VFW_E_NO_COPP_HW;
820 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionStatus(IAMCertifiedOutputProtection *iface,
821 const AMCOPPStatusInput* pStatusInput,
822 AMCOPPStatusOutput* pStatusOutput)
824 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
826 FIXME("(%p/%p)->(%p, %p) stub\n", iface, This, pStatusInput, pStatusOutput);
827 return VFW_E_NO_COPP_HW;
830 static const IAMCertifiedOutputProtectionVtbl IAMCertifiedOutputProtection_Vtbl =
832 AMCertifiedOutputProtection_QueryInterface,
833 AMCertifiedOutputProtection_AddRef,
834 AMCertifiedOutputProtection_Release,
835 AMCertifiedOutputProtection_KeyExchange,
836 AMCertifiedOutputProtection_SessionSequenceStart,
837 AMCertifiedOutputProtection_ProtectionCommand,
838 AMCertifiedOutputProtection_ProtectionStatus
841 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
842 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
843 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
846 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
847 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
848 return IUnknown_AddRef(This->renderer.filter.outer_unk);
851 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
852 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
853 return IUnknown_Release(This->renderer.filter.outer_unk);
856 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
857 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
860 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
861 AMFilterMiscFlags_QueryInterface,
862 AMFilterMiscFlags_AddRef,
863 AMFilterMiscFlags_Release,
864 AMFilterMiscFlags_GetMiscFlags
867 static HRESULT WINAPI VMR7FilterConfig_QueryInterface(IVMRFilterConfig *iface, REFIID riid,
868 void** ppv)
870 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
871 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
874 static ULONG WINAPI VMR7FilterConfig_AddRef(IVMRFilterConfig *iface)
876 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
877 return IUnknown_AddRef(This->renderer.filter.outer_unk);
880 static ULONG WINAPI VMR7FilterConfig_Release(IVMRFilterConfig *iface)
882 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
883 return IUnknown_Release(This->renderer.filter.outer_unk);
886 static HRESULT WINAPI VMR7FilterConfig_SetImageCompositor(IVMRFilterConfig *iface,
887 IVMRImageCompositor *compositor)
889 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
891 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
892 return E_NOTIMPL;
895 static HRESULT WINAPI VMR7FilterConfig_SetNumberOfStreams(IVMRFilterConfig *iface, DWORD count)
897 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
899 FIXME("filter %p, count %lu, stub!\n", filter, count);
901 return E_NOTIMPL;
904 static HRESULT WINAPI VMR7FilterConfig_GetNumberOfStreams(IVMRFilterConfig *iface, DWORD *max)
906 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
908 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
909 return E_NOTIMPL;
912 static HRESULT WINAPI VMR7FilterConfig_SetRenderingPrefs(IVMRFilterConfig *iface, DWORD flags)
914 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
916 FIXME("filter %p, flags %#lx, stub!\n", filter, flags);
918 return E_NOTIMPL;
921 static HRESULT WINAPI VMR7FilterConfig_GetRenderingPrefs(IVMRFilterConfig *iface, DWORD *renderflags)
923 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
925 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
926 return E_NOTIMPL;
929 static HRESULT WINAPI VMR7FilterConfig_SetRenderingMode(IVMRFilterConfig *iface, DWORD mode)
931 struct quartz_vmr *filter = impl_from_IVMRFilterConfig(iface);
933 TRACE("iface %p, mode %#lx.\n", iface, mode);
935 return IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, mode);
938 static HRESULT WINAPI VMR7FilterConfig_GetRenderingMode(IVMRFilterConfig *iface, DWORD *mode)
940 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
942 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
943 if (!mode) return E_POINTER;
945 if (This->mode)
946 *mode = This->mode;
947 else
948 *mode = VMRMode_Windowed;
950 return S_OK;
953 static const IVMRFilterConfigVtbl VMR7_FilterConfig_Vtbl =
955 VMR7FilterConfig_QueryInterface,
956 VMR7FilterConfig_AddRef,
957 VMR7FilterConfig_Release,
958 VMR7FilterConfig_SetImageCompositor,
959 VMR7FilterConfig_SetNumberOfStreams,
960 VMR7FilterConfig_GetNumberOfStreams,
961 VMR7FilterConfig_SetRenderingPrefs,
962 VMR7FilterConfig_GetRenderingPrefs,
963 VMR7FilterConfig_SetRenderingMode,
964 VMR7FilterConfig_GetRenderingMode
967 struct get_available_monitors_args
969 VMRMONITORINFO *info7;
970 VMR9MonitorInfo *info9;
971 DWORD arraysize;
972 DWORD numdev;
975 static BOOL CALLBACK get_available_monitors_proc(HMONITOR hmon, HDC hdc, LPRECT lprc, LPARAM lparam)
977 struct get_available_monitors_args *args = (struct get_available_monitors_args *)lparam;
978 MONITORINFOEXW mi;
980 if (args->info7 || args->info9)
983 if (!args->arraysize)
984 return FALSE;
986 mi.cbSize = sizeof(mi);
987 if (!GetMonitorInfoW(hmon, (MONITORINFO*)&mi))
988 return TRUE;
990 /* fill VMRMONITORINFO struct */
991 if (args->info7)
993 VMRMONITORINFO *info = args->info7++;
994 memset(info, 0, sizeof(*info));
996 if (args->numdev > 0)
998 info->guid.pGUID = &info->guid.GUID;
999 info->guid.GUID.Data4[7] = args->numdev;
1001 else
1002 info->guid.pGUID = NULL;
1004 info->rcMonitor = mi.rcMonitor;
1005 info->hMon = hmon;
1006 info->dwFlags = mi.dwFlags;
1008 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1010 /* FIXME: how to get these values? */
1011 info->szDescription[0] = 0;
1014 /* fill VMR9MonitorInfo struct */
1015 if (args->info9)
1017 VMR9MonitorInfo *info = args->info9++;
1018 memset(info, 0, sizeof(*info));
1020 info->uDevID = 0; /* FIXME */
1021 info->rcMonitor = mi.rcMonitor;
1022 info->hMon = hmon;
1023 info->dwFlags = mi.dwFlags;
1025 lstrcpynW(info->szDevice, mi.szDevice, ARRAY_SIZE(info->szDevice));
1027 /* FIXME: how to get these values? */
1028 info->szDescription[0] = 0;
1029 info->dwVendorId = 0;
1030 info->dwDeviceId = 0;
1031 info->dwSubSysId = 0;
1032 info->dwRevision = 0;
1035 args->arraysize--;
1038 args->numdev++;
1039 return TRUE;
1042 static HRESULT WINAPI VMR7MonitorConfig_QueryInterface(IVMRMonitorConfig *iface, REFIID riid,
1043 LPVOID * ppv)
1045 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1046 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1049 static ULONG WINAPI VMR7MonitorConfig_AddRef(IVMRMonitorConfig *iface)
1051 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1052 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1055 static ULONG WINAPI VMR7MonitorConfig_Release(IVMRMonitorConfig *iface)
1057 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1058 return IUnknown_Release(This->renderer.filter.outer_unk);
1061 static HRESULT WINAPI VMR7MonitorConfig_SetMonitor(IVMRMonitorConfig *iface, const VMRGUID *pGUID)
1063 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1065 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1067 if (!pGUID)
1068 return E_POINTER;
1070 return S_OK;
1073 static HRESULT WINAPI VMR7MonitorConfig_GetMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1075 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1077 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1079 if (!pGUID)
1080 return E_POINTER;
1082 pGUID->pGUID = NULL; /* default DirectDraw device */
1083 return S_OK;
1086 static HRESULT WINAPI VMR7MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig *iface,
1087 const VMRGUID *pGUID)
1089 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1091 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1093 if (!pGUID)
1094 return E_POINTER;
1096 return S_OK;
1099 static HRESULT WINAPI VMR7MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1101 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1103 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1105 if (!pGUID)
1106 return E_POINTER;
1108 pGUID->pGUID = NULL; /* default DirectDraw device */
1109 return S_OK;
1112 static HRESULT WINAPI VMR7MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig *iface,
1113 VMRMONITORINFO *info, DWORD arraysize,
1114 DWORD *numdev)
1116 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1117 struct get_available_monitors_args args;
1119 TRACE("filter %p, info %p, arraysize %lu, numdev %p.\n", This, info, arraysize, numdev);
1121 if (!numdev)
1122 return E_POINTER;
1124 if (info && arraysize == 0)
1125 return E_INVALIDARG;
1127 args.info7 = info;
1128 args.info9 = NULL;
1129 args.arraysize = arraysize;
1130 args.numdev = 0;
1131 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1133 *numdev = args.numdev;
1134 return S_OK;
1137 static const IVMRMonitorConfigVtbl VMR7_MonitorConfig_Vtbl =
1139 VMR7MonitorConfig_QueryInterface,
1140 VMR7MonitorConfig_AddRef,
1141 VMR7MonitorConfig_Release,
1142 VMR7MonitorConfig_SetMonitor,
1143 VMR7MonitorConfig_GetMonitor,
1144 VMR7MonitorConfig_SetDefaultMonitor,
1145 VMR7MonitorConfig_GetDefaultMonitor,
1146 VMR7MonitorConfig_GetAvailableMonitors
1149 static HRESULT WINAPI VMR9MonitorConfig_QueryInterface(IVMRMonitorConfig9 *iface, REFIID riid,
1150 LPVOID * ppv)
1152 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1153 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1156 static ULONG WINAPI VMR9MonitorConfig_AddRef(IVMRMonitorConfig9 *iface)
1158 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1159 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1162 static ULONG WINAPI VMR9MonitorConfig_Release(IVMRMonitorConfig9 *iface)
1164 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1165 return IUnknown_Release(This->renderer.filter.outer_unk);
1168 static HRESULT WINAPI VMR9MonitorConfig_SetMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1170 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1172 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1174 return S_OK;
1177 static HRESULT WINAPI VMR9MonitorConfig_GetMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1179 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1181 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1183 if (!uDev)
1184 return E_POINTER;
1186 *uDev = 0;
1187 return S_OK;
1190 static HRESULT WINAPI VMR9MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1192 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1194 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1196 return S_OK;
1199 static HRESULT WINAPI VMR9MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1201 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1203 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1205 if (!uDev)
1206 return E_POINTER;
1208 *uDev = 0;
1209 return S_OK;
1212 static HRESULT WINAPI VMR9MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig9 *iface,
1213 VMR9MonitorInfo *info, DWORD arraysize,
1214 DWORD *numdev)
1216 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1217 struct get_available_monitors_args args;
1219 TRACE("filter %p, info %p, arraysize %lu, numdev %p.\n", This, info, arraysize, numdev);
1221 if (!numdev)
1222 return E_POINTER;
1224 if (info && arraysize == 0)
1225 return E_INVALIDARG;
1227 args.info7 = NULL;
1228 args.info9 = info;
1229 args.arraysize = arraysize;
1230 args.numdev = 0;
1231 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1233 *numdev = args.numdev;
1234 return S_OK;
1237 static const IVMRMonitorConfig9Vtbl VMR9_MonitorConfig_Vtbl =
1239 VMR9MonitorConfig_QueryInterface,
1240 VMR9MonitorConfig_AddRef,
1241 VMR9MonitorConfig_Release,
1242 VMR9MonitorConfig_SetMonitor,
1243 VMR9MonitorConfig_GetMonitor,
1244 VMR9MonitorConfig_SetDefaultMonitor,
1245 VMR9MonitorConfig_GetDefaultMonitor,
1246 VMR9MonitorConfig_GetAvailableMonitors
1249 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
1251 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1252 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1255 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
1257 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1258 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1261 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
1263 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1264 return IUnknown_Release(This->renderer.filter.outer_unk);
1267 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
1269 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1271 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
1272 return E_NOTIMPL;
1275 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD count)
1277 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1279 FIXME("iface %p, count %lu, stub!\n", iface, count);
1281 if (!count)
1283 WARN("Application requested zero streams; returning E_INVALIDARG.\n");
1284 return E_INVALIDARG;
1287 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1289 if (filter->stream_count)
1291 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1292 WARN("Stream count is already set; returning VFW_E_WRONG_STATE.\n");
1293 return VFW_E_WRONG_STATE;
1296 filter->stream_count = count;
1298 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1299 return S_OK;
1302 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *count)
1304 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1306 TRACE("filter %p, count %p.\n", filter, count);
1308 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1310 if (!filter->stream_count)
1312 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1313 return VFW_E_VMR_NOT_IN_MIXER_MODE;
1316 *count = filter->stream_count;
1318 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1319 return S_OK;
1322 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD flags)
1324 struct quartz_vmr *filter = impl_from_IVMRFilterConfig9(iface);
1326 TRACE("filter %p, flags %#lx.\n", filter, flags);
1328 return E_NOTIMPL;
1331 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
1333 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1335 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
1336 return E_NOTIMPL;
1339 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
1341 struct default_presenter *default_presenter;
1342 HRESULT hr = S_OK;
1343 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1345 TRACE("filter %p, mode %lu.\n", This, mode);
1347 EnterCriticalSection(&This->renderer.filter.filter_cs);
1348 if (This->mode)
1350 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1351 return VFW_E_WRONG_STATE;
1354 switch (mode)
1356 case VMR9Mode_Windowed:
1357 case VMR9Mode_Windowless:
1358 if (FAILED(hr = default_presenter_create(This, &default_presenter)))
1360 ERR("Failed to create default presenter, hr %#lx.\n", hr);
1361 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1362 return hr;
1364 This->allocator = &default_presenter->IVMRSurfaceAllocator9_iface;
1365 This->presenter = &default_presenter->IVMRImagePresenter9_iface;
1366 IVMRImagePresenter9_AddRef(This->presenter);
1368 IVMRSurfaceAllocator9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
1369 break;
1370 case VMR9Mode_Renderless:
1371 break;
1372 default:
1373 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1374 return E_INVALIDARG;
1377 if (mode != VMR9Mode_Windowed)
1378 video_window_cleanup(&This->window);
1380 This->mode = mode;
1381 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1382 return hr;
1385 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
1387 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1389 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
1390 if (!mode)
1391 return E_POINTER;
1393 if (This->mode)
1394 *mode = This->mode;
1395 else
1396 *mode = VMR9Mode_Windowed;
1398 return S_OK;
1401 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
1403 VMR9FilterConfig_QueryInterface,
1404 VMR9FilterConfig_AddRef,
1405 VMR9FilterConfig_Release,
1406 VMR9FilterConfig_SetImageCompositor,
1407 VMR9FilterConfig_SetNumberOfStreams,
1408 VMR9FilterConfig_GetNumberOfStreams,
1409 VMR9FilterConfig_SetRenderingPrefs,
1410 VMR9FilterConfig_GetRenderingPrefs,
1411 VMR9FilterConfig_SetRenderingMode,
1412 VMR9FilterConfig_GetRenderingMode
1415 static HRESULT WINAPI VMR7WindowlessControl_QueryInterface(IVMRWindowlessControl *iface, REFIID riid,
1416 LPVOID * ppv)
1418 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1419 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1422 static ULONG WINAPI VMR7WindowlessControl_AddRef(IVMRWindowlessControl *iface)
1424 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1425 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1428 static ULONG WINAPI VMR7WindowlessControl_Release(IVMRWindowlessControl *iface)
1430 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1431 return IUnknown_Release(This->renderer.filter.outer_unk);
1434 static HRESULT WINAPI VMR7WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl *iface,
1435 LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height)
1437 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1438 const BITMAPINFOHEADER *bmiheader = get_filter_bitmap_header(filter);
1440 TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n",
1441 filter, width, height, aspect_width, aspect_height);
1443 if (!width || !height)
1444 return E_POINTER;
1446 *width = bmiheader->biWidth;
1447 *height = bmiheader->biHeight;
1448 if (aspect_width)
1449 *aspect_width = bmiheader->biWidth;
1450 if (aspect_height)
1451 *aspect_height = bmiheader->biHeight;
1453 return S_OK;
1456 static HRESULT WINAPI VMR7WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl *iface,
1457 LONG *width, LONG *height)
1459 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1461 FIXME("(%p/%p)->(...) stub\n", iface, This);
1462 return E_NOTIMPL;
1465 static HRESULT WINAPI VMR7WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl *iface,
1466 LONG *width, LONG *height)
1468 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1470 FIXME("(%p/%p)->(...) stub\n", iface, This);
1471 return E_NOTIMPL;
1474 static HRESULT WINAPI VMR7WindowlessControl_SetVideoPosition(IVMRWindowlessControl *iface,
1475 const RECT *source, const RECT *dest)
1477 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1479 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1481 EnterCriticalSection(&This->renderer.filter.filter_cs);
1483 if (source)
1484 This->window.src = *source;
1485 if (dest)
1486 This->window.dst = *dest;
1488 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1490 return S_OK;
1493 static HRESULT WINAPI VMR7WindowlessControl_GetVideoPosition(IVMRWindowlessControl *iface,
1494 RECT *source, RECT *dest)
1496 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1498 if (source)
1499 *source = This->window.src;
1501 if (dest)
1502 *dest = This->window.dst;
1504 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1505 return S_OK;
1508 static HRESULT WINAPI VMR7WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl *iface,
1509 DWORD *mode)
1511 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1513 FIXME("(%p/%p)->(...) stub\n", iface, This);
1514 return E_NOTIMPL;
1517 static HRESULT WINAPI VMR7WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl *iface,
1518 DWORD mode)
1520 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1522 FIXME("(%p/%p)->(...) stub\n", iface, This);
1523 return E_NOTIMPL;
1526 static HRESULT WINAPI VMR7WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl *iface, HWND window)
1528 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl(iface);
1530 TRACE("iface %p, window %p.\n", iface, window);
1532 return IVMRWindowlessControl9_SetVideoClippingWindow(&filter->IVMRWindowlessControl9_iface, window);
1535 static HRESULT WINAPI VMR7WindowlessControl_RepaintVideo(IVMRWindowlessControl *iface,
1536 HWND hwnd, HDC hdc)
1538 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1540 FIXME("(%p/%p)->(...) stub\n", iface, This);
1541 return E_NOTIMPL;
1544 static HRESULT WINAPI VMR7WindowlessControl_DisplayModeChanged(IVMRWindowlessControl *iface)
1546 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1548 FIXME("(%p/%p)->(...) stub\n", iface, This);
1549 return E_NOTIMPL;
1552 static HRESULT WINAPI VMR7WindowlessControl_GetCurrentImage(IVMRWindowlessControl *iface,
1553 BYTE **dib)
1555 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1557 FIXME("(%p/%p)->(...) stub\n", iface, This);
1558 return E_NOTIMPL;
1561 static HRESULT WINAPI VMR7WindowlessControl_SetBorderColor(IVMRWindowlessControl *iface,
1562 COLORREF color)
1564 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1566 FIXME("(%p/%p)->(...) stub\n", iface, This);
1567 return E_NOTIMPL;
1570 static HRESULT WINAPI VMR7WindowlessControl_GetBorderColor(IVMRWindowlessControl *iface,
1571 COLORREF *color)
1573 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1575 FIXME("(%p/%p)->(...) stub\n", iface, This);
1576 return E_NOTIMPL;
1579 static HRESULT WINAPI VMR7WindowlessControl_SetColorKey(IVMRWindowlessControl *iface, COLORREF color)
1581 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1583 FIXME("(%p/%p)->(...) stub\n", iface, This);
1584 return E_NOTIMPL;
1587 static HRESULT WINAPI VMR7WindowlessControl_GetColorKey(IVMRWindowlessControl *iface, COLORREF *color)
1589 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1591 FIXME("(%p/%p)->(...) stub\n", iface, This);
1592 return E_NOTIMPL;
1595 static const IVMRWindowlessControlVtbl VMR7_WindowlessControl_Vtbl =
1597 VMR7WindowlessControl_QueryInterface,
1598 VMR7WindowlessControl_AddRef,
1599 VMR7WindowlessControl_Release,
1600 VMR7WindowlessControl_GetNativeVideoSize,
1601 VMR7WindowlessControl_GetMinIdealVideoSize,
1602 VMR7WindowlessControl_GetMaxIdealVideoSize,
1603 VMR7WindowlessControl_SetVideoPosition,
1604 VMR7WindowlessControl_GetVideoPosition,
1605 VMR7WindowlessControl_GetAspectRatioMode,
1606 VMR7WindowlessControl_SetAspectRatioMode,
1607 VMR7WindowlessControl_SetVideoClippingWindow,
1608 VMR7WindowlessControl_RepaintVideo,
1609 VMR7WindowlessControl_DisplayModeChanged,
1610 VMR7WindowlessControl_GetCurrentImage,
1611 VMR7WindowlessControl_SetBorderColor,
1612 VMR7WindowlessControl_GetBorderColor,
1613 VMR7WindowlessControl_SetColorKey,
1614 VMR7WindowlessControl_GetColorKey
1617 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
1619 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1620 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1623 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
1625 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1626 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1629 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
1631 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1632 return IUnknown_Release(This->renderer.filter.outer_unk);
1635 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface,
1636 LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height)
1638 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1639 const BITMAPINFOHEADER *bmiheader = get_filter_bitmap_header(filter);
1641 TRACE("filter %p, width %p, height %p, aspect_width %p, aspect_height %p.\n",
1642 filter, width, height, aspect_width, aspect_height);
1644 if (!width || !height)
1645 return E_POINTER;
1647 *width = bmiheader->biWidth;
1648 *height = bmiheader->biHeight;
1649 if (aspect_width)
1650 *aspect_width = bmiheader->biWidth;
1651 if (aspect_height)
1652 *aspect_height = bmiheader->biHeight;
1654 return S_OK;
1657 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1659 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1661 FIXME("(%p/%p)->(...) stub\n", iface, This);
1662 return E_NOTIMPL;
1665 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1667 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1669 FIXME("(%p/%p)->(...) stub\n", iface, This);
1670 return E_NOTIMPL;
1673 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface,
1674 const RECT *src, const RECT *dst)
1676 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1678 TRACE("filter %p, src %s, dst %s.\n", filter, wine_dbgstr_rect(src), wine_dbgstr_rect(dst));
1680 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1682 if (src)
1683 filter->window.src = *src;
1684 if (dst)
1685 filter->window.dst = *dst;
1687 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1689 return S_OK;
1692 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *src, RECT *dst)
1694 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1696 TRACE("filter %p, src %p, dst %p.\n", filter, src, dst);
1698 if (src)
1699 *src = filter->window.src;
1701 if (dst)
1702 *dst = filter->window.dst;
1704 return S_OK;
1707 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1709 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1711 TRACE("filter %p, mode %p.\n", filter, mode);
1713 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1714 *mode = filter->aspect_mode;
1715 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1716 return S_OK;
1719 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1721 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1723 TRACE("filter %p, mode %lu.\n", filter, mode);
1725 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1726 filter->aspect_mode = mode;
1727 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1728 return S_OK;
1731 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND window)
1733 struct quartz_vmr *filter = impl_from_IVMRWindowlessControl9(iface);
1734 HRESULT hr;
1736 TRACE("filter %p, window %p.\n", filter, window);
1738 if (!IsWindow(window))
1740 WARN("Invalid window %p, returning E_INVALIDARG.\n", window);
1741 return E_INVALIDARG;
1744 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1746 if (filter->renderer.sink.pin.peer)
1748 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1749 WARN("Attempt to set the clipping window while connected; returning VFW_E_WRONG_STATE.\n");
1750 return VFW_E_WRONG_STATE;
1753 filter->clipping_window = window;
1755 hr = IVMRFilterConfig9_SetNumberOfStreams(&filter->IVMRFilterConfig9_iface, 4);
1757 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1758 return hr;
1761 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1763 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1764 HRESULT hr;
1766 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1768 EnterCriticalSection(&This->renderer.filter.filter_cs);
1769 if (hwnd != This->clipping_window)
1771 ERR("Not handling changing windows yet!!!\n");
1772 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1773 return S_OK;
1776 if (!This->allocator_d3d9_dev)
1778 ERR("No d3d9 device!\n");
1779 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1780 return VFW_E_WRONG_STATE;
1783 /* Windowless extension */
1784 hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, NULL, NULL);
1785 LeaveCriticalSection(&This->renderer.filter.filter_cs);
1787 return hr;
1790 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1792 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1794 FIXME("(%p/%p)->(...) stub\n", iface, This);
1795 return E_NOTIMPL;
1798 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1800 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1802 FIXME("(%p/%p)->(...) stub\n", iface, This);
1803 return E_NOTIMPL;
1806 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1808 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1810 FIXME("(%p/%p)->(...) stub\n", iface, This);
1811 return E_NOTIMPL;
1814 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1816 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1818 FIXME("(%p/%p)->(...) stub\n", iface, This);
1819 return E_NOTIMPL;
1822 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1824 VMR9WindowlessControl_QueryInterface,
1825 VMR9WindowlessControl_AddRef,
1826 VMR9WindowlessControl_Release,
1827 VMR9WindowlessControl_GetNativeVideoSize,
1828 VMR9WindowlessControl_GetMinIdealVideoSize,
1829 VMR9WindowlessControl_GetMaxIdealVideoSize,
1830 VMR9WindowlessControl_SetVideoPosition,
1831 VMR9WindowlessControl_GetVideoPosition,
1832 VMR9WindowlessControl_GetAspectRatioMode,
1833 VMR9WindowlessControl_SetAspectRatioMode,
1834 VMR9WindowlessControl_SetVideoClippingWindow,
1835 VMR9WindowlessControl_RepaintVideo,
1836 VMR9WindowlessControl_DisplayModeChanged,
1837 VMR9WindowlessControl_GetCurrentImage,
1838 VMR9WindowlessControl_SetBorderColor,
1839 VMR9WindowlessControl_GetBorderColor
1842 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify *iface,
1843 REFIID riid, LPVOID * ppv)
1845 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1846 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1849 static ULONG WINAPI VMR7SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify *iface)
1851 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1852 return IUnknown_AddRef(This->renderer.filter.outer_unk);
1855 static ULONG WINAPI VMR7SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify *iface)
1857 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1858 return IUnknown_Release(This->renderer.filter.outer_unk);
1861 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify *iface,
1862 DWORD_PTR id,
1863 IVMRSurfaceAllocator *alloc)
1865 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1867 FIXME("(%p/%p)->(...) stub\n", iface, This);
1868 return E_NOTIMPL;
1871 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1872 IDirectDraw7 *device, HMONITOR monitor)
1874 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1876 FIXME("(%p/%p)->(...) stub\n", iface, This);
1877 return E_NOTIMPL;
1880 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_ChangeDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
1881 IDirectDraw7 *device, HMONITOR monitor)
1883 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1885 FIXME("(%p/%p)->(...) stub\n", iface, This);
1886 return E_NOTIMPL;
1889 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces(IVMRSurfaceAllocatorNotify *iface)
1891 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1893 FIXME("(%p/%p)->(...) stub\n", iface, This);
1894 return E_NOTIMPL;
1897 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify *iface, LONG code,
1898 LONG_PTR param1, LONG_PTR param2)
1900 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1902 FIXME("(%p/%p)->(...) stub\n", iface, This);
1903 return E_NOTIMPL;
1906 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetBorderColor(IVMRSurfaceAllocatorNotify *iface,
1907 COLORREF clrBorder)
1909 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
1911 FIXME("(%p/%p)->(...) stub\n", iface, This);
1912 return E_NOTIMPL;
1915 static const IVMRSurfaceAllocatorNotifyVtbl VMR7_SurfaceAllocatorNotify_Vtbl =
1917 VMR7SurfaceAllocatorNotify_QueryInterface,
1918 VMR7SurfaceAllocatorNotify_AddRef,
1919 VMR7SurfaceAllocatorNotify_Release,
1920 VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1921 VMR7SurfaceAllocatorNotify_SetDDrawDevice,
1922 VMR7SurfaceAllocatorNotify_ChangeDDrawDevice,
1923 VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces,
1924 VMR7SurfaceAllocatorNotify_NotifyEvent,
1925 VMR7SurfaceAllocatorNotify_SetBorderColor
1928 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1930 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1931 return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppv);
1934 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1936 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1937 ULONG refcount = InterlockedIncrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1939 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
1941 return refcount;
1944 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1946 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1947 ULONG refcount = InterlockedDecrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
1949 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
1951 if (!refcount && !filter->renderer.filter.refcount)
1952 free(filter);
1954 return refcount;
1957 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(
1958 IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR cookie, IVMRSurfaceAllocator9 *allocator)
1960 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1961 IVMRImagePresenter9 *presenter;
1963 TRACE("filter %p, cookie %#Ix, allocator %p.\n", filter, cookie, allocator);
1965 EnterCriticalSection(&filter->renderer.filter.filter_cs);
1967 filter->cookie = cookie;
1969 if (filter->renderer.sink.pin.peer)
1971 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1972 WARN("Attempt to set allocator while connected; returning VFW_E_WRONG_STATE.\n");
1973 return VFW_E_WRONG_STATE;
1976 if (FAILED(IVMRSurfaceAllocator9_QueryInterface(allocator, &IID_IVMRImagePresenter9, (void **)&presenter)))
1978 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1979 return E_NOINTERFACE;
1982 if (filter->allocator)
1984 IVMRImagePresenter9_Release(filter->presenter);
1985 IVMRSurfaceAllocator9_Release(filter->allocator);
1987 filter->allocator = allocator;
1988 filter->presenter = presenter;
1989 IVMRSurfaceAllocator9_AddRef(allocator);
1991 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
1992 return S_OK;
1995 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface,
1996 IDirect3DDevice9 *device, HMONITOR monitor)
1998 struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2000 TRACE("filter %p, device %p, monitor %p.\n", filter, device, monitor);
2002 if (filter->allocator_d3d9_dev)
2003 IDirect3DDevice9_Release(filter->allocator_d3d9_dev);
2004 filter->allocator_d3d9_dev = device;
2005 IDirect3DDevice9_AddRef(device);
2007 return S_OK;
2010 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface,
2011 IDirect3DDevice9 *device, HMONITOR monitor)
2013 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2015 TRACE("(%p/%p)->(...).\n", iface, This);
2017 if (This->allocator_d3d9_dev)
2018 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
2019 This->allocator_d3d9_dev = device;
2020 IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
2022 if (This->mode && This->allocator && This->presenter)
2024 deallocate_surfaces(This);
2025 allocate_surfaces(This, &This->renderer.sink.pin.mt);
2028 return S_OK;
2031 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
2033 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2034 DWORD i;
2035 HRESULT hr = S_OK;
2037 TRACE("filter %p, allocinfo %p, numbuffers %p, surface %p.\n", This, numbuffers, allocinfo, surface);
2039 if (!allocinfo || !numbuffers || !surface)
2040 return E_POINTER;
2042 TRACE("Flags %#lx, size %lux%lu, format %u (%#x), pool %u, minimum buffers %lu.\n",
2043 allocinfo->dwFlags, allocinfo->dwWidth, allocinfo->dwHeight,
2044 allocinfo->Format, allocinfo->Format, allocinfo->Pool, allocinfo->MinBuffers);
2046 if ((allocinfo->dwFlags & VMR9AllocFlag_TextureSurface)
2047 && (allocinfo->dwFlags & VMR9AllocFlag_OffscreenSurface))
2049 WARN("Invalid flags specified; returning E_INVALIDARG.\n");
2050 return E_INVALIDARG;
2053 if (!allocinfo->Format)
2055 IDirect3DSurface9 *backbuffer;
2056 D3DSURFACE_DESC desc;
2058 IDirect3DDevice9_GetBackBuffer(This->allocator_d3d9_dev, 0, 0,
2059 D3DBACKBUFFER_TYPE_MONO, &backbuffer);
2060 IDirect3DSurface9_GetDesc(backbuffer, &desc);
2061 IDirect3DSurface9_Release(backbuffer);
2062 allocinfo->Format = desc.Format;
2065 if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
2067 WARN("%lu surfaces requested (minimum %lu); returning E_INVALIDARG.\n",
2068 *numbuffers, allocinfo->MinBuffers);
2069 return E_INVALIDARG;
2072 if (!This->allocator_d3d9_dev)
2074 WARN("No Direct3D device; returning VFW_E_WRONG_STATE.\n");
2075 return VFW_E_WRONG_STATE;
2078 if (allocinfo->dwFlags == VMR9AllocFlag_OffscreenSurface)
2080 for (i = 0; i < *numbuffers; ++i)
2082 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight,
2083 allocinfo->Format, allocinfo->Pool, &surface[i], NULL);
2084 if (FAILED(hr))
2085 break;
2088 else if (allocinfo->dwFlags == VMR9AllocFlag_TextureSurface)
2090 for (i = 0; i < *numbuffers; ++i)
2092 IDirect3DTexture9 *texture;
2094 hr = IDirect3DDevice9_CreateTexture(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, 1, D3DUSAGE_DYNAMIC,
2095 allocinfo->Format, allocinfo->Pool, &texture, NULL);
2096 if (FAILED(hr))
2097 break;
2098 IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface[i]);
2099 IDirect3DTexture9_Release(texture);
2102 else if (allocinfo->dwFlags == VMR9AllocFlag_3DRenderTarget)
2104 for (i = 0; i < *numbuffers; ++i)
2106 if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(This->allocator_d3d9_dev,
2107 allocinfo->dwWidth, allocinfo->dwHeight, allocinfo->Format,
2108 D3DMULTISAMPLE_NONE, 0, FALSE, &surface[i], NULL)))
2109 break;
2112 else
2114 FIXME("Unhandled flags %#lx.\n", allocinfo->dwFlags);
2115 return E_NOTIMPL;
2118 if (FAILED(hr))
2119 WARN("%lu/%lu surfaces allocated, hr %#lx.\n", i, *numbuffers, hr);
2121 if (i >= allocinfo->MinBuffers)
2123 hr = S_OK;
2124 *numbuffers = i;
2126 else
2128 for ( ; i > 0; --i) IDirect3DSurface9_Release(surface[i - 1]);
2129 *numbuffers = 0;
2131 return hr;
2134 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
2136 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2137 IMediaEventSink *sink;
2138 HRESULT hr;
2140 TRACE("filter %p, code %#lx, param1 %#Ix, param2 %#Ix.\n", This, code, param1, param2);
2142 hr = IFilterGraph_QueryInterface(This->renderer.filter.graph, &IID_IMediaEventSink, (void **)&sink);
2143 if (FAILED(hr))
2144 return hr;
2145 hr = IMediaEventSink_Notify(sink, code, param1, param2);
2146 IMediaEventSink_Release(sink);
2147 return hr;
2150 static const IVMRSurfaceAllocatorNotify9Vtbl VMR9_SurfaceAllocatorNotify_Vtbl =
2152 VMR9SurfaceAllocatorNotify_QueryInterface,
2153 VMR9SurfaceAllocatorNotify_AddRef,
2154 VMR9SurfaceAllocatorNotify_Release,
2155 VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
2156 VMR9SurfaceAllocatorNotify_SetD3DDevice,
2157 VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
2158 VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
2159 VMR9SurfaceAllocatorNotify_NotifyEvent
2162 static inline struct quartz_vmr *impl_from_IVMRMixerControl9(IVMRMixerControl9 *iface)
2164 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerControl9_iface);
2167 static HRESULT WINAPI mixer_control9_QueryInterface(IVMRMixerControl9 *iface, REFIID iid, void **out)
2169 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2170 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2173 static ULONG WINAPI mixer_control9_AddRef(IVMRMixerControl9 *iface)
2175 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2176 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2179 static ULONG WINAPI mixer_control9_Release(IVMRMixerControl9 *iface)
2181 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2182 return IUnknown_Release(filter->renderer.filter.outer_unk);
2185 static HRESULT WINAPI mixer_control9_SetAlpha(IVMRMixerControl9 *iface, DWORD stream, float alpha)
2187 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2189 FIXME("filter %p, stream %lu, alpha %.8e, stub!\n", filter, stream, alpha);
2191 return E_NOTIMPL;
2194 static HRESULT WINAPI mixer_control9_GetAlpha(IVMRMixerControl9 *iface, DWORD stream, float *alpha)
2196 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2198 FIXME("filter %p, stream %lu, alpha %p, stub!\n", filter, stream, alpha);
2200 return E_NOTIMPL;
2203 static HRESULT WINAPI mixer_control9_SetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD z)
2205 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2207 FIXME("filter %p, stream %lu, z %lu, stub!\n", filter, stream, z);
2209 return E_NOTIMPL;
2212 static HRESULT WINAPI mixer_control9_GetZOrder(IVMRMixerControl9 *iface, DWORD stream, DWORD *z)
2214 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2216 FIXME("filter %p, stream %lu, z %p, stub!\n", filter, stream, z);
2218 return E_NOTIMPL;
2221 static HRESULT WINAPI mixer_control9_SetOutputRect(IVMRMixerControl9 *iface,
2222 DWORD stream, const VMR9NormalizedRect *rect)
2224 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2226 FIXME("filter %p, stream %lu, rect %s, stub!\n", filter, stream, debugstr_normalized_rect(rect));
2228 return E_NOTIMPL;
2231 static HRESULT WINAPI mixer_control9_GetOutputRect(IVMRMixerControl9 *iface,
2232 DWORD stream, VMR9NormalizedRect *rect)
2234 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2236 FIXME("filter %p, stream %lu, rect %p, stub!\n", filter, stream, rect);
2238 return E_NOTIMPL;
2241 static HRESULT WINAPI mixer_control9_SetBackgroundClr(IVMRMixerControl9 *iface, COLORREF color)
2243 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2245 FIXME("filter %p, color #%06lx, stub!\n", filter, color);
2247 return E_NOTIMPL;
2250 static HRESULT WINAPI mixer_control9_GetBackgroundClr(IVMRMixerControl9 *iface, COLORREF *color)
2252 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2254 FIXME("filter %p, color %p, stub!\n", filter, color);
2256 return E_NOTIMPL;
2259 static HRESULT WINAPI mixer_control9_SetMixingPrefs(IVMRMixerControl9 *iface, DWORD flags)
2261 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2263 FIXME("filter %p, flags %#lx, stub!\n", filter, flags);
2265 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2266 filter->mixing_prefs = flags;
2267 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2268 return S_OK;
2271 static HRESULT WINAPI mixer_control9_GetMixingPrefs(IVMRMixerControl9 *iface, DWORD *flags)
2273 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2275 FIXME("filter %p, flags %p, stub!\n", filter, flags);
2277 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2278 *flags = filter->mixing_prefs;
2279 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2280 return S_OK;
2283 static HRESULT WINAPI mixer_control9_SetProcAmpControl(IVMRMixerControl9 *iface,
2284 DWORD stream, VMR9ProcAmpControl *settings)
2286 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2288 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2290 return E_NOTIMPL;
2293 static HRESULT WINAPI mixer_control9_GetProcAmpControl(IVMRMixerControl9 *iface,
2294 DWORD stream, VMR9ProcAmpControl *settings)
2296 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2298 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2300 return E_NOTIMPL;
2303 static HRESULT WINAPI mixer_control9_GetProcAmpControlRange(IVMRMixerControl9 *iface,
2304 DWORD stream, VMR9ProcAmpControlRange *settings)
2306 struct quartz_vmr *filter = impl_from_IVMRMixerControl9(iface);
2308 FIXME("filter %p, settings %p, stub!\n", filter, settings);
2310 return E_NOTIMPL;
2313 static const IVMRMixerControl9Vtbl mixer_control9_vtbl =
2315 mixer_control9_QueryInterface,
2316 mixer_control9_AddRef,
2317 mixer_control9_Release,
2318 mixer_control9_SetAlpha,
2319 mixer_control9_GetAlpha,
2320 mixer_control9_SetZOrder,
2321 mixer_control9_GetZOrder,
2322 mixer_control9_SetOutputRect,
2323 mixer_control9_GetOutputRect,
2324 mixer_control9_SetBackgroundClr,
2325 mixer_control9_GetBackgroundClr,
2326 mixer_control9_SetMixingPrefs,
2327 mixer_control9_GetMixingPrefs,
2328 mixer_control9_SetProcAmpControl,
2329 mixer_control9_GetProcAmpControl,
2330 mixer_control9_GetProcAmpControlRange,
2333 static inline struct quartz_vmr *impl_from_IVMRMixerBitmap9(IVMRMixerBitmap9 *iface)
2335 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMixerBitmap9_iface);
2338 static HRESULT WINAPI mixer_bitmap9_QueryInterface(IVMRMixerBitmap9 *iface, REFIID iid, void **out)
2340 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2341 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2344 static ULONG WINAPI mixer_bitmap9_AddRef(IVMRMixerBitmap9 *iface)
2346 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2347 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2350 static ULONG WINAPI mixer_bitmap9_Release(IVMRMixerBitmap9 *iface)
2352 struct quartz_vmr *filter = impl_from_IVMRMixerBitmap9(iface);
2353 return IUnknown_Release(filter->renderer.filter.outer_unk);
2356 static HRESULT WINAPI mixer_bitmap9_SetAlphaBitmap(IVMRMixerBitmap9 *iface,
2357 const VMR9AlphaBitmap *bitmap)
2359 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2360 TRACE("dwFlags %#lx, hdc %p, pDDS %p, rSrc %s, rDest %s, fAlpha %.8e, clrSrcKey #%06lx, dwFilterMode %#lx.\n",
2361 bitmap->dwFlags, bitmap->hdc, bitmap->pDDS, wine_dbgstr_rect(&bitmap->rSrc),
2362 debugstr_normalized_rect(&bitmap->rDest), bitmap->fAlpha, bitmap->clrSrcKey, bitmap->dwFilterMode);
2363 return E_NOTIMPL;
2366 static HRESULT WINAPI mixer_bitmap9_UpdateAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2367 const VMR9AlphaBitmap *bitmap)
2369 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2370 return E_NOTIMPL;
2373 static HRESULT WINAPI mixer_bitmap9_GetAlphaBitmapParameters(IVMRMixerBitmap9 *iface,
2374 VMR9AlphaBitmap *bitmap)
2376 FIXME("iface %p, bitmap %p, stub!\n", iface, bitmap);
2377 return E_NOTIMPL;
2380 static const IVMRMixerBitmap9Vtbl mixer_bitmap9_vtbl =
2382 mixer_bitmap9_QueryInterface,
2383 mixer_bitmap9_AddRef,
2384 mixer_bitmap9_Release,
2385 mixer_bitmap9_SetAlphaBitmap,
2386 mixer_bitmap9_UpdateAlphaBitmapParameters,
2387 mixer_bitmap9_GetAlphaBitmapParameters,
2390 static inline struct quartz_vmr *impl_from_IVMRAspectRatioControl9(IVMRAspectRatioControl9 *iface)
2392 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRAspectRatioControl9_iface);
2395 static HRESULT WINAPI aspect_ratio_control9_QueryInterface(IVMRAspectRatioControl9 *iface, REFIID iid, void **out)
2397 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2398 return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, iid, out);
2401 static ULONG WINAPI aspect_ratio_control9_AddRef(IVMRAspectRatioControl9 *iface)
2403 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2404 return IUnknown_AddRef(filter->renderer.filter.outer_unk);
2407 static ULONG WINAPI aspect_ratio_control9_Release(IVMRAspectRatioControl9 *iface)
2409 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2410 return IUnknown_Release(filter->renderer.filter.outer_unk);
2413 static HRESULT WINAPI aspect_ratio_control9_GetAspectRatioMode(IVMRAspectRatioControl9 *iface, DWORD *mode)
2415 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2417 TRACE("filter %p, mode %p.\n", filter, mode);
2419 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2420 *mode = filter->aspect_mode;
2421 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2422 return S_OK;
2425 static HRESULT WINAPI aspect_ratio_control9_SetAspectRatioMode(IVMRAspectRatioControl9 *iface, DWORD mode)
2427 struct quartz_vmr *filter = impl_from_IVMRAspectRatioControl9(iface);
2429 TRACE("filter %p, mode %lu.\n", filter, mode);
2431 EnterCriticalSection(&filter->renderer.filter.filter_cs);
2432 filter->aspect_mode = mode;
2433 LeaveCriticalSection(&filter->renderer.filter.filter_cs);
2434 return S_OK;
2437 static const IVMRAspectRatioControl9Vtbl aspect_ratio_control9_vtbl =
2439 aspect_ratio_control9_QueryInterface,
2440 aspect_ratio_control9_AddRef,
2441 aspect_ratio_control9_Release,
2442 aspect_ratio_control9_GetAspectRatioMode,
2443 aspect_ratio_control9_SetAspectRatioMode,
2446 static struct quartz_vmr *impl_from_IAMVideoAccelerator(IAMVideoAccelerator *iface)
2448 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMVideoAccelerator_iface);
2451 static HRESULT WINAPI video_accelerator_QueryInterface(IAMVideoAccelerator *iface, REFIID iid, void **out)
2453 struct quartz_vmr *filter = impl_from_IAMVideoAccelerator(iface);
2454 return IPin_QueryInterface(&filter->renderer.sink.pin.IPin_iface, iid, out);
2457 static ULONG WINAPI video_accelerator_AddRef(IAMVideoAccelerator *iface)
2459 struct quartz_vmr *filter = impl_from_IAMVideoAccelerator(iface);
2460 return IPin_AddRef(&filter->renderer.sink.pin.IPin_iface);
2463 static ULONG WINAPI video_accelerator_Release(IAMVideoAccelerator *iface)
2465 struct quartz_vmr *filter = impl_from_IAMVideoAccelerator(iface);
2466 return IPin_Release(&filter->renderer.sink.pin.IPin_iface);
2469 static HRESULT WINAPI video_accelerator_GetVideoAcceleratorGUIDs(
2470 IAMVideoAccelerator *iface, DWORD *count, GUID *accelerators)
2472 FIXME("iface %p, count %p, accelerators %p, stub!\n", iface, count, accelerators);
2473 return E_NOTIMPL;
2476 static HRESULT WINAPI video_accelerator_GetUncompFormatsSupported(IAMVideoAccelerator *iface,
2477 const GUID *accelerator, DWORD *count, DDPIXELFORMAT *formats)
2479 FIXME("iface %p, accelerator %s, count %p, formats %p, stub!\n",
2480 iface, debugstr_guid(accelerator), count, formats);
2481 return E_NOTIMPL;
2484 static HRESULT WINAPI video_accelerator_GetInternalMemInfo(IAMVideoAccelerator *iface,
2485 const GUID *accelerator, const AMVAUncompDataInfo *format_info, AMVAInternalMemInfo *mem_info)
2487 FIXME("iface %p, accelerator %s, format_info %p, mem_info %p, stub!\n",
2488 iface, debugstr_guid(accelerator), format_info, mem_info);
2489 return E_NOTIMPL;
2492 static HRESULT WINAPI video_accelerator_GetCompBufferInfo(IAMVideoAccelerator *iface,
2493 const GUID *accelerator, const AMVAUncompDataInfo *uncompressed_info,
2494 DWORD *compressed_info_count, AMVACompBufferInfo *compressed_infos)
2496 FIXME("iface %p, accelerator %s, uncompressed_info %p, compressed_info_count %p, compressed_infos %p, stub!\n",
2497 iface, debugstr_guid(accelerator), uncompressed_info, compressed_info_count, compressed_infos);
2498 return E_NOTIMPL;
2501 static HRESULT WINAPI video_accelerator_GetInternalCompBufferInfo(
2502 IAMVideoAccelerator *iface, DWORD *count, AMVACompBufferInfo *infos)
2504 FIXME("iface %p, count %p, infos %p, stub!\n", iface, count, infos);
2505 return E_NOTIMPL;
2508 static HRESULT WINAPI video_accelerator_BeginFrame(IAMVideoAccelerator *iface, const AMVABeginFrameInfo *info)
2510 FIXME("iface %p, info %p, stub!\n", iface, info);
2511 return E_NOTIMPL;
2514 static HRESULT WINAPI video_accelerator_EndFrame(IAMVideoAccelerator *iface, const AMVAEndFrameInfo *info)
2516 FIXME("iface %p, info %p, stub!\n", iface, info);
2517 return E_NOTIMPL;
2520 static HRESULT WINAPI video_accelerator_GetBuffer(IAMVideoAccelerator *iface,
2521 DWORD type_index, DWORD buffer_index, BOOL read_only, void **buffer, LONG *stride)
2523 FIXME("iface %p, type_index %lu, buffer_index %lu, read_only %d, buffer %p, stride %p, stub!\n",
2524 iface, type_index, buffer_index, read_only, buffer, stride);
2525 return E_NOTIMPL;
2528 static HRESULT WINAPI video_accelerator_ReleaseBuffer(
2529 IAMVideoAccelerator *iface, DWORD type_index, DWORD buffer_index)
2531 FIXME("iface %p, type_index %lu, buffer_index %lu, stub!\n", iface, type_index, buffer_index);
2532 return E_NOTIMPL;
2535 static HRESULT WINAPI video_accelerator_Execute(IAMVideoAccelerator *iface,
2536 DWORD function, void *in_data, DWORD in_size, void *out_data,
2537 DWORD out_size, DWORD buffer_count, const AMVABUFFERINFO *buffers)
2539 FIXME("iface %p, function %#lx, in_data %p, in_size %lu,"
2540 " out_data %p, out_size %lu, buffer_count %lu, buffers %p, stub!\n",
2541 iface, function, in_data, in_size, out_data, out_size, buffer_count, buffers);
2542 return E_NOTIMPL;
2545 static HRESULT WINAPI video_accelerator_QueryRenderStatus(IAMVideoAccelerator *iface,
2546 DWORD type_index, DWORD buffer_index, DWORD flags)
2548 FIXME("iface %p, type_index %lu, buffer_index %lu, flags %#lx, stub!\n",
2549 iface, type_index, buffer_index, flags);
2550 return E_NOTIMPL;
2553 static HRESULT WINAPI video_accelerator_DisplayFrame(
2554 IAMVideoAccelerator *iface, DWORD index, IMediaSample *sample)
2556 FIXME("iface %p, index %lu, sample %p, stub!\n", iface, index, sample);
2557 return E_NOTIMPL;
2560 static const IAMVideoAcceleratorVtbl video_accelerator_vtbl =
2562 video_accelerator_QueryInterface,
2563 video_accelerator_AddRef,
2564 video_accelerator_Release,
2565 video_accelerator_GetVideoAcceleratorGUIDs,
2566 video_accelerator_GetUncompFormatsSupported,
2567 video_accelerator_GetInternalMemInfo,
2568 video_accelerator_GetCompBufferInfo,
2569 video_accelerator_GetInternalCompBufferInfo,
2570 video_accelerator_BeginFrame,
2571 video_accelerator_EndFrame,
2572 video_accelerator_GetBuffer,
2573 video_accelerator_ReleaseBuffer,
2574 video_accelerator_Execute,
2575 video_accelerator_QueryRenderStatus,
2576 video_accelerator_DisplayFrame,
2579 static inline struct quartz_vmr *impl_from_IOverlay(IOverlay *iface)
2581 return CONTAINING_RECORD(iface, struct quartz_vmr, IOverlay_iface);
2584 static HRESULT WINAPI overlay_QueryInterface(IOverlay *iface, REFIID iid, void **out)
2586 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2587 return IPin_QueryInterface(&filter->renderer.sink.pin.IPin_iface, iid, out);
2590 static ULONG WINAPI overlay_AddRef(IOverlay *iface)
2592 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2593 return IPin_AddRef(&filter->renderer.sink.pin.IPin_iface);
2596 static ULONG WINAPI overlay_Release(IOverlay *iface)
2598 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2599 return IPin_Release(&filter->renderer.sink.pin.IPin_iface);
2602 static HRESULT WINAPI overlay_GetPalette(IOverlay *iface, DWORD *count, PALETTEENTRY **palette)
2604 FIXME("iface %p, count %p, palette %p, stub!\n", iface, count, palette);
2605 return E_NOTIMPL;
2608 static HRESULT WINAPI overlay_SetPalette(IOverlay *iface, DWORD count, PALETTEENTRY *palette)
2610 FIXME("iface %p, count %lu, palette %p, stub!\n", iface, count, palette);
2611 return E_NOTIMPL;
2614 static HRESULT WINAPI overlay_GetDefaultColorKey(IOverlay *iface, COLORKEY *key)
2616 FIXME("iface %p, key %p, stub!\n", iface, key);
2617 return E_NOTIMPL;
2620 static HRESULT WINAPI overlay_GetColorKey(IOverlay *iface, COLORKEY *key)
2622 FIXME("iface %p, key %p, stub!\n", iface, key);
2623 return E_NOTIMPL;
2626 static HRESULT WINAPI overlay_SetColorKey(IOverlay *iface, COLORKEY *key)
2628 FIXME("iface %p, key %p, stub!\n", iface, key);
2629 return E_NOTIMPL;
2632 static HRESULT WINAPI overlay_GetWindowHandle(IOverlay *iface, HWND *window)
2634 struct quartz_vmr *filter = impl_from_IOverlay(iface);
2636 TRACE("filter %p, window %p.\n", filter, window);
2638 if (!filter->window.hwnd)
2639 return VFW_E_WRONG_STATE;
2641 *window = filter->window.hwnd;
2642 return S_OK;
2645 static HRESULT WINAPI overlay_GetClipList(IOverlay *iface, RECT *source, RECT *dest, RGNDATA **region)
2647 FIXME("iface %p, source %p, dest %p, region %p, stub!\n", iface, source, dest, region);
2648 return E_NOTIMPL;
2651 static HRESULT WINAPI overlay_GetVideoPosition(IOverlay *iface, RECT *source, RECT *dest)
2653 FIXME("iface %p, source %p, dest %p, stub!\n", iface, source, dest);
2654 return E_NOTIMPL;
2657 static HRESULT WINAPI overlay_Advise(IOverlay *iface, IOverlayNotify *sink, DWORD flags)
2659 FIXME("iface %p, sink %p, flags %#lx, stub!\n", iface, sink, flags);
2660 return E_NOTIMPL;
2663 static HRESULT WINAPI overlay_Unadvise(IOverlay *iface)
2665 FIXME("iface %p, stub!\n", iface);
2666 return E_NOTIMPL;
2669 static const IOverlayVtbl overlay_vtbl =
2671 overlay_QueryInterface,
2672 overlay_AddRef,
2673 overlay_Release,
2674 overlay_GetPalette,
2675 overlay_SetPalette,
2676 overlay_GetDefaultColorKey,
2677 overlay_GetColorKey,
2678 overlay_SetColorKey,
2679 overlay_GetWindowHandle,
2680 overlay_GetClipList,
2681 overlay_GetVideoPosition,
2682 overlay_Advise,
2683 overlay_Unadvise,
2686 static HRESULT vmr_create(IUnknown *outer, IUnknown **out, const CLSID *clsid)
2688 struct quartz_vmr *object;
2689 HRESULT hr;
2691 if (!(object = calloc(1, sizeof(*object))))
2692 return E_OUTOFMEMORY;
2694 object->hD3d9 = LoadLibraryA("d3d9.dll");
2695 if (!object->hD3d9)
2697 WARN("Could not load d3d9.dll\n");
2698 free(object);
2699 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2702 strmbase_renderer_init(&object->renderer, outer, clsid, L"VMR Input0", &renderer_ops);
2703 object->IAMCertifiedOutputProtection_iface.lpVtbl = &IAMCertifiedOutputProtection_Vtbl;
2704 object->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
2705 object->IVMRAspectRatioControl9_iface.lpVtbl = &aspect_ratio_control9_vtbl;
2706 object->IVMRFilterConfig_iface.lpVtbl = &VMR7_FilterConfig_Vtbl;
2707 object->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
2708 object->IVMRMixerBitmap9_iface.lpVtbl = &mixer_bitmap9_vtbl;
2709 object->IVMRMixerControl9_iface.lpVtbl = &mixer_control9_vtbl;
2710 object->IVMRMonitorConfig_iface.lpVtbl = &VMR7_MonitorConfig_Vtbl;
2711 object->IVMRMonitorConfig9_iface.lpVtbl = &VMR9_MonitorConfig_Vtbl;
2712 object->IVMRSurfaceAllocatorNotify_iface.lpVtbl = &VMR7_SurfaceAllocatorNotify_Vtbl;
2713 object->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &VMR9_SurfaceAllocatorNotify_Vtbl;
2714 object->IVMRWindowlessControl_iface.lpVtbl = &VMR7_WindowlessControl_Vtbl;
2715 object->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
2717 object->IAMVideoAccelerator_iface.lpVtbl = &video_accelerator_vtbl;
2718 object->IOverlay_iface.lpVtbl = &overlay_vtbl;
2720 video_window_init(&object->window, &IVideoWindow_VTable,
2721 &object->renderer.filter, &object->renderer.sink.pin, &window_ops);
2723 if (FAILED(hr = video_window_create_window(&object->window)))
2725 video_window_cleanup(&object->window);
2726 strmbase_renderer_cleanup(&object->renderer);
2727 FreeLibrary(object->hD3d9);
2728 free(object);
2729 return hr;
2732 object->mixing_prefs = MixerPref9_NoDecimation | MixerPref9_ARAdjustXorY
2733 | MixerPref9_BiLinearFiltering | MixerPref9_RenderTargetRGB;
2735 TRACE("Created VMR %p.\n", object);
2736 *out = &object->renderer.filter.IUnknown_inner;
2737 return S_OK;
2740 HRESULT vmr7_create(IUnknown *outer, IUnknown **out)
2742 return vmr_create(outer, out, &CLSID_VideoMixingRenderer);
2745 HRESULT vmr9_create(IUnknown *outer, IUnknown **out)
2747 return vmr_create(outer, out, &CLSID_VideoMixingRenderer9);
2751 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, void **ppv)
2753 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2755 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
2757 *ppv = NULL;
2759 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IVMRImagePresenter9))
2760 *ppv = &This->IVMRImagePresenter9_iface;
2761 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocator9))
2762 *ppv = &This->IVMRSurfaceAllocator9_iface;
2764 if (*ppv)
2766 IUnknown_AddRef((IUnknown *)(*ppv));
2767 return S_OK;
2770 FIXME("No interface for %s\n", debugstr_guid(riid));
2772 return E_NOINTERFACE;
2775 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
2777 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2778 ULONG refcount = InterlockedIncrement(&presenter->refCount);
2780 TRACE("%p increasing refcount to %lu.\n", presenter, refcount);
2782 return refcount;
2785 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
2787 struct default_presenter *This = impl_from_IVMRImagePresenter9(iface);
2788 ULONG refcount = InterlockedDecrement(&This->refCount);
2790 TRACE("%p decreasing refcount to %lu.\n", This, refcount);
2792 if (!refcount)
2794 DWORD i;
2796 IDirect3D9_Release(This->d3d9_ptr);
2798 for (i = 0; i < This->num_surfaces; ++i)
2800 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2801 if (surface)
2802 IDirect3DSurface9_Release(surface);
2805 if (This->d3d9_dev)
2806 IDirect3DDevice9_Release(This->d3d9_dev);
2807 free(This->d3d9_surfaces);
2808 This->d3d9_surfaces = NULL;
2809 This->num_surfaces = 0;
2810 free(This);
2811 return 0;
2813 return refcount;
2816 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2818 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2820 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2822 return S_OK;
2825 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
2827 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2829 TRACE("presenter %p, cookie %#Ix.\n", presenter, cookie);
2831 return S_OK;
2834 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface,
2835 DWORD_PTR cookie, VMR9PresentationInfo *info)
2837 struct default_presenter *presenter = impl_from_IVMRImagePresenter9(iface);
2838 const struct quartz_vmr *filter = presenter->pVMR9;
2839 IDirect3DDevice9 *device = presenter->d3d9_dev;
2840 const RECT src = filter->window.src;
2841 IDirect3DSurface9 *backbuffer;
2842 RECT dst = filter->window.dst;
2843 HRESULT hr;
2845 TRACE("presenter %p, cookie %#Ix, info %p.\n", presenter, cookie, info);
2847 /* This might happen if we don't have active focus (eg on a different virtual desktop) */
2848 if (!device)
2849 return S_OK;
2851 if (FAILED(hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET,
2852 D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0)))
2853 ERR("Failed to clear, hr %#lx.\n", hr);
2855 if (FAILED(hr = IDirect3DDevice9_BeginScene(device)))
2856 ERR("Failed to begin scene, hr %#lx.\n", hr);
2858 if (FAILED(hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer)))
2860 ERR("Failed to get backbuffer, hr %#lx.\n", hr);
2861 return hr;
2864 if (FAILED(hr = IDirect3DDevice9_StretchRect(device, info->lpSurf, NULL, backbuffer, NULL, D3DTEXF_POINT)))
2865 ERR("Failed to blit image, hr %#lx.\n", hr);
2866 IDirect3DSurface9_Release(backbuffer);
2868 if (FAILED(hr = IDirect3DDevice9_EndScene(device)))
2869 ERR("Failed to end scene, hr %#lx.\n", hr);
2871 if (filter->aspect_mode == VMR9ARMode_LetterBox)
2873 unsigned int src_width = src.right - src.left, src_height = src.bottom - src.top;
2874 unsigned int dst_width = dst.right - dst.left, dst_height = dst.bottom - dst.top;
2876 if (src_width * dst_height > dst_width * src_height)
2878 /* src is "wider" than dst. */
2879 unsigned int dst_center = (dst.top + dst.bottom) / 2;
2880 unsigned int scaled_height = src_height * dst_width / src_width;
2882 dst.top = dst_center - scaled_height / 2;
2883 dst.bottom = dst.top + scaled_height;
2885 else if (src_width * dst_height < dst_width * src_height)
2887 /* src is "taller" than dst. */
2888 unsigned int dst_center = (dst.left + dst.right) / 2;
2889 unsigned int scaled_width = src_width * dst_height / src_height;
2891 dst.left = dst_center - scaled_width / 2;
2892 dst.right = dst.left + scaled_width;
2896 if (FAILED(hr = IDirect3DDevice9_Present(device, &src, &dst, NULL, NULL)))
2897 ERR("Failed to present, hr %#lx.\n", hr);
2899 return S_OK;
2902 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
2904 VMR9_ImagePresenter_QueryInterface,
2905 VMR9_ImagePresenter_AddRef,
2906 VMR9_ImagePresenter_Release,
2907 VMR9_ImagePresenter_StartPresenting,
2908 VMR9_ImagePresenter_StopPresenting,
2909 VMR9_ImagePresenter_PresentImage
2912 static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocator9 *iface, REFIID iid, void **out)
2914 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2915 return IVMRImagePresenter9_QueryInterface(&presenter->IVMRImagePresenter9_iface, iid, out);
2918 static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocator9 *iface)
2920 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2921 return IVMRImagePresenter9_AddRef(&presenter->IVMRImagePresenter9_iface);
2924 static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocator9 *iface)
2926 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
2927 return IVMRImagePresenter9_Release(&presenter->IVMRImagePresenter9_iface);
2930 static void adjust_surface_size(const D3DCAPS9 *caps, VMR9AllocationInfo *allocinfo)
2932 UINT width, height;
2934 /* There are no restrictions on the size of offscreen surfaces. */
2935 if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface))
2936 return;
2938 if (!(caps->TextureCaps & D3DPTEXTURECAPS_POW2) || (caps->TextureCaps & D3DPTEXTURECAPS_SQUAREONLY))
2940 width = allocinfo->dwWidth;
2941 height = allocinfo->dwHeight;
2943 else
2945 width = height = 1;
2946 while (width < allocinfo->dwWidth)
2947 width *= 2;
2949 while (height < allocinfo->dwHeight)
2950 height *= 2;
2951 FIXME("NPOW2 support missing, not using proper surfaces!\n");
2954 if (caps->TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
2956 if (height > width)
2957 width = height;
2958 else
2959 height = width;
2960 FIXME("Square texture support required..\n");
2963 allocinfo->dwHeight = height;
2964 allocinfo->dwWidth = width;
2967 static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
2969 UINT d3d9_adapter;
2970 HMONITOR mon;
2972 mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
2973 if (!mon)
2974 d3d9_adapter = 0;
2975 else
2977 for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
2979 if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
2980 break;
2982 if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
2983 d3d9_adapter = 0;
2985 if (mon_out)
2986 *mon_out = mon;
2987 return d3d9_adapter;
2990 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocator9 *iface,
2991 DWORD_PTR cookie, VMR9AllocationInfo *info, DWORD *numbuffers)
2993 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
2994 D3DPRESENT_PARAMETERS d3dpp;
2995 IDirect3DDevice9 *device;
2996 DWORD d3d9_adapter;
2997 D3DCAPS9 caps;
2998 HWND window;
2999 HRESULT hr;
3001 TRACE("presenter %p, cookie %#Ix, info %p, numbuffers %p.\n", This, cookie, info, numbuffers);
3003 This->info = *info;
3005 if (This->pVMR9->mode == VMR9Mode_Windowed)
3006 window = This->pVMR9->window.hwnd;
3007 else
3008 window = This->pVMR9->clipping_window;
3010 /* Obtain a monitor and d3d9 device */
3011 d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, window, &This->hMon);
3013 /* Now try to create the d3d9 device */
3014 ZeroMemory(&d3dpp, sizeof(d3dpp));
3015 d3dpp.Windowed = TRUE;
3016 d3dpp.hDeviceWindow = window;
3017 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
3018 d3dpp.BackBufferWidth = info->dwWidth;
3019 d3dpp.BackBufferHeight = info->dwHeight;
3021 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL,
3022 NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
3023 if (FAILED(hr))
3025 ERR("Failed to create device, hr %#lx.\n", hr);
3026 return hr;
3029 IDirect3DDevice9_GetDeviceCaps(device, &caps);
3030 if (!(caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES))
3032 WARN("Device does not support blitting from textures.\n");
3033 IDirect3DDevice9_Release(device);
3034 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3037 This->d3d9_dev = device;
3038 IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
3040 if (!(This->d3d9_surfaces = calloc(*numbuffers, sizeof(IDirect3DSurface9 *))))
3041 return E_OUTOFMEMORY;
3043 adjust_surface_size(&caps, info);
3045 hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify,
3046 info, numbuffers, This->d3d9_surfaces);
3047 if (FAILED(hr))
3049 ERR("Failed to allocate surfaces, hr %#lx.\n", hr);
3050 IVMRSurfaceAllocator9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
3051 return hr;
3054 This->num_surfaces = *numbuffers;
3056 return S_OK;
3059 static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocator9 *iface, DWORD_PTR cookie)
3061 TRACE("iface %p, cookie %#Ix.\n", iface, cookie);
3063 return S_OK;
3066 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocator9 *iface,
3067 DWORD_PTR cookie, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
3069 struct default_presenter *This = impl_from_IVMRSurfaceAllocator9(iface);
3071 /* Update everything first, this is needed because the surface might be destroyed in the reset */
3072 if (!This->d3d9_dev)
3074 TRACE("Device has left me!\n");
3075 return E_FAIL;
3078 if (surfaceindex >= This->num_surfaces)
3080 ERR("surfaceindex is greater than num_surfaces\n");
3081 return E_FAIL;
3083 *surface = This->d3d9_surfaces[surfaceindex];
3084 IDirect3DSurface9_AddRef(*surface);
3086 return S_OK;
3089 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocator9 *iface,
3090 IVMRSurfaceAllocatorNotify9 *notify)
3092 struct default_presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
3094 TRACE("presenter %p, notify %p.\n", presenter, notify);
3096 /* No AddRef taken here or the base VMR9 filter would never be destroyed */
3097 presenter->SurfaceAllocatorNotify = notify;
3098 return S_OK;
3101 static const IVMRSurfaceAllocator9Vtbl VMR9_SurfaceAllocator =
3103 VMR9_SurfaceAllocator_QueryInterface,
3104 VMR9_SurfaceAllocator_AddRef,
3105 VMR9_SurfaceAllocator_Release,
3106 VMR9_SurfaceAllocator_InitializeDevice,
3107 VMR9_SurfaceAllocator_TerminateDevice,
3108 VMR9_SurfaceAllocator_GetSurface,
3109 VMR9_SurfaceAllocator_AdviseNotify,
3112 static IDirect3D9 *init_d3d9(HMODULE d3d9_handle)
3114 IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion);
3116 d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
3117 if (!d3d9_create) return NULL;
3119 return d3d9_create(D3D_SDK_VERSION);
3122 static HRESULT default_presenter_create(struct quartz_vmr *parent, struct default_presenter **presenter)
3124 struct default_presenter *object;
3126 if (!(object = calloc(1, sizeof(*object))))
3127 return E_OUTOFMEMORY;
3129 object->d3d9_ptr = init_d3d9(parent->hD3d9);
3130 if (!object->d3d9_ptr)
3132 WARN("Could not initialize d3d9.dll\n");
3133 free(object);
3134 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3137 object->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
3138 object->IVMRSurfaceAllocator9_iface.lpVtbl = &VMR9_SurfaceAllocator;
3140 object->refCount = 1;
3141 object->pVMR9 = parent;
3143 TRACE("Created default presenter %p.\n", object);
3144 *presenter = object;
3145 return S_OK;