d3d11: handle VLC_CODEC_D3D11_OPAQUE_10B upload/download
[vlc.git] / modules / video_chroma / d3d9_fmt.c
blob73ad2aa55ab1185eeb91d6090f9462412312fb89
1 /*****************************************************************************
2 * d3d9_fmt.c : D3D9 helper calls
3 *****************************************************************************
4 * Copyright © 2017 VLC authors, VideoLAN and VideoLabs
6 * Authors: Steve Lhomme <robux4@gmail.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program 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
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
26 #include <assert.h>
28 #include "d3d9_fmt.h"
30 #include "../codec/avcodec/va_surface.h"
32 picture_sys_t *ActivePictureSys(picture_t *p_pic)
34 struct va_pic_context *pic_ctx = (struct va_pic_context*)p_pic->context;
35 return pic_ctx ? &pic_ctx->picsys : p_pic->p_sys;
38 #undef D3D9_CreateDevice
39 HRESULT D3D9_CreateDevice(vlc_object_t *o, d3d9_handle_t *hd3d, HWND hwnd,
40 const video_format_t *source, d3d9_device_t *out)
42 HRESULT hr;
44 UINT AdapterToUse = D3DADAPTER_DEFAULT;
45 D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
47 #ifndef NDEBUG
48 // Look for 'NVIDIA PerfHUD' adapter
49 // If it is present, override default settings
50 for (UINT Adapter=0; Adapter< IDirect3D9_GetAdapterCount(hd3d->obj); ++Adapter) {
51 D3DADAPTER_IDENTIFIER9 Identifier;
52 hr = IDirect3D9_GetAdapterIdentifier(hd3d->obj,Adapter,0,&Identifier);
53 if (SUCCEEDED(hr) && strstr(Identifier.Description,"PerfHUD") != 0) {
54 AdapterToUse = Adapter;
55 DeviceType = D3DDEVTYPE_REF;
56 break;
59 #endif
62 ** Get device capabilities
64 ZeroMemory(&out->caps, sizeof(out->caps));
65 hr = IDirect3D9_GetDeviceCaps(hd3d->obj, AdapterToUse, DeviceType, &out->caps);
66 if (FAILED(hr)) {
67 msg_Err(o, "Could not read adapter capabilities. (hr=0x%0lx)", hr);
68 return hr;
70 msg_Dbg(o, "D3D9 device caps 0x%0lX / 0x%0lX", out->caps.DevCaps, out->caps.DevCaps2);
72 /* TODO: need to test device capabilities and select the right render function */
73 if (!(out->caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES)) {
74 msg_Err(o, "Device does not support stretching from textures.");
75 return E_INVALIDARG;
78 if ( source->i_width > out->caps.MaxTextureWidth ||
79 source->i_height > out->caps.MaxTextureHeight )
81 msg_Err(o, "Textures too large %ux%u max possible: %ux%u",
82 source->i_width, source->i_height,
83 (unsigned) out->caps.MaxTextureWidth,
84 (unsigned) out->caps.MaxTextureHeight);
85 return E_INVALIDARG;
88 out->adapterId = AdapterToUse;
89 out->hwnd = hwnd;
90 if (D3D9_FillPresentationParameters(hd3d, source, out))
92 msg_Err(o, "Could not presentation parameters");
93 return E_INVALIDARG;
96 /* */
97 D3DADAPTER_IDENTIFIER9 d3dai;
98 if (FAILED(IDirect3D9_GetAdapterIdentifier(hd3d->obj, AdapterToUse,0, &d3dai))) {
99 msg_Warn(o, "IDirect3D9_GetAdapterIdentifier failed");
100 } else {
101 msg_Dbg(o, "Direct3d9 Device: %s %lu %lu %lu", d3dai.Description,
102 d3dai.VendorId, d3dai.DeviceId, d3dai.Revision );
105 DWORD thread_modes[] = { D3DCREATE_MULTITHREADED, 0 };
106 DWORD vertex_modes[] = { D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
107 D3DCREATE_HARDWARE_VERTEXPROCESSING,
108 D3DCREATE_MIXED_VERTEXPROCESSING,
109 D3DCREATE_SOFTWARE_VERTEXPROCESSING };
111 for (size_t t = 0; t < ARRAY_SIZE(thread_modes); t++)
113 for (size_t v = 0; v < ARRAY_SIZE(vertex_modes); v++)
115 DWORD creationFlags = thread_modes[t] | vertex_modes[v];
116 if (hd3d->use_ex)
117 hr = IDirect3D9Ex_CreateDeviceEx(hd3d->objex, AdapterToUse,
118 DeviceType, hwnd,
119 creationFlags,
120 &out->pp, NULL, &out->devex);
121 else
122 hr = IDirect3D9_CreateDevice(hd3d->obj, AdapterToUse,
123 DeviceType, hwnd,
124 creationFlags,
125 &out->pp, &out->dev);
126 if (SUCCEEDED(hr))
128 out->owner = true;
129 return hr;
134 msg_Err(o, "failed to create the D3D9%s device %d/%d. (hr=0x%lX)",
135 hd3d->use_ex?"Ex":"", AdapterToUse, DeviceType, hr);
136 return hr;
139 void D3D9_ReleaseDevice(d3d9_device_t *d3d_dev)
141 if (d3d_dev->dev)
143 IDirect3DDevice9_Release(d3d_dev->dev);
144 d3d_dev->dev = NULL;
149 * It setup vout_display_sys_t::d3dpp and vout_display_sys_t::rect_display
150 * from the default adapter.
152 int D3D9_FillPresentationParameters(d3d9_handle_t *hd3d,
153 const video_format_t *source, d3d9_device_t *out)
156 ** Get the current desktop display mode, so we can set up a back
157 ** buffer of the same format
159 D3DDISPLAYMODE d3ddm;
160 if (source->i_width)
162 HRESULT hr = IDirect3D9_GetAdapterDisplayMode(hd3d->obj, out->adapterId, &d3ddm);
163 if (FAILED(hr))
164 return VLC_EGENERIC;
167 /* Set up the structure used to create the D3DDevice. */
168 D3DPRESENT_PARAMETERS *d3dpp = &out->pp;
169 ZeroMemory(d3dpp, sizeof(D3DPRESENT_PARAMETERS));
170 d3dpp->Flags = D3DPRESENTFLAG_VIDEO;
171 d3dpp->Windowed = TRUE;
172 d3dpp->MultiSampleType = D3DMULTISAMPLE_NONE;
173 d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
174 d3dpp->EnableAutoDepthStencil = FALSE;
175 if (source->i_width)
177 d3dpp->hDeviceWindow = out->hwnd;
178 d3dpp->SwapEffect = D3DSWAPEFFECT_COPY;
179 d3dpp->BackBufferFormat = d3ddm.Format;
180 d3dpp->BackBufferCount = 1;
181 d3dpp->BackBufferWidth = __MAX((unsigned int)GetSystemMetrics(SM_CXVIRTUALSCREEN),
182 source->i_width);
183 d3dpp->BackBufferHeight = __MAX((unsigned int)GetSystemMetrics(SM_CYVIRTUALSCREEN),
184 source->i_height);
186 else
188 d3dpp->hDeviceWindow = NULL;
189 d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD;
190 d3dpp->BackBufferCount = 0;
191 d3dpp->BackBufferFormat = D3DFMT_X8R8G8B8; /* FIXME what to put here */
194 return VLC_SUCCESS;
197 void D3D9_Destroy(d3d9_handle_t *hd3d)
199 if (hd3d->obj)
201 IDirect3D9_Release(hd3d->obj);
202 hd3d->obj = NULL;
204 if (hd3d->hdll)
206 FreeLibrary(hd3d->hdll);
207 hd3d->hdll = NULL;
212 * It initializes an instance of Direct3D9
214 #undef D3D9_Create
215 int D3D9_Create(vlc_object_t *o, d3d9_handle_t *hd3d)
217 hd3d->hdll = LoadLibrary(TEXT("D3D9.DLL"));
218 if (!hd3d->hdll) {
219 msg_Warn(o, "cannot load d3d9.dll, aborting");
220 return VLC_EGENERIC;
223 LPDIRECT3D9 (WINAPI *OurDirect3DCreate9)(UINT SDKVersion);
224 OurDirect3DCreate9 =
225 (void *)GetProcAddress(hd3d->hdll, "Direct3DCreate9");
226 if (!OurDirect3DCreate9) {
227 msg_Err(o, "Cannot locate reference to Direct3DCreate9 ABI in DLL");
228 goto error;
231 HRESULT (WINAPI *OurDirect3DCreate9Ex)(UINT SDKVersion, IDirect3D9Ex **ppD3D);
232 OurDirect3DCreate9Ex =
233 (void *)GetProcAddress(hd3d->hdll, "Direct3DCreate9Ex");
235 /* Create the D3D object. */
236 hd3d->use_ex = false;
237 if (OurDirect3DCreate9Ex) {
238 HRESULT hr = OurDirect3DCreate9Ex(D3D_SDK_VERSION, &hd3d->objex);
239 if(!FAILED(hr)) {
240 msg_Dbg(o, "Using Direct3D9 Extended API!");
241 hd3d->use_ex = true;
245 if (!hd3d->obj)
247 hd3d->obj = OurDirect3DCreate9(D3D_SDK_VERSION);
248 if (!hd3d->obj) {
249 msg_Err(o, "Could not create Direct3D9 instance.");
250 goto error;
253 return VLC_SUCCESS;
254 error:
255 D3D9_Destroy( hd3d );
256 return VLC_EGENERIC;
259 int D3D9CheckDriverVersion(d3d9_handle_t *hd3d, d3d9_device_t *d3d_dev,
260 UINT vendorId, const struct wddm_version *min_ver)
262 D3DADAPTER_IDENTIFIER9 identifier;
263 HRESULT hr = IDirect3D9_GetAdapterIdentifier(hd3d->obj, d3d_dev->adapterId, 0, &identifier);
264 if (FAILED(hr))
265 return VLC_EGENERIC;
267 if (vendorId && identifier.VendorId != vendorId)
268 return VLC_SUCCESS;
270 int wddm, d3d_features, revision, build;
271 wddm = (int) (identifier.DriverVersion.HighPart >> 16 & 0xFFFF);
272 d3d_features = (int) (identifier.DriverVersion.HighPart >> 0 & 0xFFFF);
273 revision = (int) (identifier.DriverVersion.LowPart >> 16 & 0xFFFF);
274 build = (int) (identifier.DriverVersion.LowPart >> 0 & 0xFFFF);
276 bool newer =
277 wddm > min_ver->wddm ||
278 (wddm == min_ver->wddm && (d3d_features > min_ver->d3d_features ||
279 (d3d_features == min_ver->d3d_features &&
280 (revision > min_ver->revision ||
281 (revision == min_ver->revision &&
282 build > min_ver->build)))));
284 return newer ? VLC_SUCCESS : VLC_EGENERIC;