[QUARTZ] Sync with Wine Staging 2.2. CORE-12823
[reactos.git] / reactos / dll / directx / wine / quartz / vmr9.c
1 /*
2 * Video Mixing Renderer for dx9
3 *
4 * Copyright 2004 Christian Costa
5 * Copyright 2008 Maarten Lankhorst
6 * Copyright 2012 Aric Stewart
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include "quartz_private.h"
24
25 #include <d3d9.h>
26 #include <vmr9.h>
27
28 struct quartz_vmr
29 {
30 BaseRenderer renderer;
31 BaseControlWindow baseControlWindow;
32 BaseControlVideo baseControlVideo;
33
34 IUnknown IUnknown_inner;
35 IAMCertifiedOutputProtection IAMCertifiedOutputProtection_iface;
36 IAMFilterMiscFlags IAMFilterMiscFlags_iface;
37 IVMRFilterConfig IVMRFilterConfig_iface;
38 IVMRFilterConfig9 IVMRFilterConfig9_iface;
39 IVMRMonitorConfig IVMRMonitorConfig_iface;
40 IVMRMonitorConfig9 IVMRMonitorConfig9_iface;
41 IVMRSurfaceAllocatorNotify IVMRSurfaceAllocatorNotify_iface;
42 IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface;
43 IVMRWindowlessControl IVMRWindowlessControl_iface;
44 IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
45
46 IVMRSurfaceAllocatorEx9 *allocator;
47 IVMRImagePresenter9 *presenter;
48 BOOL allocator_is_ex;
49
50 /*
51 * The Video Mixing Renderer supports 3 modes, renderless, windowless and windowed
52 * What I do is implement windowless as a special case of renderless, and then
53 * windowed also as a special case of windowless. This is probably the easiest way.
54 */
55 VMR9Mode mode;
56 BITMAPINFOHEADER bmiheader;
57 IUnknown * outer_unk;
58 BOOL bUnkOuterValid;
59 BOOL bAggregatable;
60
61 HMODULE hD3d9;
62
63 /* Presentation related members */
64 IDirect3DDevice9 *allocator_d3d9_dev;
65 HMONITOR allocator_mon;
66 DWORD num_surfaces;
67 DWORD cur_surface;
68 DWORD_PTR cookie;
69
70 /* for Windowless Mode */
71 HWND hWndClippingWindow;
72
73 RECT source_rect;
74 RECT target_rect;
75 LONG VideoWidth;
76 LONG VideoHeight;
77 };
78
79 static inline struct quartz_vmr *impl_from_inner_IUnknown(IUnknown *iface)
80 {
81 return CONTAINING_RECORD(iface, struct quartz_vmr, IUnknown_inner);
82 }
83
84 static inline struct quartz_vmr *impl_from_BaseWindow(BaseWindow *wnd)
85 {
86 return CONTAINING_RECORD(wnd, struct quartz_vmr, baseControlWindow.baseWindow);
87 }
88
89 static inline struct quartz_vmr *impl_from_IVideoWindow(IVideoWindow *iface)
90 {
91 return CONTAINING_RECORD(iface, struct quartz_vmr, baseControlWindow.IVideoWindow_iface);
92 }
93
94 static inline struct quartz_vmr *impl_from_BaseControlVideo(BaseControlVideo *cvid)
95 {
96 return CONTAINING_RECORD(cvid, struct quartz_vmr, baseControlVideo);
97 }
98
99 static inline struct quartz_vmr *impl_from_IBasicVideo(IBasicVideo *iface)
100 {
101 return CONTAINING_RECORD(iface, struct quartz_vmr, baseControlVideo.IBasicVideo_iface);
102 }
103
104 static inline struct quartz_vmr *impl_from_IAMCertifiedOutputProtection(IAMCertifiedOutputProtection *iface)
105 {
106 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMCertifiedOutputProtection_iface);
107 }
108
109 static inline struct quartz_vmr *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
110 {
111 return CONTAINING_RECORD(iface, struct quartz_vmr, IAMFilterMiscFlags_iface);
112 }
113
114 static inline struct quartz_vmr *impl_from_IVMRFilterConfig(IVMRFilterConfig *iface)
115 {
116 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig_iface);
117 }
118
119 static inline struct quartz_vmr *impl_from_IVMRFilterConfig9(IVMRFilterConfig9 *iface)
120 {
121 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRFilterConfig9_iface);
122 }
123
124 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig(IVMRMonitorConfig *iface)
125 {
126 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig_iface);
127 }
128
129 static inline struct quartz_vmr *impl_from_IVMRMonitorConfig9(IVMRMonitorConfig9 *iface)
130 {
131 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRMonitorConfig9_iface);
132 }
133
134 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify(IVMRSurfaceAllocatorNotify *iface)
135 {
136 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify_iface);
137 }
138
139 static inline struct quartz_vmr *impl_from_IVMRSurfaceAllocatorNotify9(IVMRSurfaceAllocatorNotify9 *iface)
140 {
141 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRSurfaceAllocatorNotify9_iface);
142 }
143
144 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl(IVMRWindowlessControl *iface)
145 {
146 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl_iface);
147 }
148
149 static inline struct quartz_vmr *impl_from_IVMRWindowlessControl9(IVMRWindowlessControl9 *iface)
150 {
151 return CONTAINING_RECORD(iface, struct quartz_vmr, IVMRWindowlessControl9_iface);
152 }
153
154 typedef struct
155 {
156 IVMRImagePresenter9 IVMRImagePresenter9_iface;
157 IVMRSurfaceAllocatorEx9 IVMRSurfaceAllocatorEx9_iface;
158
159 LONG refCount;
160
161 HANDLE ack;
162 DWORD tid;
163 HANDLE hWndThread;
164
165 IDirect3DDevice9 *d3d9_dev;
166 IDirect3D9 *d3d9_ptr;
167 IDirect3DSurface9 **d3d9_surfaces;
168 IDirect3DVertexBuffer9 *d3d9_vertex;
169 HMONITOR hMon;
170 DWORD num_surfaces;
171
172 BOOL reset;
173 VMR9AllocationInfo info;
174
175 struct quartz_vmr* pVMR9;
176 IVMRSurfaceAllocatorNotify9 *SurfaceAllocatorNotify;
177 } VMR9DefaultAllocatorPresenterImpl;
178
179 static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRImagePresenter9( IVMRImagePresenter9 *iface)
180 {
181 return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRImagePresenter9_iface);
182 }
183
184 static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRSurfaceAllocatorEx9( IVMRSurfaceAllocatorEx9 *iface)
185 {
186 return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRSurfaceAllocatorEx9_iface);
187 }
188
189 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(struct quartz_vmr *parent, LPVOID * ppv);
190
191 static DWORD VMR9_SendSampleData(struct quartz_vmr *This, VMR9PresentationInfo *info, LPBYTE data,
192 DWORD size)
193 {
194 AM_MEDIA_TYPE *amt;
195 HRESULT hr = S_OK;
196 int width;
197 int height;
198 BITMAPINFOHEADER *bmiHeader;
199 D3DLOCKED_RECT lock;
200
201 TRACE("%p %p %d\n", This, data, size);
202
203 amt = &This->renderer.pInputPin->pin.mtCurrent;
204
205 if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
206 {
207 bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
208 }
209 else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
210 {
211 bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
212 }
213 else
214 {
215 FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
216 return VFW_E_RUNTIME_ERROR;
217 }
218
219 TRACE("biSize = %d\n", bmiHeader->biSize);
220 TRACE("biWidth = %d\n", bmiHeader->biWidth);
221 TRACE("biHeight = %d\n", bmiHeader->biHeight);
222 TRACE("biPlanes = %d\n", bmiHeader->biPlanes);
223 TRACE("biBitCount = %d\n", bmiHeader->biBitCount);
224 TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(bmiHeader->biCompression), 4));
225 TRACE("biSizeImage = %d\n", bmiHeader->biSizeImage);
226
227 width = bmiHeader->biWidth;
228 height = bmiHeader->biHeight;
229
230 TRACE("Src Rect: %s\n", wine_dbgstr_rect(&This->source_rect));
231 TRACE("Dst Rect: %s\n", wine_dbgstr_rect(&This->target_rect));
232
233 hr = IDirect3DSurface9_LockRect(info->lpSurf, &lock, NULL, D3DLOCK_DISCARD);
234 if (FAILED(hr))
235 {
236 ERR("IDirect3DSurface9_LockRect failed (%x)\n",hr);
237 return hr;
238 }
239
240 if (height > 0) {
241 /* Bottom up image needs inverting */
242 lock.pBits = (char *)lock.pBits + (height * lock.Pitch);
243 while (height--)
244 {
245 lock.pBits = (char *)lock.pBits - lock.Pitch;
246 memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8);
247 data = data + width * bmiHeader->biBitCount / 8;
248 }
249 }
250 else if (lock.Pitch != width * bmiHeader->biBitCount / 8)
251 {
252 WARN("Slow path! %u/%u\n", lock.Pitch, width * bmiHeader->biBitCount/8);
253
254 while (height--)
255 {
256 memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8);
257 data = data + width * bmiHeader->biBitCount / 8;
258 lock.pBits = (char *)lock.pBits + lock.Pitch;
259 }
260 }
261 else memcpy(lock.pBits, data, size);
262
263 IDirect3DSurface9_UnlockRect(info->lpSurf);
264
265 hr = IVMRImagePresenter9_PresentImage(This->presenter, This->cookie, info);
266 return hr;
267 }
268
269 static HRESULT WINAPI VMR9_DoRenderSample(BaseRenderer *iface, IMediaSample * pSample)
270 {
271 struct quartz_vmr *This = (struct quartz_vmr*)iface;
272 LPBYTE pbSrcStream = NULL;
273 long cbSrcStream = 0;
274 REFERENCE_TIME tStart, tStop;
275 VMR9PresentationInfo info;
276 HRESULT hr;
277
278 TRACE("%p %p\n", iface, pSample);
279
280 /* It is possible that there is no device at this point */
281
282 if (!This->allocator || !This->presenter)
283 {
284 ERR("NO PRESENTER!!\n");
285 return S_FALSE;
286 }
287
288 hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
289 if (FAILED(hr))
290 info.dwFlags = VMR9Sample_SrcDstRectsValid;
291 else
292 info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
293
294 if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
295 info.dwFlags |= VMR9Sample_Discontinuity;
296
297 if (IMediaSample_IsPreroll(pSample) == S_OK)
298 info.dwFlags |= VMR9Sample_Preroll;
299
300 if (IMediaSample_IsSyncPoint(pSample) == S_OK)
301 info.dwFlags |= VMR9Sample_SyncPoint;
302
303 /* If we render ourselves, and this is a preroll sample, discard it */
304 if (This->baseControlWindow.baseWindow.hWnd && (info.dwFlags & VMR9Sample_Preroll))
305 {
306 return S_OK;
307 }
308
309 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
310 if (FAILED(hr))
311 {
312 ERR("Cannot get pointer to sample data (%x)\n", hr);
313 return hr;
314 }
315
316 cbSrcStream = IMediaSample_GetActualDataLength(pSample);
317
318 info.rtStart = tStart;
319 info.rtEnd = tStop;
320 info.szAspectRatio.cx = This->bmiheader.biWidth;
321 info.szAspectRatio.cy = This->bmiheader.biHeight;
322
323 hr = IVMRSurfaceAllocatorEx9_GetSurface(This->allocator, This->cookie, (++This->cur_surface)%This->num_surfaces, 0, &info.lpSurf);
324
325 if (FAILED(hr))
326 return hr;
327
328 VMR9_SendSampleData(This, &info, pbSrcStream, cbSrcStream);
329 IDirect3DSurface9_Release(info.lpSurf);
330
331 return hr;
332 }
333
334 static HRESULT WINAPI VMR9_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
335 {
336 struct quartz_vmr *This = (struct quartz_vmr*)iface;
337
338 if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) || !pmt->pbFormat)
339 return S_FALSE;
340
341 /* Ignore subtype, test for bicompression instead */
342 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
343 {
344 VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
345
346 This->bmiheader = format->bmiHeader;
347 TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
348 This->VideoWidth = format->bmiHeader.biWidth;
349 This->VideoHeight = format->bmiHeader.biHeight;
350 SetRect(&This->source_rect, 0, 0, This->VideoWidth, This->VideoHeight);
351 }
352 else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
353 {
354 VIDEOINFOHEADER2 *format = (VIDEOINFOHEADER2 *)pmt->pbFormat;
355
356 This->bmiheader = format->bmiHeader;
357
358 TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
359 This->VideoWidth = format->bmiHeader.biWidth;
360 This->VideoHeight = format->bmiHeader.biHeight;
361 SetRect(&This->source_rect, 0, 0, This->VideoWidth, This->VideoHeight);
362 }
363 else
364 {
365 ERR("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
366 return S_FALSE;
367 }
368 if (This->bmiheader.biCompression)
369 return S_FALSE;
370 return S_OK;
371 }
372
373 static HRESULT VMR9_maybe_init(struct quartz_vmr *This, BOOL force)
374 {
375 VMR9AllocationInfo info;
376 DWORD buffers;
377 HRESULT hr;
378
379 TRACE("my mode: %u, my window: %p, my last window: %p\n", This->mode, This->baseControlWindow.baseWindow.hWnd, This->hWndClippingWindow);
380 if (This->baseControlWindow.baseWindow.hWnd || !This->renderer.pInputPin->pin.pConnectedTo)
381 return S_OK;
382
383 if (This->mode == VMR9Mode_Windowless && !This->hWndClippingWindow)
384 return (force ? VFW_E_RUNTIME_ERROR : S_OK);
385
386 TRACE("Initializing\n");
387 info.dwFlags = VMR9AllocFlag_TextureSurface;
388 info.dwHeight = This->source_rect.bottom;
389 info.dwWidth = This->source_rect.right;
390 info.Pool = D3DPOOL_DEFAULT;
391 info.MinBuffers = 2;
392 FIXME("Reduce ratio to least common denominator\n");
393 info.szAspectRatio.cx = info.dwWidth;
394 info.szAspectRatio.cy = info.dwHeight;
395 info.szNativeSize.cx = This->bmiheader.biWidth;
396 info.szNativeSize.cy = This->bmiheader.biHeight;
397 buffers = 2;
398
399 switch (This->bmiheader.biBitCount)
400 {
401 case 8: info.Format = D3DFMT_R3G3B2; break;
402 case 15: info.Format = D3DFMT_X1R5G5B5; break;
403 case 16: info.Format = D3DFMT_R5G6B5; break;
404 case 24: info.Format = D3DFMT_R8G8B8; break;
405 case 32: info.Format = D3DFMT_X8R8G8B8; break;
406 default:
407 FIXME("Unknown bpp %u\n", This->bmiheader.biBitCount);
408 hr = E_INVALIDARG;
409 }
410
411 This->cur_surface = 0;
412 if (This->num_surfaces)
413 {
414 ERR("num_surfaces or d3d9_surfaces not 0\n");
415 return E_FAIL;
416 }
417
418 hr = IVMRSurfaceAllocatorEx9_InitializeDevice(This->allocator, This->cookie, &info, &buffers);
419 if (SUCCEEDED(hr))
420 {
421 SetRect(&This->source_rect, 0, 0, This->bmiheader.biWidth, This->bmiheader.biHeight);
422
423 This->num_surfaces = buffers;
424 }
425 return hr;
426 }
427
428 static VOID WINAPI VMR9_OnStartStreaming(BaseRenderer* iface)
429 {
430 struct quartz_vmr *This = (struct quartz_vmr*)iface;
431
432 TRACE("(%p)\n", This);
433
434 VMR9_maybe_init(This, TRUE);
435 IVMRImagePresenter9_StartPresenting(This->presenter, This->cookie);
436 SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
437 This->source_rect.left,
438 This->source_rect.top,
439 This->source_rect.right - This->source_rect.left,
440 This->source_rect.bottom - This->source_rect.top,
441 SWP_NOZORDER|SWP_NOMOVE|SWP_DEFERERASE);
442 ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_SHOW);
443 GetClientRect(This->baseControlWindow.baseWindow.hWnd, &This->target_rect);
444 }
445
446 static VOID WINAPI VMR9_OnStopStreaming(BaseRenderer* iface)
447 {
448 struct quartz_vmr *This = (struct quartz_vmr*)iface;
449
450 TRACE("(%p)\n", This);
451
452 if (This->renderer.filter.state == State_Running)
453 IVMRImagePresenter9_StopPresenting(This->presenter, This->cookie);
454 }
455
456 static HRESULT WINAPI VMR9_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
457 {
458 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
459 if (IMediaSample_IsPreroll(pSample) == S_OK)
460 return E_FAIL;
461 return S_FALSE;
462 }
463
464 static HRESULT WINAPI VMR9_CompleteConnect(BaseRenderer *This, IPin *pReceivePin)
465 {
466 struct quartz_vmr *pVMR9 = (struct quartz_vmr*)This;
467 HRESULT hr;
468
469 TRACE("(%p)\n", This);
470
471 if (pVMR9->mode ||
472 SUCCEEDED(hr = IVMRFilterConfig9_SetRenderingMode(&pVMR9->IVMRFilterConfig9_iface, VMR9Mode_Windowed)))
473 hr = VMR9_maybe_init(pVMR9, FALSE);
474
475 return hr;
476 }
477
478 static HRESULT WINAPI VMR9_BreakConnect(BaseRenderer *This)
479 {
480 struct quartz_vmr *pVMR9 = (struct quartz_vmr*)This;
481 HRESULT hr = S_OK;
482
483 if (!pVMR9->mode)
484 return S_FALSE;
485 if (This->pInputPin->pin.pConnectedTo && pVMR9->allocator && pVMR9->presenter)
486 {
487 if (pVMR9->renderer.filter.state != State_Stopped)
488 {
489 ERR("Disconnecting while not stopped! UNTESTED!!\n");
490 }
491 if (pVMR9->renderer.filter.state == State_Running)
492 hr = IVMRImagePresenter9_StopPresenting(pVMR9->presenter, pVMR9->cookie);
493 IVMRSurfaceAllocatorEx9_TerminateDevice(pVMR9->allocator, pVMR9->cookie);
494 pVMR9->num_surfaces = 0;
495 }
496 return hr;
497 }
498
499 static const BaseRendererFuncTable BaseFuncTable = {
500 VMR9_CheckMediaType,
501 VMR9_DoRenderSample,
502 /**/
503 NULL,
504 NULL,
505 NULL,
506 VMR9_OnStartStreaming,
507 VMR9_OnStopStreaming,
508 NULL,
509 NULL,
510 NULL,
511 VMR9_ShouldDrawSampleNow,
512 NULL,
513 /**/
514 VMR9_CompleteConnect,
515 VMR9_BreakConnect,
516 NULL,
517 NULL,
518 NULL,
519 };
520
521 static LPWSTR WINAPI VMR9_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx)
522 {
523 static WCHAR classnameW[] = { 'I','V','M','R','9',' ','C','l','a','s','s', 0 };
524
525 *pClassStyles = 0;
526 *pWindowStyles = WS_SIZEBOX;
527 *pWindowStylesEx = 0;
528
529 return classnameW;
530 }
531
532 static RECT WINAPI VMR9_GetDefaultRect(BaseWindow *This)
533 {
534 struct quartz_vmr* pVMR9 = impl_from_BaseWindow(This);
535 static RECT defRect;
536
537 SetRect(&defRect, 0, 0, pVMR9->VideoWidth, pVMR9->VideoHeight);
538
539 return defRect;
540 }
541
542 static BOOL WINAPI VMR9_OnSize(BaseWindow *This, LONG Width, LONG Height)
543 {
544 struct quartz_vmr* pVMR9 = impl_from_BaseWindow(This);
545
546 TRACE("WM_SIZE %d %d\n", Width, Height);
547 GetClientRect(This->hWnd, &pVMR9->target_rect);
548 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
549 pVMR9->target_rect.left,
550 pVMR9->target_rect.top,
551 pVMR9->target_rect.right - pVMR9->target_rect.left,
552 pVMR9->target_rect.bottom - pVMR9->target_rect.top);
553 return BaseWindowImpl_OnSize(This, Width, Height);
554 }
555
556 static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
557 VMR9_GetClassWindowStyles,
558 VMR9_GetDefaultRect,
559 NULL,
560 BaseControlWindowImpl_PossiblyEatMessage,
561 VMR9_OnSize,
562 };
563
564 static HRESULT WINAPI VMR9_GetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
565 {
566 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
567 CopyRect(pSourceRect,&pVMR9->source_rect);
568 return S_OK;
569 }
570
571 static HRESULT WINAPI VMR9_GetStaticImage(BaseControlVideo* This, LONG *pBufferSize, LONG *pDIBImage)
572 {
573 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
574 BITMAPINFOHEADER *bmiHeader;
575 LONG needed_size;
576 AM_MEDIA_TYPE *amt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
577 char *ptr;
578
579 FIXME("(%p/%p)->(%p, %p): partial stub\n", pVMR9, This, pBufferSize, pDIBImage);
580
581 EnterCriticalSection(&pVMR9->renderer.filter.csFilter);
582
583 if (!pVMR9->renderer.pMediaSample)
584 {
585 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
586 return (pVMR9->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
587 }
588
589 if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
590 {
591 bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
592 }
593 else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
594 {
595 bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
596 }
597 else
598 {
599 FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
600 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
601 return VFW_E_RUNTIME_ERROR;
602 }
603
604 needed_size = bmiHeader->biSize;
605 needed_size += IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample);
606
607 if (!pDIBImage)
608 {
609 *pBufferSize = needed_size;
610 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
611 return S_OK;
612 }
613
614 if (needed_size < *pBufferSize)
615 {
616 ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
617 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
618 return E_FAIL;
619 }
620 *pBufferSize = needed_size;
621
622 memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
623 IMediaSample_GetPointer(pVMR9->renderer.pMediaSample, (BYTE **)&ptr);
624 memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample));
625
626 LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
627 return S_OK;
628 }
629
630 static HRESULT WINAPI VMR9_GetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
631 {
632 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
633 CopyRect(pTargetRect,&pVMR9->target_rect);
634 return S_OK;
635 }
636
637 static VIDEOINFOHEADER* WINAPI VMR9_GetVideoFormat(BaseControlVideo* This)
638 {
639 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
640 AM_MEDIA_TYPE *pmt;
641
642 TRACE("(%p/%p)\n", pVMR9, This);
643
644 pmt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
645 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
646 return (VIDEOINFOHEADER*)pmt->pbFormat;
647 } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
648 static VIDEOINFOHEADER vih;
649 VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
650 memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
651 memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
652 return &vih;
653 } else {
654 ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
655 return NULL;
656 }
657 }
658
659 static HRESULT WINAPI VMR9_IsDefaultSourceRect(BaseControlVideo* This)
660 {
661 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
662 FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
663
664 return S_OK;
665 }
666
667 static HRESULT WINAPI VMR9_IsDefaultTargetRect(BaseControlVideo* This)
668 {
669 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
670 FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
671
672 return S_OK;
673 }
674
675 static HRESULT WINAPI VMR9_SetDefaultSourceRect(BaseControlVideo* This)
676 {
677 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
678
679 SetRect(&pVMR9->source_rect, 0, 0, pVMR9->VideoWidth, pVMR9->VideoHeight);
680
681 return S_OK;
682 }
683
684 static HRESULT WINAPI VMR9_SetDefaultTargetRect(BaseControlVideo* This)
685 {
686 RECT rect;
687 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
688
689 if (!GetClientRect(pVMR9->baseControlWindow.baseWindow.hWnd, &rect))
690 return E_FAIL;
691
692 SetRect(&pVMR9->target_rect, 0, 0, rect.right, rect.bottom);
693
694 return S_OK;
695 }
696
697 static HRESULT WINAPI VMR9_SetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
698 {
699 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
700 CopyRect(&pVMR9->source_rect,pSourceRect);
701 return S_OK;
702 }
703
704 static HRESULT WINAPI VMR9_SetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
705 {
706 struct quartz_vmr* pVMR9 = impl_from_BaseControlVideo(This);
707 CopyRect(&pVMR9->target_rect,pTargetRect);
708 return S_OK;
709 }
710
711 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
712 VMR9_GetSourceRect,
713 VMR9_GetStaticImage,
714 VMR9_GetTargetRect,
715 VMR9_GetVideoFormat,
716 VMR9_IsDefaultSourceRect,
717 VMR9_IsDefaultTargetRect,
718 VMR9_SetDefaultSourceRect,
719 VMR9_SetDefaultTargetRect,
720 VMR9_SetSourceRect,
721 VMR9_SetTargetRect
722 };
723
724 static HRESULT WINAPI VMR9Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
725 {
726 struct quartz_vmr *This = impl_from_inner_IUnknown(iface);
727 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
728
729 if (This->bAggregatable)
730 This->bUnkOuterValid = TRUE;
731
732 *ppv = NULL;
733
734 if (IsEqualIID(riid, &IID_IUnknown))
735 *ppv = &This->IUnknown_inner;
736 else if (IsEqualIID(riid, &IID_IVideoWindow))
737 *ppv = &This->baseControlWindow.IVideoWindow_iface;
738 else if (IsEqualIID(riid, &IID_IBasicVideo))
739 *ppv = &This->baseControlVideo.IBasicVideo_iface;
740 else if (IsEqualIID(riid, &IID_IAMCertifiedOutputProtection))
741 *ppv = &This->IAMCertifiedOutputProtection_iface;
742 else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
743 *ppv = &This->IAMFilterMiscFlags_iface;
744 else if (IsEqualIID(riid, &IID_IVMRFilterConfig))
745 *ppv = &This->IVMRFilterConfig_iface;
746 else if (IsEqualIID(riid, &IID_IVMRFilterConfig9))
747 *ppv = &This->IVMRFilterConfig9_iface;
748 else if (IsEqualIID(riid, &IID_IVMRMonitorConfig))
749 *ppv = &This->IVMRMonitorConfig_iface;
750 else if (IsEqualIID(riid, &IID_IVMRMonitorConfig9))
751 *ppv = &This->IVMRMonitorConfig9_iface;
752 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify) && This->mode == (VMR9Mode)VMRMode_Renderless)
753 *ppv = &This->IVMRSurfaceAllocatorNotify_iface;
754 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9) && This->mode == VMR9Mode_Renderless)
755 *ppv = &This->IVMRSurfaceAllocatorNotify9_iface;
756 else if (IsEqualIID(riid, &IID_IVMRWindowlessControl) && This->mode == (VMR9Mode)VMRMode_Windowless)
757 *ppv = &This->IVMRWindowlessControl_iface;
758 else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9) && This->mode == VMR9Mode_Windowless)
759 *ppv = &This->IVMRWindowlessControl9_iface;
760 else
761 {
762 HRESULT hr;
763 hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
764 if (SUCCEEDED(hr))
765 return hr;
766 }
767
768 if (*ppv)
769 {
770 IUnknown_AddRef((IUnknown *)(*ppv));
771 return S_OK;
772 }
773
774 else if (IsEqualIID(riid, &IID_IBasicVideo2))
775 FIXME("No interface for IID_IBasicVideo2\n");
776 else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9))
777 ;
778 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9))
779 ;
780 else if (IsEqualIID(riid, &IID_IMediaPosition))
781 FIXME("No interface for IID_IMediaPosition\n");
782 else if (IsEqualIID(riid, &IID_IQualProp))
783 FIXME("No interface for IID_IQualProp\n");
784 else if (IsEqualIID(riid, &IID_IVMRAspectRatioControl9))
785 FIXME("No interface for IID_IVMRAspectRatioControl9\n");
786 else if (IsEqualIID(riid, &IID_IVMRDeinterlaceControl9))
787 FIXME("No interface for IID_IVMRDeinterlaceControl9\n");
788 else if (IsEqualIID(riid, &IID_IVMRMixerBitmap9))
789 FIXME("No interface for IID_IVMRMixerBitmap9\n");
790 else if (IsEqualIID(riid, &IID_IVMRMixerControl9))
791 FIXME("No interface for IID_IVMRMixerControl9\n");
792 else
793 FIXME("No interface for %s\n", debugstr_guid(riid));
794
795 return E_NOINTERFACE;
796 }
797
798 static ULONG WINAPI VMR9Inner_AddRef(IUnknown * iface)
799 {
800 struct quartz_vmr *This = impl_from_inner_IUnknown(iface);
801 ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
802
803 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
804
805 return refCount;
806 }
807
808 static ULONG WINAPI VMR9Inner_Release(IUnknown * iface)
809 {
810 struct quartz_vmr *This = impl_from_inner_IUnknown(iface);
811 ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface);
812
813 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
814
815 if (!refCount)
816 {
817 TRACE("Destroying\n");
818 BaseControlWindow_Destroy(&This->baseControlWindow);
819 FreeLibrary(This->hD3d9);
820
821 if (This->allocator)
822 IVMRSurfaceAllocatorEx9_Release(This->allocator);
823 if (This->presenter)
824 IVMRImagePresenter9_Release(This->presenter);
825
826 This->num_surfaces = 0;
827 if (This->allocator_d3d9_dev)
828 {
829 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
830 This->allocator_d3d9_dev = NULL;
831 }
832
833 CoTaskMemFree(This);
834 }
835 return refCount;
836 }
837
838 static const IUnknownVtbl IInner_VTable =
839 {
840 VMR9Inner_QueryInterface,
841 VMR9Inner_AddRef,
842 VMR9Inner_Release
843 };
844
845 static HRESULT WINAPI VMR9_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
846 {
847 struct quartz_vmr *This = (struct quartz_vmr*)iface;
848
849 if (This->bAggregatable)
850 This->bUnkOuterValid = TRUE;
851
852 if (This->outer_unk)
853 {
854 if (This->bAggregatable)
855 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
856
857 if (IsEqualIID(riid, &IID_IUnknown))
858 {
859 HRESULT hr;
860
861 IUnknown_AddRef(&This->IUnknown_inner);
862 hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
863 IUnknown_Release(&This->IUnknown_inner);
864 This->bAggregatable = TRUE;
865 return hr;
866 }
867
868 *ppv = NULL;
869 return E_NOINTERFACE;
870 }
871
872 return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
873 }
874
875 static ULONG WINAPI VMR9_AddRef(IBaseFilter * iface)
876 {
877 struct quartz_vmr *This = (struct quartz_vmr*)iface;
878 LONG ret;
879
880 if (This->outer_unk && This->bUnkOuterValid)
881 ret = IUnknown_AddRef(This->outer_unk);
882 else
883 ret = IUnknown_AddRef(&This->IUnknown_inner);
884
885 TRACE("(%p)->AddRef from %d\n", iface, ret - 1);
886
887 return ret;
888 }
889
890 static ULONG WINAPI VMR9_Release(IBaseFilter * iface)
891 {
892 struct quartz_vmr *This = (struct quartz_vmr*)iface;
893 LONG ret;
894
895 if (This->outer_unk && This->bUnkOuterValid)
896 ret = IUnknown_Release(This->outer_unk);
897 else
898 ret = IUnknown_Release(&This->IUnknown_inner);
899
900 TRACE("(%p)->Release from %d\n", iface, ret + 1);
901
902 if (ret)
903 return ret;
904 return 0;
905 }
906
907 static const IBaseFilterVtbl VMR_Vtbl =
908 {
909 VMR9_QueryInterface,
910 VMR9_AddRef,
911 VMR9_Release,
912 BaseFilterImpl_GetClassID,
913 BaseRendererImpl_Stop,
914 BaseRendererImpl_Pause,
915 BaseRendererImpl_Run,
916 BaseRendererImpl_GetState,
917 BaseRendererImpl_SetSyncSource,
918 BaseFilterImpl_GetSyncSource,
919 BaseFilterImpl_EnumPins,
920 BaseRendererImpl_FindPin,
921 BaseFilterImpl_QueryFilterInfo,
922 BaseFilterImpl_JoinFilterGraph,
923 BaseFilterImpl_QueryVendorInfo
924 };
925
926 /*** IUnknown methods ***/
927 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface, REFIID riid, LPVOID*ppvObj)
928 {
929 struct quartz_vmr *This = impl_from_IVideoWindow(iface);
930
931 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
932
933 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
934 }
935
936 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface)
937 {
938 struct quartz_vmr *This = impl_from_IVideoWindow(iface);
939
940 TRACE("(%p/%p)->()\n", This, iface);
941
942 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
943 }
944
945 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface)
946 {
947 struct quartz_vmr *This = impl_from_IVideoWindow(iface);
948
949 TRACE("(%p/%p)->()\n", This, iface);
950
951 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
952 }
953
954 static const IVideoWindowVtbl IVideoWindow_VTable =
955 {
956 Videowindow_QueryInterface,
957 Videowindow_AddRef,
958 Videowindow_Release,
959 BaseControlWindowImpl_GetTypeInfoCount,
960 BaseControlWindowImpl_GetTypeInfo,
961 BaseControlWindowImpl_GetIDsOfNames,
962 BaseControlWindowImpl_Invoke,
963 BaseControlWindowImpl_put_Caption,
964 BaseControlWindowImpl_get_Caption,
965 BaseControlWindowImpl_put_WindowStyle,
966 BaseControlWindowImpl_get_WindowStyle,
967 BaseControlWindowImpl_put_WindowStyleEx,
968 BaseControlWindowImpl_get_WindowStyleEx,
969 BaseControlWindowImpl_put_AutoShow,
970 BaseControlWindowImpl_get_AutoShow,
971 BaseControlWindowImpl_put_WindowState,
972 BaseControlWindowImpl_get_WindowState,
973 BaseControlWindowImpl_put_BackgroundPalette,
974 BaseControlWindowImpl_get_BackgroundPalette,
975 BaseControlWindowImpl_put_Visible,
976 BaseControlWindowImpl_get_Visible,
977 BaseControlWindowImpl_put_Left,
978 BaseControlWindowImpl_get_Left,
979 BaseControlWindowImpl_put_Width,
980 BaseControlWindowImpl_get_Width,
981 BaseControlWindowImpl_put_Top,
982 BaseControlWindowImpl_get_Top,
983 BaseControlWindowImpl_put_Height,
984 BaseControlWindowImpl_get_Height,
985 BaseControlWindowImpl_put_Owner,
986 BaseControlWindowImpl_get_Owner,
987 BaseControlWindowImpl_put_MessageDrain,
988 BaseControlWindowImpl_get_MessageDrain,
989 BaseControlWindowImpl_get_BorderColor,
990 BaseControlWindowImpl_put_BorderColor,
991 BaseControlWindowImpl_get_FullScreenMode,
992 BaseControlWindowImpl_put_FullScreenMode,
993 BaseControlWindowImpl_SetWindowForeground,
994 BaseControlWindowImpl_NotifyOwnerMessage,
995 BaseControlWindowImpl_SetWindowPosition,
996 BaseControlWindowImpl_GetWindowPosition,
997 BaseControlWindowImpl_GetMinIdealImageSize,
998 BaseControlWindowImpl_GetMaxIdealImageSize,
999 BaseControlWindowImpl_GetRestorePosition,
1000 BaseControlWindowImpl_HideCursor,
1001 BaseControlWindowImpl_IsCursorHidden
1002 };
1003
1004 /*** IUnknown methods ***/
1005 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID * ppvObj)
1006 {
1007 struct quartz_vmr *This = impl_from_IBasicVideo(iface);
1008
1009 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
1010
1011 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
1012 }
1013
1014 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface)
1015 {
1016 struct quartz_vmr *This = impl_from_IBasicVideo(iface);
1017
1018 TRACE("(%p/%p)->()\n", This, iface);
1019
1020 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1021 }
1022
1023 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface)
1024 {
1025 struct quartz_vmr *This = impl_from_IBasicVideo(iface);
1026
1027 TRACE("(%p/%p)->()\n", This, iface);
1028
1029 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1030 }
1031
1032 static const IBasicVideoVtbl IBasicVideo_VTable =
1033 {
1034 Basicvideo_QueryInterface,
1035 Basicvideo_AddRef,
1036 Basicvideo_Release,
1037 BaseControlVideoImpl_GetTypeInfoCount,
1038 BaseControlVideoImpl_GetTypeInfo,
1039 BaseControlVideoImpl_GetIDsOfNames,
1040 BaseControlVideoImpl_Invoke,
1041 BaseControlVideoImpl_get_AvgTimePerFrame,
1042 BaseControlVideoImpl_get_BitRate,
1043 BaseControlVideoImpl_get_BitErrorRate,
1044 BaseControlVideoImpl_get_VideoWidth,
1045 BaseControlVideoImpl_get_VideoHeight,
1046 BaseControlVideoImpl_put_SourceLeft,
1047 BaseControlVideoImpl_get_SourceLeft,
1048 BaseControlVideoImpl_put_SourceWidth,
1049 BaseControlVideoImpl_get_SourceWidth,
1050 BaseControlVideoImpl_put_SourceTop,
1051 BaseControlVideoImpl_get_SourceTop,
1052 BaseControlVideoImpl_put_SourceHeight,
1053 BaseControlVideoImpl_get_SourceHeight,
1054 BaseControlVideoImpl_put_DestinationLeft,
1055 BaseControlVideoImpl_get_DestinationLeft,
1056 BaseControlVideoImpl_put_DestinationWidth,
1057 BaseControlVideoImpl_get_DestinationWidth,
1058 BaseControlVideoImpl_put_DestinationTop,
1059 BaseControlVideoImpl_get_DestinationTop,
1060 BaseControlVideoImpl_put_DestinationHeight,
1061 BaseControlVideoImpl_get_DestinationHeight,
1062 BaseControlVideoImpl_SetSourcePosition,
1063 BaseControlVideoImpl_GetSourcePosition,
1064 BaseControlVideoImpl_SetDefaultSourcePosition,
1065 BaseControlVideoImpl_SetDestinationPosition,
1066 BaseControlVideoImpl_GetDestinationPosition,
1067 BaseControlVideoImpl_SetDefaultDestinationPosition,
1068 BaseControlVideoImpl_GetVideoSize,
1069 BaseControlVideoImpl_GetVideoPaletteEntries,
1070 BaseControlVideoImpl_GetCurrentImage,
1071 BaseControlVideoImpl_IsUsingDefaultSource,
1072 BaseControlVideoImpl_IsUsingDefaultDestination
1073 };
1074
1075 static HRESULT WINAPI AMCertifiedOutputProtection_QueryInterface(IAMCertifiedOutputProtection *iface,
1076 REFIID riid, void **ppv)
1077 {
1078 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
1079 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1080 }
1081
1082 static ULONG WINAPI AMCertifiedOutputProtection_AddRef(IAMCertifiedOutputProtection *iface)
1083 {
1084 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
1085 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1086 }
1087
1088 static ULONG WINAPI AMCertifiedOutputProtection_Release(IAMCertifiedOutputProtection *iface)
1089 {
1090 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
1091 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1092 }
1093
1094 static HRESULT WINAPI AMCertifiedOutputProtection_KeyExchange(IAMCertifiedOutputProtection *iface,
1095 GUID* pRandom, BYTE** VarLenCertGH,
1096 DWORD* pdwLengthCertGH)
1097 {
1098 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
1099
1100 FIXME("(%p/%p)->(%p, %p, %p) stub\n", iface, This, pRandom, VarLenCertGH, pdwLengthCertGH);
1101 return VFW_E_NO_COPP_HW;
1102 }
1103
1104 static HRESULT WINAPI AMCertifiedOutputProtection_SessionSequenceStart(IAMCertifiedOutputProtection *iface,
1105 AMCOPPSignature* pSig)
1106 {
1107 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
1108
1109 FIXME("(%p/%p)->(%p) stub\n", iface, This, pSig);
1110 return VFW_E_NO_COPP_HW;
1111 }
1112
1113 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionCommand(IAMCertifiedOutputProtection *iface,
1114 const AMCOPPCommand* cmd)
1115 {
1116 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
1117
1118 FIXME("(%p/%p)->(%p) stub\n", iface, This, cmd);
1119 return VFW_E_NO_COPP_HW;
1120 }
1121
1122 static HRESULT WINAPI AMCertifiedOutputProtection_ProtectionStatus(IAMCertifiedOutputProtection *iface,
1123 const AMCOPPStatusInput* pStatusInput,
1124 AMCOPPStatusOutput* pStatusOutput)
1125 {
1126 struct quartz_vmr *This = impl_from_IAMCertifiedOutputProtection(iface);
1127
1128 FIXME("(%p/%p)->(%p, %p) stub\n", iface, This, pStatusInput, pStatusOutput);
1129 return VFW_E_NO_COPP_HW;
1130 }
1131
1132 static const IAMCertifiedOutputProtectionVtbl IAMCertifiedOutputProtection_Vtbl =
1133 {
1134 AMCertifiedOutputProtection_QueryInterface,
1135 AMCertifiedOutputProtection_AddRef,
1136 AMCertifiedOutputProtection_Release,
1137 AMCertifiedOutputProtection_KeyExchange,
1138 AMCertifiedOutputProtection_SessionSequenceStart,
1139 AMCertifiedOutputProtection_ProtectionCommand,
1140 AMCertifiedOutputProtection_ProtectionStatus
1141 };
1142
1143 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
1144 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
1145 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1146 }
1147
1148 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
1149 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
1150 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1151 }
1152
1153 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
1154 struct quartz_vmr *This = impl_from_IAMFilterMiscFlags(iface);
1155 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1156 }
1157
1158 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
1159 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
1160 }
1161
1162 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
1163 AMFilterMiscFlags_QueryInterface,
1164 AMFilterMiscFlags_AddRef,
1165 AMFilterMiscFlags_Release,
1166 AMFilterMiscFlags_GetMiscFlags
1167 };
1168
1169 static HRESULT WINAPI VMR7FilterConfig_QueryInterface(IVMRFilterConfig *iface, REFIID riid,
1170 void** ppv)
1171 {
1172 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1173 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1174 }
1175
1176 static ULONG WINAPI VMR7FilterConfig_AddRef(IVMRFilterConfig *iface)
1177 {
1178 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1179 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1180 }
1181
1182 static ULONG WINAPI VMR7FilterConfig_Release(IVMRFilterConfig *iface)
1183 {
1184 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1185 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1186 }
1187
1188 static HRESULT WINAPI VMR7FilterConfig_SetImageCompositor(IVMRFilterConfig *iface,
1189 IVMRImageCompositor *compositor)
1190 {
1191 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1192
1193 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
1194 return E_NOTIMPL;
1195 }
1196
1197 static HRESULT WINAPI VMR7FilterConfig_SetNumberOfStreams(IVMRFilterConfig *iface, DWORD max)
1198 {
1199 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1200
1201 FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
1202 return E_NOTIMPL;
1203 }
1204
1205 static HRESULT WINAPI VMR7FilterConfig_GetNumberOfStreams(IVMRFilterConfig *iface, DWORD *max)
1206 {
1207 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1208
1209 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
1210 return E_NOTIMPL;
1211 }
1212
1213 static HRESULT WINAPI VMR7FilterConfig_SetRenderingPrefs(IVMRFilterConfig *iface, DWORD renderflags)
1214 {
1215 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1216
1217 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
1218 return E_NOTIMPL;
1219 }
1220
1221 static HRESULT WINAPI VMR7FilterConfig_GetRenderingPrefs(IVMRFilterConfig *iface, DWORD *renderflags)
1222 {
1223 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1224
1225 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
1226 return E_NOTIMPL;
1227 }
1228
1229 static HRESULT WINAPI VMR7FilterConfig_SetRenderingMode(IVMRFilterConfig *iface, DWORD mode)
1230 {
1231 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1232
1233 FIXME("(%p/%p)->(%u) stub\n", iface, This, mode);
1234 return E_NOTIMPL;
1235 }
1236
1237 static HRESULT WINAPI VMR7FilterConfig_GetRenderingMode(IVMRFilterConfig *iface, DWORD *mode)
1238 {
1239 struct quartz_vmr *This = impl_from_IVMRFilterConfig(iface);
1240
1241 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
1242 if (!mode) return E_POINTER;
1243
1244 if (This->mode)
1245 *mode = This->mode;
1246 else
1247 *mode = VMRMode_Windowed;
1248
1249 return S_OK;
1250 }
1251
1252 static const IVMRFilterConfigVtbl VMR7_FilterConfig_Vtbl =
1253 {
1254 VMR7FilterConfig_QueryInterface,
1255 VMR7FilterConfig_AddRef,
1256 VMR7FilterConfig_Release,
1257 VMR7FilterConfig_SetImageCompositor,
1258 VMR7FilterConfig_SetNumberOfStreams,
1259 VMR7FilterConfig_GetNumberOfStreams,
1260 VMR7FilterConfig_SetRenderingPrefs,
1261 VMR7FilterConfig_GetRenderingPrefs,
1262 VMR7FilterConfig_SetRenderingMode,
1263 VMR7FilterConfig_GetRenderingMode
1264 };
1265
1266 struct get_available_monitors_args
1267 {
1268 VMRMONITORINFO *info7;
1269 VMR9MonitorInfo *info9;
1270 DWORD arraysize;
1271 DWORD numdev;
1272 };
1273
1274 static BOOL CALLBACK get_available_monitors_proc(HMONITOR hmon, HDC hdc, LPRECT lprc, LPARAM lparam)
1275 {
1276 struct get_available_monitors_args *args = (struct get_available_monitors_args *)lparam;
1277 MONITORINFOEXW mi;
1278
1279 if (args->info7 || args->info9)
1280 {
1281
1282 if (!args->arraysize)
1283 return FALSE;
1284
1285 mi.cbSize = sizeof(mi);
1286 if (!GetMonitorInfoW(hmon, (MONITORINFO*)&mi))
1287 return TRUE;
1288
1289 /* fill VMRMONITORINFO struct */
1290 if (args->info7)
1291 {
1292 VMRMONITORINFO *info = args->info7++;
1293 memset(info, 0, sizeof(*info));
1294
1295 if (args->numdev > 0)
1296 {
1297 info->guid.pGUID = &info->guid.GUID;
1298 info->guid.GUID.Data4[7] = args->numdev;
1299 }
1300 else
1301 info->guid.pGUID = NULL;
1302
1303 info->rcMonitor = mi.rcMonitor;
1304 info->hMon = hmon;
1305 info->dwFlags = mi.dwFlags;
1306
1307 lstrcpynW(info->szDevice, mi.szDevice, sizeof(info->szDevice)/sizeof(WCHAR));
1308
1309 /* FIXME: how to get these values? */
1310 info->szDescription[0] = 0;
1311 }
1312
1313 /* fill VMR9MonitorInfo struct */
1314 if (args->info9)
1315 {
1316 VMR9MonitorInfo *info = args->info9++;
1317 memset(info, 0, sizeof(*info));
1318
1319 info->uDevID = 0; /* FIXME */
1320 info->rcMonitor = mi.rcMonitor;
1321 info->hMon = hmon;
1322 info->dwFlags = mi.dwFlags;
1323
1324 lstrcpynW(info->szDevice, mi.szDevice, sizeof(info->szDevice)/sizeof(WCHAR));
1325
1326 /* FIXME: how to get these values? */
1327 info->szDescription[0] = 0;
1328 info->dwVendorId = 0;
1329 info->dwDeviceId = 0;
1330 info->dwSubSysId = 0;
1331 info->dwRevision = 0;
1332 }
1333
1334 args->arraysize--;
1335 }
1336
1337 args->numdev++;
1338 return TRUE;
1339 }
1340
1341 static HRESULT WINAPI VMR7MonitorConfig_QueryInterface(IVMRMonitorConfig *iface, REFIID riid,
1342 LPVOID * ppv)
1343 {
1344 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1345 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1346 }
1347
1348 static ULONG WINAPI VMR7MonitorConfig_AddRef(IVMRMonitorConfig *iface)
1349 {
1350 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1351 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1352 }
1353
1354 static ULONG WINAPI VMR7MonitorConfig_Release(IVMRMonitorConfig *iface)
1355 {
1356 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1357 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1358 }
1359
1360 static HRESULT WINAPI VMR7MonitorConfig_SetMonitor(IVMRMonitorConfig *iface, const VMRGUID *pGUID)
1361 {
1362 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1363
1364 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1365
1366 if (!pGUID)
1367 return E_POINTER;
1368
1369 return S_OK;
1370 }
1371
1372 static HRESULT WINAPI VMR7MonitorConfig_GetMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1373 {
1374 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1375
1376 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1377
1378 if (!pGUID)
1379 return E_POINTER;
1380
1381 pGUID->pGUID = NULL; /* default DirectDraw device */
1382 return S_OK;
1383 }
1384
1385 static HRESULT WINAPI VMR7MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig *iface,
1386 const VMRGUID *pGUID)
1387 {
1388 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1389
1390 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1391
1392 if (!pGUID)
1393 return E_POINTER;
1394
1395 return S_OK;
1396 }
1397
1398 static HRESULT WINAPI VMR7MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig *iface, VMRGUID *pGUID)
1399 {
1400 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1401
1402 FIXME("(%p/%p)->(%p) stub\n", iface, This, pGUID);
1403
1404 if (!pGUID)
1405 return E_POINTER;
1406
1407 pGUID->pGUID = NULL; /* default DirectDraw device */
1408 return S_OK;
1409 }
1410
1411 static HRESULT WINAPI VMR7MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig *iface,
1412 VMRMONITORINFO *info, DWORD arraysize,
1413 DWORD *numdev)
1414 {
1415 struct quartz_vmr *This = impl_from_IVMRMonitorConfig(iface);
1416 struct get_available_monitors_args args;
1417
1418 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1419
1420 if (!numdev)
1421 return E_POINTER;
1422
1423 if (info && arraysize == 0)
1424 return E_INVALIDARG;
1425
1426 args.info7 = info;
1427 args.info9 = NULL;
1428 args.arraysize = arraysize;
1429 args.numdev = 0;
1430 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1431
1432 *numdev = args.numdev;
1433 return S_OK;
1434 }
1435
1436 static const IVMRMonitorConfigVtbl VMR7_MonitorConfig_Vtbl =
1437 {
1438 VMR7MonitorConfig_QueryInterface,
1439 VMR7MonitorConfig_AddRef,
1440 VMR7MonitorConfig_Release,
1441 VMR7MonitorConfig_SetMonitor,
1442 VMR7MonitorConfig_GetMonitor,
1443 VMR7MonitorConfig_SetDefaultMonitor,
1444 VMR7MonitorConfig_GetDefaultMonitor,
1445 VMR7MonitorConfig_GetAvailableMonitors
1446 };
1447
1448 static HRESULT WINAPI VMR9MonitorConfig_QueryInterface(IVMRMonitorConfig9 *iface, REFIID riid,
1449 LPVOID * ppv)
1450 {
1451 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1452 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1453 }
1454
1455 static ULONG WINAPI VMR9MonitorConfig_AddRef(IVMRMonitorConfig9 *iface)
1456 {
1457 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1458 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1459 }
1460
1461 static ULONG WINAPI VMR9MonitorConfig_Release(IVMRMonitorConfig9 *iface)
1462 {
1463 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1464 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1465 }
1466
1467 static HRESULT WINAPI VMR9MonitorConfig_SetMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1468 {
1469 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1470
1471 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1472
1473 return S_OK;
1474 }
1475
1476 static HRESULT WINAPI VMR9MonitorConfig_GetMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1477 {
1478 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1479
1480 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1481
1482 if (!uDev)
1483 return E_POINTER;
1484
1485 *uDev = 0;
1486 return S_OK;
1487 }
1488
1489 static HRESULT WINAPI VMR9MonitorConfig_SetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT uDev)
1490 {
1491 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1492
1493 FIXME("(%p/%p)->(%u) stub\n", iface, This, uDev);
1494
1495 return S_OK;
1496 }
1497
1498 static HRESULT WINAPI VMR9MonitorConfig_GetDefaultMonitor(IVMRMonitorConfig9 *iface, UINT *uDev)
1499 {
1500 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1501
1502 FIXME("(%p/%p)->(%p) stub\n", iface, This, uDev);
1503
1504 if (!uDev)
1505 return E_POINTER;
1506
1507 *uDev = 0;
1508 return S_OK;
1509 }
1510
1511 static HRESULT WINAPI VMR9MonitorConfig_GetAvailableMonitors(IVMRMonitorConfig9 *iface,
1512 VMR9MonitorInfo *info, DWORD arraysize,
1513 DWORD *numdev)
1514 {
1515 struct quartz_vmr *This = impl_from_IVMRMonitorConfig9(iface);
1516 struct get_available_monitors_args args;
1517
1518 FIXME("(%p/%p)->(%p, %u, %p) semi-stub\n", iface, This, info, arraysize, numdev);
1519
1520 if (!numdev)
1521 return E_POINTER;
1522
1523 if (info && arraysize == 0)
1524 return E_INVALIDARG;
1525
1526 args.info7 = NULL;
1527 args.info9 = info;
1528 args.arraysize = arraysize;
1529 args.numdev = 0;
1530 EnumDisplayMonitors(NULL, NULL, get_available_monitors_proc, (LPARAM)&args);
1531
1532 *numdev = args.numdev;
1533 return S_OK;
1534 }
1535
1536 static const IVMRMonitorConfig9Vtbl VMR9_MonitorConfig_Vtbl =
1537 {
1538 VMR9MonitorConfig_QueryInterface,
1539 VMR9MonitorConfig_AddRef,
1540 VMR9MonitorConfig_Release,
1541 VMR9MonitorConfig_SetMonitor,
1542 VMR9MonitorConfig_GetMonitor,
1543 VMR9MonitorConfig_SetDefaultMonitor,
1544 VMR9MonitorConfig_GetDefaultMonitor,
1545 VMR9MonitorConfig_GetAvailableMonitors
1546 };
1547
1548 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
1549 {
1550 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1551 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1552 }
1553
1554 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
1555 {
1556 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1557 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1558 }
1559
1560 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
1561 {
1562 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1563 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1564 }
1565
1566 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
1567 {
1568 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1569
1570 FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
1571 return E_NOTIMPL;
1572 }
1573
1574 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD max)
1575 {
1576 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1577
1578 FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
1579 return E_NOTIMPL;
1580 }
1581
1582 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *max)
1583 {
1584 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1585
1586 FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
1587 return E_NOTIMPL;
1588 }
1589
1590 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
1591 {
1592 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1593
1594 FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
1595 return E_NOTIMPL;
1596 }
1597
1598 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
1599 {
1600 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1601
1602 FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
1603 return E_NOTIMPL;
1604 }
1605
1606 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
1607 {
1608 HRESULT hr = S_OK;
1609 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1610
1611 TRACE("(%p/%p)->(%u)\n", iface, This, mode);
1612
1613 EnterCriticalSection(&This->renderer.filter.csFilter);
1614 if (This->mode)
1615 {
1616 LeaveCriticalSection(&This->renderer.filter.csFilter);
1617 return VFW_E_WRONG_STATE;
1618 }
1619
1620 if (This->allocator)
1621 IVMRSurfaceAllocatorEx9_Release(This->allocator);
1622 if (This->presenter)
1623 IVMRImagePresenter9_Release(This->presenter);
1624
1625 This->allocator = NULL;
1626 This->presenter = NULL;
1627
1628 switch (mode)
1629 {
1630 case VMR9Mode_Windowed:
1631 case VMR9Mode_Windowless:
1632 This->allocator_is_ex = 0;
1633 This->cookie = ~0;
1634
1635 hr = VMR9DefaultAllocatorPresenterImpl_create(This, (LPVOID*)&This->presenter);
1636 if (SUCCEEDED(hr))
1637 hr = IVMRImagePresenter9_QueryInterface(This->presenter, &IID_IVMRSurfaceAllocatorEx9, (LPVOID*)&This->allocator);
1638 if (FAILED(hr))
1639 {
1640 ERR("Unable to find Presenter interface\n");
1641 IVMRImagePresenter9_Release(This->presenter);
1642 This->allocator = NULL;
1643 This->presenter = NULL;
1644 }
1645 else
1646 hr = IVMRSurfaceAllocatorEx9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
1647 break;
1648 case VMR9Mode_Renderless:
1649 break;
1650 default:
1651 LeaveCriticalSection(&This->renderer.filter.csFilter);
1652 return E_INVALIDARG;
1653 }
1654
1655 This->mode = mode;
1656 LeaveCriticalSection(&This->renderer.filter.csFilter);
1657 return hr;
1658 }
1659
1660 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
1661 {
1662 struct quartz_vmr *This = impl_from_IVMRFilterConfig9(iface);
1663
1664 TRACE("(%p/%p)->(%p)\n", iface, This, mode);
1665 if (!mode)
1666 return E_POINTER;
1667
1668 if (This->mode)
1669 *mode = This->mode;
1670 else
1671 *mode = VMR9Mode_Windowed;
1672
1673 return S_OK;
1674 }
1675
1676 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
1677 {
1678 VMR9FilterConfig_QueryInterface,
1679 VMR9FilterConfig_AddRef,
1680 VMR9FilterConfig_Release,
1681 VMR9FilterConfig_SetImageCompositor,
1682 VMR9FilterConfig_SetNumberOfStreams,
1683 VMR9FilterConfig_GetNumberOfStreams,
1684 VMR9FilterConfig_SetRenderingPrefs,
1685 VMR9FilterConfig_GetRenderingPrefs,
1686 VMR9FilterConfig_SetRenderingMode,
1687 VMR9FilterConfig_GetRenderingMode
1688 };
1689
1690 static HRESULT WINAPI VMR7WindowlessControl_QueryInterface(IVMRWindowlessControl *iface, REFIID riid,
1691 LPVOID * ppv)
1692 {
1693 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1694 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1695 }
1696
1697 static ULONG WINAPI VMR7WindowlessControl_AddRef(IVMRWindowlessControl *iface)
1698 {
1699 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1700 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1701 }
1702
1703 static ULONG WINAPI VMR7WindowlessControl_Release(IVMRWindowlessControl *iface)
1704 {
1705 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1706 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1707 }
1708
1709 static HRESULT WINAPI VMR7WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl *iface,
1710 LONG *width, LONG *height,
1711 LONG *arwidth, LONG *arheight)
1712 {
1713 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1714 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
1715
1716 if (!width || !height || !arwidth || !arheight)
1717 {
1718 ERR("Got no pointer\n");
1719 return E_POINTER;
1720 }
1721
1722 *width = This->bmiheader.biWidth;
1723 *height = This->bmiheader.biHeight;
1724 *arwidth = This->bmiheader.biWidth;
1725 *arheight = This->bmiheader.biHeight;
1726
1727 return S_OK;
1728 }
1729
1730 static HRESULT WINAPI VMR7WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl *iface,
1731 LONG *width, LONG *height)
1732 {
1733 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1734
1735 FIXME("(%p/%p)->(...) stub\n", iface, This);
1736 return E_NOTIMPL;
1737 }
1738
1739 static HRESULT WINAPI VMR7WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl *iface,
1740 LONG *width, LONG *height)
1741 {
1742 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1743
1744 FIXME("(%p/%p)->(...) stub\n", iface, This);
1745 return E_NOTIMPL;
1746 }
1747
1748 static HRESULT WINAPI VMR7WindowlessControl_SetVideoPosition(IVMRWindowlessControl *iface,
1749 const RECT *source, const RECT *dest)
1750 {
1751 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1752
1753 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1754
1755 EnterCriticalSection(&This->renderer.filter.csFilter);
1756
1757 if (source)
1758 This->source_rect = *source;
1759 if (dest)
1760 {
1761 This->target_rect = *dest;
1762 if (This->baseControlWindow.baseWindow.hWnd)
1763 {
1764 FIXME("Output rectangle: %s\n", wine_dbgstr_rect(dest));
1765 SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
1766 dest->left, dest->top, dest->right - dest->left, dest->bottom-dest->top,
1767 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
1768 }
1769 }
1770
1771 LeaveCriticalSection(&This->renderer.filter.csFilter);
1772
1773 return S_OK;
1774 }
1775
1776 static HRESULT WINAPI VMR7WindowlessControl_GetVideoPosition(IVMRWindowlessControl *iface,
1777 RECT *source, RECT *dest)
1778 {
1779 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1780
1781 if (source)
1782 *source = This->source_rect;
1783
1784 if (dest)
1785 *dest = This->target_rect;
1786
1787 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1788 return S_OK;
1789 }
1790
1791 static HRESULT WINAPI VMR7WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl *iface,
1792 DWORD *mode)
1793 {
1794 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1795
1796 FIXME("(%p/%p)->(...) stub\n", iface, This);
1797 return E_NOTIMPL;
1798 }
1799
1800 static HRESULT WINAPI VMR7WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl *iface,
1801 DWORD mode)
1802 {
1803 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1804
1805 FIXME("(%p/%p)->(...) stub\n", iface, This);
1806 return E_NOTIMPL;
1807 }
1808
1809 static HRESULT WINAPI VMR7WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl *iface,
1810 HWND hwnd)
1811 {
1812 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1813
1814 FIXME("(%p/%p)->(...) stub\n", iface, This);
1815 return E_NOTIMPL;
1816 }
1817
1818 static HRESULT WINAPI VMR7WindowlessControl_RepaintVideo(IVMRWindowlessControl *iface,
1819 HWND hwnd, HDC hdc)
1820 {
1821 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1822
1823 FIXME("(%p/%p)->(...) stub\n", iface, This);
1824 return E_NOTIMPL;
1825 }
1826
1827 static HRESULT WINAPI VMR7WindowlessControl_DisplayModeChanged(IVMRWindowlessControl *iface)
1828 {
1829 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1830
1831 FIXME("(%p/%p)->(...) stub\n", iface, This);
1832 return E_NOTIMPL;
1833 }
1834
1835 static HRESULT WINAPI VMR7WindowlessControl_GetCurrentImage(IVMRWindowlessControl *iface,
1836 BYTE **dib)
1837 {
1838 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1839
1840 FIXME("(%p/%p)->(...) stub\n", iface, This);
1841 return E_NOTIMPL;
1842 }
1843
1844 static HRESULT WINAPI VMR7WindowlessControl_SetBorderColor(IVMRWindowlessControl *iface,
1845 COLORREF color)
1846 {
1847 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1848
1849 FIXME("(%p/%p)->(...) stub\n", iface, This);
1850 return E_NOTIMPL;
1851 }
1852
1853 static HRESULT WINAPI VMR7WindowlessControl_GetBorderColor(IVMRWindowlessControl *iface,
1854 COLORREF *color)
1855 {
1856 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1857
1858 FIXME("(%p/%p)->(...) stub\n", iface, This);
1859 return E_NOTIMPL;
1860 }
1861
1862 static HRESULT WINAPI VMR7WindowlessControl_SetColorKey(IVMRWindowlessControl *iface, COLORREF color)
1863 {
1864 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1865
1866 FIXME("(%p/%p)->(...) stub\n", iface, This);
1867 return E_NOTIMPL;
1868 }
1869
1870 static HRESULT WINAPI VMR7WindowlessControl_GetColorKey(IVMRWindowlessControl *iface, COLORREF *color)
1871 {
1872 struct quartz_vmr *This = impl_from_IVMRWindowlessControl(iface);
1873
1874 FIXME("(%p/%p)->(...) stub\n", iface, This);
1875 return E_NOTIMPL;
1876 }
1877
1878 static const IVMRWindowlessControlVtbl VMR7_WindowlessControl_Vtbl =
1879 {
1880 VMR7WindowlessControl_QueryInterface,
1881 VMR7WindowlessControl_AddRef,
1882 VMR7WindowlessControl_Release,
1883 VMR7WindowlessControl_GetNativeVideoSize,
1884 VMR7WindowlessControl_GetMinIdealVideoSize,
1885 VMR7WindowlessControl_GetMaxIdealVideoSize,
1886 VMR7WindowlessControl_SetVideoPosition,
1887 VMR7WindowlessControl_GetVideoPosition,
1888 VMR7WindowlessControl_GetAspectRatioMode,
1889 VMR7WindowlessControl_SetAspectRatioMode,
1890 VMR7WindowlessControl_SetVideoClippingWindow,
1891 VMR7WindowlessControl_RepaintVideo,
1892 VMR7WindowlessControl_DisplayModeChanged,
1893 VMR7WindowlessControl_GetCurrentImage,
1894 VMR7WindowlessControl_SetBorderColor,
1895 VMR7WindowlessControl_GetBorderColor,
1896 VMR7WindowlessControl_SetColorKey,
1897 VMR7WindowlessControl_GetColorKey
1898 };
1899
1900 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
1901 {
1902 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1903 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1904 }
1905
1906 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
1907 {
1908 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1909 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1910 }
1911
1912 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
1913 {
1914 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1915 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1916 }
1917
1918 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height, LONG *arwidth, LONG *arheight)
1919 {
1920 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1921 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
1922
1923 if (!width || !height || !arwidth || !arheight)
1924 {
1925 ERR("Got no pointer\n");
1926 return E_POINTER;
1927 }
1928
1929 *width = This->bmiheader.biWidth;
1930 *height = This->bmiheader.biHeight;
1931 *arwidth = This->bmiheader.biWidth;
1932 *arheight = This->bmiheader.biHeight;
1933
1934 return S_OK;
1935 }
1936
1937 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1938 {
1939 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1940
1941 FIXME("(%p/%p)->(...) stub\n", iface, This);
1942 return E_NOTIMPL;
1943 }
1944
1945 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1946 {
1947 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1948
1949 FIXME("(%p/%p)->(...) stub\n", iface, This);
1950 return E_NOTIMPL;
1951 }
1952
1953 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface, const RECT *source, const RECT *dest)
1954 {
1955 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1956
1957 TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1958
1959 EnterCriticalSection(&This->renderer.filter.csFilter);
1960
1961 if (source)
1962 This->source_rect = *source;
1963 if (dest)
1964 {
1965 This->target_rect = *dest;
1966 if (This->baseControlWindow.baseWindow.hWnd)
1967 {
1968 FIXME("Output rectangle: %s\n", wine_dbgstr_rect(dest));
1969 SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left,
1970 dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
1971 }
1972 }
1973
1974 LeaveCriticalSection(&This->renderer.filter.csFilter);
1975
1976 return S_OK;
1977 }
1978
1979 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *source, RECT *dest)
1980 {
1981 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1982
1983 if (source)
1984 *source = This->source_rect;
1985
1986 if (dest)
1987 *dest = This->target_rect;
1988
1989 FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1990 return S_OK;
1991 }
1992
1993 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1994 {
1995 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
1996
1997 FIXME("(%p/%p)->(...) stub\n", iface, This);
1998 return E_NOTIMPL;
1999 }
2000
2001 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
2002 {
2003 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
2004
2005 FIXME("(%p/%p)->(...) stub\n", iface, This);
2006 return E_NOTIMPL;
2007 }
2008
2009 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND hwnd)
2010 {
2011 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
2012
2013 TRACE("(%p/%p)->(%p)\n", iface, This, hwnd);
2014
2015 EnterCriticalSection(&This->renderer.filter.csFilter);
2016 This->hWndClippingWindow = hwnd;
2017 VMR9_maybe_init(This, FALSE);
2018 if (!hwnd)
2019 IVMRSurfaceAllocatorEx9_TerminateDevice(This->allocator, This->cookie);
2020 LeaveCriticalSection(&This->renderer.filter.csFilter);
2021 return S_OK;
2022 }
2023
2024 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
2025 {
2026 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
2027 HRESULT hr;
2028
2029 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
2030
2031 EnterCriticalSection(&This->renderer.filter.csFilter);
2032 if (hwnd != This->hWndClippingWindow && hwnd != This->baseControlWindow.baseWindow.hWnd)
2033 {
2034 ERR("Not handling changing windows yet!!!\n");
2035 LeaveCriticalSection(&This->renderer.filter.csFilter);
2036 return S_OK;
2037 }
2038
2039 if (!This->allocator_d3d9_dev)
2040 {
2041 ERR("No d3d9 device!\n");
2042 LeaveCriticalSection(&This->renderer.filter.csFilter);
2043 return VFW_E_WRONG_STATE;
2044 }
2045
2046 /* Windowless extension */
2047 hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, This->baseControlWindow.baseWindow.hWnd, NULL);
2048 LeaveCriticalSection(&This->renderer.filter.csFilter);
2049
2050 return hr;
2051 }
2052
2053 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
2054 {
2055 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
2056
2057 FIXME("(%p/%p)->(...) stub\n", iface, This);
2058 return E_NOTIMPL;
2059 }
2060
2061 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
2062 {
2063 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
2064
2065 FIXME("(%p/%p)->(...) stub\n", iface, This);
2066 return E_NOTIMPL;
2067 }
2068
2069 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
2070 {
2071 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
2072
2073 FIXME("(%p/%p)->(...) stub\n", iface, This);
2074 return E_NOTIMPL;
2075 }
2076
2077 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
2078 {
2079 struct quartz_vmr *This = impl_from_IVMRWindowlessControl9(iface);
2080
2081 FIXME("(%p/%p)->(...) stub\n", iface, This);
2082 return E_NOTIMPL;
2083 }
2084
2085 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
2086 {
2087 VMR9WindowlessControl_QueryInterface,
2088 VMR9WindowlessControl_AddRef,
2089 VMR9WindowlessControl_Release,
2090 VMR9WindowlessControl_GetNativeVideoSize,
2091 VMR9WindowlessControl_GetMinIdealVideoSize,
2092 VMR9WindowlessControl_GetMaxIdealVideoSize,
2093 VMR9WindowlessControl_SetVideoPosition,
2094 VMR9WindowlessControl_GetVideoPosition,
2095 VMR9WindowlessControl_GetAspectRatioMode,
2096 VMR9WindowlessControl_SetAspectRatioMode,
2097 VMR9WindowlessControl_SetVideoClippingWindow,
2098 VMR9WindowlessControl_RepaintVideo,
2099 VMR9WindowlessControl_DisplayModeChanged,
2100 VMR9WindowlessControl_GetCurrentImage,
2101 VMR9WindowlessControl_SetBorderColor,
2102 VMR9WindowlessControl_GetBorderColor
2103 };
2104
2105 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify *iface,
2106 REFIID riid, LPVOID * ppv)
2107 {
2108 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
2109 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
2110 }
2111
2112 static ULONG WINAPI VMR7SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify *iface)
2113 {
2114 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
2115 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
2116 }
2117
2118 static ULONG WINAPI VMR7SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify *iface)
2119 {
2120 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
2121 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
2122 }
2123
2124 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify *iface,
2125 DWORD_PTR id,
2126 IVMRSurfaceAllocator *alloc)
2127 {
2128 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
2129
2130 FIXME("(%p/%p)->(...) stub\n", iface, This);
2131 return E_NOTIMPL;
2132 }
2133
2134 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
2135 IDirectDraw7 *device, HMONITOR monitor)
2136 {
2137 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
2138
2139 FIXME("(%p/%p)->(...) stub\n", iface, This);
2140 return E_NOTIMPL;
2141 }
2142
2143 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_ChangeDDrawDevice(IVMRSurfaceAllocatorNotify *iface,
2144 IDirectDraw7 *device, HMONITOR monitor)
2145 {
2146 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
2147
2148 FIXME("(%p/%p)->(...) stub\n", iface, This);
2149 return E_NOTIMPL;
2150 }
2151
2152 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces(IVMRSurfaceAllocatorNotify *iface)
2153 {
2154 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
2155
2156 FIXME("(%p/%p)->(...) stub\n", iface, This);
2157 return E_NOTIMPL;
2158 }
2159
2160 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify *iface, LONG code,
2161 LONG_PTR param1, LONG_PTR param2)
2162 {
2163 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
2164
2165 FIXME("(%p/%p)->(...) stub\n", iface, This);
2166 return E_NOTIMPL;
2167 }
2168
2169 static HRESULT WINAPI VMR7SurfaceAllocatorNotify_SetBorderColor(IVMRSurfaceAllocatorNotify *iface,
2170 COLORREF clrBorder)
2171 {
2172 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify(iface);
2173
2174 FIXME("(%p/%p)->(...) stub\n", iface, This);
2175 return E_NOTIMPL;
2176 }
2177
2178 static const IVMRSurfaceAllocatorNotifyVtbl VMR7_SurfaceAllocatorNotify_Vtbl =
2179 {
2180 VMR7SurfaceAllocatorNotify_QueryInterface,
2181 VMR7SurfaceAllocatorNotify_AddRef,
2182 VMR7SurfaceAllocatorNotify_Release,
2183 VMR7SurfaceAllocatorNotify_AdviseSurfaceAllocator,
2184 VMR7SurfaceAllocatorNotify_SetDDrawDevice,
2185 VMR7SurfaceAllocatorNotify_ChangeDDrawDevice,
2186 VMR7SurfaceAllocatorNotify_RestoreDDrawSurfaces,
2187 VMR7SurfaceAllocatorNotify_NotifyEvent,
2188 VMR7SurfaceAllocatorNotify_SetBorderColor
2189 };
2190
2191 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
2192 {
2193 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2194 return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
2195 }
2196
2197 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
2198 {
2199 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2200 return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
2201 }
2202
2203 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
2204 {
2205 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2206 return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
2207 }
2208
2209 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR id, IVMRSurfaceAllocator9 *alloc)
2210 {
2211 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2212
2213 /* FIXME: This code is not tested!!! */
2214 FIXME("(%p/%p)->(...) stub\n", iface, This);
2215 This->cookie = id;
2216
2217 if (This->presenter)
2218 return VFW_E_WRONG_STATE;
2219
2220 if (FAILED(IVMRSurfaceAllocator9_QueryInterface(alloc, &IID_IVMRImagePresenter9, (void **)&This->presenter)))
2221 return E_NOINTERFACE;
2222
2223 if (SUCCEEDED(IVMRSurfaceAllocator9_QueryInterface(alloc, &IID_IVMRSurfaceAllocatorEx9, (void **)&This->allocator)))
2224 This->allocator_is_ex = 1;
2225 else
2226 {
2227 This->allocator = (IVMRSurfaceAllocatorEx9 *)alloc;
2228 IVMRSurfaceAllocator9_AddRef(alloc);
2229 This->allocator_is_ex = 0;
2230 }
2231
2232 return S_OK;
2233 }
2234
2235 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
2236 {
2237 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2238
2239 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
2240 if (This->allocator_d3d9_dev)
2241 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
2242 This->allocator_d3d9_dev = device;
2243 IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
2244 This->allocator_mon = monitor;
2245
2246 return S_OK;
2247 }
2248
2249 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
2250 {
2251 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2252
2253 FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
2254 if (This->allocator_d3d9_dev)
2255 IDirect3DDevice9_Release(This->allocator_d3d9_dev);
2256 This->allocator_d3d9_dev = device;
2257 IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
2258 This->allocator_mon = monitor;
2259
2260 return S_OK;
2261 }
2262
2263 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
2264 {
2265 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2266 DWORD i;
2267 HRESULT hr = S_OK;
2268
2269 FIXME("(%p/%p)->(%p, %p => %u, %p) semi-stub\n", iface, This, allocinfo, numbuffers, (numbuffers ? *numbuffers : 0), surface);
2270
2271 if (!allocinfo || !numbuffers || !surface)
2272 return E_POINTER;
2273
2274 if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
2275 {
2276 ERR("Invalid number of buffers?\n");
2277 return E_INVALIDARG;
2278 }
2279
2280 if (!This->allocator_d3d9_dev)
2281 {
2282 ERR("No direct3d device when requested to allocate a surface!\n");
2283 return VFW_E_WRONG_STATE;
2284 }
2285
2286 if (allocinfo->dwFlags & VMR9AllocFlag_OffscreenSurface)
2287 {
2288 ERR("Creating offscreen surface\n");
2289 for (i = 0; i < *numbuffers; ++i)
2290 {
2291 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight,
2292 allocinfo->Format, allocinfo->Pool, &surface[i], NULL);
2293 if (FAILED(hr))
2294 break;
2295 }
2296 }
2297 else if (allocinfo->dwFlags & VMR9AllocFlag_TextureSurface)
2298 {
2299 TRACE("Creating texture surface\n");
2300 for (i = 0; i < *numbuffers; ++i)
2301 {
2302 IDirect3DTexture9 *texture;
2303
2304 hr = IDirect3DDevice9_CreateTexture(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, 1, 0,
2305 allocinfo->Format, allocinfo->Pool, &texture, NULL);
2306 if (FAILED(hr))
2307 break;
2308 IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface[i]);
2309 IDirect3DTexture9_Release(texture);
2310 }
2311 }
2312 else
2313 {
2314 FIXME("Could not allocate for type %08x\n", allocinfo->dwFlags);
2315 return E_NOTIMPL;
2316 }
2317
2318 if (i >= allocinfo->MinBuffers)
2319 {
2320 hr = S_OK;
2321 *numbuffers = i;
2322 }
2323 else
2324 {
2325 for ( ; i > 0; --i) IDirect3DSurface9_Release(surface[i - 1]);
2326 *numbuffers = 0;
2327 }
2328 return hr;
2329 }
2330
2331 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
2332 {
2333 struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
2334
2335 FIXME("(%p/%p)->(...) stub\n", iface, This);
2336 return E_NOTIMPL;
2337 }
2338
2339 static const IVMRSurfaceAllocatorNotify9Vtbl VMR9_SurfaceAllocatorNotify_Vtbl =
2340 {
2341 VMR9SurfaceAllocatorNotify_QueryInterface,
2342 VMR9SurfaceAllocatorNotify_AddRef,
2343 VMR9SurfaceAllocatorNotify_Release,
2344 VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
2345 VMR9SurfaceAllocatorNotify_SetD3DDevice,
2346 VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
2347 VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
2348 VMR9SurfaceAllocatorNotify_NotifyEvent
2349 };
2350
2351 static HRESULT vmr_create(IUnknown *outer_unk, LPVOID *ppv, const CLSID *clsid)
2352 {
2353 HRESULT hr;
2354 struct quartz_vmr* pVMR;
2355
2356 TRACE("(%p, %p)\n", outer_unk, ppv);
2357
2358 *ppv = NULL;
2359
2360 pVMR = CoTaskMemAlloc(sizeof(struct quartz_vmr));
2361
2362 pVMR->hD3d9 = LoadLibraryA("d3d9.dll");
2363 if (!pVMR->hD3d9 )
2364 {
2365 WARN("Could not load d3d9.dll\n");
2366 CoTaskMemFree(pVMR);
2367 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2368 }
2369
2370 pVMR->outer_unk = outer_unk;
2371 pVMR->bUnkOuterValid = FALSE;
2372 pVMR->bAggregatable = FALSE;
2373 pVMR->IUnknown_inner.lpVtbl = &IInner_VTable;
2374 pVMR->IAMCertifiedOutputProtection_iface.lpVtbl = &IAMCertifiedOutputProtection_Vtbl;
2375 pVMR->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
2376
2377 pVMR->mode = 0;
2378 pVMR->allocator_d3d9_dev = NULL;
2379 pVMR->allocator_mon= NULL;
2380 pVMR->num_surfaces = pVMR->cur_surface = 0;
2381 pVMR->allocator = NULL;
2382 pVMR->presenter = NULL;
2383 pVMR->hWndClippingWindow = NULL;
2384 pVMR->IVMRFilterConfig_iface.lpVtbl = &VMR7_FilterConfig_Vtbl;
2385 pVMR->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
2386 pVMR->IVMRMonitorConfig_iface.lpVtbl = &VMR7_MonitorConfig_Vtbl;
2387 pVMR->IVMRMonitorConfig9_iface.lpVtbl = &VMR9_MonitorConfig_Vtbl;
2388 pVMR->IVMRSurfaceAllocatorNotify_iface.lpVtbl = &VMR7_SurfaceAllocatorNotify_Vtbl;
2389 pVMR->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &VMR9_SurfaceAllocatorNotify_Vtbl;
2390 pVMR->IVMRWindowlessControl_iface.lpVtbl = &VMR7_WindowlessControl_Vtbl;
2391 pVMR->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
2392
2393 if (IsEqualGUID(clsid, &CLSID_VideoMixingRenderer))
2394 hr = BaseRenderer_Init(&pVMR->renderer, &VMR_Vtbl, outer_unk, &CLSID_VideoMixingRenderer,
2395 (DWORD_PTR)(__FILE__ ": VMR7Impl.csFilter"), &BaseFuncTable);
2396 else
2397 hr = BaseRenderer_Init(&pVMR->renderer, &VMR_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9,
2398 (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
2399
2400 if (FAILED(hr))
2401 goto fail;
2402
2403 hr = BaseControlWindow_Init(&pVMR->baseControlWindow, &IVideoWindow_VTable, &pVMR->renderer.filter,
2404 &pVMR->renderer.filter.csFilter, &pVMR->renderer.pInputPin->pin,
2405 &renderer_BaseWindowFuncTable);
2406 if (FAILED(hr))
2407 goto fail;
2408
2409 hr = BaseControlVideo_Init(&pVMR->baseControlVideo, &IBasicVideo_VTable, &pVMR->renderer.filter,
2410 &pVMR->renderer.filter.csFilter, &pVMR->renderer.pInputPin->pin,
2411 &renderer_BaseControlVideoFuncTable);
2412 if (FAILED(hr))
2413 goto fail;
2414
2415 *ppv = (LPVOID)pVMR;
2416 ZeroMemory(&pVMR->source_rect, sizeof(RECT));
2417 ZeroMemory(&pVMR->target_rect, sizeof(RECT));
2418 TRACE("Created at %p\n", pVMR);
2419 return hr;
2420
2421 fail:
2422 BaseRendererImpl_Release(&pVMR->renderer.filter.IBaseFilter_iface);
2423 FreeLibrary(pVMR->hD3d9);
2424 CoTaskMemFree(pVMR);
2425 return hr;
2426 }
2427
2428 HRESULT VMR7Impl_create(IUnknown *outer_unk, LPVOID *ppv)
2429 {
2430 return vmr_create(outer_unk, ppv, &CLSID_VideoMixingRenderer);
2431 }
2432
2433 HRESULT VMR9Impl_create(IUnknown *outer_unk, LPVOID *ppv)
2434 {
2435 return vmr_create(outer_unk, ppv, &CLSID_VideoMixingRenderer9);
2436 }
2437
2438
2439 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, LPVOID * ppv)
2440 {
2441 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2442 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
2443
2444 *ppv = NULL;
2445
2446 if (IsEqualIID(riid, &IID_IUnknown))
2447 *ppv = (LPVOID)&(This->IVMRImagePresenter9_iface);
2448 else if (IsEqualIID(riid, &IID_IVMRImagePresenter9))
2449 *ppv = &This->IVMRImagePresenter9_iface;
2450 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorEx9))
2451 *ppv = &This->IVMRSurfaceAllocatorEx9_iface;
2452
2453 if (*ppv)
2454 {
2455 IUnknown_AddRef((IUnknown *)(*ppv));
2456 return S_OK;
2457 }
2458
2459 FIXME("No interface for %s\n", debugstr_guid(riid));
2460
2461 return E_NOINTERFACE;
2462 }
2463
2464 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
2465 {
2466 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2467 ULONG refCount = InterlockedIncrement(&This->refCount);
2468
2469 TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
2470
2471 return refCount;
2472 }
2473
2474 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
2475 {
2476 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2477 ULONG refCount = InterlockedDecrement(&This->refCount);
2478
2479 TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
2480
2481 if (!refCount)
2482 {
2483 DWORD i;
2484 TRACE("Destroying\n");
2485 CloseHandle(This->ack);
2486 IDirect3D9_Release(This->d3d9_ptr);
2487
2488 TRACE("Number of surfaces: %u\n", This->num_surfaces);
2489 for (i = 0; i < This->num_surfaces; ++i)
2490 {
2491 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2492 TRACE("Releasing surface %p\n", surface);
2493 if (surface)
2494 IDirect3DSurface9_Release(surface);
2495 }
2496
2497 CoTaskMemFree(This->d3d9_surfaces);
2498 This->d3d9_surfaces = NULL;
2499 This->num_surfaces = 0;
2500 if (This->d3d9_vertex)
2501 {
2502 IDirect3DVertexBuffer9_Release(This->d3d9_vertex);
2503 This->d3d9_vertex = NULL;
2504 }
2505 CoTaskMemFree(This);
2506 return 0;
2507 }
2508 return refCount;
2509 }
2510
2511 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
2512 {
2513 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2514
2515 TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
2516 return S_OK;
2517 }
2518
2519 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
2520 {
2521 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2522
2523 TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
2524 return S_OK;
2525 }
2526
2527 #define USED_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)
2528 struct VERTEX { float x, y, z, rhw, u, v; };
2529
2530 static HRESULT VMR9_ImagePresenter_PresentTexture(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
2531 {
2532 IDirect3DTexture9 *texture = NULL;
2533 HRESULT hr;
2534
2535 hr = IDirect3DDevice9_SetFVF(This->d3d9_dev, USED_FVF);
2536 if (FAILED(hr))
2537 {
2538 FIXME("SetFVF: %08x\n", hr);
2539 return hr;
2540 }
2541
2542 hr = IDirect3DDevice9_SetStreamSource(This->d3d9_dev, 0, This->d3d9_vertex, 0, sizeof(struct VERTEX));
2543 if (FAILED(hr))
2544 {
2545 FIXME("SetStreamSource: %08x\n", hr);
2546 return hr;
2547 }
2548
2549 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **) &texture);
2550 if (FAILED(hr))
2551 {
2552 FIXME("IDirect3DSurface9_GetContainer failed\n");
2553 return hr;
2554 }
2555 hr = IDirect3DDevice9_SetTexture(This->d3d9_dev, 0, (IDirect3DBaseTexture9 *)texture);
2556 IDirect3DTexture9_Release(texture);
2557 if (FAILED(hr))
2558 {
2559 FIXME("SetTexture: %08x\n", hr);
2560 return hr;
2561 }
2562
2563 hr = IDirect3DDevice9_DrawPrimitive(This->d3d9_dev, D3DPT_TRIANGLESTRIP, 0, 2);
2564 if (FAILED(hr))
2565 {
2566 FIXME("DrawPrimitive: %08x\n", hr);
2567 return hr;
2568 }
2569
2570 return S_OK;
2571 }
2572
2573 static HRESULT VMR9_ImagePresenter_PresentOffscreenSurface(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
2574 {
2575 HRESULT hr;
2576 IDirect3DSurface9 *target = NULL;
2577 RECT target_rect;
2578
2579 hr = IDirect3DDevice9_GetBackBuffer(This->d3d9_dev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &target);
2580 if (FAILED(hr))
2581 {
2582 ERR("IDirect3DDevice9_GetBackBuffer -- %08x\n", hr);
2583 return hr;
2584 }
2585
2586 /* Move rect to origin and flip it */
2587 SetRect(&target_rect, 0, This->pVMR9->target_rect.bottom - This->pVMR9->target_rect.top,
2588 This->pVMR9->target_rect.right - This->pVMR9->target_rect.left, 0);
2589
2590 hr = IDirect3DDevice9_StretchRect(This->d3d9_dev, surface, &This->pVMR9->source_rect, target, &target_rect, D3DTEXF_LINEAR);
2591 if (FAILED(hr))
2592 ERR("IDirect3DDevice9_StretchRect -- %08x\n", hr);
2593 IDirect3DSurface9_Release(target);
2594
2595 return hr;
2596 }
2597
2598 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface, DWORD_PTR id, VMR9PresentationInfo *info)
2599 {
2600 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
2601 HRESULT hr;
2602 RECT output;
2603 BOOL render = FALSE;
2604
2605 TRACE("(%p/%p/%p)->(...) stub\n", iface, This, This->pVMR9);
2606 GetWindowRect(This->pVMR9->baseControlWindow.baseWindow.hWnd, &output);
2607 TRACE("Output rectangle: %s\n", wine_dbgstr_rect(&output));
2608
2609 /* This might happen if we don't have active focus (eg on a different virtual desktop) */
2610 if (!This->d3d9_dev)
2611 return S_OK;
2612
2613 /* Display image here */
2614 hr = IDirect3DDevice9_Clear(This->d3d9_dev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
2615 if (FAILED(hr))
2616 FIXME("hr: %08x\n", hr);
2617 hr = IDirect3DDevice9_BeginScene(This->d3d9_dev);
2618 if (SUCCEEDED(hr))
2619 {
2620 if (This->d3d9_vertex)
2621 hr = VMR9_ImagePresenter_PresentTexture(This, info->lpSurf);
2622 else
2623 hr = VMR9_ImagePresenter_PresentOffscreenSurface(This, info->lpSurf);
2624 render = SUCCEEDED(hr);
2625 }
2626 else
2627 FIXME("BeginScene: %08x\n", hr);
2628 hr = IDirect3DDevice9_EndScene(This->d3d9_dev);
2629 if (render && SUCCEEDED(hr))
2630 {
2631 hr = IDirect3DDevice9_Present(This->d3d9_dev, NULL, NULL, This->pVMR9->baseControlWindow.baseWindow.hWnd, NULL);
2632 if (FAILED(hr))
2633 FIXME("Presenting image: %08x\n", hr);
2634 }
2635
2636 return S_OK;
2637 }
2638
2639 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
2640 {
2641 VMR9_ImagePresenter_QueryInterface,
2642 VMR9_ImagePresenter_AddRef,
2643 VMR9_ImagePresenter_Release,
2644 VMR9_ImagePresenter_StartPresenting,
2645 VMR9_ImagePresenter_StopPresenting,
2646 VMR9_ImagePresenter_PresentImage
2647 };
2648
2649 static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocatorEx9 *iface, REFIID riid, LPVOID * ppv)
2650 {
2651 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2652
2653 return VMR9_ImagePresenter_QueryInterface(&This->IVMRImagePresenter9_iface, riid, ppv);
2654 }
2655
2656 static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocatorEx9 *iface)
2657 {
2658 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2659
2660 return VMR9_ImagePresenter_AddRef(&This->IVMRImagePresenter9_iface);
2661 }
2662
2663 static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocatorEx9 *iface)
2664 {
2665 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2666
2667 return VMR9_ImagePresenter_Release(&This->IVMRImagePresenter9_iface);
2668 }
2669
2670 static HRESULT VMR9_SurfaceAllocator_SetAllocationSettings(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *allocinfo)
2671 {
2672 D3DCAPS9 caps;
2673 UINT width, height;
2674 HRESULT hr;
2675
2676 if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface))
2677 /* Only needed for texture surfaces */
2678 return S_OK;
2679
2680 hr = IDirect3DDevice9_GetDeviceCaps(This->d3d9_dev, &caps);
2681 if (FAILED(hr))
2682 return hr;
2683
2684 if (!(caps.TextureCaps & D3DPTEXTURECAPS_POW2) || (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY))
2685 {
2686 width = allocinfo->dwWidth;
2687 height = allocinfo->dwHeight;
2688 }
2689 else
2690 {
2691 width = height = 1;
2692 while (width < allocinfo->dwWidth)
2693 width *= 2;
2694
2695 while (height < allocinfo->dwHeight)
2696 height *= 2;
2697 FIXME("NPOW2 support missing, not using proper surfaces!\n");
2698 }
2699
2700 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
2701 {
2702 if (height > width)
2703 width = height;
2704 else
2705 height = width;
2706 FIXME("Square texture support required..\n");
2707 }
2708
2709 hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF, allocinfo->Pool, &This->d3d9_vertex, NULL);
2710 if (FAILED(hr))
2711 {
2712 ERR("Couldn't create vertex buffer: %08x\n", hr);
2713 return hr;
2714 }
2715
2716 This->reset = TRUE;
2717 allocinfo->dwHeight = height;
2718 allocinfo->dwWidth = width;
2719
2720 return hr;
2721 }
2722
2723 static DWORD WINAPI MessageLoop(LPVOID lpParameter)
2724 {
2725 MSG msg;
2726 BOOL fGotMessage;
2727 VMR9DefaultAllocatorPresenterImpl *This = lpParameter;
2728
2729 TRACE("Starting message loop\n");
2730
2731 if (FAILED(BaseWindowImpl_PrepareWindow(&This->pVMR9->baseControlWindow.baseWindow)))
2732 {
2733 FIXME("Failed to prepare window\n");
2734 return FALSE;
2735 }
2736
2737 SetEvent(This->ack);
2738 while ((fGotMessage = GetMessageW(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1)
2739 {
2740 TranslateMessage(&msg);
2741 DispatchMessageW(&msg);
2742 }
2743
2744 TRACE("End of message loop\n");
2745
2746 return 0;
2747 }
2748
2749 static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
2750 {
2751 UINT d3d9_adapter;
2752 HMONITOR mon;
2753
2754 mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
2755 if (!mon)
2756 d3d9_adapter = 0;
2757 else
2758 {
2759 for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
2760 {
2761 if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
2762 break;
2763 }
2764 if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
2765 d3d9_adapter = 0;
2766 }
2767 if (mon_out)
2768 *mon_out = mon;
2769 return d3d9_adapter;
2770 }
2771
2772 static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *info, DWORD *numbuffers)
2773 {
2774 D3DPRESENT_PARAMETERS d3dpp;
2775 DWORD d3d9_adapter;
2776 HRESULT hr;
2777
2778 TRACE("(%p)->()\n", This);
2779
2780 This->hWndThread = CreateThread(NULL, 0, MessageLoop, This, 0, &This->tid);
2781 if (!This->hWndThread)
2782 return FALSE;
2783
2784 WaitForSingleObject(This->ack, INFINITE);
2785
2786 if (!This->pVMR9->baseControlWindow.baseWindow.hWnd) return FALSE;
2787
2788 /* Obtain a monitor and d3d9 device */
2789 d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon);
2790
2791 /* Now try to create the d3d9 device */
2792 ZeroMemory(&d3dpp, sizeof(d3dpp));
2793 d3dpp.Windowed = TRUE;
2794 d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd;
2795 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2796 d3dpp.BackBufferHeight = This->pVMR9->target_rect.bottom - This->pVMR9->target_rect.top;
2797 d3dpp.BackBufferWidth = This->pVMR9->target_rect.right - This->pVMR9->target_rect.left;
2798
2799 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
2800 if (FAILED(hr))
2801 {
2802 ERR("Could not create device: %08x\n", hr);
2803 BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
2804 return FALSE;
2805 }
2806 IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2807
2808 This->d3d9_surfaces = CoTaskMemAlloc(*numbuffers * sizeof(IDirect3DSurface9 *));
2809 ZeroMemory(This->d3d9_surfaces, *numbuffers * sizeof(IDirect3DSurface9 *));
2810
2811 hr = VMR9_SurfaceAllocator_SetAllocationSettings(This, info);
2812 if (FAILED(hr))
2813 ERR("Setting allocation settings failed: %08x\n", hr);
2814
2815 if (SUCCEEDED(hr))
2816 {
2817 hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, info, numbuffers, This->d3d9_surfaces);
2818 if (FAILED(hr))
2819 ERR("Allocating surfaces failed: %08x\n", hr);
2820 }
2821
2822 if (FAILED(hr))
2823 {
2824 IVMRSurfaceAllocatorEx9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
2825 BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
2826 return FALSE;
2827 }
2828
2829 This->num_surfaces = *numbuffers;
2830
2831 return TRUE;
2832 }
2833
2834 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, VMR9AllocationInfo *allocinfo, DWORD *numbuffers)
2835 {
2836 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2837
2838 if (This->pVMR9->mode != VMR9Mode_Windowed && !This->pVMR9->hWndClippingWindow)
2839 {
2840 ERR("No window set\n");
2841 return VFW_E_WRONG_STATE;
2842 }
2843
2844 This->info = *allocinfo;
2845
2846 if (!CreateRenderingWindow(This, allocinfo, numbuffers))
2847 {
2848 ERR("Failed to create rendering window, expect no output!\n");
2849 return VFW_E_WRONG_STATE;
2850 }
2851
2852 return S_OK;
2853 }
2854
2855 static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id)
2856 {
2857 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2858
2859 if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
2860 {
2861 return S_OK;
2862 }
2863
2864 SendMessageW(This->pVMR9->baseControlWindow.baseWindow.hWnd, WM_CLOSE, 0, 0);
2865 PostThreadMessageW(This->tid, WM_QUIT, 0, 0);
2866 WaitForSingleObject(This->hWndThread, INFINITE);
2867 This->hWndThread = NULL;
2868 BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
2869
2870 return S_OK;
2871 }
2872
2873 /* Recreate all surfaces (If allocated as D3DPOOL_DEFAULT) and survive! */
2874 static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(VMR9DefaultAllocatorPresenterImpl *This)
2875 {
2876 struct VERTEX t_vert[4];
2877 UINT width, height;
2878 unsigned int i;
2879 void *bits = NULL;
2880 D3DPRESENT_PARAMETERS d3dpp;
2881 HRESULT hr;
2882
2883 if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
2884 {
2885 ERR("No window\n");
2886 return E_FAIL;
2887 }
2888
2889 if (!This->d3d9_surfaces || !This->reset)
2890 return S_OK;
2891
2892 This->reset = FALSE;
2893 TRACE("RESETTING\n");
2894 if (This->d3d9_vertex)
2895 {
2896 IDirect3DVertexBuffer9_Release(This->d3d9_vertex);
2897 This->d3d9_vertex = NULL;
2898 }
2899
2900 for (i = 0; i < This->num_surfaces; ++i)
2901 {
2902 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2903 TRACE("Releasing surface %p\n", surface);
2904 if (surface)
2905 IDirect3DSurface9_Release(surface);
2906 }
2907 ZeroMemory(This->d3d9_surfaces, sizeof(IDirect3DSurface9 *) * This->num_surfaces);
2908
2909 /* Now try to create the d3d9 device */
2910 ZeroMemory(&d3dpp, sizeof(d3dpp));
2911 d3dpp.Windowed = TRUE;
2912 d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd;
2913 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2914
2915 if (This->d3d9_dev)
2916 IDirect3DDevice9_Release(This->d3d9_dev);
2917 This->d3d9_dev = NULL;
2918 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon), D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
2919 if (FAILED(hr))
2920 {
2921 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon), D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
2922 if (FAILED(hr))
2923 {
2924 ERR("--> Creating device: %08x\n", hr);
2925 return S_OK;
2926 }
2927 }
2928 IVMRSurfaceAllocatorNotify9_ChangeD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2929
2930 IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, &This->info, &This->num_surfaces, This->d3d9_surfaces);
2931
2932 This->reset = FALSE;
2933
2934 if (!(This->info.dwFlags & VMR9AllocFlag_TextureSurface))
2935 return S_OK;
2936
2937 hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF,
2938 This->info.Pool, &This->d3d9_vertex, NULL);
2939
2940 width = This->info.dwWidth;
2941 height = This->info.dwHeight;
2942
2943 for (i = 0; i < sizeof(t_vert) / sizeof(t_vert[0]); ++i)
2944 {
2945 if (i % 2)
2946 {
2947 t_vert[i].x = (float)This->pVMR9->target_rect.right - (float)This->pVMR9->target_rect.left - 0.5f;
2948 t_vert[i].u = (float)This->pVMR9->source_rect.right / (float)width;
2949 }
2950 else
2951 {
2952 t_vert[i].x = -0.5f;
2953 t_vert[i].u = (float)This->pVMR9->source_rect.left / (float)width;
2954 }
2955
2956 if (i % 4 < 2)
2957 {
2958 t_vert[i].y = -0.5f;
2959 t_vert[i].v = (float)This->pVMR9->source_rect.bottom / (float)height;
2960 }
2961 else
2962 {
2963 t_vert[i].y = (float)This->pVMR9->target_rect.bottom - (float)This->pVMR9->target_rect.top - 0.5f;
2964 t_vert[i].v = (float)This->pVMR9->source_rect.top / (float)height;
2965 }
2966 t_vert[i].z = 0.0f;
2967 t_vert[i].rhw = 1.0f;
2968 }
2969
2970 FIXME("Vertex rectangle:\n");
2971 FIXME("X, Y: %f, %f\n", t_vert[0].x, t_vert[0].y);
2972 FIXME("X, Y: %f, %f\n", t_vert[3].x, t_vert[3].y);
2973 FIXME("TOP, LEFT: %f, %f\n", t_vert[0].u, t_vert[0].v);
2974 FIXME("DOWN, BOTTOM: %f, %f\n", t_vert[3].u, t_vert[3].v);
2975
2976 IDirect3DVertexBuffer9_Lock(This->d3d9_vertex, 0, sizeof(t_vert), &bits, 0);
2977 memcpy(bits, t_vert, sizeof(t_vert));
2978 IDirect3DVertexBuffer9_Unlock(This->d3d9_vertex);
2979
2980 return S_OK;
2981 }
2982
2983 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
2984 {
2985 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2986
2987 /* Update everything first, this is needed because the surface might be destroyed in the reset */
2988 if (!This->d3d9_dev)
2989 {
2990 TRACE("Device has left me!\n");
2991 return E_FAIL;
2992 }
2993
2994 VMR9_SurfaceAllocator_UpdateDeviceReset(This);
2995
2996 if (surfaceindex >= This->num_surfaces)
2997 {
2998 ERR("surfaceindex is greater than num_surfaces\n");
2999 return E_FAIL;
3000 }
3001 *surface = This->d3d9_surfaces[surfaceindex];
3002 IDirect3DSurface9_AddRef(*surface);
3003
3004 return S_OK;
3005 }
3006
3007 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocatorEx9 *iface, IVMRSurfaceAllocatorNotify9 *allocnotify)
3008 {
3009 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
3010
3011 TRACE("(%p/%p)->(...)\n", iface, This);
3012
3013 /* No AddRef taken here or the base VMR9 filter would never be destroyed */
3014 This->SurfaceAllocatorNotify = allocnotify;
3015 return S_OK;
3016 }
3017
3018 static const IVMRSurfaceAllocatorEx9Vtbl VMR9_SurfaceAllocator =
3019 {
3020 VMR9_SurfaceAllocator_QueryInterface,
3021 VMR9_SurfaceAllocator_AddRef,
3022 VMR9_SurfaceAllocator_Release,
3023 VMR9_SurfaceAllocator_InitializeDevice,
3024 VMR9_SurfaceAllocator_TerminateDevice,
3025 VMR9_SurfaceAllocator_GetSurface,
3026 VMR9_SurfaceAllocator_AdviseNotify,
3027 NULL /* This isn't the SurfaceAllocatorEx type yet, working on it */
3028 };
3029
3030 static IDirect3D9 *init_d3d9(HMODULE d3d9_handle)
3031 {
3032 IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion);
3033
3034 d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
3035 if (!d3d9_create) return NULL;
3036
3037 return d3d9_create(D3D_SDK_VERSION);
3038 }
3039
3040 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(struct quartz_vmr *parent, LPVOID * ppv)
3041 {
3042 HRESULT hr = S_OK;
3043 int i;
3044 VMR9DefaultAllocatorPresenterImpl* This;
3045
3046 This = CoTaskMemAlloc(sizeof(VMR9DefaultAllocatorPresenterImpl));
3047 if (!This)
3048 return E_OUTOFMEMORY;
3049
3050 This->d3d9_ptr = init_d3d9(parent->hD3d9);
3051 if (!This->d3d9_ptr)
3052 {
3053 WARN("Could not initialize d3d9.dll\n");
3054 CoTaskMemFree(This);
3055 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3056 }
3057
3058 i = 0;
3059 do
3060 {
3061 D3DDISPLAYMODE mode;
3062
3063 hr = IDirect3D9_EnumAdapterModes(This->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode);
3064 if (hr == D3DERR_INVALIDCALL) break; /* out of adapters */
3065 } while (FAILED(hr));
3066 if (FAILED(hr))
3067 ERR("HR: %08x\n", hr);
3068 if (hr == D3DERR_NOTAVAILABLE)
3069 {
3070 ERR("Format not supported\n");
3071 IDirect3D9_Release(This->d3d9_ptr);
3072 CoTaskMemFree(This);
3073 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
3074 }
3075
3076 This->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
3077 This->IVMRSurfaceAllocatorEx9_iface.lpVtbl = &VMR9_SurfaceAllocator;
3078
3079 This->refCount = 1;
3080 This->pVMR9 = parent;
3081 This->d3d9_surfaces = NULL;
3082 This->d3d9_dev = NULL;
3083 This->hMon = 0;
3084 This->d3d9_vertex = NULL;
3085 This->num_surfaces = 0;
3086 This->hWndThread = NULL;
3087 This->ack = CreateEventW(NULL, 0, 0, NULL);
3088 This->SurfaceAllocatorNotify = NULL;
3089 This->reset = FALSE;
3090
3091 *ppv = &This->IVMRImagePresenter9_iface;
3092 return S_OK;
3093 }