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.
25 // The package level header files this module uses
30 // The protocols, PPI and GUID defintions for this module
32 #include <Guid/EventGroup.h>
33 #include <Protocol/WinNtIo.h>
34 #include <Protocol/ComponentName.h>
35 #include <Protocol/SimpleTextIn.h>
36 #include <Protocol/DriverBinding.h>
37 #include <Protocol/GraphicsOutput.h>
39 // The Library classes this module consumes
41 #include <Library/DebugLib.h>
42 #include <Library/BaseLib.h>
43 #include <Library/UefiDriverEntryPoint.h>
44 #include <Library/UefiLib.h>
45 #include <Library/BaseMemoryLib.h>
46 #include <Library/UefiBootServicesTableLib.h>
47 #include <Library/MemoryAllocationLib.h>
51 EFI_WIN_NT_THUNK_PROTOCOL
*mWinNt
;
52 DWORD mTlsIndex
= TLS_OUT_OF_INDEXES
;
53 DWORD mTlsIndexUseCount
= 0; // lets us know when we can free mTlsIndex.
54 static EFI_EVENT mGopScreenExitBootServicesEvent
;
55 GOP_MODE_DATA mGopModeData
[] = {
65 IN GOP_PRIVATE_DATA
*Private
,
66 IN UINT32 HorizontalResolution
,
67 IN UINT32 VerticalResolution
,
81 // GOP Protocol Member Functions
86 Graphics Output protocol interface to get video mode
88 @param This Protocol instance pointer.
89 @param ModeNumber The mode number to return information on.
90 @param Info Caller allocated buffer that returns information
92 @param SizeOfInfo A pointer to the size, in bytes, of the Info
95 @retval EFI_SUCCESS Mode information returned.
96 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
97 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
99 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
100 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
106 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
107 IN UINT32 ModeNumber
,
108 OUT UINTN
*SizeOfInfo
,
109 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
112 GOP_PRIVATE_DATA
*Private
;
114 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
116 if (Info
== NULL
|| SizeOfInfo
== NULL
|| (UINTN
) ModeNumber
>= This
->Mode
->MaxMode
) {
117 return EFI_INVALID_PARAMETER
;
120 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
122 return EFI_OUT_OF_RESOURCES
;
125 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
127 (*Info
)->Version
= 0;
128 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
129 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
130 (*Info
)->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
131 (*Info
)->PixelsPerScanLine
= (*Info
)->HorizontalResolution
;
138 Graphics Output protocol interface to set video mode
140 @param This Protocol instance pointer.
141 @param ModeNumber The mode number to be set.
143 @retval EFI_SUCCESS Graphics mode was changed.
144 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
146 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
152 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
157 GOP_PRIVATE_DATA
*Private
;
158 GOP_MODE_DATA
*ModeData
;
159 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill
;
160 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewFillLine
;
166 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
168 if (ModeNumber
>= This
->Mode
->MaxMode
) {
169 return EFI_UNSUPPORTED
;
172 if (ModeNumber
== This
->Mode
->Mode
) {
176 ModeData
= &Private
->ModeData
[ModeNumber
];
177 This
->Mode
->Mode
= ModeNumber
;
178 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
179 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
180 Private
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= ModeData
->HorizontalResolution
;
182 if (Private
->HardwareNeedsStarting
) {
183 Status
= WinNtGopStartWindow (
185 ModeData
->HorizontalResolution
,
186 ModeData
->VerticalResolution
,
187 ModeData
->ColorDepth
,
188 ModeData
->RefreshRate
190 if (EFI_ERROR (Status
)) {
191 return EFI_DEVICE_ERROR
;
194 Private
->HardwareNeedsStarting
= FALSE
;
197 // Change the resolution and resize of the window
201 // Free the old buffer. We do not save the content of the old buffer since the
202 // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.
203 // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
205 Private
->WinNtThunk
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
208 // Allocate DIB frame buffer directly from NT for performance enhancement
209 // This buffer is the virtual screen/frame buffer. This buffer is not the
210 // same a a frame buffer. The first row of this buffer will be the bottom
211 // line of the image. This is an artifact of the way we draw to the screen.
213 Size
= ModeData
->HorizontalResolution
* ModeData
->VerticalResolution
* sizeof (RGBQUAD
) + sizeof (BITMAPV4HEADER
);
214 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
215 Private
->WinNtThunk
->GetProcessHeap (),
221 // Update the virtual screen info data structure
223 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
224 Private
->VirtualScreenInfo
->bV4Width
= ModeData
->HorizontalResolution
;
225 Private
->VirtualScreenInfo
->bV4Height
= ModeData
->VerticalResolution
;
226 Private
->VirtualScreenInfo
->bV4Planes
= 1;
227 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
231 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
234 // The rest of the allocated memory block is the virtual screen buffer
236 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
239 // Use the AdjuctWindowRect fuction to calculate the real width and height
240 // of the new window including the border and caption
244 Rect
.right
= ModeData
->HorizontalResolution
;
245 Rect
.bottom
= ModeData
->VerticalResolution
;
247 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
249 Width
= Rect
.right
- Rect
.left
;
250 Height
= Rect
.bottom
- Rect
.top
;
253 // Retrieve the original window position information
255 Private
->WinNtThunk
->GetWindowRect (Private
->WindowHandle
, &Rect
);
258 // Adjust the window size
260 Private
->WinNtThunk
->MoveWindow (Private
->WindowHandle
, Rect
.left
, Rect
.top
, Width
, Height
, TRUE
);
264 NewFillLine
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->HorizontalResolution
);
265 if (NewFillLine
== NULL
) {
266 return EFI_DEVICE_ERROR
;
269 if (Private
->FillLine
!= NULL
) {
270 FreePool (Private
->FillLine
);
273 Private
->FillLine
= NewFillLine
;
286 ModeData
->HorizontalResolution
,
287 ModeData
->VerticalResolution
,
288 ModeData
->HorizontalResolution
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
295 Blt pixels from the rectangle (Width X Height) formed by the BltBuffer
296 onto the graphics screen starting a location (X, Y). (0, 0) is defined as
297 the upper left hand side of the screen. (X, Y) can be outside of the
298 current screen geometry and the BltBuffer will be cliped when it is
299 displayed. X and Y can be negative or positive. If Width or Height is
300 bigger than the current video screen the image will be clipped.
302 @param This Protocol instance pointer.
303 @param X X location on graphics screen.
304 @param Y Y location on the graphics screen.
305 @param Width Width of BltBuffer.
306 @param Height Hight of BltBuffer
307 @param BltOperation Operation to perform on BltBuffer and video memory
308 @param BltBuffer Buffer containing data to blt into video buffer.
309 This buffer has a size of
310 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
311 @param SourceX If the BltOperation is a EfiCopyBlt this is the
312 source of the copy. For other BLT operations this
313 argument is not used.
314 @param SourceX If the BltOperation is a EfiCopyBlt this is the
315 source of the copy. For other BLT operations this
316 argument is not used.
318 @retval EFI_SUCCESS The palette is updated with PaletteArray.
319 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
320 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
324 // TODO: SourceY - add argument and description to function comment
325 // TODO: DestinationX - add argument and description to function comment
326 // TODO: DestinationY - add argument and description to function comment
327 // TODO: Delta - add argument and description to function comment
331 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
332 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
333 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
336 IN UINTN DestinationX
,
337 IN UINTN DestinationY
,
340 IN UINTN Delta OPTIONAL
343 GOP_PRIVATE_DATA
*Private
;
349 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
352 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*FillPixel
;
353 UINT32 VerticalResolution
;
354 UINT32 HorizontalResolution
;
356 Private
= GOP_PRIVATE_DATA_FROM_THIS (This
);
358 if ((BltOperation
< 0) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
359 return EFI_INVALID_PARAMETER
;
362 if (Width
== 0 || Height
== 0) {
363 return EFI_INVALID_PARAMETER
;
366 // If Delta is zero, then the entire BltBuffer is being used, so Delta
367 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
368 // the number of bytes in each row can be computed.
371 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
375 // We need to fill the Virtual Screen buffer with the blt data.
376 // The virtual screen is upside down, as the first row is the bootom row of
379 VerticalResolution
= This
->Mode
->Info
->VerticalResolution
;
380 HorizontalResolution
= This
->Mode
->Info
->HorizontalResolution
;
381 if (BltOperation
== EfiBltVideoToBltBuffer
) {
384 // Video to BltBuffer: Source is Video, destination is BltBuffer
386 if (SourceY
+ Height
> VerticalResolution
) {
387 return EFI_INVALID_PARAMETER
;
390 if (SourceX
+ Width
> HorizontalResolution
) {
391 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 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
401 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (DstY
* Delta
) + DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
402 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
403 CopyMem (Blt
, VScreen
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * Width
);
407 // BltBuffer to Video: Source is BltBuffer, destination is Video
409 if (DestinationY
+ Height
> VerticalResolution
) {
410 return EFI_INVALID_PARAMETER
;
413 if (DestinationX
+ Width
> HorizontalResolution
) {
414 return EFI_INVALID_PARAMETER
;
418 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
419 // We would not want a timer based event (Cursor, ...) to come in while we are
420 // doing this operation.
422 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
424 if (BltOperation
== EfiBltVideoFill
) {
425 FillPixel
= BltBuffer
;
426 for (Index
= 0; Index
< Width
; Index
++) {
427 Private
->FillLine
[Index
] = *FillPixel
;
431 for (Index
= 0; Index
< Height
; Index
++) {
432 if (DestinationY
<= SourceY
) {
433 SrcY
= SourceY
+ Index
;
434 DstY
= DestinationY
+ Index
;
436 SrcY
= SourceY
+ Height
- Index
- 1;
437 DstY
= DestinationY
+ Height
- Index
- 1;
440 VScreen
= &Private
->VirtualScreen
[(VerticalResolution
- DstY
- 1) * HorizontalResolution
+ DestinationX
];
441 switch (BltOperation
) {
442 case EfiBltBufferToVideo
:
443 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (SrcY
* Delta
) + SourceX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
444 CopyMem (VScreen
, Blt
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
447 case EfiBltVideoToVideo
:
448 VScreenSrc
= &Private
->VirtualScreen
[(VerticalResolution
- SrcY
- 1) * HorizontalResolution
+ SourceX
];
449 CopyMem (VScreen
, VScreenSrc
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
452 case EfiBltVideoFill
:
453 CopyMem (VScreen
, Private
->FillLine
, Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
459 if (BltOperation
!= EfiBltVideoToBltBuffer
) {
461 // Mark the area we just blted as Invalid so WM_PAINT will update.
463 Rect
.left
= DestinationX
;
464 Rect
.top
= DestinationY
;
465 Rect
.right
= DestinationX
+ Width
;
466 Rect
.bottom
= DestinationY
+ Height
;
467 Private
->WinNtThunk
->InvalidateRect (Private
->WindowHandle
, &Rect
, FALSE
);
470 // Send the WM_PAINT message to the thread that is drawing the window. We
471 // are in the main thread and the window drawing is in a child thread.
472 // There is a child thread per window. We have no CriticalSection or Mutex
473 // since we write the data and the other thread displays the data. While
474 // we may miss some data for a short period of time this is no different than
475 // a write combining on writes to a frame buffer.
478 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
481 gBS
->RestoreTPL (OriginalTPL
);
487 // Construction and Destruction functions
497 // TODO: WinNtIo - add argument and description to function comment
498 // TODO: EFI_UNSUPPORTED - add return value to function comment
499 // TODO: EFI_SUCCESS - add return value to function comment
502 IN EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
506 // Check to see if the IO abstraction represents a device type we support.
508 // This would be replaced a check of PCI subsystem ID, etc.
510 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtGopGuid
)) {
511 return EFI_UNSUPPORTED
;
519 Win32 Windows event handler.
523 @return See Win32 Book
526 // TODO: hwnd - add argument and description to function comment
527 // TODO: iMsg - add argument and description to function comment
528 // TODO: wParam - add argument and description to function comment
529 // TODO: lParam - add argument and description to function comment
532 WinNtGopThreadWindowProc (
539 GOP_PRIVATE_DATA
*Private
;
542 PAINTSTRUCT PaintStruct
;
547 // BugBug - if there are two instances of this DLL in memory (such as is
548 // the case for ERM), the correct instance of this function may not be called.
549 // This also means that the address of the mTlsIndex value will be wrong, and
550 // the value may be wrong too.
555 // Use mTlsIndex global to get a Thread Local Storage version of Private.
556 // This works since each Gop protocol has a unique Private data instance and
559 Private
= mWinNt
->TlsGetValue (mTlsIndex
);
560 ASSERT (NULL
!= Private
);
564 Size
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
* Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
* sizeof (RGBQUAD
);
567 // Allocate DIB frame buffer directly from NT for performance enhancement
568 // This buffer is the virtual screen/frame buffer. This buffer is not the
569 // same a a frame buffer. The first fow of this buffer will be the bottom
570 // line of the image. This is an artifact of the way we draw to the screen.
572 Private
->VirtualScreenInfo
= Private
->WinNtThunk
->HeapAlloc (
573 Private
->WinNtThunk
->GetProcessHeap (),
578 Private
->VirtualScreenInfo
->bV4Size
= sizeof (BITMAPV4HEADER
);
579 Private
->VirtualScreenInfo
->bV4Width
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
580 Private
->VirtualScreenInfo
->bV4Height
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
581 Private
->VirtualScreenInfo
->bV4Planes
= 1;
582 Private
->VirtualScreenInfo
->bV4BitCount
= 32;
586 Private
->VirtualScreenInfo
->bV4V4Compression
= BI_RGB
;
587 Private
->VirtualScreen
= (RGBQUAD
*) (Private
->VirtualScreenInfo
+ 1);
592 // I have not found a way to convert hwnd into a Private context. So for
593 // now we use this API to convert hwnd to Private data.
596 Handle
= mWinNt
->BeginPaint (hwnd
, &PaintStruct
);
598 mWinNt
->SetDIBitsToDevice (
599 Handle
, // Destination Device Context
600 0, // Destination X - 0
601 0, // Destination Y - 0
602 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
, // Width
603 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Height
606 0, // DIB Start Scan Line
607 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
, // Number of scan lines
608 Private
->VirtualScreen
, // Address of array of DIB bits
609 (BITMAPINFO
*) Private
->VirtualScreenInfo
, // Address of structure with bitmap info
610 DIB_RGB_COLORS
// RGB or palette indexes
613 mWinNt
->EndPaint (hwnd
, &PaintStruct
);
617 // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case
623 Key
.ScanCode
= SCAN_F10
;
625 GopPrivateAddQ (Private
, Key
);
633 case VK_HOME
: Key
.ScanCode
= SCAN_HOME
; break;
634 case VK_END
: Key
.ScanCode
= SCAN_END
; break;
635 case VK_LEFT
: Key
.ScanCode
= SCAN_LEFT
; break;
636 case VK_RIGHT
: Key
.ScanCode
= SCAN_RIGHT
; break;
637 case VK_UP
: Key
.ScanCode
= SCAN_UP
; break;
638 case VK_DOWN
: Key
.ScanCode
= SCAN_DOWN
; break;
639 case VK_DELETE
: Key
.ScanCode
= SCAN_DELETE
; break;
640 case VK_INSERT
: Key
.ScanCode
= SCAN_INSERT
; break;
641 case VK_PRIOR
: Key
.ScanCode
= SCAN_PAGE_UP
; break;
642 case VK_NEXT
: Key
.ScanCode
= SCAN_PAGE_DOWN
; break;
643 case VK_ESCAPE
: Key
.ScanCode
= SCAN_ESC
; break;
645 case VK_F1
: Key
.ScanCode
= SCAN_F1
; break;
646 case VK_F2
: Key
.ScanCode
= SCAN_F2
; break;
647 case VK_F3
: Key
.ScanCode
= SCAN_F3
; break;
648 case VK_F4
: Key
.ScanCode
= SCAN_F4
; break;
649 case VK_F5
: Key
.ScanCode
= SCAN_F5
; break;
650 case VK_F6
: Key
.ScanCode
= SCAN_F6
; break;
651 case VK_F7
: Key
.ScanCode
= SCAN_F7
; break;
652 case VK_F8
: Key
.ScanCode
= SCAN_F8
; break;
653 case VK_F9
: Key
.ScanCode
= SCAN_F9
; break;
654 case VK_F11
: Key
.ScanCode
= SCAN_F11
; break;
655 case VK_F12
: Key
.ScanCode
= SCAN_F12
; break;
658 if (Key
.ScanCode
!= 0) {
660 GopPrivateAddQ (Private
, Key
);
667 // The ESC key also generate WM_CHAR.
669 if (wParam
== 0x1B) {
673 for (Index
= 0; Index
< (lParam
& 0xffff); Index
++) {
675 Key
.UnicodeChar
= (CHAR16
) wParam
;
677 GopPrivateAddQ (Private
, Key
);
685 // This close message is issued by user, core is not aware of this,
686 // so don't release the window display resource, just hide the window.
688 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_HIDE
);
692 mWinNt
->DestroyWindow (hwnd
);
693 mWinNt
->PostQuitMessage (0);
695 mWinNt
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
697 mWinNt
->ExitThread (0);
704 return mWinNt
->DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
709 This thread simulates the end of WinMain () aplication. Each Winow nededs
710 to process it's events. The messages are dispatched to
711 WinNtGopThreadWindowProc ().
712 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
713 are running in a seperate thread. We have to do this to process the events.
715 @param lpParameter Handle of window to manage.
717 @return if a WM_QUIT message is returned exit.
722 WinNtGopThreadWinMain (
727 GOP_PRIVATE_DATA
*Private
;
731 Private
= (GOP_PRIVATE_DATA
*) lpParameter
;
732 ASSERT (NULL
!= Private
);
735 // Since each thread has unique private data, save the private data in Thread
736 // Local Storage slot. Then the shared global mTlsIndex can be used to get
737 // thread specific context.
739 Private
->WinNtThunk
->TlsSetValue (mTlsIndex
, Private
);
741 Private
->ThreadId
= Private
->WinNtThunk
->GetCurrentThreadId ();
743 Private
->WindowsClass
.cbSize
= sizeof (WNDCLASSEX
);
744 Private
->WindowsClass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_OWNDC
;
745 Private
->WindowsClass
.lpfnWndProc
= WinNtGopThreadWindowProc
;
746 Private
->WindowsClass
.cbClsExtra
= 0;
747 Private
->WindowsClass
.cbWndExtra
= 0;
748 Private
->WindowsClass
.hInstance
= NULL
;
749 Private
->WindowsClass
.hIcon
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
750 Private
->WindowsClass
.hCursor
= Private
->WinNtThunk
->LoadCursor (NULL
, IDC_ARROW
);
751 Private
->WindowsClass
.hbrBackground
= (HBRUSH
) COLOR_WINDOW
;
752 Private
->WindowsClass
.lpszMenuName
= NULL
;
753 Private
->WindowsClass
.lpszClassName
= WIN_NT_GOP_CLASS_NAME
;
754 Private
->WindowsClass
.hIconSm
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
757 // This call will fail after the first time, but thats O.K. since we only need
758 // WIN_NT_GOP_CLASS_NAME to exist to create the window.
760 // Note: Multiple instances of this DLL will use the same instance of this
761 // Class, including the callback function, unless the Class is unregistered and
762 // successfully registered again.
764 Atom
= Private
->WinNtThunk
->RegisterClassEx (&Private
->WindowsClass
);
767 // Setting Rect values to allow for the AdjustWindowRect to provide
768 // us the correct sizes for the client area when doing the CreateWindowEx
771 Rect
.bottom
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
773 Rect
.right
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
775 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
777 Private
->WindowHandle
= Private
->WinNtThunk
->CreateWindowEx (
779 WIN_NT_GOP_CLASS_NAME
,
784 Rect
.right
- Rect
.left
,
785 Rect
.bottom
- Rect
.top
,
793 // The reset of this thread is the standard winows program. We need a sperate
794 // thread since we must process the message loop to make windows act like
798 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_SHOW
);
799 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
802 // Let the main thread get some work done
804 Private
->WinNtThunk
->ReleaseSemaphore (Private
->ThreadInited
, 1, NULL
);
807 // This is the message loop that all Windows programs need.
809 while (Private
->WinNtThunk
->GetMessage (&Message
, Private
->WindowHandle
, 0, 0)) {
810 Private
->WinNtThunk
->TranslateMessage (&Message
);
811 Private
->WinNtThunk
->DispatchMessage (&Message
);
814 return Message
.wParam
;
819 TODO: Add function description
821 @param Private TODO: add argument description
822 @param HorizontalResolution TODO: add argument description
823 @param VerticalResolution TODO: add argument description
824 @param ColorDepth TODO: add argument description
825 @param RefreshRate TODO: add argument description
827 @return TODO: add return values
831 WinNtGopStartWindow (
832 IN GOP_PRIVATE_DATA
*Private
,
833 IN UINT32 HorizontalResolution
,
834 IN UINT32 VerticalResolution
,
835 IN UINT32 ColorDepth
,
836 IN UINT32 RefreshRate
842 mWinNt
= Private
->WinNtThunk
;
845 // Initialize a Thread Local Storge variable slot. We use TLS to get the
846 // correct Private data instance into the windows thread.
848 if (mTlsIndex
== TLS_OUT_OF_INDEXES
) {
849 ASSERT (0 == mTlsIndexUseCount
);
850 mTlsIndex
= Private
->WinNtThunk
->TlsAlloc ();
854 // always increase the use count!
859 // Register to be notified on exit boot services so we can destroy the window.
861 Status
= gBS
->CreateEvent (
862 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
866 &mGopScreenExitBootServicesEvent
869 Private
->ThreadInited
= Private
->WinNtThunk
->CreateSemaphore (NULL
, 0, 1, NULL
);
870 Private
->ThreadHandle
= Private
->WinNtThunk
->CreateThread (
873 WinNtGopThreadWinMain
,
880 // The other thread has entered the windows message loop so we can
881 // continue our initialization.
883 Private
->WinNtThunk
->WaitForSingleObject (Private
->ThreadInited
, INFINITE
);
884 Private
->WinNtThunk
->CloseHandle (Private
->ThreadInited
);
896 // TODO: Private - add argument and description to function comment
897 // TODO: EFI_SUCCESS - add return value to function comment
899 WinNtGopConstructor (
900 GOP_PRIVATE_DATA
*Private
903 Private
->ModeData
= mGopModeData
;
905 Private
->GraphicsOutput
.QueryMode
= WinNtGopQuerytMode
;
906 Private
->GraphicsOutput
.SetMode
= WinNtGopSetMode
;
907 Private
->GraphicsOutput
.Blt
= WinNtGopBlt
;
910 // Allocate buffer for Graphics Output Protocol mode information
912 Private
->GraphicsOutput
.Mode
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
));
913 if (Private
->GraphicsOutput
.Mode
== NULL
) {
914 return EFI_OUT_OF_RESOURCES
;
916 Private
->GraphicsOutput
.Mode
->Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
917 if (Private
->GraphicsOutput
.Mode
->Info
== NULL
) {
918 return EFI_OUT_OF_RESOURCES
;
921 Private
->GraphicsOutput
.Mode
->MaxMode
= sizeof(mGopModeData
) / sizeof(GOP_MODE_DATA
);
923 // Till now, we have no idea about the window size.
925 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
926 Private
->GraphicsOutput
.Mode
->Info
->Version
= 0;
927 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= 0;
928 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= 0;
929 Private
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBltOnly
;
930 Private
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
931 Private
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
932 Private
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
934 Private
->HardwareNeedsStarting
= TRUE
;
935 Private
->FillLine
= NULL
;
937 WinNtGopInitializeSimpleTextInForWindow (Private
);
949 // TODO: Private - add argument and description to function comment
950 // TODO: EFI_SUCCESS - add return value to function comment
953 GOP_PRIVATE_DATA
*Private
956 UINT32 UnregisterReturn
;
958 if (!Private
->HardwareNeedsStarting
) {
960 // BugBug: Shutdown GOP Hardware and any child devices.
962 Private
->WinNtThunk
->SendMessage (Private
->WindowHandle
, WM_DESTROY
, 0, 0);
963 Private
->WinNtThunk
->CloseHandle (Private
->ThreadHandle
);
968 // The callback function for another window could still be called,
969 // so we need to make sure there are no more users of mTlsIndex.
971 if (0 == mTlsIndexUseCount
) {
972 ASSERT (TLS_OUT_OF_INDEXES
!= mTlsIndex
);
974 Private
->WinNtThunk
->TlsFree (mTlsIndex
);
975 mTlsIndex
= TLS_OUT_OF_INDEXES
;
977 UnregisterReturn
= Private
->WinNtThunk
->UnregisterClass (
978 Private
->WindowsClass
.lpszClassName
,
979 Private
->WindowsClass
.hInstance
983 WinNtGopDestroySimpleTextInForWindow (Private
);
987 // Free graphics output protocol occupied resource
989 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
990 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
991 FreePool (Private
->GraphicsOutput
.Mode
->Info
);
993 FreePool (Private
->GraphicsOutput
.Mode
);
1001 This is the GOP screen's callback notification function for exit-boot-services.
1002 All we do here is call WinNtGopDestructor().
1004 @param Event not used
1005 @param Context pointer to the Private structure.
1019 Status
= WinNtGopDestructor (Context
);