VirtualBox

source: vbox/trunk/src/VBox/Additions/3D/win/VBoxGL/VBoxGL.c@ 75443

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

Exported Mesa related code to OSE.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.1 KB
Line 
1/* $Id: VBoxGL.c 75443 2018-11-14 10:17:08Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Mesa3D - OpenGL driver.
4 */
5
6/*
7 * Copyright (C) 2018 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 "GaDrvEnvKMT.h"
19
20#include "stw_winsys.h"
21#include "stw_device.h"
22#include "stw_context.h"
23
24#include "pipe/p_state.h"
25#include "svga3d_reg.h"
26
27#include <iprt/asm.h>
28
29#include <common/wddm/VBoxMPIf.h>
30
31static const char *g_pszSvgaDll =
32#ifdef VBOX_WOW64
33 "VBoxSVGA-x86.dll"
34#else
35 "VBoxSVGA.dll"
36#endif
37;
38
39static struct GaDrvFunctions
40{
41 PFNGaDrvScreenCreate pfnGaDrvScreenCreate;
42 PFNGaDrvScreenDestroy pfnGaDrvScreenDestroy;
43 PFNGaDrvGetWDDMEnv pfnGaDrvGetWDDMEnv;
44 PFNGaDrvGetContextId pfnGaDrvGetContextId;
45 PFNGaDrvGetSurfaceId pfnGaDrvGetSurfaceId;
46 PFNGaDrvContextFlush pfnGaDrvContextFlush;
47} g_drvfuncs;
48
49
50static HMODULE gaDrvLoadSVGA(struct GaDrvFunctions *pDrvFuncs)
51{
52 struct VBOXWDDMDLLPROC aDrvProcs[] =
53 {
54 { "GaDrvScreenCreate", (FARPROC *)&pDrvFuncs->pfnGaDrvScreenCreate },
55 { "GaDrvScreenDestroy", (FARPROC *)&pDrvFuncs->pfnGaDrvScreenDestroy },
56 { "GaDrvGetWDDMEnv", (FARPROC *)&pDrvFuncs->pfnGaDrvGetWDDMEnv },
57 { "GaDrvGetContextId", (FARPROC *)&pDrvFuncs->pfnGaDrvGetContextId },
58 { "GaDrvGetSurfaceId", (FARPROC *)&pDrvFuncs->pfnGaDrvGetSurfaceId },
59 { "GaDrvContextFlush", (FARPROC *)&pDrvFuncs->pfnGaDrvContextFlush },
60 { NULL, NULL }
61 };
62
63 HMODULE hmod = VBoxWddmLoadAdresses(g_pszSvgaDll, aDrvProcs);
64 return hmod;
65}
66
67struct stw_shared_surface
68{
69 D3DKMT_HANDLE hResource;
70 D3DKMT_HANDLE hSurface;
71 uint32_t u32Sid;
72};
73
74static NTSTATUS vboxKmtPresent(D3DKMT_HANDLE hContext, HWND hwnd, D3DKMT_HANDLE hSource, LONG lWidth, LONG lHeight)
75{
76 RECT r;
77 r.left = 0;
78 r.top = 0;
79 r.right = lWidth;
80 r.bottom = lHeight;
81
82 D3DKMT_PRESENT PresentData;
83 memset(&PresentData, 0, sizeof(PresentData));
84 PresentData.hContext = hContext;
85 PresentData.hWindow = hwnd;
86 PresentData.hSource = hSource;
87 PresentData.hDestination = 0;
88 PresentData.Flags.Blt = 1;
89 PresentData.Flags.SrcRectValid = 1;
90 PresentData.Flags.DstRectValid = 1;
91 PresentData.SrcRect = r;
92 PresentData.SubRectCnt = 1;
93 PresentData.pSrcSubRects = &r;
94 PresentData.DstRect = r;
95
96 D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
97 NTSTATUS Status = d3dkmt->pfnD3DKMTPresent(&PresentData);
98 return Status;
99}
100
101NTSTATUS vboxKmtOpenSharedSurface(D3DKMT_HANDLE hDevice, D3DKMT_HANDLE hSharedSurface, struct stw_shared_surface *pSurf)
102{
103 D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
104
105 D3DKMT_QUERYRESOURCEINFO QueryResourceInfoData;
106 memset(&QueryResourceInfoData, 0, sizeof(QueryResourceInfoData));
107 QueryResourceInfoData.hDevice = hDevice;
108 QueryResourceInfoData.hGlobalShare = hSharedSurface;
109
110 NTSTATUS Status = d3dkmt->pfnD3DKMTQueryResourceInfo(&QueryResourceInfoData);
111 if (Status == STATUS_SUCCESS)
112 {
113 D3DDDI_OPENALLOCATIONINFO OpenAllocationInfoData;
114 memset(&OpenAllocationInfoData, 0, sizeof(OpenAllocationInfoData));
115
116 D3DKMT_OPENRESOURCE OpenResourceData;
117 memset(&OpenResourceData, 0, sizeof(OpenResourceData));
118 OpenResourceData.hDevice = hDevice;
119 OpenResourceData.hGlobalShare = hSharedSurface;
120 OpenResourceData.NumAllocations = 1;
121 OpenResourceData.pOpenAllocationInfo = &OpenAllocationInfoData;
122 if (QueryResourceInfoData.PrivateRuntimeDataSize)
123 {
124 OpenResourceData.pPrivateRuntimeData = malloc(QueryResourceInfoData.PrivateRuntimeDataSize);
125 if (OpenResourceData.pPrivateRuntimeData == NULL)
126 {
127 Status = STATUS_NOT_SUPPORTED;
128 }
129 OpenResourceData.PrivateRuntimeDataSize = QueryResourceInfoData.PrivateRuntimeDataSize;
130 }
131 if (QueryResourceInfoData.ResourcePrivateDriverDataSize)
132 {
133 OpenResourceData.pResourcePrivateDriverData = malloc(QueryResourceInfoData.ResourcePrivateDriverDataSize);
134 if (OpenResourceData.pResourcePrivateDriverData == NULL)
135 {
136 Status = STATUS_NOT_SUPPORTED;
137 }
138 OpenResourceData.ResourcePrivateDriverDataSize = QueryResourceInfoData.ResourcePrivateDriverDataSize;
139 }
140 if (QueryResourceInfoData.TotalPrivateDriverDataSize)
141 {
142 OpenResourceData.pTotalPrivateDriverDataBuffer = malloc(QueryResourceInfoData.TotalPrivateDriverDataSize);
143 if (OpenResourceData.pTotalPrivateDriverDataBuffer == NULL)
144 {
145 Status = STATUS_NOT_SUPPORTED;
146 }
147 OpenResourceData.TotalPrivateDriverDataBufferSize = QueryResourceInfoData.TotalPrivateDriverDataSize;
148 }
149
150 if (Status == STATUS_SUCCESS)
151 {
152 Status = d3dkmt->pfnD3DKMTOpenResource(&OpenResourceData);
153 if (Status == STATUS_SUCCESS)
154 {
155 Assert(OpenAllocationInfoData.PrivateDriverDataSize == sizeof(VBOXWDDM_ALLOCINFO));
156 VBOXWDDM_ALLOCINFO *pVBoxAllocInfo = (VBOXWDDM_ALLOCINFO *)OpenAllocationInfoData.pPrivateDriverData;
157 pSurf->hResource = OpenResourceData.hResource;
158 pSurf->hSurface = OpenAllocationInfoData.hAllocation;
159 pSurf->u32Sid = pVBoxAllocInfo->hostID;
160 }
161 }
162
163 if (OpenResourceData.pPrivateRuntimeData != NULL)
164 {
165 free(OpenResourceData.pPrivateRuntimeData);
166 }
167 if (OpenResourceData.pResourcePrivateDriverData != NULL)
168 {
169 free(OpenResourceData.pResourcePrivateDriverData);
170 }
171 if (OpenResourceData.pTotalPrivateDriverDataBuffer != NULL)
172 {
173 free(OpenResourceData.pTotalPrivateDriverDataBuffer);
174 }
175 }
176
177 return Status;
178}
179
180NTSTATUS vboxKmtCloseSharedSurface(D3DKMT_HANDLE hDevice, struct stw_shared_surface *pSurf)
181{
182 D3DKMTFUNCTIONS const *d3dkmt = D3DKMTFunctions();
183
184 D3DKMT_DESTROYALLOCATION DestroyAllocationData;
185 memset(&DestroyAllocationData, 0, sizeof(DestroyAllocationData));
186 DestroyAllocationData.hDevice = hDevice;
187 DestroyAllocationData.hResource = pSurf->hResource;
188 /* "If the OpenGL ICD sets the handle in the hResource member to a non-NULL value,
189 * the ICD must set phAllocationList to NULL." and
190 * "the AllocationCount member is ignored by the OpenGL runtime."
191 */
192 // DestroyAllocationData.phAllocationList = NULL;
193 // DestroyAllocationData.AllocationCount = 0;
194
195 NTSTATUS Status = d3dkmt->pfnD3DKMTDestroyAllocation(&DestroyAllocationData);
196 Assert(Status == STATUS_SUCCESS);
197 return Status;
198}
199
200
201static struct pipe_screen *
202wddm_screen_create(void)
203{
204 struct pipe_screen *screen = NULL;
205
206 if (gaDrvLoadSVGA(&g_drvfuncs))
207 {
208 WDDMGalliumDriverEnv const *pEnv = GaDrvEnvKmtCreate();
209 if (pEnv)
210 {
211 /// @todo pEnv to include destructor callback, to be called from winsys screen destructor?
212 screen = g_drvfuncs.pfnGaDrvScreenCreate(pEnv);
213 }
214 }
215
216 return screen;
217}
218
219static void
220wddm_present(struct pipe_screen *screen,
221 struct pipe_resource *res,
222 HDC hDC)
223{
224ASMBreakpoint();
225 struct stw_context *ctx = stw_current_context();
226 struct pipe_context *pipe = ctx->st->pipe;
227
228 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
229 if (pEnv)
230 {
231 /* Get context and kernel-mode handle of the resource. */
232 uint32_t u32Cid = g_drvfuncs.pfnGaDrvGetContextId(pipe);
233 D3DKMT_HANDLE hContext = GaDrvEnvKmtContextHandle(pEnv, u32Cid);
234
235 uint32_t u32SourceSid = g_drvfuncs.pfnGaDrvGetSurfaceId(screen, res);
236 D3DKMT_HANDLE hSource = GaDrvEnvKmtSurfaceHandle(pEnv, u32SourceSid);
237
238 HWND hwnd = WindowFromDC(hDC);
239
240 vboxKmtPresent(hContext, hwnd, hSource, res->width0, res->height0);
241 }
242}
243
244static boolean
245wddm_get_adapter_luid(struct pipe_screen *screen,
246 LUID *pAdapterLuid)
247{
248 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
249 if (pEnv)
250 {
251 GaDrvEnvKmtAdapterLUID(pEnv, pAdapterLuid);
252 return true;
253 }
254
255 return false;
256}
257
258static struct stw_shared_surface *
259wddm_shared_surface_open(struct pipe_screen *screen,
260 HANDLE hSharedSurface)
261{
262ASMBreakpoint();
263 struct stw_shared_surface *surface = NULL;
264
265 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
266 if (pEnv)
267 {
268 surface = (struct stw_shared_surface *)malloc(sizeof(struct stw_shared_surface));
269 if (surface)
270 {
271 D3DKMT_HANDLE hDevice = GaDrvEnvKmtDeviceHandle(pEnv);
272 NTSTATUS Status = vboxKmtOpenSharedSurface(hDevice, (D3DKMT_HANDLE)hSharedSurface, surface);
273 if (Status != STATUS_SUCCESS)
274 {
275 free(surface);
276 surface = NULL;
277 }
278 }
279 }
280 return surface;
281}
282
283static void
284wddm_shared_surface_close(struct pipe_screen *screen,
285 struct stw_shared_surface *surface)
286{
287ASMBreakpoint();
288 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
289 if (pEnv)
290 {
291 D3DKMT_HANDLE hDevice = GaDrvEnvKmtDeviceHandle(pEnv);
292 vboxKmtCloseSharedSurface(hDevice, surface);
293 }
294 free(surface);
295}
296
297static void
298wddm_compose(struct pipe_screen *screen,
299 struct pipe_resource *res,
300 struct stw_shared_surface *dest,
301 LPCRECT pRect,
302 ULONGLONG PresentHistoryToken)
303{
304ASMBreakpoint();
305 struct stw_context *ctx = stw_current_context();
306 struct pipe_context *pipe = ctx->st->pipe;
307
308 /* The ICD asked to present something, make sure that any outstanding commends are submitted. */
309 g_drvfuncs.pfnGaDrvContextFlush(pipe);
310
311 uint32_t u32SourceSid = g_drvfuncs.pfnGaDrvGetSurfaceId(screen, res);
312
313 /* Generate SVGA_3D_CMD_SURFACE_COPY command for these resources. */
314 struct
315 {
316 SVGA3dCmdHeader header;
317 SVGA3dCmdSurfaceCopy surfaceCopy;
318 SVGA3dCopyBox box;
319 } command;
320
321 command.header.id = SVGA_3D_CMD_SURFACE_COPY;
322 command.header.size = sizeof(command) - sizeof(SVGA3dCmdHeader);
323
324 command.surfaceCopy.src.sid = u32SourceSid;
325 command.surfaceCopy.src.face = 0;
326 command.surfaceCopy.src.mipmap = 0;
327 command.surfaceCopy.dest.sid = dest->u32Sid;
328 command.surfaceCopy.dest.face = 0;
329 command.surfaceCopy.dest.mipmap = 0;
330
331 command.box.x = pRect->left;
332 command.box.y = pRect->top;
333 command.box.z = 0;
334 command.box.w = pRect->right - pRect->left;
335 command.box.h = pRect->bottom - pRect->top;
336 command.box.d = 1;
337 command.box.srcx = 0;
338 command.box.srcy = 0;
339 command.box.srcz = 0;
340
341 const WDDMGalliumDriverEnv *pEnv = g_drvfuncs.pfnGaDrvGetWDDMEnv(screen);
342 if (pEnv)
343 {
344 uint32_t u32Cid = g_drvfuncs.pfnGaDrvGetContextId(pipe);
345 GaDrvEnvKmtRenderCompose(pEnv, u32Cid, &command, sizeof(command), PresentHistoryToken);
346 }
347}
348
349static const struct stw_winsys stw_winsys = {
350 wddm_screen_create,
351 wddm_present,
352 wddm_get_adapter_luid,
353 wddm_shared_surface_open,
354 wddm_shared_surface_close,
355 wddm_compose
356};
357
358BOOL WINAPI DllMain(HINSTANCE hDLLInst,
359 DWORD fdwReason,
360 LPVOID lpvReserved)
361{
362 RT_NOREF2(hDLLInst, lpvReserved);
363
364 switch (fdwReason)
365 {
366 case DLL_PROCESS_ATTACH:
367 D3DKMTLoad();
368 stw_init(&stw_winsys);
369 stw_init_thread();
370 break;
371
372 case DLL_PROCESS_DETACH:
373 break;
374
375 case DLL_THREAD_ATTACH:
376 stw_init_thread();
377 break;
378
379 case DLL_THREAD_DETACH:
380 stw_cleanup_thread();
381 break;
382
383 default:
384 if (lpvReserved == NULL)
385 {
386 // We're being unloaded from the process.
387 stw_cleanup_thread();
388 stw_cleanup();
389 }
390 else
391 {
392 // Process itself is terminating, and all threads and modules are
393 // being detached.
394 //
395 // The order threads (including llvmpipe rasterizer threads) are
396 // destroyed can not be relied up, so it's not safe to cleanup.
397 //
398 // However global destructors (e.g., LLVM's) will still be called, and
399 // if Microsoft OPENGL32.DLL's DllMain is called after us, it will
400 // still try to invoke DrvDeleteContext to destroys all outstanding,
401 // so set stw_dev to NULL to return immediately if that happens.
402 stw_dev = NULL;
403 }
404 break;
405 }
406
407 return TRUE;
408}
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