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 + -
显示快捷键?