kernelbase/tests: Fix the Sleep() test for non-default timer resolutions.
[wine.git] / dlls / dxva2 / main.c
blobf91b033055c6a1d573dd559973841cc183edb432
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 BOOL dxva_is_supported_stream_format(const DXVA2_VideoDesc *video_desc)
382 return video_desc->Format == D3DFMT_A8R8G8B8 ||
383 video_desc->Format == D3DFMT_X8R8G8B8 ||
384 video_desc->Format == D3DFMT_YUY2 ||
385 video_desc->Format == MAKEFOURCC('A','Y','U','V');
388 static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorDeviceGuids(
389 IDirectXVideoProcessorService *iface, const DXVA2_VideoDesc *video_desc, UINT *count, GUID **guids)
391 FIXME("%p, %p, %p, %p semi-stub.\n", iface, video_desc, count, guids);
393 *count = 0;
395 if (!dxva_is_supported_stream_format(video_desc))
396 return E_FAIL;
398 if (!(*guids = CoTaskMemAlloc(sizeof(**guids))))
399 return E_OUTOFMEMORY;
401 memcpy(*guids, &DXVA2_VideoProcSoftwareDevice, sizeof(**guids));
402 *count = 1;
404 return S_OK;
407 static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorRenderTargets(
408 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc, UINT *count,
409 D3DFORMAT **formats)
411 TRACE("%p, %s, %p, %p, %p.\n", iface, debugstr_guid(deviceguid), video_desc, count, formats);
413 if (IsEqualGUID(deviceguid, &DXVA2_VideoProcSoftwareDevice))
415 if (!dxva_is_supported_stream_format(video_desc))
417 WARN("Unsupported content format %#x.\n", video_desc->Format);
418 return E_FAIL;
421 if (!(*formats = CoTaskMemAlloc(2 * sizeof(**formats))))
422 return E_OUTOFMEMORY;
424 *count = 2;
425 (*formats)[0] = D3DFMT_X8R8G8B8;
426 (*formats)[1] = D3DFMT_A8R8G8B8;
428 return S_OK;
430 else
431 FIXME("Unsupported device %s.\n", debugstr_guid(deviceguid));
433 return E_NOTIMPL;
436 static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorSubStreamFormats(
437 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc,
438 D3DFORMAT rt_format, UINT *count, D3DFORMAT **formats)
440 FIXME("%p, %s, %p, %u, %p, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, count, formats);
442 return E_NOTIMPL;
445 static HRESULT WINAPI device_manager_processor_service_GetVideoProcessorCaps(
446 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc,
447 D3DFORMAT rt_format, DXVA2_VideoProcessorCaps *caps)
449 FIXME("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, caps);
451 return E_NOTIMPL;
454 static HRESULT WINAPI device_manager_processor_service_GetProcAmpRange(
455 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc,
456 D3DFORMAT rt_format, UINT ProcAmpCap, DXVA2_ValueRange *range)
458 FIXME("%p, %s, %p, %u, %u, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, ProcAmpCap, range);
460 return E_NOTIMPL;
463 static HRESULT WINAPI device_manager_processor_service_GetFilterPropertyRange(
464 IDirectXVideoProcessorService *iface, REFGUID deviceguid, const DXVA2_VideoDesc *video_desc,
465 D3DFORMAT rt_format, UINT filter_setting, DXVA2_ValueRange *range)
467 FIXME("%p, %s, %p, %d, %d, %p.\n", iface, debugstr_guid(deviceguid), video_desc, rt_format, filter_setting, range);
469 return E_NOTIMPL;
472 static HRESULT WINAPI device_manager_processor_service_CreateVideoProcessor(IDirectXVideoProcessorService *iface,
473 REFGUID device, const DXVA2_VideoDesc *video_desc, D3DFORMAT rt_format, UINT max_substreams,
474 IDirectXVideoProcessor **processor)
476 struct video_processor *object;
478 FIXME("%p, %s, %p, %d, %u, %p.\n", iface, debugstr_guid(device), video_desc, rt_format, max_substreams,
479 processor);
481 /* FIXME: validate render target format */
483 if (!(object = heap_alloc_zero(sizeof(*object))))
484 return E_OUTOFMEMORY;
486 object->IDirectXVideoProcessor_iface.lpVtbl = &video_processor_vtbl;
487 object->refcount = 1;
488 object->service = iface;
489 IDirectXVideoProcessorService_AddRef(object->service);
490 object->device = *device;
491 object->video_desc = *video_desc;
492 object->rt_format = rt_format;
493 object->max_substreams = max_substreams;
495 *processor = &object->IDirectXVideoProcessor_iface;
497 return S_OK;
500 static const IDirectXVideoProcessorServiceVtbl device_manager_processor_service_vtbl =
502 device_manager_processor_service_QueryInterface,
503 device_manager_processor_service_AddRef,
504 device_manager_processor_service_Release,
505 device_manager_processor_service_CreateSurface,
506 device_manager_processor_service_RegisterVideoProcessorSoftwareDevice,
507 device_manager_processor_service_GetVideoProcessorDeviceGuids,
508 device_manager_processor_service_GetVideoProcessorRenderTargets,
509 device_manager_processor_service_GetVideoProcessorSubStreamFormats,
510 device_manager_processor_service_GetVideoProcessorCaps,
511 device_manager_processor_service_GetProcAmpRange,
512 device_manager_processor_service_GetFilterPropertyRange,
513 device_manager_processor_service_CreateVideoProcessor,
516 static HRESULT WINAPI device_manager_decoder_service_QueryInterface(IDirectXVideoDecoderService *iface,
517 REFIID riid, void **obj)
519 if (IsEqualIID(riid, &IID_IDirectXVideoDecoderService) ||
520 IsEqualIID(riid, &IID_IDirectXVideoAccelerationService) ||
521 IsEqualIID(riid, &IID_IUnknown))
523 *obj = iface;
524 IDirectXVideoDecoderService_AddRef(iface);
525 return S_OK;
528 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
529 *obj = NULL;
530 return E_NOINTERFACE;
533 static ULONG WINAPI device_manager_decoder_service_AddRef(IDirectXVideoDecoderService *iface)
535 struct device_manager *manager = impl_from_IDirectXVideoDecoderService(iface);
536 return IDirect3DDeviceManager9_AddRef(&manager->IDirect3DDeviceManager9_iface);
539 static ULONG WINAPI device_manager_decoder_service_Release(IDirectXVideoDecoderService *iface)
541 struct device_manager *manager = impl_from_IDirectXVideoDecoderService(iface);
542 return IDirect3DDeviceManager9_Release(&manager->IDirect3DDeviceManager9_iface);
545 static HRESULT WINAPI device_manager_decoder_service_CreateSurface(IDirectXVideoDecoderService *iface,
546 UINT width, UINT height, UINT backbuffers, D3DFORMAT format, D3DPOOL pool, DWORD usage, DWORD dxvaType,
547 IDirect3DSurface9 **surfaces, HANDLE *shared_handle)
549 FIXME("%p, %u, %u, %u, %#x, %d, %d, %d, %p, %p.\n", iface, width, height, backbuffers, format, pool, usage,
550 dxvaType, surfaces, shared_handle);
552 return E_NOTIMPL;
555 static HRESULT WINAPI device_manager_decoder_service_GetDecoderDeviceGuids(IDirectXVideoDecoderService *iface,
556 UINT *count, GUID **guids)
558 FIXME("%p, %p, %p.\n", iface, count, guids);
560 return E_NOTIMPL;
563 static HRESULT WINAPI device_manager_decoder_service_GetDecoderRenderTargets(IDirectXVideoDecoderService *iface,
564 REFGUID guid, UINT *count, D3DFORMAT **formats)
566 FIXME("%p, %s, %p, %p.\n", iface, debugstr_guid(guid), count, formats);
568 return E_NOTIMPL;
571 static HRESULT WINAPI device_manager_decoder_service_GetDecoderConfigurations(IDirectXVideoDecoderService *iface,
572 REFGUID guid, const DXVA2_VideoDesc *video_desc, IUnknown *reserved, UINT *count, DXVA2_ConfigPictureDecode **configs)
574 FIXME("%p, %s, %p, %p, %p, %p.\n", iface, debugstr_guid(guid), video_desc, reserved, count, configs);
576 return E_NOTIMPL;
579 static HRESULT WINAPI device_manager_decoder_service_CreateVideoDecoder(IDirectXVideoDecoderService *iface,
580 REFGUID guid, const DXVA2_VideoDesc *video_desc, DXVA2_ConfigPictureDecode *config, IDirect3DSurface9 **rts,
581 UINT num_surfaces, IDirectXVideoDecoder **decoder)
583 FIXME("%p, %s, %p, %p, %p, %u, %p.\n", iface, debugstr_guid(guid), video_desc, config, rts, num_surfaces,
584 decoder);
586 return E_NOTIMPL;
589 static const IDirectXVideoDecoderServiceVtbl device_manager_decoder_service_vtbl =
591 device_manager_decoder_service_QueryInterface,
592 device_manager_decoder_service_AddRef,
593 device_manager_decoder_service_Release,
594 device_manager_decoder_service_CreateSurface,
595 device_manager_decoder_service_GetDecoderDeviceGuids,
596 device_manager_decoder_service_GetDecoderRenderTargets,
597 device_manager_decoder_service_GetDecoderConfigurations,
598 device_manager_decoder_service_CreateVideoDecoder,
601 static HRESULT WINAPI device_manager_QueryInterface(IDirect3DDeviceManager9 *iface, REFIID riid, void **obj)
603 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
605 if (IsEqualIID(&IID_IDirect3DDeviceManager9, riid) ||
606 IsEqualIID(&IID_IUnknown, riid))
608 *obj = iface;
609 IDirect3DDeviceManager9_AddRef(iface);
610 return S_OK;
613 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
614 *obj = NULL;
615 return E_NOINTERFACE;
618 static ULONG WINAPI device_manager_AddRef(IDirect3DDeviceManager9 *iface)
620 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
621 ULONG refcount = InterlockedIncrement(&manager->refcount);
623 TRACE("%p, refcount %u.\n", iface, refcount);
625 return refcount;
628 static ULONG WINAPI device_manager_Release(IDirect3DDeviceManager9 *iface)
630 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
631 ULONG refcount = InterlockedDecrement(&manager->refcount);
632 size_t i;
634 TRACE("%p, refcount %u.\n", iface, refcount);
636 if (!refcount)
638 if (manager->device)
639 IDirect3DDevice9_Release(manager->device);
640 DeleteCriticalSection(&manager->cs);
641 for (i = 0; i < manager->count; ++i)
643 if (manager->handles[i].state_block)
644 IDirect3DStateBlock9_Release(manager->handles[i].state_block);
646 heap_free(manager->handles);
647 heap_free(manager);
650 return refcount;
653 static HRESULT WINAPI device_manager_ResetDevice(IDirect3DDeviceManager9 *iface, IDirect3DDevice9 *device,
654 UINT token)
656 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
657 size_t i;
659 TRACE("%p, %p, %#x.\n", iface, device, token);
661 if (token != manager->token)
662 return E_INVALIDARG;
664 EnterCriticalSection(&manager->cs);
665 if (manager->device)
667 for (i = 0; i < manager->count; ++i)
669 if (manager->handles[i].state_block)
670 IDirect3DStateBlock9_Release(manager->handles[i].state_block);
671 manager->handles[i].state_block = NULL;
672 manager->handles[i].flags |= HANDLE_FLAG_INVALID;
674 manager->locking_handle = NULL;
675 IDirect3DDevice9_Release(manager->device);
677 manager->device = device;
678 IDirect3DDevice9_AddRef(manager->device);
679 LeaveCriticalSection(&manager->cs);
681 WakeAllConditionVariable(&manager->lock);
683 return S_OK;
686 static HRESULT WINAPI device_manager_OpenDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE *hdevice)
688 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
689 HRESULT hr = S_OK;
690 size_t i;
692 TRACE("%p, %p.\n", iface, hdevice);
694 *hdevice = NULL;
696 EnterCriticalSection(&manager->cs);
697 if (!manager->device)
698 hr = DXVA2_E_NOT_INITIALIZED;
699 else
701 for (i = 0; i < manager->count; ++i)
703 if (!(manager->handles[i].flags & HANDLE_FLAG_OPEN))
705 manager->handles[i].flags |= HANDLE_FLAG_OPEN;
706 *hdevice = ULongToHandle(i + 1);
707 break;
711 if (dxva_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
712 sizeof(*manager->handles)))
714 *hdevice = ULongToHandle(manager->count + 1);
715 manager->handles[manager->count].flags = HANDLE_FLAG_OPEN;
716 manager->handles[manager->count].state_block = NULL;
717 manager->count++;
719 else
720 hr = E_OUTOFMEMORY;
722 LeaveCriticalSection(&manager->cs);
724 return hr;
727 static HRESULT device_manager_get_handle_index(struct device_manager *manager, HANDLE hdevice, size_t *idx)
729 if (!hdevice || hdevice > ULongToHandle(manager->count))
730 return E_HANDLE;
731 *idx = (ULONG_PTR)hdevice - 1;
732 return S_OK;
735 static HRESULT WINAPI device_manager_CloseDeviceHandle(IDirect3DDeviceManager9 *iface, HANDLE hdevice)
737 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
738 HRESULT hr;
739 size_t idx;
741 TRACE("%p, %p.\n", iface, hdevice);
743 EnterCriticalSection(&manager->cs);
744 if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
746 if (manager->handles[idx].flags & HANDLE_FLAG_OPEN)
748 if (manager->locking_handle == hdevice)
749 manager->locking_handle = NULL;
750 manager->handles[idx].flags = 0;
751 if (idx == manager->count - 1)
752 manager->count--;
753 if (manager->handles[idx].state_block)
754 IDirect3DStateBlock9_Release(manager->handles[idx].state_block);
755 manager->handles[idx].state_block = NULL;
757 else
758 hr = E_HANDLE;
760 LeaveCriticalSection(&manager->cs);
762 WakeAllConditionVariable(&manager->lock);
764 return hr;
767 static HRESULT WINAPI device_manager_TestDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice)
769 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
770 HRESULT hr;
771 size_t idx;
773 TRACE("%p, %p.\n", iface, hdevice);
775 EnterCriticalSection(&manager->cs);
776 if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
778 unsigned int flags = manager->handles[idx].flags;
780 if (flags & HANDLE_FLAG_INVALID)
781 hr = DXVA2_E_NEW_VIDEO_DEVICE;
782 else if (!(flags & HANDLE_FLAG_OPEN))
783 hr = E_HANDLE;
785 LeaveCriticalSection(&manager->cs);
787 return hr;
790 static HRESULT WINAPI device_manager_LockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice,
791 IDirect3DDevice9 **device, BOOL block)
793 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
794 HRESULT hr;
795 size_t idx;
797 TRACE("%p, %p, %p, %d.\n", iface, hdevice, device, block);
799 EnterCriticalSection(&manager->cs);
800 if (!manager->device)
801 hr = DXVA2_E_NOT_INITIALIZED;
802 else if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
804 if (manager->locking_handle && !block)
805 hr = DXVA2_E_VIDEO_DEVICE_LOCKED;
806 else
808 while (manager->locking_handle && block)
810 SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
813 if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
815 if (manager->handles[idx].flags & HANDLE_FLAG_INVALID)
816 hr = DXVA2_E_NEW_VIDEO_DEVICE;
817 else
819 if (manager->handles[idx].state_block)
821 if (FAILED(IDirect3DStateBlock9_Apply(manager->handles[idx].state_block)))
822 WARN("Failed to apply state.\n");
823 IDirect3DStateBlock9_Release(manager->handles[idx].state_block);
824 manager->handles[idx].state_block = NULL;
826 *device = manager->device;
827 IDirect3DDevice9_AddRef(*device);
828 manager->locking_handle = hdevice;
833 LeaveCriticalSection(&manager->cs);
835 return hr;
838 static HRESULT WINAPI device_manager_UnlockDevice(IDirect3DDeviceManager9 *iface, HANDLE hdevice, BOOL savestate)
840 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
841 HRESULT hr;
842 size_t idx;
844 TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
846 EnterCriticalSection(&manager->cs);
848 if (hdevice != manager->locking_handle)
849 hr = E_INVALIDARG;
850 else if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
852 manager->locking_handle = NULL;
853 if (savestate)
854 IDirect3DDevice9_CreateStateBlock(manager->device, D3DSBT_ALL, &manager->handles[idx].state_block);
857 LeaveCriticalSection(&manager->cs);
859 WakeAllConditionVariable(&manager->lock);
861 return hr;
864 static HRESULT WINAPI device_manager_GetVideoService(IDirect3DDeviceManager9 *iface, HANDLE hdevice, REFIID riid,
865 void **obj)
867 struct device_manager *manager = impl_from_IDirect3DDeviceManager9(iface);
868 HRESULT hr;
869 size_t idx;
871 TRACE("%p, %p, %s, %p.\n", iface, hdevice, debugstr_guid(riid), obj);
873 EnterCriticalSection(&manager->cs);
874 if (SUCCEEDED(hr = device_manager_get_handle_index(manager, hdevice, &idx)))
876 unsigned int flags = manager->handles[idx].flags;
878 if (flags & HANDLE_FLAG_INVALID)
879 hr = DXVA2_E_NEW_VIDEO_DEVICE;
880 else if (!(flags & HANDLE_FLAG_OPEN))
881 hr = E_HANDLE;
882 else
883 hr = IDirectXVideoProcessorService_QueryInterface(&manager->IDirectXVideoProcessorService_iface,
884 riid, obj);
886 LeaveCriticalSection(&manager->cs);
888 return hr;
891 static const IDirect3DDeviceManager9Vtbl device_manager_vtbl =
893 device_manager_QueryInterface,
894 device_manager_AddRef,
895 device_manager_Release,
896 device_manager_ResetDevice,
897 device_manager_OpenDeviceHandle,
898 device_manager_CloseDeviceHandle,
899 device_manager_TestDevice,
900 device_manager_LockDevice,
901 device_manager_UnlockDevice,
902 device_manager_GetVideoService,
905 BOOL WINAPI CapabilitiesRequestAndCapabilitiesReply( HMONITOR monitor, LPSTR buffer, DWORD length )
907 FIXME("(%p, %p, %d): stub\n", monitor, buffer, length);
909 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
910 return FALSE;
913 HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9(UINT *token, IDirect3DDeviceManager9 **manager)
915 struct device_manager *object;
917 TRACE("%p, %p.\n", token, manager);
919 *manager = NULL;
921 if (!(object = heap_alloc_zero(sizeof(*object))))
922 return E_OUTOFMEMORY;
924 object->IDirect3DDeviceManager9_iface.lpVtbl = &device_manager_vtbl;
925 object->IDirectXVideoProcessorService_iface.lpVtbl = &device_manager_processor_service_vtbl;
926 object->IDirectXVideoDecoderService_iface.lpVtbl = &device_manager_decoder_service_vtbl;
927 object->refcount = 1;
928 object->token = GetTickCount();
929 InitializeCriticalSection(&object->cs);
930 InitializeConditionVariable(&object->lock);
932 *token = object->token;
933 *manager = &object->IDirect3DDeviceManager9_iface;
935 return S_OK;
938 HRESULT WINAPI DXVA2CreateVideoService(IDirect3DDevice9 *device, REFIID riid, void **obj)
940 IDirect3DDeviceManager9 *manager;
941 HANDLE handle;
942 HRESULT hr;
943 UINT token;
945 TRACE("%p, %s, %p.\n", device, debugstr_guid(riid), obj);
947 if (FAILED(hr = DXVA2CreateDirect3DDeviceManager9(&token, &manager)))
948 return hr;
950 if (FAILED(hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token)))
951 goto done;
953 if (FAILED(hr = IDirect3DDeviceManager9_OpenDeviceHandle(manager, &handle)))
954 goto done;
956 hr = IDirect3DDeviceManager9_GetVideoService(manager, handle, riid, obj);
957 IDirect3DDeviceManager9_CloseDeviceHandle(manager, handle);
959 done:
960 IDirect3DDeviceManager9_Release(manager);
962 return hr;
965 BOOL WINAPI DegaussMonitor( HMONITOR monitor )
967 FIXME("(%p): stub\n", monitor);
969 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
970 return FALSE;
973 BOOL WINAPI DestroyPhysicalMonitor( HMONITOR monitor )
975 FIXME("(%p): stub\n", monitor);
977 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
978 return FALSE;
981 BOOL WINAPI DestroyPhysicalMonitors( DWORD arraySize, LPPHYSICAL_MONITOR array )
983 FIXME("(0x%x, %p): stub\n", arraySize, array);
985 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
986 return FALSE;
989 BOOL WINAPI GetCapabilitiesStringLength( HMONITOR monitor, LPDWORD length )
991 FIXME("(%p, %p): stub\n", monitor, length);
993 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
994 return FALSE;
997 BOOL WINAPI GetMonitorBrightness( HMONITOR monitor, LPDWORD minimum, LPDWORD current, LPDWORD maximum )
999 FIXME("(%p, %p, %p, %p): stub\n", monitor, minimum, current, maximum);
1001 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1002 return FALSE;
1005 BOOL WINAPI GetMonitorCapabilities( HMONITOR monitor, LPDWORD capabilities, LPDWORD temperatures )
1007 FIXME("(%p, %p, %p): stub\n", monitor, capabilities, temperatures);
1009 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1010 return FALSE;
1014 BOOL WINAPI GetMonitorColorTemperature( HMONITOR monitor, LPMC_COLOR_TEMPERATURE temperature )
1016 FIXME("(%p, %p): stub\n", monitor, temperature);
1018 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1019 return FALSE;
1022 BOOL WINAPI GetMonitorContrast( HMONITOR monitor, LPDWORD minimum, LPDWORD current, LPDWORD maximum )
1024 FIXME("(%p, %p, %p, %p): stub\n", monitor, minimum, current, maximum);
1026 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1027 return FALSE;
1030 BOOL WINAPI GetMonitorDisplayAreaPosition( HMONITOR monitor, MC_POSITION_TYPE type, LPDWORD minimum,
1031 LPDWORD current, LPDWORD maximum )
1033 FIXME("(%p, 0x%x, %p, %p, %p): stub\n", monitor, type, minimum, current, maximum);
1035 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1036 return FALSE;
1039 BOOL WINAPI GetMonitorDisplayAreaSize( HMONITOR monitor, MC_SIZE_TYPE type, LPDWORD minimum,
1040 LPDWORD current, LPDWORD maximum )
1042 FIXME("(%p, 0x%x, %p, %p, %p): stub\n", monitor, type, minimum, current, maximum);
1044 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1045 return FALSE;
1048 BOOL WINAPI GetMonitorRedGreenOrBlueDrive( HMONITOR monitor, MC_DRIVE_TYPE type, LPDWORD minimum,
1049 LPDWORD current, LPDWORD maximum )
1051 FIXME("(%p, 0x%x, %p, %p, %p): stub\n", monitor, type, minimum, current, maximum);
1053 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1054 return FALSE;
1057 BOOL WINAPI GetMonitorRedGreenOrBlueGain( HMONITOR monitor, MC_GAIN_TYPE type, LPDWORD minimum,
1058 LPDWORD current, LPDWORD maximum )
1060 FIXME("(%p, 0x%x, %p, %p, %p): stub\n", monitor, type, minimum, current, maximum);
1062 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1063 return FALSE;
1066 BOOL WINAPI GetMonitorTechnologyType( HMONITOR monitor, LPMC_DISPLAY_TECHNOLOGY_TYPE type )
1068 FIXME("(%p, %p): stub\n", monitor, type);
1070 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1071 return FALSE;
1074 BOOL WINAPI GetNumberOfPhysicalMonitorsFromHMONITOR( HMONITOR monitor, LPDWORD number )
1076 FIXME("(%p, %p): stub\n", monitor, number);
1078 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1079 return FALSE;
1082 HRESULT WINAPI GetNumberOfPhysicalMonitorsFromIDirect3DDevice9( IDirect3DDevice9 *device, LPDWORD number )
1084 FIXME("(%p, %p): stub\n", device, number);
1086 return E_NOTIMPL;
1089 BOOL WINAPI GetPhysicalMonitorsFromHMONITOR( HMONITOR monitor, DWORD arraySize, LPPHYSICAL_MONITOR array )
1091 FIXME("(%p, 0x%x, %p): stub\n", monitor, arraySize, array);
1093 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1094 return FALSE;
1097 HRESULT WINAPI GetPhysicalMonitorsFromIDirect3DDevice9( IDirect3DDevice9 *device, DWORD arraySize, LPPHYSICAL_MONITOR array )
1099 FIXME("(%p, 0x%x, %p): stub\n", device, arraySize, array);
1101 return E_NOTIMPL;
1104 BOOL WINAPI GetTimingReport( HMONITOR monitor, LPMC_TIMING_REPORT timingReport )
1106 FIXME("(%p, %p): stub\n", monitor, timingReport);
1108 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1109 return FALSE;
1112 BOOL WINAPI GetVCPFeatureAndVCPFeatureReply( HMONITOR monitor, BYTE vcpCode, LPMC_VCP_CODE_TYPE pvct,
1113 LPDWORD current, LPDWORD maximum )
1115 FIXME("(%p, 0x%02x, %p, %p, %p): stub\n", monitor, vcpCode, pvct, current, maximum);
1117 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1118 return FALSE;
1121 HRESULT WINAPI OPMGetVideoOutputsFromHMONITOR( HMONITOR monitor, /* OPM_VIDEO_OUTPUT_SEMANTICS */ int vos,
1122 ULONG *numVideoOutputs, /* IOPMVideoOutput */ void ***videoOutputs )
1124 FIXME("(%p, 0x%x, %p, %p): stub\n", monitor, vos, numVideoOutputs, videoOutputs);
1126 return E_NOTIMPL;
1129 HRESULT WINAPI OPMGetVideoOutputsFromIDirect3DDevice9Object( IDirect3DDevice9 *device, /* OPM_VIDEO_OUTPUT_SEMANTICS */ int vos,
1130 ULONG *numVideoOutputs, /* IOPMVideoOutput */ void ***videoOutputs )
1132 FIXME("(%p, 0x%x, %p, %p): stub\n", device, vos, numVideoOutputs, videoOutputs);
1134 return E_NOTIMPL;
1137 BOOL WINAPI RestoreMonitorFactoryColorDefaults( HMONITOR monitor )
1139 FIXME("(%p): stub\n", monitor);
1141 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1142 return FALSE;
1145 BOOL WINAPI RestoreMonitorFactoryDefaults( HMONITOR monitor )
1147 FIXME("(%p): stub\n", monitor);
1149 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1150 return FALSE;
1153 BOOL WINAPI SaveCurrentMonitorSettings( HMONITOR monitor )
1155 FIXME("(%p): stub\n", monitor);
1157 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1158 return FALSE;
1161 BOOL WINAPI SaveCurrentSettings( HMONITOR monitor )
1163 FIXME("(%p): stub\n", monitor);
1165 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1166 return FALSE;
1169 BOOL WINAPI SetMonitorBrightness( HMONITOR monitor, DWORD brightness )
1171 FIXME("(%p, 0x%x): stub\n", monitor, brightness);
1173 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1174 return FALSE;
1177 BOOL WINAPI SetMonitorColorTemperature( HMONITOR monitor, MC_COLOR_TEMPERATURE temperature )
1179 FIXME("(%p, 0x%x): stub\n", monitor, temperature);
1181 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1182 return FALSE;
1185 BOOL WINAPI SetMonitorContrast( HMONITOR monitor, DWORD contrast )
1187 FIXME("(%p, 0x%x): stub\n", monitor, contrast);
1189 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1190 return FALSE;
1193 BOOL WINAPI SetMonitorDisplayAreaPosition( HMONITOR monitor, MC_POSITION_TYPE type, DWORD position )
1195 FIXME("(%p, 0x%x, 0x%x): stub\n", monitor, type, position);
1197 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1198 return FALSE;
1201 BOOL WINAPI SetMonitorDisplayAreaSize( HMONITOR monitor, MC_SIZE_TYPE type, DWORD size )
1203 FIXME("(%p, 0x%x, 0x%x): stub\n", monitor, type, size);
1205 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1206 return FALSE;
1209 BOOL WINAPI SetMonitorRedGreenOrBlueDrive( HMONITOR monitor, MC_DRIVE_TYPE type, DWORD drive )
1211 FIXME("(%p, 0x%x, 0x%x): stub\n", monitor, type, drive);
1213 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1214 return FALSE;
1217 BOOL WINAPI SetMonitorRedGreenOrBlueGain( HMONITOR monitor, MC_GAIN_TYPE type, DWORD gain )
1219 FIXME("(%p, 0x%x, 0x%x): stub\n", monitor, type, gain);
1221 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1222 return FALSE;
1225 BOOL WINAPI SetVCPFeature( HMONITOR monitor, BYTE vcpCode, DWORD value )
1227 FIXME("(%p, 0x%02x, 0x%x): stub\n", monitor, vcpCode, value);
1229 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1230 return FALSE;