3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. 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 EFI 1.1 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 static EFI_EVENT mGopScreenExitBootServicesEvent
;
31 GOP_MODE_DATA mGopModeData
[] = {
41 IN GOP_PRIVATE_DATA
*Private
,
42 IN UINT32 HorizontalResolution
,
43 IN UINT32 VerticalResolution
,
57 // GOP Protocol Member Functions
62 Graphics Output protocol interface to get video mode
64 @param This Protocol instance pointer.
65 @param ModeNumber The mode number to return information on.
66 @param Info Caller allocated buffer that returns information
68 @param SizeOfInfo A pointer to the size, in bytes, of the Info
71 @retval EFI_SUCCESS Mode information returned.
72 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
73 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
75 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
76 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
82 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
84 OUT UINTN
*SizeOfInfo
,
85 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
88 GOP_PRIVATE_DATA
*Private
;
90 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
92 if (Info
== NULL
|| SizeOfInfo
== NULL
|| (UINTN
) ModeNumber
>= This
->Mode
->MaxMode
) {
93 return EFI_INVALID_PARAMETER
;
96 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
98 return EFI_OUT_OF_RESOURCES
;
101 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
103 (*Info
)->Version
= 0;
104 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
105 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
106 (*Info
)->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
107 (*Info
)->PixelsPerScanLine
= (*Info
)->HorizontalResolution
;
114 Graphics Output protocol interface to set video mode
116 @param This Protocol instance pointer.
117 @param ModeNumber The mode number to be set.
119 @retval EFI_SUCCESS Graphics mode was changed.
120 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
122 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
128 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
133 GOP_PRIVATE_DATA
*Private
;
134 GOP_MODE_DATA
*ModeData
;
135 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill
;
136 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewFillLine
;
142 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
144 if (ModeNumber
>= This
->Mode
->MaxMode
) {
145 return EFI_UNSUPPORTED
;
148 if (ModeNumber
== This
->Mode
->Mode
) {
152 ModeData
= &Private
->ModeData
[ModeNumber
];
153 This
->Mode
->Mode
= ModeNumber
;
154 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
155 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
156 Private
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= ModeData
->HorizontalResolution
;
158 if (Private
->HardwareNeedsStarting
) {
159 Status
= WinNtGopStartWindow (
161 ModeData
->HorizontalResolution
,
162 ModeData
->VerticalResolution
,
163 ModeData
->ColorDepth
,
164 ModeData
->RefreshRate
166 if (EFI_ERROR (Status
)) {
167 return EFI_DEVICE_ERROR
;
170 Private
->HardwareNeedsStarting
= FALSE
;
173 // Change the resolution and resize of the window
177 // Free the old buffer. We do not save the content of the old buffer since the
178 // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
179 // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
181 Private
->WinNtThunk
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
184 // Allocate DIB frame buffer directly from NT for performance enhancement
185 // This buffer is the virtual screen/frame buffer. This buffer is not the
186 // same a a frame buffer. The first row of this buffer will be the bottom
187 // line of the image. This is an artifact of the way we draw to the screen.
189 Size
= ModeData
->HorizontalResolution
* ModeData
->VerticalResolution
* sizeof (RGBQUAD
) + sizeof (BITMAPV4HEADER
);
190 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
191 Private
->WinNtThunk
->GetProcessHeap (),
197 // Update the virtual screen info data structure
199 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
200 Private
->VirtualScreenInfo
->bV4Width
= ModeData
->HorizontalResolution
;
201 Private
->VirtualScreenInfo
->bV4Height
= ModeData
->VerticalResolution
;
202 Private
->VirtualScreenInfo
->bV4Planes
= 1;
203 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
207 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
210 // The rest of the allocated memory block is the virtual screen buffer
212 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
215 // Use the AdjuctWindowRect fuction to calculate the real width and height
216 // of the new window including the border and caption
220 Rect
.right
= ModeData
->HorizontalResolution
;
221 Rect
.bottom
= ModeData
->VerticalResolution
;
223 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
225 Width
= Rect
.right
- Rect
.left
;
226 Height
= Rect
.bottom
- Rect
.top
;
229 // Retrieve the original window position information
231 Private
->WinNtThunk
->GetWindowRect (Private
->WindowHandle
, &Rect
);
234 // Adjust the window size
236 Private
->WinNtThunk
->MoveWindow (Private
->WindowHandle
, Rect
.left
, Rect
.top
, Width
, Height
, TRUE
);
240 NewFillLine
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->HorizontalResolution
);
241 if (NewFillLine
== NULL
) {
242 return EFI_DEVICE_ERROR
;
245 if (Private
->FillLine
!= NULL
) {
246 FreePool (Private
->FillLine
);
249 Private
->FillLine
= NewFillLine
;
262 ModeData
->HorizontalResolution
,
263 ModeData
->VerticalResolution
,
264 ModeData
->HorizontalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
271 Blt pixels from the rectangle (Width X Height) formed by the BltBuffer
272 onto the graphics screen starting a location (X, Y). (0, 0) is defined as
273 the upper left hand side of the screen. (X, Y) can be outside of the
274 current screen geometry and the BltBuffer will be cliped when it is
275 displayed. X and Y can be negative or positive. If Width or Height is
276 bigger than the current video screen the image will be clipped.
278 @param This Protocol instance pointer.
279 @param X X location on graphics screen.
280 @param Y Y location on the graphics screen.
281 @param Width Width of BltBuffer.
282 @param Height Hight of BltBuffer
283 @param BltOperation Operation to perform on BltBuffer and video memory
284 @param BltBuffer Buffer containing data to blt into video buffer.
285 This buffer has a size of
286 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
287 @param SourceX If the BltOperation is a EfiCopyBlt this is the
288 source of the copy. For other BLT operations this
289 argument is not used.
290 @param SourceX If the BltOperation is a EfiCopyBlt this is the
291 source of the copy. For other BLT operations this
292 argument is not used.
294 @retval EFI_SUCCESS The palette is updated with PaletteArray.
295 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
296 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
300 // TODO: SourceY - add argument and description to function comment
301 // TODO: DestinationX - add argument and description to function comment
302 // TODO: DestinationY - add argument and description to function comment
303 // TODO: Delta - add argument and description to function comment
307 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
308 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
309 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
312 IN UINTN DestinationX
,
313 IN UINTN DestinationY
,
316 IN UINTN Delta OPTIONAL
319 GOP_PRIVATE_DATA
*Private
;
325 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
328 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*FillPixel
;
329 UINT32 VerticalResolution
;
330 UINT32 HorizontalResolution
;
332 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
334 if ((BltOperation
< 0) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
335 return EFI_INVALID_PARAMETER
;
338 if (Width
== 0 || Height
== 0) {
339 return EFI_INVALID_PARAMETER
;
342 // If Delta is zero, then the entire BltBuffer is being used, so Delta
343 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
344 // the number of bytes in each row can be computed.
347 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
351 // We need to fill the Virtual Screen buffer with the blt data.
352 // The virtual screen is upside down, as the first row is the bootom row of
355 VerticalResolution
= This
->Mode
->Info
->VerticalResolution
;
356 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
357 if (BltOperation
== EfiBltVideoToBltBuffer
) {
360 // Video to BltBuffer: Source is Video, destination is BltBuffer
362 if (SourceY
+ Height
> VerticalResolution
) {
363 return EFI_INVALID_PARAMETER
;
366 if (SourceX
+ Width
> HorizontalResolution
) {
367 return EFI_INVALID_PARAMETER
;
370 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
371 // We would not want a timer based event (Cursor, ...) to come in while we are
372 // doing this operation.
374 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
376 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
377 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (DstY
* Delta
) + DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
378 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
379 CopyMem (Blt
, VScreen
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * Width
);
383 // BltBuffer to Video: Source is BltBuffer, destination is Video
385 if (DestinationY
+ Height
> VerticalResolution
) {
386 return EFI_INVALID_PARAMETER
;
389 if (DestinationX
+ Width
> HorizontalResolution
) {
390 return EFI_INVALID_PARAMETER
;
394 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
395 // We would not want a timer based event (Cursor, ...) to come in while we are
396 // doing this operation.
398 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
400 if (BltOperation
== EfiBltVideoFill
) {
401 FillPixel
= BltBuffer
;
402 for (Index
= 0; Index
< Width
; Index
++) {
403 Private
->FillLine
[Index
] = *FillPixel
;
407 for (Index
= 0; Index
< Height
; Index
++) {
408 if (DestinationY
<= SourceY
) {
409 SrcY
= SourceY
+ Index
;
410 DstY
= DestinationY
+ Index
;
412 SrcY
= SourceY
+ Height
- Index
- 1;
413 DstY
= DestinationY
+ Height
- Index
- 1;
416 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- DstY
- 1) * HorizontalResolution
+ DestinationX
];
417 switch (BltOperation
) {
418 case EfiBltBufferToVideo
:
419 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (SrcY
* Delta
) + SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
420 CopyMem (VScreen
, Blt
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
423 case EfiBltVideoToVideo
:
424 VScreenSrc
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
425 CopyMem (VScreen
, VScreenSrc
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
428 case EfiBltVideoFill
:
429 CopyMem (VScreen
, Private
->FillLine
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
435 if (BltOperation
!= EfiBltVideoToBltBuffer
) {
437 // Mark the area we just blted as Invalid so WM_PAINT will update.
439 Rect
.left
= DestinationX
;
440 Rect
.top
= DestinationY
;
441 Rect
.right
= DestinationX
+ Width
;
442 Rect
.bottom
= DestinationY
+ Height
;
443 Private
->WinNtThunk
->InvalidateRect (Private
->WindowHandle
, &Rect
, FALSE
);
446 // Send the WM_PAINT message to the thread that is drawing the window. We
447 // are in the main thread and the window drawing is in a child thread.
448 // There is a child thread per window. We have no CriticalSection or Mutex
449 // since we write the data and the other thread displays the data. While
450 // we may miss some data for a short period of time this is no different than
451 // a write combining on writes to a frame buffer.
454 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
457 gBS
->RestoreTPL (OriginalTPL
);
463 // Construction and Destruction functions
473 // TODO: WinNtIo - add argument and description to function comment
474 // TODO: EFI_UNSUPPORTED - add return value to function comment
475 // TODO: EFI_SUCCESS - add return value to function comment
478 IN EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
482 // Check to see if the IO abstraction represents a device type we support.
484 // This would be replaced a check of PCI subsystem ID, etc.
486 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtGopGuid
)) {
487 return EFI_UNSUPPORTED
;
495 Win32 Windows event handler.
499 @return See Win32 Book
502 // TODO: hwnd - add argument and description to function comment
503 // TODO: iMsg - add argument and description to function comment
504 // TODO: wParam - add argument and description to function comment
505 // TODO: lParam - add argument and description to function comment
508 WinNtGopThreadWindowProc (
515 GOP_PRIVATE_DATA
*Private
;
518 PAINTSTRUCT PaintStruct
;
523 // BugBug - if there are two instances of this DLL in memory (such as is
524 // the case for ERM), the correct instance of this function may not be called.
525 // This also means that the address of the mTlsIndex value will be wrong, and
526 // the value may be wrong too.
531 // Use mTlsIndex global to get a Thread Local Storage version of Private.
532 // This works since each Gop protocol has a unique Private data instance and
535 Private
= mWinNt
->TlsGetValue (mTlsIndex
);
536 ASSERT (NULL
!= Private
);
540 Size
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
* Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
* sizeof (RGBQUAD
);
543 // Allocate DIB frame buffer directly from NT for performance enhancement
544 // This buffer is the virtual screen/frame buffer. This buffer is not the
545 // same a a frame buffer. The first fow of this buffer will be the bottom
546 // line of the image. This is an artifact of the way we draw to the screen.
548 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
549 Private
->WinNtThunk
->GetProcessHeap (),
554 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
555 Private
->VirtualScreenInfo
->bV4Width
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
556 Private
->VirtualScreenInfo
->bV4Height
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
557 Private
->VirtualScreenInfo
->bV4Planes
= 1;
558 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
562 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
563 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
568 // I have not found a way to convert hwnd into a Private context. So for
569 // now we use this API to convert hwnd to Private data.
572 Handle
= mWinNt
->BeginPaint (hwnd
, &PaintStruct
);
574 mWinNt
->SetDIBitsToDevice (
575 Handle
, // Destination Device Context
576 0, // Destination X - 0
577 0, // Destination Y - 0
578 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
, // Width
579 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Height
582 0, // DIB Start Scan Line
583 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Number of scan lines
584 Private
->VirtualScreen
, // Address of array of DIB bits
585 (BITMAPINFO
*) Private
->VirtualScreenInfo
, // Address of structure with bitmap info
586 DIB_RGB_COLORS
// RGB or palette indexes
589 mWinNt
->EndPaint (hwnd
, &PaintStruct
);
593 // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case
599 Key
.ScanCode
= SCAN_F10
;
601 GopPrivateAddQ (Private
, Key
);
609 case VK_HOME
: Key
.ScanCode
= SCAN_HOME
; break;
610 case VK_END
: Key
.ScanCode
= SCAN_END
; break;
611 case VK_LEFT
: Key
.ScanCode
= SCAN_LEFT
; break;
612 case VK_RIGHT
: Key
.ScanCode
= SCAN_RIGHT
; break;
613 case VK_UP
: Key
.ScanCode
= SCAN_UP
; break;
614 case VK_DOWN
: Key
.ScanCode
= SCAN_DOWN
; break;
615 case VK_DELETE
: Key
.ScanCode
= SCAN_DELETE
; break;
616 case VK_INSERT
: Key
.ScanCode
= SCAN_INSERT
; break;
617 case VK_PRIOR
: Key
.ScanCode
= SCAN_PAGE_UP
; break;
618 case VK_NEXT
: Key
.ScanCode
= SCAN_PAGE_DOWN
; break;
619 case VK_ESCAPE
: Key
.ScanCode
= SCAN_ESC
; break;
621 case VK_F1
: Key
.ScanCode
= SCAN_F1
; break;
622 case VK_F2
: Key
.ScanCode
= SCAN_F2
; break;
623 case VK_F3
: Key
.ScanCode
= SCAN_F3
; break;
624 case VK_F4
: Key
.ScanCode
= SCAN_F4
; break;
625 case VK_F5
: Key
.ScanCode
= SCAN_F5
; break;
626 case VK_F6
: Key
.ScanCode
= SCAN_F6
; break;
627 case VK_F7
: Key
.ScanCode
= SCAN_F7
; break;
628 case VK_F8
: Key
.ScanCode
= SCAN_F8
; break;
629 case VK_F9
: Key
.ScanCode
= SCAN_F9
; break;
630 case VK_F11
: Key
.ScanCode
= SCAN_F11
; break;
631 case VK_F12
: Key
.ScanCode
= SCAN_F12
; break;
634 if (Key
.ScanCode
!= 0) {
636 GopPrivateAddQ (Private
, Key
);
643 // The ESC key also generate WM_CHAR.
645 if (wParam
== 0x1B) {
649 for (Index
= 0; Index
< (lParam
& 0xffff); Index
++) {
651 Key
.UnicodeChar
= (CHAR16
) wParam
;
653 GopPrivateAddQ (Private
, Key
);
661 // This close message is issued by user, core is not aware of this,
662 // so don't release the window display resource, just hide the window.
664 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_HIDE
);
668 mWinNt
->DestroyWindow (hwnd
);
669 mWinNt
->PostQuitMessage (0);
671 mWinNt
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
673 mWinNt
->ExitThread (0);
680 return mWinNt
->DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
685 This thread simulates the end of WinMain () aplication. Each Winow nededs
686 to process it's events. The messages are dispatched to
687 WinNtGopThreadWindowProc ().
688 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
689 are running in a seperate thread. We have to do this to process the events.
691 @param lpParameter Handle of window to manage.
693 @return if a WM_QUIT message is returned exit.
698 WinNtGopThreadWinMain (
703 GOP_PRIVATE_DATA
*Private
;
707 Private
= (GOP_PRIVATE_DATA
*) lpParameter
;
708 ASSERT (NULL
!= Private
);
711 // Since each thread has unique private data, save the private data in Thread
712 // Local Storage slot. Then the shared global mTlsIndex can be used to get
713 // thread specific context.
715 Private
->WinNtThunk
->TlsSetValue (mTlsIndex
, Private
);
717 Private
->ThreadId
= Private
->WinNtThunk
->GetCurrentThreadId ();
719 Private
->WindowsClass
.cbSize
= sizeof (WNDCLASSEX
);
720 Private
->WindowsClass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_OWNDC
;
721 Private
->WindowsClass
.lpfnWndProc
= WinNtGopThreadWindowProc
;
722 Private
->WindowsClass
.cbClsExtra
= 0;
723 Private
->WindowsClass
.cbWndExtra
= 0;
724 Private
->WindowsClass
.hInstance
= NULL
;
725 Private
->WindowsClass
.hIcon
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
726 Private
->WindowsClass
.hCursor
= Private
->WinNtThunk
->LoadCursor (NULL
, IDC_ARROW
);
727 Private
->WindowsClass
.hbrBackground
= (HBRUSH
) COLOR_WINDOW
;
728 Private
->WindowsClass
.lpszMenuName
= NULL
;
729 Private
->WindowsClass
.lpszClassName
= WIN_NT_GOP_CLASS_NAME
;
730 Private
->WindowsClass
.hIconSm
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
733 // This call will fail after the first time, but thats O.K. since we only need
734 // WIN_NT_GOP_CLASS_NAME to exist to create the window.
736 // Note: Multiple instances of this DLL will use the same instance of this
737 // Class, including the callback function, unless the Class is unregistered and
738 // successfully registered again.
740 Atom
= Private
->WinNtThunk
->RegisterClassEx (&Private
->WindowsClass
);
743 // Setting Rect values to allow for the AdjustWindowRect to provide
744 // us the correct sizes for the client area when doing the CreateWindowEx
747 Rect
.bottom
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
749 Rect
.right
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
751 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
753 Private
->WindowHandle
= Private
->WinNtThunk
->CreateWindowEx (
755 WIN_NT_GOP_CLASS_NAME
,
760 Rect
.right
- Rect
.left
,
761 Rect
.bottom
- Rect
.top
,
769 // The reset of this thread is the standard winows program. We need a sperate
770 // thread since we must process the message loop to make windows act like
774 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_SHOW
);
775 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
778 // Let the main thread get some work done
780 Private
->WinNtThunk
->ReleaseSemaphore (Private
->ThreadInited
, 1, NULL
);
783 // This is the message loop that all Windows programs need.
785 while (Private
->WinNtThunk
->GetMessage (&Message
, Private
->WindowHandle
, 0, 0)) {
786 Private
->WinNtThunk
->TranslateMessage (&Message
);
787 Private
->WinNtThunk
->DispatchMessage (&Message
);
790 return Message
.wParam
;
795 TODO: Add function description
797 @param Private TODO: add argument description
798 @param HorizontalResolution TODO: add argument description
799 @param VerticalResolution TODO: add argument description
800 @param ColorDepth TODO: add argument description
801 @param RefreshRate TODO: add argument description
803 @return TODO: add return values
807 WinNtGopStartWindow (
808 IN GOP_PRIVATE_DATA
*Private
,
809 IN UINT32 HorizontalResolution
,
810 IN UINT32 VerticalResolution
,
811 IN UINT32 ColorDepth
,
812 IN UINT32 RefreshRate
818 mWinNt
= Private
->WinNtThunk
;
821 // Initialize a Thread Local Storge variable slot. We use TLS to get the
822 // correct Private data instance into the windows thread.
824 if (mTlsIndex
== TLS_OUT_OF_INDEXES
) {
825 ASSERT (0 == mTlsIndexUseCount
);
826 mTlsIndex
= Private
->WinNtThunk
->TlsAlloc ();
830 // always increase the use count!
835 // Register to be notified on exit boot services so we can destroy the window.
837 Status
= gBS
->CreateEvent (
838 EVENT_SIGNAL_EXIT_BOOT_SERVICES
,
842 &mGopScreenExitBootServicesEvent
845 Private
->ThreadInited
= Private
->WinNtThunk
->CreateSemaphore (NULL
, 0, 1, NULL
);
846 Private
->ThreadHandle
= Private
->WinNtThunk
->CreateThread (
849 WinNtGopThreadWinMain
,
856 // The other thread has entered the windows message loop so we can
857 // continue our initialization.
859 Private
->WinNtThunk
->WaitForSingleObject (Private
->ThreadInited
, INFINITE
);
860 Private
->WinNtThunk
->CloseHandle (Private
->ThreadInited
);
872 // TODO: Private - add argument and description to function comment
873 // TODO: EFI_SUCCESS - add return value to function comment
875 WinNtGopConstructor (
876 GOP_PRIVATE_DATA
*Private
879 Private
->ModeData
= mGopModeData
;
881 Private
->GraphicsOutput
.QueryMode
= WinNtGopQuerytMode
;
882 Private
->GraphicsOutput
.SetMode
= WinNtGopSetMode
;
883 Private
->GraphicsOutput
.Blt
= WinNtGopBlt
;
886 // Allocate buffer for Graphics Output Protocol mode information
888 Private
->GraphicsOutput
.Mode
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
));
889 if (Private
->GraphicsOutput
.Mode
== NULL
) {
890 return EFI_OUT_OF_RESOURCES
;
892 Private
->GraphicsOutput
.Mode
->Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
893 if (Private
->GraphicsOutput
.Mode
->Info
== NULL
) {
894 return EFI_OUT_OF_RESOURCES
;
897 Private
->GraphicsOutput
.Mode
->MaxMode
= sizeof(mGopModeData
) / sizeof(GOP_MODE_DATA
);
899 // Till now, we have no idea about the window size.
901 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
902 Private
->GraphicsOutput
.Mode
->Info
->Version
= 0;
903 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= 0;
904 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= 0;
905 Private
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
906 Private
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
907 Private
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
908 Private
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
910 Private
->HardwareNeedsStarting
= TRUE
;
911 Private
->FillLine
= NULL
;
913 WinNtGopInitializeSimpleTextInForWindow (Private
);
925 // TODO: Private - add argument and description to function comment
926 // TODO: EFI_SUCCESS - add return value to function comment
929 GOP_PRIVATE_DATA
*Private
932 UINT32 UnregisterReturn
;
934 if (!Private
->HardwareNeedsStarting
) {
936 // BugBug: Shutdown GOP Hardware and any child devices.
938 Private
->WinNtThunk
->SendMessage (Private
->WindowHandle
, WM_DESTROY
, 0, 0);
939 Private
->WinNtThunk
->CloseHandle (Private
->ThreadHandle
);
944 // The callback function for another window could still be called,
945 // so we need to make sure there are no more users of mTlsIndex.
947 if (0 == mTlsIndexUseCount
) {
948 ASSERT (TLS_OUT_OF_INDEXES
!= mTlsIndex
);
950 Private
->WinNtThunk
->TlsFree (mTlsIndex
);
951 mTlsIndex
= TLS_OUT_OF_INDEXES
;
953 UnregisterReturn
= Private
->WinNtThunk
->UnregisterClass (
954 Private
->WindowsClass
.lpszClassName
,
955 Private
->WindowsClass
.hInstance
959 WinNtGopDestroySimpleTextInForWindow (Private
);
963 // Free graphics output protocol occupied resource
965 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
966 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
967 FreePool (Private
->GraphicsOutput
.Mode
->Info
);
969 FreePool (Private
->GraphicsOutput
.Mode
);
977 This is the GOP screen's callback notification function for exit-boot-services.
978 All we do here is call WinNtGopDestructor().
980 @param Event not used
981 @param Context pointer to the Private structure.
995 Status
= WinNtGopDestructor (Context
);