From: John Tsiombikas Date: Sun, 24 Mar 2019 00:05:08 +0000 (+0200) Subject: video modes X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=efitest1;a=commitdiff_plain;h=bf13b9a4e264ec0dd189f0ff486549ed933968b5 video modes --- diff --git a/test.c b/test.c index 2b80863..5dbbed7 100644 --- a/test.c +++ b/test.c @@ -2,11 +2,110 @@ #include #include +int find_best_video_mode(void); +int find_video_mode(int xres, int yres, int bpp); +int set_video_mode(int mode); +int cur_video_mode(void); +void draw_box(int x, int y, int w, int h, int r, int g, int b); +int mask_to_shift(unsigned int mask); +int mask_to_bpp(unsigned int mask); +int mode_bpp(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *minf); + +uint32_t *fb; +int fb_width, fb_height; +int scanwidth; +int rshift, bshift, gshift; +unsigned int rmask, bmask, gmask; +EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + EFI_STATUS EFIAPI efi_main(EFI_HANDLE img, EFI_SYSTEM_TABLE *systab) { + int mode; + EFI_HANDLE *handles; + unsigned long nhandles = 0; + unsigned long misize; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mi; + SIMPLE_TEXT_OUTPUT_INTERFACE *sout; + InitializeLib(img, systab); + + sout = systab->ConOut; + uefi_call_wrapper(sout->ClearScreen, 1, sout); Print(L"hello world\n"); + LibLocateHandle(ByProtocol, &GraphicsOutputProtocol, 0, &nhandles, 0); + if(nhandles <= 0) { + Print(L"Failed to locate any graphics output devices\n"); + goto end; + } + if(!(handles = AllocatePool(nhandles))) { + Print(L"Failed to allocate memory for %lu handles\n", nhandles); + goto end; + } + Print(L"Found %lu graphics output devices\n", nhandles); + if(LibLocateHandle(ByProtocol, &GraphicsOutputProtocol, 0, &nhandles, &handles) != 0) { + Print(L"Failed to retreive graphics output device handles\n"); + goto end; + } + if(uefi_call_wrapper(BS->HandleProtocol, 3, handles[0], &GraphicsOutputProtocol, &gop) != 0) { + Print(L"Failed to retreive graphics output protocol structure\n"); + goto end; + } + + + if((mode = find_best_video_mode()) == -1) { + Print(L"Failed to find best video mode, leaving as is\n"); + } else { + if(set_video_mode(mode) == -1) { + Print(L"Failed to change video mode, leaving as is\n"); + } + } + uefi_call_wrapper(gop->QueryMode, 4, gop, gop->Mode->Mode, &misize, &mi); + + fb_width = mi->HorizontalResolution; + fb_height = mi->VerticalResolution; + scanwidth = mi->PixelsPerScanLine; + + switch(mi->PixelFormat) { + case PixelRedGreenBlueReserved8BitPerColor: + rshift = 0; + gshift = 8; + bshift = 16; + rmask = 0xff; + gmask = 0xff00; + bmask = 0xff0000; + break; + + case PixelBlueGreenRedReserved8BitPerColor: + rshift = 16; + gshift = 8; + bshift = 0; + rmask = 0xff0000; + gmask = 0xff00; + bmask = 0xff; + break; + + case PixelBitMask: + rmask = mi->PixelInformation.RedMask; + gmask = mi->PixelInformation.GreenMask; + bmask = mi->PixelInformation.BlueMask; + rshift = mask_to_shift(rmask); + gshift = mask_to_shift(gmask); + bshift = mask_to_shift(bmask); + break; + + default: + Print(L"Unsupported pixel format\n"); + goto end; + } + fb = (uint32_t*)gop->Mode->FrameBufferBase; + + Print(L"Video mode %ux%u %dbpp (fmt id: %u)\n", mi->HorizontalResolution, + mi->VerticalResolution, mask_to_bpp(rmask | gmask | bmask), (unsigned int)mi->PixelFormat); + + draw_box(100, 100, 200, 200, 255, 128, 64); + +end: asm volatile("cli"); for(;;) { asm volatile("hlt"); @@ -14,3 +113,123 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE img, EFI_SYSTEM_TABLE *systab) return EFI_SUCCESS; } + +static uint32_t calc_score(int x, int y, int bpp) +{ + uint32_t a = y >> 5; + uint32_t b = x >> 5; + + if(a > 0xfff) a = 0xfff; + if(b > 0xfff) b = 0xfff; + + return (a << 20) | (b << 8) | (bpp & 0xff); +} + +int find_best_video_mode(void) +{ + int i, nmodes, w, h; + int score, best_score = 0, best_mode = -1; + unsigned long misize; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mi; + + nmodes = gop->Mode->MaxMode; + for(i=0; iQueryMode, 4, gop, i, &misize, &mi); + w = mi->HorizontalResolution; + h = mi->VerticalResolution; + + score = calc_score(w, h, mode_bpp(mi)); + if(score > best_score) { + best_score = score; + best_mode = i; + } + } + return best_mode; +} + +int find_video_mode(int xres, int yres, int bpp) +{ + int i, nmodes, w, h; + unsigned long misize; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mi; + + nmodes = gop->Mode->MaxMode; + for(i=0; iQueryMode, 4, gop, i, &misize, &mi); + w = mi->HorizontalResolution; + h = mi->VerticalResolution; + if(w == xres && h == yres && mode_bpp(mi) >= bpp) { + return i; + } + } + return -1; +} + +int set_video_mode(int mode) +{ + if(uefi_call_wrapper(gop->SetMode, 2, gop, mode) != 0) { + return -1; + } + return 0; +} + +int cur_video_mode(void) +{ + return gop->Mode->Mode; +} + +void draw_box(int x, int y, int w, int h, int r, int g, int b) +{ + int i, j; + uint32_t pixcol; + uint32_t *pptr = fb + y * scanwidth + x; + + pixcol = (((uint32_t)r << rshift) & rmask) | + (((uint32_t)g << gshift) & gmask) | + (((uint32_t)b << bshift) & bmask); + + for(i=0; i>= 1; + res++; + } + return res; +} + +int mask_to_bpp(unsigned int mask) +{ + int res = 0; + + while(mask) { + mask >>= 1; + res++; + } + return res; +} + +int mode_bpp(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *minf) +{ + switch(minf->PixelFormat) { + case PixelRedGreenBlueReserved8BitPerColor: + case PixelBlueGreenRedReserved8BitPerColor: + return 24; + + case PixelBitMask: + return mask_to_bpp(minf->PixelInformation.RedMask | minf->PixelInformation.GreenMask | + minf->PixelInformation.BlueMask); + + default: + break; + } + return 0; +}