VirtualBox

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

Last change on this file since 42499 was 42499, checked in by vboxsync, 12 years ago

crOgl/wddm: per-context connections

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1/* $Id: VBoxUhgsmiBase.cpp 42499 2012-08-01 10:26:43Z 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->PrivateBase.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->PrivateBase.pHgsmi = pPrivate;
101 pBuffer->PrivateBase.Base.pfnLock = vboxUhgsmiBaseEscBufferLock;
102 pBuffer->PrivateBase.Base.pfnUnlock = vboxUhgsmiBaseEscBufferUnlock;
103 pBuffer->PrivateBase.Base.pfnDestroy = pfnDestroy;
104 pBuffer->PrivateBase.Base.fType = fUhgsmiType;
105 pBuffer->PrivateBase.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->PrivateBase.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 no 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) + 1)
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 pSubmInfo->Info.bDoNotSignalCompletion = 0;
181 if (pBufInfo->fFlags.bEntireBuffer)
182 {
183 pSubmInfo->Info.offData = 0;
184 pSubmInfo->Info.cbData = pBuf->PrivateBase.Base.cbBuffer;
185 }
186 else
187 {
188 pSubmInfo->Info.offData = pBufInfo->offData;
189 pSubmInfo->Info.cbData = pBufInfo->cbData;
190 }
191 }
192
193 int rc = vboxCrHgsmiPrivateEscape(pPrivate, &Buf.SubmitInfo, RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[cBuffers]), FALSE);
194 if (RT_SUCCESS(rc))
195 {
196 DWORD dwResult = WaitForSingleObject(hSynch, INFINITE);
197 if (dwResult == WAIT_OBJECT_0)
198 return VINF_SUCCESS;
199 WARN(("wait failed, (0x%x)", dwResult));
200 return VERR_GENERAL_FAILURE;
201 }
202 else
203 {
204 WARN(("vboxCrHgsmiPrivateEscape failed, rc (%d)", rc));
205 }
206
207 return VERR_GENERAL_FAILURE;
208}
209
210/* Cr calls have <= 3args, we try to allocate it on stack first */
211typedef struct VBOXCRHGSMI_CALLDATA
212{
213 VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL CallHdr;
214 HGCMFunctionParameter aArgs[3];
215} VBOXCRHGSMI_CALLDATA, *PVBOXCRHGSMI_CALLDATA;
216
217int vboxCrHgsmiPrivateCtlConCall(struct VBOXUHGSMI_PRIVATE_BASE *pHgsmi, struct VBoxGuestHGCMCallInfo *pCallInfo, int cbCallInfo)
218{
219 VBOXCRHGSMI_CALLDATA Buf;
220 PVBOXCRHGSMI_CALLDATA pBuf;
221 int cbBuffer = cbCallInfo + RT_OFFSETOF(VBOXCRHGSMI_CALLDATA, CallHdr.CallInfo);
222
223 if (cbBuffer <= sizeof (Buf))
224 pBuf = &Buf;
225 else
226 {
227 pBuf = (PVBOXCRHGSMI_CALLDATA)RTMemAlloc(cbBuffer);
228 if (!pBuf)
229 {
230 WARN(("RTMemAlloc failed!"));
231 return VERR_NO_MEMORY;
232 }
233 }
234
235 pBuf->CallHdr.EscapeHdr.escapeCode = VBOXESC_CRHGSMICTLCON_CALL;
236 pBuf->CallHdr.EscapeHdr.u32CmdSpecific = 0;
237 memcpy(&pBuf->CallHdr.CallInfo, pCallInfo, cbCallInfo);
238
239 int rc = vboxCrHgsmiPrivateEscape(pHgsmi, pBuf, cbBuffer, FALSE);
240 if (RT_SUCCESS(rc))
241 {
242 memcpy(pCallInfo, &pBuf->CallHdr.CallInfo, cbCallInfo);
243 rc = VINF_SUCCESS;
244 }
245 else
246 {
247 WARN(("vboxCrHgsmiPrivateEscape failed, rc (%d)", rc));
248 }
249 /* cleanup */
250 if (pBuf != &Buf)
251 RTMemFree(pBuf);
252
253 return rc;
254}
255
256int vboxCrHgsmiPrivateCtlConGetClientID(struct VBOXUHGSMI_PRIVATE_BASE *pHgsmi, uint32_t *pu32ClientID)
257{
258 VBOXDISPIFESCAPE GetId = {0};
259 GetId.escapeCode = VBOXESC_CRHGSMICTLCON_GETCLIENTID;
260
261 int rc = vboxCrHgsmiPrivateEscape(pHgsmi, &GetId, sizeof (GetId), FALSE);
262 if (RT_SUCCESS(rc))
263 {
264 Assert(GetId.u32CmdSpecific);
265 *pu32ClientID = GetId.u32CmdSpecific;
266 return VINF_SUCCESS;
267 }
268 else
269 {
270 *pu32ClientID = 0;
271 WARN(("vboxCrHgsmiPrivateEscape failed, rc (%d)", rc));
272 }
273 return rc;
274}
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