- //
- // VBoxDispDrvEnablePDEV 主要做了两件事
- // @1. 分配内存给PVBOXDISPDEV
- // @2. 填充gdiInfo, devInfo, 并赋值给pdevcaps, pdi
- // @2.1 显示模式
- // @2.2 鼠标支持模式
- // @2.3 画刷
- //
- //
- /* First function which is called after entry point, provides info about device to GDI.
- * Returns pointer to our driver private info structure which would be passed by GDI to our other callbacks.
- */
- DHPDEV APIENTRY
- VBoxDispDrvEnablePDEV(DEVMODEW *pdm, LPWSTR pwszLogAddress, ULONG cPat, HSURF *phsurfPatterns,
- ULONG cjCaps, ULONG *pdevcaps,
- ULONG cjDevInfo, DEVINFO *pdi,
- HDEV hdev, PWSTR pwszDeviceName, HANDLE hDriver)
- {
- PVBOXDISPDEV pDev = NULL;
- GDIINFO gdiInfo;
- DEVINFO devInfo;
- int rc;
-
- /* Next 3 are only used for printer drivers */
- NOREF(pwszLogAddress);
- NOREF(cPat);
- NOREF(phsurfPatterns);
- NOREF(pwszDeviceName);
-
- LOGF_ENTER();
-
- //@1
- pDev = (PVBOXDISPDEV) EngAllocMem(FL_ZERO_MEMORY, sizeof(VBOXDISPDEV), MEM_ALLOC_TAG);
- if (!pDev)
- {
- WARN(("EngAllocMem failed!\n"));
- return NULL;
- }
- pDev->hDriver = hDriver;
-
- //@2
- //通过miniport从注册表获取配置
- ULONG ulRegistryFlags = 0;
- rc = VBoxDispMPQueryRegistryFlags(hDriver, &ulRegistryFlags);
- if (RT_SUCCESS(rc))
- {
- pDev->bBitmapCacheDisabled = (ulRegistryFlags & VBOXVIDEO_REGISTRY_FLAGS_DISABLE_BITMAP_CACHE) != 0;
- LOG(("Bitmap cache %s", pDev->bBitmapCacheDisabled? "disabled": "enabled"));
- }
-
- //@2.1
- /* Initialize device structure and query miniport to fill device and gdi infos */
- rc = VBoxDispInitDevice(pDev, pdm, &gdiInfo, &devInfo);
- if (RT_FAILURE(rc))
- {
- VBOX_WARNRC(rc);
- EngFreeMem(pDev);
- return NULL;
- }
-
- //@2.2
- /* Initialize mouse pointer caps */
- rc = VBoxDispInitPointerCaps(pDev, &devInfo);
- if (RT_FAILURE(rc))
- {
- VBOX_WARNRC(rc);
- }
-
- //@2.3
- /* Initialize palette */
- rc = VBoxDispInitPalette(pDev, &devInfo);
- if (RT_FAILURE(rc))
- {
- VBOX_WARNRC(rc);
- EngFreeMem(pDev);
- return NULL;
- }
-
- if(g_EngineVersionDDI >= DDI_DRIVER_VERSION_NT5)
- {
- devInfo.flGraphicsCaps2 |= GCAPS2_RESERVED1;
- }
-
- /* Copy gathered info to supplied buffers */
- memcpy(pdevcaps, &gdiInfo, min(sizeof(GDIINFO), cjCaps));
- memcpy(pdi, &devInfo, min(sizeof(DEVINFO), cjDevInfo));
-
- LOGF_LEAVE();
- return (DHPDEV)pDev;
- }
-
-
- // @2.1 显示模式
- //
- // VBoxDispInitDevice
- // 1. 从miniport获取支持的显示模式,对比用户设置的显示模式
- // 2. /* Fill GDIINFO structure */
- // 3. /* Fill DEVINFO structure */
- //
- static int VBoxDispInitDevice(PVBOXDISPDEV pDev, DEVMODEW *pdm, GDIINFO *pGdiInfo, DEVINFO *pDevInfo)
- {
- VIDEO_MODE_INFORMATION *pModesTable, selectedMode;
- ULONG cModes, i=0;
- int rc;
-
- LOGF_ENTER();
-
- //@1
- /* Get a list of supported modes by both miniport and display driver */
- rc = VBoxDispMPGetVideoModes(pDev->hDriver, &pModesTable, &cModes);
- VBOX_WARNRC_RETRC(rc);
-
- /* Check if requested mode is available in the list */
- if ((g_EngineVersionDDI < DDI_DRIVER_VERSION_NT5)
- && (pdm->dmBitsPerPel==0)
- && (pdm->dmPelsWidth==0)
- && (pdm->dmPelsHeight==0)
- && (pdm->dmDisplayFrequency==0))
- {
- /* Special case for NT4, just return default(first) mode */
- memcpy(&selectedMode, &pModesTable[0], sizeof(VIDEO_MODE_INFORMATION));
- }
- else
- {
- for (; i<cModes; ++i)
- {
- if ((pdm->dmBitsPerPel == (pModesTable[i].BitsPerPlane * pModesTable[i].NumberOfPlanes))
- && (pdm->dmPelsWidth == pModesTable[i].VisScreenWidth)
- && (pdm->dmPelsHeight == pModesTable[i].VisScreenHeight)
- && (pdm->dmDisplayFrequency == pModesTable[i].Frequency))
- {
- memcpy(&selectedMode, &pModesTable[i], sizeof(VIDEO_MODE_INFORMATION));
- break;
- }
- }
- }
- EngFreeMem(pModesTable);
-
- if (i>=cModes)
- {
- WARN(("can't support requested mode %dx%d@%dbpp(%dHz)!",
- pdm->dmPelsWidth, pdm->dmPelsHeight, pdm->dmBitsPerPel, pdm->dmDisplayFrequency));
- return VERR_NOT_SUPPORTED;
- }
-
- LOG(("match for requested mode %dx%d@%dbpp(%dHz)",
- selectedMode.VisScreenWidth, selectedMode.VisScreenHeight, selectedMode.BitsPerPlane, selectedMode.Frequency));
-
- /* Update private device info with mode information */
- pDev->mode.ulIndex = selectedMode.ModeIndex;
- pDev->mode.ulWidth = selectedMode.VisScreenWidth;
- pDev->mode.ulHeight = selectedMode.VisScreenHeight;
- pDev->mode.ulBitsPerPel = selectedMode.BitsPerPlane * selectedMode.NumberOfPlanes;
- pDev->mode.lScanlineStride = selectedMode.ScreenStride;
- pDev->mode.flMaskR = selectedMode.RedMask;
- pDev->mode.flMaskG = selectedMode.GreenMask;
- pDev->mode.flMaskB = selectedMode.BlueMask;
- pDev->mode.ulPaletteShift = (pDev->mode.ulBitsPerPel==8) ? (8-selectedMode.NumberRedBits) : 0;
-
- //@2
- /* Fill GDIINFO structure */
- memset(pGdiInfo, 0, sizeof(GDIINFO));
-
- pGdiInfo->ulVersion = (g_EngineVersionDDI<DDI_DRIVER_VERSION_NT5) ? GDI_DRIVER_VERSION:0x5000;
- pGdiInfo->ulVersion |= VBOXDISPDRIVERVERSION;
-
- pGdiInfo->ulTechnology = DT_RASDISPLAY;
-
- pGdiInfo->ulHorzSize = selectedMode.XMillimeter;
- pGdiInfo->ulVertSize = selectedMode.YMillimeter;
-
- pGdiInfo->ulHorzRes = pDev->mode.ulWidth;
- pGdiInfo->ulVertRes = pDev->mode.ulHeight;
-
- pGdiInfo->cBitsPixel = pDev->mode.ulBitsPerPel;
- pGdiInfo->cPlanes = selectedMode.NumberOfPlanes;
-
- pGdiInfo->ulNumColors = (pDev->mode.ulBitsPerPel==8) ? 20 : ((ULONG)(-1));
-
- pGdiInfo->ulLogPixelsX = pdm->dmLogPixels;
- pGdiInfo->ulLogPixelsY = pdm->dmLogPixels;
- if (pdm->dmLogPixels!=96)
- {
- WARN(("requested logical pixel res %d isn't 96", pdm->dmLogPixels));
- }
-
- pGdiInfo->flTextCaps = TC_RA_ABLE;
-
- pGdiInfo->ulDACRed = selectedMode.NumberRedBits;
- pGdiInfo->ulDACGreen = selectedMode.NumberGreenBits;
- pGdiInfo->ulDACBlue = selectedMode.NumberBlueBits;
-
- pGdiInfo->ulAspectX = 0x24;
- pGdiInfo->ulAspectY = 0x24;
- /* note: ulAspectXY should be square root of sum of squares of x and y aspects */
- pGdiInfo->ulAspectXY = 0x33;
-
- /* search for "styled cosmetic lines" on msdn for more info */
- pGdiInfo->xStyleStep = 1;
- pGdiInfo->yStyleStep = 1;
- pGdiInfo->denStyleStep = 3;
-
- pGdiInfo->ulNumPalReg = (pDev->mode.ulBitsPerPel==8) ? (1<<pDev->mode.ulBitsPerPel) : 0;
-
- /* @todo: might want to implement IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES in miniport driver
- * and query host for this info there
- */
- VBOXDISPSETCIEC(pGdiInfo->ciDevice.Red, 6700, 3300, 0);
- VBOXDISPSETCIEC(pGdiInfo->ciDevice.Green, 2100, 7100, 0);
- VBOXDISPSETCIEC(pGdiInfo->ciDevice.Blue, 1400, 800, 0);
- VBOXDISPSETCIEC(pGdiInfo->ciDevice.AlignmentWhite, 3127, 3290, 0);
- VBOXDISPSETCIEC(pGdiInfo->ciDevice.Cyan, 0, 0, 0);
- VBOXDISPSETCIEC(pGdiInfo->ciDevice.Magenta, 0, 0, 0);
- VBOXDISPSETCIEC(pGdiInfo->ciDevice.Yellow, 0, 0, 0);
- pGdiInfo->ciDevice.RedGamma = 20000;
- pGdiInfo->ciDevice.GreenGamma = 20000;
- pGdiInfo->ciDevice.BlueGamma = 20000;
-
- pGdiInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA;
-
- pGdiInfo->ulHTPatternSize = HT_PATSIZE_4x4_M;
- switch (pDev->mode.ulBitsPerPel)
- {
- case 8:
- {
- pGdiInfo->ulHTOutputFormat = HT_FORMAT_8BPP;
- break;
- }
- case 16:
- {
- pGdiInfo->ulHTOutputFormat = HT_FORMAT_16BPP;
- break;
- }
- case 24:
- {
- pGdiInfo->ulHTOutputFormat = HT_FORMAT_24BPP;
- break;
- }
- case 32:
- {
- pGdiInfo->ulHTOutputFormat = HT_FORMAT_32BPP;
- break;
- }
- }
- pGdiInfo->flHTFlags = HT_FLAG_ADDITIVE_PRIMS;
-
- pGdiInfo->ulVRefresh = selectedMode.Frequency;
-
- /* 0 means BitBlt's are accelerated by driver */
- pGdiInfo->ulBltAlignment = 0;
-
- pGdiInfo->ulPhysicalPixelCharacteristics = PPC_UNDEFINED;
- pGdiInfo->ulPhysicalPixelGamma = PPG_DEFAULT;
-
- //@3
- /* Fill DEVINFO structure */
- memset(pDevInfo, 0, sizeof(DEVINFO));
-
- pDevInfo->flGraphicsCaps = GCAPS_OPAQUERECT;
- #ifdef VBOX_WITH_DDRAW
- pDevInfo->flGraphicsCaps |= GCAPS_DIRECTDRAW;
- #endif
- VBOXDISPMAKELOGFONTW(pDevInfo->lfDefaultFont,
- 16, 7, FW_BOLD, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH, L"System");
-
- VBOXDISPMAKELOGFONTW(pDevInfo->lfAnsiVarFont,
- 12, 9, FW_NORMAL, CLIP_STROKE_PRECIS, PROOF_QUALITY, VARIABLE_PITCH, L"MS Sans Serif");
-
- VBOXDISPMAKELOGFONTW(pDevInfo->lfAnsiFixFont,
- 12, 9, FW_NORMAL, CLIP_STROKE_PRECIS, PROOF_QUALITY, FIXED_PITCH, L"Courier");
- pDevInfo->cFonts = 0;
- pDevInfo->cxDither = 8;
- pDevInfo->cyDither = 8;
- pDevInfo->hpalDefault = 0;
- pDevInfo->flGraphicsCaps2 = 0;
-
- switch (pDev->mode.ulBitsPerPel)
- {
- case 8:
- {
- pDevInfo->flGraphicsCaps |= GCAPS_PALMANAGED|GCAPS_COLOR_DITHER;
- pDevInfo->iDitherFormat = BMF_8BPP;
- break;
- }
- case 16:
- {
- pDevInfo->iDitherFormat = BMF_16BPP;
- break;
- }
- case 24:
- {
- pDevInfo->iDitherFormat = BMF_24BPP;
- break;
- }
- case 32:
- {
- pDevInfo->iDitherFormat = BMF_32BPP;
- break;
- }
- }
-
- LOGF_LEAVE();
- return rc;
- }
-
- //
- //Disp.dll 与 miniport通过 EngDeviceIoControl通信
- // 1. 查询有几种模式
- // 2. 获取所有的模式
- // 3. 筛选支持的模式
- // 4. copy
- //
- /* Returns list video modes supported by both miniport and display driver.
- * Note: caller is resposible to free up ppModesTable.
- */
- int VBoxDispMPGetVideoModes(HANDLE hDriver, PVIDEO_MODE_INFORMATION *ppModesTable, ULONG *pcModes)
- {
- DWORD dwrc;
- VIDEO_NUM_MODES numModes;
- ULONG cbReturned, i, j, cSupportedModes;
- PVIDEO_MODE_INFORMATION pMiniportModes, pMode;
-
- LOGF_ENTER();
-
- //@1
- /* Get number of video modes supported by miniport */
- dwrc = EngDeviceIoControl(hDriver, IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES, NULL, 0,
- &numModes, sizeof(VIDEO_NUM_MODES), &cbReturned);
- VBOX_CHECK_WINERR_RETRC(dwrc, VERR_DEV_IO_ERROR);
-
- if (numModes.ModeInformationLength != sizeof(VIDEO_MODE_INFORMATION))
- {
- WARN(("sizeof(VIDEO_MODE_INFORMATION) differs for miniport and display drivers. "
- "Check that both are compiled with same ddk version!"));
- }
-
- /* Allocate temp buffer */
- pMiniportModes = (PVIDEO_MODE_INFORMATION)
- EngAllocMem(0, numModes.NumModes*numModes.ModeInformationLength, MEM_ALLOC_TAG);
-
- if (!pMiniportModes)
- {
- WARN(("not enough memory!"));
- return VERR_NO_MEMORY;
- }
-
- //@2
- /* Get video modes supported by miniport */
- dwrc = EngDeviceIoControl(hDriver, IOCTL_VIDEO_QUERY_AVAIL_MODES, NULL, 0,
- pMiniportModes, numModes.NumModes*numModes.ModeInformationLength, &cbReturned);
- if (dwrc != NO_ERROR)
- {
- EngFreeMem(pMiniportModes);
- VBOX_CHECK_WINERR_RETRC(dwrc, VERR_DEV_IO_ERROR);
- }
-
- //@3
- /* Check which of miniport modes are supprted by display driver.
- * Note: size of VIDEO_MODE_INFORMATION is returned by miniport driver in numModes.ModeInformationLength,
- * it might be different from the one we have here.
- */
- cSupportedModes = 0;
- pMode = pMiniportModes;
- for (i=0; i<numModes.NumModes; ++i)
- {
- /*sanity check*/
- if (pMode->Length != sizeof(VIDEO_MODE_INFORMATION))
- {
- WARN(("Unexpected mode len %i expected %i!", pMode->Length, sizeof(VIDEO_MODE_INFORMATION)));
- }
-
- #if 0
- /* Returns if given video mode is supported by display driver */
- static BOOL VBoxDispVideoModeSupported(const PVIDEO_MODE_INFORMATION pMode)
- {
- if ((pMode->NumberOfPlanes==1)
- && (pMode->AttributeFlags & VIDEO_MODE_GRAPHICS)
- && !(pMode->AttributeFlags & VIDEO_MODE_BANKED)
- && (pMode->BitsPerPlane==8 || pMode->BitsPerPlane==16 || pMode->BitsPerPlane==24 || pMode->BitsPerPlane==32))
- {
- return TRUE;
- }
- return FALSE;
- }
- #endif
- if (VBoxDispVideoModeSupported(pMode))
- {
- cSupportedModes++;
- }
- else
- {
- pMode->Length = 0;
- }
-
- pMode = (PVIDEO_MODE_INFORMATION) (((PUCHAR)pMode)+numModes.ModeInformationLength);
- }
- *pcModes = cSupportedModes;
-
- if (0==cSupportedModes)
- {
- WARN(("0 video modes supported!"));
- EngFreeMem(pMiniportModes);
- return VERR_NOT_SUPPORTED;
- }
-
- /* Allocate and zero output buffer */
- *ppModesTable = (PVIDEO_MODE_INFORMATION)
- EngAllocMem(FL_ZERO_MEMORY, cSupportedModes*sizeof(VIDEO_MODE_INFORMATION), MEM_ALLOC_TAG);
-
- if (!*ppModesTable)
- {
- WARN(("not enough memory!"));
- EngFreeMem(pMiniportModes);
- return VERR_NO_MEMORY;
- }
-
- //@4
- /* Copy supported modes to output buffer */
- pMode = pMiniportModes;
- for (j=0, i=0; i<numModes.NumModes; ++i)
- {
- if (pMode->Length != 0)
- {
- memcpy(&(*ppModesTable)[j], pMode, numModes.ModeInformationLength);
- ++j;
- }
-
- pMode = (PVIDEO_MODE_INFORMATION) (((PUCHAR)pMode)+numModes.ModeInformationLength);
- }
- Assert(j==cSupportedModes);
-
- /* Free temp buffer */
- EngFreeMem(pMiniportModes);
-
- LOGF_LEAVE();
- return VINF_SUCCESS;
- }
-
-
-
- /* Process Video Request Packet. */
- static BOOLEAN
- VBoxDrvStartIO(PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket)
- {
-
- /* Returns count of supported video modes and structure size in bytes,
- * used to allocate buffer for the following IOCTL_VIDEO_QUERY_AVAIL_MODES call.
- */
- case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
- {
- STARTIO_OUT(VIDEO_NUM_MODES, pNumModes);
-
- //硬编码生成显示模式列表,并保存在pExt
- bResult = VBoxMPQueryNumAvailModes(pExt, pNumModes, pStatus);
- break;
- }
-
- /* Returns information about supported video modes. */
- case IOCTL_VIDEO_QUERY_AVAIL_MODES:
- {
- PVIDEO_MODE_INFORMATION pModes = (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer;
-
- if (RequestPacket->OutputBufferLength < VBoxMPXpdmGetVideoModesCount(pExt)*sizeof(VIDEO_MODE_INFORMATION))
- {
- pStatus->Status = ERROR_INSUFFICIENT_BUFFER;
- break;
- }
-
- //复制IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES保存在pExt的显示模式
- bResult = VBoxMPQueryAvailModes(pExt, pModes, pStatus);
- break;
- }
- }
-
-
- // @2.2 鼠标支持模式
- // miniport所提供的画刷的能力caps
- //
- /* Called for IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES.
- * Query supported hardware pointer feaures.
- * Note: we always return all caps we could ever support,
- * related functions will return errors if host doesn't accept pointer integration
- * and force display driver to enter software fallback codepath.
- */
- BOOLEAN VBoxMPQueryPointerCapabilities(PVBOXMP_DEVEXT pExt, PVIDEO_POINTER_CAPABILITIES pCaps, PSTATUS_BLOCK pStatus)
- {
- LOGF_ENTER();
-
- pStatus->Information = sizeof(VIDEO_POINTER_CAPABILITIES);
-
- pCaps->Flags = VIDEO_MODE_ASYNC_POINTER | VIDEO_MODE_COLOR_POINTER | VIDEO_MODE_MONO_POINTER;
- /* Up to 64x64 shapes */
- pCaps->MaxWidth = 64;
- pCaps->MaxHeight = 64;
- /* Not used by our display driver */
- pCaps->HWPtrBitmapStart = -1;
- pCaps->HWPtrBitmapEnd = -1;
-
- LOGF_LEAVE();
- return TRUE;
- }
-
-
- // @2.3 画刷
- /* Creates default device palette */
- int VBoxDispInitPalette(PVBOXDISPDEV pDev, DEVINFO *pDevInfo)
- {
- if (pDev->mode.ulBitsPerPel!=8)
- {
- pDev->hDefaultPalette = EngCreatePalette(PAL_BITFIELDS, 0, NULL,
- pDev->mode.flMaskR, pDev->mode.flMaskG, pDev->mode.flMaskB);
-
- if (!pDev->hDefaultPalette)
- {
- WARN(("EngCreatePalette failed"));
- return VERR_GENERAL_FAILURE;
- }
-
- pDevInfo->hpalDefault = pDev->hDefaultPalette;
- return VINF_SUCCESS;
- }
-
- /* Create driver managed palette.
- * First entry should be black (0,0,0), last should be while (255, 255, 255).
- * Note: Other entries should be set in similar way, so that entries with complementing indicies
- * have quite contrast colors stored.
- */
-
- pDev->pPalette = (PPALETTEENTRY) EngAllocMem(0, sizeof(PALETTEENTRY) * 256, MEM_ALLOC_TAG);
- if (!pDev->pPalette)
- {
- WARN(("not enough memory!"));
- return VERR_NO_MEMORY;
- }
-
- BYTE r=0, g=0, b=0;
- for (ULONG i=0; i<256; ++i)
- {
- pDev->pPalette[i].peRed = r;
- pDev->pPalette[i].peGreen = g;
- pDev->pPalette[i].peBlue = b;
- pDev->pPalette[i].peFlags = 0;
-
- r += 32;
- if (!r)
- {
- g += 32;
- if (!g)
- {
- b += 64;
- }
- }
- }
-
- /* Now overwrite window decoration colors by common ones */
- for (ULONG i=0; i<RT_ELEMENTS(defPal); ++i)
- {
- pDev->pPalette[i] = defPal[i];
- pDev->pPalette[(~i)&0xFF] = defPalComp[i];
- }
-
- /* Sanity check in case we'd change palette filling */
- Assert(pDev->pPalette[0].peRed==0 && pDev->pPalette[0].peGreen==0 && pDev->pPalette[0].peBlue==0);
- Assert(pDev->pPalette[255].peRed==255 && pDev->pPalette[255].peGreen==255 && pDev->pPalette[255].peBlue==255);
-
- pDev->hDefaultPalette = EngCreatePalette(PAL_INDEXED, 256, (PULONG)pDev->pPalette, 0, 0, 0);
- if (!pDev->hDefaultPalette)
- {
- WARN(("EngCreatePalette failed"));
- EngFreeMem(pDev->pPalette);
- pDev->pPalette = NULL;
- return VERR_GENERAL_FAILURE;
- }
-
- pDevInfo->hpalDefault = pDev->hDefaultPalette;
- return VINF_SUCCESS;
- }
相关热门文章
给主人留下些什么吧!~~
评论热议