VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3DIf.cpp@ 69498

Last change on this file since 69498 was 69498, checked in by vboxsync, 7 years ago

backed out r118835 as it incorrectly updated the 'This file is based on' file headers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.2 KB
Line 
1/* $Id: VBoxDispD3DIf.cpp 69498 2017-10-28 15:07:25Z vboxsync $ */
2/** @file
3 * VBoxVideo Display D3D User mode dll
4 */
5
6/*
7 * Copyright (C) 2011-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "VBoxDispD3DIf.h"
19#include "VBoxDispD3DCmn.h"
20
21#include <iprt/assert.h>
22
23/** Convert a given FourCC code to a D3DDDIFORMAT enum. */
24#define VBOXWDDM_D3DDDIFORMAT_FROM_FOURCC(_a, _b, _c, _d) \
25 ((D3DDDIFORMAT)MAKEFOURCC(_a, _b, _c, _d))
26
27void VBoxDispD3DClose(VBOXDISPD3D *pD3D)
28{
29 FreeLibrary(pD3D->hD3DLib);
30 pD3D->hD3DLib = NULL;
31}
32
33/**
34 * Loads a system DLL.
35 *
36 * @returns Module handle or NULL
37 * @param pszName The DLL name.
38 */
39static HMODULE loadSystemDll(const char *pszName)
40{
41 /* Assumed here that DEBUG version of VBoxDispD3D.dll will not be installed system wide
42 but will be loaded from local folder of an application being debugged. */
43#ifndef DEBUG
44 char szPath[MAX_PATH];
45 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
46 size_t cbName = strlen(pszName) + 1;
47 if (cchPath + 1 + cbName > sizeof(szPath))
48 {
49 SetLastError(ERROR_FILENAME_EXCED_RANGE);
50 return NULL;
51 }
52 szPath[cchPath] = '\\';
53 memcpy(&szPath[cchPath + 1], pszName, cbName);
54 return LoadLibraryA(szPath);
55#else
56 return LoadLibraryA(pszName);
57#endif
58}
59
60HRESULT VBoxDispD3DOpen(VBOXDISPD3D *pD3D)
61{
62#ifdef VBOX_WDDM_WOW64
63 pD3D->hD3DLib = loadSystemDll("VBoxD3D9wddm-x86.dll");
64#else
65 pD3D->hD3DLib = loadSystemDll("VBoxD3D9wddm.dll");
66#endif
67 if (!pD3D->hD3DLib)
68 {
69 DWORD winErr = GetLastError(); NOREF(winErr);
70 WARN((__FUNCTION__": LoadLibrary failed, winErr = (%d)", winErr));
71 return E_FAIL;
72 }
73
74 do
75 {
76 pD3D->pfnDirect3DCreate9Ex = (PFNVBOXDISPD3DCREATE9EX)GetProcAddress(pD3D->hD3DLib, "Direct3DCreate9Ex");
77 if (!pD3D->pfnDirect3DCreate9Ex)
78 {
79 WARN(("no Direct3DCreate9Ex"));
80 break;
81 }
82
83 pD3D->pfnVBoxWineExD3DDev9CreateTexture = (PFNVBOXWINEEXD3DDEV9_CREATETEXTURE)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9CreateTexture");
84 if (!pD3D->pfnVBoxWineExD3DDev9CreateTexture)
85 {
86 WARN(("no VBoxWineExD3DDev9CreateTexture"));
87 break;
88 }
89
90 pD3D->pfnVBoxWineExD3DDev9CreateCubeTexture = (PFNVBOXWINEEXD3DDEV9_CREATECUBETEXTURE)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9CreateCubeTexture");
91 if (!pD3D->pfnVBoxWineExD3DDev9CreateCubeTexture)
92 {
93 WARN(("no VBoxWineExD3DDev9CreateCubeTexture"));
94 break;
95 }
96
97 pD3D->pfnVBoxWineExD3DDev9CreateVolumeTexture = (PFNVBOXWINEEXD3DDEV9_CREATEVOLUMETEXTURE)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9CreateVolumeTexture");
98 if (!pD3D->pfnVBoxWineExD3DDev9CreateVolumeTexture)
99 {
100 WARN(("no VBoxWineExD3DDev9CreateVolumeTexture"));
101 break;
102 }
103
104 pD3D->pfnVBoxWineExD3DDev9Flush = (PFNVBOXWINEEXD3DDEV9_FLUSH)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9Flush");
105 if (!pD3D->pfnVBoxWineExD3DDev9Flush)
106 {
107 WARN(("no VBoxWineExD3DDev9Flush"));
108 break;
109 }
110
111 pD3D->pfnVBoxWineExD3DDev9FlushToHost = (PFNVBOXWINEEXD3DDEV9_FLUSHTOHOST)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9FlushToHost");
112 if (!pD3D->pfnVBoxWineExD3DDev9FlushToHost)
113 {
114 WARN(("no VBoxWineExD3DDev9FlushToHost"));
115 break;
116 }
117
118 pD3D->pfnVBoxWineExD3DDev9Finish = (PFNVBOXWINEEXD3DDEV9_FINISH)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9Finish");
119 if (!pD3D->pfnVBoxWineExD3DDev9Finish)
120 {
121 WARN(("no VBoxWineExD3DDev9Finish"));
122 break;
123 }
124
125 pD3D->pfnVBoxWineExD3DDev9VolBlt = (PFNVBOXWINEEXD3DDEV9_VOLBLT)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9VolBlt");
126 if (!pD3D->pfnVBoxWineExD3DDev9VolBlt)
127 {
128 WARN(("no VBoxWineExD3DDev9VolBlt"));
129 break;
130 }
131
132 pD3D->pfnVBoxWineExD3DDev9VolTexBlt = (PFNVBOXWINEEXD3DDEV9_VOLTEXBLT)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9VolTexBlt");
133 if (!pD3D->pfnVBoxWineExD3DDev9VolTexBlt)
134 {
135 WARN(("no VBoxWineExD3DDev9VolTexBlt"));
136 break;
137 }
138
139 pD3D->pfnVBoxWineExD3DDev9Term = (PFNVBOXWINEEXD3DDEV9_TERM)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9Term");
140 if (!pD3D->pfnVBoxWineExD3DDev9Term)
141 {
142 WARN(("no VBoxWineExD3DDev9Term"));
143 break;
144 }
145
146 pD3D->pfnVBoxWineExD3DSwapchain9Present = (PFNVBOXWINEEXD3DSWAPCHAIN9_PRESENT)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DSwapchain9Present");
147 if (!pD3D->pfnVBoxWineExD3DSwapchain9Present)
148 {
149 WARN(("no VBoxWineExD3DSwapchain9Present"));
150 break;
151 }
152
153 pD3D->pfnVBoxWineExD3DSurf9GetHostId = (PFNVBOXWINEEXD3DSURF9_GETHOSTID)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DSurf9GetHostId");
154 if (!pD3D->pfnVBoxWineExD3DSurf9GetHostId)
155 {
156 WARN(("no VBoxWineExD3DSurf9GetHostId"));
157 break;
158 }
159
160 pD3D->pfnVBoxWineExD3DSurf9SyncToHost = (PFNVBOXWINEEXD3DSURF9_SYNCTOHOST)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DSurf9SyncToHost");
161 if (!pD3D->pfnVBoxWineExD3DSurf9SyncToHost)
162 {
163 WARN(("no VBoxWineExD3DSurf9SyncToHost"));
164 break;
165 }
166
167 pD3D->pfnVBoxWineExD3DSwapchain9GetHostWinID = (PFNVBOXWINEEXD3DSWAPCHAIN9_GETHOSTWINID)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DSwapchain9GetHostWinID");
168 if (!pD3D->pfnVBoxWineExD3DSwapchain9GetHostWinID)
169 {
170 WARN(("no VBoxWineExD3DSwapchain9GetHostWinID"));
171 break;
172 }
173
174 pD3D->pfnVBoxWineExD3DDev9GetHostId = (PFNVBOXWINEEXD3DDEV9_GETHOSTID)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DDev9GetHostId");
175 if (!pD3D->pfnVBoxWineExD3DDev9GetHostId)
176 {
177 WARN(("no VBoxWineExD3DDev9GetHostId"));
178 break;
179 }
180
181 return S_OK;
182
183 } while (0);
184
185 VBoxDispD3DClose(pD3D);
186
187 return E_FAIL;
188}
189
190
191
192static FORMATOP gVBoxFormatOps3D[] = {
193 {D3DDDIFMT_A8R8G8B8,
194 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
195 FORMATOP_SAME_FORMAT_RENDERTARGET|
196 FORMATOP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET|
197 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|FORMATOP_SRGBREAD|
198 FORMATOP_MEMBEROFGROUP_ARGB|
199 FORMATOP_SRGBWRITE|FORMATOP_VERTEXTEXTURE, 0, 0, 0},
200
201 {D3DDDIFMT_X8R8G8B8,
202 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
203 FORMATOP_SAME_FORMAT_RENDERTARGET|
204 FORMATOP_DISPLAYMODE|FORMATOP_3DACCELERATION|
205 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|FORMATOP_SRGBREAD|
206 FORMATOP_MEMBEROFGROUP_ARGB|
207 FORMATOP_SRGBWRITE|FORMATOP_VERTEXTEXTURE, 0, 0, 0},
208
209 {D3DDDIFMT_A2R10G10B10,
210 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
211 FORMATOP_SAME_FORMAT_RENDERTARGET|
212 0|
213 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|
214 FORMATOP_MEMBEROFGROUP_ARGB|
215 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
216
217 {D3DDDIFMT_X1R5G5B5,
218 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
219 FORMATOP_SAME_FORMAT_RENDERTARGET|
220 0|
221 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|
222 FORMATOP_MEMBEROFGROUP_ARGB|
223 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
224
225 {D3DDDIFMT_A1R5G5B5,
226 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
227 FORMATOP_SAME_FORMAT_RENDERTARGET|
228 FORMATOP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET|
229 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|
230 FORMATOP_MEMBEROFGROUP_ARGB|
231 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
232
233 {D3DDDIFMT_A4R4G4B4,
234 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
235 FORMATOP_SAME_FORMAT_RENDERTARGET|
236 FORMATOP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET|
237 FORMATOP_OFFSCREENPLAIN|
238 0|
239 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
240
241 {D3DDDIFMT_R5G6B5,
242 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
243 FORMATOP_SAME_FORMAT_RENDERTARGET|
244 FORMATOP_DISPLAYMODE|FORMATOP_3DACCELERATION|
245 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|
246 FORMATOP_MEMBEROFGROUP_ARGB|
247 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
248
249 {D3DDDIFMT_L16,
250 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|
251 0|
252 0|
253 FORMATOP_OFFSCREENPLAIN|
254 0|
255 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
256
257 {D3DDDIFMT_A8L8,
258 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|
259 0|
260 0|
261 FORMATOP_OFFSCREENPLAIN|
262 0|
263 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
264
265 {D3DDDIFMT_A8,
266 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|
267 0|
268 0|
269 FORMATOP_OFFSCREENPLAIN|
270 0|
271 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
272
273 {D3DDDIFMT_L8,
274 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|
275 0|
276 0|
277 FORMATOP_OFFSCREENPLAIN|
278 0|
279 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
280
281 {D3DDDIFMT_D16, FORMATOP_TEXTURE|FORMATOP_ZSTENCIL|FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH, 0, 0, 0},
282 {D3DDDIFMT_D24S8, FORMATOP_TEXTURE|FORMATOP_ZSTENCIL|FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH, 0, 0, 0},
283 {D3DDDIFMT_D24X8, FORMATOP_TEXTURE|FORMATOP_ZSTENCIL|FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH, 0, 0, 0},
284 {D3DDDIFMT_D16_LOCKABLE, FORMATOP_ZSTENCIL|FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH, 0, 0, 0},
285 {D3DDDIFMT_X8D24, FORMATOP_TEXTURE|FORMATOP_ZSTENCIL|FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH, 0, 0, 0},
286 {D3DDDIFMT_D32F_LOCKABLE, FORMATOP_TEXTURE|FORMATOP_ZSTENCIL|FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH, 0, 0, 0},
287 {D3DDDIFMT_S8D24, FORMATOP_TEXTURE|FORMATOP_ZSTENCIL|FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH, 0, 0, 0},
288
289 {D3DDDIFMT_DXT1,
290 FORMATOP_TEXTURE|FORMATOP_CUBETEXTURE|
291 0|
292 0|
293 FORMATOP_OFFSCREENPLAIN|FORMATOP_SRGBREAD|
294 0|
295 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
296
297 {D3DDDIFMT_DXT2,
298 FORMATOP_TEXTURE|FORMATOP_CUBETEXTURE|
299 0|
300 0|
301 FORMATOP_OFFSCREENPLAIN|FORMATOP_SRGBREAD|
302 0|
303 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
304
305 {D3DDDIFMT_DXT3,
306 FORMATOP_TEXTURE|FORMATOP_CUBETEXTURE|
307 0|
308 0|
309 FORMATOP_OFFSCREENPLAIN|FORMATOP_SRGBREAD|
310 0|
311 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
312
313 {D3DDDIFMT_DXT4,
314 FORMATOP_TEXTURE|FORMATOP_CUBETEXTURE|
315 0|
316 0|
317 FORMATOP_OFFSCREENPLAIN|FORMATOP_SRGBREAD|
318 0|
319 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
320
321 {D3DDDIFMT_DXT5,
322 FORMATOP_TEXTURE|FORMATOP_CUBETEXTURE|
323 0|
324 0|
325 FORMATOP_OFFSCREENPLAIN|FORMATOP_SRGBREAD|
326 0|
327 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
328
329 {D3DDDIFMT_X8L8V8U8,
330 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|
331 0|
332 0|
333 0|
334 FORMATOP_BUMPMAP|
335 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
336
337 {D3DDDIFMT_A2W10V10U10,
338 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|
339 0|
340 0|
341 0|
342 FORMATOP_BUMPMAP|
343 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
344
345 {D3DDDIFMT_V8U8,
346 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|
347 0|
348 0|
349 0|
350 FORMATOP_BUMPMAP|
351 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
352
353 {D3DDDIFMT_Q8W8V8U8,
354 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
355 0|
356 0|
357 FORMATOP_OFFSCREENPLAIN|
358 FORMATOP_BUMPMAP|
359 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
360
361 {D3DDDIFMT_CxV8U8, FORMATOP_NOFILTER|FORMATOP_NOALPHABLEND|FORMATOP_NOTEXCOORDWRAPNORMIP, 0, 0, 0},
362
363 {D3DDDIFMT_R16F,
364 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
365 FORMATOP_SAME_FORMAT_RENDERTARGET|
366 0|
367 FORMATOP_OFFSCREENPLAIN|
368 0|
369 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
370
371 {D3DDDIFMT_R32F,
372 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
373 FORMATOP_SAME_FORMAT_RENDERTARGET|
374 0|
375 FORMATOP_OFFSCREENPLAIN|
376 0|
377 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
378
379 {D3DDDIFMT_G16R16F,
380 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
381 FORMATOP_SAME_FORMAT_RENDERTARGET|
382 0|
383 FORMATOP_OFFSCREENPLAIN|
384 0|
385 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
386
387 {D3DDDIFMT_G32R32F,
388 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
389 FORMATOP_SAME_FORMAT_RENDERTARGET|
390 0|
391 FORMATOP_OFFSCREENPLAIN|
392 0|
393 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
394
395// Floating-point formats are not implemented in Chromium.
396 {D3DDDIFMT_A16B16G16R16F,
397 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
398 FORMATOP_SAME_FORMAT_RENDERTARGET|
399 0|
400 FORMATOP_OFFSCREENPLAIN|
401 0|
402 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
403
404 {D3DDDIFMT_A32B32G32R32F,
405 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
406 FORMATOP_SAME_FORMAT_RENDERTARGET|
407 0|
408 FORMATOP_OFFSCREENPLAIN|
409 0|
410 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
411
412 {D3DDDIFMT_G16R16,
413 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
414 FORMATOP_SAME_FORMAT_RENDERTARGET|
415 0|
416 FORMATOP_OFFSCREENPLAIN|
417 0|
418 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
419
420 {D3DDDIFMT_A16B16G16R16,
421 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
422 FORMATOP_SAME_FORMAT_RENDERTARGET|
423 0|
424 FORMATOP_OFFSCREENPLAIN|
425 0|
426 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
427
428 {D3DDDIFMT_V16U16,
429 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|
430 0|
431 0|
432 0|
433 FORMATOP_BUMPMAP|
434 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
435
436 {D3DDDIFMT_P8, FORMATOP_DISPLAYMODE|FORMATOP_3DACCELERATION|FORMATOP_OFFSCREENPLAIN, 0, 0, 0},
437
438 {D3DDDIFMT_UYVY,
439 0|
440 0|
441 0|
442 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|
443 FORMATOP_NOFILTER|
444 FORMATOP_NOALPHABLEND|
445 FORMATOP_NOTEXCOORDWRAPNORMIP, 0, 0, 0},
446
447 {D3DDDIFMT_YUY2,
448 0|
449 0|
450 0|
451 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|
452 FORMATOP_NOFILTER|
453 FORMATOP_NOALPHABLEND|
454 FORMATOP_NOTEXCOORDWRAPNORMIP, 0, 0, 0},
455
456 {VBOXWDDM_D3DDDIFORMAT_FROM_FOURCC('Y', 'V', '1', '2'),
457 0|
458 0|
459 0|
460 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|
461 FORMATOP_NOFILTER|
462 FORMATOP_NOALPHABLEND|
463 FORMATOP_NOTEXCOORDWRAPNORMIP, 0, 0, 0},
464
465 {D3DDDIFMT_Q16W16V16U16,
466 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
467 FORMATOP_SAME_FORMAT_RENDERTARGET|
468 0|
469 FORMATOP_OFFSCREENPLAIN|
470 FORMATOP_BUMPMAP|FORMATOP_DMAP|
471 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
472
473 {D3DDDIFMT_X8B8G8R8,
474 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
475 FORMATOP_SAME_FORMAT_RENDERTARGET|
476 FORMATOP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET|
477 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|FORMATOP_SRGBREAD|
478 FORMATOP_DMAP|FORMATOP_MEMBEROFGROUP_ARGB|
479 FORMATOP_SRGBWRITE|FORMATOP_AUTOGENMIPMAP|FORMATOP_VERTEXTEXTURE|
480 FORMATOP_OVERLAY, 0, 0, 0},
481
482 {D3DDDIFMT_BINARYBUFFER, FORMATOP_OFFSCREENPLAIN, 0, 0, 0},
483
484 {D3DDDIFMT_A4L4,
485 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|
486 0|
487 0|
488 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|
489 FORMATOP_DMAP|
490 FORMATOP_VERTEXTEXTURE, 0, 0, 0},
491
492 {D3DDDIFMT_A2B10G10R10,
493 FORMATOP_TEXTURE|FORMATOP_VOLUMETEXTURE|FORMATOP_CUBETEXTURE|FORMATOP_OFFSCREEN_RENDERTARGET|
494 FORMATOP_SAME_FORMAT_RENDERTARGET|
495 0|
496 FORMATOP_CONVERT_TO_ARGB|FORMATOP_OFFSCREENPLAIN|
497 FORMATOP_DMAP|FORMATOP_MEMBEROFGROUP_ARGB|
498 FORMATOP_AUTOGENMIPMAP|FORMATOP_VERTEXTEXTURE, 0, 0, 0},
499};
500
501static FORMATOP gVBoxFormatOpsBase[] = {
502 {D3DDDIFMT_X8R8G8B8, FORMATOP_DISPLAYMODE, 0, 0, 0},
503
504 {D3DDDIFMT_R8G8B8, FORMATOP_DISPLAYMODE, 0, 0, 0},
505
506 {D3DDDIFMT_R5G6B5, FORMATOP_DISPLAYMODE, 0, 0, 0},
507
508 {D3DDDIFMT_P8, FORMATOP_DISPLAYMODE, 0, 0, 0},
509};
510
511static DDSURFACEDESC gVBoxSurfDescsBase[] = {
512 {
513 sizeof (DDSURFACEDESC), /* DWORD dwSize; */
514 DDSD_CAPS | DDSD_PIXELFORMAT, /* DWORD dwFlags; */
515 0, /* DWORD dwHeight; */
516 0, /* DWORD dwWidth; */
517 {
518 0, /* Union */
519 /* LONG lPitch; */
520 /* DWORD dwLinearSize; */
521 },
522 0, /* DWORD dwBackBufferCount; */
523 {
524 0, /* Union */
525 /* DWORD dwMipMapCount; */
526 /* DWORD dwZBufferBitDepth; */
527 /* DWORD dwRefreshRate; */
528 },
529 0, /* DWORD dwAlphaBitDepth; */
530 0, /* DWORD dwReserved; */
531 NULL, /* LPVOID lpSurface; */
532 {
533 0, /* DWORD dwColorSpaceLowValue; */
534 0, /* DWORD dwColorSpaceHighValue; */
535 }, /* DDCOLORKEY ddckCKDestOverlay; */
536 {
537 0, /* DWORD dwColorSpaceLowValue; */
538 0, /* DWORD dwColorSpaceHighValue; */
539 }, /* DDCOLORKEY ddckCKDestBlt; */
540 {
541 0, /* DWORD dwColorSpaceLowValue; */
542 0, /* DWORD dwColorSpaceHighValue; */
543 }, /* DDCOLORKEY ddckCKSrcOverlay; */
544 {
545 0, /* DWORD dwColorSpaceLowValue; */
546 0, /* DWORD dwColorSpaceHighValue; */
547 }, /* DDCOLORKEY ddckCKSrcBlt; */
548 {
549 sizeof (DDPIXELFORMAT), /* DWORD dwSize; */
550 DDPF_RGB, /* DWORD dwFlags; */
551 0, /* DWORD dwFourCC; */
552 {
553 32, /* union */
554 /* DWORD dwRGBBitCount; */
555 /* DWORD dwYUVBitCount; */
556 /* DWORD dwZBufferBitDepth; */
557 /* DWORD dwAlphaBitDepth; */
558 /* DWORD dwLuminanceBitCount; */
559 /* DWORD dwBumpBitCount; */
560 },
561 {
562 0xff0000, /* union */
563 /* DWORD dwRBitMask; */
564 /* DWORD dwYBitMask; */
565 /* DWORD dwStencilBitDepth; */
566 /* DWORD dwLuminanceBitMask; */
567 /* DWORD dwBumpDuBitMask; */
568 },
569 {
570 0xff00,
571 /* DWORD dwGBitMask; */
572 /* DWORD dwUBitMask; */
573 /* DWORD dwZBitMask; */
574 /* DWORD dwBumpDvBitMask; */
575 },
576 {
577 0xff,
578 /* DWORD dwBBitMask; */
579 /* DWORD dwVBitMask; */
580 /* DWORD dwStencilBitMask; */
581 /* DWORD dwBumpLuminanceBitMask; */
582 },
583 {
584 0,
585 /* DWORD dwRGBAlphaBitMask; */
586 /* DWORD dwYUVAlphaBitMask; */
587 /* DWORD dwLuminanceAlphaBitMask; */
588 /* DWORD dwRGBZBitMask; */
589 /* DWORD dwYUVZBitMask; */
590 },
591 }, /* DDPIXELFORMAT ddpfPixelFormat; */
592 {
593 DDSCAPS_BACKBUFFER
594 | DDSCAPS_COMPLEX
595 | DDSCAPS_FLIP
596 | DDSCAPS_FRONTBUFFER
597 | DDSCAPS_LOCALVIDMEM
598 | DDSCAPS_PRIMARYSURFACE
599 | DDSCAPS_VIDEOMEMORY
600 | DDSCAPS_VISIBLE /* DWORD dwCaps; */
601 } /* DDSCAPS ddsCaps; */
602 },
603 {
604 sizeof (DDSURFACEDESC), /* DWORD dwSize; */
605 DDSD_CAPS | DDSD_PIXELFORMAT, /* DWORD dwFlags; */
606 0, /* DWORD dwHeight; */
607 0, /* DWORD dwWidth; */
608 {
609 0, /* Union */
610 /* LONG lPitch; */
611 /* DWORD dwLinearSize; */
612 },
613 0, /* DWORD dwBackBufferCount; */
614 {
615 0, /* Union */
616 /* DWORD dwMipMapCount; */
617 /* DWORD dwZBufferBitDepth; */
618 /* DWORD dwRefreshRate; */
619 },
620 0, /* DWORD dwAlphaBitDepth; */
621 0, /* DWORD dwReserved; */
622 NULL, /* LPVOID lpSurface; */
623 {
624 0, /* DWORD dwColorSpaceLowValue; */
625 0, /* DWORD dwColorSpaceHighValue; */
626 }, /* DDCOLORKEY ddckCKDestOverlay; */
627 {
628 0, /* DWORD dwColorSpaceLowValue; */
629 0, /* DWORD dwColorSpaceHighValue; */
630 }, /* DDCOLORKEY ddckCKDestBlt; */
631 {
632 0, /* DWORD dwColorSpaceLowValue; */
633 0, /* DWORD dwColorSpaceHighValue; */
634 }, /* DDCOLORKEY ddckCKSrcOverlay; */
635 {
636 0, /* DWORD dwColorSpaceLowValue; */
637 0, /* DWORD dwColorSpaceHighValue; */
638 }, /* DDCOLORKEY ddckCKSrcBlt; */
639 {
640 sizeof (DDPIXELFORMAT), /* DWORD dwSize; */
641 DDPF_RGB, /* DWORD dwFlags; */
642 0, /* DWORD dwFourCC; */
643 {
644 24, /* union */
645 /* DWORD dwRGBBitCount; */
646 /* DWORD dwYUVBitCount; */
647 /* DWORD dwZBufferBitDepth; */
648 /* DWORD dwAlphaBitDepth; */
649 /* DWORD dwLuminanceBitCount; */
650 /* DWORD dwBumpBitCount; */
651 },
652 {
653 0xff0000, /* union */
654 /* DWORD dwRBitMask; */
655 /* DWORD dwYBitMask; */
656 /* DWORD dwStencilBitDepth; */
657 /* DWORD dwLuminanceBitMask; */
658 /* DWORD dwBumpDuBitMask; */
659 },
660 {
661 0xff00,
662 /* DWORD dwGBitMask; */
663 /* DWORD dwUBitMask; */
664 /* DWORD dwZBitMask; */
665 /* DWORD dwBumpDvBitMask; */
666 },
667 {
668 0xff,
669 /* DWORD dwBBitMask; */
670 /* DWORD dwVBitMask; */
671 /* DWORD dwStencilBitMask; */
672 /* DWORD dwBumpLuminanceBitMask; */
673 },
674 {
675 0,
676 /* DWORD dwRGBAlphaBitMask; */
677 /* DWORD dwYUVAlphaBitMask; */
678 /* DWORD dwLuminanceAlphaBitMask; */
679 /* DWORD dwRGBZBitMask; */
680 /* DWORD dwYUVZBitMask; */
681 },
682 }, /* DDPIXELFORMAT ddpfPixelFormat; */
683 {
684 DDSCAPS_BACKBUFFER
685 | DDSCAPS_COMPLEX
686 | DDSCAPS_FLIP
687 | DDSCAPS_FRONTBUFFER
688 | DDSCAPS_LOCALVIDMEM
689 | DDSCAPS_PRIMARYSURFACE
690 | DDSCAPS_VIDEOMEMORY
691 | DDSCAPS_VISIBLE /* DWORD dwCaps; */
692 } /* DDSCAPS ddsCaps; */
693 },
694 {
695 sizeof (DDSURFACEDESC), /* DWORD dwSize; */
696 DDSD_CAPS | DDSD_PIXELFORMAT, /* DWORD dwFlags; */
697 0, /* DWORD dwHeight; */
698 0, /* DWORD dwWidth; */
699 {
700 0, /* Union */
701 /* LONG lPitch; */
702 /* DWORD dwLinearSize; */
703 },
704 0, /* DWORD dwBackBufferCount; */
705 {
706 0, /* Union */
707 /* DWORD dwMipMapCount; */
708 /* DWORD dwZBufferBitDepth; */
709 /* DWORD dwRefreshRate; */
710 },
711 0, /* DWORD dwAlphaBitDepth; */
712 0, /* DWORD dwReserved; */
713 NULL, /* LPVOID lpSurface; */
714 {
715 0, /* DWORD dwColorSpaceLowValue; */
716 0, /* DWORD dwColorSpaceHighValue; */
717 }, /* DDCOLORKEY ddckCKDestOverlay; */
718 {
719 0, /* DWORD dwColorSpaceLowValue; */
720 0, /* DWORD dwColorSpaceHighValue; */
721 }, /* DDCOLORKEY ddckCKDestBlt; */
722 {
723 0, /* DWORD dwColorSpaceLowValue; */
724 0, /* DWORD dwColorSpaceHighValue; */
725 }, /* DDCOLORKEY ddckCKSrcOverlay; */
726 {
727 0, /* DWORD dwColorSpaceLowValue; */
728 0, /* DWORD dwColorSpaceHighValue; */
729 }, /* DDCOLORKEY ddckCKSrcBlt; */
730 {
731 sizeof (DDPIXELFORMAT), /* DWORD dwSize; */
732 DDPF_RGB, /* DWORD dwFlags; */
733 0, /* DWORD dwFourCC; */
734 {
735 16, /* union */
736 /* DWORD dwRGBBitCount; */
737 /* DWORD dwYUVBitCount; */
738 /* DWORD dwZBufferBitDepth; */
739 /* DWORD dwAlphaBitDepth; */
740 /* DWORD dwLuminanceBitCount; */
741 /* DWORD dwBumpBitCount; */
742 },
743 {
744 0xf800, /* union */
745 /* DWORD dwRBitMask; */
746 /* DWORD dwYBitMask; */
747 /* DWORD dwStencilBitDepth; */
748 /* DWORD dwLuminanceBitMask; */
749 /* DWORD dwBumpDuBitMask; */
750 },
751 {
752 0x7e0,
753 /* DWORD dwGBitMask; */
754 /* DWORD dwUBitMask; */
755 /* DWORD dwZBitMask; */
756 /* DWORD dwBumpDvBitMask; */
757 },
758 {
759 0x1f,
760 /* DWORD dwBBitMask; */
761 /* DWORD dwVBitMask; */
762 /* DWORD dwStencilBitMask; */
763 /* DWORD dwBumpLuminanceBitMask; */
764 },
765 {
766 0,
767 /* DWORD dwRGBAlphaBitMask; */
768 /* DWORD dwYUVAlphaBitMask; */
769 /* DWORD dwLuminanceAlphaBitMask; */
770 /* DWORD dwRGBZBitMask; */
771 /* DWORD dwYUVZBitMask; */
772 },
773 }, /* DDPIXELFORMAT ddpfPixelFormat; */
774 {
775 DDSCAPS_BACKBUFFER
776 | DDSCAPS_COMPLEX
777 | DDSCAPS_FLIP
778 | DDSCAPS_FRONTBUFFER
779 | DDSCAPS_LOCALVIDMEM
780 | DDSCAPS_PRIMARYSURFACE
781 | DDSCAPS_VIDEOMEMORY
782 | DDSCAPS_VISIBLE /* DWORD dwCaps; */
783 } /* DDSCAPS ddsCaps; */
784 },
785};
786
787#ifdef VBOX_WITH_VIDEOHWACCEL
788
789static void vboxVhwaPopulateOverlayFourccSurfDesc(DDSURFACEDESC *pDesc, uint32_t fourcc)
790{
791 memset(pDesc, 0, sizeof (DDSURFACEDESC));
792
793 pDesc->dwSize = sizeof (DDSURFACEDESC);
794 pDesc->dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT;
795 pDesc->ddpfPixelFormat.dwSize = sizeof (DDPIXELFORMAT);
796 pDesc->ddpfPixelFormat.dwFlags = DDPF_FOURCC;
797 pDesc->ddpfPixelFormat.dwFourCC = fourcc;
798 pDesc->ddsCaps.dwCaps = DDSCAPS_BACKBUFFER
799 | DDSCAPS_COMPLEX
800 | DDSCAPS_FLIP
801 | DDSCAPS_FRONTBUFFER
802 | DDSCAPS_LOCALVIDMEM
803 | DDSCAPS_OVERLAY
804 | DDSCAPS_VIDEOMEMORY
805 | DDSCAPS_VISIBLE;
806}
807
808static bool vboxPixFormatMatch(DDPIXELFORMAT *pFormat1, DDPIXELFORMAT *pFormat2)
809{
810 return !memcmp(pFormat1, pFormat2, sizeof (DDPIXELFORMAT));
811}
812
813HRESULT vboxSurfDescMerge(DDSURFACEDESC *paDescs, uint32_t *pcDescs, uint32_t cMaxDescs, DDSURFACEDESC *pDesc)
814{
815 uint32_t cDescs = *pcDescs;
816
817 Assert(cMaxDescs >= cDescs);
818 Assert(pDesc->dwFlags == (DDSD_CAPS | DDSD_PIXELFORMAT));
819 if (pDesc->dwFlags != (DDSD_CAPS | DDSD_PIXELFORMAT))
820 return E_INVALIDARG;
821
822 for (uint32_t i = 0; i < cDescs; ++i)
823 {
824 DDSURFACEDESC *pCur = &paDescs[i];
825 if (vboxPixFormatMatch(&pCur->ddpfPixelFormat, &pDesc->ddpfPixelFormat))
826 {
827 if (pDesc->dwFlags & DDSD_CAPS)
828 {
829 pCur->dwFlags |= DDSD_CAPS;
830 pCur->ddsCaps.dwCaps |= pDesc->ddsCaps.dwCaps;
831 }
832 return S_OK;
833 }
834 }
835
836 if (cMaxDescs > cDescs)
837 {
838 paDescs[cDescs] = *pDesc;
839 ++cDescs;
840 *pcDescs = cDescs;
841 return VINF_SUCCESS;
842 }
843 return E_FAIL;
844}
845
846HRESULT vboxFormatOpsMerge(FORMATOP *paOps, uint32_t *pcOps, uint32_t cMaxOps, FORMATOP *pOp)
847{
848 uint32_t cOps = *pcOps;
849
850 Assert(cMaxOps >= cOps);
851
852 for (uint32_t i = 0; i < cOps; ++i)
853 {
854 FORMATOP *pCur = &paOps[i];
855 if (pCur->Format == pOp->Format)
856 {
857 pCur->Operations |= pOp->Operations;
858 Assert(pCur->FlipMsTypes == pOp->FlipMsTypes);
859 Assert(pCur->BltMsTypes == pOp->BltMsTypes);
860 Assert(pCur->PrivateFormatBitCount == pOp->PrivateFormatBitCount);
861 return S_OK;
862 }
863 }
864
865 if (cMaxOps > cOps)
866 {
867 paOps[cOps] = *pOp;
868 ++cOps;
869 *pcOps = cOps;
870 return VINF_SUCCESS;
871 }
872 return E_FAIL;
873}
874
875HRESULT VBoxDispD3DGlobal2DFormatsInit(PVBOXWDDMDISP_ADAPTER pAdapter)
876{
877 HRESULT hr = S_OK;
878 memset(&pAdapter->D3D, 0, sizeof (pAdapter->D3D));
879 memset(&pAdapter->Formats, 0, sizeof (pAdapter->Formats));
880
881 /* just calc the max number of formats */
882 uint32_t cFormats = RT_ELEMENTS(gVBoxFormatOpsBase);
883 uint32_t cSurfDescs = RT_ELEMENTS(gVBoxSurfDescsBase);
884 uint32_t cOverlayFormats = 0;
885 for (uint32_t i = 0; i < pAdapter->cHeads; ++i)
886 {
887 VBOXDISPVHWA_INFO *pVhwa = &pAdapter->aHeads[i].Vhwa;
888 if (pVhwa->Settings.fFlags & VBOXVHWA_F_ENABLED)
889 {
890 cOverlayFormats += pVhwa->Settings.cFormats;
891 }
892 }
893
894 cFormats += cOverlayFormats;
895 cSurfDescs += cOverlayFormats;
896
897 uint32_t cbFormatOps = cFormats * sizeof (FORMATOP);
898 cbFormatOps = (cbFormatOps + 7) & ~3;
899 /* ensure the surf descs are 8 byte aligned */
900 uint32_t offSurfDescs = (cbFormatOps + 7) & ~3;
901 uint32_t cbSurfDescs = cSurfDescs * sizeof (DDSURFACEDESC);
902 uint32_t cbBuf = offSurfDescs + cbSurfDescs;
903 uint8_t* pvBuf = (uint8_t*)RTMemAllocZ(cbBuf);
904 if (pvBuf)
905 {
906 pAdapter->Formats.paFormstOps = (FORMATOP*)pvBuf;
907 memcpy ((void*)pAdapter->Formats.paFormstOps , gVBoxFormatOpsBase, sizeof (gVBoxFormatOpsBase));
908 pAdapter->Formats.cFormstOps = RT_ELEMENTS(gVBoxFormatOpsBase);
909
910 FORMATOP fo = {D3DDDIFMT_UNKNOWN, 0, 0, 0, 0};
911 for (uint32_t i = 0; i < pAdapter->cHeads; ++i)
912 {
913 VBOXDISPVHWA_INFO *pVhwa = &pAdapter->aHeads[i].Vhwa;
914 if (pVhwa->Settings.fFlags & VBOXVHWA_F_ENABLED)
915 {
916 for (uint32_t j = 0; j < pVhwa->Settings.cFormats; ++j)
917 {
918 fo.Format = pVhwa->Settings.aFormats[j];
919 fo.Operations = FORMATOP_OVERLAY;
920 hr = vboxFormatOpsMerge((FORMATOP *)pAdapter->Formats.paFormstOps, &pAdapter->Formats.cFormstOps, cFormats, &fo);
921 if (FAILED(hr))
922 {
923 WARN(("vboxFormatOpsMerge failed, hr 0x%x", hr));
924 }
925 }
926 }
927 }
928
929 pAdapter->Formats.paSurfDescs = (DDSURFACEDESC*)(pvBuf + offSurfDescs);
930 memcpy ((void*)pAdapter->Formats.paSurfDescs , gVBoxSurfDescsBase, sizeof (gVBoxSurfDescsBase));
931 pAdapter->Formats.cSurfDescs = RT_ELEMENTS(gVBoxSurfDescsBase);
932
933 DDSURFACEDESC sd;
934 for (uint32_t i = 0; i < pAdapter->cHeads; ++i)
935 {
936 VBOXDISPVHWA_INFO *pVhwa = &pAdapter->aHeads[i].Vhwa;
937 if (pVhwa->Settings.fFlags & VBOXVHWA_F_ENABLED)
938 {
939 for (uint32_t j = 0; j < pVhwa->Settings.cFormats; ++j)
940 {
941 uint32_t fourcc = vboxWddmFormatToFourcc(pVhwa->Settings.aFormats[j]);
942 if (fourcc)
943 {
944 vboxVhwaPopulateOverlayFourccSurfDesc(&sd, fourcc);
945 hr = vboxSurfDescMerge((DDSURFACEDESC *)pAdapter->Formats.paSurfDescs, &pAdapter->Formats.cSurfDescs, cSurfDescs, &sd);
946 if (FAILED(hr))
947 {
948 WARN(("vboxFormatOpsMerge failed, hr 0x%x", hr));
949 }
950 }
951 }
952 }
953 }
954 }
955 else
956 {
957 WARN(("RTMemAllocZ failed"));
958 return E_FAIL;
959 }
960 return S_OK;
961}
962
963void VBoxDispD3DGlobal2DFormatsTerm(PVBOXWDDMDISP_ADAPTER pAdapter)
964{
965 if (pAdapter->Formats.paFormstOps)
966 RTMemFree((void *)pAdapter->Formats.paFormstOps);
967}
968
969#endif
970
971static CRITICAL_SECTION g_VBoxDispD3DGlobalCritSect;
972static VBOXWDDMDISP_D3D g_VBoxDispD3DGlobalD3D;
973static VBOXWDDMDISP_FORMATS g_VBoxDispD3DGlobalD3DFormats;
974static uint32_t g_cVBoxDispD3DGlobalOpens;
975
976void vboxDispD3DGlobalLock()
977{
978 EnterCriticalSection(&g_VBoxDispD3DGlobalCritSect);
979}
980
981void vboxDispD3DGlobalUnlock()
982{
983 LeaveCriticalSection(&g_VBoxDispD3DGlobalCritSect);
984}
985
986void VBoxDispD3DGlobalInit()
987{
988 g_cVBoxDispD3DGlobalOpens = 0;
989 InitializeCriticalSection(&g_VBoxDispD3DGlobalCritSect);
990}
991
992void VBoxDispD3DGlobalTerm()
993{
994 DeleteCriticalSection(&g_VBoxDispD3DGlobalCritSect);
995}
996
997static void vboxDispD3DGlobalD3DFormatsInit(PVBOXWDDMDISP_FORMATS pFormats)
998{
999 memset(pFormats, 0, sizeof (*pFormats));
1000 pFormats->paFormstOps = gVBoxFormatOps3D;
1001 pFormats->cFormstOps = RT_ELEMENTS(gVBoxFormatOps3D);
1002}
1003
1004#ifndef D3DCAPS2_CANRENDERWINDOWED
1005#define D3DCAPS2_CANRENDERWINDOWED UINT32_C(0x00080000)
1006#endif
1007
1008#ifdef DEBUG
1009/*
1010 * Check capabilities reported by wine and log any which are not good enough for a D3D feature level.
1011 */
1012
1013#define VBOX_D3D_CHECK_FLAGS(level, field, flags) do { \
1014 if (((field) & (flags)) != (flags)) \
1015 { \
1016 LogRel(("D3D level %s %s flags: 0x%08X -> 0x%08X\n", #level, #field, (field), (flags))); \
1017 } \
1018 } while (0)
1019
1020#define VBOX_D3D_CHECK_VALUE(level, field, value) do { \
1021 if ((int64_t)(value) >= 0? (field) < (value): (field) > (value)) \
1022 { \
1023 LogRel(("D3D level %s %s value: %lld -> %lld\n", #level, #field, (int64_t)(field), (int64_t)(value))); \
1024 } \
1025 } while (0)
1026
1027#define VBOX_D3D_CHECK_VALUE_HEX(level, field, value) do { \
1028 if ((field) < (value)) \
1029 { \
1030 LogRel(("D3D level %s %s value: 0x%08X -> 0x%08X\n", #level, #field, (field), (value))); \
1031 } \
1032 } while (0)
1033
1034static void vboxDispCheckCapsLevel(const D3DCAPS9 *pCaps)
1035{
1036 /* Misc. */
1037 VBOX_D3D_CHECK_FLAGS(misc, pCaps->Caps, D3DCAPS_READ_SCANLINE);
1038 VBOX_D3D_CHECK_FLAGS(misc, pCaps->Caps2, D3DCAPS2_CANRENDERWINDOWED | D3DCAPS2_CANSHARERESOURCE);
1039 VBOX_D3D_CHECK_FLAGS(misc, pCaps->DevCaps, D3DDEVCAPS_FLOATTLVERTEX
1040 /*| D3DDEVCAPS_HWVERTEXBUFFER | D3DDEVCAPS_HWINDEXBUFFER | D3DDEVCAPS_SUBVOLUMELOCK */);
1041 VBOX_D3D_CHECK_FLAGS(misc, pCaps->PrimitiveMiscCaps, D3DPMISCCAPS_INDEPENDENTWRITEMASKS /** @todo needs GL_EXT_draw_buffers2 */
1042 | D3DPMISCCAPS_FOGINFVF
1043 | D3DPMISCCAPS_SEPARATEALPHABLEND
1044 | D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS);
1045 VBOX_D3D_CHECK_FLAGS(misc, pCaps->RasterCaps, D3DPRASTERCAPS_SUBPIXEL
1046 | D3DPRASTERCAPS_STIPPLE
1047 | D3DPRASTERCAPS_ZBIAS
1048 | D3DPRASTERCAPS_COLORPERSPECTIVE);
1049 VBOX_D3D_CHECK_FLAGS(misc, pCaps->TextureCaps, D3DPTEXTURECAPS_TRANSPARENCY
1050 | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE);
1051 VBOX_D3D_CHECK_FLAGS(misc, pCaps->TextureAddressCaps, D3DPTADDRESSCAPS_MIRRORONCE); /** @todo needs GL_ARB_texture_mirror_clamp_to_edge */
1052 VBOX_D3D_CHECK_FLAGS(misc, pCaps->VolumeTextureAddressCaps, D3DPTADDRESSCAPS_MIRRORONCE); /** @todo needs GL_ARB_texture_mirror_clamp_to_edge */
1053 VBOX_D3D_CHECK_FLAGS(misc, pCaps->StencilCaps, D3DSTENCILCAPS_TWOSIDED);
1054 VBOX_D3D_CHECK_FLAGS(misc, pCaps->DeclTypes, D3DDTCAPS_FLOAT16_2 | D3DDTCAPS_FLOAT16_4); /** @todo both need GL_ARB_half_float_vertex */
1055 VBOX_D3D_CHECK_FLAGS(misc, pCaps->VertexTextureFilterCaps, D3DPTFILTERCAPS_MINFPOINT
1056 | D3DPTFILTERCAPS_MAGFPOINT);
1057 VBOX_D3D_CHECK_VALUE(misc, pCaps->GuardBandLeft, -8192.);
1058 VBOX_D3D_CHECK_VALUE(misc, pCaps->GuardBandTop, -8192.);
1059 VBOX_D3D_CHECK_VALUE(misc, pCaps->GuardBandRight, 8192.);
1060 VBOX_D3D_CHECK_VALUE(misc, pCaps->GuardBandBottom, 8192.);
1061 VBOX_D3D_CHECK_VALUE(misc, pCaps->VS20Caps.DynamicFlowControlDepth, 24);
1062 VBOX_D3D_CHECK_VALUE(misc, pCaps->VS20Caps.NumTemps, D3DVS20_MAX_NUMTEMPS);
1063 VBOX_D3D_CHECK_VALUE(misc, pCaps->PS20Caps.DynamicFlowControlDepth, 24);
1064 VBOX_D3D_CHECK_VALUE(misc, pCaps->PS20Caps.NumTemps, D3DVS20_MAX_NUMTEMPS);
1065
1066 /* 9_1 */
1067 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->Caps2, D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_FULLSCREENGAMMA);
1068 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->PresentationIntervals, D3DPRESENT_INTERVAL_IMMEDIATE | D3DPRESENT_INTERVAL_ONE);
1069 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->PrimitiveMiscCaps, D3DPMISCCAPS_COLORWRITEENABLE);
1070 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->ShadeCaps, D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORGOURAUDRGB
1071 | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARGOURAUDRGB);
1072 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT
1073 | D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MAGFPOINT);
1074 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->TextureCaps, D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_CUBEMAP
1075 | D3DPTEXTURECAPS_MIPMAP | D3DPTEXTURECAPS_PERSPECTIVE);
1076 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_INDEPENDENTUV
1077 | D3DPTADDRESSCAPS_MIRROR | D3DPTADDRESSCAPS_WRAP);
1078 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->TextureOpCaps, D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_MODULATE
1079 | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2);
1080 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->SrcBlendCaps, D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_INVDESTCOLOR
1081 | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_ONE
1082 | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_ZERO);
1083 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->DestBlendCaps, D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_INVSRCALPHA
1084 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_ZERO);
1085 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->StretchRectFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MAGFPOINT
1086 | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT);
1087 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->ZCmpCaps, D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_LESSEQUAL);
1088 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->RasterCaps, D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS);
1089 VBOX_D3D_CHECK_FLAGS(9.1, pCaps->StencilCaps, D3DSTENCILCAPS_TWOSIDED);
1090
1091 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxTextureWidth, 2048);
1092 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxTextureHeight, 2048);
1093 VBOX_D3D_CHECK_VALUE(9.1, pCaps->NumSimultaneousRTs, 1);
1094 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxSimultaneousTextures, 8);
1095 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxTextureBlendStages, 8);
1096 VBOX_D3D_CHECK_VALUE_HEX(9.1, pCaps->PixelShaderVersion, D3DPS_VERSION(2,0));
1097 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxPrimitiveCount, 65535);
1098 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxVertexIndex, 65534);
1099 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxVolumeExtent, 256);
1100 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxTextureRepeat, 128); /* Must be zero, or 128, or greater. */
1101 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxAnisotropy, 2);
1102 VBOX_D3D_CHECK_VALUE(9.1, pCaps->MaxVertexW, 0.f);
1103
1104 /* 9_2 */
1105 VBOX_D3D_CHECK_FLAGS(9.2, pCaps->PrimitiveMiscCaps, D3DPMISCCAPS_SEPARATEALPHABLEND);
1106 VBOX_D3D_CHECK_FLAGS(9.2, pCaps->DevCaps2, D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET);
1107 VBOX_D3D_CHECK_FLAGS(9.2, pCaps->TextureAddressCaps, D3DPTADDRESSCAPS_MIRRORONCE);
1108 VBOX_D3D_CHECK_FLAGS(9.2, pCaps->VolumeTextureAddressCaps, D3DPTADDRESSCAPS_MIRRORONCE);
1109 VBOX_D3D_CHECK_VALUE(9.2, pCaps->MaxTextureWidth, 2048);
1110 VBOX_D3D_CHECK_VALUE(9.2, pCaps->MaxTextureHeight, 2048);
1111 VBOX_D3D_CHECK_VALUE(9.2, pCaps->MaxTextureRepeat, 2048); /* Must be zero, or 2048, or greater. */
1112 VBOX_D3D_CHECK_VALUE_HEX(9.2, pCaps->VertexShaderVersion, D3DVS_VERSION(2,0));
1113 VBOX_D3D_CHECK_VALUE(9.2, pCaps->MaxAnisotropy, 16);
1114 VBOX_D3D_CHECK_VALUE(9.2, pCaps->MaxPrimitiveCount, 1048575);
1115 VBOX_D3D_CHECK_VALUE(9.2, pCaps->MaxVertexIndex, 1048575);
1116 VBOX_D3D_CHECK_VALUE(9.2, pCaps->MaxVertexW, 10000000000.f);
1117
1118 /* 9_3 */
1119 VBOX_D3D_CHECK_FLAGS(9.3, pCaps->PS20Caps.Caps, D3DPS20CAPS_GRADIENTINSTRUCTIONS);
1120 VBOX_D3D_CHECK_FLAGS(9.3, pCaps->VS20Caps.Caps, D3DVS20CAPS_PREDICATION);
1121 VBOX_D3D_CHECK_FLAGS(9.3, pCaps->PrimitiveMiscCaps, D3DPMISCCAPS_INDEPENDENTWRITEMASKS | D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING);
1122 VBOX_D3D_CHECK_FLAGS(9.3, pCaps->TextureAddressCaps, D3DPTADDRESSCAPS_BORDER);
1123 VBOX_D3D_CHECK_VALUE(9.3, pCaps->MaxTextureWidth, 4096);
1124 VBOX_D3D_CHECK_VALUE(9.3, pCaps->MaxTextureHeight, 4096);
1125 VBOX_D3D_CHECK_VALUE(9.3, pCaps->MaxTextureRepeat, 8192); /* Must be zero, or 8192, or greater. */
1126 VBOX_D3D_CHECK_VALUE(9.3, pCaps->NumSimultaneousRTs, 4);
1127 VBOX_D3D_CHECK_VALUE(9.3, pCaps->PS20Caps.NumInstructionSlots, 512); /* (Pixel Shader Version 2b) */
1128 VBOX_D3D_CHECK_VALUE(9.3, pCaps->PS20Caps.NumTemps, 32); /* (Pixel Shader Version 2b) */
1129 VBOX_D3D_CHECK_VALUE(9.3, pCaps->VS20Caps.NumTemps, 32); /* (Vertex Shader Version 2a) */
1130 VBOX_D3D_CHECK_VALUE(9.3, pCaps->VS20Caps.StaticFlowControlDepth, 4);
1131 VBOX_D3D_CHECK_VALUE(9.3, pCaps->MaxVertexShaderConst, 256); /* (Vertex Shader Version 2a); */
1132 VBOX_D3D_CHECK_VALUE(9.3, pCaps->MaxVertexShader30InstructionSlots, 512);
1133 VBOX_D3D_CHECK_VALUE_HEX(9.3, pCaps->VertexShaderVersion, D3DVS_VERSION(3,0));
1134
1135 LogRel(("Capabilities check completed\n"));
1136}
1137
1138#undef VBOX_D3D_CHECK_FLAGS
1139#undef VBOX_D3D_CHECK_VALUE
1140#undef VBOX_D3D_CHECK_VALUE_HEX
1141
1142#endif /* DEBUG */
1143
1144static HRESULT vboxWddmGetD3D9Caps(PVBOXWDDMDISP_D3D pD3D, D3DCAPS9 *pCaps)
1145{
1146 HRESULT hr = pD3D->pD3D9If->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, pCaps);
1147 if (FAILED(hr))
1148 {
1149 WARN(("GetDeviceCaps failed hr(0x%x)",hr));
1150 return hr;
1151 }
1152
1153#ifdef DEBUG
1154 vboxDispCheckCapsLevel(pCaps);
1155#endif
1156
1157 /* needed for Windows Media Player to work properly */
1158 pCaps->Caps |= D3DCAPS_READ_SCANLINE;
1159 pCaps->Caps2 |= 0x00080000 /*D3DCAPS2_CANRENDERWINDOWED*/;
1160 pCaps->Caps2 |= D3DCAPS2_CANSHARERESOURCE;
1161 pCaps->DevCaps |= D3DDEVCAPS_FLOATTLVERTEX /* <- must be set according to the docs */
1162 /*| D3DDEVCAPS_HWVERTEXBUFFER | D3DDEVCAPS_HWINDEXBUFFER | D3DDEVCAPS_SUBVOLUMELOCK */;
1163 pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1164 | D3DPMISCCAPS_FOGINFVF
1165 | D3DPMISCCAPS_SEPARATEALPHABLEND | D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS;
1166 pCaps->RasterCaps |= D3DPRASTERCAPS_SUBPIXEL | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_COLORPERSPECTIVE /* keep */;
1167 pCaps->TextureCaps |= D3DPTEXTURECAPS_TRANSPARENCY | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE;
1168 pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
1169 pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
1170 pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
1171 pCaps->DeclTypes |= D3DDTCAPS_FLOAT16_2 | D3DDTCAPS_FLOAT16_4;
1172 pCaps->VertexTextureFilterCaps |= D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MAGFPOINT;
1173 pCaps->GuardBandLeft = -8192.;
1174 pCaps->GuardBandTop = -8192.;
1175 pCaps->GuardBandRight = 8192.;
1176 pCaps->GuardBandBottom = 8192.;
1177 pCaps->VS20Caps.DynamicFlowControlDepth = 24;
1178 pCaps->VS20Caps.NumTemps = D3DVS20_MAX_NUMTEMPS;
1179 pCaps->PS20Caps.DynamicFlowControlDepth = 24;
1180 pCaps->PS20Caps.NumTemps = D3DVS20_MAX_NUMTEMPS;
1181
1182 /* workaround for wine not returning InstructionSlots correctly for shaders v3.0 */
1183 if ((pCaps->VertexShaderVersion & 0xff00) == 0x0300)
1184 {
1185 pCaps->MaxVertexShader30InstructionSlots = RT_MIN(32768, pCaps->MaxVertexShader30InstructionSlots);
1186 pCaps->MaxPixelShader30InstructionSlots = RT_MIN(32768, pCaps->MaxPixelShader30InstructionSlots);
1187 }
1188#if defined(DEBUG)
1189 if ((pCaps->VertexShaderVersion & 0xff00) == 0x0300)
1190 {
1191 Assert(pCaps->MaxVertexShader30InstructionSlots >= 512);
1192 Assert(pCaps->MaxVertexShader30InstructionSlots <= 32768);
1193 Assert(pCaps->MaxPixelShader30InstructionSlots >= 512);
1194 Assert(pCaps->MaxPixelShader30InstructionSlots <= 32768);
1195 }
1196 else if ((pCaps->VertexShaderVersion & 0xff00) == 0x0200)
1197 {
1198 Assert(pCaps->MaxVertexShader30InstructionSlots == 0);
1199 Assert(pCaps->MaxPixelShader30InstructionSlots == 0);
1200 }
1201 else
1202 {
1203 WARN(("incorect shader caps!"));
1204 }
1205#endif
1206
1207 pCaps->MaxVertexW = 10000000000.f; /* Required by D3D feature level 9.3. */
1208
1209#ifdef DEBUG
1210 vboxDispCheckCapsLevel(pCaps);
1211#endif
1212
1213 vboxDispDumpD3DCAPS9(pCaps);
1214
1215 return S_OK;
1216}
1217
1218static void vboxDispD3DGlobalDoClose(PVBOXWDDMDISP_D3D pD3D)
1219{
1220 pD3D->pD3D9If->Release();
1221 VBoxDispD3DClose(&pD3D->D3D);
1222}
1223
1224static HRESULT vboxDispD3DGlobalDoOpen(PVBOXWDDMDISP_D3D pD3D)
1225{
1226 memset(pD3D, 0, sizeof (*pD3D));
1227 HRESULT hr = VBoxDispD3DOpen(&pD3D->D3D);
1228 if (SUCCEEDED(hr))
1229 {
1230 hr = pD3D->D3D.pfnDirect3DCreate9Ex(D3D_SDK_VERSION, &pD3D->pD3D9If);
1231 if (SUCCEEDED(hr))
1232 {
1233 hr = vboxWddmGetD3D9Caps(pD3D, &pD3D->Caps);
1234 if (SUCCEEDED(hr))
1235 {
1236 pD3D->cMaxSimRTs = pD3D->Caps.NumSimultaneousRTs;
1237 Assert(pD3D->cMaxSimRTs);
1238 Assert(pD3D->cMaxSimRTs < UINT32_MAX/2);
1239 LOG(("SUCCESS 3D Enabled, pD3D (0x%p)", pD3D));
1240 return S_OK;
1241 }
1242 else
1243 {
1244 WARN(("vboxWddmGetD3D9Caps failed hr = 0x%x", hr));
1245 }
1246 pD3D->pD3D9If->Release();
1247 }
1248 else
1249 {
1250 WARN(("pfnDirect3DCreate9Ex failed hr = 0x%x", hr));
1251 }
1252 VBoxDispD3DClose(&pD3D->D3D);
1253 }
1254 else
1255 {
1256 WARN(("VBoxDispD3DOpen failed hr = 0x%x", hr));
1257 }
1258 return hr;
1259}
1260
1261HRESULT VBoxDispD3DGlobalOpen(PVBOXWDDMDISP_D3D pD3D, PVBOXWDDMDISP_FORMATS pFormats)
1262{
1263 vboxDispD3DGlobalLock();
1264 if (!g_cVBoxDispD3DGlobalOpens)
1265 {
1266 HRESULT hr = vboxDispD3DGlobalDoOpen(&g_VBoxDispD3DGlobalD3D);
1267 if (!SUCCEEDED(hr))
1268 {
1269 vboxDispD3DGlobalUnlock();
1270 WARN(("vboxDispD3DGlobalDoOpen failed hr = 0x%x", hr));
1271 return hr;
1272 }
1273
1274 vboxDispD3DGlobalD3DFormatsInit(&g_VBoxDispD3DGlobalD3DFormats);
1275 }
1276 ++g_cVBoxDispD3DGlobalOpens;
1277 vboxDispD3DGlobalUnlock();
1278
1279 *pD3D = g_VBoxDispD3DGlobalD3D;
1280 *pFormats = g_VBoxDispD3DGlobalD3DFormats;
1281 return S_OK;
1282}
1283
1284void VBoxDispD3DGlobalClose(PVBOXWDDMDISP_D3D pD3D, PVBOXWDDMDISP_FORMATS pFormats)
1285{
1286 RT_NOREF(pD3D, pFormats);
1287 vboxDispD3DGlobalLock();
1288 --g_cVBoxDispD3DGlobalOpens;
1289 if (!g_cVBoxDispD3DGlobalOpens)
1290 vboxDispD3DGlobalDoClose(&g_VBoxDispD3DGlobalD3D);
1291 vboxDispD3DGlobalUnlock();
1292}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette