VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/xpdm/VBoxDispDriver.cpp@ 46896

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

VBoxDisp,VBoxVideo,VBoxControl: registry flags to tweak the Windows guest graphics driver.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.3 KB
Line 
1/* $Id: VBoxDispDriver.cpp 46896 2013-07-02 08:16:43Z vboxsync $ */
2
3/** @file
4 * VBox XPDM Display driver interface functions
5 */
6
7/*
8 * Copyright (C) 2011-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 "VBoxDisp.h"
20#include "VBoxDispMini.h"
21#include "VBoxDispDDraw.h"
22#include <iprt/initterm.h>
23
24/* Engine version we're running on, set in DrvEnableDriver */
25static ULONG g_EngineVersionDDI = DDI_DRIVER_VERSION_NT4;
26
27/* Callback function supported by our driver, stored in index/address pairs (see winddi.h) */
28/* NT4 version */
29static DRVFN g_aDrvFnTableNT4[] =
30{
31 /* Required functions */
32 {INDEX_DrvGetModes, (PFN) VBoxDispDrvGetModes },
33 {INDEX_DrvEnablePDEV, (PFN) VBoxDispDrvEnablePDEV },
34 {INDEX_DrvCompletePDEV, (PFN) VBoxDispDrvCompletePDEV },
35 {INDEX_DrvDisablePDEV, (PFN) VBoxDispDrvDisablePDEV },
36 {INDEX_DrvEnableSurface, (PFN) VBoxDispDrvEnableSurface },
37 {INDEX_DrvDisableSurface, (PFN) VBoxDispDrvDisableSurface },
38 {INDEX_DrvAssertMode, (PFN) VBoxDispDrvAssertMode },
39 /* Drawing commands */
40 {INDEX_DrvLineTo, (PFN) VBoxDispDrvLineTo },
41 {INDEX_DrvStrokePath, (PFN) VBoxDispDrvStrokePath },
42 {INDEX_DrvFillPath, (PFN) VBoxDispDrvFillPath },
43 {INDEX_DrvPaint, (PFN) VBoxDispDrvPaint },
44 {INDEX_DrvTextOut, (PFN) VBoxDispDrvTextOut },
45 {INDEX_DrvSaveScreenBits, (PFN) VBoxDispDrvSaveScreenBits },
46 /* BitBlt's*/
47 {INDEX_DrvBitBlt, (PFN) VBoxDispDrvBitBlt },
48 {INDEX_DrvStretchBlt, (PFN) VBoxDispDrvStretchBlt, },
49 {INDEX_DrvCopyBits, (PFN) VBoxDispDrvCopyBits },
50 /* Brush related */
51 {INDEX_DrvRealizeBrush, (PFN) VBoxDispDrvRealizeBrush },
52 {INDEX_DrvDitherColor, (PFN) VBoxDispDrvDitherColor },
53 /* Pointer related */
54 {INDEX_DrvSetPointerShape, (PFN) VBoxDispDrvSetPointerShape },
55 {INDEX_DrvMovePointer, (PFN) VBoxDispDrvMovePointer },
56 /* Misc */
57 {INDEX_DrvDisableDriver, (PFN) VBoxDispDrvDisableDriver },
58 {INDEX_DrvSetPalette, (PFN) VBoxDispDrvSetPalette },
59 {INDEX_DrvEscape, (PFN) VBoxDispDrvEscape },
60#ifdef VBOX_WITH_DDRAW
61 {INDEX_DrvGetDirectDrawInfo, (PFN) VBoxDispDrvGetDirectDrawInfo},
62 {INDEX_DrvEnableDirectDraw, (PFN) VBoxDispDrvEnableDirectDraw },
63 {INDEX_DrvDisableDirectDraw, (PFN) VBoxDispDrvDisableDirectDraw},
64#endif
65 /* g_aDrvFnTableNT4, NT4 specific */
66 {INDEX_DrvOffset, (PFN) VBoxDispDrvOffset } /*Obsolete*/
67};
68
69/* WIN2K+ version */
70static DRVFN g_aDrvFnTableNT5[] =
71{
72 /* Required functions */
73 {INDEX_DrvGetModes, (PFN) VBoxDispDrvGetModes },
74 {INDEX_DrvEnablePDEV, (PFN) VBoxDispDrvEnablePDEV },
75 {INDEX_DrvCompletePDEV, (PFN) VBoxDispDrvCompletePDEV },
76 {INDEX_DrvDisablePDEV, (PFN) VBoxDispDrvDisablePDEV },
77 {INDEX_DrvEnableSurface, (PFN) VBoxDispDrvEnableSurface },
78 {INDEX_DrvDisableSurface, (PFN) VBoxDispDrvDisableSurface },
79 {INDEX_DrvAssertMode, (PFN) VBoxDispDrvAssertMode },
80 /* Drawing commands */
81 {INDEX_DrvLineTo, (PFN) VBoxDispDrvLineTo },
82 {INDEX_DrvStrokePath, (PFN) VBoxDispDrvStrokePath },
83 {INDEX_DrvFillPath, (PFN) VBoxDispDrvFillPath },
84 {INDEX_DrvPaint, (PFN) VBoxDispDrvPaint },
85 {INDEX_DrvTextOut, (PFN) VBoxDispDrvTextOut },
86 {INDEX_DrvSaveScreenBits, (PFN) VBoxDispDrvSaveScreenBits },
87 /* BitBlt's*/
88 {INDEX_DrvBitBlt, (PFN) VBoxDispDrvBitBlt },
89 {INDEX_DrvStretchBlt, (PFN) VBoxDispDrvStretchBlt, },
90 {INDEX_DrvCopyBits, (PFN) VBoxDispDrvCopyBits },
91 /* Brush related */
92 {INDEX_DrvRealizeBrush, (PFN) VBoxDispDrvRealizeBrush },
93 {INDEX_DrvDitherColor, (PFN) VBoxDispDrvDitherColor },
94 /* Pointer related */
95 {INDEX_DrvSetPointerShape, (PFN) VBoxDispDrvSetPointerShape },
96 {INDEX_DrvMovePointer, (PFN) VBoxDispDrvMovePointer },
97 /* Misc */
98 {INDEX_DrvDisableDriver, (PFN) VBoxDispDrvDisableDriver },
99 {INDEX_DrvSetPalette, (PFN) VBoxDispDrvSetPalette },
100 {INDEX_DrvEscape, (PFN) VBoxDispDrvEscape },
101#ifdef VBOX_WITH_DDRAW
102 {INDEX_DrvGetDirectDrawInfo, (PFN) VBoxDispDrvGetDirectDrawInfo},
103 {INDEX_DrvEnableDirectDraw, (PFN) VBoxDispDrvEnableDirectDraw },
104 {INDEX_DrvDisableDirectDraw, (PFN) VBoxDispDrvDisableDirectDraw},
105#endif
106 /* g_aDrvFnTableNT5, NT5 specific */
107 {INDEX_DrvNotify, (PFN) VBoxDispDrvNotify },
108#ifdef VBOX_WITH_DDRAW
109 {INDEX_DrvDeriveSurface, (PFN) VBoxDispDrvDeriveSurface }
110#endif
111};
112
113#ifdef VBOX_WITH_CROGL
114typedef struct
115{
116 DWORD dwVersion;
117 DWORD dwDriverVersion;
118 WCHAR szDriverName[256];
119} OPENGL_INFO, *POPENGL_INFO;
120#endif
121
122RT_C_DECLS_BEGIN
123ULONG __cdecl DbgPrint(PCH pszFormat, ...)
124{
125 va_list args;
126 va_start(args, pszFormat);
127 RTLogBackdoorPrintfV(pszFormat, args);
128 va_end(args);
129
130 return 0;
131}
132RT_C_DECLS_END
133
134VOID _wcsncpy(WCHAR *pwcd, WCHAR *pwcs, ULONG dstsize)
135{
136 ULONG cnt=0;
137
138 while (*pwcs!=*L"")
139 {
140 if (cnt>=dstsize)
141 {
142 break;
143 }
144
145 *pwcd = *pwcs;
146
147 pwcs++;
148 pwcd++;
149 cnt ++;
150 }
151
152 if (cnt<dstsize)
153 {
154 memset(pwcd, 0, (dstsize-cnt) * sizeof(WCHAR));
155 }
156}
157
158#define VBOXDISPSETCIEC(_ciec, _x, _y, _lum) \
159 do { \
160 _ciec.x = _x; \
161 _ciec.y = _y; \
162 _ciec.Y = _lum; \
163 } while (0)
164
165
166#define VBOXDISPMAKELOGFONTW(_font, _w, _h, _weight, _clip, _quality, _pitch, _name) \
167 do { \
168 _font.lfHeight = _w; \
169 _font.lfWidth = _h; \
170 _font.lfEscapement = 0; \
171 _font.lfOrientation = 0; \
172 _font.lfWeight = _weight; \
173 _font.lfItalic = 0; \
174 _font.lfUnderline = 0; \
175 _font.lfStrikeOut = 0; \
176 _font.lfCharSet = ANSI_CHARSET; \
177 _font.lfOutPrecision = OUT_DEFAULT_PRECIS; \
178 _font.lfClipPrecision = _clip; \
179 _font.lfQuality = _quality; \
180 _font.lfPitchAndFamily = (_pitch) | FF_DONTCARE; \
181 memset(_font.lfFaceName, 0, sizeof(_font.lfFaceName)); \
182 memcpy(_font.lfFaceName, _name, sizeof(_name)); \
183 } while (0)
184
185static int VBoxDispInitDevice(PVBOXDISPDEV pDev, DEVMODEW *pdm, GDIINFO *pGdiInfo, DEVINFO *pDevInfo)
186{
187 VIDEO_MODE_INFORMATION *pModesTable, selectedMode;
188 ULONG cModes, i=0;
189 int rc;
190
191 LOGF_ENTER();
192
193 /* Get a list of supported modes by both miniport and display driver */
194 rc = VBoxDispMPGetVideoModes(pDev->hDriver, &pModesTable, &cModes);
195 VBOX_WARNRC_RETRC(rc);
196
197 /* Check if requested mode is available in the list */
198 if ((g_EngineVersionDDI < DDI_DRIVER_VERSION_NT5)
199 && (pdm->dmBitsPerPel==0)
200 && (pdm->dmPelsWidth==0)
201 && (pdm->dmPelsHeight==0)
202 && (pdm->dmDisplayFrequency==0))
203 {
204 /* Special case for NT4, just return default(first) mode */
205 memcpy(&selectedMode, &pModesTable[0], sizeof(VIDEO_MODE_INFORMATION));
206 }
207 else
208 {
209 for (; i<cModes; ++i)
210 {
211 if ((pdm->dmBitsPerPel == (pModesTable[i].BitsPerPlane * pModesTable[i].NumberOfPlanes))
212 && (pdm->dmPelsWidth == pModesTable[i].VisScreenWidth)
213 && (pdm->dmPelsHeight == pModesTable[i].VisScreenHeight)
214 && (pdm->dmDisplayFrequency == pModesTable[i].Frequency))
215 {
216 memcpy(&selectedMode, &pModesTable[i], sizeof(VIDEO_MODE_INFORMATION));
217 break;
218 }
219 }
220 }
221 EngFreeMem(pModesTable);
222
223 if (i>=cModes)
224 {
225 WARN(("can't support requested mode %dx%d@%dbpp(%dHz)!",
226 pdm->dmPelsWidth, pdm->dmPelsHeight, pdm->dmBitsPerPel, pdm->dmDisplayFrequency));
227 return VERR_NOT_SUPPORTED;
228 }
229
230 LOG(("match for requested mode %dx%d@%dbpp(%dHz)",
231 selectedMode.VisScreenWidth, selectedMode.VisScreenHeight, selectedMode.BitsPerPlane, selectedMode.Frequency));
232
233 /* Update private device info with mode information */
234 pDev->mode.ulIndex = selectedMode.ModeIndex;
235 pDev->mode.ulWidth = selectedMode.VisScreenWidth;
236 pDev->mode.ulHeight = selectedMode.VisScreenHeight;
237 pDev->mode.ulBitsPerPel = selectedMode.BitsPerPlane * selectedMode.NumberOfPlanes;
238 pDev->mode.lScanlineStride = selectedMode.ScreenStride;
239 pDev->mode.flMaskR = selectedMode.RedMask;
240 pDev->mode.flMaskG = selectedMode.GreenMask;
241 pDev->mode.flMaskB = selectedMode.BlueMask;
242 pDev->mode.ulPaletteShift = (pDev->mode.ulBitsPerPel==8) ? (8-selectedMode.NumberRedBits) : 0;
243
244 /* Fill GDIINFO structure */
245 memset(pGdiInfo, 0, sizeof(GDIINFO));
246
247 pGdiInfo->ulVersion = (g_EngineVersionDDI<DDI_DRIVER_VERSION_NT5) ? GDI_DRIVER_VERSION:0x5000;
248 pGdiInfo->ulVersion |= VBOXDISPDRIVERVERSION;
249
250 pGdiInfo->ulTechnology = DT_RASDISPLAY;
251
252 pGdiInfo->ulHorzSize = selectedMode.XMillimeter;
253 pGdiInfo->ulVertSize = selectedMode.YMillimeter;
254
255 pGdiInfo->ulHorzRes = pDev->mode.ulWidth;
256 pGdiInfo->ulVertRes = pDev->mode.ulHeight;
257
258 pGdiInfo->cBitsPixel = pDev->mode.ulBitsPerPel;
259 pGdiInfo->cPlanes = selectedMode.NumberOfPlanes;
260
261 pGdiInfo->ulNumColors = (pDev->mode.ulBitsPerPel==8) ? 20 : ((ULONG)(-1));
262
263 pGdiInfo->ulLogPixelsX = pdm->dmLogPixels;
264 pGdiInfo->ulLogPixelsY = pdm->dmLogPixels;
265 if (pdm->dmLogPixels!=96)
266 {
267 WARN(("requested logical pixel res %d isn't 96", pdm->dmLogPixels));
268 }
269
270 pGdiInfo->flTextCaps = TC_RA_ABLE;
271
272 pGdiInfo->ulDACRed = selectedMode.NumberRedBits;
273 pGdiInfo->ulDACGreen = selectedMode.NumberGreenBits;
274 pGdiInfo->ulDACBlue = selectedMode.NumberBlueBits;
275
276 pGdiInfo->ulAspectX = 0x24;
277 pGdiInfo->ulAspectY = 0x24;
278 /* note: ulAspectXY should be square root of sum of squares of x and y aspects */
279 pGdiInfo->ulAspectXY = 0x33;
280
281 /* search for "styled cosmetic lines" on msdn for more info */
282 pGdiInfo->xStyleStep = 1;
283 pGdiInfo->yStyleStep = 1;
284 pGdiInfo->denStyleStep = 3;
285
286 pGdiInfo->ulNumPalReg = (pDev->mode.ulBitsPerPel==8) ? (1<<pDev->mode.ulBitsPerPel) : 0;
287
288 /* @todo: might want to implement IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES in miniport driver
289 * and query host for this info there
290 */
291 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Red, 6700, 3300, 0);
292 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Green, 2100, 7100, 0);
293 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Blue, 1400, 800, 0);
294 VBOXDISPSETCIEC(pGdiInfo->ciDevice.AlignmentWhite, 3127, 3290, 0);
295 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Cyan, 0, 0, 0);
296 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Magenta, 0, 0, 0);
297 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Yellow, 0, 0, 0);
298 pGdiInfo->ciDevice.RedGamma = 20000;
299 pGdiInfo->ciDevice.GreenGamma = 20000;
300 pGdiInfo->ciDevice.BlueGamma = 20000;
301
302 pGdiInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA;
303
304 pGdiInfo->ulHTPatternSize = HT_PATSIZE_4x4_M;
305 switch (pDev->mode.ulBitsPerPel)
306 {
307 case 8:
308 {
309 pGdiInfo->ulHTOutputFormat = HT_FORMAT_8BPP;
310 break;
311 }
312 case 16:
313 {
314 pGdiInfo->ulHTOutputFormat = HT_FORMAT_16BPP;
315 break;
316 }
317 case 24:
318 {
319 pGdiInfo->ulHTOutputFormat = HT_FORMAT_24BPP;
320 break;
321 }
322 case 32:
323 {
324 pGdiInfo->ulHTOutputFormat = HT_FORMAT_32BPP;
325 break;
326 }
327 }
328 pGdiInfo->flHTFlags = HT_FLAG_ADDITIVE_PRIMS;
329
330 pGdiInfo->ulVRefresh = selectedMode.Frequency;
331
332 /* 0 means BitBlt's are accelerated by driver */
333 pGdiInfo->ulBltAlignment = 0;
334
335 pGdiInfo->ulPhysicalPixelCharacteristics = PPC_UNDEFINED;
336 pGdiInfo->ulPhysicalPixelGamma = PPG_DEFAULT;
337
338 /* Fill DEVINFO structure */
339 memset(pDevInfo, 0, sizeof(DEVINFO));
340
341 pDevInfo->flGraphicsCaps = GCAPS_OPAQUERECT;
342#ifdef VBOX_WITH_DDRAW
343 pDevInfo->flGraphicsCaps |= GCAPS_DIRECTDRAW;
344#endif
345 VBOXDISPMAKELOGFONTW(pDevInfo->lfDefaultFont,
346 16, 7, FW_BOLD, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH, L"System");
347
348 VBOXDISPMAKELOGFONTW(pDevInfo->lfAnsiVarFont,
349 12, 9, FW_NORMAL, CLIP_STROKE_PRECIS, PROOF_QUALITY, VARIABLE_PITCH, L"MS Sans Serif");
350
351 VBOXDISPMAKELOGFONTW(pDevInfo->lfAnsiFixFont,
352 12, 9, FW_NORMAL, CLIP_STROKE_PRECIS, PROOF_QUALITY, FIXED_PITCH, L"Courier");
353 pDevInfo->cFonts = 0;
354 pDevInfo->cxDither = 8;
355 pDevInfo->cyDither = 8;
356 pDevInfo->hpalDefault = 0;
357 pDevInfo->flGraphicsCaps2 = 0;
358
359 switch (pDev->mode.ulBitsPerPel)
360 {
361 case 8:
362 {
363 pDevInfo->flGraphicsCaps |= GCAPS_PALMANAGED|GCAPS_COLOR_DITHER;
364 pDevInfo->iDitherFormat = BMF_8BPP;
365 break;
366 }
367 case 16:
368 {
369 pDevInfo->iDitherFormat = BMF_16BPP;
370 break;
371 }
372 case 24:
373 {
374 pDevInfo->iDitherFormat = BMF_24BPP;
375 break;
376 }
377 case 32:
378 {
379 pDevInfo->iDitherFormat = BMF_32BPP;
380 break;
381 }
382 }
383
384 LOGF_LEAVE();
385 return rc;
386}
387
388/* Display Driver entry point,
389 * Returns DDI version number and callbacks supported by driver.
390 */
391BOOL DrvEnableDriver(ULONG iEngineVersion, ULONG cj, PDRVENABLEDATA pded)
392{
393 /*@todo: can't link with hal.lib
394 int irc = RTR0Init(0);
395 if (RT_FAILURE(irc))
396 {
397 LOGREL(("failed to init IPRT (rc=%#x)", irc));
398 return FALSE;
399 }
400 */
401
402 LOGF(("iEngineVersion=%#08X, cj=%d", iEngineVersion, cj));
403
404 g_EngineVersionDDI = iEngineVersion;
405
406 /* Driver can't work if we can't fill atleast first 3 fields in passed PDRVENABLEDATA */
407 if (cj < (2*sizeof(ULONG)+sizeof(DRVFN*)))
408 {
409 WARN(("cj<%d, terminating\n", sizeof(DRVENABLEDATA)));
410 return FALSE;
411 }
412
413 /* Report driver DDI version and appropriate callbacks table based on engine DDI */
414 if (iEngineVersion>=DDI_DRIVER_VERSION_NT5)
415 {
416 /* WIN2K and above */
417 pded->iDriverVersion = DDI_DRIVER_VERSION_NT5;
418 pded->pdrvfn = g_aDrvFnTableNT5;
419 pded->c = RT_ELEMENTS(g_aDrvFnTableNT5);
420 }
421 else
422 {
423 /* NT4_SP3 and below*/
424 pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
425 pded->pdrvfn = g_aDrvFnTableNT4;
426 pded->c = RT_ELEMENTS(g_aDrvFnTableNT4);
427 }
428
429 LOGF_LEAVE();
430 return TRUE;
431}
432
433/* Free all resources allocated in DrvEnableDriver */
434VOID APIENTRY VBoxDispDrvDisableDriver()
435{
436 LOGF_ENTER();
437
438 /* Intentionally left blank */
439
440 LOGF_LEAVE();
441 return;
442}
443
444/* Returns video modes supported by our device/driver
445 * Note: If we fail here we'd be asked to enter 800x600@4bpp mode later in VBoxDispDrvEnablePDEV.
446 */
447ULONG APIENTRY VBoxDispDrvGetModes(HANDLE hDriver, ULONG cjSize, DEVMODEW *pdm)
448{
449 int rc;
450 VIDEO_MODE_INFORMATION *pModesTable;
451 ULONG cModes;
452 LOGF_ENTER();
453
454 rc = VBoxDispMPGetVideoModes(hDriver, &pModesTable, &cModes);
455 VBOX_WARNRC_RETV(rc, 0);
456
457 if (!pdm) /* return size of buffer required to store all supported modes */
458 {
459 EngFreeMem(pModesTable);
460 LOGF_LEAVE();
461 return cModes * sizeof(DEVMODEW);
462 }
463
464 ULONG mode, cMaxNodes=cjSize/sizeof(DEVMODEW);
465
466 for (mode=0; mode<cModes && mode<cMaxNodes; ++mode, ++pdm)
467 {
468 memset(pdm, 0, sizeof(DEVMODEW));
469 memcpy(pdm->dmDeviceName, VBOXDISP_DEVICE_NAME, sizeof(VBOXDISP_DEVICE_NAME));
470
471 pdm->dmSpecVersion = DM_SPECVERSION;
472 pdm->dmDriverVersion = DM_SPECVERSION;
473 pdm->dmSize = sizeof(DEVMODEW);
474 pdm->dmDriverExtra = 0;
475
476 pdm->dmBitsPerPel = pModesTable[mode].NumberOfPlanes*pModesTable[mode].BitsPerPlane;
477 pdm->dmPelsWidth = pModesTable[mode].VisScreenWidth;
478 pdm->dmPelsHeight = pModesTable[mode].VisScreenHeight;
479 pdm->dmDisplayFrequency = pModesTable[mode].Frequency;
480 pdm->dmDisplayFlags = 0;
481 pdm->dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY|DM_DISPLAYFLAGS;
482 }
483 EngFreeMem(pModesTable);
484
485 LOG(("%d mode(s) reported", mode));
486
487 LOGF_LEAVE();
488 return mode * sizeof(DEVMODEW);
489}
490
491/* First function which is called after entry point, provides info about device to GDI.
492 * Returns pointer to our driver private info structure which would be passed by GDI to our other callbacks.
493 */
494DHPDEV APIENTRY
495VBoxDispDrvEnablePDEV(DEVMODEW *pdm, LPWSTR pwszLogAddress, ULONG cPat, HSURF *phsurfPatterns,
496 ULONG cjCaps, ULONG *pdevcaps,
497 ULONG cjDevInfo, DEVINFO *pdi,
498 HDEV hdev, PWSTR pwszDeviceName, HANDLE hDriver)
499{
500 PVBOXDISPDEV pDev = NULL;
501 GDIINFO gdiInfo;
502 DEVINFO devInfo;
503 int rc;
504
505 /* Next 3 are only used for printer drivers */
506 NOREF(pwszLogAddress);
507 NOREF(cPat);
508 NOREF(phsurfPatterns);
509 NOREF(pwszDeviceName);
510
511 LOGF_ENTER();
512
513 pDev = (PVBOXDISPDEV) EngAllocMem(FL_ZERO_MEMORY, sizeof(VBOXDISPDEV), MEM_ALLOC_TAG);
514 if (!pDev)
515 {
516 WARN(("EngAllocMem failed!\n"));
517 return NULL;
518 }
519 pDev->hDriver = hDriver;
520
521 ULONG ulRegistryFlags = 0;
522 rc = VBoxDispMPQueryRegistryFlags(hDriver, &ulRegistryFlags);
523 if (RT_SUCCESS(rc))
524 {
525 pDev->bBitmapCacheDisabled = (ulRegistryFlags & VBOXVIDEO_REGISTRY_FLAGS_DISABLE_BITMAP_CACHE) != 0;
526 LOG(("Bitmap cache %s", pDev->bBitmapCacheDisabled? "disabled": "enabled"));
527 }
528
529 /* Initialize device structure and query miniport to fill device and gdi infos */
530 rc = VBoxDispInitDevice(pDev, pdm, &gdiInfo, &devInfo);
531 if (RT_FAILURE(rc))
532 {
533 VBOX_WARNRC(rc);
534 EngFreeMem(pDev);
535 return NULL;
536 }
537
538 /* Initialize mouse pointer caps */
539 rc = VBoxDispInitPointerCaps(pDev, &devInfo);
540 if (RT_FAILURE(rc))
541 {
542 VBOX_WARNRC(rc);
543 }
544
545 /* Initialize palette */
546 rc = VBoxDispInitPalette(pDev, &devInfo);
547 if (RT_FAILURE(rc))
548 {
549 VBOX_WARNRC(rc);
550 EngFreeMem(pDev);
551 return NULL;
552 }
553
554 if(g_EngineVersionDDI >= DDI_DRIVER_VERSION_NT5)
555 {
556 devInfo.flGraphicsCaps2 |= GCAPS2_RESERVED1;
557 }
558
559 /* Copy gathered info to supplied buffers */
560 memcpy(pdevcaps, &gdiInfo, min(sizeof(GDIINFO), cjCaps));
561 memcpy(pdi, &devInfo, min(sizeof(DEVINFO), cjDevInfo));
562
563 LOGF_LEAVE();
564 return (DHPDEV)pDev;
565}
566
567/* Called to provide us GDI handle for our device, which we should use later for GDI calls */
568VOID APIENTRY VBoxDispDrvCompletePDEV(DHPDEV dhpdev, HDEV hdev)
569{
570 LOGF_ENTER();
571
572 ((PVBOXDISPDEV)dhpdev)->hDevGDI = hdev;
573
574 LOGF_LEAVE();
575}
576
577/* Called to free resources allocated for device in VBoxDispDrvEnablePDEV */
578VOID APIENTRY VBoxDispDrvDisablePDEV(DHPDEV dhpdev)
579{
580 LOGF_ENTER();
581
582 VBoxDispDestroyPalette((PVBOXDISPDEV) dhpdev);
583
584 EngFreeMem(dhpdev);
585
586 LOGF_LEAVE();
587}
588
589/* Called to create and associate surface with device */
590HSURF APIENTRY VBoxDispDrvEnableSurface(DHPDEV dhpdev)
591{
592 int rc;
593 PVBOXDISPDEV pDev = (PVBOXDISPDEV)dhpdev;
594
595 LOGF_ENTER();
596
597 /* Switch device to mode requested in VBoxDispDrvEnablePDEV */
598 rc = VBoxDispMPSetCurrentMode(pDev->hDriver, pDev->mode.ulIndex);
599 VBOX_WARNRC_RETV(rc, NULL);
600
601 /* Map fb and vram */
602 rc = VBoxDispMPMapMemory(pDev, &pDev->memInfo);
603 VBOX_WARNRC_RETV(rc, NULL);
604
605 /* Clear mapped memory, to avoid garbage while video mode is switching */
606 /* @todo: VIDEO_MODE_NO_ZERO_MEMORY does nothing in miniport's IOCTL_VIDEO_SET_CURRENT_MODE*/
607 memset(pDev->memInfo.FrameBufferBase, 0, pDev->mode.ulHeight * abs(pDev->mode.lScanlineStride));
608
609 /* Allocate memory for pointer attrs */
610 rc = VBoxDispInitPointerAttrs(pDev);
611 VBOX_WARNRC_RETV(rc, NULL);
612
613 /* Init VBVA */
614 rc = VBoxDispVBVAInit(pDev);
615 VBOX_WARNRC_RETV(rc, NULL);
616
617 /* Enable VBVA */
618 if (pDev->hgsmi.bSupported)
619 {
620 if (pDev->mode.ulBitsPerPel==16 || pDev->mode.ulBitsPerPel==24 || pDev->mode.ulBitsPerPel==32)
621 {
622 VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)pDev->memInfo.VideoRamBase+pDev->layout.offVBVABuffer);
623 pDev->hgsmi.bSupported = VBoxVBVAEnable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, pVBVA, -1);
624 LogRel(("VBoxDisp[%d]: VBVA %senabled\n", pDev->iDevice, pDev->hgsmi.bSupported? "":"not "));
625 }
626 }
627
628 /* Inform host */
629 if (pDev->hgsmi.bSupported)
630 {
631 VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y,
632 0, abs(pDev->mode.lScanlineStride), pDev->mode.ulWidth, pDev->mode.ulHeight,
633 (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE);
634 }
635
636#ifdef VBOX_WITH_VIDEOHWACCEL
637 VBoxDispVHWAEnable(pDev);
638#endif
639
640 /* Set device palette if needed */
641 if (pDev->mode.ulBitsPerPel == 8)
642 {
643 rc = VBoxDispSetPalette8BPP(pDev);
644 VBOX_WARNRC_RETV(rc, NULL);
645 }
646
647 pDev->orgDisp.x = 0;
648 pDev->orgDisp.y = 0;
649
650 /* Create GDI managed bitmap, which resides in our framebuffer memory */
651 ULONG iFormat;
652 SIZEL size;
653
654 switch (pDev->mode.ulBitsPerPel)
655 {
656 case 8:
657 {
658 iFormat = BMF_8BPP;
659 break;
660 }
661 case 16:
662 {
663 iFormat = BMF_16BPP;
664 break;
665 }
666 case 24:
667 {
668 iFormat = BMF_24BPP;
669 break;
670 }
671 case 32:
672 {
673 iFormat = BMF_32BPP;
674 break;
675 }
676 }
677
678 size.cx = pDev->mode.ulWidth;
679 size.cy = pDev->mode.ulHeight;
680
681 pDev->surface.hBitmap = EngCreateBitmap(size, pDev->mode.lScanlineStride, iFormat,
682 pDev->mode.lScanlineStride>0 ? BMF_TOPDOWN:0,
683 pDev->memInfo.FrameBufferBase);
684 if (!pDev->surface.hBitmap)
685 {
686 WARN(("EngCreateBitmap failed!"));
687 return NULL;
688 }
689 pDev->surface.psoBitmap = EngLockSurface((HSURF)pDev->surface.hBitmap);
690
691 /* Create device-managed surface */
692 pDev->surface.hSurface = EngCreateDeviceSurface((DHSURF)pDev, size, iFormat);
693 if (!pDev->surface.hSurface)
694 {
695 WARN(("EngCreateDeviceSurface failed!"));
696 VBoxDispDrvDisableSurface(dhpdev);
697 return NULL;
698 }
699
700 FLONG flHooks = HOOK_BITBLT|HOOK_TEXTOUT|HOOK_FILLPATH|HOOK_COPYBITS|HOOK_STROKEPATH|HOOK_LINETO|
701 HOOK_PAINT|HOOK_STRETCHBLT;
702
703 /* Associate created surface with our device */
704 if (!EngAssociateSurface(pDev->surface.hSurface, pDev->hDevGDI, flHooks))
705 {
706 WARN(("EngAssociateSurface failed!"));
707 VBoxDispDrvDisableSurface(dhpdev);
708 return NULL;
709 }
710
711 pDev->surface.ulFormat = iFormat;
712 pDev->flDrawingHooks = flHooks;
713
714 LOG(("Created surface %p for physical device %p", pDev->surface.hSurface, pDev));
715
716 LOGF_LEAVE();
717 return pDev->surface.hSurface;
718}
719
720VOID APIENTRY VBoxDispDrvDisableSurface(DHPDEV dhpdev)
721{
722 PVBOXDISPDEV pDev = (PVBOXDISPDEV)dhpdev;
723 LOGF_ENTER();
724
725 if (pDev->surface.hSurface)
726 {
727 EngDeleteSurface(pDev->surface.hSurface);
728 pDev->surface.hSurface = NULL;
729 }
730
731 if (pDev->surface.psoBitmap)
732 {
733 Assert(pDev->surface.hBitmap);
734 EngUnlockSurface(pDev->surface.psoBitmap);
735 pDev->surface.psoBitmap = NULL;
736 }
737
738 if (pDev->surface.hBitmap)
739 {
740 EngDeleteSurface((HSURF) pDev->surface.hBitmap);
741 pDev->surface.hBitmap = NULL;
742 }
743
744 int rc;
745 rc = VBoxDispMPUnmapMemory(pDev);
746 VBOX_WARNRC(rc);
747
748 LOGF_LEAVE();
749}
750
751BOOL APIENTRY
752VBoxDispDrvRealizeBrush(BRUSHOBJ *pbo, SURFOBJ *psoTarget, SURFOBJ *psoPattern, SURFOBJ *psoMask,
753 XLATEOBJ *pxlo, ULONG iHatch)
754{
755 BOOL bRc = FALSE;
756 LOGF_ENTER();
757
758 if (VBoxDispIsScreenSurface(psoTarget))
759 {
760 PVBOXDISPDEV pDev = (PVBOXDISPDEV)psoTarget->dhpdev;
761
762 if (pDev->vbvaCtx.pVBVA && (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
763 {
764 if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET)
765 {
766 vrdpReset(pDev);
767 pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents &= ~VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;
768 }
769
770 if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_VRDP)
771 {
772 bRc = vrdpDrvRealizeBrush(pbo, psoTarget, psoPattern, psoMask, pxlo, iHatch);
773 }
774 }
775 }
776
777 LOGF_LEAVE();
778 return bRc;
779}
780
781ULONG APIENTRY VBoxDispDrvDitherColor(DHPDEV dhpdev, ULONG iMode, ULONG rgb, ULONG *pul)
782{
783 ULONG rc;
784 LOGF_ENTER();
785
786 /* There is no EngDitherColor on NT4, so take the easy path and tell the graphics
787 * engine to create a halftone approximation.
788 */
789 rc = DCR_HALFTONE;
790
791 LOGF_LEAVE();
792 return rc;
793}
794
795/* Called to reset device to default mode or to mode specified with dhpdev */
796BOOL APIENTRY VBoxDispDrvAssertMode(DHPDEV dhpdev, BOOL bEnable)
797{
798 PVBOXDISPDEV pDev = (PVBOXDISPDEV) dhpdev;
799 int rc;
800 LOGF_ENTER();
801
802 if (!bEnable)
803 {
804 LOGF(("!bEnable"));
805#ifdef VBOX_WITH_VIDEOHWACCEL
806 /* tells we can not process host commands any more and ensures that
807 * we've completed processing of the host VHWA commands
808 */
809 VBoxDispVHWADisable(pDev);
810#endif
811
812 /* disable VBVA */
813 if (pDev->hgsmi.bSupported)
814 {
815 VBoxVBVADisable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, -1);
816 }
817
818 /* reset the device to default mode */
819 rc = VBoxDispMPResetDevice(pDev->hDriver);
820 VBOX_WARNRC_RETV(rc, FALSE);
821 }
822 else
823 {
824 LOGF(("bEnable"));
825
826 /* switch device to previous pDev mode */
827 rc = VBoxDispMPSetCurrentMode(pDev->hDriver, pDev->mode.ulIndex);
828 VBOX_WARNRC_RETV(rc, NULL);
829
830 /* enable VBVA */
831 if (pDev->hgsmi.bSupported)
832 {
833 if (pDev->mode.ulBitsPerPel==16 || pDev->mode.ulBitsPerPel==24 || pDev->mode.ulBitsPerPel==32)
834 {
835 VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)pDev->memInfo.VideoRamBase+pDev->layout.offVBVABuffer);
836 pDev->hgsmi.bSupported = VBoxVBVAEnable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, pVBVA, -1);
837 LogRel(("VBoxDisp[%d]: VBVA %senabled\n", pDev->iDevice, pDev->hgsmi.bSupported? "":"not "));
838 }
839 }
840
841 /* inform host */
842 if (pDev->hgsmi.bSupported)
843 {
844 VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y,
845 0, abs(pDev->mode.lScanlineStride), pDev->mode.ulWidth, pDev->mode.ulHeight,
846 (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE);
847 }
848
849#ifdef VBOX_WITH_VIDEOHWACCEL
850 /* tells we can process host commands */
851 VBoxDispVHWAEnable(pDev);
852#endif
853
854 /* Associate back GDI bitmap residing in our framebuffer memory with GDI's handle to our device */
855 if (!EngAssociateSurface((HSURF)pDev->surface.hBitmap, pDev->hDevGDI, 0))
856 {
857 WARN(("EngAssociateSurface on bitmap failed"));
858 return FALSE;
859 }
860
861 /* Associate device managed surface with GDI's handle to our device */
862 if (!EngAssociateSurface(pDev->surface.hSurface, pDev->hDevGDI, pDev->flDrawingHooks))
863 {
864 WARN(("EngAssociateSurface on surface failed"));
865 return FALSE;
866 }
867 }
868
869 LOGF_LEAVE();
870 return TRUE;
871}
872
873ULONG APIENTRY VBoxDispDrvEscape(SURFOBJ *pso, ULONG iEsc, ULONG cjIn, PVOID pvIn, ULONG cjOut, PVOID pvOut)
874{
875 PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
876 LOGF_ENTER();
877
878 switch (iEsc)
879 {
880#ifdef VBOX_WITH_CROGL
881 case OPENGL_GETINFO:
882 {
883 if (pvOut && cjOut >= sizeof(OPENGL_INFO))
884 {
885 POPENGL_INFO pInfo = (POPENGL_INFO)pvOut;
886
887 pInfo->dwVersion = 2;
888 pInfo->dwDriverVersion = 1;
889 pInfo->szDriverName[0] = 'V';
890 pInfo->szDriverName[1] = 'B';
891 pInfo->szDriverName[2] = 'o';
892 pInfo->szDriverName[3] = 'x';
893 pInfo->szDriverName[4] = 'O';
894 pInfo->szDriverName[5] = 'G';
895 pInfo->szDriverName[6] = 'L';
896 pInfo->szDriverName[7] = 0;
897
898 LOG(("OPENGL_GETINFO ok"));
899 return cjOut;
900 }
901 else
902 {
903 WARN(("OPENGL_GETINFO invalid parms"));
904 return 0;
905 }
906 }
907 case QUERYESCSUPPORT:
908 {
909 if (pvIn && cjIn == sizeof(DWORD))
910 {
911 DWORD nEscapeQuery = *(DWORD *)pvIn;
912
913 if (nEscapeQuery==OPENGL_GETINFO)
914 {
915 LOG(("QUERYESCSUPPORT OPENGL_GETINFO"));
916 return 1;
917 }
918 else
919 {
920 LOG(("QUERYESCSUPPORT unsupported query %d", nEscapeQuery));
921 return 0;
922 }
923 }
924 else
925 {
926 WARN(("QUERYESCSUPPORT invalid parms"));
927 return 0;
928 }
929 }
930#endif
931 case VBOXESC_ISVRDPACTIVE:
932 {
933 if (pDev && pDev->vbvaCtx.pVBVA && pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents&VBVA_F_MODE_VRDP)
934 {
935 LOGF(("VBOXESC_ISVRDPACTIVE: 1"));
936 return 1;
937 }
938 LOGF(("VBOXESC_ISVRDPACTIVE: 0"));
939 return 0;
940 }
941 case VBOXESC_SETVISIBLEREGION:
942 {
943 LOGF(("VBOXESC_SETVISIBLEREGION"));
944 LPRGNDATA lpRgnData = (LPRGNDATA)pvIn;
945 DWORD cRects;
946
947 if ( cjIn >= sizeof(RGNDATAHEADER)
948 && pvIn
949 && lpRgnData->rdh.dwSize == sizeof(RGNDATAHEADER)
950 && lpRgnData->rdh.iType == RDH_RECTANGLES
951 && (cRects = lpRgnData->rdh.nCount) <= _1M
952 && cjIn == cRects * (uint64_t)sizeof(RECT) + sizeof(RGNDATAHEADER))
953 {
954 /** @todo this whole conversion thing could maybe be skipped
955 * since RTRECT matches the RECT layout. */
956#if 0
957 AssertCompile(sizeof(RTRECT) == sizeof(RECT));
958 AssertCompileMembersSameSizeAndOffset(RTRECT, xLeft, RECT, left);
959 AssertCompileMembersSameSizeAndOffset(RTRECT, xBottom, RECT, bottom);
960 AssertCompileMembersSameSizeAndOffset(RTRECT, xRight, RECT, right);
961 AssertCompileMembersSameSizeAndOffset(RTRECT, xTop, RECT, top);
962
963 rc = VBoxDispMPSetVisibleRegion(pDev->hDriver, (PRTRECT)&lpRgnData->Buffer[0], cRects);
964 VBOX_WARNRC(rc);
965#else
966 DWORD i;
967 PRTRECT pRTRect;
968 int rc;
969 RECT *pRect = (RECT *)&lpRgnData->Buffer;
970
971 pRTRect = (PRTRECT) EngAllocMem(0, cRects*sizeof(RTRECT), MEM_ALLOC_TAG);
972 if (!pRTRect)
973 {
974 WARN(("failed to allocate %d bytes", cRects*sizeof(RTRECT)));
975 break;
976 }
977
978 for (i = 0; i < cRects; ++i)
979 {
980 LOG(("New visible rectangle (%d,%d) (%d,%d)",
981 pRect[i].left, pRect[i].bottom, pRect[i].right, pRect[i].top));
982 pRTRect[i].xLeft = pRect[i].left;
983 pRTRect[i].yBottom = pRect[i].bottom;
984 pRTRect[i].xRight = pRect[i].right;
985 pRTRect[i].yTop = pRect[i].top;
986 }
987
988 rc = VBoxDispMPSetVisibleRegion(pDev->hDriver, pRTRect, cRects);
989 VBOX_WARNRC(rc);
990
991 EngFreeMem(pRTRect);
992
993#endif
994 if (RT_SUCCESS(rc))
995 {
996 LOGF_LEAVE();
997 return 1;
998 }
999 }
1000 else
1001 {
1002 if (pvIn)
1003 {
1004 WARN(("check failed rdh.dwSize=%x iType=%d size=%d expected size=%d",
1005 lpRgnData->rdh.dwSize, lpRgnData->rdh.iType, cjIn,
1006 lpRgnData->rdh.nCount * sizeof(RECT) + sizeof(RGNDATAHEADER)));
1007 }
1008 }
1009 break;
1010 }
1011 case VBOXESC_ISANYX:
1012 {
1013 if (pvOut && cjOut == sizeof(DWORD))
1014 {
1015 DWORD cbReturned;
1016 DWORD dwrc = EngDeviceIoControl(pDev->hDriver, IOCTL_VIDEO_VBOX_ISANYX, NULL, 0,
1017 pvOut, sizeof (uint32_t), &cbReturned);
1018 if (dwrc == NO_ERROR && cbReturned == sizeof (uint32_t))
1019 return 1;
1020 WARN(("EngDeviceIoControl failed, dwrc(%d), cbReturned(%d)", dwrc, cbReturned));
1021 return 0;
1022 }
1023 else
1024 {
1025 WARN(("VBOXESC_ISANYX invalid parms"));
1026 return 0;
1027 }
1028 break;
1029 }
1030 default:
1031 {
1032 LOG(("unsupported iEsc %#x", iEsc));
1033 }
1034 }
1035
1036 LOGF_LEAVE();
1037 return 0;
1038}
1039
1040#define FB_OFFSET(_dev, _x, _y) ((_y)*pDev->mode.lScanlineStride) + ((_x)*((pDev->mode.ulBitsPerPel+1)/8))
1041/* Obsolete, NT4 specific. Called to set display offset in virtual desktop */
1042BOOL APIENTRY VBoxDispDrvOffset(SURFOBJ* pso, LONG x, LONG y, FLONG flReserved)
1043{
1044 PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
1045 LOGF(("%x %x %x\n", x, y, flReserved));
1046
1047 pDev->memInfo.FrameBufferBase = ((BYTE*)pDev->memInfo.VideoRamBase) + pDev->layout.offFramebuffer
1048 - FB_OFFSET(pDev, x, y);
1049
1050 pDev->orgDisp.x = x;
1051 pDev->orgDisp.y = y;
1052
1053 LOGF_LEAVE();
1054 return TRUE;
1055}
1056
1057/* Called to notify driver about various events */
1058VOID APIENTRY VBoxDispDrvNotify(SURFOBJ *pso, ULONG iType, PVOID pvData)
1059{
1060 PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
1061 LOGF_ENTER();
1062
1063 switch (iType)
1064 {
1065 case DN_DEVICE_ORIGIN:
1066 {
1067 /*device origin in dualview*/
1068 POINTL *pOrg = (POINTL *)pvData;
1069 if (pOrg)
1070 {
1071 LOG(("DN_DEVICE_ORIGIN (pso=%p, pDev[%d]=%p) old=%d,%d new=%d,%d",
1072 pso, pDev->iDevice, pDev, pDev->orgDev.x, pDev->orgDev.y, pOrg->x, pOrg->y));
1073 if (pDev->orgDev.x!=pOrg->x || pDev->orgDev.y!=pOrg->y)
1074 {
1075 pDev->orgDev = *pOrg;
1076
1077 /* Inform host about display change */
1078 VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y,
1079 0, abs(pDev->mode.lScanlineStride),
1080 pDev->mode.ulWidth, pDev->mode.ulHeight,
1081 (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE);
1082 }
1083 }
1084 else
1085 {
1086 WARN(("DN_DEVICE_ORIGIN pvData==NULL"));
1087 }
1088
1089 break;
1090 }
1091 case DN_DRAWING_BEGIN:
1092 {
1093 /*first drawing op is about to happen for this device*/
1094 LOG(("DN_DRAWING_BEGIN (pso=%p, pDev[%d]=%p)", pso, pDev->iDevice, pDev));
1095 break;
1096 }
1097 default:
1098 {
1099 LOG(("unknown iType=%#x", iType));
1100 }
1101 }
1102
1103 LOGF_LEAVE();
1104 return;
1105}
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