winntugascreen.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,024 行 · 第 1/3 页
C
1,024 行
Delta = Width * sizeof (EFI_UGA_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.
//
if (BltOperation == EfiUgaVideoToBltBuffer) {
//
// Video to BltBuffer: Source is Video, destination is BltBuffer
//
if (SourceY + Height > Private->VerticalResolution) {
return EFI_INVALID_PARAMETER;
}
if (SourceX + Width > Private->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_UGA_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + DestinationX * sizeof (EFI_UGA_PIXEL));
VScreen = &Private->VirtualScreen[(Private->VerticalResolution - SrcY - 1) * Private->HorizontalResolution + SourceX];
EfiCopyMem (Blt, VScreen, sizeof (EFI_UGA_PIXEL) * Width);
}
} else {
//
// BltBuffer to Video: Source is BltBuffer, destination is Video
//
if (DestinationY + Height > Private->VerticalResolution) {
return EFI_INVALID_PARAMETER;
}
if (DestinationX + Width > Private->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 == EfiUgaVideoFill) {
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[(Private->VerticalResolution - DstY - 1) * Private->HorizontalResolution + DestinationX];
switch (BltOperation) {
case EfiUgaBltBufferToVideo:
Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + SourceX * sizeof (EFI_UGA_PIXEL));
EfiCopyMem (VScreen, Blt, Width * sizeof (EFI_UGA_PIXEL));
break;
case EfiUgaVideoToVideo:
VScreenSrc = &Private->VirtualScreen[(Private->VerticalResolution - SrcY - 1) * Private->HorizontalResolution + SourceX];
EfiCopyMem (VScreen, VScreenSrc, Width * sizeof (EFI_UGA_PIXEL));
break;
case EfiUgaVideoFill:
EfiCopyMem (VScreen, Private->FillLine, Width * sizeof (EFI_UGA_PIXEL));
break;
}
}
}
if (BltOperation != EfiUgaVideoToBltBuffer) {
//
// 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;
}
EFI_STATUS
EFIAPI
WinNtUgaDispatchService (
IN PUGA_DEVICE pDevice,
IN PUGA_IO_REQUEST pIoRequest
)
/*++
Routine Description:
Send an IO operation to the root video graphics device or one of it's
children. You can use the root device pDevice == NULL to discover
all child devices.
Arguments:
pDevice - Device to send pIoRequest to. Null is the root device.
pIoRequest - IO operation requested.
Returns:
Varies depending on pIoRequest.
--*/
// TODO: EFI_NOT_FOUND - add return value to function comment
{
return EFI_NOT_FOUND;
}
//
// Construction and Destruction functions
//
EFI_STATUS
WinNtUgaSupported (
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, &gEfiWinNtUgaGuid)) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
LRESULT
CALLBACK
WinNtUgaThreadWindowProc (
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
{
UGA_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 Uga 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->HorizontalResolution * Private->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->HorizontalResolution;
Private->VirtualScreenInfo->bV4Height = Private->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->HorizontalResolution, // Width
Private->VerticalResolution, // Height
0, // Source X
0, // Source Y
0, // DIB Start Scan Line
Private->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;
UgaPrivateAddQ (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;
UgaPrivateAddQ (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;
UgaPrivateAddQ (Private, Key);
}
}
return 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?