VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/Present.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1/* $Id: Present.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Mesa3D - ID3DPresent and ID3DPresentGroup implementation.
4 */
5
6/*
7 * Copyright (C) 2016-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include "VBoxPresent.h"
29#include "VBoxGallium.h"
30
31#include <iprt/alloc.h>
32#include <iprt/asm.h>
33#include <iprt/log.h>
34
35#include "../../../common/wddm/VBoxMPIf.h"
36
37#define TRAPNOTIMPL do { \
38 ASMBreakpoint(); \
39} while (0)
40
41const GUID IID_ID3DPresent = { 0x77D60E80, 0xF1E6, 0x11DF, { 0x9E, 0x39, 0x95, 0x0C, 0xDF, 0xD7, 0x20, 0x85 } };
42const GUID IID_ID3DPresentGroup = { 0xB9C3016E, 0xF32A, 0x11DF, { 0x9C, 0x18, 0x92, 0xEA, 0xDE, 0xD7, 0x20, 0x85 } };
43
44/*
45 * Gallium D3D9 state tracker (nine) uses ID3DPresent interface to present (display) rendered buffers,
46 * when IDirect3DDevice9::Present method is called.
47 *
48 * The WDDM driver uses this mechanism _only_ when running the embedded GaDrvTest code.
49 *
50 * I.e. during normal operations ID3DPresent interface is _not_ used.
51 *
52 * However 'nine' creates the buffers for the implicit swapchain.
53 *
54 * The implementation here simply stores the surface id and dimensions in D3DWindowBuffer
55 * structure and tells the host to display the surface in PresentBuffer.
56 *
57 * Most of methods will trigger a breakpoint, because it its not expected that they willl be called.
58 */
59
60struct D3DWindowBuffer
61{
62 uint32_t u32Width;
63 uint32_t u32Height;
64 uint32_t u32Sid;
65};
66
67class WDDMPresentGroup;
68
69class WDDMPresent: public ID3DPresent
70{
71 public:
72 /* IUnknown */
73 virtual HRESULT WINAPI QueryInterface(REFIID riid, void **ppvObject);
74 virtual ULONG WINAPI AddRef();
75 virtual ULONG WINAPI Release();
76
77 /* ID3DPresent */
78 virtual HRESULT WINAPI SetPresentParameters(D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode);
79 virtual HRESULT WINAPI NewD3DWindowBufferFromDmaBuf(int dmaBufFd, int width, int height, int stride, int depth, int bpp, D3DWindowBuffer **out);
80 virtual HRESULT WINAPI DestroyD3DWindowBuffer(D3DWindowBuffer *buffer);
81 virtual HRESULT WINAPI WaitBufferReleased(D3DWindowBuffer *buffer);
82 virtual HRESULT WINAPI FrontBufferCopy(D3DWindowBuffer *buffer);
83 virtual HRESULT WINAPI PresentBuffer(D3DWindowBuffer *buffer, HWND hWndOverride, const RECT *pSourceRect, const RECT *pDestRect, const RGNDATA *pDirtyRegion, DWORD Flags);
84 virtual HRESULT WINAPI GetRasterStatus(D3DRASTER_STATUS *pRasterStatus);
85 virtual HRESULT WINAPI GetDisplayMode(D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation);
86 virtual HRESULT WINAPI GetPresentStats(D3DPRESENTSTATS *pStats);
87 virtual HRESULT WINAPI GetCursorPos(POINT *pPoint);
88 virtual HRESULT WINAPI SetCursorPos(POINT *pPoint);
89 virtual HRESULT WINAPI SetCursor(void *pBitmap, POINT *pHotspot, BOOL bShow);
90 virtual HRESULT WINAPI SetGammaRamp(const D3DGAMMARAMP *pRamp, HWND hWndOverride);
91 virtual HRESULT WINAPI GetWindowInfo(HWND hWnd, int *width, int *height, int *depth);
92
93 WDDMPresent();
94 virtual ~WDDMPresent();
95
96 HRESULT Init(WDDMPresentGroup *pPresentGroup, D3DPRESENT_PARAMETERS *pPresentationParameters);
97
98 private:
99 volatile ULONG mcRefs;
100 WDDMPresentGroup *mpPresentGroup;
101};
102
103class WDDMPresentGroup: public ID3DPresentGroup
104{
105 public:
106 /* IUnknown */
107 virtual HRESULT WINAPI QueryInterface(REFIID riid, void **ppvObject);
108 virtual ULONG WINAPI AddRef();
109 virtual ULONG WINAPI Release();
110
111 /* ID3DPresentGroup */
112 virtual UINT WINAPI GetMultiheadCount();
113 virtual HRESULT WINAPI GetPresent(UINT Index, ID3DPresent **ppPresent);
114 virtual HRESULT WINAPI CreateAdditionalPresent(D3DPRESENT_PARAMETERS *pPresentationParameters, ID3DPresent **ppPresent);
115 virtual void WINAPI GetVersion(int *major, int *minor);
116
117 WDDMPresentGroup();
118 virtual ~WDDMPresentGroup();
119
120 HRESULT Init(int cPresentBackends, IGaDirect3DDevice9Ex *pGaDevice);
121 IGaDirect3DDevice9Ex *GaDevice() { return mpGaDevice; }
122
123 private:
124 volatile ULONG mcRefs;
125
126 IGaDirect3DDevice9Ex *mpGaDevice; /** @todo ref count? */
127 int mcPresentBackends;
128 WDDMPresent **mpaPresentBackends;
129};
130
131
132/*
133 * WDDMPresent implementation.
134 */
135
136WDDMPresent::WDDMPresent()
137 :
138 mcRefs(0)
139{
140}
141
142WDDMPresent::~WDDMPresent()
143{
144}
145
146HRESULT WDDMPresent::Init(WDDMPresentGroup *pPresentGroup, D3DPRESENT_PARAMETERS *pPresentationParameters)
147{
148 RT_NOREF(pPresentationParameters);
149 mpPresentGroup = pPresentGroup;
150 return S_OK;
151}
152
153ULONG WINAPI WDDMPresent::AddRef()
154{
155 ULONG refs = InterlockedIncrement(&mcRefs);
156 return refs;
157}
158
159ULONG WINAPI WDDMPresent::Release()
160{
161 ULONG refs = InterlockedDecrement(&mcRefs);
162 if (refs == 0)
163 {
164 delete this;
165 }
166 return refs;
167}
168
169HRESULT WINAPI WDDMPresent::QueryInterface(REFIID riid,
170 void **ppvObject)
171{
172 if (!ppvObject)
173 {
174 return E_POINTER;
175 }
176
177 if ( IsEqualGUID(IID_IUnknown, riid)
178 || IsEqualGUID(IID_ID3DPresent, riid))
179 {
180 AddRef();
181 *ppvObject = this;
182 return S_OK;
183 }
184
185 *ppvObject = NULL;
186
187 return E_NOINTERFACE;
188}
189
190HRESULT WINAPI WDDMPresent::SetPresentParameters(D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode)
191{
192 RT_NOREF(pPresentationParameters);
193 RT_NOREF(pFullscreenDisplayMode);
194 /* Ignore. */
195 return S_OK;
196}
197
198HRESULT WINAPI WDDMPresent::NewD3DWindowBufferFromDmaBuf(int dmaBufFd, int width, int height, int stride, int depth, int bpp, D3DWindowBuffer **out)
199{
200 RT_NOREF3(stride, depth, bpp);
201
202 D3DWindowBuffer *pBuffer = (D3DWindowBuffer *)RTMemAlloc(sizeof(D3DWindowBuffer));
203 if (!pBuffer)
204 return E_OUTOFMEMORY;
205
206 pBuffer->u32Width = width;
207 pBuffer->u32Height = height;
208 pBuffer->u32Sid = dmaBufFd;
209
210 *out = pBuffer;
211 return S_OK;
212}
213
214HRESULT WINAPI WDDMPresent::DestroyD3DWindowBuffer(D3DWindowBuffer *buffer)
215{
216 RTMemFree(buffer);
217 return S_OK;
218}
219
220HRESULT WINAPI WDDMPresent::WaitBufferReleased(D3DWindowBuffer *buffer)
221{
222 RT_NOREF(buffer);
223 /* Ignore */
224 return D3D_OK;
225}
226
227HRESULT WINAPI WDDMPresent::FrontBufferCopy(D3DWindowBuffer *buffer)
228{
229 RT_NOREF(buffer);
230 TRAPNOTIMPL;
231 return D3DERR_INVALIDCALL;
232}
233
234HRESULT WINAPI WDDMPresent::PresentBuffer(D3DWindowBuffer *pBuffer, HWND hWndOverride, const RECT *pSourceRect, const RECT *pDestRect, const RGNDATA *pDirtyRegion, DWORD Flags)
235{
236 RT_NOREF5(hWndOverride, pSourceRect, pDestRect, pDirtyRegion, Flags);
237
238 ASMBreakpoint(); /* This is expected to run only as part of GaDrvTest under kernel debugger. */
239
240 IGaDirect3DDevice9Ex *pGaDevice = mpPresentGroup->GaDevice();
241
242 VBOXDISPIFESCAPE_GAPRESENT data;
243 RT_ZERO(data);
244 data.EscapeHdr.escapeCode = VBOXESC_GAPRESENT;
245 data.u32Sid = pBuffer->u32Sid;
246 data.u32Width = pBuffer->u32Width;
247 data.u32Height = pBuffer->u32Height;
248 HRESULT hr = pGaDevice->EscapeCb(&data, sizeof(data), /* fHardwareAccess= */ true);
249 if (SUCCEEDED(hr))
250 return D3D_OK;
251
252 return D3DERR_INVALIDCALL;
253}
254
255HRESULT WINAPI WDDMPresent::GetRasterStatus(D3DRASTER_STATUS *pRasterStatus)
256{
257 RT_NOREF(pRasterStatus);
258 TRAPNOTIMPL;
259 return D3DERR_INVALIDCALL;
260}
261
262HRESULT WINAPI WDDMPresent::GetDisplayMode(D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation)
263{
264 RT_NOREF2(pMode, pRotation);
265 TRAPNOTIMPL;
266 return D3DERR_INVALIDCALL;
267}
268
269HRESULT WINAPI WDDMPresent::GetPresentStats(D3DPRESENTSTATS *pStats)
270{
271 RT_NOREF(pStats);
272 TRAPNOTIMPL;
273 return D3DERR_INVALIDCALL;
274}
275
276HRESULT WINAPI WDDMPresent::GetCursorPos(POINT *pPoint)
277{
278 if (!::GetCursorPos(pPoint))
279 {
280 pPoint->x = 0;
281 pPoint->y = 0;
282 }
283 return S_OK;
284}
285
286HRESULT WINAPI WDDMPresent::SetCursorPos(POINT *pPoint)
287{
288 RT_NOREF(pPoint);
289 TRAPNOTIMPL;
290 return D3DERR_INVALIDCALL;
291}
292
293HRESULT WINAPI WDDMPresent::SetCursor(void *pBitmap, POINT *pHotspot, BOOL bShow)
294{
295 RT_NOREF3(pBitmap, pHotspot, bShow);
296 TRAPNOTIMPL;
297 return D3DERR_INVALIDCALL;
298}
299
300HRESULT WINAPI WDDMPresent::SetGammaRamp(const D3DGAMMARAMP *pRamp, HWND hWndOverride)
301{
302 RT_NOREF2(pRamp, hWndOverride);
303 TRAPNOTIMPL;
304 return D3DERR_INVALIDCALL;
305}
306
307HRESULT WINAPI WDDMPresent::GetWindowInfo(HWND hWnd, int *width, int *height, int *depth)
308{
309 RT_NOREF4(hWnd, width, height, depth);
310 TRAPNOTIMPL;
311 return D3DERR_INVALIDCALL;
312}
313
314
315/*
316 * WDDMPresentGroup implementation.
317 */
318WDDMPresentGroup::WDDMPresentGroup()
319 :
320 mcRefs(0),
321 mcPresentBackends(0),
322 mpaPresentBackends(NULL)
323{
324}
325
326WDDMPresentGroup::~WDDMPresentGroup()
327{
328 if (mpaPresentBackends)
329 {
330 int i;
331 for (i = 0; i < mcPresentBackends; ++i)
332 {
333 if (mpaPresentBackends[i])
334 {
335 mpaPresentBackends[i]->Release();
336 mpaPresentBackends[i] = NULL;
337 }
338 }
339
340 RTMemFree(mpaPresentBackends);
341 mpaPresentBackends = NULL;
342 }
343}
344
345HRESULT WDDMPresentGroup::Init(int cPresentBackends, IGaDirect3DDevice9Ex *pGaDevice)
346{
347 mpGaDevice = pGaDevice;
348 mcPresentBackends = cPresentBackends;
349 mpaPresentBackends = (WDDMPresent **)RTMemAllocZ(mcPresentBackends);
350 if (!mpaPresentBackends)
351 {
352 return E_OUTOFMEMORY;
353 }
354
355 int i;
356 for (i = 0; i < mcPresentBackends; ++i)
357 {
358 WDDMPresent *p = new WDDMPresent();
359 if (!p)
360 {
361 return E_OUTOFMEMORY;
362 }
363
364 HRESULT hr = p->Init(this, NULL);
365 if (FAILED(hr))
366 {
367 delete p;
368 return hr;
369 }
370
371 p->AddRef();
372 mpaPresentBackends[i] = p;
373 }
374
375 return S_OK;
376}
377
378ULONG WINAPI WDDMPresentGroup::AddRef()
379{
380 ULONG refs = InterlockedIncrement(&mcRefs);
381 return refs;
382}
383
384ULONG WINAPI WDDMPresentGroup::Release()
385{
386 ULONG refs = InterlockedDecrement(&mcRefs);
387 if (refs == 0)
388 {
389 delete this;
390 }
391 return refs;
392}
393
394HRESULT WINAPI WDDMPresentGroup::QueryInterface(REFIID riid,
395 void **ppvObject)
396{
397 if (!ppvObject)
398 {
399 return E_POINTER;
400 }
401
402 if ( IsEqualGUID(IID_IUnknown, riid)
403 || IsEqualGUID(IID_ID3DPresentGroup, riid))
404 {
405 AddRef();
406 *ppvObject = this;
407 return S_OK;
408 }
409
410 *ppvObject = NULL;
411
412 return E_NOINTERFACE;
413}
414
415UINT WINAPI WDDMPresentGroup::GetMultiheadCount()
416{
417 return mcPresentBackends;
418}
419
420HRESULT WINAPI WDDMPresentGroup::GetPresent(UINT Index, ID3DPresent **ppPresent)
421{
422 if (Index >= GetMultiheadCount())
423 {
424 return D3DERR_INVALIDCALL;
425 }
426
427 mpaPresentBackends[Index]->AddRef();
428 *ppPresent = mpaPresentBackends[Index];
429
430 return S_OK;
431}
432
433HRESULT WINAPI WDDMPresentGroup::CreateAdditionalPresent(D3DPRESENT_PARAMETERS *pPresentationParameters,
434 ID3DPresent **ppPresent)
435{
436 WDDMPresent *p = new WDDMPresent();
437 if (!p)
438 {
439 return E_OUTOFMEMORY;
440 }
441
442 HRESULT hr = p->Init(this, pPresentationParameters);
443 if (SUCCEEDED(hr))
444 {
445 p->AddRef();
446 *ppPresent = p;
447 }
448 else
449 {
450 delete p;
451 }
452
453 return hr;
454}
455
456void WINAPI WDDMPresentGroup::GetVersion(int *major, int *minor)
457{
458 *major = 1;
459 *minor = 0;
460}
461
462HRESULT WDDMPresentGroupCreate(IGaDirect3DDevice9Ex *pGaDevice, ID3DPresentGroup **ppOut)
463{
464 WDDMPresentGroup *p = new WDDMPresentGroup();
465 if (!p)
466 {
467 return E_OUTOFMEMORY;
468 }
469
470 HRESULT hr = p->Init(1, pGaDevice);
471 if (SUCCEEDED(hr))
472 {
473 p->AddRef();
474 *ppOut = p;
475 }
476 else
477 {
478 delete p;
479 }
480
481 return hr;
482}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use