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
89 GOP_PRIVATE_DATA
*Private
;
91 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
93 if (Info
== NULL
|| SizeOfInfo
== NULL
|| (UINTN
) ModeNumber
>= This
->Mode
->MaxMode
) {
94 return EFI_INVALID_PARAMETER
;
97 Status
= gBS
->AllocatePool (
99 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
102 if (EFI_ERROR (Status
)) {
106 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
108 (*Info
)->Version
= 0;
109 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
110 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
111 (*Info
)->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
112 (*Info
)->PixelsPerScanLine
= (*Info
)->HorizontalResolution
;
119 Graphics Output protocol interface to set video mode
121 @param This Protocol instance pointer.
122 @param ModeNumber The mode number to be set.
124 @retval EFI_SUCCESS Graphics mode was changed.
125 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
127 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
133 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
138 GOP_PRIVATE_DATA
*Private
;
139 GOP_MODE_DATA
*ModeData
;
140 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill
;
141 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewFillLine
;
147 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
149 if (ModeNumber
>= This
->Mode
->MaxMode
) {
150 return EFI_UNSUPPORTED
;
153 if (ModeNumber
== This
->Mode
->Mode
) {
157 ModeData
= &Private
->ModeData
[ModeNumber
];
158 This
->Mode
->Mode
= ModeNumber
;
159 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
160 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
161 Private
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= ModeData
->HorizontalResolution
;
163 if (Private
->HardwareNeedsStarting
) {
164 Status
= WinNtGopStartWindow (
166 ModeData
->HorizontalResolution
,
167 ModeData
->VerticalResolution
,
168 ModeData
->ColorDepth
,
169 ModeData
->RefreshRate
171 if (EFI_ERROR (Status
)) {
172 return EFI_DEVICE_ERROR
;
175 Private
->HardwareNeedsStarting
= FALSE
;
178 // Change the resolution and resize of the window
182 // Free the old buffer. We do not save the content of the old buffer since the
183 // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
184 // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
186 Private
->WinNtThunk
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
189 // Allocate DIB frame buffer directly from NT for performance enhancement
190 // This buffer is the virtual screen/frame buffer. This buffer is not the
191 // same a a frame buffer. The first row of this buffer will be the bottom
192 // line of the image. This is an artifact of the way we draw to the screen.
194 Size
= ModeData
->HorizontalResolution
* ModeData
->VerticalResolution
* sizeof (RGBQUAD
) + sizeof (BITMAPV4HEADER
);
195 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
196 Private
->WinNtThunk
->GetProcessHeap (),
202 // Update the virtual screen info data structure
204 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
205 Private
->VirtualScreenInfo
->bV4Width
= ModeData
->HorizontalResolution
;
206 Private
->VirtualScreenInfo
->bV4Height
= ModeData
->VerticalResolution
;
207 Private
->VirtualScreenInfo
->bV4Planes
= 1;
208 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
212 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
215 // The rest of the allocated memory block is the virtual screen buffer
217 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
220 // Use the AdjuctWindowRect fuction to calculate the real width and height
221 // of the new window including the border and caption
225 Rect
.right
= ModeData
->HorizontalResolution
;
226 Rect
.bottom
= ModeData
->VerticalResolution
;
228 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
230 Width
= Rect
.right
- Rect
.left
;
231 Height
= Rect
.bottom
- Rect
.top
;
234 // Retrieve the original window position information
236 Private
->WinNtThunk
->GetWindowRect (Private
->WindowHandle
, &Rect
);
239 // Adjust the window size
241 Private
->WinNtThunk
->MoveWindow (Private
->WindowHandle
, Rect
.left
, Rect
.top
, Width
, Height
, TRUE
);
245 Status
= gBS
->AllocatePool (
247 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->HorizontalResolution
,
250 if (EFI_ERROR (Status
)) {
251 return EFI_DEVICE_ERROR
;
254 if (Private
->FillLine
!= NULL
) {
255 gBS
->FreePool (Private
->FillLine
);
258 Private
->FillLine
= NewFillLine
;
271 ModeData
->HorizontalResolution
,
272 ModeData
->VerticalResolution
,
273 ModeData
->HorizontalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
280 Blt pixels from the rectangle (Width X Height) formed by the BltBuffer
281 onto the graphics screen starting a location (X, Y). (0, 0) is defined as
282 the upper left hand side of the screen. (X, Y) can be outside of the
283 current screen geometry and the BltBuffer will be cliped when it is
284 displayed. X and Y can be negative or positive. If Width or Height is
285 bigger than the current video screen the image will be clipped.
287 @param This Protocol instance pointer.
288 @param X X location on graphics screen.
289 @param Y Y location on the graphics screen.
290 @param Width Width of BltBuffer.
291 @param Height Hight of BltBuffer
292 @param BltOperation Operation to perform on BltBuffer and video memory
293 @param BltBuffer Buffer containing data to blt into video buffer.
294 This buffer has a size of
295 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
296 @param SourceX If the BltOperation is a EfiCopyBlt this is the
297 source of the copy. For other BLT operations this
298 argument is not used.
299 @param SourceX If the BltOperation is a EfiCopyBlt this is the
300 source of the copy. For other BLT operations this
301 argument is not used.
303 @retval EFI_SUCCESS The palette is updated with PaletteArray.
304 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
305 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
309 // TODO: SourceY - add argument and description to function comment
310 // TODO: DestinationX - add argument and description to function comment
311 // TODO: DestinationY - add argument and description to function comment
312 // TODO: Delta - add argument and description to function comment
316 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
317 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
318 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
321 IN UINTN DestinationX
,
322 IN UINTN DestinationY
,
325 IN UINTN Delta OPTIONAL
328 GOP_PRIVATE_DATA
*Private
;
334 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
337 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*FillPixel
;
338 UINT32 VerticalResolution
;
339 UINT32 HorizontalResolution
;
341 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
343 if ((BltOperation
< 0) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
344 return EFI_INVALID_PARAMETER
;
347 if (Width
== 0 || Height
== 0) {
348 return EFI_INVALID_PARAMETER
;
351 // If Delta is zero, then the entire BltBuffer is being used, so Delta
352 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
353 // the number of bytes in each row can be computed.
356 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
360 // We need to fill the Virtual Screen buffer with the blt data.
361 // The virtual screen is upside down, as the first row is the bootom row of
364 VerticalResolution
= This
->Mode
->Info
->VerticalResolution
;
365 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
366 if (BltOperation
== EfiBltVideoToBltBuffer
) {
369 // Video to BltBuffer: Source is Video, destination is BltBuffer
371 if (SourceY
+ Height
> VerticalResolution
) {
372 return EFI_INVALID_PARAMETER
;
375 if (SourceX
+ Width
> HorizontalResolution
) {
376 return EFI_INVALID_PARAMETER
;
379 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
380 // We would not want a timer based event (Cursor, ...) to come in while we are
381 // doing this operation.
383 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
385 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
386 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (DstY
* Delta
) + DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
387 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
388 CopyMem (Blt
, VScreen
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * Width
);
392 // BltBuffer to Video: Source is BltBuffer, destination is Video
394 if (DestinationY
+ Height
> VerticalResolution
) {
395 return EFI_INVALID_PARAMETER
;
398 if (DestinationX
+ Width
> HorizontalResolution
) {
399 return EFI_INVALID_PARAMETER
;
403 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
404 // We would not want a timer based event (Cursor, ...) to come in while we are
405 // doing this operation.
407 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
409 if (BltOperation
== EfiBltVideoFill
) {
410 FillPixel
= BltBuffer
;
411 for (Index
= 0; Index
< Width
; Index
++) {
412 Private
->FillLine
[Index
] = *FillPixel
;
416 for (Index
= 0; Index
< Height
; Index
++) {
417 if (DestinationY
<= SourceY
) {
418 SrcY
= SourceY
+ Index
;
419 DstY
= DestinationY
+ Index
;
421 SrcY
= SourceY
+ Height
- Index
- 1;
422 DstY
= DestinationY
+ Height
- Index
- 1;
425 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- DstY
- 1) * HorizontalResolution
+ DestinationX
];
426 switch (BltOperation
) {
427 case EfiBltBufferToVideo
:
428 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (SrcY
* Delta
) + SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
429 CopyMem (VScreen
, Blt
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
432 case EfiBltVideoToVideo
:
433 VScreenSrc
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
434 CopyMem (VScreen
, VScreenSrc
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
437 case EfiBltVideoFill
:
438 CopyMem (VScreen
, Private
->FillLine
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
444 if (BltOperation
!= EfiBltVideoToBltBuffer
) {
446 // Mark the area we just blted as Invalid so WM_PAINT will update.
448 Rect
.left
= DestinationX
;
449 Rect
.top
= DestinationY
;
450 Rect
.right
= DestinationX
+ Width
;
451 Rect
.bottom
= DestinationY
+ Height
;
452 Private
->WinNtThunk
->InvalidateRect (Private
->WindowHandle
, &Rect
, FALSE
);
455 // Send the WM_PAINT message to the thread that is drawing the window. We
456 // are in the main thread and the window drawing is in a child thread.
457 // There is a child thread per window. We have no CriticalSection or Mutex
458 // since we write the data and the other thread displays the data. While
459 // we may miss some data for a short period of time this is no different than
460 // a write combining on writes to a frame buffer.
463 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
466 gBS
->RestoreTPL (OriginalTPL
);
472 // Construction and Destruction functions
482 // TODO: WinNtIo - add argument and description to function comment
483 // TODO: EFI_UNSUPPORTED - add return value to function comment
484 // TODO: EFI_SUCCESS - add return value to function comment
487 IN EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
491 // Check to see if the IO abstraction represents a device type we support.
493 // This would be replaced a check of PCI subsystem ID, etc.
495 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtGopGuid
)) {
496 return EFI_UNSUPPORTED
;
504 Win32 Windows event handler.
508 @return See Win32 Book
511 // TODO: hwnd - add argument and description to function comment
512 // TODO: iMsg - add argument and description to function comment
513 // TODO: wParam - add argument and description to function comment
514 // TODO: lParam - add argument and description to function comment
517 WinNtGopThreadWindowProc (
524 GOP_PRIVATE_DATA
*Private
;
527 PAINTSTRUCT PaintStruct
;
532 // BugBug - if there are two instances of this DLL in memory (such as is
533 // the case for ERM), the correct instance of this function may not be called.
534 // This also means that the address of the mTlsIndex value will be wrong, and
535 // the value may be wrong too.
540 // Use mTlsIndex global to get a Thread Local Storage version of Private.
541 // This works since each Gop protocol has a unique Private data instance and
544 Private
= mWinNt
->TlsGetValue (mTlsIndex
);
545 ASSERT (NULL
!= Private
);
549 Size
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
* Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
* sizeof (RGBQUAD
);
552 // Allocate DIB frame buffer directly from NT for performance enhancement
553 // This buffer is the virtual screen/frame buffer. This buffer is not the
554 // same a a frame buffer. The first fow of this buffer will be the bottom
555 // line of the image. This is an artifact of the way we draw to the screen.
557 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
558 Private
->WinNtThunk
->GetProcessHeap (),
563 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
564 Private
->VirtualScreenInfo
->bV4Width
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
565 Private
->VirtualScreenInfo
->bV4Height
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
566 Private
->VirtualScreenInfo
->bV4Planes
= 1;
567 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
571 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
572 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
577 // I have not found a way to convert hwnd into a Private context. So for
578 // now we use this API to convert hwnd to Private data.
581 Handle
= mWinNt
->BeginPaint (hwnd
, &PaintStruct
);
583 mWinNt
->SetDIBitsToDevice (
584 Handle
, // Destination Device Context
585 0, // Destination X - 0
586 0, // Destination Y - 0
587 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
, // Width
588 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Height
591 0, // DIB Start Scan Line
592 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Number of scan lines
593 Private
->VirtualScreen
, // Address of array of DIB bits
594 (BITMAPINFO
*) Private
->VirtualScreenInfo
, // Address of structure with bitmap info
595 DIB_RGB_COLORS
// RGB or palette indexes
598 mWinNt
->EndPaint (hwnd
, &PaintStruct
);
602 // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case
608 Key
.ScanCode
= SCAN_F10
;
610 GopPrivateAddQ (Private
, Key
);
618 case VK_HOME
: Key
.ScanCode
= SCAN_HOME
; break;
619 case VK_END
: Key
.ScanCode
= SCAN_END
; break;
620 case VK_LEFT
: Key
.ScanCode
= SCAN_LEFT
; break;
621 case VK_RIGHT
: Key
.ScanCode
= SCAN_RIGHT
; break;
622 case VK_UP
: Key
.ScanCode
= SCAN_UP
; break;
623 case VK_DOWN
: Key
.ScanCode
= SCAN_DOWN
; break;
624 case VK_DELETE
: Key
.ScanCode
= SCAN_DELETE
; break;
625 case VK_INSERT
: Key
.ScanCode
= SCAN_INSERT
; break;
626 case VK_PRIOR
: Key
.ScanCode
= SCAN_PAGE_UP
; break;
627 case VK_NEXT
: Key
.ScanCode
= SCAN_PAGE_DOWN
; break;
628 case VK_ESCAPE
: Key
.ScanCode
= SCAN_ESC
; break;
630 case VK_F1
: Key
.ScanCode
= SCAN_F1
; break;
631 case VK_F2
: Key
.ScanCode
= SCAN_F2
; break;
632 case VK_F3
: Key
.ScanCode
= SCAN_F3
; break;
633 case VK_F4
: Key
.ScanCode
= SCAN_F4
; break;
634 case VK_F5
: Key
.ScanCode
= SCAN_F5
; break;
635 case VK_F6
: Key
.ScanCode
= SCAN_F6
; break;
636 case VK_F7
: Key
.ScanCode
= SCAN_F7
; break;
637 case VK_F8
: Key
.ScanCode
= SCAN_F8
; break;
638 case VK_F9
: Key
.ScanCode
= SCAN_F9
; break;
639 case VK_F11
: Key
.ScanCode
= SCAN_F11
; break;
640 case VK_F12
: Key
.ScanCode
= SCAN_F12
; break;
643 if (Key
.ScanCode
!= 0) {
645 GopPrivateAddQ (Private
, Key
);
652 // The ESC key also generate WM_CHAR.
654 if (wParam
== 0x1B) {
658 for (Index
= 0; Index
< (lParam
& 0xffff); Index
++) {
660 Key
.UnicodeChar
= (CHAR16
) wParam
;
662 GopPrivateAddQ (Private
, Key
);
670 // This close message is issued by user, core is not aware of this,
671 // so don't release the window display resource, just hide the window.
673 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_HIDE
);
677 mWinNt
->DestroyWindow (hwnd
);
678 mWinNt
->PostQuitMessage (0);
680 mWinNt
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
682 mWinNt
->ExitThread (0);
689 return mWinNt
->DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
694 This thread simulates the end of WinMain () aplication. Each Winow nededs
695 to process it's events. The messages are dispatched to
696 WinNtGopThreadWindowProc ().
697 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
698 are running in a seperate thread. We have to do this to process the events.
700 @param lpParameter Handle of window to manage.
702 @return if a WM_QUIT message is returned exit.
707 WinNtGopThreadWinMain (
712 GOP_PRIVATE_DATA
*Private
;
716 Private
= (GOP_PRIVATE_DATA
*) lpParameter
;
717 ASSERT (NULL
!= Private
);
720 // Since each thread has unique private data, save the private data in Thread
721 // Local Storage slot. Then the shared global mTlsIndex can be used to get
722 // thread specific context.
724 Private
->WinNtThunk
->TlsSetValue (mTlsIndex
, Private
);
726 Private
->ThreadId
= Private
->WinNtThunk
->GetCurrentThreadId ();
728 Private
->WindowsClass
.cbSize
= sizeof (WNDCLASSEX
);
729 Private
->WindowsClass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_OWNDC
;
730 Private
->WindowsClass
.lpfnWndProc
= WinNtGopThreadWindowProc
;
731 Private
->WindowsClass
.cbClsExtra
= 0;
732 Private
->WindowsClass
.cbWndExtra
= 0;
733 Private
->WindowsClass
.hInstance
= NULL
;
734 Private
->WindowsClass
.hIcon
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
735 Private
->WindowsClass
.hCursor
= Private
->WinNtThunk
->LoadCursor (NULL
, IDC_ARROW
);
736 Private
->WindowsClass
.hbrBackground
= (HBRUSH
) COLOR_WINDOW
;
737 Private
->WindowsClass
.lpszMenuName
= NULL
;
738 Private
->WindowsClass
.lpszClassName
= WIN_NT_GOP_CLASS_NAME
;
739 Private
->WindowsClass
.hIconSm
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
742 // This call will fail after the first time, but thats O.K. since we only need
743 // WIN_NT_GOP_CLASS_NAME to exist to create the window.
745 // Note: Multiple instances of this DLL will use the same instance of this
746 // Class, including the callback function, unless the Class is unregistered and
747 // successfully registered again.
749 Atom
= Private
->WinNtThunk
->RegisterClassEx (&Private
->WindowsClass
);
752 // Setting Rect values to allow for the AdjustWindowRect to provide
753 // us the correct sizes for the client area when doing the CreateWindowEx
756 Rect
.bottom
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
758 Rect
.right
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
760 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
762 Private
->WindowHandle
= Private
->WinNtThunk
->CreateWindowEx (
764 WIN_NT_GOP_CLASS_NAME
,
769 Rect
.right
- Rect
.left
,
770 Rect
.bottom
- Rect
.top
,
778 // The reset of this thread is the standard winows program. We need a sperate
779 // thread since we must process the message loop to make windows act like
783 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_SHOW
);
784 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
787 // Let the main thread get some work done
789 Private
->WinNtThunk
->ReleaseSemaphore (Private
->ThreadInited
, 1, NULL
);
792 // This is the message loop that all Windows programs need.
794 while (Private
->WinNtThunk
->GetMessage (&Message
, Private
->WindowHandle
, 0, 0)) {
795 Private
->WinNtThunk
->TranslateMessage (&Message
);
796 Private
->WinNtThunk
->DispatchMessage (&Message
);
799 return Message
.wParam
;
804 TODO: Add function description
806 @param Private TODO: add argument description
807 @param HorizontalResolution TODO: add argument description
808 @param VerticalResolution TODO: add argument description
809 @param ColorDepth TODO: add argument description
810 @param RefreshRate TODO: add argument description
812 @return TODO: add return values
816 WinNtGopStartWindow (
817 IN GOP_PRIVATE_DATA
*Private
,
818 IN UINT32 HorizontalResolution
,
819 IN UINT32 VerticalResolution
,
820 IN UINT32 ColorDepth
,
821 IN UINT32 RefreshRate
827 mWinNt
= Private
->WinNtThunk
;
830 // Initialize a Thread Local Storge variable slot. We use TLS to get the
831 // correct Private data instance into the windows thread.
833 if (mTlsIndex
== TLS_OUT_OF_INDEXES
) {
834 ASSERT (0 == mTlsIndexUseCount
);
835 mTlsIndex
= Private
->WinNtThunk
->TlsAlloc ();
839 // always increase the use count!
844 // Register to be notified on exit boot services so we can destroy the window.
846 Status
= gBS
->CreateEvent (
847 EVENT_SIGNAL_EXIT_BOOT_SERVICES
,
851 &mGopScreenExitBootServicesEvent
854 Private
->ThreadInited
= Private
->WinNtThunk
->CreateSemaphore (NULL
, 0, 1, NULL
);
855 Private
->ThreadHandle
= Private
->WinNtThunk
->CreateThread (
858 WinNtGopThreadWinMain
,
865 // The other thread has entered the windows message loop so we can
866 // continue our initialization.
868 Private
->WinNtThunk
->WaitForSingleObject (Private
->ThreadInited
, INFINITE
);
869 Private
->WinNtThunk
->CloseHandle (Private
->ThreadInited
);
881 // TODO: Private - add argument and description to function comment
882 // TODO: EFI_SUCCESS - add return value to function comment
884 WinNtGopConstructor (
885 GOP_PRIVATE_DATA
*Private
890 Private
->ModeData
= mGopModeData
;
892 Private
->GraphicsOutput
.QueryMode
= WinNtGopQuerytMode
;
893 Private
->GraphicsOutput
.SetMode
= WinNtGopSetMode
;
894 Private
->GraphicsOutput
.Blt
= WinNtGopBlt
;
897 // Allocate buffer for Graphics Output Protocol mode information
899 Status
= gBS
->AllocatePool (
901 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
902 (VOID
**) &Private
->GraphicsOutput
.Mode
904 if (EFI_ERROR (Status
)) {
907 Status
= gBS
->AllocatePool (
909 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
910 (VOID
**) &Private
->GraphicsOutput
.Mode
->Info
912 if (EFI_ERROR (Status
)) {
915 Private
->GraphicsOutput
.Mode
->MaxMode
= sizeof(mGopModeData
) / sizeof(GOP_MODE_DATA
);
917 // Till now, we have no idea about the window size.
919 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
920 Private
->GraphicsOutput
.Mode
->Info
->Version
= 0;
921 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= 0;
922 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= 0;
923 Private
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
924 Private
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
925 Private
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
926 Private
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
928 Private
->HardwareNeedsStarting
= TRUE
;
929 Private
->FillLine
= NULL
;
931 WinNtGopInitializeSimpleTextInForWindow (Private
);
943 // TODO: Private - add argument and description to function comment
944 // TODO: EFI_SUCCESS - add return value to function comment
947 GOP_PRIVATE_DATA
*Private
950 UINT32 UnregisterReturn
;
952 if (!Private
->HardwareNeedsStarting
) {
954 // BugBug: Shutdown GOP Hardware and any child devices.
956 Private
->WinNtThunk
->SendMessage (Private
->WindowHandle
, WM_DESTROY
, 0, 0);
957 Private
->WinNtThunk
->CloseHandle (Private
->ThreadHandle
);
962 // The callback function for another window could still be called,
963 // so we need to make sure there are no more users of mTlsIndex.
965 if (0 == mTlsIndexUseCount
) {
966 ASSERT (TLS_OUT_OF_INDEXES
!= mTlsIndex
);
968 Private
->WinNtThunk
->TlsFree (mTlsIndex
);
969 mTlsIndex
= TLS_OUT_OF_INDEXES
;
971 UnregisterReturn
= Private
->WinNtThunk
->UnregisterClass (
972 Private
->WindowsClass
.lpszClassName
,
973 Private
->WindowsClass
.hInstance
977 WinNtGopDestroySimpleTextInForWindow (Private
);
981 // Free graphics output protocol occupied resource
983 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
984 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
985 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
987 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);
995 This is the GOP screen's callback notification function for exit-boot-services.
996 All we do here is call WinNtGopDestructor().
998 @param Event not used
999 @param Context pointer to the Private structure.
1013 Status
= WinNtGopDestructor (Context
);