mf/session: Forward more events to the application.
[wine/zf.git] / dlls / dxva2 / main.c
blob8952de17b1e53afa17aa0cee15e847cdd2df6a40
1 /*
2 * Copyright 2014 Michael Müller for Pipelight
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include <stdarg.h>
22 #include <limits.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "d3d9.h"
26 #include "physicalmonitorenumerationapi.h"
27 #include "lowlevelmonitorconfigurationapi.h"
28 #include "highlevelmonitorconfigurationapi.h"
29 #include "initguid.h"
30 #include "dxva2api.h"
32 #include "wine/debug.h"
33 #include "wine/heap.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
37 enum device_handle_flags
39 HANDLE_FLAG_OPEN = 0x1,
40 HANDLE_FLAG_INVALID = 0x2,
43 struct device_handle
45 unsigned int flags;
46 IDirect3DStateBlock9 *state_block;
49 struct device_manager
51 IDirect3DDeviceManager9 IDirect3DDeviceManager9_iface;
52 IDirectXVideoProcessorService IDirectXVideoProcessorService_iface;
53 IDirectXVideoDecoderService IDirectXVideoDecoderService_iface;
54 LONG refcount;
56 IDirect3DDevice9 *device;
57 UINT token;
59 struct device_handle *handles;
60 size_t count;
61 size_t capacity;
63 HANDLE locking_handle;
65 CRITICAL_SECTION cs;
66 CONDITION_VARIABLE lock;
69 struct video_processor
71 IDirectXVideoProcessor IDirectXVideoProcessor_iface;
72 LONG refcount;
74 IDirectXVideoProcessorService *service;
75 GUID device;
76 DXVA2_VideoDesc video_desc;
77 D3DFORMAT rt_format;
78 unsigned int max_substreams;
81 static BOOL dxva_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
83 size_t new_capacity, max_capacity;
84 void *new_elements;
86 if (count <= *capacity)
87 return TRUE;
89 max_capacity = ~(SIZE_T)0 / size;
90 if (count > max_capacity)
91 return FALSE;
93 new_capacity = max(4, *capacity);
94 while (new_capacity < count && new_capacity <= max_capacity / 2)
95 new_capacity *= 2;
96 if (new_capacity < count)
97 new_capacity = max_capacity;
99 if (!(new_elements = heap_realloc(*elements, new_capacity * size)))
100 return FALSE;
102 *elements = new_elements;
103 *capacity = new_capacity;
105 return TRUE;
108 static struct device_manager *impl_from_IDirect3DDeviceManager9(IDirect3DDeviceManager9 *iface)
110 return CONTAINING_RECORD(iface, struct device_manager, IDirect3DDeviceManager9_iface);
113 static struct device_manager *impl_from_IDirectXVideoProcessorService(IDirectXVideoProcessorService *iface)
115 return CONTAINING_RECORD(iface, struct device_manager, IDirectXVideoProcessorService_iface);
118 static struct device_manager *impl_from_IDirectXVideoDecoderService(IDirectXVideoDecoderService *iface)
120 return CONTAINING_RECORD(iface, struct device_manager, IDirectXVideoDecoderService_iface);
123 static struct video_processor *impl_from_IDirectXVideoProcessor(IDirectXVideoProcessor *iface)
125 return CONTAINING_RECORD(iface, struct video_processor, IDirectXVideoProcessor_iface);
128 static HRESULT WINAPI video_processor_QueryInterface(IDirectXVideoProcessor *iface, REFIID riid, void **obj)
130 if (IsEqualIID(riid, &IID_IDirectXVideoProcessor) ||
131 IsEqualIID(riid, &IID_IUnknown))
133 *obj = iface;
134 IDirectXVideoProcessor_AddRef(iface);
135 return S_OK;
138 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
139 *obj = NULL;
140 return E_NOINTERFACE;
143 static ULONG WINAPI video_processor_AddRef(IDirectXVideoProcessor *iface)
145 struct video_processor *processor = impl_from_IDirectXVideoProcessor(iface);
146 ULONG refcount = InterlockedIncrement(&processor->refcount);
148 TRACE("%p, refcount %u.\n", iface, refcount);
150 return refcount;
153 static ULONG WINAPI video_processor_Release(IDirectXVideoProcessor *iface)
155 struct video_processor *processor = impl_from_IDirectXVideoProcessor(iface);
156 ULONG refcount = InterlockedDecrement(&processor->refcount);
158 TRACE("%p, refcount %u.\n", iface, refcount);
160 if (!refcount)
162 IDirectXVideoProcessorService_Release(processor->service);
163 heap_free(processor);
166 return refcount;
169 static HRESULT WINAPI video_processor_GetVideoProcessorService(IDirectXVideoProcessor *iface,
170 IDirectXVideoProcessorService **service)
172 struct video_processor *processor = impl_from_IDirectXVideoProcessor(iface);
174 TRACE("%p, %p.\n", iface, service);
176 *service = processor->service;
177 IDirectXVideoProcessorService_AddRef(*service);
179 return S_OK;
182 static HRESULT WINAPI video_processor_GetCreationParameters(IDirectXVideoProcessor *iface,
183 GUID *device, DXVA2_VideoDesc *video_desc, D3DFORMAT *rt_format, UINT *max_substreams)
185 struct video_processor *processor = impl_from_IDirectXVideoProcessor(iface);
187 TRACE("%p, %p, %p, %p, %p.\n", iface, device, video_desc, rt_format, max_substreams);
189 if (!device && !video_desc && !rt_format && !max_substreams)
190 return E_INVALIDARG;
192 if (device)
193 *device = processor->device;
194 if (video_desc)
195 *video_desc = processor->video_desc;
196 if (rt_format)
197 *rt_format = processor->rt_format;
198 if (max_substreams)
199 *max_substreams = processor->max_substreams;
201 return S_OK;
204 static HRESULT WINAPI video_processor_GetVideoProcessorCaps(IDirectXVideoProcessor *iface,
205 DXVA2_VideoProcessorCaps *caps)
207 FIXME("%p, %p.\n", iface, caps);
209 return E_NOTIMPL;
212 static HRESULT WINAPI video_processor_GetProcAmpRange(IDirectXVideoProcessor *iface, UINT cap, DXVA2_ValueRange *range)
214 FIXME("%p, %u, %p.\n", iface, cap, range);
216 return E_NOTIMPL;
219 static HRESULT WINAPI video_processor_GetFilterPropertyRange(IDirectXVideoProcessor *iface, UINT setting,
220 DXVA2_ValueRange *range)
222 FIXME("%p, %u, %p.\n", iface, setting, range);
224 return E_NOTIMPL;
227 static BOOL intersect_rect(RECT *dest, const RECT *src1, const RECT *src2)
229 if (IsRectEmpty(src1) || IsRectEmpty(src2) ||
230 (src1->left >= src2->right) || (src2->left >= src1->right) ||
231 (src1->top >= src2->bottom) || (src2->top >= src1->bottom))
233 SetRectEmpty(dest);
234 return FALSE;
236 dest->left = max(src1->left, src2->left);
237 dest->right = min(src1->right, src2->right);
238 dest->top = max(src1->top, src2->top);
239 dest->bottom = min(src1->bottom, src2->bottom);
241 return TRUE;
244 static HRESULT WINAPI video_processor_VideoProcessBlt(IDirectXVideoProcessor *iface, IDirect3DSurface9 *rt,
245 const DXVA2_VideoProcessBltParams *params, const DXVA2_VideoSample *samples, UINT sample_count,
246 HANDLE *complete_handle)
248 IDirect3DDevice9 *device;
249 unsigned int i;
250 RECT dst_rect;
251 HRESULT hr;
253 TRACE("%p, %p, %p, %p, %u, %p.\n", iface, rt, params, samples, sample_count, complete_handle);
255 if (FAILED(hr = IDirect3DSurface9_GetDevice(rt, &device)))
257 WARN("Failed to get surface device, hr %#x.\n", hr);
258 return hr;
261 /* FIXME: use specified color */
262 IDirect3DDevice9_ColorFill(device, rt, NULL, 0);
264 for (i = 0; i < sample_count; ++i)
266 dst_rect = params->TargetRect;
268 if (!intersect_rect(&dst_rect, &dst_rect, &samples[i].DstRect))
269 continue;
271 if (FAILED(hr = IDirect3DDevice9_StretchRect(device, samples[i].SrcSurface, &samples[i].SrcRect,
272 rt, &dst_rect, D3DTEXF_POINT)))
274 WARN("Failed to copy sample %u, hr %#x.\n", i, hr);
278 IDirect3DDevice9_Release(device);
280 return S_OK;
283 static const IDirectXVideoProcessorVtbl video_processor_vtbl =
285 video_processor_QueryInterface,
286 video_processor_AddRef,
287 video_processor_Release,
288 video_processor_GetVideoProcessorService,
289 video_processor_GetCreationParameters,
290 video_processor_GetVideoProcessorCaps,
291 video_processor_GetProcAmpRange,
292 video_processor_GetFilterPropertyRange,
293 video_processor_VideoProcessBlt,
296 static HRESULT WINAPI device_manager_processor_service_QueryInterface(IDirectXVideoProcessorService *iface,
297 REFIID riid, void **obj)
299 struct device_manager *manager = impl_from_IDirectXVideoProcessorService(iface);
301 if (IsEqualIID(riid, &IID_IDirectXVideoProcessorService) ||
302 IsEqualIID(riid, &IID_IDirectXVideoAccelerationService) ||
303 IsEqualIID(riid, &IID_IUnknown))
305 *obj = iface;
307 else if (IsEqualIID(riid, &IID_IDirectXVideoDecoderService))
309 *obj = &manager->IDirectXVideoDecoderService_iface;
311 else
313 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
314 *obj = NULL;
315 return E_NOINTERFACE;
318 IUnknown_AddRef((IUnknown *)*obj);
319 return S_OK;
322 static ULONG WINAPI device_manager_processor_service_AddRef(IDirectXVideoProcessorService *iface)
324 struct device_manager *manager = impl_from_IDirectXVideoProcessorService(iface);
325 return IDirect3DDeviceManager9_AddRef(&manager->IDirect3DDeviceManager9_iface);
328 static ULONG WINAPI device_manager_processor_service_Release(IDirectXVideoProcessorService *iface)
330 struct device_manager *manager = impl_from_IDirectXVideoProcessorService(iface);
331 return IDirect3DDeviceManager9_Release(&manager->IDirect3DDeviceManager9_iface);
334 static HRESULT WINAPI device_manager_processor_service_CreateSurface(IDirectXVideoProcessorService *iface,
335 UINT width, UINT height, UINT backbuffers, D3DFORMAT format, D3DPOOL pool, DWORD usage, DWORD dxvaType,
336 IDirect3DSurface9 **surfaces, HANDLE *shared_handle)
338 struct device_manager *manager = impl_from_IDirectXVideoProcessorService(iface);
339 unsigned int i, j;
340 HRESULT hr;
342 TRACE("%p, %u, %u, %u, %u, %u, %u, %u, %p, %p.\n", iface, width, height, backbuffers, format, pool, usage, dxvaType,
343 surfaces, shared_handle);
345 if (backbuffers >= UINT_MAX)
346 return E_INVALIDARG;
348 memset(surfaces, 0, (backbuffers + 1) * sizeof(*surfaces));
350 for (i = 0; i < backbuffers + 1; ++i)
352 if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(manager->device, width, height, format,
353 pool, &surfaces[i], NULL)))
354 break;
357 if (FAILED(hr))
359 for (j = 0; j < i; ++j)
361 if (surfaces[j])
363 IDirect3DSurface9_Release(surfaces[j]);
364 surfaces[j] = NULL;
369 return hr;
372 static HRESULT WINAPI device_manager_processor_service_RegisterVideoProcessorSoftwareDevice(
373 IDirectXVideoProcessorService *iface, void *callbacks)
375 FIXME("%p, %p.\n", iface, callbacks);
377 return E_NOTIMPL;
380 static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorDeviceGuids(
381 IDirectXVideoProcessorService *iface, const DXVA2_VideoDesc *video_desc, UINT *count, GUID **guids)
383 FIXME("%p, %p, %p, %p semi-stub.\n", iface, video_desc, count, guids);
385 if (!(*guids = CoTaskMemAlloc(sizeof(**guids))))
386 return E_OUTOFMEMORY;
388 memcpy(*guids, &DXVA2_VideoProcSoftwareDevice, sizeof(**guids));
389 *count = 1;
391 return S_OK;
394 static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorRenderTargets(
395 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc, UINT *count,
396 D3DFORMAT **formats)
398 TRACE("%p, %s, %p, %p, %p.\n", iface, debugstr_guid(deviceguid), video_desc, count, formats);
400 if (IsEqualGUID(deviceguid, &DXVA2_VideoProcSoftwareDevice))
402 if (!(video_desc->Format == D3DFMT_A8R8G8B8 ||
403 video_desc->Format == D3DFMT_X8R8G8B8 ||
404 video_desc->Format == D3DFMT_YUY2))
406 WARN("Unsupported content format %#x.\n", video_desc->Format);
407 return E_FAIL;
410 if (!(*formats = CoTaskMemAlloc(2 * sizeof(**formats))))
411 return E_OUTOFMEMORY;
413 *count = 2;
414 (*formats)[0] = D3DFMT_X8R8G8B8;
415 (*formats)[1] = D3DFMT_A8R8G8B8;
417 return S_OK;
419 else
420 FIXME("Unsupported device %s.\n", debugstr_guid(deviceguid));
422 return E_NOTIMPL;
425 static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorSubStreamFormats(
426 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc,
427 D3DFORMAT rt_format, UINT *count, D3DFORMAT **formats)
429 FIXME("%p, %s, %p, %u, %p, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, count, formats);
431 return E_NOTIMPL;
434 static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorCaps(
435 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc,
436 D3DFORMAT rt_format, DXVA2_VideoProcessorCaps *caps)
438 FIXME("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, caps);
440 return E_NOTIMPL;
443 static HRESULT WINAPI device_manager_processor_service_GetProcAmpRange(
444 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc,
445 D3DFORMAT rt_format, UINT ProcAmpCap, DXVA2_ValueRange *range)
447 FIXME("%p, %s, %p, %u, %u, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, ProcAmpCap, range);
449 return E_NOTIMPL;
452 static HRESULT WINAPI device_manager_processor_service_GetFilterPropertyRange(
453 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc,
454 D3DFORMAT rt_format, UINT filter_setting, DXVA2_ValueRange *range)
456 FIXME("%p, %s, %p, %d, %d, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, filter_setting, range);
458 return E_NOTIMPL;
461 static HRESULT WINAPI device_manager_processor_service_CreateVideoProcessor(IDirectXVideoProcessorService *iface,
462 REFGUID device, const DXVA2_VideoDesc *video_desc, D3DFORMAT rt_format, UINT max_substreams,
463 IDirectXVideoProcessor **processor)
465 struct video_processor *object;
467 FIXME("%p, %s, %p, %d, %u, %p.\n", iface, debugstr_guid(device), video_desc, rt_format, max_substreams,
468 processor);
470 /* FIXME: validate render target format */
472 if (!(object = heap_alloc_zero(sizeof(*object))))
473 return E_OUTOFMEMORY;
475 object->IDirectXVideoProcessor_iface.lpVtbl = &video_processor_vtbl;
476 object->refcount = 1;
477 object->service = iface;
478 IDirectXVideoProcessorService_AddRef(object->service);
479 object->device = *device;
480 object->video_desc = *video_desc;
481 object->rt_format = rt_format;
482 object->max_substreams = max_substreams;
484 *processor = &object->IDirectXVideoProcessor_iface;
486 return S_OK;
489 static const IDirectXVideoProcessorServiceVtbl device_manager_processor_service_vtbl =
491 device_manager_processor_service_QueryInterface,
492 device_manager_processor_service_AddRef,
493 device_manager_processor_service_Release,
494 device_manager_processor_service_CreateSurface,
495 device_manager_processor_service_RegisterVideoProcessorSoftwareDevice,
496 device_manager_processor_service_GetVideoProcessorDeviceGuids,
497 device_manager_processor_service_GetVideoProcessorRenderTargets,
498 device_manager_processor_service_GetVideoProcessorSubStreamFormats,
499 device_manager_processor_service_GetVideoProcessorCaps,
500 device_manager_processor_service_GetProcAmpRange,
501 device_manager_processor_service_GetFilterPropertyRange,
502 device_manager_processor_service_CreateVideoProcessor,
505 static HRESULT WINAPI device_manager_decoder_service_QueryInterface(IDirectXVideoDecoderService *iface,
506 REFIID riid, void **obj)
508 if (IsEqualIID(riid, &IID_IDirectXVideoDecoderService) ||
509 IsEqualIID(riid, &IID_IDirectXVideoAccelerationService) ||
510 IsEqualIID(riid, &IID_IUnknown))
512 *obj = iface;
513 IDirectXVideoDecoderService_AddRef(iface);
514 return S_OK;
517 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
518 *obj = NULL;
519 return E_NOINTERFACE;
522 static ULONG WINAPI device_manager_decoder_service_AddRef(IDirectXVideoDecoderService *iface)
524 struct device_manager *manager = impl_from_IDirectXVideoDecoderService(iface);
525 return IDirect3DDeviceManager9_AddRef(&manager->IDirect3DDeviceManager9_iface);
528 static ULONG WINAPI device_manager_decoder_service_Release(IDirectXVideoDecoderService *iface)
530 struct device_manager *manager = impl_from_IDirectXVideoDecoderService(iface);
531 return IDirect3DDeviceManager9_Release(&manager->IDirect3DDeviceManager9_iface);
534 static HRESULT WINAPI device_manager_decoder_service_CreateSurface(IDirectXVideoDecoderService *iface,
535 UINT width, UINT height, UINT backbuffers, D3DFORMAT format, D3DPOOL pool, DWORD usage, DWORD dxvaType,
536 IDirect3DSurface9 **surfaces, HANDLE *shared_handle)
538 FIXME("%p, %u, %u, %u, %#x, %d, %d, %d, %p, %p.\n", iface, width, height, backbuffers, format, pool, usage,
539 dxvaType, surfaces, shared_handle);
541 return E_NOTIMPL;
544 static HRESULT WINAPI device_manager_decoder_service_GetDecoderDeviceGuids(IDirectXVideoDecoderService *iface,
545 UINT *count, GUID **guids)
547 FIXME("%p, %p, %p.\n", iface, count, guids);
549 return E_NOTIMPL;
552 static HRESULT WINAPI device_manager_decoder_service_GetDecoderRenderTargets(IDirectXVideoDecoderService *iface,
553 REFGUID guid, UINT *count, D3DFORMAT **formats)
555 FIXME("%p, %s, %p, %p.\n", iface, debugstr_guid(guid), count, formats);
557 return E_NOTIMPL;
560 static HRESULT WINAPI device_manager_decoder_service_GetDecoderConfigurations(IDirectXVideoDecoderService *iface,
561 REFGUID guid, const DXVA2_VideoDesc *video_desc, IUnknown *reserved, UINT *count, DXVA2_ConfigPictureDecode **configs)
563 FIXME("%p, %s, %p, %p, %p, %p.\n", iface, debugstr_guid(guid), video_desc, reserved, count, configs);
565 return E_NOTIMPL;
568 static HRESULT WINAPI device_manager_decoder_service_CreateVideoDecoder(IDirectXVideoDecoderService *iface,
569 REFGUID guid, const DXVA2_VideoDesc *video_desc, DXVA2_ConfigPictureDecode *config, IDirect3DSurface9 **rts,
570 UINT num_surfaces, IDirectXVideoDecoder **decoder)
572 FIXME("%p, %s, %p, %p, %p, %u, %p.\n", iface, debugstr_guid(guid), video_desc, config, rts, num_surfaces,
573 decoder);
575 return E_NOTIMPL;
578 static const IDirectXVideoDecoderServiceVtbl device_manager_decoder_service_vtbl =
580 device_manager_decoder_service_QueryInterface,
581 device_manager_decoder_service_AddRef,
582 device_manager_decoder_service_Release,
583 device_manager_decoder_service_CreateSurface,
584 device_manager_decoder_service_GetDecoderDeviceGuids,
585 device_manager_decoder_service_GetDecoderRenderTargets,
586 device_manager_decoder_service_GetDecoderConfigurations,
587 device_manager_decoder_service_CreateVideoDecoder,
590 static HRESULT WINAPI device_manager_QueryInterface(IDirect3DDeviceManager9 *iface, REFIID riid, void **obj)
592 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
594 if (IsEqualIID(&IID_IDirect3DDeviceManager9, riid) ||
595 IsEqualIID(&IID_IUnknown, riid))
597 *obj = iface;
598 IDirect3DDeviceManager9_AddRef(iface);
599 return S_OK;
602 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
603 *obj = NULL;
604 return E_NOINTERFACE;
607 static ULONG WINAPI device_manager_AddRef(IDirect3DDeviceManager9 *iface)
609 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
610 ULONG refcount = InterlockedIncrement(&manager->refcount);
612 TRACE("%p, refcount %u.\n", iface, refcount);
614 return refcount;
617 static ULONG WINAPI device_manager_Release(IDirect3DDeviceManager9 *iface)
619 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
620 ULONG refcount = InterlockedDecrement(&manager->refcount);
621 size_t i;
623 TRACE("%p, refcount %u.\n", iface, refcount);
625 if (!refcount)
627 if (manager->device)
628 IDirect3DDevice9_Release(manager->device);
629 DeleteCriticalSection(&manager->cs);
630 for (i = 0; i < manager->count; ++i)
632 if (manager->handles[i].state_block)
633 IDirect3DStateBlock9_Release(manager->handles[i].state_block);
635 heap_free(manager->handles);
636 heap_free(manager);
639 return refcount;
642 static HRESULT WINAPI device_manager_ResetDevice(IDirect3DDeviceManager9 *iface, IDirect3DDevice9 *device,
643 UINT token)
645 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
646 size_t i;
648 TRACE("%p, %p, %#x.\n", iface, device, token);
650 if (token != manager->token)
651 return E_INVALIDARG;
653 EnterCriticalSection(&manager->cs);
654 if (manager->device)
656 for (i = 0; i < manager->count; ++i)
658 if (manager->handles[i].state_block)
659 IDirect3DStateBlock9_Release(manager->handles[i].state_block);
660 manager->handles[i].state_block = NULL;
661 manager->handles[i].flags |= HANDLE_FLAG_INVALID;
663 manager->locking_handle = NULL;
664 IDirect3DDevice9_Release(manager->device);
666 manager->device = device;
667 IDirect3DDevice9_AddRef(manager->device);
668 LeaveCriticalSection(&manager->cs);
670 WakeAllConditionVariable(&manager->lock);
672 return S_OK;
675 static HRESULT WINAPI device_manager_OpenDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE *hdevice)
677 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
678 HRESULT hr = S_OK;
679 size_t i;
681 TRACE("%p, %p.\n", iface, hdevice);
683 *hdevice = NULL;
685 EnterCriticalSection(&manager->cs);
686 if (!manager->device)
687 hr = DXVA2_E_NOT_INITIALIZED;
688 else
690 for (i = 0; i < manager->count; ++i)
692 if (!(manager->handles[i].flags & HANDLE_FLAG_OPEN))
694 manager->handles[i].flags |= HANDLE_FLAG_OPEN;
695 *hdevice = ULongToHandle(i + 1);
696 break;
700 if (dxva_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
701 sizeof(*manager->handles)))
703 *hdevice = ULongToHandle(manager->count + 1);
704 manager->handles[manager->count].flags = HANDLE_FLAG_OPEN;
705 manager->handles[manager->count].state_block = NULL;
706 manager->count++;
708 else
709 hr = E_OUTOFMEMORY;
711 LeaveCriticalSection(&manager->cs);
713 return hr;
716 static HRESULT device_manager_get_handle_index(struct device_manager *manager, HANDLE hdevice, size_t *idx)
718 if (!hdevice || hdevice > ULongToHandle(manager->count))
719 return E_HANDLE;
720 *idx = (ULONG_PTR)hdevice - 1;
721 return S_OK;
724 static HRESULT WINAPI device_manager_CloseDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE hdevice)
726 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
727 HRESULT hr;
728 size_t idx;
730 TRACE("%p, %p.\n", iface, hdevice);
732 EnterCriticalSection(&manager->cs);
733 if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
735 if (manager->handles[idx].flags & HANDLE_FLAG_OPEN)
737 if (manager->locking_handle == hdevice)
738 manager->locking_handle = NULL;
739 manager->handles[idx].flags = 0;
740 if (idx == manager->count - 1)
741 manager->count--;
742 if (manager->handles[idx].state_block)
743 IDirect3DStateBlock9_Release(manager->handles[idx].state_block);
744 manager->handles[idx].state_block = NULL;
746 else
747 hr = E_HANDLE;
749 LeaveCriticalSection(&manager->cs);
751 WakeAllConditionVariable(&manager->lock);
753 return hr;
756 static HRESULT WINAPI device_manager_TestDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice)
758 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
759 HRESULT hr;
760 size_t idx;
762 TRACE("%p, %p.\n", iface, hdevice);
764 EnterCriticalSection(&manager->cs);
765 if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
767 unsigned int flags = manager->handles[idx].flags;
769 if (flags & HANDLE_FLAG_INVALID)
770 hr = DXVA2_E_NEW_VIDEO_DEVICE;
771 else if (!(flags & HANDLE_FLAG_OPEN))
772 hr = E_HANDLE;
774 LeaveCriticalSection(&manager->cs);
776 return hr;
779 static HRESULT WINAPI device_manager_LockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice,
780 IDirect3DDevice9 **device, BOOL block)
782 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
783 HRESULT hr;
784 size_t idx;
786 TRACE("%p, %p, %p, %d.\n", iface, hdevice, device, block);
788 EnterCriticalSection(&manager->cs);
789 if (!manager->device)
790 hr = DXVA2_E_NOT_INITIALIZED;
791 else if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
793 if (manager->locking_handle && !block)
794 hr = DXVA2_E_VIDEO_DEVICE_LOCKED;
795 else
797 while (manager->locking_handle && block)
799 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
802 if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
804 if (manager->handles[idx].flags & HANDLE_FLAG_INVALID)
805 hr = DXVA2_E_NEW_VIDEO_DEVICE;
806 else
808 if (manager->handles[idx].state_block)
810 if (FAILED(IDirect3DStateBlock9_Apply(manager->handles[idx].state_block)))
811 WARN("Failed to apply state.\n");
812 IDirect3DStateBlock9_Release(manager->handles[idx].state_block);
813 manager->handles[idx].state_block = NULL;
815 *device = manager->device;
816 IDirect3DDevice9_AddRef(*device);
817 manager->locking_handle = hdevice;
822 LeaveCriticalSection(&manager->cs);
824 return hr;
827 static HRESULT WINAPI device_manager_UnlockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice, BOOL savestate)
829 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
830 HRESULT hr;
831 size_t idx;
833 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
835 EnterCriticalSection(&manager->cs);
837 if (hdevice != manager->locking_handle)
838 hr = E_INVALIDARG;
839 else if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
841 manager->locking_handle = NULL;
842 if (savestate)
843 IDirect3DDevice9_CreateStateBlock(manager->device, D3DSBT_ALL, &manager->handles[idx].state_block);
846 LeaveCriticalSection(&manager->cs);
848 WakeAllConditionVariable(&manager->lock);
850 return hr;
853 static HRESULT WINAPI device_manager_GetVideoService(IDirect3DDeviceManager9 *iface, HANDLE hdevice, REFIID riid,
854 void **obj)
856 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
857 HRESULT hr;
858 size_t idx;
860 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), obj);
862 EnterCriticalSection(&manager->cs);
863 if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
865 unsigned int flags = manager->handles[idx].flags;
867 if (flags & HANDLE_FLAG_INVALID)
868 hr = DXVA2_E_NEW_VIDEO_DEVICE;
869 else if (!(flags & HANDLE_FLAG_OPEN))
870 hr = E_HANDLE;
871 else
872 hr = IDirectXVideoProcessorService_QueryInterface(&manager->IDirectXVideoProcessorService_iface,
873 riid, obj);
875 LeaveCriticalSection(&manager->cs);
877 return hr;
880 static const IDirect3DDeviceManager9Vtbl device_manager_vtbl =
882 device_manager_QueryInterface,
883 device_manager_AddRef,
884 device_manager_Release,
885 device_manager_ResetDevice,
886 device_manager_OpenDeviceHandle,
887 device_manager_CloseDeviceHandle,
888 device_manager_TestDevice,
889 device_manager_LockDevice,
890 device_manager_UnlockDevice,
891 device_manager_GetVideoService,
894 BOOL WINAPI CapabilitiesRequestAndCapabilitiesReply( HMONITOR monitor, LPSTR buffer, DWORD length )
896 FIXME("(%p, %p, %d): stub\n", monitor, buffer, length);
898 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
899 return FALSE;
902 HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9(UINT *token, IDirect3DDeviceManager9 **manager)
904 struct device_manager *object;
906 TRACE("%p, %p.\n", token, manager);
908 *manager = NULL;
910 if (!(object = heap_alloc_zero(sizeof(*object))))
911 return E_OUTOFMEMORY;
913 object->IDirect3DDeviceManager9_iface.lpVtbl = &device_manager_vtbl;
914 object->IDirectXVideoProcessorService_iface.lpVtbl = &device_manager_processor_service_vtbl;
915 object->IDirectXVideoDecoderService_iface.lpVtbl = &device_manager_decoder_service_vtbl;
916 object->refcount = 1;
917 object->token = GetTickCount();
918 InitializeCriticalSection(&object->cs);
919 InitializeConditionVariable(&object->lock);
921 *token = object->token;
922 *manager = &object->IDirect3DDeviceManager9_iface;
924 return S_OK;
927 HRESULT WINAPI DXVA2CreateVideoService(IDirect3DDevice9 *device, REFIID riid, void **obj)
929 IDirect3DDeviceManager9 *manager;
930 HANDLE handle;
931 HRESULT hr;
932 UINT token;
934 TRACE("%p, %s, %p.\n", device, debugstr_guid(riid), obj);
936 if (FAILED(hr = DXVA2CreateDirect3DDeviceManager9(&token, &manager)))
937 return hr;
939 if (FAILED(hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token)))
940 goto done;
942 if (FAILED(hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle)))
943 goto done;
945 hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, riid, obj);
946 IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle);
948 done:
949 IDirect3DDeviceManager9_Release(manager);
951 return hr;
954 BOOL WINAPI DegaussMonitor( HMONITOR monitor )
956 FIXME("(%p): stub\n", monitor);
958 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
959 return FALSE;
962 BOOL WINAPI DestroyPhysicalMonitor( HMONITOR monitor )
964 FIXME("(%p): stub\n", monitor);
966 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
967 return FALSE;
970 BOOL WINAPI DestroyPhysicalMonitors( DWORD arraySize, LPPHYSICAL_MONITOR array )
972 FIXME("(0x%x, %p): stub\n", arraySize, array);
974 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
975 return FALSE;
978 BOOL WINAPI GetCapabilitiesStringLength( HMONITOR monitor, LPDWORD length )
980 FIXME("(%p, %p): stub\n", monitor, length);
982 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
983 return FALSE;
986 BOOL WINAPI GetMonitorBrightness( HMONITOR monitor, LPDWORD minimum, LPDWORD current, LPDWORD maximum )
988 FIXME("(%p, %p, %p, %p): stub\n", monitor, minimum, current, maximum);
990 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
991 return FALSE;
994 BOOL WINAPI GetMonitorCapabilities( HMONITOR monitor, LPDWORD capabilities, LPDWORD temperatures )
996 FIXME("(%p, %p, %p): stub\n", monitor, capabilities, temperatures);
998 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
999 return FALSE;
1003 BOOL WINAPI GetMonitorColorTemperature( HMONITOR monitor, LPMC_COLOR_TEMPERATURE temperature )
1005 FIXME("(%p, %p): stub\n", monitor, temperature);
1007 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1008 return FALSE;
1011 BOOL WINAPI GetMonitorContrast( HMONITOR monitor, LPDWORD minimum, LPDWORD current, LPDWORD maximum )
1013 FIXME("(%p, %p, %p, %p): stub\n", monitor, minimum, current, maximum);
1015 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1016 return FALSE;
1019 BOOL WINAPI GetMonitorDisplayAreaPosition( HMONITOR monitor, MC_POSITION_TYPE type, LPDWORD minimum,
1020 LPDWORD current, LPDWORD maximum )
1022 FIXME("(%p, 0x%x, %p, %p, %p): stub\n", monitor, type, minimum, current, maximum);
1024 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1025 return FALSE;
1028 BOOL WINAPI GetMonitorDisplayAreaSize( HMONITOR monitor, MC_SIZE_TYPE type, LPDWORD minimum,
1029 LPDWORD current, LPDWORD maximum )
1031 FIXME("(%p, 0x%x, %p, %p, %p): stub\n", monitor, type, minimum, current, maximum);
1033 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1034 return FALSE;
1037 BOOL WINAPI GetMonitorRedGreenOrBlueDrive( HMONITOR monitor, MC_DRIVE_TYPE type, LPDWORD minimum,
1038 LPDWORD current, LPDWORD maximum )
1040 FIXME("(%p, 0x%x, %p, %p, %p): stub\n", monitor, type, minimum, current, maximum);
1042 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1043 return FALSE;
1046 BOOL WINAPI GetMonitorRedGreenOrBlueGain( HMONITOR monitor, MC_GAIN_TYPE type, LPDWORD minimum,
1047 LPDWORD current, LPDWORD maximum )
1049 FIXME("(%p, 0x%x, %p, %p, %p): stub\n", monitor, type, minimum, current, maximum);
1051 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1052 return FALSE;
1055 BOOL WINAPI GetMonitorTechnologyType( HMONITOR monitor, LPMC_DISPLAY_TECHNOLOGY_TYPE type )
1057 FIXME("(%p, %p): stub\n", monitor, type);
1059 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1060 return FALSE;
1063 BOOL WINAPI GetNumberOfPhysicalMonitorsFromHMONITOR( HMONITOR monitor, LPDWORD number )
1065 FIXME("(%p, %p): stub\n", monitor, number);
1067 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1068 return FALSE;
1071 HRESULT WINAPI GetNumberOfPhysicalMonitorsFromIDirect3DDevice9( IDirect3DDevice9 *device, LPDWORD number )
1073 FIXME("(%p, %p): stub\n", device, number);
1075 return E_NOTIMPL;
1078 BOOL WINAPI GetPhysicalMonitorsFromHMONITOR( HMONITOR monitor, DWORD arraySize, LPPHYSICAL_MONITOR array )
1080 FIXME("(%p, 0x%x, %p): stub\n", monitor, arraySize, array);
1082 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1083 return FALSE;
1086 HRESULT WINAPI GetPhysicalMonitorsFromIDirect3DDevice9( IDirect3DDevice9 *device, DWORD arraySize, LPPHYSICAL_MONITOR array )
1088 FIXME("(%p, 0x%x, %p): stub\n", device, arraySize, array);
1090 return E_NOTIMPL;
1093 BOOL WINAPI GetTimingReport( HMONITOR monitor, LPMC_TIMING_REPORT timingReport )
1095 FIXME("(%p, %p): stub\n", monitor, timingReport);
1097 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1098 return FALSE;
1101 BOOL WINAPI GetVCPFeatureAndVCPFeatureReply( HMONITOR monitor, BYTE vcpCode, LPMC_VCP_CODE_TYPE pvct,
1102 LPDWORD current, LPDWORD maximum )
1104 FIXME("(%p, 0x%02x, %p, %p, %p): stub\n", monitor, vcpCode, pvct, current, maximum);
1106 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1107 return FALSE;
1110 HRESULT WINAPI OPMGetVideoOutputsFromHMONITOR( HMONITOR monitor, /* OPM_VIDEO_OUTPUT_SEMANTICS */ int vos,
1111 ULONG *numVideoOutputs, /* IOPMVideoOutput */ void ***videoOutputs )
1113 FIXME("(%p, 0x%x, %p, %p): stub\n", monitor, vos, numVideoOutputs, videoOutputs);
1115 return E_NOTIMPL;
1118 HRESULT WINAPI OPMGetVideoOutputsFromIDirect3DDevice9Object( IDirect3DDevice9 *device, /* OPM_VIDEO_OUTPUT_SEMANTICS */ int vos,
1119 ULONG *numVideoOutputs, /* IOPMVideoOutput */ void ***videoOutputs )
1121 FIXME("(%p, 0x%x, %p, %p): stub\n", device, vos, numVideoOutputs, videoOutputs);
1123 return E_NOTIMPL;
1126 BOOL WINAPI RestoreMonitorFactoryColorDefaults( HMONITOR monitor )
1128 FIXME("(%p): stub\n", monitor);
1130 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1131 return FALSE;
1134 BOOL WINAPI RestoreMonitorFactoryDefaults( HMONITOR monitor )
1136 FIXME("(%p): stub\n", monitor);
1138 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1139 return FALSE;
1142 BOOL WINAPI SaveCurrentMonitorSettings( HMONITOR monitor )
1144 FIXME("(%p): stub\n", monitor);
1146 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1147 return FALSE;
1150 BOOL WINAPI SaveCurrentSettings( HMONITOR monitor )
1152 FIXME("(%p): stub\n", monitor);
1154 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1155 return FALSE;
1158 BOOL WINAPI SetMonitorBrightness( HMONITOR monitor, DWORD brightness )
1160 FIXME("(%p, 0x%x): stub\n", monitor, brightness);
1162 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1163 return FALSE;
1166 BOOL WINAPI SetMonitorColorTemperature( HMONITOR monitor, MC_COLOR_TEMPERATURE temperature )
1168 FIXME("(%p, 0x%x): stub\n", monitor, temperature);
1170 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1171 return FALSE;
1174 BOOL WINAPI SetMonitorContrast( HMONITOR monitor, DWORD contrast )
1176 FIXME("(%p, 0x%x): stub\n", monitor, contrast);
1178 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1179 return FALSE;
1182 BOOL WINAPI SetMonitorDisplayAreaPosition( HMONITOR monitor, MC_POSITION_TYPE type, DWORD position )
1184 FIXME("(%p, 0x%x, 0x%x): stub\n", monitor, type, position);
1186 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1187 return FALSE;
1190 BOOL WINAPI SetMonitorDisplayAreaSize( HMONITOR monitor, MC_SIZE_TYPE type, DWORD size )
1192 FIXME("(%p, 0x%x, 0x%x): stub\n", monitor, type, size);
1194 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1195 return FALSE;
1198 BOOL WINAPI SetMonitorRedGreenOrBlueDrive( HMONITOR monitor, MC_DRIVE_TYPE type, DWORD drive )
1200 FIXME("(%p, 0x%x, 0x%x): stub\n", monitor, type, drive);
1202 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1203 return FALSE;
1206 BOOL WINAPI SetMonitorRedGreenOrBlueGain( HMONITOR monitor, MC_GAIN_TYPE type, DWORD gain )
1208 FIXME("(%p, 0x%x, 0x%x): stub\n", monitor, type, gain);
1210 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1211 return FALSE;
1214 BOOL WINAPI SetVCPFeature( HMONITOR monitor, BYTE vcpCode, DWORD value )
1216 FIXME("(%p, 0x%02x, 0x%x): stub\n", monitor, vcpCode, value);
1218 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1219 return FALSE;