ULONG APIENTRY DrvGetModes( IN HANDLE hDriver, IN ULONG cjSize, OUT DEVMODEW *pdm) { ULONG ModeCount; ULONG ModeInfoSize; PVIDEO_MODE_INFORMATION ModeInfo, ModeInfoPtr; ULONG OutputSize; ModeCount = GetAvailableModes(hDriver, &ModeInfo, &ModeInfoSize); if (ModeCount == 0) { return 0; } if (pdm == NULL) { EngFreeMem(ModeInfo); return ModeCount * sizeof(DEVMODEW); } /* * Copy the information about supported modes into the output buffer. */ OutputSize = 0; ModeInfoPtr = ModeInfo; while (ModeCount-- > 0) { if (ModeInfoPtr->Length == 0) { ModeInfoPtr = (PVIDEO_MODE_INFORMATION)(((ULONG_PTR)ModeInfoPtr) + ModeInfoSize); continue; } memset(pdm, 0, sizeof(DEVMODEW)); memcpy(pdm->dmDeviceName, DEVICE_NAME, sizeof(DEVICE_NAME)); pdm->dmSpecVersion = pdm->dmDriverVersion = DM_SPECVERSION; pdm->dmSize = sizeof(DEVMODEW); pdm->dmDriverExtra = 0; pdm->dmBitsPerPel = ModeInfoPtr->NumberOfPlanes * ModeInfoPtr->BitsPerPlane; pdm->dmPelsWidth = ModeInfoPtr->VisScreenWidth; pdm->dmPelsHeight = ModeInfoPtr->VisScreenHeight; pdm->dmDisplayFrequency = ModeInfoPtr->Frequency; pdm->dmDisplayFlags = 0; pdm->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS; ModeInfoPtr = (PVIDEO_MODE_INFORMATION)(((ULONG_PTR)ModeInfoPtr) + ModeInfoSize); pdm = (LPDEVMODEW)(((ULONG_PTR)pdm) + sizeof(DEVMODEW)); OutputSize += sizeof(DEVMODEW); } EngFreeMem(ModeInfo); return OutputSize; }
int main(int argc, char* argv[]) { struct filter filter; filter.include_all = false; filter.include_supported = true; filter.include_unsupported = false; filter.include_text = true; filter.include_graphics = true; // TODO: HACK: The kernel log printing requires either text mode or 32-bit // graphics. For now, just filter away anything but 32-bit graphics. filter.minbpp = 32; filter.maxbpp = 32; filter.minxres = 0; filter.maxxres = SIZE_MAX; filter.minyres = 0; filter.maxyres = SIZE_MAX; filter.minxchars = 0; filter.maxxchars = SIZE_MAX; filter.minychars = 0; filter.maxychars = SIZE_MAX; const char* argv0 = argv[0]; for ( int i = 1; i < argc; i++ ) { const char* arg = argv[i]; if ( arg[0] != '-' || !arg[1] ) break; // Intentionally not continue. argv[i] = NULL; if ( !strcmp(arg, "--") ) break; if ( arg[1] != '-' ) { char c; while ( (c = *++arg) ) switch ( c ) { default: fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c); help(stderr, argv0); exit(1); } } else if ( !strcmp(arg, "--help") ) help(stdout, argv0), exit(0); else if ( !strcmp(arg, "--version") ) version(stdout, argv0), exit(0); else if ( BOOL_PARAMETER("show-all", &filter.include_all) ) { } else if ( BOOL_PARAMETER("show-supported", &filter.include_supported) ) { } else if ( BOOL_PARAMETER("show-unsupported", &filter.include_unsupported) ) { } else if ( BOOL_PARAMETER("show-text", &filter.include_text) ) { } else if ( BOOL_PARAMETER("show-graphics", &filter.include_graphics) ) { } else if ( MINMAX_PARAMETER("bpp", &filter.minbpp, &filter.maxbpp) ) { } else if ( MINMAX_PARAMETER("width", &filter.minxres, &filter.maxxres) ) { } else if ( MINMAX_PARAMETER("height", &filter.minyres, &filter.maxyres) ) { } else { fprintf(stderr, "%s: unknown option: %s\n", argv0, arg); help(stderr, argv0); exit(1); } } compact_arguments(&argc, &argv); size_t num_modes = 0; struct dispmsg_crtc_mode* modes = GetAvailableModes(&num_modes); if ( !modes ) error(1, errno, "Unable to detect available video modes"); if ( !num_modes ) { fprintf(stderr, "No video modes are currently available.\n"); fprintf(stderr, "Try make sure a device driver exists and is activated.\n"); exit(11); } filter_modes(modes, &num_modes, &filter); if ( !num_modes ) { fprintf(stderr, "No video mode remains after filtering away unwanted modes.\n"); fprintf(stderr, "Try make sure the desired device driver is loaded and is configured correctly.\n"); exit(12); } int num_modes_display_length = 1; for ( size_t i = num_modes; 10 <= i; i /= 10 ) num_modes_display_length++; int mode_set_error = 0; size_t selection; bool decided; bool first_render; struct wincurpos render_at; retry_pick_mode: selection = 0; decided = false; first_render = true; memset(&render_at, 0, sizeof(render_at)); while ( !decided ) { fflush(stdout); struct winsize ws; if ( tcgetwinsize(1, &ws) != 0 ) { ws.ws_col = 80; ws.ws_row = 25; } struct wincurpos wcp; if ( tcgetwincurpos(1, &wcp) != 0 ) { wcp.wcp_col = 1; wcp.wcp_row = 1; } size_t off = 1; // The "Please select ..." line at the top. if ( mode_set_error ) off++; size_t entries_per_page = ws.ws_row - off; size_t page = selection / entries_per_page; size_t from = page * entries_per_page; size_t how_many_available = num_modes - from; size_t how_many = entries_per_page; if ( how_many_available < how_many ) how_many = how_many_available; size_t lines_on_screen = off + how_many; if ( first_render ) { while ( wcp.wcp_row && ws.ws_row - (wcp.wcp_row + 1) < lines_on_screen ) { printf("\e[S"); printf("\e[%juH", 1 + (uintmax_t) wcp.wcp_row); wcp.wcp_row--; wcp.wcp_col = 1; } render_at = wcp; first_render = false; } printf("\e[m"); printf("\e[%juH", 1 + (uintmax_t) render_at.wcp_row); printf("\e[2K"); if ( mode_set_error ) printf("Error: Could not set desired mode: %s\n", strerror(mode_set_error)); printf("Please select one of these video modes or press ESC to abort.\n"); for ( size_t i = 0; i < how_many; i++ ) { size_t index = from + i; size_t screenline = off + index - from; const char* color = index == selection ? "\e[31m" : "\e[m"; printf("\e[%zuH", 1 + render_at.wcp_row + screenline); printf("%s", color); printf("\e[2K"); printf(" [%-*zu] ", num_modes_display_length, index); if ( modes[i].control & DISPMSG_CONTROL_VALID ) printf("%u x %u x %u", modes[i].fb_format, modes[i].view_xres, modes[i].view_yres); else if ( modes[i].control & DISPMSG_CONTROL_OTHER_RESOLUTIONS ) printf("(enter a custom resolution)"); else printf("(unknown video device feature)"); printf("\e[m"); } printf("\e[J"); fflush(stdout); unsigned int oldtermmode; if ( gettermmode(0, &oldtermmode) < 0 ) error(1, errno, "gettermmode"); if ( settermmode(0, TERMMODE_KBKEY | TERMMODE_UNICODE | TERMMODE_SIGNAL) < 0 ) error(1, errno, "settermmode"); bool redraw = false; while ( !redraw && !decided ) { uint32_t codepoint; ssize_t numbytes = read(0, &codepoint, sizeof(codepoint)); if ( numbytes < 0 ) error(1, errno, "read"); int kbkey = KBKEY_DECODE(codepoint); if ( kbkey ) { switch ( kbkey ) { case KBKEY_ESC: if ( settermmode(0, oldtermmode) < 0 ) error(1, errno, "settermmode"); printf("\n"); exit(10); break; case KBKEY_UP: if ( selection ) selection--; else selection = num_modes -1; redraw = true; break; case KBKEY_DOWN: if ( selection + 1 == num_modes ) selection = 0; else selection++; redraw = true; break; case KBKEY_ENTER: if ( settermmode(0, oldtermmode) < 0 ) error(1, errno, "settermmode"); fgetc(stdin); printf("\n"); decided = true; break; } } else { if ( L'0' <= codepoint && codepoint <= '9' ) { uint32_t requested = codepoint - '0'; if ( requested < num_modes ) { selection = requested; redraw = true; } } } } if ( settermmode(0, oldtermmode) < 0 ) error(1, errno, "settermmode"); } struct dispmsg_crtc_mode mode = modes[selection]; if ( mode.control & DISPMSG_CONTROL_OTHER_RESOLUTIONS ) { uintmax_t req_bpp; uintmax_t req_width; uintmax_t req_height; while ( true ) { printf("Enter video mode [BPP x WIDTH x HEIGHT]: "); fflush(stdout); if ( scanf("%ju x %ju x %ju", &req_bpp, &req_width, &req_height) != 3 ) { fgetc(stdin); fflush(stdin); continue; } fgetc(stdin); break; } mode.fb_format = req_bpp; mode.view_xres = req_width; mode.view_yres = req_height; mode.control &= ~DISPMSG_CONTROL_OTHER_RESOLUTIONS; mode.control |= DISPMSG_CONTROL_VALID; } if ( !SetCurrentMode(mode) ) { error(0, mode_set_error = errno, "Unable to set video mode %ju x %ju x %ju", (uintmax_t) mode.fb_format, (uintmax_t) mode.view_xres, (uintmax_t) mode.view_yres); goto retry_pick_mode; } if ( 1 < argc ) { execvp(argv[1], argv + 1); error(127, errno, "`%s'", argv[1]); } return 0; }
BOOL IntInitScreenInfo( PPDEV ppdev, LPDEVMODEW pDevMode, PGDIINFO pGdiInfo, PDEVINFO pDevInfo) { ULONG ModeCount; ULONG ModeInfoSize; PVIDEO_MODE_INFORMATION ModeInfo, ModeInfoPtr, SelectedMode = NULL; VIDEO_COLOR_CAPABILITIES ColorCapabilities; /* hack LOGFONTW SystemFont = {16, 7, 0, 0, 700, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_DONTCARE, L"System"}; LOGFONTW AnsiVariableFont = {12, 9, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_STROKE_PRECIS, PROOF_QUALITY, VARIABLE_PITCH | FF_DONTCARE, L"MS Sans Serif"}; LOGFONTW AnsiFixedFont = {12, 9, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_STROKE_PRECIS, PROOF_QUALITY, FIXED_PITCH | FF_DONTCARE, L"Courier"}; */ ULONG Temp; /* * Call miniport to get information about video modes. */ ModeCount = GetAvailableModes(ppdev->hDriver, &ModeInfo, &ModeInfoSize); if (ModeCount == 0) { return FALSE; } /* * Select the video mode depending on the info passed in pDevMode. */ if (pDevMode->dmPelsWidth == 0 && pDevMode->dmPelsHeight == 0 && pDevMode->dmBitsPerPel == 0 && pDevMode->dmDisplayFrequency == 0) { ModeInfoPtr = ModeInfo; while (ModeCount-- > 0) { if (ModeInfoPtr->Length == 0) { ModeInfoPtr = (PVIDEO_MODE_INFORMATION) (((PUCHAR)ModeInfoPtr) + ModeInfoSize); continue; } SelectedMode = ModeInfoPtr; break; } } else { ModeInfoPtr = ModeInfo; while (ModeCount-- > 0) { if (ModeInfoPtr->Length > 0 && pDevMode->dmPelsWidth == ModeInfoPtr->VisScreenWidth && pDevMode->dmPelsHeight == ModeInfoPtr->VisScreenHeight && pDevMode->dmBitsPerPel == (ModeInfoPtr->BitsPerPlane * ModeInfoPtr->NumberOfPlanes) && pDevMode->dmDisplayFrequency == ModeInfoPtr->Frequency) { SelectedMode = ModeInfoPtr; break; } ModeInfoPtr = (PVIDEO_MODE_INFORMATION) (((PUCHAR)ModeInfoPtr) + ModeInfoSize); } } if (SelectedMode == NULL) { EngFreeMem(ModeInfo); return FALSE; } /* * Fill in the GDIINFO data structure with the information returned from * the kernel driver. */ ppdev->ModeIndex = SelectedMode->ModeIndex; ppdev->ScreenWidth = SelectedMode->VisScreenWidth; ppdev->ScreenHeight = SelectedMode->VisScreenHeight; ppdev->ScreenDelta = SelectedMode->ScreenStride; ppdev->BitsPerPixel = SelectedMode->BitsPerPlane * SelectedMode->NumberOfPlanes; ppdev->MemWidth = SelectedMode->VideoMemoryBitmapWidth; ppdev->MemHeight = SelectedMode->VideoMemoryBitmapHeight; ppdev->RedMask = SelectedMode->RedMask; ppdev->GreenMask = SelectedMode->GreenMask; ppdev->BlueMask = SelectedMode->BlueMask; pGdiInfo->ulVersion = GDI_DRIVER_VERSION; pGdiInfo->ulTechnology = DT_RASDISPLAY; pGdiInfo->ulHorzSize = SelectedMode->XMillimeter; pGdiInfo->ulVertSize = SelectedMode->YMillimeter; pGdiInfo->ulHorzRes = SelectedMode->VisScreenWidth; pGdiInfo->ulVertRes = SelectedMode->VisScreenHeight; pGdiInfo->ulPanningHorzRes = SelectedMode->VisScreenWidth; pGdiInfo->ulPanningVertRes = SelectedMode->VisScreenHeight; pGdiInfo->cBitsPixel = SelectedMode->BitsPerPlane; pGdiInfo->cPlanes = SelectedMode->NumberOfPlanes; pGdiInfo->ulVRefresh = SelectedMode->Frequency; pGdiInfo->ulBltAlignment = 1; pGdiInfo->ulLogPixelsX = pDevMode->dmLogPixels; pGdiInfo->ulLogPixelsY = pDevMode->dmLogPixels; pGdiInfo->flTextCaps = TC_RA_ABLE; pGdiInfo->flRaster = 0; pGdiInfo->ulDACRed = SelectedMode->NumberRedBits; pGdiInfo->ulDACGreen = SelectedMode->NumberGreenBits; pGdiInfo->ulDACBlue = SelectedMode->NumberBlueBits; pGdiInfo->ulAspectX = 0x24; pGdiInfo->ulAspectY = 0x24; pGdiInfo->ulAspectXY = 0x33; pGdiInfo->xStyleStep = 1; pGdiInfo->yStyleStep = 1; pGdiInfo->denStyleStep = 3; pGdiInfo->ptlPhysOffset.x = 0; pGdiInfo->ptlPhysOffset.y = 0; pGdiInfo->szlPhysSize.cx = 0; pGdiInfo->szlPhysSize.cy = 0; /* * Try to get the color info from the miniport. */ if (!EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES, NULL, 0, &ColorCapabilities, sizeof(VIDEO_COLOR_CAPABILITIES), &Temp)) { pGdiInfo->ciDevice.Red.x = ColorCapabilities.RedChromaticity_x; pGdiInfo->ciDevice.Red.y = ColorCapabilities.RedChromaticity_y; pGdiInfo->ciDevice.Green.x = ColorCapabilities.GreenChromaticity_x; pGdiInfo->ciDevice.Green.y = ColorCapabilities.GreenChromaticity_y; pGdiInfo->ciDevice.Blue.x = ColorCapabilities.BlueChromaticity_x; pGdiInfo->ciDevice.Blue.y = ColorCapabilities.BlueChromaticity_y; pGdiInfo->ciDevice.AlignmentWhite.x = ColorCapabilities.WhiteChromaticity_x; pGdiInfo->ciDevice.AlignmentWhite.y = ColorCapabilities.WhiteChromaticity_y; pGdiInfo->ciDevice.AlignmentWhite.Y = ColorCapabilities.WhiteChromaticity_Y; if (ColorCapabilities.AttributeFlags & VIDEO_DEVICE_COLOR) { pGdiInfo->ciDevice.RedGamma = ColorCapabilities.RedGamma; pGdiInfo->ciDevice.GreenGamma = ColorCapabilities.GreenGamma; pGdiInfo->ciDevice.BlueGamma = ColorCapabilities.BlueGamma; } else { pGdiInfo->ciDevice.RedGamma = ColorCapabilities.WhiteGamma; pGdiInfo->ciDevice.GreenGamma = ColorCapabilities.WhiteGamma; pGdiInfo->ciDevice.BlueGamma = ColorCapabilities.WhiteGamma; } } else { pGdiInfo->ciDevice.Red.x = 6700; pGdiInfo->ciDevice.Red.y = 3300; pGdiInfo->ciDevice.Green.x = 2100; pGdiInfo->ciDevice.Green.y = 7100; pGdiInfo->ciDevice.Blue.x = 1400; pGdiInfo->ciDevice.Blue.y = 800; pGdiInfo->ciDevice.AlignmentWhite.x = 3127; pGdiInfo->ciDevice.AlignmentWhite.y = 3290; pGdiInfo->ciDevice.AlignmentWhite.Y = 0; pGdiInfo->ciDevice.RedGamma = 20000; pGdiInfo->ciDevice.GreenGamma = 20000; pGdiInfo->ciDevice.BlueGamma = 20000; } pGdiInfo->ciDevice.Red.Y = 0; pGdiInfo->ciDevice.Green.Y = 0; pGdiInfo->ciDevice.Blue.Y = 0; pGdiInfo->ciDevice.Cyan.x = 0; pGdiInfo->ciDevice.Cyan.y = 0; pGdiInfo->ciDevice.Cyan.Y = 0; pGdiInfo->ciDevice.Magenta.x = 0; pGdiInfo->ciDevice.Magenta.y = 0; pGdiInfo->ciDevice.Magenta.Y = 0; pGdiInfo->ciDevice.Yellow.x = 0; pGdiInfo->ciDevice.Yellow.y = 0; pGdiInfo->ciDevice.Yellow.Y = 0; pGdiInfo->ciDevice.MagentaInCyanDye = 0; pGdiInfo->ciDevice.YellowInCyanDye = 0; pGdiInfo->ciDevice.CyanInMagentaDye = 0; pGdiInfo->ciDevice.YellowInMagentaDye = 0; pGdiInfo->ciDevice.CyanInYellowDye = 0; pGdiInfo->ciDevice.MagentaInYellowDye = 0; pGdiInfo->ulDevicePelsDPI = 0; pGdiInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA; pGdiInfo->ulHTPatternSize = HT_PATSIZE_4x4_M; pGdiInfo->flHTFlags = HT_FLAG_ADDITIVE_PRIMS; pDevInfo->flGraphicsCaps = 0; /* hack pDevInfo->lfDefaultFont = SystemFont; pDevInfo->lfAnsiVarFont = AnsiVariableFont; pDevInfo->lfAnsiFixFont = AnsiFixedFont; */ pDevInfo->cFonts = 0; pDevInfo->cxDither = 0; pDevInfo->cyDither = 0; pDevInfo->hpalDefault = 0; pDevInfo->flGraphicsCaps2 = 0; if (ppdev->BitsPerPixel == 8) { pGdiInfo->ulNumColors = 20; pGdiInfo->ulNumPalReg = 1 << ppdev->BitsPerPixel; pGdiInfo->ulHTOutputFormat = HT_FORMAT_8BPP; pDevInfo->flGraphicsCaps |= GCAPS_PALMANAGED; pDevInfo->iDitherFormat = BMF_8BPP; /* Assuming palette is orthogonal - all colors are same size. */ ppdev->PaletteShift = 8 - pGdiInfo->ulDACRed; } else { pGdiInfo->ulNumColors = (ULONG)(-1); pGdiInfo->ulNumPalReg = 0; switch (ppdev->BitsPerPixel) { case 16: pGdiInfo->ulHTOutputFormat = HT_FORMAT_16BPP; pDevInfo->iDitherFormat = BMF_16BPP; break; case 24: pGdiInfo->ulHTOutputFormat = HT_FORMAT_24BPP; pDevInfo->iDitherFormat = BMF_24BPP; break; default: pGdiInfo->ulHTOutputFormat = HT_FORMAT_32BPP; pDevInfo->iDitherFormat = BMF_32BPP; } } EngFreeMem(ModeInfo); return TRUE; }