VirtualBox

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

Last change on this file since 76553 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1/* $Id: VBoxUhgsmiBase.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBoxVideo Display D3D User mode dll
4 */
5
6/*
7 * Copyright (C) 2012-2019 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 "VBoxDispD3DCmn.h"
19#include <VBox/VMMDevCoreTypes.h>
20
21
22DECLCALLBACK(int) vboxUhgsmiBaseEscBufferLock(PVBOXUHGSMI_BUFFER pBuf, uint32_t offLock, uint32_t cbLock,
23 VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags, void**pvLock)
24{
25 RT_NOREF(cbLock, fFlags);
26 PVBOXUHGSMI_BUFFER_PRIVATE_ESC_BASE pBuffer = VBOXUHGSMIESCBASE_GET_BUFFER(pBuf);
27 *pvLock = (void*)(pBuffer->Alloc.pvData + offLock);
28 return VINF_SUCCESS;
29}
30
31DECLCALLBACK(int) vboxUhgsmiBaseEscBufferUnlock(PVBOXUHGSMI_BUFFER pBuf)
32{
33 RT_NOREF(pBuf);
34 return VINF_SUCCESS;
35}
36
37int vboxUhgsmiBaseBufferTerm(PVBOXUHGSMI_BUFFER_PRIVATE_ESC_BASE pBuffer)
38{
39 PVBOXUHGSMI_PRIVATE_BASE pPrivate = VBOXUHGSMIBASE_GET(pBuffer->BasePrivate.pHgsmi);
40 VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE DeallocInfo = {0};
41 DeallocInfo.EscapeHdr.escapeCode = VBOXESC_UHGSMI_DEALLOCATE;
42 DeallocInfo.hAlloc = pBuffer->Alloc.hAlloc;
43 return vboxCrHgsmiPrivateEscape(pPrivate, &DeallocInfo, sizeof (DeallocInfo), FALSE);
44}
45
46static int vboxUhgsmiBaseEventChkCreate(VBOXUHGSMI_BUFFER_TYPE_FLAGS fUhgsmiType, HANDLE *phSynch)
47{
48 *phSynch = NULL;
49
50 if (fUhgsmiType.s.fCommand)
51 {
52 *phSynch = CreateEvent(
53 NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes */
54 FALSE, /* BOOL bManualReset */
55 FALSE, /* BOOL bInitialState */
56 NULL /* LPCTSTR lpName */
57 );
58 Assert(*phSynch);
59 if (!*phSynch)
60 {
61 /*DWORD winEr = GetLastError(); - unused */
62 /** @todo translate winer */
63 return VERR_GENERAL_FAILURE;
64 }
65 }
66 return VINF_SUCCESS;
67}
68
69int vboxUhgsmiKmtEscBufferInit(PVBOXUHGSMI_PRIVATE_BASE pPrivate, PVBOXUHGSMI_BUFFER_PRIVATE_ESC_BASE pBuffer, uint32_t cbBuf,
70 VBOXUHGSMI_BUFFER_TYPE_FLAGS fUhgsmiType, PFNVBOXUHGSMI_BUFFER_DESTROY pfnDestroy)
71{
72 HANDLE hSynch = NULL;
73 if (!cbBuf)
74 return VERR_INVALID_PARAMETER;
75
76 int rc = vboxUhgsmiBaseEventChkCreate(fUhgsmiType, &hSynch);
77 if (RT_FAILURE(rc))
78 {
79 WARN(("vboxUhgsmiBaseEventChkCreate failed, rc %d", rc));
80 return rc;
81 }
82
83 cbBuf = VBOXWDDM_ROUNDBOUND(cbBuf, 0x1000);
84 Assert(cbBuf);
85#ifdef VBOX_STRICT
86 uint32_t cPages = cbBuf >> 12;
87 Assert(cPages);
88#endif
89
90 VBOXDISPIFESCAPE_UHGSMI_ALLOCATE AllocInfo = {0};
91 AllocInfo.EscapeHdr.escapeCode = VBOXESC_UHGSMI_ALLOCATE;
92 AllocInfo.Alloc.cbData = cbBuf;
93 AllocInfo.Alloc.hSynch = (uintptr_t)hSynch;
94 AllocInfo.Alloc.fUhgsmiType = fUhgsmiType;
95
96 rc = vboxCrHgsmiPrivateEscape(pPrivate, &AllocInfo, sizeof (AllocInfo), FALSE);
97 if (RT_FAILURE(rc))
98 {
99 if (hSynch)
100 CloseHandle(hSynch);
101 WARN(("vboxCrHgsmiPrivateEscape failed, rc %d", rc));
102 return rc;
103 }
104
105 pBuffer->Alloc = AllocInfo.Alloc;
106 Assert(pBuffer->Alloc.pvData);
107 pBuffer->BasePrivate.pHgsmi = pPrivate;
108 pBuffer->BasePrivate.Base.pfnLock = vboxUhgsmiBaseEscBufferLock;
109 pBuffer->BasePrivate.Base.pfnUnlock = vboxUhgsmiBaseEscBufferUnlock;
110 pBuffer->BasePrivate.Base.pfnDestroy = pfnDestroy;
111 pBuffer->BasePrivate.Base.fType = fUhgsmiType;
112 pBuffer->BasePrivate.Base.cbBuffer = AllocInfo.Alloc.cbData;
113 pBuffer->hSynch = hSynch;
114 return VINF_SUCCESS;
115}
116
117DECLCALLBACK(int) vboxUhgsmiBaseEscBufferDestroy(PVBOXUHGSMI_BUFFER pBuf)
118{
119 PVBOXUHGSMI_BUFFER_PRIVATE_ESC_BASE pBuffer = VBOXUHGSMIESCBASE_GET_BUFFER(pBuf);
120 int rc = vboxUhgsmiBaseBufferTerm(pBuffer);
121 if (RT_FAILURE(rc))
122 {
123 WARN(("vboxUhgsmiBaseBufferTerm failed rc %d", rc));
124 return rc;
125 }
126
127 RTMemFree(pBuffer);
128 return VINF_SUCCESS;
129}
130
131DECLCALLBACK(int) vboxUhgsmiBaseEscBufferCreate(PVBOXUHGSMI pHgsmi, uint32_t cbBuf, VBOXUHGSMI_BUFFER_TYPE_FLAGS fUhgsmiType,
132 PVBOXUHGSMI_BUFFER* ppBuf)
133{
134 *ppBuf = NULL;
135
136 PVBOXUHGSMI_BUFFER_PRIVATE_ESC_BASE pBuffer = (PVBOXUHGSMI_BUFFER_PRIVATE_ESC_BASE)RTMemAllocZ(sizeof (*pBuffer));
137 if (!pBuffer)
138 {
139 WARN(("RTMemAllocZ failed"));
140 return VERR_NO_MEMORY;
141 }
142
143 PVBOXUHGSMI_PRIVATE_BASE pPrivate = VBOXUHGSMIBASE_GET(pHgsmi);
144 int rc = vboxUhgsmiKmtEscBufferInit(pPrivate, pBuffer, cbBuf, fUhgsmiType, vboxUhgsmiBaseEscBufferDestroy);
145 if (RT_SUCCESS(rc))
146 {
147 *ppBuf = &pBuffer->BasePrivate.Base;
148 return VINF_SUCCESS;
149 }
150
151 WARN(("vboxUhgsmiKmtEscBufferInit failed, rc %d", rc));
152 RTMemFree(pBuffer);
153 return rc;
154}
155
156DECLCALLBACK(int) vboxUhgsmiBaseEscBufferSubmit(PVBOXUHGSMI pHgsmi, PVBOXUHGSMI_BUFFER_SUBMIT aBuffers, uint32_t cBuffers)
157{
158 /* We know chromium will not submit more than three buffers actually,
159 * for simplicity allocate it statically on the stack */
160 struct
161 {
162 VBOXDISPIFESCAPE_UHGSMI_SUBMIT SubmitInfo;
163 VBOXWDDM_UHGSMI_BUFFER_UI_INFO_ESCAPE aBufInfos[3];
164 } Buf;
165
166 if (!cBuffers || cBuffers > RT_ELEMENTS(Buf.aBufInfos))
167 {
168 WARN(("invalid cBuffers!"));
169 return VERR_INVALID_PARAMETER;
170 }
171
172 HANDLE hSynch = VBOXUHGSMIESCBASE_GET_BUFFER(aBuffers[0].pBuf)->hSynch;
173 if (!hSynch)
174 {
175 WARN(("the fist buffer is not command!"));
176 return VERR_INVALID_PARAMETER;
177 }
178
179 PVBOXUHGSMI_PRIVATE_BASE pPrivate = VBOXUHGSMIBASE_GET(pHgsmi);
180 Buf.SubmitInfo.EscapeHdr.escapeCode = VBOXESC_UHGSMI_SUBMIT;
181 Buf.SubmitInfo.EscapeHdr.u32CmdSpecific = cBuffers;
182 for (UINT i = 0; i < cBuffers; ++i)
183 {
184 VBOXWDDM_UHGSMI_BUFFER_UI_INFO_ESCAPE *pSubmInfo = &Buf.SubmitInfo.aBuffers[i];
185 PVBOXUHGSMI_BUFFER_SUBMIT pBufInfo = &aBuffers[i];
186 PVBOXUHGSMI_BUFFER_PRIVATE_ESC_BASE pBuf = VBOXUHGSMIESCBASE_GET_BUFFER(pBufInfo->pBuf);
187 pSubmInfo->hAlloc = pBuf->Alloc.hAlloc;
188 if (pBufInfo->fFlags.s.fEntireBuffer)
189 {
190 pSubmInfo->Info.offData = 0;
191 pSubmInfo->Info.cbData = pBuf->BasePrivate.Base.cbBuffer;
192 }
193 else
194 {
195 pSubmInfo->Info.offData = pBufInfo->offData;
196 pSubmInfo->Info.cbData = pBufInfo->cbData;
197 }
198 }
199
200 int rc = vboxCrHgsmiPrivateEscape(pPrivate, &Buf.SubmitInfo,
201 RT_UOFFSETOF_DYN(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[cBuffers]), FALSE);
202 if (RT_SUCCESS(rc))
203 {
204 DWORD dwResult = WaitForSingleObject(hSynch, INFINITE);
205 if (dwResult == WAIT_OBJECT_0)
206 return VINF_SUCCESS;
207 WARN(("wait failed, (0x%x)", dwResult));
208 return VERR_GENERAL_FAILURE;
209 }
210 else
211 {
212 WARN(("vboxCrHgsmiPrivateEscape failed, rc (%d)", rc));
213 }
214
215 return VERR_GENERAL_FAILURE;
216}
217
218/* Cr calls have <= 3args, we try to allocate it on stack first */
219typedef struct VBOXCRHGSMI_CALLDATA
220{
221 VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL CallHdr;
222 HGCMFunctionParameter aArgs[3];
223} VBOXCRHGSMI_CALLDATA, *PVBOXCRHGSMI_CALLDATA;
224
225int vboxCrHgsmiPrivateCtlConCall(struct VBOXUHGSMI_PRIVATE_BASE *pHgsmi, struct VBGLIOCHGCMCALL *pCallInfo, int cbCallInfo)
226{
227 VBOXCRHGSMI_CALLDATA Buf;
228 PVBOXCRHGSMI_CALLDATA pBuf;
229 int cbBuffer = cbCallInfo + RT_OFFSETOF(VBOXCRHGSMI_CALLDATA, CallHdr.CallInfo);
230
231 if (cbBuffer <= sizeof (Buf))
232 pBuf = &Buf;
233 else
234 {
235 pBuf = (PVBOXCRHGSMI_CALLDATA)RTMemAlloc(cbBuffer);
236 if (!pBuf)
237 {
238 WARN(("RTMemAlloc failed!"));
239 return VERR_NO_MEMORY;
240 }
241 }
242
243 pBuf->CallHdr.EscapeHdr.escapeCode = VBOXESC_CRHGSMICTLCON_CALL;
244 pBuf->CallHdr.EscapeHdr.u32CmdSpecific = (uint32_t)VERR_GENERAL_FAILURE;
245 memcpy(&pBuf->CallHdr.CallInfo, pCallInfo, cbCallInfo);
246
247 int rc = vboxCrHgsmiPrivateEscape(pHgsmi, pBuf, cbBuffer, FALSE);
248 if (RT_SUCCESS(rc))
249 {
250 rc = (int)pBuf->CallHdr.EscapeHdr.u32CmdSpecific;
251 if (RT_SUCCESS(rc))
252 {
253 memcpy(pCallInfo, &pBuf->CallHdr.CallInfo, cbCallInfo);
254 rc = VINF_SUCCESS;
255 }
256 else
257 WARN(("vboxCrHgsmiPrivateEscape u32CmdSpecific failed, rc (%d)", rc));
258 }
259 else
260 WARN(("vboxCrHgsmiPrivateEscape failed, rc (%d)", rc));
261
262 /* cleanup */
263 if (pBuf != &Buf)
264 RTMemFree(pBuf);
265
266 return rc;
267}
268
269int vboxCrHgsmiPrivateCtlConGetClientID(struct VBOXUHGSMI_PRIVATE_BASE *pHgsmi, uint32_t *pu32ClientID)
270{
271 VBOXDISPIFESCAPE GetId = {0};
272 GetId.escapeCode = VBOXESC_CRHGSMICTLCON_GETCLIENTID;
273
274 int rc = vboxCrHgsmiPrivateEscape(pHgsmi, &GetId, sizeof (GetId), FALSE);
275 if (RT_SUCCESS(rc))
276 {
277 Assert(GetId.u32CmdSpecific);
278 *pu32ClientID = GetId.u32CmdSpecific;
279 return VINF_SUCCESS;
280 }
281 else
282 {
283 *pu32ClientID = 0;
284 WARN(("vboxCrHgsmiPrivateEscape failed, rc (%d)", rc));
285 }
286 return rc;
287}
288
289int vboxCrHgsmiPrivateCtlConGetHostCaps(struct VBOXUHGSMI_PRIVATE_BASE *pHgsmi, uint32_t *pu32HostCaps)
290{
291 VBOXDISPIFESCAPE GetHostCaps = {0};
292 GetHostCaps.escapeCode = VBOXESC_CRHGSMICTLCON_GETHOSTCAPS;
293
294 int rc = vboxCrHgsmiPrivateEscape(pHgsmi, &GetHostCaps, sizeof (GetHostCaps), FALSE);
295 if (RT_SUCCESS(rc))
296 {
297 *pu32HostCaps = GetHostCaps.u32CmdSpecific;
298 return VINF_SUCCESS;
299 }
300 else
301 {
302 *pu32HostCaps = 0;
303 WARN(("vboxCrHgsmiPrivateEscape failed, rc (%d)", rc));
304 }
305 return rc;
306}
Note: See TracBrowser for help on using the repository browser.

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