From: Ruiyu Ni <ruiyu.ni@intel.com>
To: edk2-devel@lists.01.org
Cc: Hao Wu <hao.a.wu@intel.com>, Andrew Fish <afish@apple.com>
Subject: [PATCH 03/10] EmulatorPkg/Win: Use FrameBufferBltLib for BLT operation
Date: Mon, 27 Aug 2018 15:53:23 +0800 [thread overview]
Message-ID: <20180827075330.269224-4-ruiyu.ni@intel.com> (raw)
In-Reply-To: <20180827075330.269224-1-ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@apple.com>
---
EmulatorPkg/EmulatorPkg.dsc | 1 +
EmulatorPkg/Win/Host/WinGop.h | 4 +-
EmulatorPkg/Win/Host/WinGopScreen.c | 218 ++++++++++++------------------------
EmulatorPkg/Win/Host/WinHost.inf | 1 +
4 files changed, 73 insertions(+), 151 deletions(-)
diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index 9f9f7d318d..ee85c9ef64 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -55,6 +55,7 @@ [LibraryClasses]
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
diff --git a/EmulatorPkg/Win/Host/WinGop.h b/EmulatorPkg/Win/Host/WinGop.h
index de27238342..7843b60b91 100644
--- a/EmulatorPkg/Win/Host/WinGop.h
+++ b/EmulatorPkg/Win/Host/WinGop.h
@@ -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.
diff --git a/EmulatorPkg/Win/Host/WinGopScreen.c b/EmulatorPkg/Win/Host/WinGopScreen.c
index 2ca51d23d0..0e1f1ff205 100644
--- a/EmulatorPkg/Win/Host/WinGopScreen.c
+++ b/EmulatorPkg/Win/Host/WinGopScreen.c
@@ -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,64 +193,85 @@ 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;
-
-
- //
- // Free the old buffer. We do not save the content of the old buffer since the
- // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
- // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
- //
- if (Private->VirtualScreenInfo != NULL) {
- HeapFree (GetProcessHeap (), 0, Private->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.
+ // This buffer is the virtual screen/frame buffer.
//
- Size = Private->Width * Private->Height * sizeof (RGBQUAD) + sizeof (BITMAPV4HEADER);
- Private->VirtualScreenInfo = HeapAlloc (
+ VirtualScreenInfo = HeapAlloc (
GetProcessHeap (),
HEAP_ZERO_MEMORY,
- Size
+ 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.
//
- Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);
- Private->VirtualScreenInfo->bV4Width = Private->Width;
- Private->VirtualScreenInfo->bV4Height = Private->Height;
- Private->VirtualScreenInfo->bV4Planes = 1;
- Private->VirtualScreenInfo->bV4BitCount = 32;
+ VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);
+ VirtualScreenInfo->bV4Width = Width;
+ VirtualScreenInfo->bV4Height = -(LONG)Height;
+ VirtualScreenInfo->bV4Planes = 1;
+ VirtualScreenInfo->bV4BitCount = 32;
//
// uncompressed
//
- Private->VirtualScreenInfo->bV4V4Compression = BI_RGB;
+ 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;
//
- // The rest of the allocated memory block is the virtual screen buffer
+ // Free the old buffer. We do not save the content of the old buffer since the
+ // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
+ // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
//
- Private->VirtualScreen = (RGBQUAD *)(Private->VirtualScreenInfo + 1);
+ if (Private->VirtualScreenInfo != NULL) {
+ HeapFree (GetProcessHeap (), 0, Private->VirtualScreenInfo);
+ }
+ Private->VirtualScreenInfo = VirtualScreenInfo;
+
+ 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);
//
diff --git a/EmulatorPkg/Win/Host/WinHost.inf b/EmulatorPkg/Win/Host/WinHost.inf
index 501edac15e..940f24da53 100644
--- a/EmulatorPkg/Win/Host/WinHost.inf
+++ b/EmulatorPkg/Win/Host/WinHost.inf
@@ -56,6 +56,7 @@ [LibraryClasses]
ThunkProtocolList
PpiListLib
PeiServicesLib
+ FrameBufferBltLib
[Ppis]
gEmuThunkPpiGuid
--
2.16.1.windows.1
next prev parent reply other threads:[~2018-08-27 7:52 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-27 7:53 [PATCH 00/10] Quality improvement for EmulatorPkg Win Host Ruiyu Ni
2018-08-27 7:53 ` [PATCH 01/10] EmulatorPkg/EmuGopDxe: Fix TxtInEx.SetState SCT conformance failure Ruiyu Ni
2018-08-27 7:53 ` [PATCH 02/10] EmulatorPkg/EmuGopDxe: Clear screen to black in GOP.SetMode Ruiyu Ni
2018-08-27 7:53 ` Ruiyu Ni [this message]
2018-08-27 7:53 ` [PATCH 04/10] EmulatorPkg/Win: ReadKeyStrokeEx() always returns correct KeyState Ruiyu Ni
2018-08-27 7:53 ` [PATCH 05/10] EmulatorPkg/Win: Do not zero out file content Ruiyu Ni
2018-08-29 1:51 ` Wu, Hao A
2018-08-27 7:53 ` [PATCH 06/10] EmulatorPkg/Win: Enable 64bit (SEC, PEI, DXE all run at 64bit) Ruiyu Ni
2018-08-27 7:53 ` [PATCH 07/10] EmulatorPkg/AutoScanPei: Report the correct CPU address size Ruiyu Ni
2018-08-29 1:54 ` Wu, Hao A
2018-08-29 2:53 ` Ni, Ruiyu
2018-08-27 7:53 ` [PATCH 08/10] EmulatorPkg/Win: Add VS2017 project file Ruiyu Ni
2018-08-27 7:53 ` [PATCH 09/10] EmulatorPkg: Use MdeModulePkg/Bds module Ruiyu Ni
2018-08-27 7:53 ` [PATCH 10/10] EmulatorPkg: IoThunk->Close() is called too early, may causing hang Ruiyu Ni
2018-08-29 1:58 ` [PATCH 00/10] Quality improvement for EmulatorPkg Win Host Wu, Hao A
2018-08-29 3:41 ` Ni, Ruiyu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180827075330.269224-4-ruiyu.ni@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox