VirtualBox

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

Last change on this file since 53349 was 53349, checked in by vboxsync, 10 years ago

Additions/Video/WDDM: fix

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