VirtualBox

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

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

fAnyX impl part2 (xpdm, not testet yet)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.0 KB
Line 
1/* $Id: VBoxDispDriver.cpp 42233 2012-07-19 16:25:49Z vboxsync $ */
2
3/** @file
4 * VBox XPDM Display driver interface functions
5 */
6
7/*
8 * Copyright (C) 2011 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 /* Initialize device structure and query miniport to fill device and gdi infos */
522 rc = VBoxDispInitDevice(pDev, pdm, &gdiInfo, &devInfo);
523 if (RT_FAILURE(rc))
524 {
525 VBOX_WARNRC(rc);
526 EngFreeMem(pDev);
527 return NULL;
528 }
529
530 /* Initialize mouse pointer caps */
531 rc = VBoxDispInitPointerCaps(pDev, &devInfo);
532 if (RT_FAILURE(rc))
533 {
534 VBOX_WARNRC(rc);
535 }
536
537 /* Initialize palette */
538 rc = VBoxDispInitPalette(pDev, &devInfo);
539 if (RT_FAILURE(rc))
540 {
541 VBOX_WARNRC(rc);
542 EngFreeMem(pDev);
543 return NULL;
544 }
545
546 if(g_EngineVersionDDI >= DDI_DRIVER_VERSION_NT5)
547 {
548 devInfo.flGraphicsCaps2 |= GCAPS2_RESERVED1;
549 }
550
551 /* Copy gathered info to supplied buffers */
552 memcpy(pdevcaps, &gdiInfo, min(sizeof(GDIINFO), cjCaps));
553 memcpy(pdi, &devInfo, min(sizeof(DEVINFO), cjDevInfo));
554
555 LOGF_LEAVE();
556 return (DHPDEV)pDev;
557}
558
559/* Called to provide us GDI handle for our device, which we should use later for GDI calls */
560VOID APIENTRY VBoxDispDrvCompletePDEV(DHPDEV dhpdev, HDEV hdev)
561{
562 LOGF_ENTER();
563
564 ((PVBOXDISPDEV)dhpdev)->hDevGDI = hdev;
565
566 LOGF_LEAVE();
567}
568
569/* Called to free resources allocated for device in VBoxDispDrvEnablePDEV */
570VOID APIENTRY VBoxDispDrvDisablePDEV(DHPDEV dhpdev)
571{
572 LOGF_ENTER();
573
574 VBoxDispDestroyPalette((PVBOXDISPDEV) dhpdev);
575
576 EngFreeMem(dhpdev);
577
578 LOGF_LEAVE();
579}
580
581/* Called to create and associate surface with device */
582HSURF APIENTRY VBoxDispDrvEnableSurface(DHPDEV dhpdev)
583{
584 int rc;
585 PVBOXDISPDEV pDev = (PVBOXDISPDEV)dhpdev;
586
587 LOGF_ENTER();
588
589 /* Switch device to mode requested in VBoxDispDrvEnablePDEV */
590 rc = VBoxDispMPSetCurrentMode(pDev->hDriver, pDev->mode.ulIndex);
591 VBOX_WARNRC_RETV(rc, NULL);
592
593 /* Map fb and vram */
594 rc = VBoxDispMPMapMemory(pDev, &pDev->memInfo);
595 VBOX_WARNRC_RETV(rc, NULL);
596
597 /* Clear mapped memory, to avoid garbage while video mode is switching */
598 /* @todo: VIDEO_MODE_NO_ZERO_MEMORY does nothing in miniport's IOCTL_VIDEO_SET_CURRENT_MODE*/
599 memset(pDev->memInfo.FrameBufferBase, 0, pDev->mode.ulHeight * abs(pDev->mode.lScanlineStride));
600
601 /* Allocate memory for pointer attrs */
602 rc = VBoxDispInitPointerAttrs(pDev);
603 VBOX_WARNRC_RETV(rc, NULL);
604
605 /* Init VBVA */
606 rc = VBoxDispVBVAInit(pDev);
607 VBOX_WARNRC_RETV(rc, NULL);
608
609 /* Enable VBVA */
610 if (pDev->hgsmi.bSupported)
611 {
612 if (pDev->mode.ulBitsPerPel==16 || pDev->mode.ulBitsPerPel==24 || pDev->mode.ulBitsPerPel==32)
613 {
614 VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)pDev->memInfo.VideoRamBase+pDev->layout.offVBVABuffer);
615 pDev->hgsmi.bSupported = VBoxVBVAEnable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, pVBVA, -1);
616 LogRel(("VBoxDisp[%d]: VBVA %senabled\n", pDev->iDevice, pDev->hgsmi.bSupported? "":"not "));
617 }
618 }
619
620 /* Inform host */
621 if (pDev->hgsmi.bSupported)
622 {
623 VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y,
624 0, abs(pDev->mode.lScanlineStride), pDev->mode.ulWidth, pDev->mode.ulHeight,
625 (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE);
626 }
627
628#ifdef VBOX_WITH_VIDEOHWACCEL
629 VBoxDispVHWAEnable(pDev);
630#endif
631
632 /* Set device palette if needed */
633 if (pDev->mode.ulBitsPerPel == 8)
634 {
635 rc = VBoxDispSetPalette8BPP(pDev);
636 VBOX_WARNRC_RETV(rc, NULL);
637 }
638
639 pDev->orgDisp.x = 0;
640 pDev->orgDisp.y = 0;
641
642 /* Create GDI managed bitmap, which resides in our framebuffer memory */
643 ULONG iFormat;
644 SIZEL size;
645
646 switch (pDev->mode.ulBitsPerPel)
647 {
648 case 8:
649 {
650 iFormat = BMF_8BPP;
651 break;
652 }
653 case 16:
654 {
655 iFormat = BMF_16BPP;
656 break;
657 }
658 case 24:
659 {
660 iFormat = BMF_24BPP;
661 break;
662 }
663 case 32:
664 {
665 iFormat = BMF_32BPP;
666 break;
667 }
668 }
669
670 size.cx = pDev->mode.ulWidth;
671 size.cy = pDev->mode.ulHeight;
672
673 pDev->surface.hBitmap = EngCreateBitmap(size, pDev->mode.lScanlineStride, iFormat,
674 pDev->mode.lScanlineStride>0 ? BMF_TOPDOWN:0,
675 pDev->memInfo.FrameBufferBase);
676 if (!pDev->surface.hBitmap)
677 {
678 WARN(("EngCreateBitmap failed!"));
679 return NULL;
680 }
681 pDev->surface.psoBitmap = EngLockSurface((HSURF)pDev->surface.hBitmap);
682
683 /* Create device-managed surface */
684 pDev->surface.hSurface = EngCreateDeviceSurface((DHSURF)pDev, size, iFormat);
685 if (!pDev->surface.hSurface)
686 {
687 WARN(("EngCreateDeviceSurface failed!"));
688 VBoxDispDrvDisableSurface(dhpdev);
689 return NULL;
690 }
691
692 FLONG flHooks = HOOK_BITBLT|HOOK_TEXTOUT|HOOK_FILLPATH|HOOK_COPYBITS|HOOK_STROKEPATH|HOOK_LINETO|
693 HOOK_PAINT|HOOK_STRETCHBLT;
694
695 /* Associate created surface with our device */
696 if (!EngAssociateSurface(pDev->surface.hSurface, pDev->hDevGDI, flHooks))
697 {
698 WARN(("EngAssociateSurface failed!"));
699 VBoxDispDrvDisableSurface(dhpdev);
700 return NULL;
701 }
702
703 pDev->surface.ulFormat = iFormat;
704 pDev->flDrawingHooks = flHooks;
705
706 LOG(("Created surface %p for physical device %p", pDev->surface.hSurface, pDev));
707
708 LOGF_LEAVE();
709 return pDev->surface.hSurface;
710}
711
712VOID APIENTRY VBoxDispDrvDisableSurface(DHPDEV dhpdev)
713{
714 PVBOXDISPDEV pDev = (PVBOXDISPDEV)dhpdev;
715 LOGF_ENTER();
716
717 if (pDev->surface.hSurface)
718 {
719 EngDeleteSurface(pDev->surface.hSurface);
720 pDev->surface.hSurface = NULL;
721 }
722
723 if (pDev->surface.psoBitmap)
724 {
725 Assert(pDev->surface.hBitmap);
726 EngUnlockSurface(pDev->surface.psoBitmap);
727 pDev->surface.psoBitmap = NULL;
728 }
729
730 if (pDev->surface.hBitmap)
731 {
732 EngDeleteSurface((HSURF) pDev->surface.hBitmap);
733 pDev->surface.hBitmap = NULL;
734 }
735
736 int rc;
737 rc = VBoxDispMPUnmapMemory(pDev);
738 VBOX_WARNRC(rc);
739
740 LOGF_LEAVE();
741}
742
743BOOL APIENTRY
744VBoxDispDrvRealizeBrush(BRUSHOBJ *pbo, SURFOBJ *psoTarget, SURFOBJ *psoPattern, SURFOBJ *psoMask,
745 XLATEOBJ *pxlo, ULONG iHatch)
746{
747 BOOL bRc = FALSE;
748 LOGF_ENTER();
749
750 if (VBoxDispIsScreenSurface(psoTarget))
751 {
752 PVBOXDISPDEV pDev = (PVBOXDISPDEV)psoTarget->dhpdev;
753
754 if (pDev->vbvaCtx.pVBVA && (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
755 {
756 if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET)
757 {
758 vrdpReset(pDev);
759 pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents &= ~VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;
760 }
761
762 if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_VRDP)
763 {
764 bRc = vrdpDrvRealizeBrush(pbo, psoTarget, psoPattern, psoMask, pxlo, iHatch);
765 }
766 }
767 }
768
769 LOGF_LEAVE();
770 return bRc;
771}
772
773ULONG APIENTRY VBoxDispDrvDitherColor(DHPDEV dhpdev, ULONG iMode, ULONG rgb, ULONG *pul)
774{
775 ULONG rc;
776 LOGF_ENTER();
777
778 /* There is no EngDitherColor on NT4, so take the easy path and tell the graphics
779 * engine to create a halftone approximation.
780 */
781 rc = DCR_HALFTONE;
782
783 LOGF_LEAVE();
784 return rc;
785}
786
787/* Called to reset device to default mode or to mode specified with dhpdev */
788BOOL APIENTRY VBoxDispDrvAssertMode(DHPDEV dhpdev, BOOL bEnable)
789{
790 PVBOXDISPDEV pDev = (PVBOXDISPDEV) dhpdev;
791 int rc;
792 LOGF_ENTER();
793
794 if (!bEnable)
795 {
796 LOGF(("!bEnable"));
797#ifdef VBOX_WITH_VIDEOHWACCEL
798 /* tells we can not process host commands any more and ensures that
799 * we've completed processing of the host VHWA commands
800 */
801 VBoxDispVHWADisable(pDev);
802#endif
803
804 /* disable VBVA */
805 if (pDev->hgsmi.bSupported)
806 {
807 VBoxVBVADisable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, -1);
808 }
809
810 /* reset the device to default mode */
811 rc = VBoxDispMPResetDevice(pDev->hDriver);
812 VBOX_WARNRC_RETV(rc, FALSE);
813 }
814 else
815 {
816 LOGF(("bEnable"));
817
818 /* switch device to previous pDev mode */
819 rc = VBoxDispMPSetCurrentMode(pDev->hDriver, pDev->mode.ulIndex);
820 VBOX_WARNRC_RETV(rc, NULL);
821
822 /* enable VBVA */
823 if (pDev->hgsmi.bSupported)
824 {
825 if (pDev->mode.ulBitsPerPel==16 || pDev->mode.ulBitsPerPel==24 || pDev->mode.ulBitsPerPel==32)
826 {
827 VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)pDev->memInfo.VideoRamBase+pDev->layout.offVBVABuffer);
828 pDev->hgsmi.bSupported = VBoxVBVAEnable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, pVBVA, -1);
829 LogRel(("VBoxDisp[%d]: VBVA %senabled\n", pDev->iDevice, pDev->hgsmi.bSupported? "":"not "));
830 }
831 }
832
833 /* inform host */
834 if (pDev->hgsmi.bSupported)
835 {
836 VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y,
837 0, abs(pDev->mode.lScanlineStride), pDev->mode.ulWidth, pDev->mode.ulHeight,
838 (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE);
839 }
840
841#ifdef VBOX_WITH_VIDEOHWACCEL
842 /* tells we can process host commands */
843 VBoxDispVHWAEnable(pDev);
844#endif
845
846 /* Associate back GDI bitmap residing in our framebuffer memory with GDI's handle to our device */
847 if (!EngAssociateSurface((HSURF)pDev->surface.hBitmap, pDev->hDevGDI, 0))
848 {
849 WARN(("EngAssociateSurface on bitmap failed"));
850 return FALSE;
851 }
852
853 /* Associate device managed surface with GDI's handle to our device */
854 if (!EngAssociateSurface(pDev->surface.hSurface, pDev->hDevGDI, pDev->flDrawingHooks))
855 {
856 WARN(("EngAssociateSurface on surface failed"));
857 return FALSE;
858 }
859 }
860
861 LOGF_LEAVE();
862 return TRUE;
863}
864
865ULONG APIENTRY VBoxDispDrvEscape(SURFOBJ *pso, ULONG iEsc, ULONG cjIn, PVOID pvIn, ULONG cjOut, PVOID pvOut)
866{
867 PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
868 LOGF_ENTER();
869
870 switch (iEsc)
871 {
872#ifdef VBOX_WITH_CROGL
873 case OPENGL_GETINFO:
874 {
875 if (pvOut && cjOut >= sizeof(OPENGL_INFO))
876 {
877 POPENGL_INFO pInfo = (POPENGL_INFO)pvOut;
878
879 pInfo->dwVersion = 2;
880 pInfo->dwDriverVersion = 1;
881 pInfo->szDriverName[0] = 'V';
882 pInfo->szDriverName[1] = 'B';
883 pInfo->szDriverName[2] = 'o';
884 pInfo->szDriverName[3] = 'x';
885 pInfo->szDriverName[4] = 'O';
886 pInfo->szDriverName[5] = 'G';
887 pInfo->szDriverName[6] = 'L';
888 pInfo->szDriverName[7] = 0;
889
890 LOG(("OPENGL_GETINFO ok"));
891 return cjOut;
892 }
893 else
894 {
895 WARN(("OPENGL_GETINFO invalid parms"));
896 return 0;
897 }
898 }
899 case QUERYESCSUPPORT:
900 {
901 if (pvIn && cjIn == sizeof(DWORD))
902 {
903 DWORD nEscapeQuery = *(DWORD *)pvIn;
904
905 if (nEscapeQuery==OPENGL_GETINFO)
906 {
907 LOG(("QUERYESCSUPPORT OPENGL_GETINFO"));
908 return 1;
909 }
910 else
911 {
912 LOG(("QUERYESCSUPPORT unsupported query %d", nEscapeQuery));
913 return 0;
914 }
915 }
916 else
917 {
918 WARN(("QUERYESCSUPPORT invalid parms"));
919 return 0;
920 }
921 }
922#endif
923 case VBOXESC_ISVRDPACTIVE:
924 {
925 if (pDev && pDev->vbvaCtx.pVBVA && pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents&VBVA_F_MODE_VRDP)
926 {
927 LOGF(("VBOXESC_ISVRDPACTIVE: 1"));
928 return 1;
929 }
930 LOGF(("VBOXESC_ISVRDPACTIVE: 0"));
931 return 0;
932 }
933 case VBOXESC_SETVISIBLEREGION:
934 {
935 LOGF(("VBOXESC_SETVISIBLEREGION"));
936 LPRGNDATA lpRgnData = (LPRGNDATA)pvIn;
937 DWORD cRects;
938
939 if ( cjIn >= sizeof(RGNDATAHEADER)
940 && pvIn
941 && lpRgnData->rdh.dwSize == sizeof(RGNDATAHEADER)
942 && lpRgnData->rdh.iType == RDH_RECTANGLES
943 && (cRects = lpRgnData->rdh.nCount) <= _1M
944 && cjIn == cRects * (uint64_t)sizeof(RECT) + sizeof(RGNDATAHEADER))
945 {
946 /** @todo this whole conversion thing could maybe be skipped
947 * since RTRECT matches the RECT layout. */
948#if 0
949 AssertCompile(sizeof(RTRECT) == sizeof(RECT));
950 AssertCompileMembersSameSizeAndOffset(RTRECT, xLeft, RECT, left);
951 AssertCompileMembersSameSizeAndOffset(RTRECT, xBottom, RECT, bottom);
952 AssertCompileMembersSameSizeAndOffset(RTRECT, xRight, RECT, right);
953 AssertCompileMembersSameSizeAndOffset(RTRECT, xTop, RECT, top);
954
955 rc = VBoxDispMPSetVisibleRegion(pDev->hDriver, (PRTRECT)&lpRgnData->Buffer[0], cRects);
956 VBOX_WARNRC(rc);
957#else
958 DWORD i;
959 PRTRECT pRTRect;
960 int rc;
961 RECT *pRect = (RECT *)&lpRgnData->Buffer;
962
963 pRTRect = (PRTRECT) EngAllocMem(0, cRects*sizeof(RTRECT), MEM_ALLOC_TAG);
964 if (!pRTRect)
965 {
966 WARN(("failed to allocate %d bytes", cRects*sizeof(RTRECT)));
967 break;
968 }
969
970 for (i = 0; i < cRects; ++i)
971 {
972 LOG(("New visible rectangle (%d,%d) (%d,%d)",
973 pRect[i].left, pRect[i].bottom, pRect[i].right, pRect[i].top));
974 pRTRect[i].xLeft = pRect[i].left;
975 pRTRect[i].yBottom = pRect[i].bottom;
976 pRTRect[i].xRight = pRect[i].right;
977 pRTRect[i].yTop = pRect[i].top;
978 }
979
980 rc = VBoxDispMPSetVisibleRegion(pDev->hDriver, pRTRect, cRects);
981 VBOX_WARNRC(rc);
982
983 EngFreeMem(pRTRect);
984
985#endif
986 if (RT_SUCCESS(rc))
987 {
988 LOGF_LEAVE();
989 return 1;
990 }
991 }
992 else
993 {
994 if (pvIn)
995 {
996 WARN(("check failed rdh.dwSize=%x iType=%d size=%d expected size=%d",
997 lpRgnData->rdh.dwSize, lpRgnData->rdh.iType, cjIn,
998 lpRgnData->rdh.nCount * sizeof(RECT) + sizeof(RGNDATAHEADER)));
999 }
1000 }
1001 break;
1002 }
1003 case VBOXESC_ISANYX:
1004 {
1005 if (pvOut && cjOut == sizeof(DWORD))
1006 {
1007 DWORD cbReturned;
1008 DWORD dwrc = EngDeviceIoControl(pDev->hDriver, IOCTL_VIDEO_VBOX_ISANYX, NULL, 0,
1009 pvOut, sizeof (uint32_t), &cbReturned);
1010 if (dwrc == NO_ERROR && cbReturned == sizeof (uint32_t))
1011 return 1;
1012 WARN(("EngDeviceIoControl failed, dwrc(%d), cbReturned(%d)", dwrc, cbReturned));
1013 return 0;
1014 }
1015 else
1016 {
1017 WARN(("VBOXESC_ISANYX invalid parms"));
1018 return 0;
1019 }
1020 break;
1021 }
1022 default:
1023 {
1024 LOG(("unsupported iEsc %#x", iEsc));
1025 }
1026 }
1027
1028 LOGF_LEAVE();
1029 return 0;
1030}
1031
1032#define FB_OFFSET(_dev, _x, _y) ((_y)*pDev->mode.lScanlineStride) + ((_x)*((pDev->mode.ulBitsPerPel+1)/8))
1033/* Obsolete, NT4 specific. Called to set display offset in virtual desktop */
1034BOOL APIENTRY VBoxDispDrvOffset(SURFOBJ* pso, LONG x, LONG y, FLONG flReserved)
1035{
1036 PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
1037 LOGF(("%x %x %x\n", x, y, flReserved));
1038
1039 pDev->memInfo.FrameBufferBase = ((BYTE*)pDev->memInfo.VideoRamBase) + pDev->layout.offFramebuffer
1040 - FB_OFFSET(pDev, x, y);
1041
1042 pDev->orgDisp.x = x;
1043 pDev->orgDisp.y = y;
1044
1045 LOGF_LEAVE();
1046 return TRUE;
1047}
1048
1049/* Called to notify driver about various events */
1050VOID APIENTRY VBoxDispDrvNotify(SURFOBJ *pso, ULONG iType, PVOID pvData)
1051{
1052 PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
1053 LOGF_ENTER();
1054
1055 switch (iType)
1056 {
1057 case DN_DEVICE_ORIGIN:
1058 {
1059 /*device origin in dualview*/
1060 POINTL *pOrg = (POINTL *)pvData;
1061 if (pOrg)
1062 {
1063 LOG(("DN_DEVICE_ORIGIN (pso=%p, pDev[%d]=%p) old=%d,%d new=%d,%d",
1064 pso, pDev->iDevice, pDev, pDev->orgDev.x, pDev->orgDev.y, pOrg->x, pOrg->y));
1065 if (pDev->orgDev.x!=pOrg->x || pDev->orgDev.y!=pOrg->y)
1066 {
1067 pDev->orgDev = *pOrg;
1068
1069 /* Inform host about display change */
1070 VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y,
1071 0, abs(pDev->mode.lScanlineStride),
1072 pDev->mode.ulWidth, pDev->mode.ulHeight,
1073 (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE);
1074 }
1075 }
1076 else
1077 {
1078 WARN(("DN_DEVICE_ORIGIN pvData==NULL"));
1079 }
1080
1081 break;
1082 }
1083 case DN_DRAWING_BEGIN:
1084 {
1085 /*first drawing op is about to happen for this device*/
1086 LOG(("DN_DRAWING_BEGIN (pso=%p, pDev[%d]=%p)", pso, pDev->iDevice, pDev));
1087 break;
1088 }
1089 default:
1090 {
1091 LOG(("unknown iType=%#x", iType));
1092 }
1093 }
1094
1095 LOGF_LEAVE();
1096 return;
1097}
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