[CABMAN]
[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 "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 DWORD 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 for ( ; i > 0; --i) IDirect3DSurface9_Release(surface[i - 1]);
1558 *numbuffers = 0;
1559 }
1560 return hr;
1561 }
1562
1563 static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2)
1564 {
1565 VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
1566
1567 FIXME("(%p/%p)->(...) stub\n", iface, This);
1568 return E_NOTIMPL;
1569 }
1570
1571 static const IVMRSurfaceAllocatorNotify9Vtbl IVMRSurfaceAllocatorNotify9_Vtbl =
1572 {
1573 VMR9SurfaceAllocatorNotify_QueryInterface,
1574 VMR9SurfaceAllocatorNotify_AddRef,
1575 VMR9SurfaceAllocatorNotify_Release,
1576 VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator,
1577 VMR9SurfaceAllocatorNotify_SetD3DDevice,
1578 VMR9SurfaceAllocatorNotify_ChangeD3DDevice,
1579 VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper,
1580 VMR9SurfaceAllocatorNotify_NotifyEvent
1581 };
1582
1583 HRESULT VMR9Impl_create(IUnknown * outer_unk, LPVOID * ppv)
1584 {
1585 HRESULT hr;
1586 VMR9Impl * pVMR9;
1587
1588 TRACE("(%p, %p)\n", outer_unk, ppv);
1589
1590 *ppv = NULL;
1591
1592 pVMR9 = CoTaskMemAlloc(sizeof(VMR9Impl));
1593
1594 pVMR9->hD3d9 = LoadLibraryA("d3d9.dll");
1595 if (!pVMR9->hD3d9 )
1596 {
1597 WARN("Could not load d3d9.dll\n");
1598 CoTaskMemFree(pVMR9);
1599 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
1600 }
1601
1602 pVMR9->outer_unk = outer_unk;
1603 pVMR9->bUnkOuterValid = FALSE;
1604 pVMR9->bAggregatable = FALSE;
1605 pVMR9->IUnknown_inner.lpVtbl = &IInner_VTable;
1606 pVMR9->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
1607
1608 pVMR9->mode = 0;
1609 pVMR9->allocator_d3d9_dev = NULL;
1610 pVMR9->allocator_mon= NULL;
1611 pVMR9->num_surfaces = pVMR9->cur_surface = 0;
1612 pVMR9->allocator = NULL;
1613 pVMR9->presenter = NULL;
1614 pVMR9->hWndClippingWindow = NULL;
1615 pVMR9->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl;
1616 pVMR9->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
1617 pVMR9->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &IVMRSurfaceAllocatorNotify9_Vtbl;
1618
1619 hr = BaseRenderer_Init(&pVMR9->renderer, &VMR9_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9, (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
1620 if (FAILED(hr))
1621 goto fail;
1622
1623 hr = BaseControlWindow_Init(&pVMR9->baseControlWindow, &IVideoWindow_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable);
1624 if (FAILED(hr))
1625 goto fail;
1626
1627 hr = BaseControlVideo_Init(&pVMR9->baseControlVideo, &IBasicVideo_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable);
1628 if (FAILED(hr))
1629 goto fail;
1630
1631 *ppv = (LPVOID)pVMR9;
1632 ZeroMemory(&pVMR9->source_rect, sizeof(RECT));
1633 ZeroMemory(&pVMR9->target_rect, sizeof(RECT));
1634 TRACE("Created at %p\n", pVMR9);
1635 return hr;
1636
1637 fail:
1638 BaseRendererImpl_Release(&pVMR9->renderer.filter.IBaseFilter_iface);
1639 CloseHandle(pVMR9->hD3d9);
1640 CoTaskMemFree(pVMR9);
1641 return hr;
1642 }
1643
1644
1645
1646 static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, LPVOID * ppv)
1647 {
1648 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1649 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
1650
1651 *ppv = NULL;
1652
1653 if (IsEqualIID(riid, &IID_IUnknown))
1654 *ppv = (LPVOID)&(This->IVMRImagePresenter9_iface);
1655 else if (IsEqualIID(riid, &IID_IVMRImagePresenter9))
1656 *ppv = &This->IVMRImagePresenter9_iface;
1657 else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorEx9))
1658 *ppv = &This->IVMRSurfaceAllocatorEx9_iface;
1659
1660 if (*ppv)
1661 {
1662 IUnknown_AddRef((IUnknown *)(*ppv));
1663 return S_OK;
1664 }
1665
1666 FIXME("No interface for %s\n", debugstr_guid(riid));
1667
1668 return E_NOINTERFACE;
1669 }
1670
1671 static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface)
1672 {
1673 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1674 ULONG refCount = InterlockedIncrement(&This->refCount);
1675
1676 TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
1677
1678 return refCount;
1679 }
1680
1681 static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface)
1682 {
1683 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1684 ULONG refCount = InterlockedDecrement(&This->refCount);
1685
1686 TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
1687
1688 if (!refCount)
1689 {
1690 DWORD i;
1691 TRACE("Destroying\n");
1692 CloseHandle(This->ack);
1693 IDirect3D9_Release(This->d3d9_ptr);
1694
1695 TRACE("Number of surfaces: %u\n", This->num_surfaces);
1696 for (i = 0; i < This->num_surfaces; ++i)
1697 {
1698 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
1699 TRACE("Releasing surface %p\n", surface);
1700 if (surface)
1701 IDirect3DSurface9_Release(surface);
1702 }
1703
1704 CoTaskMemFree(This->d3d9_surfaces);
1705 This->d3d9_surfaces = NULL;
1706 This->num_surfaces = 0;
1707 if (This->d3d9_vertex)
1708 {
1709 IDirect3DVertexBuffer9_Release(This->d3d9_vertex);
1710 This->d3d9_vertex = NULL;
1711 }
1712 CoTaskMemFree(This);
1713 return 0;
1714 }
1715 return refCount;
1716 }
1717
1718 static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
1719 {
1720 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1721
1722 TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
1723 return S_OK;
1724 }
1725
1726 static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id)
1727 {
1728 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1729
1730 TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9);
1731 return S_OK;
1732 }
1733
1734 #define USED_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)
1735 struct VERTEX { float x, y, z, rhw, u, v; };
1736
1737 static HRESULT VMR9_ImagePresenter_PresentTexture(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
1738 {
1739 IDirect3DTexture9 *texture = NULL;
1740 HRESULT hr;
1741
1742 hr = IDirect3DDevice9_SetFVF(This->d3d9_dev, USED_FVF);
1743 if (FAILED(hr))
1744 {
1745 FIXME("SetFVF: %08x\n", hr);
1746 return hr;
1747 }
1748
1749 hr = IDirect3DDevice9_SetStreamSource(This->d3d9_dev, 0, This->d3d9_vertex, 0, sizeof(struct VERTEX));
1750 if (FAILED(hr))
1751 {
1752 FIXME("SetStreamSource: %08x\n", hr);
1753 return hr;
1754 }
1755
1756 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **) &texture);
1757 if (FAILED(hr))
1758 {
1759 FIXME("IDirect3DSurface9_GetContainer failed\n");
1760 return hr;
1761 }
1762 hr = IDirect3DDevice9_SetTexture(This->d3d9_dev, 0, (IDirect3DBaseTexture9 *)texture);
1763 IDirect3DTexture9_Release(texture);
1764 if (FAILED(hr))
1765 {
1766 FIXME("SetTexture: %08x\n", hr);
1767 return hr;
1768 }
1769
1770 hr = IDirect3DDevice9_DrawPrimitive(This->d3d9_dev, D3DPT_TRIANGLESTRIP, 0, 2);
1771 if (FAILED(hr))
1772 {
1773 FIXME("DrawPrimitive: %08x\n", hr);
1774 return hr;
1775 }
1776
1777 return S_OK;
1778 }
1779
1780 static HRESULT VMR9_ImagePresenter_PresentOffscreenSurface(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface)
1781 {
1782 HRESULT hr;
1783 IDirect3DSurface9 *target = NULL;
1784 RECT target_rect;
1785
1786 hr = IDirect3DDevice9_GetBackBuffer(This->d3d9_dev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &target);
1787 if (FAILED(hr))
1788 {
1789 ERR("IDirect3DDevice9_GetBackBuffer -- %08x\n", hr);
1790 return hr;
1791 }
1792
1793 target_rect = This->pVMR9->target_rect;
1794 target_rect.right -= target_rect.left;
1795 target_rect.bottom -= target_rect.top;
1796 target_rect.left = target_rect.top = 0;
1797
1798 /* Flip */
1799 target_rect.top = target_rect.bottom;
1800 target_rect.bottom = 0;
1801
1802 hr = IDirect3DDevice9_StretchRect(This->d3d9_dev, surface, &This->pVMR9->source_rect, target, &target_rect, D3DTEXF_LINEAR);
1803 if (FAILED(hr))
1804 ERR("IDirect3DDevice9_StretchRect -- %08x\n", hr);
1805 IDirect3DSurface9_Release(target);
1806
1807 return hr;
1808 }
1809
1810 static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface, DWORD_PTR id, VMR9PresentationInfo *info)
1811 {
1812 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface);
1813 HRESULT hr;
1814 RECT output;
1815 BOOL render = FALSE;
1816
1817 TRACE("(%p/%p/%p)->(...) stub\n", iface, This, This->pVMR9);
1818 GetWindowRect(This->pVMR9->baseControlWindow.baseWindow.hWnd, &output);
1819 TRACE("Output rectangle: starting at %dx%d, up to point %dx%d\n", output.left, output.top, output.right, output.bottom);
1820
1821 /* This might happen if we don't have active focus (eg on a different virtual desktop) */
1822 if (!This->d3d9_dev)
1823 return S_OK;
1824
1825 /* Display image here */
1826 hr = IDirect3DDevice9_Clear(This->d3d9_dev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
1827 if (FAILED(hr))
1828 FIXME("hr: %08x\n", hr);
1829 hr = IDirect3DDevice9_BeginScene(This->d3d9_dev);
1830 if (SUCCEEDED(hr))
1831 {
1832 if (This->d3d9_vertex)
1833 hr = VMR9_ImagePresenter_PresentTexture(This, info->lpSurf);
1834 else
1835 hr = VMR9_ImagePresenter_PresentOffscreenSurface(This, info->lpSurf);
1836 render = SUCCEEDED(hr);
1837 }
1838 else
1839 FIXME("BeginScene: %08x\n", hr);
1840 hr = IDirect3DDevice9_EndScene(This->d3d9_dev);
1841 if (render && SUCCEEDED(hr))
1842 {
1843 hr = IDirect3DDevice9_Present(This->d3d9_dev, NULL, NULL, This->pVMR9->baseControlWindow.baseWindow.hWnd, NULL);
1844 if (FAILED(hr))
1845 FIXME("Presenting image: %08x\n", hr);
1846 }
1847
1848 return S_OK;
1849 }
1850
1851 static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter =
1852 {
1853 VMR9_ImagePresenter_QueryInterface,
1854 VMR9_ImagePresenter_AddRef,
1855 VMR9_ImagePresenter_Release,
1856 VMR9_ImagePresenter_StartPresenting,
1857 VMR9_ImagePresenter_StopPresenting,
1858 VMR9_ImagePresenter_PresentImage
1859 };
1860
1861 static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocatorEx9 *iface, REFIID riid, LPVOID * ppv)
1862 {
1863 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
1864
1865 return VMR9_ImagePresenter_QueryInterface(&This->IVMRImagePresenter9_iface, riid, ppv);
1866 }
1867
1868 static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocatorEx9 *iface)
1869 {
1870 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
1871
1872 return VMR9_ImagePresenter_AddRef(&This->IVMRImagePresenter9_iface);
1873 }
1874
1875 static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocatorEx9 *iface)
1876 {
1877 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
1878
1879 return VMR9_ImagePresenter_Release(&This->IVMRImagePresenter9_iface);
1880 }
1881
1882 static HRESULT VMR9_SurfaceAllocator_SetAllocationSettings(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *allocinfo)
1883 {
1884 D3DCAPS9 caps;
1885 UINT width, height;
1886 HRESULT hr;
1887
1888 if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface))
1889 /* Only needed for texture surfaces */
1890 return S_OK;
1891
1892 hr = IDirect3DDevice9_GetDeviceCaps(This->d3d9_dev, &caps);
1893 if (FAILED(hr))
1894 return hr;
1895
1896 if (!(caps.TextureCaps & D3DPTEXTURECAPS_POW2) || (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY))
1897 {
1898 width = allocinfo->dwWidth;
1899 height = allocinfo->dwHeight;
1900 }
1901 else
1902 {
1903 width = height = 1;
1904 while (width < allocinfo->dwWidth)
1905 width *= 2;
1906
1907 while (height < allocinfo->dwHeight)
1908 height *= 2;
1909 FIXME("NPOW2 support missing, not using proper surfaces!\n");
1910 }
1911
1912 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
1913 {
1914 if (height > width)
1915 width = height;
1916 else
1917 height = width;
1918 FIXME("Square texture support required..\n");
1919 }
1920
1921 hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF, allocinfo->Pool, &This->d3d9_vertex, NULL);
1922 if (FAILED(hr))
1923 {
1924 ERR("Couldn't create vertex buffer: %08x\n", hr);
1925 return hr;
1926 }
1927
1928 This->reset = TRUE;
1929 allocinfo->dwHeight = height;
1930 allocinfo->dwWidth = width;
1931
1932 return hr;
1933 }
1934
1935 static DWORD WINAPI MessageLoop(LPVOID lpParameter)
1936 {
1937 MSG msg;
1938 BOOL fGotMessage;
1939 VMR9DefaultAllocatorPresenterImpl *This = lpParameter;
1940
1941 TRACE("Starting message loop\n");
1942
1943 if (FAILED(BaseWindowImpl_PrepareWindow(&This->pVMR9->baseControlWindow.baseWindow)))
1944 {
1945 FIXME("Failed to prepare window\n");
1946 return FALSE;
1947 }
1948
1949 SetEvent(This->ack);
1950 while ((fGotMessage = GetMessageW(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1)
1951 {
1952 TranslateMessage(&msg);
1953 DispatchMessageW(&msg);
1954 }
1955
1956 TRACE("End of message loop\n");
1957
1958 return 0;
1959 }
1960
1961 static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out)
1962 {
1963 UINT d3d9_adapter;
1964 HMONITOR mon;
1965
1966 mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
1967 if (!mon)
1968 d3d9_adapter = 0;
1969 else
1970 {
1971 for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter)
1972 {
1973 if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter))
1974 break;
1975 }
1976 if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9))
1977 d3d9_adapter = 0;
1978 }
1979 if (mon_out)
1980 *mon_out = mon;
1981 return d3d9_adapter;
1982 }
1983
1984 static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *info, DWORD *numbuffers)
1985 {
1986 D3DPRESENT_PARAMETERS d3dpp;
1987 DWORD d3d9_adapter;
1988 HRESULT hr;
1989
1990 TRACE("(%p)->()\n", This);
1991
1992 This->hWndThread = CreateThread(NULL, 0, MessageLoop, This, 0, &This->tid);
1993 if (!This->hWndThread)
1994 return FALSE;
1995
1996 WaitForSingleObject(This->ack, INFINITE);
1997
1998 if (!This->pVMR9->baseControlWindow.baseWindow.hWnd) return FALSE;
1999
2000 /* Obtain a monitor and d3d9 device */
2001 d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon);
2002
2003 /* Now try to create the d3d9 device */
2004 ZeroMemory(&d3dpp, sizeof(d3dpp));
2005 d3dpp.Windowed = TRUE;
2006 d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd;
2007 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2008 d3dpp.BackBufferHeight = This->pVMR9->target_rect.bottom - This->pVMR9->target_rect.top;
2009 d3dpp.BackBufferWidth = This->pVMR9->target_rect.right - This->pVMR9->target_rect.left;
2010
2011 hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev);
2012 if (FAILED(hr))
2013 {
2014 ERR("Could not create device: %08x\n", hr);
2015 BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
2016 return FALSE;
2017 }
2018 IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2019
2020 This->d3d9_surfaces = CoTaskMemAlloc(*numbuffers * sizeof(IDirect3DSurface9 *));
2021 ZeroMemory(This->d3d9_surfaces, *numbuffers * sizeof(IDirect3DSurface9 *));
2022
2023 hr = VMR9_SurfaceAllocator_SetAllocationSettings(This, info);
2024 if (FAILED(hr))
2025 ERR("Setting allocation settings failed: %08x\n", hr);
2026
2027 if (SUCCEEDED(hr))
2028 {
2029 hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, info, numbuffers, This->d3d9_surfaces);
2030 if (FAILED(hr))
2031 ERR("Allocating surfaces failed: %08x\n", hr);
2032 }
2033
2034 if (FAILED(hr))
2035 {
2036 IVMRSurfaceAllocatorEx9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
2037 BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
2038 return FALSE;
2039 }
2040
2041 This->num_surfaces = *numbuffers;
2042
2043 return TRUE;
2044 }
2045
2046 static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, VMR9AllocationInfo *allocinfo, DWORD *numbuffers)
2047 {
2048 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2049
2050 if (This->pVMR9->mode != VMR9Mode_Windowed && !This->pVMR9->hWndClippingWindow)
2051 {
2052 ERR("No window set\n");
2053 return VFW_E_WRONG_STATE;
2054 }
2055
2056 This->info = *allocinfo;
2057
2058 if (!CreateRenderingWindow(This, allocinfo, numbuffers))
2059 {
2060 ERR("Failed to create rendering window, expect no output!\n");
2061 return VFW_E_WRONG_STATE;
2062 }
2063
2064 return S_OK;
2065 }
2066
2067 static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id)
2068 {
2069 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2070
2071 if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
2072 {
2073 return S_OK;
2074 }
2075
2076 SendMessageW(This->pVMR9->baseControlWindow.baseWindow.hWnd, WM_CLOSE, 0, 0);
2077 PostThreadMessageW(This->tid, WM_QUIT, 0, 0);
2078 WaitForSingleObject(This->hWndThread, INFINITE);
2079 This->hWndThread = NULL;
2080 BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
2081
2082 return S_OK;
2083 }
2084
2085 /* Recreate all surfaces (If allocated as D3DPOOL_DEFAULT) and survive! */
2086 static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(VMR9DefaultAllocatorPresenterImpl *This)
2087 {
2088 struct VERTEX t_vert[4];
2089 UINT width, height;
2090 unsigned int i;
2091 void *bits = NULL;
2092 D3DPRESENT_PARAMETERS d3dpp;
2093 HRESULT hr;
2094
2095 if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
2096 {
2097 ERR("No window\n");
2098 return E_FAIL;
2099 }
2100
2101 if (!This->d3d9_surfaces || !This->reset)
2102 return S_OK;
2103
2104 This->reset = FALSE;
2105 TRACE("RESETTING\n");
2106 if (This->d3d9_vertex)
2107 {
2108 IDirect3DVertexBuffer9_Release(This->d3d9_vertex);
2109 This->d3d9_vertex = NULL;
2110 }
2111
2112 for (i = 0; i < This->num_surfaces; ++i)
2113 {
2114 IDirect3DSurface9 *surface = This->d3d9_surfaces[i];
2115 TRACE("Releasing surface %p\n", surface);
2116 if (surface)
2117 IDirect3DSurface9_Release(surface);
2118 }
2119 ZeroMemory(This->d3d9_surfaces, sizeof(IDirect3DSurface9 *) * This->num_surfaces);
2120
2121 /* Now try to create the d3d9 device */
2122 ZeroMemory(&d3dpp, sizeof(d3dpp));
2123 d3dpp.Windowed = TRUE;
2124 d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd;
2125 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2126
2127 if (This->d3d9_dev)
2128 IDirect3DDevice9_Release(This->d3d9_dev);
2129 This->d3d9_dev = NULL;
2130 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);
2131 if (FAILED(hr))
2132 {
2133 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);
2134 if (FAILED(hr))
2135 {
2136 ERR("--> Creating device: %08x\n", hr);
2137 return S_OK;
2138 }
2139 }
2140 IVMRSurfaceAllocatorNotify9_ChangeD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
2141
2142 IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, &This->info, &This->num_surfaces, This->d3d9_surfaces);
2143
2144 This->reset = FALSE;
2145
2146 if (!(This->info.dwFlags & VMR9AllocFlag_TextureSurface))
2147 return S_OK;
2148
2149 hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF,
2150 This->info.Pool, &This->d3d9_vertex, NULL);
2151
2152 width = This->info.dwWidth;
2153 height = This->info.dwHeight;
2154
2155 for (i = 0; i < sizeof(t_vert) / sizeof(t_vert[0]); ++i)
2156 {
2157 if (i % 2)
2158 {
2159 t_vert[i].x = (float)This->pVMR9->target_rect.right - (float)This->pVMR9->target_rect.left - 0.5f;
2160 t_vert[i].u = (float)This->pVMR9->source_rect.right / (float)width;
2161 }
2162 else
2163 {
2164 t_vert[i].x = -0.5f;
2165 t_vert[i].u = (float)This->pVMR9->source_rect.left / (float)width;
2166 }
2167
2168 if (i % 4 < 2)
2169 {
2170 t_vert[i].y = -0.5f;
2171 t_vert[i].v = (float)This->pVMR9->source_rect.bottom / (float)height;
2172 }
2173 else
2174 {
2175 t_vert[i].y = (float)This->pVMR9->target_rect.bottom - (float)This->pVMR9->target_rect.top - 0.5f;
2176 t_vert[i].v = (float)This->pVMR9->source_rect.top / (float)height;
2177 }
2178 t_vert[i].z = 0.0f;
2179 t_vert[i].rhw = 1.0f;
2180 }
2181
2182 FIXME("Vertex rectangle:\n");
2183 FIXME("X, Y: %f, %f\n", t_vert[0].x, t_vert[0].y);
2184 FIXME("X, Y: %f, %f\n", t_vert[3].x, t_vert[3].y);
2185 FIXME("TOP, LEFT: %f, %f\n", t_vert[0].u, t_vert[0].v);
2186 FIXME("DOWN, BOTTOM: %f, %f\n", t_vert[3].u, t_vert[3].v);
2187
2188 IDirect3DVertexBuffer9_Lock(This->d3d9_vertex, 0, sizeof(t_vert), &bits, 0);
2189 memcpy(bits, t_vert, sizeof(t_vert));
2190 IDirect3DVertexBuffer9_Unlock(This->d3d9_vertex);
2191
2192 return S_OK;
2193 }
2194
2195 static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface)
2196 {
2197 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2198
2199 /* Update everything first, this is needed because the surface might be destroyed in the reset */
2200 if (!This->d3d9_dev)
2201 {
2202 TRACE("Device has left me!\n");
2203 return E_FAIL;
2204 }
2205
2206 VMR9_SurfaceAllocator_UpdateDeviceReset(This);
2207
2208 if (surfaceindex >= This->num_surfaces)
2209 {
2210 ERR("surfaceindex is greater than num_surfaces\n");
2211 return E_FAIL;
2212 }
2213 *surface = This->d3d9_surfaces[surfaceindex];
2214 IDirect3DSurface9_AddRef(*surface);
2215
2216 return S_OK;
2217 }
2218
2219 static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocatorEx9 *iface, IVMRSurfaceAllocatorNotify9 *allocnotify)
2220 {
2221 VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
2222
2223 TRACE("(%p/%p)->(...)\n", iface, This);
2224
2225 /* No AddRef taken here or the base VMR9 filter would never be destroied */
2226 This->SurfaceAllocatorNotify = allocnotify;
2227 return S_OK;
2228 }
2229
2230 static const IVMRSurfaceAllocatorEx9Vtbl VMR9_SurfaceAllocator =
2231 {
2232 VMR9_SurfaceAllocator_QueryInterface,
2233 VMR9_SurfaceAllocator_AddRef,
2234 VMR9_SurfaceAllocator_Release,
2235 VMR9_SurfaceAllocator_InitializeDevice,
2236 VMR9_SurfaceAllocator_TerminateDevice,
2237 VMR9_SurfaceAllocator_GetSurface,
2238 VMR9_SurfaceAllocator_AdviseNotify,
2239 NULL /* This isn't the SurfaceAllocatorEx type yet, working on it */
2240 };
2241
2242 static IDirect3D9 *init_d3d9(HMODULE d3d9_handle)
2243 {
2244 IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion);
2245
2246 d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
2247 if (!d3d9_create) return NULL;
2248
2249 return d3d9_create(D3D_SDK_VERSION);
2250 }
2251
2252 static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID * ppv)
2253 {
2254 HRESULT hr = S_OK;
2255 int i;
2256 VMR9DefaultAllocatorPresenterImpl* This;
2257
2258 This = CoTaskMemAlloc(sizeof(VMR9DefaultAllocatorPresenterImpl));
2259 if (!This)
2260 return E_OUTOFMEMORY;
2261
2262 This->d3d9_ptr = init_d3d9(parent->hD3d9);
2263 if (!This->d3d9_ptr)
2264 {
2265 WARN("Could not initialize d3d9.dll\n");
2266 CoTaskMemFree(This);
2267 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2268 }
2269
2270 i = 0;
2271 do
2272 {
2273 D3DDISPLAYMODE mode;
2274
2275 hr = IDirect3D9_EnumAdapterModes(This->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode);
2276 } while (FAILED(hr));
2277 if (FAILED(hr))
2278 ERR("HR: %08x\n", hr);
2279 if (hr == D3DERR_NOTAVAILABLE)
2280 {
2281 ERR("Format not supported\n");
2282 IDirect3D9_Release(This->d3d9_ptr);
2283 CoTaskMemFree(This);
2284 return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
2285 }
2286
2287 This->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter;
2288 This->IVMRSurfaceAllocatorEx9_iface.lpVtbl = &VMR9_SurfaceAllocator;
2289
2290 This->refCount = 1;
2291 This->pVMR9 = parent;
2292 This->d3d9_surfaces = NULL;
2293 This->d3d9_dev = NULL;
2294 This->hMon = 0;
2295 This->d3d9_vertex = NULL;
2296 This->num_surfaces = 0;
2297 This->hWndThread = NULL;
2298 This->ack = CreateEventW(NULL, 0, 0, NULL);
2299 This->SurfaceAllocatorNotify = NULL;
2300 This->reset = FALSE;
2301
2302 *ppv = This;
2303 return S_OK;
2304 }