VirtualBox

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

Last change on this file since 63566 was 63566, checked in by vboxsync, 9 years ago

scm: cleaning up todos

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