mirror of https://github.com/acidanthera/audk.git
EmulatorPkg/Win: Use FrameBufferBltLib for BLT operation
Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com> Cc: Andrew Fish <afish@apple.com>
This commit is contained in:
parent
ce8c1d92f5
commit
d773459e2f
|
@ -55,6 +55,7 @@
|
|||
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
|
||||
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
|
||||
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
|
||||
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
|
||||
|
||||
#
|
||||
# UEFI & PI
|
||||
|
|
|
@ -31,6 +31,7 @@ Abstract:
|
|||
#include <Protocol/SimpleTextIn.h>
|
||||
#include <Protocol/SimpleTextInEx.h>
|
||||
#include <Protocol/GraphicsOutput.h>
|
||||
#include <Library/FrameBufferBltLib.h>
|
||||
|
||||
//
|
||||
// WM_SYSKEYDOWN/WM_SYSKEYUP Notification
|
||||
|
@ -86,9 +87,8 @@ typedef struct {
|
|||
// updated in the main thread and displayed in the windows thread.
|
||||
//
|
||||
BITMAPV4HEADER *VirtualScreenInfo;
|
||||
RGBQUAD *VirtualScreen;
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FillLine;
|
||||
FRAME_BUFFER_CONFIGURE *FrameBufferConfigure;
|
||||
|
||||
//
|
||||
// Keyboard Queue used by Simple Text In.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -193,15 +193,63 @@ WinNtWndSize (
|
|||
IN UINT32 Height
|
||||
)
|
||||
{
|
||||
UINT32 Size;
|
||||
GRAPHICS_PRIVATE_DATA *Private;
|
||||
RECT Rect;
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewFillLine;
|
||||
RETURN_STATUS RStatus;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION Info;
|
||||
GRAPHICS_PRIVATE_DATA *Private;
|
||||
RECT Rect;
|
||||
BITMAPV4HEADER *VirtualScreenInfo;
|
||||
FRAME_BUFFER_CONFIGURE *FrameBufferConfigure;
|
||||
UINTN FrameBufferConfigureSize;
|
||||
|
||||
Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
|
||||
Private->Width = Width;
|
||||
Private->Height = Height;
|
||||
|
||||
//
|
||||
// Allocate DIB frame buffer directly from NT for performance enhancement
|
||||
// This buffer is the virtual screen/frame buffer.
|
||||
//
|
||||
VirtualScreenInfo = HeapAlloc (
|
||||
GetProcessHeap (),
|
||||
HEAP_ZERO_MEMORY,
|
||||
Width * Height * sizeof (RGBQUAD) + sizeof (BITMAPV4HEADER)
|
||||
);
|
||||
if (VirtualScreenInfo == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the virtual screen info data structure
|
||||
// Use negative Height to make sure screen/buffer are using the same coordinate.
|
||||
//
|
||||
VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);
|
||||
VirtualScreenInfo->bV4Width = Width;
|
||||
VirtualScreenInfo->bV4Height = -(LONG)Height;
|
||||
VirtualScreenInfo->bV4Planes = 1;
|
||||
VirtualScreenInfo->bV4BitCount = 32;
|
||||
//
|
||||
// uncompressed
|
||||
//
|
||||
VirtualScreenInfo->bV4V4Compression = BI_RGB;
|
||||
|
||||
Info.HorizontalResolution = Width;
|
||||
Info.VerticalResolution = Height;
|
||||
Info.PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
|
||||
Info.PixelsPerScanLine = Width;
|
||||
FrameBufferConfigureSize = 0;
|
||||
RStatus = FrameBufferBltConfigure (VirtualScreenInfo + 1, &Info, NULL, &FrameBufferConfigureSize);
|
||||
ASSERT (RStatus == EFI_BUFFER_TOO_SMALL);
|
||||
FrameBufferConfigure = AllocatePool (FrameBufferConfigureSize);
|
||||
if (FrameBufferConfigure == NULL) {
|
||||
HeapFree (GetProcessHeap (), 0, VirtualScreenInfo);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
RStatus = FrameBufferBltConfigure (VirtualScreenInfo + 1, &Info, FrameBufferConfigure, &FrameBufferConfigureSize);
|
||||
ASSERT_RETURN_ERROR (RStatus);
|
||||
|
||||
|
||||
if (Private->FrameBufferConfigure != NULL) {
|
||||
FreePool (Private->FrameBufferConfigure);
|
||||
}
|
||||
Private->FrameBufferConfigure = FrameBufferConfigure;
|
||||
|
||||
//
|
||||
// Free the old buffer. We do not save the content of the old buffer since the
|
||||
|
@ -211,46 +259,19 @@ WinNtWndSize (
|
|||
if (Private->VirtualScreenInfo != NULL) {
|
||||
HeapFree (GetProcessHeap (), 0, Private->VirtualScreenInfo);
|
||||
}
|
||||
Private->VirtualScreenInfo = VirtualScreenInfo;
|
||||
|
||||
//
|
||||
// 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 row of this buffer will be the bottom
|
||||
// line of the image. This is an artifact of the way we draw to the screen.
|
||||
//
|
||||
Size = Private->Width * Private->Height * sizeof (RGBQUAD) + sizeof (BITMAPV4HEADER);
|
||||
Private->VirtualScreenInfo = HeapAlloc (
|
||||
GetProcessHeap (),
|
||||
HEAP_ZERO_MEMORY,
|
||||
Size
|
||||
);
|
||||
|
||||
//
|
||||
// Update the virtual screen info data structure
|
||||
//
|
||||
Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);
|
||||
Private->VirtualScreenInfo->bV4Width = Private->Width;
|
||||
Private->VirtualScreenInfo->bV4Height = Private->Height;
|
||||
Private->VirtualScreenInfo->bV4Planes = 1;
|
||||
Private->VirtualScreenInfo->bV4BitCount = 32;
|
||||
//
|
||||
// uncompressed
|
||||
//
|
||||
Private->VirtualScreenInfo->bV4V4Compression = BI_RGB;
|
||||
|
||||
//
|
||||
// The rest of the allocated memory block is the virtual screen buffer
|
||||
//
|
||||
Private->VirtualScreen = (RGBQUAD *)(Private->VirtualScreenInfo + 1);
|
||||
Private->Width = Width;
|
||||
Private->Height = Height;
|
||||
|
||||
//
|
||||
// Use the AdjuctWindowRect fuction to calculate the real width and height
|
||||
// of the new window including the border and caption
|
||||
//
|
||||
Rect.left = 0;
|
||||
Rect.top = 0;
|
||||
Rect.right = Private->Width;
|
||||
Rect.bottom = Private->Height;
|
||||
Rect.left = 0;
|
||||
Rect.top = 0;
|
||||
Rect.right = Width;
|
||||
Rect.bottom = Height;
|
||||
|
||||
AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);
|
||||
|
||||
|
@ -267,16 +288,6 @@ WinNtWndSize (
|
|||
//
|
||||
MoveWindow (Private->WindowHandle, Rect.left, Rect.top, (INT32)Width, (INT32)Height, TRUE);
|
||||
|
||||
NewFillLine = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Private->Width);
|
||||
if (NewFillLine == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (Private->FillLine != NULL) {
|
||||
FreePool (Private->FillLine);
|
||||
}
|
||||
|
||||
Private->FillLine = NewFillLine;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -322,68 +333,22 @@ WinNtWndBlt (
|
|||
IN EMU_GRAPHICS_WINDOWS__BLT_ARGS *Args
|
||||
)
|
||||
{
|
||||
RETURN_STATUS RStatus;
|
||||
GRAPHICS_PRIVATE_DATA *Private;
|
||||
UINTN DstY;
|
||||
UINTN SrcY;
|
||||
RGBQUAD *VScreen;
|
||||
RGBQUAD *VScreenSrc;
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
|
||||
UINTN Index;
|
||||
RECT Rect;
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FillPixel;
|
||||
UINT32 VerticalResolution;
|
||||
UINT32 HorizontalResolution;
|
||||
|
||||
Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);
|
||||
|
||||
//
|
||||
// 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 = Private->VirtualScreenInfo->bV4Height;
|
||||
HorizontalResolution = Private->VirtualScreenInfo->bV4Width;
|
||||
if (BltOperation == EfiBltVideoToBltBuffer) {
|
||||
|
||||
for (SrcY = Args->SourceY, DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); SrcY++, DstY++) {
|
||||
Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Args->Delta) + Args->DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
||||
VScreen = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + Args->SourceX];
|
||||
CopyMem (Blt, VScreen, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Args->Width);
|
||||
}
|
||||
} else {
|
||||
if (BltOperation == EfiBltVideoFill) {
|
||||
FillPixel = BltBuffer;
|
||||
for (Index = 0; Index < Args->Width; Index++) {
|
||||
Private->FillLine[Index] = *FillPixel;
|
||||
}
|
||||
}
|
||||
|
||||
for (Index = 0; Index < Args->Height; Index++) {
|
||||
if (Args->DestinationY <= Args->SourceY) {
|
||||
SrcY = Args->SourceY + Index;
|
||||
DstY = Args->DestinationY + Index;
|
||||
} else {
|
||||
SrcY = Args->SourceY + Args->Height - Index - 1;
|
||||
DstY = Args->DestinationY + Args->Height - Index - 1;
|
||||
}
|
||||
|
||||
VScreen = &Private->VirtualScreen[(VerticalResolution - DstY - 1) * HorizontalResolution + Args->DestinationX];
|
||||
switch (BltOperation) {
|
||||
case EfiBltBufferToVideo:
|
||||
Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Args->Delta) + Args->SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
||||
CopyMem (VScreen, Blt, Args->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
||||
break;
|
||||
|
||||
case EfiBltVideoToVideo:
|
||||
VScreenSrc = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + Args->SourceX];
|
||||
CopyMem (VScreen, VScreenSrc, Args->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
||||
break;
|
||||
|
||||
case EfiBltVideoFill:
|
||||
CopyMem (VScreen, Private->FillLine, Args->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
||||
break;
|
||||
}
|
||||
}
|
||||
RStatus = FrameBufferBlt (
|
||||
Private->FrameBufferConfigure,
|
||||
BltBuffer,
|
||||
BltOperation,
|
||||
Args->SourceX, Args->SourceY,
|
||||
Args->DestinationX, Args->DestinationY,
|
||||
Args->Width, Args->Height,
|
||||
Args->Delta
|
||||
);
|
||||
if (RETURN_ERROR (RStatus)) {
|
||||
return (EFI_STATUS)RStatus;
|
||||
}
|
||||
|
||||
if (BltOperation != EfiBltVideoToBltBuffer) {
|
||||
|
@ -435,21 +400,12 @@ WinNtGopThreadWindowProc (
|
|||
)
|
||||
{
|
||||
GRAPHICS_PRIVATE_DATA *Private;
|
||||
UINTN Size;
|
||||
HDC Handle;
|
||||
PAINTSTRUCT PaintStruct;
|
||||
LPARAM Index;
|
||||
EFI_INPUT_KEY Key;
|
||||
BOOLEAN AltIsPress;
|
||||
|
||||
//
|
||||
// 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
|
||||
|
@ -460,39 +416,7 @@ WinNtGopThreadWindowProc (
|
|||
ASSERT (NULL != Private);
|
||||
|
||||
switch (iMsg) {
|
||||
case WM_CREATE:
|
||||
Size = Private->Width * Private->Height * 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 = HeapAlloc (
|
||||
GetProcessHeap (),
|
||||
HEAP_ZERO_MEMORY,
|
||||
Size
|
||||
);
|
||||
|
||||
Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);
|
||||
Private->VirtualScreenInfo->bV4Width = Private->Width;
|
||||
Private->VirtualScreenInfo->bV4Height = Private->Height;
|
||||
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 = BeginPaint (hwnd, &PaintStruct);
|
||||
|
||||
SetDIBitsToDevice (
|
||||
|
@ -505,7 +429,7 @@ WinNtGopThreadWindowProc (
|
|||
0, // Source Y
|
||||
0, // DIB Start Scan Line
|
||||
Private->Height, // Number of scan lines
|
||||
Private->VirtualScreen, // Address of array of DIB bits
|
||||
Private->VirtualScreenInfo + 1, // Address of array of DIB bits
|
||||
(BITMAPINFO *) Private->VirtualScreenInfo, // Address of structure with bitmap info
|
||||
DIB_RGB_COLORS // RGB or palette indexes
|
||||
);
|
||||
|
@ -691,10 +615,6 @@ WinNtGopThreadWinMain (
|
|||
// This call will fail after the first time, but thats O.K. since we only need
|
||||
// WIN_NT_GOP_CLASS_NAME to exist to create the window.
|
||||
//
|
||||
// Note: Multiple instances of this DLL will use the same instance of this
|
||||
// Class, including the callback function, unless the Class is unregistered and
|
||||
// successfully registered again.
|
||||
//
|
||||
RegisterClassEx (&Private->WindowsClass);
|
||||
|
||||
//
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
ThunkProtocolList
|
||||
PpiListLib
|
||||
PeiServicesLib
|
||||
FrameBufferBltLib
|
||||
|
||||
[Ppis]
|
||||
gEmuThunkPpiGuid
|
||||
|
|
Loading…
Reference in New Issue