3 Copyright (c) 2006, 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;
641 if (Key
.ScanCode
!= 0) {
643 GopPrivateAddQ (Private
, Key
);
650 // The ESC key also generate WM_CHAR.
652 if (wParam
== 0x1B) {
656 for (Index
= 0; Index
< (lParam
& 0xffff); Index
++) {
658 Key
.UnicodeChar
= (CHAR16
) wParam
;
660 GopPrivateAddQ (Private
, Key
);
668 // This close message is issued by user, core is not aware of this,
669 // so don't release the window display resource, just hide the window.
671 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_HIDE
);
675 mWinNt
->DestroyWindow (hwnd
);
676 mWinNt
->PostQuitMessage (0);
678 mWinNt
->HeapFree (Private
->WinNtThunk
->GetProcessHeap (), 0, Private
->VirtualScreenInfo
);
680 mWinNt
->ExitThread (0);
687 return mWinNt
->DefWindowProc (hwnd
, iMsg
, wParam
, lParam
);
692 This thread simulates the end of WinMain () aplication. Each Winow nededs
693 to process it's events. The messages are dispatched to
694 WinNtGopThreadWindowProc ().
695 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
696 are running in a seperate thread. We have to do this to process the events.
698 @param lpParameter Handle of window to manage.
700 @return if a WM_QUIT message is returned exit.
705 WinNtGopThreadWinMain (
710 GOP_PRIVATE_DATA
*Private
;
714 Private
= (GOP_PRIVATE_DATA
*) lpParameter
;
715 ASSERT (NULL
!= Private
);
718 // Since each thread has unique private data, save the private data in Thread
719 // Local Storage slot. Then the shared global mTlsIndex can be used to get
720 // thread specific context.
722 Private
->WinNtThunk
->TlsSetValue (mTlsIndex
, Private
);
724 Private
->ThreadId
= Private
->WinNtThunk
->GetCurrentThreadId ();
726 Private
->WindowsClass
.cbSize
= sizeof (WNDCLASSEX
);
727 Private
->WindowsClass
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_OWNDC
;
728 Private
->WindowsClass
.lpfnWndProc
= WinNtGopThreadWindowProc
;
729 Private
->WindowsClass
.cbClsExtra
= 0;
730 Private
->WindowsClass
.cbWndExtra
= 0;
731 Private
->WindowsClass
.hInstance
= NULL
;
732 Private
->WindowsClass
.hIcon
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
733 Private
->WindowsClass
.hCursor
= Private
->WinNtThunk
->LoadCursor (NULL
, IDC_ARROW
);
734 Private
->WindowsClass
.hbrBackground
= (HBRUSH
) COLOR_WINDOW
;
735 Private
->WindowsClass
.lpszMenuName
= NULL
;
736 Private
->WindowsClass
.lpszClassName
= WIN_NT_GOP_CLASS_NAME
;
737 Private
->WindowsClass
.hIconSm
= Private
->WinNtThunk
->LoadIcon (NULL
, IDI_APPLICATION
);
740 // This call will fail after the first time, but thats O.K. since we only need
741 // WIN_NT_GOP_CLASS_NAME to exist to create the window.
743 // Note: Multiple instances of this DLL will use the same instance of this
744 // Class, including the callback function, unless the Class is unregistered and
745 // successfully registered again.
747 Atom
= Private
->WinNtThunk
->RegisterClassEx (&Private
->WindowsClass
);
750 // Setting Rect values to allow for the AdjustWindowRect to provide
751 // us the correct sizes for the client area when doing the CreateWindowEx
754 Rect
.bottom
= Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
;
756 Rect
.right
= Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
;
758 Private
->WinNtThunk
->AdjustWindowRect (&Rect
, WS_OVERLAPPEDWINDOW
, 0);
760 Private
->WindowHandle
= Private
->WinNtThunk
->CreateWindowEx (
762 WIN_NT_GOP_CLASS_NAME
,
767 Rect
.right
- Rect
.left
,
768 Rect
.bottom
- Rect
.top
,
776 // The reset of this thread is the standard winows program. We need a sperate
777 // thread since we must process the message loop to make windows act like
781 Private
->WinNtThunk
->ShowWindow (Private
->WindowHandle
, SW_SHOW
);
782 Private
->WinNtThunk
->UpdateWindow (Private
->WindowHandle
);
785 // Let the main thread get some work done
787 Private
->WinNtThunk
->ReleaseSemaphore (Private
->ThreadInited
, 1, NULL
);
790 // This is the message loop that all Windows programs need.
792 while (Private
->WinNtThunk
->GetMessage (&Message
, Private
->WindowHandle
, 0, 0)) {
793 Private
->WinNtThunk
->TranslateMessage (&Message
);
794 Private
->WinNtThunk
->DispatchMessage (&Message
);
797 return Message
.wParam
;
802 TODO: Add function description
804 @param Private TODO: add argument description
805 @param HorizontalResolution TODO: add argument description
806 @param VerticalResolution TODO: add argument description
807 @param ColorDepth TODO: add argument description
808 @param RefreshRate TODO: add argument description
810 @return TODO: add return values
814 WinNtGopStartWindow (
815 IN GOP_PRIVATE_DATA
*Private
,
816 IN UINT32 HorizontalResolution
,
817 IN UINT32 VerticalResolution
,
818 IN UINT32 ColorDepth
,
819 IN UINT32 RefreshRate
825 mWinNt
= Private
->WinNtThunk
;
828 // Initialize a Thread Local Storge variable slot. We use TLS to get the
829 // correct Private data instance into the windows thread.
831 if (mTlsIndex
== TLS_OUT_OF_INDEXES
) {
832 ASSERT (0 == mTlsIndexUseCount
);
833 mTlsIndex
= Private
->WinNtThunk
->TlsAlloc ();
837 // always increase the use count!
842 // Register to be notified on exit boot services so we can destroy the window.
844 Status
= gBS
->CreateEvent (
845 EVENT_SIGNAL_EXIT_BOOT_SERVICES
,
849 &mGopScreenExitBootServicesEvent
852 Private
->ThreadInited
= Private
->WinNtThunk
->CreateSemaphore (NULL
, 0, 1, NULL
);
853 Private
->ThreadHandle
= Private
->WinNtThunk
->CreateThread (
856 WinNtGopThreadWinMain
,
863 // The other thread has entered the windows message loop so we can
864 // continue our initialization.
866 Private
->WinNtThunk
->WaitForSingleObject (Private
->ThreadInited
, INFINITE
);
867 Private
->WinNtThunk
->CloseHandle (Private
->ThreadInited
);
879 // TODO: Private - add argument and description to function comment
880 // TODO: EFI_SUCCESS - add return value to function comment
882 WinNtGopConstructor (
883 GOP_PRIVATE_DATA
*Private
888 Private
->ModeData
= mGopModeData
;
890 Private
->GraphicsOutput
.QueryMode
= WinNtGopQuerytMode
;
891 Private
->GraphicsOutput
.SetMode
= WinNtGopSetMode
;
892 Private
->GraphicsOutput
.Blt
= WinNtGopBlt
;
895 // Allocate buffer for Graphics Output Protocol mode information
897 Status
= gBS
->AllocatePool (
899 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
900 (VOID
**) &Private
->GraphicsOutput
.Mode
902 if (EFI_ERROR (Status
)) {
905 Status
= gBS
->AllocatePool (
907 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
908 (VOID
**) &Private
->GraphicsOutput
.Mode
->Info
910 if (EFI_ERROR (Status
)) {
913 Private
->GraphicsOutput
.Mode
->MaxMode
= sizeof(mGopModeData
) / sizeof(GOP_MODE_DATA
);
915 // Till now, we have no idea about the window size.
917 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
918 Private
->GraphicsOutput
.Mode
->Info
->Version
= 0;
919 Private
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= 0;
920 Private
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= 0;
921 Private
->GraphicsOutput
.Mode
->Info
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
922 Private
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
923 Private
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) NULL
;
924 Private
->GraphicsOutput
.Mode
->FrameBufferSize
= 0;
926 Private
->HardwareNeedsStarting
= TRUE
;
927 Private
->FillLine
= NULL
;
929 WinNtGopInitializeSimpleTextInForWindow (Private
);
941 // TODO: Private - add argument and description to function comment
942 // TODO: EFI_SUCCESS - add return value to function comment
945 GOP_PRIVATE_DATA
*Private
948 UINT32 UnregisterReturn
;
950 if (!Private
->HardwareNeedsStarting
) {
952 // BugBug: Shutdown GOP Hardware and any child devices.
954 Private
->WinNtThunk
->SendMessage (Private
->WindowHandle
, WM_DESTROY
, 0, 0);
955 Private
->WinNtThunk
->CloseHandle (Private
->ThreadHandle
);
960 // The callback function for another window could still be called,
961 // so we need to make sure there are no more users of mTlsIndex.
963 if (0 == mTlsIndexUseCount
) {
964 ASSERT (TLS_OUT_OF_INDEXES
!= mTlsIndex
);
966 Private
->WinNtThunk
->TlsFree (mTlsIndex
);
967 mTlsIndex
= TLS_OUT_OF_INDEXES
;
969 UnregisterReturn
= Private
->WinNtThunk
->UnregisterClass (
970 Private
->WindowsClass
.lpszClassName
,
971 Private
->WindowsClass
.hInstance
975 WinNtGopDestroySimpleTextInForWindow (Private
);
979 // Free graphics output protocol occupied resource
981 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
982 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
983 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
985 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);
993 This is the GOP screen's callback notification function for exit-boot-services.
994 All we do here is call WinNtGopDestructor().
996 @param Event not used
997 @param Context pointer to the Private structure.
1011 Status
= WinNtGopDestructor (Context
);