winntgopscreen.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,052 行 · 第 1/3 页
C
1,052 行
if (Width == 0 || Height == 0) {
return EFI_INVALID_PARAMETER;
}
//
// If Delta is zero, then the entire BltBuffer is being used, so Delta
// is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
// the number of bytes in each row can be computed.
//
if (Delta == 0) {
Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
}
//
// We need to fill the Virtual Screen buffer with the blt data.
// The virtual screen is upside down, as the first row is the bootom row of
// the image.
//
VerticalResolution = This->Mode->Info->VerticalResolution;
HorizontalResolution = This->Mode->Info->HorizontalResolution;
if (BltOperation == EfiBltVideoToBltBuffer) {
//
// Video to BltBuffer: Source is Video, destination is BltBuffer
//
if (SourceY + Height > VerticalResolution) {
return EFI_INVALID_PARAMETER;
}
if (SourceX + Width > HorizontalResolution) {
return EFI_INVALID_PARAMETER;
}
//
// We have to raise to TPL Notify, so we make an atomic write the frame buffer.
// We would not want a timer based event (Cursor, ...) to come in while we are
// doing this operation.
//
OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY);
for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
VScreen = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + SourceX];
EfiCopyMem (Blt, VScreen, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Width);
}
} else {
//
// BltBuffer to Video: Source is BltBuffer, destination is Video
//
if (DestinationY + Height > VerticalResolution) {
return EFI_INVALID_PARAMETER;
}
if (DestinationX + Width > HorizontalResolution) {
return EFI_INVALID_PARAMETER;
}
//
// We have to raise to TPL Notify, so we make an atomic write the frame buffer.
// We would not want a timer based event (Cursor, ...) to come in while we are
// doing this operation.
//
OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY);
if (BltOperation == EfiBltVideoFill) {
FillPixel = BltBuffer;
for (Index = 0; Index < Width; Index++) {
Private->FillLine[Index] = *FillPixel;
}
}
for (Index = 0; Index < Height; Index++) {
if (DestinationY <= SourceY) {
SrcY = SourceY + Index;
DstY = DestinationY + Index;
} else {
SrcY = SourceY + Height - Index - 1;
DstY = DestinationY + Height - Index - 1;
}
VScreen = &Private->VirtualScreen[(VerticalResolution - DstY - 1) * HorizontalResolution + DestinationX];
switch (BltOperation) {
case EfiBltBufferToVideo:
Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
EfiCopyMem (VScreen, Blt, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
break;
case EfiBltVideoToVideo:
VScreenSrc = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + SourceX];
EfiCopyMem (VScreen, VScreenSrc, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
break;
case EfiBltVideoFill:
EfiCopyMem (VScreen, Private->FillLine, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
break;
}
}
}
if (BltOperation != EfiBltVideoToBltBuffer) {
//
// Mark the area we just blted as Invalid so WM_PAINT will update.
//
Rect.left = DestinationX;
Rect.top = DestinationY;
Rect.right = DestinationX + Width;
Rect.bottom = DestinationY + Height;
Private->WinNtThunk->InvalidateRect (Private->WindowHandle, &Rect, FALSE);
//
// Send the WM_PAINT message to the thread that is drawing the window. We
// are in the main thread and the window drawing is in a child thread.
// There is a child thread per window. We have no CriticalSection or Mutex
// since we write the data and the other thread displays the data. While
// we may miss some data for a short period of time this is no different than
// a write combining on writes to a frame buffer.
//
Private->WinNtThunk->UpdateWindow (Private->WindowHandle);
}
gBS->RestoreTPL (OriginalTPL);
return EFI_SUCCESS;
}
//
// Construction and Destruction functions
//
EFI_STATUS
WinNtGopSupported (
IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
// TODO: WinNtIo - add argument and description to function comment
// TODO: EFI_UNSUPPORTED - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
//
// Check to see if the IO abstraction represents a device type we support.
//
// This would be replaced a check of PCI subsystem ID, etc.
//
if (!EfiCompareGuid (WinNtIo->TypeGuid, &gEfiWinNtGopGuid)) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
LRESULT
CALLBACK
WinNtGopThreadWindowProc (
IN HWND hwnd,
IN UINT iMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
Win32 Windows event handler.
Arguments:
See Win32 Book
Returns:
See Win32 Book
--*/
// TODO: hwnd - add argument and description to function comment
// TODO: iMsg - add argument and description to function comment
// TODO: wParam - add argument and description to function comment
// TODO: lParam - add argument and description to function comment
{
GOP_PRIVATE_DATA *Private;
UINTN Size;
HDC Handle;
PAINTSTRUCT PaintStruct;
LPARAM Index;
EFI_INPUT_KEY Key;
//
// BugBug - if there are two instances of this DLL in memory (such as is
// the case for ERM), the correct instance of this function may not be called.
// This also means that the address of the mTlsIndex value will be wrong, and
// the value may be wrong too.
//
//
// Use mTlsIndex global to get a Thread Local Storage version of Private.
// This works since each Gop protocol has a unique Private data instance and
// a unique thread.
//
Private = mWinNt->TlsGetValue (mTlsIndex);
ASSERT (NULL != Private);
switch (iMsg) {
case WM_CREATE:
Size = Private->GraphicsOutput.Mode->Info->HorizontalResolution * Private->GraphicsOutput.Mode->Info->VerticalResolution * sizeof (RGBQUAD);
//
// Allocate DIB frame buffer directly from NT for performance enhancement
// This buffer is the virtual screen/frame buffer. This buffer is not the
// same a a frame buffer. The first fow of this buffer will be the bottom
// line of the image. This is an artifact of the way we draw to the screen.
//
Private->VirtualScreenInfo = Private->WinNtThunk->HeapAlloc (
Private->WinNtThunk->GetProcessHeap (),
HEAP_ZERO_MEMORY,
Size
);
Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);
Private->VirtualScreenInfo->bV4Width = Private->GraphicsOutput.Mode->Info->HorizontalResolution;
Private->VirtualScreenInfo->bV4Height = Private->GraphicsOutput.Mode->Info->VerticalResolution;
Private->VirtualScreenInfo->bV4Planes = 1;
Private->VirtualScreenInfo->bV4BitCount = 32;
//
// uncompressed
//
Private->VirtualScreenInfo->bV4V4Compression = BI_RGB;
Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1);
return 0;
case WM_PAINT:
//
// I have not found a way to convert hwnd into a Private context. So for
// now we use this API to convert hwnd to Private data.
//
Handle = mWinNt->BeginPaint (hwnd, &PaintStruct);
mWinNt->SetDIBitsToDevice (
Handle, // Destination Device Context
0, // Destination X - 0
0, // Destination Y - 0
Private->GraphicsOutput.Mode->Info->HorizontalResolution, // Width
Private->GraphicsOutput.Mode->Info->VerticalResolution, // Height
0, // Source X
0, // Source Y
0, // DIB Start Scan Line
Private->GraphicsOutput.Mode->Info->VerticalResolution, // Number of scan lines
Private->VirtualScreen, // Address of array of DIB bits
(BITMAPINFO *) Private->VirtualScreenInfo, // Address of structure with bitmap info
DIB_RGB_COLORS // RGB or palette indexes
);
mWinNt->EndPaint (hwnd, &PaintStruct);
return 0;
//
// F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case
//
case WM_SYSKEYDOWN:
Key.ScanCode = 0;
switch (wParam) {
case VK_F10:
Key.ScanCode = SCAN_F10;
Key.UnicodeChar = 0;
GopPrivateAddQ (Private, Key);
return 0;
}
break;
case WM_KEYDOWN:
Key.ScanCode = 0;
switch (wParam) {
case VK_HOME: Key.ScanCode = SCAN_HOME; break;
case VK_END: Key.ScanCode = SCAN_END; break;
case VK_LEFT: Key.ScanCode = SCAN_LEFT; break;
case VK_RIGHT: Key.ScanCode = SCAN_RIGHT; break;
case VK_UP: Key.ScanCode = SCAN_UP; break;
case VK_DOWN: Key.ScanCode = SCAN_DOWN; break;
case VK_DELETE: Key.ScanCode = SCAN_DELETE; break;
case VK_INSERT: Key.ScanCode = SCAN_INSERT; break;
case VK_PRIOR: Key.ScanCode = SCAN_PAGE_UP; break;
case VK_NEXT: Key.ScanCode = SCAN_PAGE_DOWN; break;
case VK_ESCAPE: Key.ScanCode = SCAN_ESC; break;
case VK_F1: Key.ScanCode = SCAN_F1; break;
case VK_F2: Key.ScanCode = SCAN_F2; break;
case VK_F3: Key.ScanCode = SCAN_F3; break;
case VK_F4: Key.ScanCode = SCAN_F4; break;
case VK_F5: Key.ScanCode = SCAN_F5; break;
case VK_F6: Key.ScanCode = SCAN_F6; break;
case VK_F7: Key.ScanCode = SCAN_F7; break;
case VK_F8: Key.ScanCode = SCAN_F8; break;
case VK_F9: Key.ScanCode = SCAN_F9; break;
}
if (Key.ScanCode != 0) {
Key.UnicodeChar = 0;
GopPrivateAddQ (Private, Key);
}
return 0;
case WM_CHAR:
//
// The ESC key also generate WM_CHAR.
//
if (wParam == 0x1B) {
return 0;
}
for (Index = 0; Index < (lParam & 0xffff); Index++) {
if (wParam != 0) {
Key.UnicodeChar = (CHAR16) wParam;
Key.ScanCode = 0;
GopPrivateAddQ (Private, Key);
}
}
return 0;
case WM_CLOSE:
//
// This close message is issued by user, core is not aware of this,
// so don't release the window display resource, just hide the window.
//
Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_HIDE);
return 0;
case WM_DESTROY:
mWinNt->DestroyWindow (hwnd);
mWinNt->PostQuitMessage (0);
mWinNt->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo);
mWinNt->ExitThread (0);
return 0;
default:
break;
};
return mWinNt->DefWindowProc (hwnd, iMsg, wParam, lParam);
}
DWORD
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?