\r
Copyright (C) 2016, Red Hat, Inc.\r
\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License which accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-#include <Library/BaseMemoryLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
\r
#include "VirtioGpu.h"\r
\r
**/\r
VOID\r
ReleaseGopResources (\r
- IN OUT VGPU_GOP *VgpuGop,\r
- IN BOOLEAN DisableHead\r
+ IN OUT VGPU_GOP *VgpuGop,\r
+ IN BOOLEAN DisableHead\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
ASSERT (VgpuGop->ResourceId != 0);\r
ASSERT (VgpuGop->BackingStore != NULL);\r
//\r
Status = VirtioGpuSetScanout (\r
VgpuGop->ParentBus, // VgpuDev\r
- 0, 0, 0, 0, // X, Y, Width, Height\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0, // X, Y, Width, Height\r
0, // ScanoutId\r
0 // ResourceId\r
);\r
}\r
\r
//\r
- // Release backing pages.\r
+ // Unmap and release backing pages.\r
//\r
- FreePages (VgpuGop->BackingStore, VgpuGop->NumberOfPages);\r
- VgpuGop->BackingStore = NULL;\r
- VgpuGop->NumberOfPages = 0;\r
+ VirtioGpuUnmapAndFreeBackingStore (\r
+ VgpuGop->ParentBus, // VgpuDev\r
+ VgpuGop->NumberOfPages, // NumberOfPages\r
+ VgpuGop->BackingStore, // HostAddress\r
+ VgpuGop->BackingStoreMap // Mapping\r
+ );\r
+ VgpuGop->BackingStore = NULL;\r
+ VgpuGop->NumberOfPages = 0;\r
+ VgpuGop->BackingStoreMap = NULL;\r
\r
//\r
// Destroy the currently used 2D host resource.\r
if (EFI_ERROR (Status)) {\r
CpuDeadLoop ();\r
}\r
+\r
VgpuGop->ResourceId = 0;\r
}\r
\r
// The resolutions supported by this driver.\r
//\r
typedef struct {\r
- UINT32 Width;\r
- UINT32 Height;\r
+ UINT32 Width;\r
+ UINT32 Height;\r
} GOP_RESOLUTION;\r
\r
-STATIC CONST GOP_RESOLUTION mGopResolutions[] = {\r
- { 640, 480 },\r
- { 800, 480 },\r
- { 800, 600 },\r
- { 832, 624 },\r
- { 960, 640 },\r
- { 1024, 600 },\r
- { 1024, 768 },\r
- { 1152, 864 },\r
- { 1152, 870 },\r
- { 1280, 720 },\r
- { 1280, 760 },\r
- { 1280, 768 },\r
- { 1280, 800 },\r
- { 1280, 960 },\r
+STATIC CONST GOP_RESOLUTION mGopResolutions[] = {\r
+ { 640, 480 },\r
+ { 800, 480 },\r
+ { 800, 600 },\r
+ { 832, 624 },\r
+ { 960, 640 },\r
+ { 1024, 600 },\r
+ { 1024, 768 },\r
+ { 1152, 864 },\r
+ { 1152, 870 },\r
+ { 1280, 720 },\r
+ { 1280, 760 },\r
+ { 1280, 768 },\r
+ { 1280, 800 },\r
+ { 1280, 960 },\r
{ 1280, 1024 },\r
- { 1360, 768 },\r
- { 1366, 768 },\r
+ { 1360, 768 },\r
+ { 1366, 768 },\r
{ 1400, 1050 },\r
- { 1440, 900 },\r
- { 1600, 900 },\r
+ { 1440, 900 },\r
+ { 1600, 900 },\r
{ 1600, 1200 },\r
{ 1680, 1050 },\r
{ 1920, 1080 },\r
#define VGPU_GOP_FROM_GOP(GopPointer) \\r
CR (GopPointer, VGPU_GOP, Gop, VGPU_GOP_SIG)\r
\r
+STATIC\r
+VOID\r
+EFIAPI\r
+GopNativeResolution (\r
+ IN VGPU_GOP *VgpuGop,\r
+ OUT UINT32 *XRes,\r
+ OUT UINT32 *YRes\r
+ )\r
+{\r
+ volatile VIRTIO_GPU_RESP_DISPLAY_INFO DisplayInfo;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+\r
+ Status = VirtioGpuGetDisplayInfo (VgpuGop->ParentBus, &DisplayInfo);\r
+ if (Status != EFI_SUCCESS) {\r
+ return;\r
+ }\r
+\r
+ for (Index = 0; Index < VIRTIO_GPU_MAX_SCANOUTS; Index++) {\r
+ if (!DisplayInfo.Pmodes[Index].Enabled ||\r
+ !DisplayInfo.Pmodes[Index].Rectangle.Width ||\r
+ !DisplayInfo.Pmodes[Index].Rectangle.Height)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: #%d: %dx%d\n",\r
+ __FUNCTION__,\r
+ Index,\r
+ DisplayInfo.Pmodes[Index].Rectangle.Width,\r
+ DisplayInfo.Pmodes[Index].Rectangle.Height\r
+ ));\r
+ if ((*XRes == 0) || (*YRes == 0)) {\r
+ *XRes = DisplayInfo.Pmodes[Index].Rectangle.Width;\r
+ *YRes = DisplayInfo.Pmodes[Index].Rectangle.Height;\r
+ }\r
+ }\r
+}\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+GopInitialize (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This\r
+ )\r
+{\r
+ VGPU_GOP *VgpuGop;\r
+ EFI_STATUS Status;\r
+ UINT32 XRes = 0, YRes = 0, Index;\r
+\r
+ VgpuGop = VGPU_GOP_FROM_GOP (This);\r
+\r
+ //\r
+ // Set up the Gop -> GopMode -> GopModeInfo pointer chain, and the other\r
+ // (nonzero) constant fields.\r
+ //\r
+ // No direct framebuffer access is supported, only Blt() is.\r
+ //\r
+ VgpuGop->Gop.Mode = &VgpuGop->GopMode;\r
+\r
+ VgpuGop->GopMode.MaxMode = (UINT32)(ARRAY_SIZE (mGopResolutions));\r
+ VgpuGop->GopMode.Info = &VgpuGop->GopModeInfo;\r
+ VgpuGop->GopMode.SizeOfInfo = sizeof VgpuGop->GopModeInfo;\r
+\r
+ VgpuGop->GopModeInfo.PixelFormat = PixelBltOnly;\r
+\r
+ //\r
+ // query host for display resolution\r
+ //\r
+ GopNativeResolution (VgpuGop, &XRes, &YRes);\r
+ if ((XRes == 0) || (YRes == 0)) {\r
+ return;\r
+ }\r
+\r
+ if (PcdGet8 (PcdVideoResolutionSource) == 0) {\r
+ Status = PcdSet32S (PcdVideoHorizontalResolution, XRes);\r
+ ASSERT_RETURN_ERROR (Status);\r
+ Status = PcdSet32S (PcdVideoVerticalResolution, YRes);\r
+ ASSERT_RETURN_ERROR (Status);\r
+ Status = PcdSet8S (PcdVideoResolutionSource, 2);\r
+ ASSERT_RETURN_ERROR (Status);\r
+ }\r
+\r
+ VgpuGop->NativeXRes = XRes;\r
+ VgpuGop->NativeYRes = YRes;\r
+ for (Index = 0; Index < ARRAY_SIZE (mGopResolutions); Index++) {\r
+ if ((mGopResolutions[Index].Width == XRes) &&\r
+ (mGopResolutions[Index].Height == YRes))\r
+ {\r
+ // native resolution already is in mode list\r
+ return;\r
+ }\r
+ }\r
+\r
+ // add to mode list\r
+ VgpuGop->GopMode.MaxMode++;\r
+}\r
+\r
//\r
// EFI_GRAPHICS_OUTPUT_PROTOCOL member functions.\r
//\r
EFI_STATUS\r
EFIAPI\r
GopQueryMode (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN UINT32 ModeNumber,\r
- OUT UINTN *SizeOfInfo,\r
- OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN UINT32 ModeNumber,\r
+ OUT UINTN *SizeOfInfo,\r
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
)\r
{\r
- EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GopModeInfo;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GopModeInfo;\r
\r
- if (ModeNumber >= ARRAY_SIZE (mGopResolutions)) {\r
+ if (ModeNumber >= This->Mode->MaxMode) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- GopModeInfo->HorizontalResolution = mGopResolutions[ModeNumber].Width;\r
- GopModeInfo->VerticalResolution = mGopResolutions[ModeNumber].Height;\r
- GopModeInfo->PixelFormat = PixelBltOnly;\r
- GopModeInfo->PixelsPerScanLine = mGopResolutions[ModeNumber].Width;\r
+ if (ModeNumber < ARRAY_SIZE (mGopResolutions)) {\r
+ GopModeInfo->HorizontalResolution = mGopResolutions[ModeNumber].Width;\r
+ GopModeInfo->VerticalResolution = mGopResolutions[ModeNumber].Height;\r
+ } else {\r
+ VGPU_GOP *VgpuGop = VGPU_GOP_FROM_GOP (This);\r
+ GopModeInfo->HorizontalResolution = VgpuGop->NativeXRes;\r
+ GopModeInfo->VerticalResolution = VgpuGop->NativeYRes;\r
+ }\r
+\r
+ GopModeInfo->PixelFormat = PixelBltOnly;\r
+ GopModeInfo->PixelsPerScanLine = GopModeInfo->HorizontalResolution;\r
\r
*SizeOfInfo = sizeof *GopModeInfo;\r
- *Info = GopModeInfo;\r
+ *Info = GopModeInfo;\r
return EFI_SUCCESS;\r
}\r
\r
EFI_STATUS\r
EFIAPI\r
GopSetMode (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN UINT32 ModeNumber\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN UINT32 ModeNumber\r
)\r
{\r
- VGPU_GOP *VgpuGop;\r
- UINT32 NewResourceId;\r
- UINTN NewNumberOfBytes;\r
- UINTN NewNumberOfPages;\r
- VOID *NewBackingStore;\r
- EFI_STATUS Status;\r
- EFI_STATUS Status2;\r
-\r
- if (ModeNumber >= ARRAY_SIZE (mGopResolutions)) {\r
- return EFI_UNSUPPORTED;\r
+ VGPU_GOP *VgpuGop;\r
+ UINT32 NewResourceId;\r
+ UINTN NewNumberOfBytes;\r
+ UINTN NewNumberOfPages;\r
+ VOID *NewBackingStore;\r
+ EFI_PHYSICAL_ADDRESS NewBackingStoreDeviceAddress;\r
+ VOID *NewBackingStoreMap;\r
+ UINTN SizeOfInfo;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GopModeInfo;\r
+\r
+ EFI_STATUS Status;\r
+ EFI_STATUS Status2;\r
+\r
+ if (!This->Mode) {\r
+ // SetMode() call in InitVgpuGop() triggers this.\r
+ GopInitialize (This);\r
+ }\r
+\r
+ Status = GopQueryMode (This, ModeNumber, &SizeOfInfo, &GopModeInfo);\r
+ if (Status != EFI_SUCCESS) {\r
+ return Status;\r
}\r
\r
VgpuGop = VGPU_GOP_FROM_GOP (This);\r
// calls.\r
//\r
if (VgpuGop->ResourceId == 0) {\r
- //\r
- // Set up the Gop -> GopMode -> GopModeInfo pointer chain, and the other\r
- // (nonzero) constant fields.\r
- //\r
- // No direct framebuffer access is supported, only Blt() is.\r
- //\r
- VgpuGop->Gop.Mode = &VgpuGop->GopMode;\r
-\r
- VgpuGop->GopMode.MaxMode = (UINT32)(ARRAY_SIZE (mGopResolutions));\r
- VgpuGop->GopMode.Info = &VgpuGop->GopModeInfo;\r
- VgpuGop->GopMode.SizeOfInfo = sizeof VgpuGop->GopModeInfo;\r
-\r
- VgpuGop->GopModeInfo.PixelFormat = PixelBltOnly;\r
-\r
//\r
// This is the first time we create a host side resource.\r
//\r
VgpuGop->ParentBus, // VgpuDev\r
NewResourceId, // ResourceId\r
VirtioGpuFormatB8G8R8X8Unorm, // Format\r
- mGopResolutions[ModeNumber].Width, // Width\r
- mGopResolutions[ModeNumber].Height // Height\r
+ GopModeInfo->HorizontalResolution, // Width\r
+ GopModeInfo->VerticalResolution // Height\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
//\r
- // Allocate guest backing store.\r
+ // Allocate, zero and map guest backing store, for bus master common buffer\r
+ // operation.\r
//\r
- NewNumberOfBytes = mGopResolutions[ModeNumber].Width *\r
- mGopResolutions[ModeNumber].Height * sizeof (UINT32);\r
+ NewNumberOfBytes = GopModeInfo->HorizontalResolution *\r
+ GopModeInfo->VerticalResolution * sizeof (UINT32);\r
NewNumberOfPages = EFI_SIZE_TO_PAGES (NewNumberOfBytes);\r
- NewBackingStore = AllocatePages (NewNumberOfPages);\r
- if (NewBackingStore == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
+ Status = VirtioGpuAllocateZeroAndMapBackingStore (\r
+ VgpuGop->ParentBus, // VgpuDev\r
+ NewNumberOfPages, // NumberOfPages\r
+ &NewBackingStore, // HostAddress\r
+ &NewBackingStoreDeviceAddress, // DeviceAddress\r
+ &NewBackingStoreMap // Mapping\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
goto DestroyHostResource;\r
}\r
- //\r
- // Fill visible part of backing store with black.\r
- //\r
- ZeroMem (NewBackingStore, NewNumberOfBytes);\r
\r
//\r
// Attach backing store to the host resource.\r
//\r
Status = VirtioGpuResourceAttachBacking (\r
- VgpuGop->ParentBus, // VgpuDev\r
- NewResourceId, // ResourceId\r
- NewBackingStore, // FirstBackingPage\r
- NewNumberOfPages // NumberOfPages\r
+ VgpuGop->ParentBus, // VgpuDev\r
+ NewResourceId, // ResourceId\r
+ NewBackingStoreDeviceAddress, // BackingStoreDeviceAddress\r
+ NewNumberOfPages // NumberOfPages\r
);\r
if (EFI_ERROR (Status)) {\r
- goto FreeBackingStore;\r
+ goto UnmapAndFreeBackingStore;\r
}\r
\r
//\r
VgpuGop->ParentBus, // VgpuDev\r
0, // X\r
0, // Y\r
- mGopResolutions[ModeNumber].Width, // Width\r
- mGopResolutions[ModeNumber].Height, // Height\r
+ GopModeInfo->HorizontalResolution, // Width\r
+ GopModeInfo->VerticalResolution, // Height\r
0, // ScanoutId\r
NewResourceId // ResourceId\r
);\r
VgpuGop->ParentBus, // VgpuDev\r
0, // X\r
0, // Y\r
- mGopResolutions[ModeNumber].Width, // Width\r
- mGopResolutions[ModeNumber].Height, // Height\r
+ GopModeInfo->HorizontalResolution, // Width\r
+ GopModeInfo->VerticalResolution, // Height\r
NewResourceId // ResourceId\r
);\r
if (EFI_ERROR (Status)) {\r
// therefore non-recoverable.\r
//\r
Status2 = VirtioGpuSetScanout (\r
- VgpuGop->ParentBus, // VgpuDev\r
- 0, // X\r
- 0, // Y\r
- mGopResolutions[This->Mode->Mode].Width, // Width\r
- mGopResolutions[This->Mode->Mode].Height, // Height\r
- 0, // ScanoutId\r
- VgpuGop->ResourceId // ResourceId\r
+ VgpuGop->ParentBus, // VgpuDev\r
+ 0, // X\r
+ 0, // Y\r
+ VgpuGop->GopModeInfo.HorizontalResolution, // Width\r
+ VgpuGop->GopModeInfo.VerticalResolution, // Height\r
+ 0, // ScanoutId\r
+ VgpuGop->ResourceId // ResourceId\r
);\r
ASSERT_EFI_ERROR (Status2);\r
if (EFI_ERROR (Status2)) {\r
CpuDeadLoop ();\r
}\r
+\r
goto DetachBackingStore;\r
}\r
\r
ASSERT (VgpuGop->ResourceId == 0);\r
ASSERT (VgpuGop->BackingStore == NULL);\r
\r
- VgpuGop->ResourceId = NewResourceId;\r
- VgpuGop->BackingStore = NewBackingStore;\r
- VgpuGop->NumberOfPages = NewNumberOfPages;\r
+ VgpuGop->ResourceId = NewResourceId;\r
+ VgpuGop->BackingStore = NewBackingStore;\r
+ VgpuGop->NumberOfPages = NewNumberOfPages;\r
+ VgpuGop->BackingStoreMap = NewBackingStoreMap;\r
\r
//\r
// Populate Mode and ModeInfo (mutable fields only).\r
//\r
VgpuGop->GopMode.Mode = ModeNumber;\r
- VgpuGop->GopModeInfo.HorizontalResolution =\r
- mGopResolutions[ModeNumber].Width;\r
- VgpuGop->GopModeInfo.VerticalResolution = mGopResolutions[ModeNumber].Height;\r
- VgpuGop->GopModeInfo.PixelsPerScanLine = mGopResolutions[ModeNumber].Width;\r
+ VgpuGop->GopModeInfo = *GopModeInfo;\r
+ FreePool (GopModeInfo);\r
return EFI_SUCCESS;\r
\r
DetachBackingStore:\r
CpuDeadLoop ();\r
}\r
\r
-FreeBackingStore:\r
- FreePages (NewBackingStore, NewNumberOfPages);\r
+UnmapAndFreeBackingStore:\r
+ VirtioGpuUnmapAndFreeBackingStore (\r
+ VgpuGop->ParentBus, // VgpuDev\r
+ NewNumberOfPages, // NumberOfPages\r
+ NewBackingStore, // HostAddress\r
+ NewBackingStoreMap // Mapping\r
+ );\r
\r
DestroyHostResource:\r
Status2 = VirtioGpuResourceUnref (VgpuGop->ParentBus, NewResourceId);\r
CpuDeadLoop ();\r
}\r
\r
+ FreePool (GopModeInfo);\r
return Status;\r
}\r
\r
EFI_STATUS\r
EFIAPI\r
GopBlt (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
- IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
- IN UINTN SourceX,\r
- IN UINTN SourceY,\r
- IN UINTN DestinationX,\r
- IN UINTN DestinationY,\r
- IN UINTN Width,\r
- IN UINTN Height,\r
- IN UINTN Delta OPTIONAL\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
+ IN UINTN SourceX,\r
+ IN UINTN SourceY,\r
+ IN UINTN DestinationX,\r
+ IN UINTN DestinationY,\r
+ IN UINTN Width,\r
+ IN UINTN Height,\r
+ IN UINTN Delta OPTIONAL\r
)\r
{\r
- VGPU_GOP *VgpuGop;\r
- UINT32 CurrentHorizontal;\r
- UINT32 CurrentVertical;\r
- UINTN SegmentSize;\r
- UINTN Y;\r
- UINTN ResourceOffset;\r
- EFI_STATUS Status;\r
-\r
- VgpuGop = VGPU_GOP_FROM_GOP (This);\r
+ VGPU_GOP *VgpuGop;\r
+ UINT32 CurrentHorizontal;\r
+ UINT32 CurrentVertical;\r
+ UINTN SegmentSize;\r
+ UINTN Y;\r
+ UINTN ResourceOffset;\r
+ EFI_STATUS Status;\r
+\r
+ VgpuGop = VGPU_GOP_FROM_GOP (This);\r
CurrentHorizontal = VgpuGop->GopModeInfo.HorizontalResolution;\r
CurrentVertical = VgpuGop->GopModeInfo.VerticalResolution;\r
\r
// zero, then Width is the entire width of BltBuffer, and the stride is\r
// supposed to be calculated from Width.\r
//\r
- if (BltOperation == EfiBltVideoToBltBuffer ||\r
- BltOperation == EfiBltBufferToVideo) {\r
+ if ((BltOperation == EfiBltVideoToBltBuffer) ||\r
+ (BltOperation == EfiBltBufferToVideo))\r
+ {\r
if (Delta == 0) {\r
Delta = SegmentSize;\r
}\r
// For operations that write to the display, check if the destination fits\r
// onto the display.\r
//\r
- if (BltOperation == EfiBltVideoFill ||\r
- BltOperation == EfiBltBufferToVideo ||\r
- BltOperation == EfiBltVideoToVideo) {\r
- if (DestinationX > CurrentHorizontal ||\r
- Width > CurrentHorizontal - DestinationX ||\r
- DestinationY > CurrentVertical ||\r
- Height > CurrentVertical - DestinationY) {\r
+ if ((BltOperation == EfiBltVideoFill) ||\r
+ (BltOperation == EfiBltBufferToVideo) ||\r
+ (BltOperation == EfiBltVideoToVideo))\r
+ {\r
+ if ((DestinationX > CurrentHorizontal) ||\r
+ (Width > CurrentHorizontal - DestinationX) ||\r
+ (DestinationY > CurrentVertical) ||\r
+ (Height > CurrentVertical - DestinationY))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
// For operations that read from the display, check if the source fits onto\r
// the display.\r
//\r
- if (BltOperation == EfiBltVideoToBltBuffer ||\r
- BltOperation == EfiBltVideoToVideo) {\r
- if (SourceX > CurrentHorizontal ||\r
- Width > CurrentHorizontal - SourceX ||\r
- SourceY > CurrentVertical ||\r
- Height > CurrentVertical - SourceY) {\r
+ if ((BltOperation == EfiBltVideoToBltBuffer) ||\r
+ (BltOperation == EfiBltVideoToVideo))\r
+ {\r
+ if ((SourceX > CurrentHorizontal) ||\r
+ (Width > CurrentHorizontal - SourceX) ||\r
+ (SourceY > CurrentVertical) ||\r
+ (Height > CurrentVertical - SourceY))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
// won't be further steps.\r
//\r
switch (BltOperation) {\r
- case EfiBltVideoFill:\r
- //\r
- // Write data from the BltBuffer pixel (0, 0) directly to every pixel of\r
- // the video display rectangle (DestinationX, DestinationY) (DestinationX +\r
- // Width, DestinationY + Height). Only one pixel will be used from the\r
- // BltBuffer. Delta is NOT used.\r
- //\r
- for (Y = 0; Y < Height; ++Y) {\r
- SetMem32 (\r
- VgpuGop->BackingStore +\r
+ case EfiBltVideoFill:\r
+ //\r
+ // Write data from the BltBuffer pixel (0, 0) directly to every pixel of\r
+ // the video display rectangle (DestinationX, DestinationY) (DestinationX +\r
+ // Width, DestinationY + Height). Only one pixel will be used from the\r
+ // BltBuffer. Delta is NOT used.\r
+ //\r
+ for (Y = 0; Y < Height; ++Y) {\r
+ SetMem32 (\r
+ VgpuGop->BackingStore +\r
(DestinationY + Y) * CurrentHorizontal + DestinationX,\r
- SegmentSize,\r
- *(UINT32 *)BltBuffer\r
- );\r
- }\r
- break;\r
-\r
- case EfiBltVideoToBltBuffer:\r
- //\r
- // Read data from the video display rectangle (SourceX, SourceY) (SourceX +\r
- // Width, SourceY + Height) and place it in the BltBuffer rectangle\r
- // (DestinationX, DestinationY ) (DestinationX + Width, DestinationY +\r
- // Height). If DestinationX or DestinationY is not zero then Delta must be\r
- // set to the length in bytes of a row in the BltBuffer.\r
- //\r
- for (Y = 0; Y < Height; ++Y) {\r
- CopyMem (\r
- (UINT8 *)BltBuffer +\r
- (DestinationY + Y) * Delta + DestinationX * sizeof *BltBuffer,\r
- VgpuGop->BackingStore +\r
- (SourceY + Y) * CurrentHorizontal + SourceX,\r
- SegmentSize\r
- );\r
- }\r
- return EFI_SUCCESS;\r
+ SegmentSize,\r
+ *(UINT32 *)BltBuffer\r
+ );\r
+ }\r
\r
- case EfiBltBufferToVideo:\r
- //\r
- // Write data from the BltBuffer rectangle (SourceX, SourceY) (SourceX +\r
- // Width, SourceY + Height) directly to the video display rectangle\r
- // (DestinationX, DestinationY) (DestinationX + Width, DestinationY +\r
- // Height). If SourceX or SourceY is not zero then Delta must be set to the\r
- // length in bytes of a row in the BltBuffer.\r
- //\r
- for (Y = 0; Y < Height; ++Y) {\r
- CopyMem (\r
- VgpuGop->BackingStore +\r
- (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
- (UINT8 *)BltBuffer +\r
- (SourceY + Y) * Delta + SourceX * sizeof *BltBuffer,\r
- SegmentSize\r
- );\r
- }\r
- break;\r
+ break;\r
\r
- case EfiBltVideoToVideo:\r
- //\r
- // Copy from the video display rectangle (SourceX, SourceY) (SourceX +\r
- // Width, SourceY + Height) to the video display rectangle (DestinationX,\r
- // DestinationY) (DestinationX + Width, DestinationY + Height). The\r
- // BltBuffer and Delta are not used in this mode.\r
- //\r
- // A single invocation of CopyMem() handles overlap between source and\r
- // destination (that is, within a single line), but for multiple\r
- // invocations, we must handle overlaps.\r
- //\r
- if (SourceY < DestinationY) {\r
- Y = Height;\r
- while (Y > 0) {\r
- --Y;\r
+ case EfiBltVideoToBltBuffer:\r
+ //\r
+ // Read data from the video display rectangle (SourceX, SourceY) (SourceX +\r
+ // Width, SourceY + Height) and place it in the BltBuffer rectangle\r
+ // (DestinationX, DestinationY ) (DestinationX + Width, DestinationY +\r
+ // Height). If DestinationX or DestinationY is not zero then Delta must be\r
+ // set to the length in bytes of a row in the BltBuffer.\r
+ //\r
+ for (Y = 0; Y < Height; ++Y) {\r
CopyMem (\r
+ (UINT8 *)BltBuffer +\r
+ (DestinationY + Y) * Delta + DestinationX * sizeof *BltBuffer,\r
VgpuGop->BackingStore +\r
- (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
- VgpuGop->BackingStore +\r
- (SourceY + Y) * CurrentHorizontal + SourceX,\r
+ (SourceY + Y) * CurrentHorizontal + SourceX,\r
SegmentSize\r
);\r
}\r
- } else {\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ case EfiBltBufferToVideo:\r
+ //\r
+ // Write data from the BltBuffer rectangle (SourceX, SourceY) (SourceX +\r
+ // Width, SourceY + Height) directly to the video display rectangle\r
+ // (DestinationX, DestinationY) (DestinationX + Width, DestinationY +\r
+ // Height). If SourceX or SourceY is not zero then Delta must be set to the\r
+ // length in bytes of a row in the BltBuffer.\r
+ //\r
for (Y = 0; Y < Height; ++Y) {\r
CopyMem (\r
VgpuGop->BackingStore +\r
- (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
- VgpuGop->BackingStore +\r
- (SourceY + Y) * CurrentHorizontal + SourceX,\r
+ (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
+ (UINT8 *)BltBuffer +\r
+ (SourceY + Y) * Delta + SourceX * sizeof *BltBuffer,\r
SegmentSize\r
);\r
}\r
- }\r
- break;\r
\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
+ break;\r
+\r
+ case EfiBltVideoToVideo:\r
+ //\r
+ // Copy from the video display rectangle (SourceX, SourceY) (SourceX +\r
+ // Width, SourceY + Height) to the video display rectangle (DestinationX,\r
+ // DestinationY) (DestinationX + Width, DestinationY + Height). The\r
+ // BltBuffer and Delta are not used in this mode.\r
+ //\r
+ // A single invocation of CopyMem() handles overlap between source and\r
+ // destination (that is, within a single line), but for multiple\r
+ // invocations, we must handle overlaps.\r
+ //\r
+ if (SourceY < DestinationY) {\r
+ Y = Height;\r
+ while (Y > 0) {\r
+ --Y;\r
+ CopyMem (\r
+ VgpuGop->BackingStore +\r
+ (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
+ VgpuGop->BackingStore +\r
+ (SourceY + Y) * CurrentHorizontal + SourceX,\r
+ SegmentSize\r
+ );\r
+ }\r
+ } else {\r
+ for (Y = 0; Y < Height; ++Y) {\r
+ CopyMem (\r
+ VgpuGop->BackingStore +\r
+ (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
+ VgpuGop->BackingStore +\r
+ (SourceY + Y) * CurrentHorizontal + SourceX,\r
+ SegmentSize\r
+ );\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
//\r
// Template for initializing VGPU_GOP.Gop.\r
//\r
-CONST EFI_GRAPHICS_OUTPUT_PROTOCOL mGopTemplate = {\r
+CONST EFI_GRAPHICS_OUTPUT_PROTOCOL mGopTemplate = {\r
GopQueryMode,\r
GopSetMode,\r
GopBlt,\r