3 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This file produces the graphics abstration of GOP. It is called by
19 WinNtGopDriver.c file which deals with the UEFI 2.0 driver model.
20 This file just does graphics.
27 EFI_WIN_NT_THUNK_PROTOCOL
*mWinNt
;
28 DWORD mTlsIndex
= TLS_OUT_OF_INDEXES
;
29 DWORD mTlsIndexUseCount
= 0; // lets us know when we can free mTlsIndex.
30 EFI_EVENT mGopScreenExitBootServicesEvent
;
31 GOP_MODE_DATA mGopModeData
[] = {
41 IN GOP_PRIVATE_DATA
*Private
,
42 IN UINT32 HorizontalResolution
,
43 IN UINT32 VerticalResolution
,
56 WinNtGopConvertParamToEfiKeyShiftState (
57 IN GOP_PRIVATE_DATA
*Private
,
65 // BUGBUG: Only GetAsyncKeyState() and GetKeyState() can distinguish
66 // left and right Ctrl, and Shift key.
67 // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL.
68 // Therefor, we can not set the correct Shift state here.
71 if ((*lParam
& GOP_EXTENDED_KEY
) == GOP_EXTENDED_KEY
) {
72 Private
->RightShift
= Flag
;
74 Private
->LeftShift
= Flag
;
79 Private
->LeftShift
= Flag
;
83 Private
->RightShift
= Flag
;
87 if ((*lParam
& GOP_EXTENDED_KEY
) == GOP_EXTENDED_KEY
) {
88 Private
->RightCtrl
= Flag
;
90 Private
->LeftCtrl
= Flag
;
95 Private
->LeftCtrl
= Flag
;
99 Private
->RightCtrl
= Flag
;
103 Private
->LeftLogo
= Flag
;
107 Private
->RightLogo
= Flag
;
111 Private
->Menu
= Flag
;
114 // BUGBUG: PrintScreen/SysRq can not trigger WM_KEYDOWN message,
115 // so SySReq shift state is not supported here.
118 Private
->SysReq
= Flag
;
121 // For Alt Keystroke.
124 if ((*lParam
& GOP_EXTENDED_KEY
) == GOP_EXTENDED_KEY
) {
125 Private
->RightAlt
= Flag
;
127 Private
->LeftAlt
= Flag
;
137 WinNtGopConvertParamToEfiKey (
138 IN GOP_PRIVATE_DATA
*Private
,
141 IN EFI_INPUT_KEY
*Key
147 case VK_HOME
: Key
->ScanCode
= SCAN_HOME
; Flag
= TRUE
; break;
148 case VK_END
: Key
->ScanCode
= SCAN_END
; Flag
= TRUE
; break;
149 case VK_LEFT
: Key
->ScanCode
= SCAN_LEFT
; Flag
= TRUE
; break;
150 case VK_RIGHT
: Key
->ScanCode
= SCAN_RIGHT
; Flag
= TRUE
; break;
151 case VK_UP
: Key
->ScanCode
= SCAN_UP
; Flag
= TRUE
; break;
152 case VK_DOWN
: Key
->ScanCode
= SCAN_DOWN
; Flag
= TRUE
; break;
153 case VK_DELETE
: Key
->ScanCode
= SCAN_DELETE
; Flag
= TRUE
; break;
154 case VK_INSERT
: Key
->ScanCode
= SCAN_INSERT
; Flag
= TRUE
; break;
155 case VK_PRIOR
: Key
->ScanCode
= SCAN_PAGE_UP
; Flag
= TRUE
; break;
156 case VK_NEXT
: Key
->ScanCode
= SCAN_PAGE_DOWN
; Flag
= TRUE
; break;
157 case VK_ESCAPE
: Key
->ScanCode
= SCAN_ESC
; Flag
= TRUE
; break;
159 case VK_F1
: Key
->ScanCode
= SCAN_F1
; Flag
= TRUE
; break;
160 case VK_F2
: Key
->ScanCode
= SCAN_F2
; Flag
= TRUE
; break;
161 case VK_F3
: Key
->ScanCode
= SCAN_F3
; Flag
= TRUE
; break;
162 case VK_F4
: Key
->ScanCode
= SCAN_F4
; Flag
= TRUE
; break;
163 case VK_F5
: Key
->ScanCode
= SCAN_F5
; Flag
= TRUE
; break;
164 case VK_F6
: Key
->ScanCode
= SCAN_F6
; Flag
= TRUE
; break;
165 case VK_F7
: Key
->ScanCode
= SCAN_F7
; Flag
= TRUE
; break;
166 case VK_F8
: Key
->ScanCode
= SCAN_F8
; Flag
= TRUE
; break;
167 case VK_F9
: Key
->ScanCode
= SCAN_F9
; Flag
= TRUE
; break;
168 case VK_F11
: Key
->ScanCode
= SCAN_F11
; Flag
= TRUE
; break;
169 case VK_F12
: Key
->ScanCode
= SCAN_F12
; Flag
= TRUE
; break;
171 case VK_F13
: Key
->ScanCode
= SCAN_F13
; Flag
= TRUE
; break;
172 case VK_F14
: Key
->ScanCode
= SCAN_F14
; Flag
= TRUE
; break;
173 case VK_F15
: Key
->ScanCode
= SCAN_F15
; Flag
= TRUE
; break;
174 case VK_F16
: Key
->ScanCode
= SCAN_F16
; Flag
= TRUE
; break;
175 case VK_F17
: Key
->ScanCode
= SCAN_F17
; Flag
= TRUE
; break;
176 case VK_F18
: Key
->ScanCode
= SCAN_F18
; Flag
= TRUE
; break;
177 case VK_F19
: Key
->ScanCode
= SCAN_F19
; Flag
= TRUE
; break;
178 case VK_F20
: Key
->ScanCode
= SCAN_F20
; Flag
= TRUE
; break;
179 case VK_F21
: Key
->ScanCode
= SCAN_F21
; Flag
= TRUE
; break;
180 case VK_F22
: Key
->ScanCode
= SCAN_F22
; Flag
= TRUE
; break;
181 case VK_F23
: Key
->ScanCode
= SCAN_F23
; Flag
= TRUE
; break;
182 case VK_F24
: Key
->ScanCode
= SCAN_F24
; Flag
= TRUE
; break;
183 case VK_PAUSE
: Key
->ScanCode
= SCAN_PAUSE
; Flag
= TRUE
; break;
189 Private
->NumLock
= (BOOLEAN
)(!Private
->NumLock
);
193 Private
->ScrollLock
= (BOOLEAN
)(!Private
->ScrollLock
);
197 Private
->CapsLock
= (BOOLEAN
)(!Private
->CapsLock
);
202 return (WinNtGopConvertParamToEfiKeyShiftState (Private
, wParam
, lParam
, TRUE
)) == TRUE
? TRUE
: Flag
;
207 // GOP Protocol Member Functions
212 Graphics Output protocol interface to get video mode
214 @param This Protocol instance pointer.
215 @param ModeNumber The mode number to return information on.
216 @param Info Caller allocated buffer that returns information
218 @param SizeOfInfo A pointer to the size, in bytes, of the Info
221 @retval EFI_SUCCESS Mode information returned.
222 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
223 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
225 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
226 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
232 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
233 IN UINT32 ModeNumber
,
234 OUT UINTN
*SizeOfInfo
,
235 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
238 GOP_PRIVATE_DATA
*Private
;
240 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
242 if (Info
== NULL
|| SizeOfInfo
== NULL
|| (UINTN
) ModeNumber
>= This
->Mode
->MaxMode
) {
243 return EFI_INVALID_PARAMETER
;
246 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
248 return EFI_OUT_OF_RESOURCES
;
251 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
253 (*Info
)->Version
= 0;
254 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
255 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
256 (*Info
)->PixelFormat
= PixelBltOnly
;
257 (*Info
)->PixelsPerScanLine
= (*Info
)->HorizontalResolution
;
264 Graphics Output protocol interface to set video mode
266 @param This Protocol instance pointer.
267 @param ModeNumber The mode number to be set.
269 @retval EFI_SUCCESS Graphics mode was changed.
270 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
272 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
278 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
283 GOP_PRIVATE_DATA
*Private
;
284 GOP_MODE_DATA
*ModeData
;
285 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill
;
286 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewFillLine
;
292 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
294 if (ModeNumber
>= This
->Mode
->MaxMode
) {
295 return EFI_UNSUPPORTED
;
298 ModeData
= &Private
->ModeData
[ModeNumber
];
299 This
->Mode
->Mode
= ModeNumber
;
300 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
301 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
302 Private
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= ModeData
->HorizontalResolution
;
304 if (Private
->HardwareNeedsStarting
) {
305 Status
= WinNtGopStartWindow (
307 ModeData
->HorizontalResolution
,
308 ModeData
->VerticalResolution
,
309 ModeData
->ColorDepth
,
310 ModeData
->RefreshRate
312 if (EFI_ERROR (Status
)) {
313 return EFI_DEVICE_ERROR
;
316 Private
->HardwareNeedsStarting
= FALSE
;
319 // Change the resolution and resize of the window
323 // Free the old buffer. We do not save the content of the old buffer since the
324 // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
325 // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
327 Private
->WinNtThunk
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
330 // Allocate DIB frame buffer directly from NT for performance enhancement
331 // This buffer is the virtual screen/frame buffer. This buffer is not the
332 // same a a frame buffer. The first row of this buffer will be the bottom
333 // line of the image. This is an artifact of the way we draw to the screen.
335 Size
= ModeData
->HorizontalResolution
* ModeData
->VerticalResolution
* sizeof (RGBQUAD
) + sizeof (BITMAPV4HEADER
);
336 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
337 Private
->WinNtThunk
->GetProcessHeap (),
343 // Update the virtual screen info data structure
345 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
346 Private
->VirtualScreenInfo
->bV4Width
= ModeData
->HorizontalResolution
;
347 Private
->VirtualScreenInfo
->bV4Height
= ModeData
->VerticalResolution
;
348 Private
->VirtualScreenInfo
->bV4Planes
= 1;
349 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
353 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
356 // The rest of the allocated memory block is the virtual screen buffer
358 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
361 // Use the AdjuctWindowRect fuction to calculate the real width and height
362 // of the new window including the border and caption
366 Rect
.right
= ModeData
->HorizontalResolution
;
367 Rect
.bottom
= ModeData
->VerticalResolution
;
369 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
371 Width
= Rect
.right
- Rect
.left
;
372 Height
= Rect
.bottom
- Rect
.top
;
375 // Retrieve the original window position information
377 Private
->WinNtThunk
->GetWindowRect (Private
->WindowHandle
, &Rect
);
380 // Adjust the window size
382 Private
->WinNtThunk
->MoveWindow (Private
->WindowHandle
, Rect
.left
, Rect
.top
, (INT32
)Width
, (INT32
)Height
, TRUE
);
386 NewFillLine
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->HorizontalResolution
);
387 if (NewFillLine
== NULL
) {
388 return EFI_DEVICE_ERROR
;
391 if (Private
->FillLine
!= NULL
) {
392 FreePool (Private
->FillLine
);
395 Private
->FillLine
= NewFillLine
;
408 ModeData
->HorizontalResolution
,
409 ModeData
->VerticalResolution
,
410 ModeData
->HorizontalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
417 Blt pixels from the rectangle (Width X Height) formed by the BltBuffer
418 onto the graphics screen starting a location (X, Y). (0, 0) is defined as
419 the upper left hand side of the screen. (X, Y) can be outside of the
420 current screen geometry and the BltBuffer will be cliped when it is
421 displayed. X and Y can be negative or positive. If Width or Height is
422 bigger than the current video screen the image will be clipped.
424 @param This Protocol instance pointer.
425 @param X X location on graphics screen.
426 @param Y Y location on the graphics screen.
427 @param Width Width of BltBuffer.
428 @param Height Hight of BltBuffer
429 @param BltOperation Operation to perform on BltBuffer and video memory
430 @param BltBuffer Buffer containing data to blt into video buffer.
431 This buffer has a size of
432 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
433 @param SourceX If the BltOperation is a EfiCopyBlt this is the
434 source of the copy. For other BLT operations this
435 argument is not used.
436 @param SourceX If the BltOperation is a EfiCopyBlt this is the
437 source of the copy. For other BLT operations this
438 argument is not used.
440 @retval EFI_SUCCESS The palette is updated with PaletteArray.
441 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
442 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
446 // TODO: SourceY - add argument and description to function comment
447 // TODO: DestinationX - add argument and description to function comment
448 // TODO: DestinationY - add argument and description to function comment
449 // TODO: Delta - add argument and description to function comment
453 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
454 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
455 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
458 IN UINTN DestinationX
,
459 IN UINTN DestinationY
,
462 IN UINTN Delta OPTIONAL
465 GOP_PRIVATE_DATA
*Private
;
471 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
474 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*FillPixel
;
475 UINT32 VerticalResolution
;
476 UINT32 HorizontalResolution
;
478 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
480 if ((BltOperation
< 0) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
481 return EFI_INVALID_PARAMETER
;
484 if (Width
== 0 || Height
== 0) {
485 return EFI_INVALID_PARAMETER
;
488 // If Delta is zero, then the entire BltBuffer is being used, so Delta
489 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
490 // the number of bytes in each row can be computed.
493 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
497 // We need to fill the Virtual Screen buffer with the blt data.
498 // The virtual screen is upside down, as the first row is the bootom row of
501 VerticalResolution
= This
->Mode
->Info
->VerticalResolution
;
502 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
503 if (BltOperation
== EfiBltVideoToBltBuffer
) {
506 // Video to BltBuffer: Source is Video, destination is BltBuffer
508 if (SourceY
+ Height
> VerticalResolution
) {
509 return EFI_INVALID_PARAMETER
;
512 if (SourceX
+ Width
> HorizontalResolution
) {
513 return EFI_INVALID_PARAMETER
;
516 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
517 // We would not want a timer based event (Cursor, ...) to come in while we are
518 // doing this operation.
520 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
522 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
523 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (DstY
* Delta
) + DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
524 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
525 CopyMem (Blt
, VScreen
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * Width
);
529 // BltBuffer to Video: Source is BltBuffer, destination is Video
531 if (DestinationY
+ Height
> VerticalResolution
) {
532 return EFI_INVALID_PARAMETER
;
535 if (DestinationX
+ Width
> HorizontalResolution
) {
536 return EFI_INVALID_PARAMETER
;
540 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
541 // We would not want a timer based event (Cursor, ...) to come in while we are
542 // doing this operation.
544 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
546 if (BltOperation
== EfiBltVideoFill
) {
547 FillPixel
= BltBuffer
;
548 for (Index
= 0; Index
< Width
; Index
++) {
549 Private
->FillLine
[Index
] = *FillPixel
;
553 for (Index
= 0; Index
< Height
; Index
++) {
554 if (DestinationY
<= SourceY
) {
555 SrcY
= SourceY
+ Index
;
556 DstY
= DestinationY
+ Index
;
558 SrcY
= SourceY
+ Height
- Index
- 1;
559 DstY
= DestinationY
+ Height
- Index
- 1;
562 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- DstY
- 1) * HorizontalResolution
+ DestinationX
];
563 switch (BltOperation
) {
564 case EfiBltBufferToVideo
:
565 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (SrcY
* Delta
) + SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
566 CopyMem (VScreen
, Blt
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
569 case EfiBltVideoToVideo
:
570 VScreenSrc
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
571 CopyMem (VScreen
, VScreenSrc
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
574 case EfiBltVideoFill
:
575 CopyMem (VScreen
, Private
->FillLine
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
581 if (BltOperation
!= EfiBltVideoToBltBuffer
) {
583 // Mark the area we just blted as Invalid so WM_PAINT will update.
585 Rect
.left
= (LONG
)DestinationX
;
586 Rect
.top
= (LONG
)DestinationY
;
587 Rect
.right
= (LONG
)(DestinationX
+ Width
);
588 Rect
.bottom
= (LONG
)(DestinationY
+ Height
);
589 Private
->WinNtThunk
->InvalidateRect (Private
->WindowHandle
, &Rect
, FALSE
);
592 // Send the WM_PAINT message to the thread that is drawing the window. We
593 // are in the main thread and the window drawing is in a child thread.
594 // There is a child thread per window. We have no CriticalSection or Mutex
595 // since we write the data and the other thread displays the data. While
596 // we may miss some data for a short period of time this is no different than
597 // a write combining on writes to a frame buffer.
600 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
603 gBS
->RestoreTPL (OriginalTPL
);
609 // Construction and Destruction functions
619 // TODO: WinNtIo - add argument and description to function comment
620 // TODO: EFI_UNSUPPORTED - add return value to function comment
621 // TODO: EFI_SUCCESS - add return value to function comment
624 IN EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
628 // Check to see if the IO abstraction represents a device type we support.
630 // This would be replaced a check of PCI subsystem ID, etc.
632 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtGopGuid
)) {
633 return EFI_UNSUPPORTED
;
641 Win32 Windows event handler.
645 @return See Win32 Book
648 // TODO: hwnd - add argument and description to function comment
649 // TODO: iMsg - add argument and description to function comment
650 // TODO: wParam - add argument and description to function comment
651 // TODO: lParam - add argument and description to function comment
654 WinNtGopThreadWindowProc (
661 GOP_PRIVATE_DATA
*Private
;
664 PAINTSTRUCT PaintStruct
;
670 // BugBug - if there are two instances of this DLL in memory (such as is
671 // the case for ERM), the correct instance of this function may not be called.
672 // This also means that the address of the mTlsIndex value will be wrong, and
673 // the value may be wrong too.
678 // Use mTlsIndex global to get a Thread Local Storage version of Private.
679 // This works since each Gop protocol has a unique Private data instance and
683 Private
= mWinNt
->TlsGetValue (mTlsIndex
);
684 ASSERT (NULL
!= Private
);
688 Size
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
* Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
* sizeof (RGBQUAD
);
691 // Allocate DIB frame buffer directly from NT for performance enhancement
692 // This buffer is the virtual screen/frame buffer. This buffer is not the
693 // same a a frame buffer. The first fow of this buffer will be the bottom
694 // line of the image. This is an artifact of the way we draw to the screen.
696 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
697 Private
->WinNtThunk
->GetProcessHeap (),
702 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
703 Private
->VirtualScreenInfo
->bV4Width
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
704 Private
->VirtualScreenInfo
->bV4Height
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
705 Private
->VirtualScreenInfo
->bV4Planes
= 1;
706 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
710 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
711 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
716 // I have not found a way to convert hwnd into a Private context. So for
717 // now we use this API to convert hwnd to Private data.
720 Handle
= mWinNt
->BeginPaint (hwnd
, &PaintStruct
);
722 mWinNt
->SetDIBitsToDevice (
723 Handle
, // Destination Device Context
724 0, // Destination X - 0
725 0, // Destination Y - 0
726 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
, // Width
727 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Height
730 0, // DIB Start Scan Line
731 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Number of scan lines
732 Private
->VirtualScreen
, // Address of array of DIB bits
733 (BITMAPINFO
*) Private
->VirtualScreenInfo
, // Address of structure with bitmap info
734 DIB_RGB_COLORS
// RGB or palette indexes
737 mWinNt
->EndPaint (hwnd
, &PaintStruct
);
741 // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case
742 // WM_SYSKEYDOWN is posted when F10 is pressed or
743 // holds down ALT key and then presses another key.
748 Key
.UnicodeChar
= CHAR_NULL
;
751 Key
.ScanCode
= SCAN_F10
;
752 Key
.UnicodeChar
= CHAR_NULL
;
753 GopPrivateAddKey (Private
, Key
);
758 // If ALT or ALT + modifier key is pressed.
760 if (WinNtGopConvertParamToEfiKey (Private
, &wParam
, &lParam
, &Key
)) {
761 if (Key
.ScanCode
!= 0){
763 // If ALT is pressed with other ScanCode.
764 // Always revers the left Alt for simple.
766 Private
->LeftAlt
= TRUE
;
768 GopPrivateAddKey (Private
, Key
);
770 // When Alt is released there is no windoes message, so
771 // clean it after using it.
773 Private
->RightAlt
= FALSE
;
774 Private
->LeftAlt
= FALSE
;
781 // The ESC key also generate WM_CHAR.
783 if (wParam
== 0x1B) {
787 if (AltIsPress
== TRUE
) {
789 // If AltIsPress is true that means the Alt key is pressed.
791 Private
->LeftAlt
= TRUE
;
793 for (Index
= 0; Index
< (lParam
& 0xffff); Index
++) {
795 Key
.UnicodeChar
= (CHAR16
) wParam
;
796 Key
.ScanCode
= SCAN_NULL
;
797 GopPrivateAddKey (Private
, Key
);
800 if (AltIsPress
== TRUE
) {
802 // When Alt is released there is no windoes message, so
803 // clean it after using it.
805 Private
->LeftAlt
= FALSE
;
806 Private
->RightAlt
= FALSE
;
812 // ALT is pressed with another key released
814 WinNtGopConvertParamToEfiKeyShiftState (Private
, &wParam
, &lParam
, FALSE
);
818 Key
.ScanCode
= SCAN_NULL
;
819 Key
.UnicodeChar
= CHAR_NULL
;
821 // A value key press will cause a WM_KEYDOWN first, then cause a WM_CHAR
822 // So if there is no modifier key updated, skip the WM_KEYDOWN even.
824 if (WinNtGopConvertParamToEfiKey (Private
, &wParam
, &lParam
, &Key
)) {
826 // Support the partial keystroke, add all keydown event into the queue.
828 GopPrivateAddKey (Private
, Key
);
833 WinNtGopConvertParamToEfiKeyShiftState (Private
, &wParam
, &lParam
, FALSE
);
838 // This close message is issued by user, core is not aware of this,
839 // so don't release the window display resource, just hide the window.
841 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_HIDE
);
845 mWinNt
->DestroyWindow (hwnd
);
846 mWinNt
->PostQuitMessage (0);
848 mWinNt
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
850 mWinNt
->ExitThread (0);
857 return mWinNt
->DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
862 This thread simulates the end of WinMain () aplication. Each Winow nededs
863 to process it's events. The messages are dispatched to
864 WinNtGopThreadWindowProc ().
865 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
866 are running in a seperate thread. We have to do this to process the events.
868 @param lpParameter Handle of window to manage.
870 @return if a WM_QUIT message is returned exit.
875 WinNtGopThreadWinMain (
880 GOP_PRIVATE_DATA
*Private
;
883 Private
= (GOP_PRIVATE_DATA
*) lpParameter
;
884 ASSERT (NULL
!= Private
);
887 // Since each thread has unique private data, save the private data in Thread
888 // Local Storage slot. Then the shared global mTlsIndex can be used to get
889 // thread specific context.
891 Private
->WinNtThunk
->TlsSetValue (mTlsIndex
, Private
);
893 Private
->ThreadId
= Private
->WinNtThunk
->GetCurrentThreadId ();
895 Private
->WindowsClass
.cbSize
= sizeof (WNDCLASSEX
);
896 Private
->WindowsClass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_OWNDC
;
897 Private
->WindowsClass
.lpfnWndProc
= WinNtGopThreadWindowProc
;
898 Private
->WindowsClass
.cbClsExtra
= 0;
899 Private
->WindowsClass
.cbWndExtra
= 0;
900 Private
->WindowsClass
.hInstance
= NULL
;
901 Private
->WindowsClass
.hIcon
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
902 Private
->WindowsClass
.hCursor
= Private
->WinNtThunk
->LoadCursor (NULL
, IDC_ARROW
);
903 Private
->WindowsClass
.hbrBackground
= (HBRUSH
)(UINTN
)COLOR_WINDOW
;
904 Private
->WindowsClass
.lpszMenuName
= NULL
;
905 Private
->WindowsClass
.lpszClassName
= WIN_NT_GOP_CLASS_NAME
;
906 Private
->WindowsClass
.hIconSm
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
909 // This call will fail after the first time, but thats O.K. since we only need
910 // WIN_NT_GOP_CLASS_NAME to exist to create the window.
912 // Note: Multiple instances of this DLL will use the same instance of this
913 // Class, including the callback function, unless the Class is unregistered and
914 // successfully registered again.
916 Private
->WinNtThunk
->RegisterClassEx (&Private
->WindowsClass
);
919 // Setting Rect values to allow for the AdjustWindowRect to provide
920 // us the correct sizes for the client area when doing the CreateWindowEx
923 Rect
.bottom
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
925 Rect
.right
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
927 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
929 Private
->WindowHandle
= Private
->WinNtThunk
->CreateWindowEx (
931 WIN_NT_GOP_CLASS_NAME
,
936 Rect
.right
- Rect
.left
,
937 Rect
.bottom
- Rect
.top
,
945 // The reset of this thread is the standard winows program. We need a sperate
946 // thread since we must process the message loop to make windows act like
950 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_SHOW
);
951 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
954 // Let the main thread get some work done
956 Private
->WinNtThunk
->ReleaseSemaphore (Private
->ThreadInited
, 1, NULL
);
959 // This is the message loop that all Windows programs need.
961 while (Private
->WinNtThunk
->GetMessage (&Message
, Private
->WindowHandle
, 0, 0)) {
962 Private
->WinNtThunk
->TranslateMessage (&Message
);
963 Private
->WinNtThunk
->DispatchMessage (&Message
);
966 return (DWORD
)Message
.wParam
;
971 TODO: Add function description
973 @param Private TODO: add argument description
974 @param HorizontalResolution TODO: add argument description
975 @param VerticalResolution TODO: add argument description
976 @param ColorDepth TODO: add argument description
977 @param RefreshRate TODO: add argument description
979 @return TODO: add return values
983 WinNtGopStartWindow (
984 IN GOP_PRIVATE_DATA
*Private
,
985 IN UINT32 HorizontalResolution
,
986 IN UINT32 VerticalResolution
,
987 IN UINT32 ColorDepth
,
988 IN UINT32 RefreshRate
994 mWinNt
= Private
->WinNtThunk
;
997 // Initialize a Thread Local Storge variable slot. We use TLS to get the
998 // correct Private data instance into the windows thread.
1000 if (mTlsIndex
== TLS_OUT_OF_INDEXES
) {
1001 ASSERT (0 == mTlsIndexUseCount
);
1002 mTlsIndex
= Private
->WinNtThunk
->TlsAlloc ();
1006 // always increase the use count!
1008 mTlsIndexUseCount
++;
1011 // Register to be notified on exit boot services so we can destroy the window.
1013 Status
= gBS
->CreateEventEx (
1018 &gEfiEventExitBootServicesGuid
,
1019 &mGopScreenExitBootServicesEvent
1022 Private
->ThreadInited
= Private
->WinNtThunk
->CreateSemaphore (NULL
, 0, 1, NULL
);
1023 Private
->ThreadHandle
= Private
->WinNtThunk
->CreateThread (
1026 WinNtGopThreadWinMain
,
1033 // The other thread has entered the windows message loop so we can
1034 // continue our initialization.
1036 Private
->WinNtThunk
->WaitForSingleObject (Private
->ThreadInited
, INFINITE
);
1037 Private
->WinNtThunk
->CloseHandle (Private
->ThreadInited
);
1049 // TODO: Private - add argument and description to function comment
1050 // TODO: EFI_SUCCESS - add return value to function comment
1052 WinNtGopConstructor (
1053 GOP_PRIVATE_DATA
*Private
1056 Private
->ModeData
= mGopModeData
;
1058 Private
->GraphicsOutput
.QueryMode
= WinNtGopQuerytMode
;
1059 Private
->GraphicsOutput
.SetMode
= WinNtGopSetMode
;
1060 Private
->GraphicsOutput
.Blt
= WinNtGopBlt
;
1063 // Allocate buffer for Graphics Output Protocol mode information
1065 Private
->GraphicsOutput
.Mode
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
));
1066 if (Private
->GraphicsOutput
.Mode
== NULL
) {
1067 return EFI_OUT_OF_RESOURCES
;
1069 Private
->GraphicsOutput
.Mode
->Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
1070 if (Private
->GraphicsOutput
.Mode
->Info
== NULL
) {
1071 return EFI_OUT_OF_RESOURCES
;
1074 Private
->GraphicsOutput
.Mode
->MaxMode
= sizeof(mGopModeData
) / sizeof(GOP_MODE_DATA
);
1076 // Till now, we have no idea about the window size.
1078 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1079 Private
->GraphicsOutput
.Mode
->Info
->Version
= 0;
1080 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= 0;
1081 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= 0;
1082 Private
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
1083 Private
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1084 Private
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
1085 Private
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
1087 Private
->HardwareNeedsStarting
= TRUE
;
1088 Private
->FillLine
= NULL
;
1090 WinNtGopInitializeSimpleTextInForWindow (Private
);
1102 // TODO: Private - add argument and description to function comment
1103 // TODO: EFI_SUCCESS - add return value to function comment
1105 WinNtGopDestructor (
1106 GOP_PRIVATE_DATA
*Private
1109 if (!Private
->HardwareNeedsStarting
) {
1111 // BugBug: Shutdown GOP Hardware and any child devices.
1113 Private
->WinNtThunk
->SendMessage (Private
->WindowHandle
, WM_DESTROY
, 0, 0);
1114 Private
->WinNtThunk
->CloseHandle (Private
->ThreadHandle
);
1116 mTlsIndexUseCount
--;
1119 // The callback function for another window could still be called,
1120 // so we need to make sure there are no more users of mTlsIndex.
1122 if (0 == mTlsIndexUseCount
) {
1123 ASSERT (TLS_OUT_OF_INDEXES
!= mTlsIndex
);
1125 Private
->WinNtThunk
->TlsFree (mTlsIndex
);
1126 mTlsIndex
= TLS_OUT_OF_INDEXES
;
1128 Private
->WinNtThunk
->UnregisterClass (
1129 Private
->WindowsClass
.lpszClassName
,
1130 Private
->WindowsClass
.hInstance
1134 WinNtGopDestroySimpleTextInForWindow (Private
);
1138 // Free graphics output protocol occupied resource
1140 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
1141 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1142 FreePool (Private
->GraphicsOutput
.Mode
->Info
);
1144 FreePool (Private
->GraphicsOutput
.Mode
);
1152 This is the GOP screen's callback notification function for exit-boot-services.
1153 All we do here is call WinNtGopDestructor().
1155 @param Event not used
1156 @param Context pointer to the Private structure.
1168 WinNtGopDestructor (Context
);