quartz: Use proper method macros.
[wine] / dlls / 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 "config.h"
24
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
27 #include "quartz_private.h"
28
29 #include "uuids.h"
30 #include "vfwmsgs.h"
31 #include "amvideo.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "dshow.h"
35 #include "evcode.h"
36 #include "strmif.h"
37 #include "ddraw.h"
38 #include "dvdmedia.h"
39 #include "d3d9.h"
40 #include "vmr9.h"
41 #include "pin.h"
42
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
47
48 typedef struct
49 {
50     BaseRenderer renderer;
51     BaseControlWindow baseControlWindow;
52     BaseControlVideo baseControlVideo;
53
54     IUnknown IUnknown_inner;
55     IAMFilterMiscFlags IAMFilterMiscFlags_iface;
56     IVMRFilterConfig9 IVMRFilterConfig9_iface;
57     IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
58     IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface;
59
60     IVMRSurfaceAllocatorEx9 *allocator;
61     IVMRImagePresenter9 *presenter;
62     BOOL allocator_is_ex;
63
64     /*
65      * The Video Mixing Renderer supports 3 modes, renderless, windowless and windowed
66      * What I do is implement windowless as a special case of renderless, and then
67      * windowed also as a special case of windowless. This is probably the easiest way.
68      */
69     VMR9Mode mode;
70     BITMAPINFOHEADER bmiheader;
71     IUnknown * outer_unk;
72     BOOL bUnkOuterValid;
73     BOOL bAggregatable;
74
75     HMODULE hD3d9;
76
77     /* Presentation related members */
78     IDirect3DDevice9 *allocator_d3d9_dev;
79     HMONITOR allocator_mon;
80     DWORD num_surfaces;
81     DWORD cur_surface;
82     DWORD_PTR cookie;
83
84     /* for Windowless Mode */
85     HWND hWndClippingWindow;
86
87     RECT source_rect;
88     RECT target_rect;
89     LONG VideoWidth;
90     LONG VideoHeight;
91 } VMR9Impl;
92
93 static inline VMR9Impl *impl_from_inner_IUnknown(IUnknown *iface)
94 {
95     return CONTAINING_RECORD(iface, VMR9Impl, IUnknown_inner);
96 }
97
98 static inline VMR9Impl *impl_from_BaseWindow( BaseWindow *wnd )
99 {
100     return CONTAINING_RECORD(wnd, VMR9Impl, baseControlWindow.baseWindow);
101 }
102
103 static inline VMR9Impl *impl_from_IVideoWindow( IVideoWindow *iface)
104 {
105     return CONTAINING_RECORD(iface, VMR9Impl, baseControlWindow.IVideoWindow_iface);
106 }
107
108 static inline VMR9Impl *impl_from_BaseControlVideo( BaseControlVideo *cvid )
109 {
110     return CONTAINING_RECORD(cvid, VMR9Impl, baseControlVideo);
111 }
112
113 static inline VMR9Impl *impl_from_IBasicVideo( IBasicVideo *iface)
114 {
115     return CONTAINING_RECORD(iface, VMR9Impl, baseControlVideo.IBasicVideo_iface);
116 }
117
118 static inline VMR9Impl *impl_from_IAMFilterMiscFlags( IAMFilterMiscFlags *iface)
119 {
120     return CONTAINING_RECORD(iface, VMR9Impl, IAMFilterMiscFlags_iface);
121 }
122
123 static inline VMR9Impl *impl_from_IVMRFilterConfig9( IVMRFilterConfig9 *iface)
124 {
125     return CONTAINING_RECORD(iface, VMR9Impl, IVMRFilterConfig9_iface);
126 }
127
128 static inline VMR9Impl *impl_from_IVMRWindowlessControl9( IVMRWindowlessControl9 *iface)
129 {
130     return CONTAINING_RECORD(iface, VMR9Impl, IVMRWindowlessControl9_iface);
131 }
132
133 static inline VMR9Impl *impl_from_IVMRSurfaceAllocatorNotify9( IVMRSurfaceAllocatorNotify9 *iface)
134 {
135     return CONTAINING_RECORD(iface, VMR9Impl, IVMRSurfaceAllocatorNotify9_iface);
136 }
137
138 typedef struct
139 {
140     IVMRImagePresenter9 IVMRImagePresenter9_iface;
141     IVMRSurfaceAllocatorEx9 IVMRSurfaceAllocatorEx9_iface;
142
143     LONG refCount;
144
145     HANDLE ack;
146     DWORD tid;
147     HANDLE hWndThread;
148
149     IDirect3DDevice9 *d3d9_dev;
150     IDirect3D9 *d3d9_ptr;
151     IDirect3DSurface9 **d3d9_surfaces;
152     IDirect3DVertexBuffer9 *d3d9_vertex;
153     HMONITOR hMon;
154     DWORD num_surfaces;
155
156     BOOL reset;
157     VMR9AllocationInfo info;
158
159     VMR9Impl* pVMR9;
160     IVMRSurfaceAllocatorNotify9 *SurfaceAllocatorNotify;
161 } VMR9DefaultAllocatorPresenterImpl;
162
163 static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRImagePresenter9( IVMRImagePresenter9 *iface)
164 {
165     return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRImagePresenter9_iface);
166 }
167
168 static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRSurfaceAllocatorEx9( IVMRSurfaceAllocatorEx9 *iface)
169 {
170     return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRSurfaceAllocatorEx9_iface);
171 }
172
173 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID * ppv);
174
175 static DWORD VMR9_SendSampleData(VMR9Impl *This, VMR9PresentationInfo *info, LPBYTE data, DWORD size)
176 {
177     AM_MEDIA_TYPE *amt;
178     HRESULT hr = S_OK;
179     int width;
180     int height;
181     BITMAPINFOHEADER *bmiHeader;
182     D3DLOCKED_RECT lock;
183
184     TRACE("%p %p %d\n", This, data, size);
185
186     amt = &This->renderer.pInputPin->pin.mtCurrent;
187
188     if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
189     {
190         bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
191     }
192     else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
193     {
194         bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
195     }
196     else
197     {
198         FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
199         return VFW_E_RUNTIME_ERROR;
200     }
201
202     TRACE("biSize = %d\n", bmiHeader->biSize);
203     TRACE("biWidth = %d\n", bmiHeader->biWidth);
204     TRACE("biHeight = %d\n", bmiHeader->biHeight);
205     TRACE("biPlanes = %d\n", bmiHeader->biPlanes);
206     TRACE("biBitCount = %d\n", bmiHeader->biBitCount);
207     TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(bmiHeader->biCompression), 4));
208     TRACE("biSizeImage = %d\n", bmiHeader->biSizeImage);
209
210     width = bmiHeader->biWidth;
211     height = bmiHeader->biHeight;
212
213     TRACE("Src Rect: %d %d %d %d\n", This->source_rect.left, This->source_rect.top, This->source_rect.right, This->source_rect.bottom);
214     TRACE("Dst Rect: %d %d %d %d\n", This->target_rect.left, This->target_rect.top, This->target_rect.right, This->target_rect.bottom);
215
216     hr = IDirect3DSurface9_LockRect(info->lpSurf, &lock, NULL, D3DLOCK_DISCARD);
217     if (FAILED(hr))
218     {
219         ERR("IDirect3DSurface9_LockRect failed (%x)\n",hr);
220         return hr;
221     }
222
223     if (lock.Pitch != width * bmiHeader->biBitCount / 8)
224     {
225         WARN("Slow path! %u/%u\n", lock.Pitch, width * bmiHeader->biBitCount/8);
226
227         while (height--)
228         {
229             memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8);
230             data = data + width * bmiHeader->biBitCount / 8;
231             lock.pBits = (char *)lock.pBits + lock.Pitch;
232         }
233     }
234     else memcpy(lock.pBits, data, size);
235
236     IDirect3DSurface9_UnlockRect(info->lpSurf);
237
238     hr = IVMRImagePresenter9_PresentImage(This->presenter, This->cookie, info);
239     return hr;
240 }
241
242 static HRESULT WINAPI VMR9_DoRenderSample(BaseRenderer *iface, IMediaSample * pSample)
243 {
244     VMR9Impl *This = (VMR9Impl *)iface;
245     LPBYTE pbSrcStream = NULL;
246     long cbSrcStream = 0;
247     REFERENCE_TIME tStart, tStop;
248     VMR9PresentationInfo info;
249     HRESULT hr;
250
251     TRACE("%p %p\n", iface, pSample);
252
253     /* It is possible that there is no device at this point */
254
255     if (!This->allocator || !This->presenter)
256     {
257         ERR("NO PRESENTER!!\n");
258         return S_FALSE;
259     }
260
261     hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
262     if (FAILED(hr))
263         info.dwFlags = VMR9Sample_SrcDstRectsValid;
264     else
265         info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
266
267     if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
268         info.dwFlags |= VMR9Sample_Discontinuity;
269
270     if (IMediaSample_IsPreroll(pSample) == S_OK)
271         info.dwFlags |= VMR9Sample_Preroll;
272
273     if (IMediaSample_IsSyncPoint(pSample) == S_OK)
274         info.dwFlags |= VMR9Sample_SyncPoint;
275
276     /* If we render ourselves, and this is a preroll sample, discard it */
277     if (This->baseControlWindow.baseWindow.hWnd && (info.dwFlags & VMR9Sample_Preroll))
278     {
279         return S_OK;
280     }
281
282     hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
283     if (FAILED(hr))
284     {
285         ERR("Cannot get pointer to sample data (%x)\n", hr);
286         return hr;
287     }
288
289     cbSrcStream = IMediaSample_GetActualDataLength(pSample);
290
291     info.rtStart = tStart;
292     info.rtEnd = tStop;
293     info.szAspectRatio.cx = This->bmiheader.biWidth;
294     info.szAspectRatio.cy = This->bmiheader.biHeight;
295
296     hr = IVMRSurfaceAllocatorEx9_GetSurface(This->allocator, This->cookie, (++This->cur_surface)%This->num_surfaces, 0, &info.lpSurf);
297
298     if (FAILED(hr))
299         return hr;
300
301     VMR9_SendSampleData(This, &info, pbSrcStream, cbSrcStream);
302     IDirect3DSurface9_Release(info.lpSurf);
303
304     return hr;
305 }
306
307 static HRESULT WINAPI VMR9_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
308 {
309     VMR9Impl *This = (VMR9Impl*)iface;
310
311     if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) || !pmt->pbFormat)
312         return S_FALSE;
313
314     /* Ignore subtype, test for bicompression instead */
315     if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
316     {
317         VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
318
319         This->bmiheader = format->bmiHeader;
320         TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
321         This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
322         This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
323         This->source_rect.top = This->source_rect.left = 0;
324     }
325     else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
326     {
327         VIDEOINFOHEADER2 *format = (VIDEOINFOHEADER2 *)pmt->pbFormat;
328
329         This->bmiheader = format->bmiHeader;
330
331         TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight);
332         This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth;
333         This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
334         This->source_rect.top = This->source_rect.left = 0;
335     }
336     else
337     {
338         ERR("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
339         return S_FALSE;
340     }
341     if (This->bmiheader.biCompression)
342         return S_FALSE;
343     return S_OK;
344 }
345
346 static HRESULT VMR9_maybe_init(VMR9Impl *This, BOOL force)
347 {
348     VMR9AllocationInfo info;
349     DWORD buffers;
350     HRESULT hr;
351
352     TRACE("my mode: %u, my window: %p, my last window: %p\n", This->mode, This->baseControlWindow.baseWindow.hWnd, This->hWndClippingWindow);
353     if (This->baseControlWindow.baseWindow.hWnd || !This->renderer.pInputPin->pin.pConnectedTo)
354         return S_OK;
355
356     if (This->mode == VMR9Mode_Windowless && !This->hWndClippingWindow)
357         return (force ? VFW_E_RUNTIME_ERROR : S_OK);
358
359     TRACE("Initializing\n");
360     info.dwFlags = VMR9AllocFlag_TextureSurface;
361     info.dwHeight = This->source_rect.bottom;
362     info.dwWidth = This->source_rect.right;
363     info.Pool = D3DPOOL_DEFAULT;
364     info.MinBuffers = 2;
365     FIXME("Reduce ratio to least common denominator\n");
366     info.szAspectRatio.cx = info.dwWidth;
367     info.szAspectRatio.cy = info.dwHeight;
368     info.szNativeSize.cx = This->bmiheader.biWidth;
369     info.szNativeSize.cy = This->bmiheader.biHeight;
370     buffers = 2;
371
372     switch (This->bmiheader.biBitCount)
373     {
374     case 8:  info.Format = D3DFMT_R3G3B2; break;
375     case 15: info.Format = D3DFMT_X1R5G5B5; break;
376     case 16: info.Format = D3DFMT_R5G6B5; break;
377     case 24: info.Format = D3DFMT_R8G8B8; break;
378     case 32: info.Format = D3DFMT_X8R8G8B8; break;
379     default:
380         FIXME("Unknown bpp %u\n", This->bmiheader.biBitCount);
381         hr = E_INVALIDARG;
382     }
383
384     This->cur_surface = 0;
385     if (This->num_surfaces)
386     {
387         ERR("num_surfaces or d3d9_surfaces not 0\n");
388         return E_FAIL;
389     }
390
391     hr = IVMRSurfaceAllocatorEx9_InitializeDevice(This->allocator, This->cookie, &info, &buffers);
392     if (SUCCEEDED(hr))
393     {
394         This->source_rect.left = This->source_rect.top = 0;
395         This->source_rect.right = This->bmiheader.biWidth;
396         This->source_rect.bottom = This->bmiheader.biHeight;
397
398         This->num_surfaces = buffers;
399     }
400     return hr;
401 }
402
403 static VOID WINAPI VMR9_OnStartStreaming(BaseRenderer* iface)
404 {
405     VMR9Impl *This = (VMR9Impl*)iface;
406
407     TRACE("(%p)\n", This);
408
409     VMR9_maybe_init(This, TRUE);
410     IVMRImagePresenter9_StartPresenting(This->presenter, This->cookie);
411     SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
412         This->source_rect.left,
413         This->source_rect.top,
414         This->source_rect.right - This->source_rect.left,
415         This->source_rect.bottom - This->source_rect.top,
416         SWP_NOZORDER|SWP_NOMOVE|SWP_DEFERERASE);
417     ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_SHOW);
418     GetClientRect(This->baseControlWindow.baseWindow.hWnd, &This->target_rect);
419 }
420
421 static VOID WINAPI VMR9_OnStopStreaming(BaseRenderer* iface)
422 {
423     VMR9Impl *This = (VMR9Impl*)iface;
424
425     TRACE("(%p)\n", This);
426
427     if (This->renderer.filter.state == State_Running)
428         IVMRImagePresenter9_StopPresenting(This->presenter, This->cookie);
429 }
430
431 static HRESULT WINAPI VMR9_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
432 {
433     /* Preroll means the sample isn't shown, this is used for key frames and things like that */
434     if (IMediaSample_IsPreroll(pSample) == S_OK)
435         return E_FAIL;
436     return S_FALSE;
437 }
438
439 static HRESULT WINAPI VMR9_CompleteConnect(BaseRenderer *This, IPin *pReceivePin)
440 {
441     VMR9Impl *pVMR9 = (VMR9Impl*)This;
442     HRESULT hr = S_OK;
443
444     TRACE("(%p)\n", This);
445
446     if (!pVMR9->mode && SUCCEEDED(hr))
447         hr = IVMRFilterConfig9_SetRenderingMode(&pVMR9->IVMRFilterConfig9_iface, VMR9Mode_Windowed);
448
449     if (SUCCEEDED(hr))
450         hr = VMR9_maybe_init(pVMR9, FALSE);
451
452     return hr;
453 }
454
455 static HRESULT WINAPI VMR9_BreakConnect(BaseRenderer *This)
456 {
457     VMR9Impl *pVMR9 = (VMR9Impl*)This;
458     HRESULT hr = S_OK;
459
460     if (!pVMR9->mode)
461         return S_FALSE;
462      if (This->pInputPin->pin.pConnectedTo && pVMR9->allocator && pVMR9->presenter)
463     {
464         if (pVMR9->renderer.filter.state != State_Stopped)
465         {
466             ERR("Disconnecting while not stopped! UNTESTED!!\n");
467         }
468         if (pVMR9->renderer.filter.state == State_Running)
469             hr = IVMRImagePresenter9_StopPresenting(pVMR9->presenter, pVMR9->cookie);
470         IVMRSurfaceAllocatorEx9_TerminateDevice(pVMR9->allocator, pVMR9->cookie);
471         pVMR9->num_surfaces = 0;
472     }
473     return hr;
474 }
475
476 static const BaseRendererFuncTable BaseFuncTable = {
477     VMR9_CheckMediaType,
478     VMR9_DoRenderSample,
479     /**/
480     NULL,
481     NULL,
482     NULL,
483     VMR9_OnStartStreaming,
484     VMR9_OnStopStreaming,
485     NULL,
486     NULL,
487     NULL,
488     VMR9_ShouldDrawSampleNow,
489     NULL,
490     /**/
491     VMR9_CompleteConnect,
492     VMR9_BreakConnect,
493     NULL,
494     NULL,
495     NULL,
496 };
497
498 static LPWSTR WINAPI VMR9_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx)
499 {
500     static WCHAR classnameW[] = { 'I','V','M','R','9',' ','C','l','a','s','s', 0 };
501
502     *pClassStyles = 0;
503     *pWindowStyles = WS_SIZEBOX;
504     *pWindowStylesEx = 0;
505
506     return classnameW;
507 }
508
509 static RECT WINAPI VMR9_GetDefaultRect(BaseWindow *This)
510 {
511     VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
512     static RECT defRect;
513
514     defRect.left = defRect.top = 0;
515     defRect.right = pVMR9->VideoWidth;
516     defRect.bottom = pVMR9->VideoHeight;
517
518     return defRect;
519 }
520
521 static BOOL WINAPI VMR9_OnSize(BaseWindow *This, LONG Width, LONG Height)
522 {
523     VMR9Impl* pVMR9 = impl_from_BaseWindow(This);
524
525     TRACE("WM_SIZE %d %d\n", Width, Height);
526     GetClientRect(This->hWnd, &pVMR9->target_rect);
527     TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
528         pVMR9->target_rect.left,
529         pVMR9->target_rect.top,
530         pVMR9->target_rect.right - pVMR9->target_rect.left,
531         pVMR9->target_rect.bottom - pVMR9->target_rect.top);
532     return BaseWindowImpl_OnSize(This, Width, Height);
533 }
534
535 static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
536     VMR9_GetClassWindowStyles,
537     VMR9_GetDefaultRect,
538     NULL,
539     BaseControlWindowImpl_PossiblyEatMessage,
540     VMR9_OnSize,
541 };
542
543 static HRESULT WINAPI VMR9_GetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
544 {
545     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
546     CopyRect(pSourceRect,&pVMR9->source_rect);
547     return S_OK;
548 }
549
550 static HRESULT WINAPI VMR9_GetStaticImage(BaseControlVideo* This, LONG *pBufferSize, LONG *pDIBImage)
551 {
552     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
553     BITMAPINFOHEADER *bmiHeader;
554     LONG needed_size;
555     AM_MEDIA_TYPE *amt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
556     char *ptr;
557
558     FIXME("(%p/%p)->(%p, %p): partial stub\n", pVMR9, This, pBufferSize, pDIBImage);
559
560     EnterCriticalSection(&pVMR9->renderer.filter.csFilter);
561
562     if (!pVMR9->renderer.pMediaSample)
563     {
564          LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
565          return (pVMR9->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
566     }
567
568     if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
569     {
570         bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
571     }
572     else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
573     {
574         bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
575     }
576     else
577     {
578         FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
579         LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
580         return VFW_E_RUNTIME_ERROR;
581     }
582
583     needed_size = bmiHeader->biSize;
584     needed_size += IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample);
585
586     if (!pDIBImage)
587     {
588         *pBufferSize = needed_size;
589         LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
590         return S_OK;
591     }
592
593     if (needed_size < *pBufferSize)
594     {
595         ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
596         LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
597         return E_FAIL;
598     }
599     *pBufferSize = needed_size;
600
601     memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
602     IMediaSample_GetPointer(pVMR9->renderer.pMediaSample, (BYTE **)&ptr);
603     memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample));
604
605     LeaveCriticalSection(&pVMR9->renderer.filter.csFilter);
606     return S_OK;
607 }
608
609 static HRESULT WINAPI VMR9_GetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
610 {
611     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
612     CopyRect(pTargetRect,&pVMR9->target_rect);
613     return S_OK;
614 }
615
616 static VIDEOINFOHEADER* WINAPI VMR9_GetVideoFormat(BaseControlVideo* This)
617 {
618     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
619     AM_MEDIA_TYPE *pmt;
620
621     TRACE("(%p/%p)\n", pVMR9, This);
622
623     pmt = &pVMR9->renderer.pInputPin->pin.mtCurrent;
624     if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
625         return (VIDEOINFOHEADER*)pmt->pbFormat;
626     } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
627         static VIDEOINFOHEADER vih;
628         VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat;
629         memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER));
630         memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER));
631         return &vih;
632     } else {
633         ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
634         return NULL;
635     }
636 }
637
638 static HRESULT WINAPI VMR9_IsDefaultSourceRect(BaseControlVideo* This)
639 {
640     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
641     FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
642
643     return S_OK;
644 }
645
646 static HRESULT WINAPI VMR9_IsDefaultTargetRect(BaseControlVideo* This)
647 {
648     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
649     FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This);
650
651     return S_OK;
652 }
653
654 static HRESULT WINAPI VMR9_SetDefaultSourceRect(BaseControlVideo* This)
655 {
656     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
657
658     pVMR9->source_rect.left = 0;
659     pVMR9->source_rect.top = 0;
660     pVMR9->source_rect.right = pVMR9->VideoWidth;
661     pVMR9->source_rect.bottom = pVMR9->VideoHeight;
662
663     return S_OK;
664 }
665
666 static HRESULT WINAPI VMR9_SetDefaultTargetRect(BaseControlVideo* This)
667 {
668     RECT rect;
669     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
670
671     if (!GetClientRect(pVMR9->baseControlWindow.baseWindow.hWnd, &rect))
672         return E_FAIL;
673
674     pVMR9->target_rect.left = 0;
675     pVMR9->target_rect.top = 0;
676     pVMR9->target_rect.right = rect.right;
677     pVMR9->target_rect.bottom = rect.bottom;
678
679     return S_OK;
680 }
681
682 static HRESULT WINAPI VMR9_SetSourceRect(BaseControlVideo* This, RECT *pSourceRect)
683 {
684     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
685     CopyRect(&pVMR9->source_rect,pSourceRect);
686     return S_OK;
687 }
688
689 static HRESULT WINAPI VMR9_SetTargetRect(BaseControlVideo* This, RECT *pTargetRect)
690 {
691     VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This);
692     CopyRect(&pVMR9->target_rect,pTargetRect);
693     return S_OK;
694 }
695
696 static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = {
697     VMR9_GetSourceRect,
698     VMR9_GetStaticImage,
699     VMR9_GetTargetRect,
700     VMR9_GetVideoFormat,
701     VMR9_IsDefaultSourceRect,
702     VMR9_IsDefaultTargetRect,
703     VMR9_SetDefaultSourceRect,
704     VMR9_SetDefaultTargetRect,
705     VMR9_SetSourceRect,
706     VMR9_SetTargetRect
707 };
708
709 static HRESULT WINAPI VMR9Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
710 {
711     VMR9Impl *This = impl_from_inner_IUnknown(iface);
712     TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
713
714     if (This->bAggregatable)
715         This->bUnkOuterValid = TRUE;
716
717     *ppv = NULL;
718
719     if (IsEqualIID(riid, &IID_IUnknown))
720         *ppv = &This->IUnknown_inner;
721     else if (IsEqualIID(riid, &IID_IVideoWindow))
722         *ppv = &This->baseControlWindow.IVideoWindow_iface;
723     else if (IsEqualIID(riid, &IID_IBasicVideo))
724         *ppv = &This->baseControlVideo.IBasicVideo_iface;
725     else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
726         *ppv = &This->IAMFilterMiscFlags_iface;
727     else if (IsEqualIID(riid, &IID_IVMRFilterConfig9))
728         *ppv = &This->IVMRFilterConfig9_iface;
729     else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9) && This->mode == VMR9Mode_Windowless)
730         *ppv = &This->IVMRWindowlessControl9_iface;
731     else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9) && This->mode == VMR9Mode_Renderless)
732         *ppv = &This->IVMRSurfaceAllocatorNotify9_iface;
733     else
734     {
735         HRESULT hr;
736         hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
737         if (SUCCEEDED(hr))
738             return hr;
739     }
740
741     if (*ppv)
742     {
743         IUnknown_AddRef((IUnknown *)(*ppv));
744         return S_OK;
745     }
746
747     else if (IsEqualIID(riid, &IID_IBasicVideo2))
748         FIXME("No interface for IID_IBasicVideo2\n");
749     else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9))
750         ;
751     else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9))
752         ;
753     else if (IsEqualIID(riid, &IID_IMediaPosition))
754         FIXME("No interface for IID_IMediaPosition\n");
755     else if (IsEqualIID(riid, &IID_IQualProp))
756         FIXME("No interface for IID_IQualProp\n");
757     else if (IsEqualIID(riid, &IID_IVMRAspectRatioControl9))
758         FIXME("No interface for IID_IVMRAspectRatioControl9\n");
759     else if (IsEqualIID(riid, &IID_IVMRDeinterlaceControl9))
760         FIXME("No interface for IID_IVMRDeinterlaceControl9\n");
761     else if (IsEqualIID(riid, &IID_IVMRMixerBitmap9))
762         FIXME("No interface for IID_IVMRMixerBitmap9\n");
763     else if (IsEqualIID(riid, &IID_IVMRMonitorConfig9))
764         FIXME("No interface for IID_IVMRMonitorConfig9\n");
765     else if (IsEqualIID(riid, &IID_IVMRMixerControl9))
766         FIXME("No interface for IID_IVMRMixerControl9\n");
767     else
768         FIXME("No interface for %s\n", debugstr_guid(riid));
769
770     return E_NOINTERFACE;
771 }
772
773 static ULONG WINAPI VMR9Inner_AddRef(IUnknown * iface)
774 {
775     VMR9Impl *This = impl_from_inner_IUnknown(iface);
776     ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
777
778     TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
779
780     return refCount;
781 }
782
783 static ULONG WINAPI VMR9Inner_Release(IUnknown * iface)
784 {
785     VMR9Impl *This = impl_from_inner_IUnknown(iface);
786     ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface);
787
788     TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
789
790     if (!refCount)
791     {
792         TRACE("Destroying\n");
793         BaseControlWindow_Destroy(&This->baseControlWindow);
794         CloseHandle(This->hD3d9);
795
796         if (This->allocator)
797             IVMRSurfaceAllocatorEx9_Release(This->allocator);
798         if (This->presenter)
799             IVMRImagePresenter9_Release(This->presenter);
800
801         This->num_surfaces = 0;
802         if (This->allocator_d3d9_dev)
803         {
804             IDirect3DDevice9_Release(This->allocator_d3d9_dev);
805             This->allocator_d3d9_dev = NULL;
806         }
807
808         CoTaskMemFree(This);
809     }
810     return refCount;
811 }
812
813 static const IUnknownVtbl IInner_VTable =
814 {
815     VMR9Inner_QueryInterface,
816     VMR9Inner_AddRef,
817     VMR9Inner_Release
818 };
819
820 static HRESULT WINAPI VMR9_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
821 {
822     VMR9Impl *This = (VMR9Impl *)iface;
823
824     if (This->bAggregatable)
825         This->bUnkOuterValid = TRUE;
826
827     if (This->outer_unk)
828     {
829         if (This->bAggregatable)
830             return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
831
832         if (IsEqualIID(riid, &IID_IUnknown))
833         {
834             HRESULT hr;
835
836             IUnknown_AddRef(&This->IUnknown_inner);
837             hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
838             IUnknown_Release(&This->IUnknown_inner);
839             This->bAggregatable = TRUE;
840             return hr;
841         }
842
843         *ppv = NULL;
844         return E_NOINTERFACE;
845     }
846
847     return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv);
848 }
849
850 static ULONG WINAPI VMR9_AddRef(IBaseFilter * iface)
851 {
852     VMR9Impl *This = (VMR9Impl *)iface;
853     LONG ret;
854
855     if (This->outer_unk && This->bUnkOuterValid)
856         ret = IUnknown_AddRef(This->outer_unk);
857     else
858         ret = IUnknown_AddRef(&This->IUnknown_inner);
859
860     TRACE("(%p)->AddRef from %d\n", iface, ret - 1);
861
862     return ret;
863 }
864
865 static ULONG WINAPI VMR9_Release(IBaseFilter * iface)
866 {
867     VMR9Impl *This = (VMR9Impl *)iface;
868     LONG ret;
869
870     if (This->outer_unk && This->bUnkOuterValid)
871         ret = IUnknown_Release(This->outer_unk);
872     else
873         ret = IUnknown_Release(&This->IUnknown_inner);
874
875     TRACE("(%p)->Release from %d\n", iface, ret + 1);
876
877     if (ret)
878         return ret;
879     return 0;
880 }
881
882 static const IBaseFilterVtbl VMR9_Vtbl =
883 {
884     VMR9_QueryInterface,
885     VMR9_AddRef,
886     VMR9_Release,
887     BaseFilterImpl_GetClassID,
888     BaseRendererImpl_Stop,
889     BaseRendererImpl_Pause,
890     BaseRendererImpl_Run,
891     BaseRendererImpl_GetState,
892     BaseRendererImpl_SetSyncSource,
893     BaseFilterImpl_GetSyncSource,
894     BaseFilterImpl_EnumPins,
895     BaseRendererImpl_FindPin,
896     BaseFilterImpl_QueryFilterInfo,
897     BaseFilterImpl_JoinFilterGraph,
898     BaseFilterImpl_QueryVendorInfo
899 };
900
901 /*** IUnknown methods ***/
902 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface, REFIID riid, LPVOID*ppvObj)
903 {
904     VMR9Impl *This = impl_from_IVideoWindow(iface);
905
906     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
907
908     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
909 }
910
911 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface)
912 {
913     VMR9Impl *This = impl_from_IVideoWindow(iface);
914
915     TRACE("(%p/%p)->()\n", This, iface);
916
917     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
918 }
919
920 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface)
921 {
922     VMR9Impl *This = impl_from_IVideoWindow(iface);
923
924     TRACE("(%p/%p)->()\n", This, iface);
925
926     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
927 }
928
929 static const IVideoWindowVtbl IVideoWindow_VTable =
930 {
931     Videowindow_QueryInterface,
932     Videowindow_AddRef,
933     Videowindow_Release,
934     BaseControlWindowImpl_GetTypeInfoCount,
935     BaseControlWindowImpl_GetTypeInfo,
936     BaseControlWindowImpl_GetIDsOfNames,
937     BaseControlWindowImpl_Invoke,
938     BaseControlWindowImpl_put_Caption,
939     BaseControlWindowImpl_get_Caption,
940     BaseControlWindowImpl_put_WindowStyle,
941     BaseControlWindowImpl_get_WindowStyle,
942     BaseControlWindowImpl_put_WindowStyleEx,
943     BaseControlWindowImpl_get_WindowStyleEx,
944     BaseControlWindowImpl_put_AutoShow,
945     BaseControlWindowImpl_get_AutoShow,
946     BaseControlWindowImpl_put_WindowState,
947     BaseControlWindowImpl_get_WindowState,
948     BaseControlWindowImpl_put_BackgroundPalette,
949     BaseControlWindowImpl_get_BackgroundPalette,
950     BaseControlWindowImpl_put_Visible,
951     BaseControlWindowImpl_get_Visible,
952     BaseControlWindowImpl_put_Left,
953     BaseControlWindowImpl_get_Left,
954     BaseControlWindowImpl_put_Width,
955     BaseControlWindowImpl_get_Width,
956     BaseControlWindowImpl_put_Top,
957     BaseControlWindowImpl_get_Top,
958     BaseControlWindowImpl_put_Height,
959     BaseControlWindowImpl_get_Height,
960     BaseControlWindowImpl_put_Owner,
961     BaseControlWindowImpl_get_Owner,
962     BaseControlWindowImpl_put_MessageDrain,
963     BaseControlWindowImpl_get_MessageDrain,
964     BaseControlWindowImpl_get_BorderColor,
965     BaseControlWindowImpl_put_BorderColor,
966     BaseControlWindowImpl_get_FullScreenMode,
967     BaseControlWindowImpl_put_FullScreenMode,
968     BaseControlWindowImpl_SetWindowForeground,
969     BaseControlWindowImpl_NotifyOwnerMessage,
970     BaseControlWindowImpl_SetWindowPosition,
971     BaseControlWindowImpl_GetWindowPosition,
972     BaseControlWindowImpl_GetMinIdealImageSize,
973     BaseControlWindowImpl_GetMaxIdealImageSize,
974     BaseControlWindowImpl_GetRestorePosition,
975     BaseControlWindowImpl_HideCursor,
976     BaseControlWindowImpl_IsCursorHidden
977 };
978
979 /*** IUnknown methods ***/
980 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID * ppvObj)
981 {
982     VMR9Impl *This = impl_from_IBasicVideo(iface);
983
984     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
985
986     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
987 }
988
989 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface)
990 {
991     VMR9Impl *This = impl_from_IBasicVideo(iface);
992
993     TRACE("(%p/%p)->()\n", This, iface);
994
995     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
996 }
997
998 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface)
999 {
1000     VMR9Impl *This = impl_from_IBasicVideo(iface);
1001
1002     TRACE("(%p/%p)->()\n", This, iface);
1003
1004     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1005 }
1006
1007 static const IBasicVideoVtbl IBasicVideo_VTable =
1008 {
1009     Basicvideo_QueryInterface,
1010     Basicvideo_AddRef,
1011     Basicvideo_Release,
1012     BaseControlVideoImpl_GetTypeInfoCount,
1013     BaseControlVideoImpl_GetTypeInfo,
1014     BaseControlVideoImpl_GetIDsOfNames,
1015     BaseControlVideoImpl_Invoke,
1016     BaseControlVideoImpl_get_AvgTimePerFrame,
1017     BaseControlVideoImpl_get_BitRate,
1018     BaseControlVideoImpl_get_BitErrorRate,
1019     BaseControlVideoImpl_get_VideoWidth,
1020     BaseControlVideoImpl_get_VideoHeight,
1021     BaseControlVideoImpl_put_SourceLeft,
1022     BaseControlVideoImpl_get_SourceLeft,
1023     BaseControlVideoImpl_put_SourceWidth,
1024     BaseControlVideoImpl_get_SourceWidth,
1025     BaseControlVideoImpl_put_SourceTop,
1026     BaseControlVideoImpl_get_SourceTop,
1027     BaseControlVideoImpl_put_SourceHeight,
1028     BaseControlVideoImpl_get_SourceHeight,
1029     BaseControlVideoImpl_put_DestinationLeft,
1030     BaseControlVideoImpl_get_DestinationLeft,
1031     BaseControlVideoImpl_put_DestinationWidth,
1032     BaseControlVideoImpl_get_DestinationWidth,
1033     BaseControlVideoImpl_put_DestinationTop,
1034     BaseControlVideoImpl_get_DestinationTop,
1035     BaseControlVideoImpl_put_DestinationHeight,
1036     BaseControlVideoImpl_get_DestinationHeight,
1037     BaseControlVideoImpl_SetSourcePosition,
1038     BaseControlVideoImpl_GetSourcePosition,
1039     BaseControlVideoImpl_SetDefaultSourcePosition,
1040     BaseControlVideoImpl_SetDestinationPosition,
1041     BaseControlVideoImpl_GetDestinationPosition,
1042     BaseControlVideoImpl_SetDefaultDestinationPosition,
1043     BaseControlVideoImpl_GetVideoSize,
1044     BaseControlVideoImpl_GetVideoPaletteEntries,
1045     BaseControlVideoImpl_GetCurrentImage,
1046     BaseControlVideoImpl_IsUsingDefaultSource,
1047     BaseControlVideoImpl_IsUsingDefaultDestination
1048 };
1049
1050 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
1051     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
1052     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1053 }
1054
1055 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
1056     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
1057     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1058 }
1059
1060 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
1061     VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface);
1062     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1063 }
1064
1065 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
1066     return AM_FILTER_MISC_FLAGS_IS_RENDERER;
1067 }
1068
1069 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
1070     AMFilterMiscFlags_QueryInterface,
1071     AMFilterMiscFlags_AddRef,
1072     AMFilterMiscFlags_Release,
1073     AMFilterMiscFlags_GetMiscFlags
1074 };
1075
1076 static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv)
1077 {
1078     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1079     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1080 }
1081
1082 static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface)
1083 {
1084     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1085     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1086 }
1087
1088 static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface)
1089 {
1090     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1091     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1092 }
1093
1094 static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor)
1095 {
1096     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1097
1098     FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor);
1099     return E_NOTIMPL;
1100 }
1101
1102 static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD max)
1103 {
1104     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1105
1106     FIXME("(%p/%p)->(%u) stub\n", iface, This, max);
1107     return E_NOTIMPL;
1108 }
1109
1110 static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *max)
1111 {
1112     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1113
1114     FIXME("(%p/%p)->(%p) stub\n", iface, This, max);
1115     return E_NOTIMPL;
1116 }
1117
1118 static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags)
1119 {
1120     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1121
1122     FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags);
1123     return E_NOTIMPL;
1124 }
1125
1126 static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags)
1127 {
1128     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1129
1130     FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags);
1131     return E_NOTIMPL;
1132 }
1133
1134 static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode)
1135 {
1136     HRESULT hr = S_OK;
1137     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1138
1139     TRACE("(%p/%p)->(%u)\n", iface, This, mode);
1140
1141     EnterCriticalSection(&This->renderer.filter.csFilter);
1142     if (This->mode)
1143     {
1144         LeaveCriticalSection(&This->renderer.filter.csFilter);
1145         return VFW_E_WRONG_STATE;
1146     }
1147
1148     if (This->allocator)
1149         IVMRSurfaceAllocatorEx9_Release(This->allocator);
1150     if (This->presenter)
1151         IVMRImagePresenter9_Release(This->presenter);
1152
1153     This->allocator = NULL;
1154     This->presenter = NULL;
1155
1156     switch (mode)
1157     {
1158     case VMR9Mode_Windowed:
1159     case VMR9Mode_Windowless:
1160         This->allocator_is_ex = 0;
1161         This->cookie = ~0;
1162
1163         hr = VMR9DefaultAllocatorPresenterImpl_create(This, (LPVOID*)&This->presenter);
1164         if (SUCCEEDED(hr))
1165             hr = IVMRImagePresenter9_QueryInterface(This->presenter, &IID_IVMRSurfaceAllocatorEx9, (LPVOID*)&This->allocator);
1166         if (FAILED(hr))
1167         {
1168             ERR("Unable to find Presenter interface\n");
1169             IVMRImagePresenter9_Release(This->presenter);
1170             This->allocator = NULL;
1171             This->presenter = NULL;
1172         }
1173         else
1174             hr = IVMRSurfaceAllocatorEx9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface);
1175         break;
1176     case VMR9Mode_Renderless:
1177         break;
1178     default:
1179         LeaveCriticalSection(&This->renderer.filter.csFilter);
1180         return E_INVALIDARG;
1181     }
1182
1183     This->mode = mode;
1184     LeaveCriticalSection(&This->renderer.filter.csFilter);
1185     return hr;
1186 }
1187
1188 static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode)
1189 {
1190     VMR9Impl *This = impl_from_IVMRFilterConfig9(iface);
1191
1192     TRACE("(%p/%p)->(%p) stub\n", iface, This, mode);
1193     if (!mode)
1194         return E_POINTER;
1195
1196     if (This->mode)
1197         *mode = This->mode;
1198     else
1199         *mode = VMR9Mode_Windowed;
1200
1201     return S_OK;
1202 }
1203
1204 static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl =
1205 {
1206     VMR9FilterConfig_QueryInterface,
1207     VMR9FilterConfig_AddRef,
1208     VMR9FilterConfig_Release,
1209     VMR9FilterConfig_SetImageCompositor,
1210     VMR9FilterConfig_SetNumberOfStreams,
1211     VMR9FilterConfig_GetNumberOfStreams,
1212     VMR9FilterConfig_SetRenderingPrefs,
1213     VMR9FilterConfig_GetRenderingPrefs,
1214     VMR9FilterConfig_SetRenderingMode,
1215     VMR9FilterConfig_GetRenderingMode
1216 };
1217
1218 static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv)
1219 {
1220     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1221     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1222 }
1223
1224 static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface)
1225 {
1226     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1227     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1228 }
1229
1230 static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface)
1231 {
1232     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1233     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1234 }
1235
1236 static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height, LONG *arwidth, LONG *arheight)
1237 {
1238     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1239     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight);
1240
1241     if (!width || !height || !arwidth || !arheight)
1242     {
1243         ERR("Got no pointer\n");
1244         return E_POINTER;
1245     }
1246
1247     *width = This->bmiheader.biWidth;
1248     *height = This->bmiheader.biHeight;
1249     *arwidth = This->bmiheader.biWidth;
1250     *arheight = This->bmiheader.biHeight;
1251
1252     return S_OK;
1253 }
1254
1255 static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1256 {
1257     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1258
1259     FIXME("(%p/%p)->(...) stub\n", iface, This);
1260     return E_NOTIMPL;
1261 }
1262
1263 static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height)
1264 {
1265     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1266
1267     FIXME("(%p/%p)->(...) stub\n", iface, This);
1268     return E_NOTIMPL;
1269 }
1270
1271 static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface, const RECT *source, const RECT *dest)
1272 {
1273     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1274
1275     TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest);
1276
1277     EnterCriticalSection(&This->renderer.filter.csFilter);
1278
1279     if (source)
1280         This->source_rect = *source;
1281     if (dest)
1282     {
1283         This->target_rect = *dest;
1284         if (This->baseControlWindow.baseWindow.hWnd)
1285         {
1286             FIXME("Output rectangle: starting at %dx%d, up to point %dx%d\n", dest->left, dest->top, dest->right, dest->bottom);
1287             SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left,
1288                          dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
1289         }
1290     }
1291
1292     LeaveCriticalSection(&This->renderer.filter.csFilter);
1293
1294     return S_OK;
1295 }
1296
1297 static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *source, RECT *dest)
1298 {
1299     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1300
1301     if (source)
1302         *source = This->source_rect;
1303
1304     if (dest)
1305         *dest = This->target_rect;
1306
1307     FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest);
1308     return S_OK;
1309 }
1310
1311 static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode)
1312 {
1313     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1314
1315     FIXME("(%p/%p)->(...) stub\n", iface, This);
1316     return E_NOTIMPL;
1317 }
1318
1319 static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode)
1320 {
1321     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1322
1323     FIXME("(%p/%p)->(...) stub\n", iface, This);
1324     return E_NOTIMPL;
1325 }
1326
1327 static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND hwnd)
1328 {
1329     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1330
1331     TRACE("(%p/%p)->(%p)\n", iface, This, hwnd);
1332
1333     EnterCriticalSection(&This->renderer.filter.csFilter);
1334     This->hWndClippingWindow = hwnd;
1335     VMR9_maybe_init(This, FALSE);
1336     if (!hwnd)
1337         IVMRSurfaceAllocatorEx9_TerminateDevice(This->allocator, This->cookie);
1338     LeaveCriticalSection(&This->renderer.filter.csFilter);
1339     return S_OK;
1340 }
1341
1342 static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc)
1343 {
1344     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1345     HRESULT hr;
1346
1347     FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1348
1349     EnterCriticalSection(&This->renderer.filter.csFilter);
1350     if (hwnd != This->hWndClippingWindow && hwnd != This->baseControlWindow.baseWindow.hWnd)
1351     {
1352         ERR("Not handling changing windows yet!!!\n");
1353         LeaveCriticalSection(&This->renderer.filter.csFilter);
1354         return S_OK;
1355     }
1356
1357     if (!This->allocator_d3d9_dev)
1358     {
1359         ERR("No d3d9 device!\n");
1360         LeaveCriticalSection(&This->renderer.filter.csFilter);
1361         return VFW_E_WRONG_STATE;
1362     }
1363
1364     /* Windowless extension */
1365     hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, This->baseControlWindow.baseWindow.hWnd, NULL);
1366     LeaveCriticalSection(&This->renderer.filter.csFilter);
1367
1368     return hr;
1369 }
1370
1371 static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface)
1372 {
1373     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1374
1375     FIXME("(%p/%p)->(...) stub\n", iface, This);
1376     return E_NOTIMPL;
1377 }
1378
1379 static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib)
1380 {
1381     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1382
1383     FIXME("(%p/%p)->(...) stub\n", iface, This);
1384     return E_NOTIMPL;
1385 }
1386
1387 static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color)
1388 {
1389     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1390
1391     FIXME("(%p/%p)->(...) stub\n", iface, This);
1392     return E_NOTIMPL;
1393 }
1394
1395 static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color)
1396 {
1397     VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface);
1398
1399     FIXME("(%p/%p)->(...) stub\n", iface, This);
1400     return E_NOTIMPL;
1401 }
1402
1403 static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl =
1404 {
1405     VMR9WindowlessControl_QueryInterface,
1406     VMR9WindowlessControl_AddRef,
1407     VMR9WindowlessControl_Release,
1408     VMR9WindowlessControl_GetNativeVideoSize,
1409     VMR9WindowlessControl_GetMinIdealVideoSize,
1410     VMR9WindowlessControl_GetMaxIdealVideoSize,
1411     VMR9WindowlessControl_SetVideoPosition,
1412     VMR9WindowlessControl_GetVideoPosition,
1413     VMR9WindowlessControl_GetAspectRatioMode,
1414     VMR9WindowlessControl_SetAspectRatioMode,
1415     VMR9WindowlessControl_SetVideoClippingWindow,
1416     VMR9WindowlessControl_RepaintVideo,
1417     VMR9WindowlessControl_DisplayModeChanged,
1418     VMR9WindowlessControl_GetCurrentImage,
1419     VMR9WindowlessControl_SetBorderColor,
1420     VMR9WindowlessControl_GetBorderColor
1421 };
1422
1423 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv)
1424 {
1425     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1426     return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
1427 }
1428
1429 static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
1430 {
1431     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1432     return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface);
1433 }
1434
1435 static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
1436 {
1437     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1438     return VMR9_Release(&This->renderer.filter.IBaseFilter_iface);
1439 }
1440
1441 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR id, IVMRSurfaceAllocator9 *alloc)
1442 {
1443     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1444
1445     /* FIXME: This code is not tested!!! */
1446     FIXME("(%p/%p)->(...) stub\n", iface, This);
1447     This->cookie = id;
1448
1449     if (This->presenter)
1450         return VFW_E_WRONG_STATE;
1451
1452     if (FAILED(IVMRSurfaceAllocator9_QueryInterface(alloc, &IID_IVMRImagePresenter9, (void **)&This->presenter)))
1453         return E_NOINTERFACE;
1454
1455     if (SUCCEEDED(IVMRSurfaceAllocator9_QueryInterface(alloc, &IID_IVMRSurfaceAllocatorEx9, (void **)&This->allocator)))
1456         This->allocator_is_ex = 1;
1457     else
1458     {
1459         This->allocator = (IVMRSurfaceAllocatorEx9 *)alloc;
1460         IVMRSurfaceAllocator9_AddRef(alloc);
1461         This->allocator_is_ex = 0;
1462     }
1463
1464     return S_OK;
1465 }
1466
1467 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
1468 {
1469     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1470
1471     FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1472     if (This->allocator_d3d9_dev)
1473         IDirect3DDevice9_Release(This->allocator_d3d9_dev);
1474     This->allocator_d3d9_dev = device;
1475     IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
1476     This->allocator_mon = monitor;
1477
1478     return S_OK;
1479 }
1480
1481 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor)
1482 {
1483     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1484
1485     FIXME("(%p/%p)->(...) semi-stub\n", iface, This);
1486     if (This->allocator_d3d9_dev)
1487         IDirect3DDevice9_Release(This->allocator_d3d9_dev);
1488     This->allocator_d3d9_dev = device;
1489     IDirect3DDevice9_AddRef(This->allocator_d3d9_dev);
1490     This->allocator_mon = monitor;
1491
1492     return S_OK;
1493 }
1494
1495 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface)
1496 {
1497     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1498     INT i;
1499     HRESULT hr = S_OK;
1500
1501     FIXME("(%p/%p)->(%p, %p => %u, %p) semi-stub\n", iface, This, allocinfo, numbuffers, (numbuffers ? *numbuffers : 0), surface);
1502
1503     if (!allocinfo || !numbuffers || !surface)
1504         return E_POINTER;
1505
1506     if (!*numbuffers || *numbuffers < allocinfo->MinBuffers)
1507     {
1508         ERR("Invalid number of buffers?\n");
1509         return E_INVALIDARG;
1510     }
1511
1512     if (!This->allocator_d3d9_dev)
1513     {
1514         ERR("No direct3d device when requested to allocate a surface!\n");
1515         return VFW_E_WRONG_STATE;
1516     }
1517
1518     if (allocinfo->dwFlags & VMR9AllocFlag_OffscreenSurface)
1519     {
1520         ERR("Creating offscreen surface\n");
1521         for (i = 0; i < *numbuffers; ++i)
1522         {
1523             hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->allocator_d3d9_dev,  allocinfo->dwWidth, allocinfo->dwHeight,
1524                                                              allocinfo->Format, allocinfo->Pool, &surface[i], NULL);
1525             if (FAILED(hr))
1526                 break;
1527         }
1528     }
1529     else if (allocinfo->dwFlags & VMR9AllocFlag_TextureSurface)
1530     {
1531         TRACE("Creating texture surface\n");
1532         for (i = 0; i < *numbuffers; ++i)
1533         {
1534             IDirect3DTexture9 *texture;
1535
1536             hr = IDirect3DDevice9_CreateTexture(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, 1, 0,
1537                                                 allocinfo->Format, allocinfo->Pool, &texture, NULL);
1538             if (FAILED(hr))
1539                 break;
1540             IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface[i]);
1541             IDirect3DTexture9_Release(texture);
1542         }
1543     }
1544     else
1545     {
1546          FIXME("Could not allocate for type %08x\n", allocinfo->dwFlags);
1547          return E_NOTIMPL;
1548     }
1549
1550     if (i >= allocinfo->MinBuffers)
1551     {
1552         hr = S_OK;
1553         *numbuffers = i;
1554     }
1555     else
1556     {
1557         ERR("Allocation failed\n");
1558         for (--i; i >= 0; --i)
1559         {
1560             IDirect3DSurface9_Release(surface[i]);
1561         }
1562         *numbuffers = 0;
1563     }
1564     return hr;
1565 }
1566
1567 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
1568 {
1569     VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1570
1571     FIXME("(%p/%p)->(...) stub\n", iface, This);
1572     return E_NOTIMPL;
1573 }
1574
1575 static const IVMRSurfaceAllocatorNotify9Vtbl IVMRSurfaceAllocatorNotify9_Vtbl =
1576 {
1577     VMR9SurfaceAllocatorNotify_QueryInterface,
1578     VMR9SurfaceAllocatorNotify_AddRef,
1579     VMR9SurfaceAllocatorNotify_Release,
1580     VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1581     VMR9SurfaceAllocatorNotify_SetD3DDevice,
1582     VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
1583     VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
1584     VMR9SurfaceAllocatorNotify_NotifyEvent
1585 };
1586
1587 HRESULT VMR9Impl_create(IUnknown * outer_unk, LPVOID * ppv)
1588 {
1589     HRESULT hr;
1590     VMR9Impl * pVMR9;
1591
1592     TRACE("(%p, %p)\n", outer_unk, ppv);
1593
1594     *ppv = NULL;
1595
1596     pVMR9 = CoTaskMemAlloc(sizeof(VMR9Impl));
1597
1598     pVMR9->hD3d9 = LoadLibraryA("d3d9.dll");
1599     if (!pVMR9->hD3d9 )
1600     {
1601         WARN("Could not load d3d9.dll\n");
1602         CoTaskMemFree(pVMR9);
1603         return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
1604     }
1605
1606     pVMR9->outer_unk = outer_unk;
1607     pVMR9->bUnkOuterValid = FALSE;
1608     pVMR9->bAggregatable = FALSE;
1609     pVMR9->IUnknown_inner.lpVtbl = &IInner_VTable;
1610     pVMR9->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
1611
1612     pVMR9->mode = 0;
1613     pVMR9->allocator_d3d9_dev = NULL;
1614     pVMR9->allocator_mon= NULL;
1615     pVMR9->num_surfaces = pVMR9->cur_surface = 0;
1616     pVMR9->allocator = NULL;
1617     pVMR9->presenter = NULL;
1618     pVMR9->hWndClippingWindow = NULL;
1619     pVMR9->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
1620     pVMR9->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
1621     pVMR9->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &IVMRSurfaceAllocatorNotify9_Vtbl;
1622
1623     hr = BaseRenderer_Init(&pVMR9->renderer, &VMR9_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9, (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
1624     if (FAILED(hr))
1625         goto fail;
1626
1627     hr = BaseControlWindow_Init(&pVMR9->baseControlWindow, &IVideoWindow_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable);
1628     if (FAILED(hr))
1629         goto fail;
1630
1631     hr = BaseControlVideo_Init(&pVMR9->baseControlVideo, &IBasicVideo_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable);
1632     if (FAILED(hr))
1633         goto fail;
1634
1635     *ppv = (LPVOID)pVMR9;
1636     ZeroMemory(&pVMR9->source_rect, sizeof(RECT));
1637     ZeroMemory(&pVMR9->target_rect, sizeof(RECT));
1638     TRACE("Created at %p\n", pVMR9);
1639     return hr;
1640
1641 fail:
1642     BaseRendererImpl_Release(&pVMR9->renderer.filter.IBaseFilter_iface);
1643     CloseHandle(pVMR9->hD3d9);
1644     CoTaskMemFree(pVMR9);
1645     return hr;
1646 }
1647
1648
1649
1650 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, LPVOID * ppv)
1651 {
1652     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1653     TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
1654
1655     *ppv = NULL;
1656
1657     if (IsEqualIID(riid, &IID_IUnknown))
1658         *ppv = (LPVOID)&(This->IVMRImagePresenter9_iface);
1659     else if (IsEqualIID(riid, &IID_IVMRImagePresenter9))
1660         *ppv = &This->IVMRImagePresenter9_iface;
1661     else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorEx9))
1662         *ppv = &This->IVMRSurfaceAllocatorEx9_iface;
1663
1664     if (*ppv)
1665     {
1666         IUnknown_AddRef((IUnknown *)(*ppv));
1667         return S_OK;
1668     }
1669
1670     FIXME("No interface for %s\n", debugstr_guid(riid));
1671
1672     return E_NOINTERFACE;
1673 }
1674
1675 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
1676 {
1677     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1678     ULONG refCount = InterlockedIncrement(&This->refCount);
1679
1680     TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
1681
1682     return refCount;
1683 }
1684
1685 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
1686 {
1687     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1688     ULONG refCount = InterlockedDecrement(&This->refCount);
1689
1690     TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
1691
1692     if (!refCount)
1693     {
1694         int i;
1695         TRACE("Destroying\n");
1696         CloseHandle(This->ack);
1697         IDirect3D9_Release(This->d3d9_ptr);
1698
1699         TRACE("Number of surfaces: %u\n", This->num_surfaces);
1700         for (i = 0; i < This->num_surfaces; ++i)
1701         {
1702             IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
1703             TRACE("Releasing surface %p\n", surface);
1704             if (surface)
1705                 IDirect3DSurface9_Release(surface);
1706         }
1707
1708         CoTaskMemFree(This->d3d9_surfaces);
1709         This->d3d9_surfaces = NULL;
1710         This->num_surfaces = 0;
1711         if (This->d3d9_vertex)
1712         {
1713             IDirect3DVertexBuffer9_Release(This->d3d9_vertex);
1714             This->d3d9_vertex = NULL;
1715         }
1716         CoTaskMemFree(This);
1717         return 0;
1718     }
1719     return refCount;
1720 }
1721
1722 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
1723 {
1724     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1725
1726     TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
1727     return S_OK;
1728 }
1729
1730 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
1731 {
1732     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1733
1734     TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
1735     return S_OK;
1736 }
1737
1738 #define USED_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)
1739 struct VERTEX { float x, y, z, rhw, u, v; };
1740
1741 static HRESULT VMR9_ImagePresenter_PresentTexture(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
1742 {
1743     IDirect3DTexture9 *texture = NULL;
1744     HRESULT hr;
1745
1746     hr = IDirect3DDevice9_SetFVF(This->d3d9_dev, USED_FVF);
1747     if (FAILED(hr))
1748     {
1749         FIXME("SetFVF: %08x\n", hr);
1750         return hr;
1751     }
1752
1753     hr = IDirect3DDevice9_SetStreamSource(This->d3d9_dev, 0, This->d3d9_vertex, 0, sizeof(struct VERTEX));
1754     if (FAILED(hr))
1755     {
1756         FIXME("SetStreamSource: %08x\n", hr);
1757         return hr;
1758     }
1759
1760     hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **) &texture);
1761     if (FAILED(hr))
1762     {
1763         FIXME("IDirect3DSurface9_GetContainer failed\n");
1764         return hr;
1765     }
1766     hr = IDirect3DDevice9_SetTexture(This->d3d9_dev, 0, (IDirect3DBaseTexture9 *)texture);
1767     IDirect3DTexture9_Release(texture);
1768     if (FAILED(hr))
1769     {
1770         FIXME("SetTexture: %08x\n", hr);
1771         return hr;
1772     }
1773
1774     hr = IDirect3DDevice9_DrawPrimitive(This->d3d9_dev, D3DPT_TRIANGLESTRIP, 0, 2);
1775     if (FAILED(hr))
1776     {
1777         FIXME("DrawPrimitive: %08x\n", hr);
1778         return hr;
1779     }
1780
1781     return S_OK;
1782 }
1783
1784 static HRESULT VMR9_ImagePresenter_PresentOffscreenSurface(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
1785 {
1786     HRESULT hr;
1787     IDirect3DSurface9 *target = NULL;
1788     RECT target_rect;
1789
1790     hr = IDirect3DDevice9_GetBackBuffer(This->d3d9_dev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &target);
1791     if (FAILED(hr))
1792     {
1793         ERR("IDirect3DDevice9_GetBackBuffer -- %08x\n", hr);
1794         return hr;
1795     }
1796
1797     target_rect = This->pVMR9->target_rect;
1798     target_rect.right -= target_rect.left;
1799     target_rect.bottom -= target_rect.top;
1800     target_rect.left = target_rect.top = 0;
1801
1802     /* Flip */
1803     target_rect.top = target_rect.bottom;
1804     target_rect.bottom = 0;
1805
1806     hr = IDirect3DDevice9_StretchRect(This->d3d9_dev, surface, &This->pVMR9->source_rect, target, &target_rect, D3DTEXF_LINEAR);
1807     if (FAILED(hr))
1808         ERR("IDirect3DDevice9_StretchRect -- %08x\n", hr);
1809     IDirect3DSurface9_Release(target);
1810
1811     return hr;
1812 }
1813
1814 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface, DWORD_PTR id, VMR9PresentationInfo *info)
1815 {
1816     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1817     HRESULT hr;
1818     RECT output;
1819     BOOL render = FALSE;
1820
1821     TRACE("(%p/%p/%p)->(...) stub\n", iface, This, This->pVMR9);
1822     GetWindowRect(This->pVMR9->baseControlWindow.baseWindow.hWnd, &output);
1823     TRACE("Output rectangle: starting at %dx%d, up to point %dx%d\n", output.left, output.top, output.right, output.bottom);
1824
1825     /* This might happen if we don't have active focus (eg on a different virtual desktop) */
1826     if (!This->d3d9_dev)
1827         return S_OK;
1828
1829     /* Display image here */
1830     hr = IDirect3DDevice9_Clear(This->d3d9_dev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
1831     if (FAILED(hr))
1832         FIXME("hr: %08x\n", hr);
1833     hr = IDirect3DDevice9_BeginScene(This->d3d9_dev);
1834     if (SUCCEEDED(hr))
1835     {
1836         if (This->d3d9_vertex)
1837             hr = VMR9_ImagePresenter_PresentTexture(This, info->lpSurf);
1838         else
1839             hr = VMR9_ImagePresenter_PresentOffscreenSurface(This, info->lpSurf);
1840         render = SUCCEEDED(hr);
1841     }
1842     else
1843         FIXME("BeginScene: %08x\n", hr);
1844     hr = IDirect3DDevice9_EndScene(This->d3d9_dev);
1845     if (render && SUCCEEDED(hr))
1846     {
1847         hr = IDirect3DDevice9_Present(This->d3d9_dev, NULL, NULL, This->pVMR9->baseControlWindow.baseWindow.hWnd, NULL);
1848         if (FAILED(hr))
1849             FIXME("Presenting image: %08x\n", hr);
1850     }
1851
1852     return S_OK;
1853 }
1854
1855 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
1856 {
1857     VMR9_ImagePresenter_QueryInterface,
1858     VMR9_ImagePresenter_AddRef,
1859     VMR9_ImagePresenter_Release,
1860     VMR9_ImagePresenter_StartPresenting,
1861     VMR9_ImagePresenter_StopPresenting,
1862     VMR9_ImagePresenter_PresentImage
1863 };
1864
1865 static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocatorEx9 *iface, REFIID riid, LPVOID * ppv)
1866 {
1867     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
1868
1869     return VMR9_ImagePresenter_QueryInterface(&This->IVMRImagePresenter9_iface, riid, ppv);
1870 }
1871
1872 static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocatorEx9 *iface)
1873 {
1874     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
1875
1876     return VMR9_ImagePresenter_AddRef(&This->IVMRImagePresenter9_iface);
1877 }
1878
1879 static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocatorEx9 *iface)
1880 {
1881     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
1882
1883     return VMR9_ImagePresenter_Release(&This->IVMRImagePresenter9_iface);
1884 }
1885
1886 static HRESULT VMR9_SurfaceAllocator_SetAllocationSettings(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *allocinfo)
1887 {
1888     D3DCAPS9 caps;
1889     UINT width, height;
1890     HRESULT hr;
1891
1892     if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface))
1893         /* Only needed for texture surfaces */
1894         return S_OK;
1895
1896     hr = IDirect3DDevice9_GetDeviceCaps(This->d3d9_dev, &caps);
1897     if (FAILED(hr))
1898         return hr;
1899
1900     if (!(caps.TextureCaps & D3DPTEXTURECAPS_POW2) || (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY))
1901     {
1902         width = allocinfo->dwWidth;
1903         height = allocinfo->dwHeight;
1904     }
1905     else
1906     {
1907         width = height = 1;
1908         while (width < allocinfo->dwWidth)
1909             width *= 2;
1910
1911         while (height < allocinfo->dwHeight)
1912             height *= 2;
1913         FIXME("NPOW2 support missing, not using proper surfaces!\n");
1914     }
1915
1916     if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
1917     {
1918         if (height > width)
1919             width = height;
1920         else
1921             height = width;
1922         FIXME("Square texture support required..\n");
1923     }
1924
1925     hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF, allocinfo->Pool, &This->d3d9_vertex, NULL);
1926     if (FAILED(hr))
1927     {
1928         ERR("Couldn't create vertex buffer: %08x\n", hr);
1929         return hr;
1930     }
1931
1932     This->reset = TRUE;
1933     allocinfo->dwHeight = height;
1934     allocinfo->dwWidth = width;
1935
1936     return hr;
1937 }
1938
1939 static DWORD WINAPI MessageLoop(LPVOID lpParameter)
1940 {
1941     MSG msg;
1942     BOOL fGotMessage;
1943     VMR9DefaultAllocatorPresenterImpl *This = lpParameter;
1944
1945     TRACE("Starting message loop\n");
1946
1947     if (FAILED(BaseWindowImpl_PrepareWindow(&This->pVMR9->baseControlWindow.baseWindow)))
1948     {
1949         FIXME("Failed to prepare window\n");
1950         return FALSE;
1951     }
1952
1953     SetEvent(This->ack);
1954     while ((fGotMessage = GetMessageW(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1)
1955     {
1956         TranslateMessage(&msg);
1957         DispatchMessageW(&msg);
1958     }
1959
1960     TRACE("End of message loop\n");
1961
1962     return 0;
1963 }
1964
1965 static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
1966 {
1967     UINT d3d9_adapter;
1968     HMONITOR mon;
1969
1970     mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
1971     if (!mon)
1972         d3d9_adapter = 0;
1973     else
1974     {
1975         for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
1976         {
1977             if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
1978                 break;
1979         }
1980         if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
1981             d3d9_adapter = 0;
1982     }
1983     if (mon_out)
1984         *mon_out = mon;
1985     return d3d9_adapter;
1986 }
1987
1988 static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *info, DWORD *numbuffers)
1989 {
1990     D3DPRESENT_PARAMETERS d3dpp;
1991     DWORD d3d9_adapter;
1992     HRESULT hr;
1993
1994     TRACE("(%p)->()\n", This);
1995
1996     This->hWndThread = CreateThread(NULL, 0, MessageLoop, This, 0, &This->tid);
1997     if (!This->hWndThread)
1998         return FALSE;
1999
2000     WaitForSingleObject(This->ack, INFINITE);
2001
2002     if (!This->pVMR9->baseControlWindow.baseWindow.hWnd) return FALSE;
2003
2004     /* Obtain a monitor and d3d9 device */
2005     d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon);
2006
2007     /* Now try to create the d3d9 device */
2008     ZeroMemory(&d3dpp, sizeof(d3dpp));
2009     d3dpp.Windowed = TRUE;
2010     d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd;
2011     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2012     d3dpp.BackBufferHeight = This->pVMR9->target_rect.bottom - This->pVMR9->target_rect.top;
2013     d3dpp.BackBufferWidth = This->pVMR9->target_rect.right - This->pVMR9->target_rect.left;
2014
2015     hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
2016     if (FAILED(hr))
2017     {
2018         ERR("Could not create device: %08x\n", hr);
2019         BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
2020         return FALSE;
2021     }
2022     IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2023
2024     This->d3d9_surfaces = CoTaskMemAlloc(*numbuffers * sizeof(IDirect3DSurface9 *));
2025     ZeroMemory(This->d3d9_surfaces, *numbuffers * sizeof(IDirect3DSurface9 *));
2026
2027     hr = VMR9_SurfaceAllocator_SetAllocationSettings(This, info);
2028     if (FAILED(hr))
2029         ERR("Setting allocation settings failed: %08x\n", hr);
2030
2031     if (SUCCEEDED(hr))
2032     {
2033         hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, info, numbuffers, This->d3d9_surfaces);
2034         if (FAILED(hr))
2035             ERR("Allocating surfaces failed: %08x\n", hr);
2036     }
2037
2038     if (FAILED(hr))
2039     {
2040         IVMRSurfaceAllocatorEx9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
2041         BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
2042         return FALSE;
2043     }
2044
2045     This->num_surfaces = *numbuffers;
2046
2047     return TRUE;
2048 }
2049
2050 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, VMR9AllocationInfo *allocinfo, DWORD *numbuffers)
2051 {
2052     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2053
2054     if (This->pVMR9->mode != VMR9Mode_Windowed && !This->pVMR9->hWndClippingWindow)
2055     {
2056         ERR("No window set\n");
2057         return VFW_E_WRONG_STATE;
2058     }
2059
2060     This->info = *allocinfo;
2061
2062     if (!CreateRenderingWindow(This, allocinfo, numbuffers))
2063     {
2064         ERR("Failed to create rendering window, expect no output!\n");
2065         return VFW_E_WRONG_STATE;
2066     }
2067
2068     return S_OK;
2069 }
2070
2071 static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id)
2072 {
2073     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2074
2075     if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
2076     {
2077         return S_OK;
2078     }
2079
2080     SendMessageW(This->pVMR9->baseControlWindow.baseWindow.hWnd, WM_CLOSE, 0, 0);
2081     PostThreadMessageW(This->tid, WM_QUIT, 0, 0);
2082     WaitForSingleObject(This->hWndThread, INFINITE);
2083     This->hWndThread = NULL;
2084     BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
2085
2086     return S_OK;
2087 }
2088
2089 /* Recreate all surfaces (If allocated as D3DPOOL_DEFAULT) and survive! */
2090 static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(VMR9DefaultAllocatorPresenterImpl *This)
2091 {
2092     struct VERTEX t_vert[4];
2093     UINT width, height;
2094     INT i;
2095     void *bits = NULL;
2096     D3DPRESENT_PARAMETERS d3dpp;
2097     HRESULT hr;
2098
2099     if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
2100     {
2101         ERR("No window\n");
2102         return E_FAIL;
2103     }
2104
2105     if (!This->d3d9_surfaces || !This->reset)
2106         return S_OK;
2107
2108     This->reset = FALSE;
2109     TRACE("RESETTING\n");
2110     if (This->d3d9_vertex)
2111     {
2112         IDirect3DVertexBuffer9_Release(This->d3d9_vertex);
2113         This->d3d9_vertex = NULL;
2114     }
2115
2116     for (i = 0; i < This->num_surfaces; ++i)
2117     {
2118         IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2119         TRACE("Releasing surface %p\n", surface);
2120         if (surface)
2121             IDirect3DSurface9_Release(surface);
2122     }
2123     ZeroMemory(This->d3d9_surfaces, sizeof(IDirect3DSurface9 *) * This->num_surfaces);
2124
2125     /* Now try to create the d3d9 device */
2126     ZeroMemory(&d3dpp, sizeof(d3dpp));
2127     d3dpp.Windowed = TRUE;
2128     d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd;
2129     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2130
2131     if (This->d3d9_dev)
2132         IDirect3DDevice9_Release(This->d3d9_dev);
2133     This->d3d9_dev = NULL;
2134     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);
2135     if (FAILED(hr))
2136     {
2137         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);
2138         if (FAILED(hr))
2139         {
2140             ERR("--> Creating device: %08x\n", hr);
2141             return S_OK;
2142         }
2143     }
2144     IVMRSurfaceAllocatorNotify9_ChangeD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2145
2146     IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, &This->info, &This->num_surfaces, This->d3d9_surfaces);
2147
2148     This->reset = FALSE;
2149
2150     if (!(This->info.dwFlags & VMR9AllocFlag_TextureSurface))
2151         return S_OK;
2152
2153     hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF,
2154                                              This->info.Pool, &This->d3d9_vertex, NULL);
2155
2156     width = This->info.dwWidth;
2157     height = This->info.dwHeight;
2158
2159     for (i = 0; i < sizeof(t_vert) / sizeof(t_vert[0]); ++i)
2160     {
2161         if (i % 2)
2162         {
2163             t_vert[i].x = (float)This->pVMR9->target_rect.right - (float)This->pVMR9->target_rect.left - 0.5f;
2164             t_vert[i].u = (float)This->pVMR9->source_rect.right / (float)width;
2165         }
2166         else
2167         {
2168             t_vert[i].x = -0.5f;
2169             t_vert[i].u = (float)This->pVMR9->source_rect.left / (float)width;
2170         }
2171
2172         if (i % 4 < 2)
2173         {
2174             t_vert[i].y = -0.5f;
2175             t_vert[i].v = (float)This->pVMR9->source_rect.bottom / (float)height;
2176         }
2177         else
2178         {
2179             t_vert[i].y = (float)This->pVMR9->target_rect.bottom - (float)This->pVMR9->target_rect.top - 0.5f;
2180             t_vert[i].v = (float)This->pVMR9->source_rect.top / (float)height;
2181         }
2182         t_vert[i].z = 0.0f;
2183         t_vert[i].rhw = 1.0f;
2184     }
2185
2186     FIXME("Vertex rectangle:\n");
2187     FIXME("X, Y: %f, %f\n", t_vert[0].x, t_vert[0].y);
2188     FIXME("X, Y: %f, %f\n", t_vert[3].x, t_vert[3].y);
2189     FIXME("TOP, LEFT: %f, %f\n", t_vert[0].u, t_vert[0].v);
2190     FIXME("DOWN, BOTTOM: %f, %f\n", t_vert[3].u, t_vert[3].v);
2191
2192     IDirect3DVertexBuffer9_Lock(This->d3d9_vertex, 0, sizeof(t_vert), &bits, 0);
2193     memcpy(bits, t_vert, sizeof(t_vert));
2194     IDirect3DVertexBuffer9_Unlock(This->d3d9_vertex);
2195
2196     return S_OK;
2197 }
2198
2199 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
2200 {
2201     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2202
2203     /* Update everything first, this is needed because the surface might be destroyed in the reset */
2204     if (!This->d3d9_dev)
2205     {
2206         TRACE("Device has left me!\n");
2207         return E_FAIL;
2208     }
2209
2210     VMR9_SurfaceAllocator_UpdateDeviceReset(This);
2211
2212     if (surfaceindex >= This->num_surfaces)
2213     {
2214         ERR("surfaceindex is greater than num_surfaces\n");
2215         return E_FAIL;
2216     }
2217     *surface = This->d3d9_surfaces[surfaceindex];
2218     IDirect3DSurface9_AddRef(*surface);
2219
2220     return S_OK;
2221 }
2222
2223 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocatorEx9 *iface, IVMRSurfaceAllocatorNotify9 *allocnotify)
2224 {
2225     VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2226
2227     TRACE("(%p/%p)->(...)\n", iface, This);
2228
2229     /* No AddRef taken here or the base VMR9 filter would never be destroied */
2230     This->SurfaceAllocatorNotify = allocnotify;
2231     return S_OK;
2232 }
2233
2234 static const IVMRSurfaceAllocatorEx9Vtbl VMR9_SurfaceAllocator =
2235 {
2236     VMR9_SurfaceAllocator_QueryInterface,
2237     VMR9_SurfaceAllocator_AddRef,
2238     VMR9_SurfaceAllocator_Release,
2239     VMR9_SurfaceAllocator_InitializeDevice,
2240     VMR9_SurfaceAllocator_TerminateDevice,
2241     VMR9_SurfaceAllocator_GetSurface,
2242     VMR9_SurfaceAllocator_AdviseNotify,
2243     NULL /* This isn't the SurfaceAllocatorEx type yet, working on it */
2244 };
2245
2246 static IDirect3D9 *init_d3d9(HMODULE d3d9_handle)
2247 {
2248     IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion);
2249
2250     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
2251     if (!d3d9_create) return NULL;
2252
2253     return d3d9_create(D3D_SDK_VERSION);
2254 }
2255
2256 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID * ppv)
2257 {
2258     HRESULT hr = S_OK;
2259     int i;
2260     VMR9DefaultAllocatorPresenterImpl* This;
2261
2262     This = CoTaskMemAlloc(sizeof(VMR9DefaultAllocatorPresenterImpl));
2263     if (!This)
2264         return E_OUTOFMEMORY;
2265
2266     This->d3d9_ptr = init_d3d9(parent->hD3d9);
2267     if (!This->d3d9_ptr)
2268     {
2269         WARN("Could not initialize d3d9.dll\n");
2270         CoTaskMemFree(This);
2271         return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2272     }
2273
2274     i = 0;
2275     do
2276     {
2277         D3DDISPLAYMODE mode;
2278
2279         hr = IDirect3D9_EnumAdapterModes(This->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode);
2280     } while (FAILED(hr));
2281     if (FAILED(hr))
2282         ERR("HR: %08x\n", hr);
2283     if (hr == D3DERR_NOTAVAILABLE)
2284     {
2285         ERR("Format not supported\n");
2286         IDirect3D9_Release(This->d3d9_ptr);
2287         CoTaskMemFree(This);
2288         return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2289     }
2290
2291     This->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
2292     This->IVMRSurfaceAllocatorEx9_iface.lpVtbl = &VMR9_SurfaceAllocator;
2293
2294     This->refCount = 1;
2295     This->pVMR9 = parent;
2296     This->d3d9_surfaces = NULL;
2297     This->d3d9_dev = NULL;
2298     This->hMon = 0;
2299     This->d3d9_vertex = NULL;
2300     This->num_surfaces = 0;
2301     This->hWndThread = NULL;
2302     This->ack = CreateEventW(NULL, 0, 0, NULL);
2303     This->SurfaceAllocatorNotify = NULL;
2304     This->reset = FALSE;
2305
2306     *ppv = This;
2307     return S_OK;
2308 }