]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c
Nt32Pkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / Nt32Pkg / WinNtGopDxe / WinNtGopScreen.c
CommitLineData
c9fc89a3 1/** @file\r
2\r
f66a43b2 3Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
9d2eedba 4SPDX-License-Identifier: BSD-2-Clause-Patent\r
c9fc89a3 5\r
6Module Name:\r
7\r
8 WinNtGopScreen.c\r
9\r
10Abstract:\r
11\r
12 This file produces the graphics abstration of GOP. It is called by\r
8a7d75b0 13 WinNtGopDriver.c file which deals with the UEFI 2.0 driver model.\r
c9fc89a3 14 This file just does graphics.\r
15\r
16\r
17**/\r
c9fc89a3 18\r
19#include "WinNtGop.h"\r
20\r
21EFI_WIN_NT_THUNK_PROTOCOL *mWinNt;\r
22DWORD mTlsIndex = TLS_OUT_OF_INDEXES;\r
23DWORD mTlsIndexUseCount = 0; // lets us know when we can free mTlsIndex.\r
78e570b6 24EFI_EVENT mGopScreenExitBootServicesEvent;\r
c9fc89a3 25GOP_MODE_DATA mGopModeData[] = {\r
26 {800, 600, 0, 0},\r
27 {640, 480, 0, 0},\r
28 {720, 400, 0, 0},\r
29 {1024, 768, 0, 0},\r
30 {1280, 1024, 0, 0}\r
31 };\r
32\r
33EFI_STATUS\r
34WinNtGopStartWindow (\r
35 IN GOP_PRIVATE_DATA *Private,\r
36 IN UINT32 HorizontalResolution,\r
37 IN UINT32 VerticalResolution,\r
38 IN UINT32 ColorDepth,\r
39 IN UINT32 RefreshRate\r
40 );\r
41\r
c9fc89a3 42VOID\r
43EFIAPI\r
44KillNtGopThread (\r
45 IN EFI_EVENT Event,\r
46 IN VOID *Context\r
47 );\r
48\r
df7499fc 49BOOLEAN\r
62cf113f 50WinNtGopConvertParamToEfiKeyShiftState (\r
51 IN GOP_PRIVATE_DATA *Private,\r
52 IN WPARAM *wParam,\r
df7499fc 53 IN LPARAM *lParam,\r
62cf113f 54 IN BOOLEAN Flag\r
55 )\r
56{\r
57 switch (*wParam) {\r
58 //\r
59 // BUGBUG: Only GetAsyncKeyState() and GetKeyState() can distinguish\r
df7499fc 60 // left and right Ctrl, and Shift key.\r
61 // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL.\r
62cf113f 62 // Therefor, we can not set the correct Shift state here.\r
df7499fc 63 //\r
64 case VK_SHIFT:\r
65 if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {\r
66 Private->RightShift = Flag;\r
67 } else {\r
68 Private->LeftShift = Flag;\r
69 }\r
70 return TRUE;\r
71\r
72 case VK_LSHIFT:\r
73 Private->LeftShift = Flag;\r
74 return TRUE;\r
75\r
76 case VK_RSHIFT:\r
77 Private->RightShift = Flag;\r
78 return TRUE;\r
79\r
62cf113f 80 case VK_CONTROL:\r
df7499fc 81 if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {\r
82 Private->RightCtrl= Flag;\r
83 } else {\r
84 Private->LeftCtrl = Flag;\r
85 }\r
86 return TRUE;\r
87\r
88 case VK_LCONTROL:\r
89 Private->LeftCtrl = Flag;\r
90 return TRUE;\r
91\r
92 case VK_RCONTROL:\r
93 Private->RightCtrl = Flag;\r
94 return TRUE;\r
95\r
96 case VK_LWIN:\r
62cf113f 97 Private->LeftLogo = Flag;\r
df7499fc 98 return TRUE;\r
99\r
100 case VK_RWIN:\r
62cf113f 101 Private->RightLogo = Flag;\r
df7499fc 102 return TRUE;\r
103\r
104 case VK_APPS:\r
62cf113f 105 Private->Menu = Flag;\r
df7499fc 106 return TRUE;\r
62cf113f 107 //\r
108 // BUGBUG: PrintScreen/SysRq can not trigger WM_KEYDOWN message,\r
109 // so SySReq shift state is not supported here.\r
110 //\r
df7499fc 111 case VK_PRINT:\r
62cf113f 112 Private->SysReq = Flag;\r
df7499fc 113 return TRUE;\r
114 //\r
115 // For Alt Keystroke.\r
116 //\r
117 case VK_MENU:\r
118 if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) {\r
119 Private->RightAlt = Flag;\r
120 } else {\r
121 Private->LeftAlt = Flag;\r
122 }\r
123 return TRUE;\r
124\r
125 default:\r
126 return FALSE;\r
62cf113f 127 }\r
128}\r
129\r
df7499fc 130BOOLEAN\r
62cf113f 131WinNtGopConvertParamToEfiKey (\r
132 IN GOP_PRIVATE_DATA *Private,\r
133 IN WPARAM *wParam,\r
df7499fc 134 IN LPARAM *lParam,\r
62cf113f 135 IN EFI_INPUT_KEY *Key\r
136 )\r
137{\r
df7499fc 138 BOOLEAN Flag;\r
139 Flag = FALSE;\r
62cf113f 140 switch (*wParam) {\r
df7499fc 141 case VK_HOME: Key->ScanCode = SCAN_HOME; Flag = TRUE; break;\r
142 case VK_END: Key->ScanCode = SCAN_END; Flag = TRUE; break;\r
143 case VK_LEFT: Key->ScanCode = SCAN_LEFT; Flag = TRUE; break;\r
144 case VK_RIGHT: Key->ScanCode = SCAN_RIGHT; Flag = TRUE; break;\r
145 case VK_UP: Key->ScanCode = SCAN_UP; Flag = TRUE; break;\r
146 case VK_DOWN: Key->ScanCode = SCAN_DOWN; Flag = TRUE; break;\r
147 case VK_DELETE: Key->ScanCode = SCAN_DELETE; Flag = TRUE; break;\r
148 case VK_INSERT: Key->ScanCode = SCAN_INSERT; Flag = TRUE; break;\r
149 case VK_PRIOR: Key->ScanCode = SCAN_PAGE_UP; Flag = TRUE; break;\r
150 case VK_NEXT: Key->ScanCode = SCAN_PAGE_DOWN; Flag = TRUE; break;\r
151 case VK_ESCAPE: Key->ScanCode = SCAN_ESC; Flag = TRUE; break;\r
152\r
153 case VK_F1: Key->ScanCode = SCAN_F1; Flag = TRUE; break;\r
154 case VK_F2: Key->ScanCode = SCAN_F2; Flag = TRUE; break;\r
155 case VK_F3: Key->ScanCode = SCAN_F3; Flag = TRUE; break;\r
156 case VK_F4: Key->ScanCode = SCAN_F4; Flag = TRUE; break;\r
157 case VK_F5: Key->ScanCode = SCAN_F5; Flag = TRUE; break;\r
158 case VK_F6: Key->ScanCode = SCAN_F6; Flag = TRUE; break;\r
159 case VK_F7: Key->ScanCode = SCAN_F7; Flag = TRUE; break;\r
160 case VK_F8: Key->ScanCode = SCAN_F8; Flag = TRUE; break;\r
161 case VK_F9: Key->ScanCode = SCAN_F9; Flag = TRUE; break;\r
162 case VK_F11: Key->ScanCode = SCAN_F11; Flag = TRUE; break;\r
163 case VK_F12: Key->ScanCode = SCAN_F12; Flag = TRUE; break;\r
164\r
165 case VK_F13: Key->ScanCode = SCAN_F13; Flag = TRUE; break;\r
166 case VK_F14: Key->ScanCode = SCAN_F14; Flag = TRUE; break;\r
167 case VK_F15: Key->ScanCode = SCAN_F15; Flag = TRUE; break;\r
168 case VK_F16: Key->ScanCode = SCAN_F16; Flag = TRUE; break;\r
169 case VK_F17: Key->ScanCode = SCAN_F17; Flag = TRUE; break;\r
170 case VK_F18: Key->ScanCode = SCAN_F18; Flag = TRUE; break;\r
171 case VK_F19: Key->ScanCode = SCAN_F19; Flag = TRUE; break;\r
172 case VK_F20: Key->ScanCode = SCAN_F20; Flag = TRUE; break;\r
173 case VK_F21: Key->ScanCode = SCAN_F21; Flag = TRUE; break;\r
174 case VK_F22: Key->ScanCode = SCAN_F22; Flag = TRUE; break;\r
175 case VK_F23: Key->ScanCode = SCAN_F23; Flag = TRUE; break;\r
176 case VK_F24: Key->ScanCode = SCAN_F24; Flag = TRUE; break;\r
177 case VK_PAUSE: Key->ScanCode = SCAN_PAUSE; Flag = TRUE; break;\r
62cf113f 178\r
179 //\r
180 // Set toggle state\r
df7499fc 181 //\r
182 case VK_NUMLOCK:\r
a00ec39b 183 Private->NumLock = (BOOLEAN)(!Private->NumLock);\r
df7499fc 184 Flag = TRUE;\r
62cf113f 185 break;\r
186 case VK_SCROLL:\r
a00ec39b 187 Private->ScrollLock = (BOOLEAN)(!Private->ScrollLock);\r
df7499fc 188 Flag = TRUE;\r
189 break;\r
62cf113f 190 case VK_CAPITAL:\r
a00ec39b 191 Private->CapsLock = (BOOLEAN)(!Private->CapsLock);\r
df7499fc 192 Flag = TRUE;\r
193 break;\r
62cf113f 194 }\r
195 \r
df7499fc 196 return (WinNtGopConvertParamToEfiKeyShiftState (Private, wParam, lParam, TRUE)) == TRUE ? TRUE : Flag;\r
62cf113f 197}\r
198\r
199\r
c9fc89a3 200//\r
201// GOP Protocol Member Functions\r
202//\r
203\r
204\r
205/**\r
206 Graphics Output protocol interface to get video mode\r
207\r
208 @param This Protocol instance pointer.\r
209 @param ModeNumber The mode number to return information on.\r
210 @param Info Caller allocated buffer that returns information\r
211 about ModeNumber.\r
212 @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
213 buffer.\r
214\r
215 @retval EFI_SUCCESS Mode information returned.\r
216 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.\r
217 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
218 video mode.\r
219 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
220 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
221\r
222**/\r
223EFI_STATUS\r
224EFIAPI\r
225WinNtGopQuerytMode (\r
226 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
227 IN UINT32 ModeNumber,\r
228 OUT UINTN *SizeOfInfo,\r
229 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
230 )\r
231{\r
232 GOP_PRIVATE_DATA *Private;\r
233\r
234 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
235\r
236 if (Info == NULL || SizeOfInfo == NULL || (UINTN) ModeNumber >= This->Mode->MaxMode) {\r
237 return EFI_INVALID_PARAMETER;\r
238 }\r
239\r
240 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
241 if (*Info == NULL) {\r
242 return EFI_OUT_OF_RESOURCES;\r
243 }\r
244\r
245 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
246\r
247 (*Info)->Version = 0;\r
248 (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;\r
249 (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution;\r
62cf113f 250 (*Info)->PixelFormat = PixelBltOnly;\r
c9fc89a3 251 (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;\r
252\r
253 return EFI_SUCCESS;\r
254}\r
255\r
256\r
257/**\r
258 Graphics Output protocol interface to set video mode\r
259\r
260 @param This Protocol instance pointer.\r
261 @param ModeNumber The mode number to be set.\r
262\r
263 @retval EFI_SUCCESS Graphics mode was changed.\r
264 @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
265 request.\r
266 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
267\r
268**/\r
269EFI_STATUS\r
270EFIAPI\r
271WinNtGopSetMode (\r
272 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
273 IN UINT32 ModeNumber\r
274 )\r
275{\r
276 EFI_STATUS Status;\r
277 GOP_PRIVATE_DATA *Private;\r
278 GOP_MODE_DATA *ModeData;\r
279 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;\r
280 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewFillLine;\r
281 RECT Rect;\r
282 UINTN Size;\r
283 UINTN Width;\r
284 UINTN Height;\r
285\r
286 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
287\r
288 if (ModeNumber >= This->Mode->MaxMode) {\r
289 return EFI_UNSUPPORTED;\r
290 }\r
291\r
c9fc89a3 292 ModeData = &Private->ModeData[ModeNumber];\r
293 This->Mode->Mode = ModeNumber;\r
294 Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
295 Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
296 Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;\r
297\r
298 if (Private->HardwareNeedsStarting) {\r
299 Status = WinNtGopStartWindow (\r
300 Private,\r
301 ModeData->HorizontalResolution,\r
302 ModeData->VerticalResolution,\r
303 ModeData->ColorDepth,\r
304 ModeData->RefreshRate\r
305 );\r
306 if (EFI_ERROR (Status)) {\r
307 return EFI_DEVICE_ERROR;\r
308 }\r
309\r
310 Private->HardwareNeedsStarting = FALSE;\r
311 } else {\r
312 //\r
313 // Change the resolution and resize of the window\r
314 //\r
315\r
316 //\r
317 // Free the old buffer. We do not save the content of the old buffer since the\r
318 // screen is to be cleared anyway. Clearing the screen is required by the EFI spec.\r
319 // See UEFI spec -EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()\r
320 //\r
321 Private->WinNtThunk->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo);\r
322\r
323 //\r
324 // Allocate DIB frame buffer directly from NT for performance enhancement\r
325 // This buffer is the virtual screen/frame buffer. This buffer is not the\r
326 // same a a frame buffer. The first row of this buffer will be the bottom\r
327 // line of the image. This is an artifact of the way we draw to the screen.\r
328 //\r
329 Size = ModeData->HorizontalResolution * ModeData->VerticalResolution * sizeof (RGBQUAD) + sizeof (BITMAPV4HEADER);\r
330 Private->VirtualScreenInfo = Private->WinNtThunk->HeapAlloc (\r
331 Private->WinNtThunk->GetProcessHeap (),\r
332 HEAP_ZERO_MEMORY,\r
333 Size\r
334 );\r
335\r
336 //\r
337 // Update the virtual screen info data structure\r
338 //\r
339 Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);\r
340 Private->VirtualScreenInfo->bV4Width = ModeData->HorizontalResolution;\r
341 Private->VirtualScreenInfo->bV4Height = ModeData->VerticalResolution;\r
342 Private->VirtualScreenInfo->bV4Planes = 1;\r
343 Private->VirtualScreenInfo->bV4BitCount = 32;\r
344 //\r
345 // uncompressed\r
346 //\r
347 Private->VirtualScreenInfo->bV4V4Compression = BI_RGB;\r
348\r
349 //\r
350 // The rest of the allocated memory block is the virtual screen buffer\r
351 //\r
352 Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1);\r
353\r
354 //\r
355 // Use the AdjuctWindowRect fuction to calculate the real width and height\r
356 // of the new window including the border and caption\r
357 //\r
358 Rect.left = 0;\r
359 Rect.top = 0;\r
360 Rect.right = ModeData->HorizontalResolution;\r
361 Rect.bottom = ModeData->VerticalResolution;\r
362\r
363 Private->WinNtThunk->AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);\r
364\r
365 Width = Rect.right - Rect.left;\r
366 Height = Rect.bottom - Rect.top;\r
367\r
368 //\r
369 // Retrieve the original window position information\r
370 //\r
371 Private->WinNtThunk->GetWindowRect (Private->WindowHandle, &Rect);\r
372\r
373 //\r
374 // Adjust the window size\r
375 //\r
f66a43b2 376 Private->WinNtThunk->MoveWindow (Private->WindowHandle, Rect.left, Rect.top, (INT32)Width, (INT32)Height, TRUE);\r
c9fc89a3 377\r
378 }\r
379\r
380 NewFillLine = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->HorizontalResolution);\r
381 if (NewFillLine == NULL) {\r
382 return EFI_DEVICE_ERROR;\r
383 }\r
384\r
385 if (Private->FillLine != NULL) {\r
386 FreePool (Private->FillLine);\r
387 }\r
388\r
389 Private->FillLine = NewFillLine;\r
390\r
391 Fill.Red = 0x00;\r
392 Fill.Green = 0x00;\r
393 Fill.Blue = 0x00;\r
394 This->Blt (\r
395 This,\r
396 &Fill,\r
397 EfiBltVideoFill,\r
398 0,\r
399 0,\r
400 0,\r
401 0,\r
402 ModeData->HorizontalResolution,\r
403 ModeData->VerticalResolution,\r
404 ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
405 );\r
406 return EFI_SUCCESS;\r
407}\r
408\r
409\r
410/**\r
411 Blt pixels from the rectangle (Width X Height) formed by the BltBuffer\r
412 onto the graphics screen starting a location (X, Y). (0, 0) is defined as\r
413 the upper left hand side of the screen. (X, Y) can be outside of the\r
414 current screen geometry and the BltBuffer will be cliped when it is\r
415 displayed. X and Y can be negative or positive. If Width or Height is\r
416 bigger than the current video screen the image will be clipped.\r
417\r
418 @param This Protocol instance pointer.\r
419 @param X X location on graphics screen.\r
420 @param Y Y location on the graphics screen.\r
421 @param Width Width of BltBuffer.\r
422 @param Height Hight of BltBuffer\r
423 @param BltOperation Operation to perform on BltBuffer and video memory\r
424 @param BltBuffer Buffer containing data to blt into video buffer.\r
425 This buffer has a size of\r
426 Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
427 @param SourceX If the BltOperation is a EfiCopyBlt this is the\r
428 source of the copy. For other BLT operations this\r
429 argument is not used.\r
430 @param SourceX If the BltOperation is a EfiCopyBlt this is the\r
431 source of the copy. For other BLT operations this\r
432 argument is not used.\r
433\r
434 @retval EFI_SUCCESS The palette is updated with PaletteArray.\r
435 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
436 @retval EFI_DEVICE_ERROR A hardware error occured writting to the video\r
437 buffer.\r
438\r
439**/\r
440// TODO: SourceY - add argument and description to function comment\r
441// TODO: DestinationX - add argument and description to function comment\r
442// TODO: DestinationY - add argument and description to function comment\r
443// TODO: Delta - add argument and description to function comment\r
444EFI_STATUS\r
445EFIAPI\r
446WinNtGopBlt (\r
447 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
448 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
449 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
450 IN UINTN SourceX,\r
451 IN UINTN SourceY,\r
452 IN UINTN DestinationX,\r
453 IN UINTN DestinationY,\r
454 IN UINTN Width,\r
455 IN UINTN Height,\r
456 IN UINTN Delta OPTIONAL\r
457 )\r
458{\r
459 GOP_PRIVATE_DATA *Private;\r
460 EFI_TPL OriginalTPL;\r
461 UINTN DstY;\r
462 UINTN SrcY;\r
463 RGBQUAD *VScreen;\r
464 RGBQUAD *VScreenSrc;\r
465 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
466 UINTN Index;\r
467 RECT Rect;\r
468 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FillPixel;\r
469 UINT32 VerticalResolution;\r
470 UINT32 HorizontalResolution;\r
471\r
472 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
473\r
474 if ((BltOperation < 0) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {\r
475 return EFI_INVALID_PARAMETER;\r
476 }\r
477\r
478 if (Width == 0 || Height == 0) {\r
479 return EFI_INVALID_PARAMETER;\r
480 }\r
481 //\r
482 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
483 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
484 // the number of bytes in each row can be computed.\r
485 //\r
486 if (Delta == 0) {\r
487 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
488 }\r
489\r
490 //\r
491 // We need to fill the Virtual Screen buffer with the blt data.\r
492 // The virtual screen is upside down, as the first row is the bootom row of\r
493 // the image.\r
494 //\r
495 VerticalResolution = This->Mode->Info->VerticalResolution;\r
496 HorizontalResolution = This->Mode->Info->HorizontalResolution;\r
497 if (BltOperation == EfiBltVideoToBltBuffer) {\r
498\r
499 //\r
500 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
501 //\r
502 if (SourceY + Height > VerticalResolution) {\r
503 return EFI_INVALID_PARAMETER;\r
504 }\r
505\r
506 if (SourceX + Width > HorizontalResolution) {\r
507 return EFI_INVALID_PARAMETER;\r
508 }\r
509 //\r
510 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
511 // We would not want a timer based event (Cursor, ...) to come in while we are\r
512 // doing this operation.\r
513 //\r
514 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
515\r
516 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
517 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
518 VScreen = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + SourceX];\r
519 CopyMem (Blt, VScreen, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Width);\r
520 }\r
521 } else {\r
522 //\r
523 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
524 //\r
525 if (DestinationY + Height > VerticalResolution) {\r
526 return EFI_INVALID_PARAMETER;\r
527 }\r
528\r
529 if (DestinationX + Width > HorizontalResolution) {\r
530 return EFI_INVALID_PARAMETER;\r
531 }\r
532\r
533 //\r
534 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
535 // We would not want a timer based event (Cursor, ...) to come in while we are\r
536 // doing this operation.\r
537 //\r
538 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
539\r
540 if (BltOperation == EfiBltVideoFill) {\r
541 FillPixel = BltBuffer;\r
542 for (Index = 0; Index < Width; Index++) {\r
543 Private->FillLine[Index] = *FillPixel;\r
544 }\r
545 }\r
546\r
547 for (Index = 0; Index < Height; Index++) {\r
548 if (DestinationY <= SourceY) {\r
549 SrcY = SourceY + Index;\r
550 DstY = DestinationY + Index;\r
551 } else {\r
552 SrcY = SourceY + Height - Index - 1;\r
553 DstY = DestinationY + Height - Index - 1;\r
554 }\r
555\r
556 VScreen = &Private->VirtualScreen[(VerticalResolution - DstY - 1) * HorizontalResolution + DestinationX];\r
557 switch (BltOperation) {\r
558 case EfiBltBufferToVideo:\r
559 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
560 CopyMem (VScreen, Blt, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
561 break;\r
562\r
563 case EfiBltVideoToVideo:\r
564 VScreenSrc = &Private->VirtualScreen[(VerticalResolution - SrcY - 1) * HorizontalResolution + SourceX];\r
565 CopyMem (VScreen, VScreenSrc, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
566 break;\r
567\r
568 case EfiBltVideoFill:\r
569 CopyMem (VScreen, Private->FillLine, Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
570 break;\r
571 }\r
572 }\r
573 }\r
574\r
575 if (BltOperation != EfiBltVideoToBltBuffer) {\r
576 //\r
577 // Mark the area we just blted as Invalid so WM_PAINT will update.\r
578 //\r
f66a43b2
JM
579 Rect.left = (LONG)DestinationX;\r
580 Rect.top = (LONG)DestinationY;\r
581 Rect.right = (LONG)(DestinationX + Width);\r
582 Rect.bottom = (LONG)(DestinationY + Height);\r
c9fc89a3 583 Private->WinNtThunk->InvalidateRect (Private->WindowHandle, &Rect, FALSE);\r
584\r
585 //\r
586 // Send the WM_PAINT message to the thread that is drawing the window. We\r
587 // are in the main thread and the window drawing is in a child thread.\r
588 // There is a child thread per window. We have no CriticalSection or Mutex\r
589 // since we write the data and the other thread displays the data. While\r
590 // we may miss some data for a short period of time this is no different than\r
591 // a write combining on writes to a frame buffer.\r
592 //\r
593\r
594 Private->WinNtThunk->UpdateWindow (Private->WindowHandle);\r
595 }\r
596\r
597 gBS->RestoreTPL (OriginalTPL);\r
598\r
599 return EFI_SUCCESS;\r
600}\r
601\r
602//\r
603// Construction and Destruction functions\r
604//\r
605\r
606\r
607/**\r
608\r
609\r
610 @return None\r
611\r
612**/\r
613// TODO: WinNtIo - add argument and description to function comment\r
614// TODO: EFI_UNSUPPORTED - add return value to function comment\r
615// TODO: EFI_SUCCESS - add return value to function comment\r
616EFI_STATUS\r
617WinNtGopSupported (\r
618 IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo\r
619 )\r
620{\r
621 //\r
622 // Check to see if the IO abstraction represents a device type we support.\r
623 //\r
624 // This would be replaced a check of PCI subsystem ID, etc.\r
625 //\r
626 if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtGopGuid)) {\r
627 return EFI_UNSUPPORTED;\r
628 }\r
629\r
630 return EFI_SUCCESS;\r
631}\r
632\r
633\r
634/**\r
635 Win32 Windows event handler.\r
636\r
637 See Win32 Book\r
638\r
639 @return See Win32 Book\r
640\r
641**/\r
642// TODO: hwnd - add argument and description to function comment\r
643// TODO: iMsg - add argument and description to function comment\r
644// TODO: wParam - add argument and description to function comment\r
645// TODO: lParam - add argument and description to function comment\r
646LRESULT\r
647CALLBACK\r
648WinNtGopThreadWindowProc (\r
649 IN HWND hwnd,\r
650 IN UINT iMsg,\r
651 IN WPARAM wParam,\r
652 IN LPARAM lParam\r
653 )\r
654{\r
655 GOP_PRIVATE_DATA *Private;\r
656 UINTN Size;\r
657 HDC Handle;\r
658 PAINTSTRUCT PaintStruct;\r
659 LPARAM Index;\r
660 EFI_INPUT_KEY Key;\r
df7499fc 661 BOOLEAN AltIsPress;\r
c9fc89a3 662\r
663 //\r
664 // BugBug - if there are two instances of this DLL in memory (such as is\r
665 // the case for ERM), the correct instance of this function may not be called.\r
666 // This also means that the address of the mTlsIndex value will be wrong, and\r
667 // the value may be wrong too.\r
668 //\r
669\r
670\r
671 //\r
672 // Use mTlsIndex global to get a Thread Local Storage version of Private.\r
673 // This works since each Gop protocol has a unique Private data instance and\r
674 // a unique thread.\r
675 //\r
df7499fc 676 AltIsPress = FALSE;\r
c9fc89a3 677 Private = mWinNt->TlsGetValue (mTlsIndex);\r
678 ASSERT (NULL != Private);\r
679\r
680 switch (iMsg) {\r
681 case WM_CREATE:\r
682 Size = Private->GraphicsOutput.Mode->Info->HorizontalResolution * Private->GraphicsOutput.Mode->Info->VerticalResolution * sizeof (RGBQUAD);\r
683\r
684 //\r
685 // Allocate DIB frame buffer directly from NT for performance enhancement\r
686 // This buffer is the virtual screen/frame buffer. This buffer is not the\r
687 // same a a frame buffer. The first fow of this buffer will be the bottom\r
688 // line of the image. This is an artifact of the way we draw to the screen.\r
689 //\r
690 Private->VirtualScreenInfo = Private->WinNtThunk->HeapAlloc (\r
691 Private->WinNtThunk->GetProcessHeap (),\r
692 HEAP_ZERO_MEMORY,\r
693 Size\r
694 );\r
695\r
696 Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER);\r
697 Private->VirtualScreenInfo->bV4Width = Private->GraphicsOutput.Mode->Info->HorizontalResolution;\r
698 Private->VirtualScreenInfo->bV4Height = Private->GraphicsOutput.Mode->Info->VerticalResolution;\r
699 Private->VirtualScreenInfo->bV4Planes = 1;\r
700 Private->VirtualScreenInfo->bV4BitCount = 32;\r
701 //\r
702 // uncompressed\r
703 //\r
704 Private->VirtualScreenInfo->bV4V4Compression = BI_RGB;\r
705 Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1);\r
706 return 0;\r
707\r
708 case WM_PAINT:\r
709 //\r
710 // I have not found a way to convert hwnd into a Private context. So for\r
711 // now we use this API to convert hwnd to Private data.\r
712 //\r
713\r
714 Handle = mWinNt->BeginPaint (hwnd, &PaintStruct);\r
715\r
716 mWinNt->SetDIBitsToDevice (\r
717 Handle, // Destination Device Context\r
718 0, // Destination X - 0\r
719 0, // Destination Y - 0\r
720 Private->GraphicsOutput.Mode->Info->HorizontalResolution, // Width\r
721 Private->GraphicsOutput.Mode->Info->VerticalResolution, // Height\r
722 0, // Source X\r
723 0, // Source Y\r
724 0, // DIB Start Scan Line\r
725 Private->GraphicsOutput.Mode->Info->VerticalResolution, // Number of scan lines\r
726 Private->VirtualScreen, // Address of array of DIB bits\r
727 (BITMAPINFO *) Private->VirtualScreenInfo, // Address of structure with bitmap info\r
728 DIB_RGB_COLORS // RGB or palette indexes\r
729 );\r
730\r
731 mWinNt->EndPaint (hwnd, &PaintStruct);\r
732 return 0;\r
733\r
734 //\r
735 // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case\r
df7499fc 736 // WM_SYSKEYDOWN is posted when F10 is pressed or\r
62cf113f 737 // holds down ALT key and then presses another key.\r
c9fc89a3 738 //\r
739 case WM_SYSKEYDOWN:\r
df7499fc 740\r
741 Key.ScanCode = 0;\r
742 Key.UnicodeChar = CHAR_NULL;\r
c9fc89a3 743 switch (wParam) {\r
744 case VK_F10:\r
745 Key.ScanCode = SCAN_F10;\r
df7499fc 746 Key.UnicodeChar = CHAR_NULL;\r
66fe7146 747 GopPrivateAddKey (Private, Key);\r
c9fc89a3 748 return 0;\r
749 }\r
c9fc89a3 750\r
df7499fc 751 //\r
752 // If ALT or ALT + modifier key is pressed.\r
753 //\r
754 if (WinNtGopConvertParamToEfiKey (Private, &wParam, &lParam, &Key)) {\r
755 if (Key.ScanCode != 0){\r
756 //\r
757 // If ALT is pressed with other ScanCode.\r
758 // Always revers the left Alt for simple.\r
759 //\r
62cf113f 760 Private->LeftAlt = TRUE;\r
761 }\r
66fe7146 762 GopPrivateAddKey (Private, Key);\r
df7499fc 763 //\r
764 // When Alt is released there is no windoes message, so \r
765 // clean it after using it.\r
766 //\r
767 Private->RightAlt = FALSE;\r
768 Private->LeftAlt = FALSE;\r
769 return 0;\r
62cf113f 770 }\r
df7499fc 771 AltIsPress = TRUE;\r
62cf113f 772\r
df7499fc 773 case WM_CHAR: \r
774 //\r
775 // The ESC key also generate WM_CHAR.\r
776 //\r
777 if (wParam == 0x1B) {\r
af1600fd 778 return 0;\r
df7499fc 779 } \r
62cf113f 780\r
df7499fc 781 if (AltIsPress == TRUE) {\r
62cf113f 782 //\r
df7499fc 783 // If AltIsPress is true that means the Alt key is pressed.\r
62cf113f 784 //\r
df7499fc 785 Private->LeftAlt = TRUE;\r
786 }\r
787 for (Index = 0; Index < (lParam & 0xffff); Index++) {\r
788 if (wParam != 0) {\r
789 Key.UnicodeChar = (CHAR16) wParam;\r
790 Key.ScanCode = SCAN_NULL; \r
791 GopPrivateAddKey (Private, Key); \r
792 }\r
793 }\r
794 if (AltIsPress == TRUE) {\r
62cf113f 795 //\r
df7499fc 796 // When Alt is released there is no windoes message, so \r
797 // clean it after using it.\r
62cf113f 798 //\r
df7499fc 799 Private->LeftAlt = FALSE;\r
62cf113f 800 Private->RightAlt = FALSE;\r
c9fc89a3 801 }\r
62cf113f 802 return 0;\r
803\r
df7499fc 804 case WM_SYSKEYUP:\r
805 //\r
806 // ALT is pressed with another key released\r
807 //\r
808 WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, &lParam, FALSE);\r
62cf113f 809 return 0;\r
810\r
df7499fc 811 case WM_KEYDOWN:\r
af1600fd 812 Key.ScanCode = SCAN_NULL;\r
813 Key.UnicodeChar = CHAR_NULL;\r
c9fc89a3 814 //\r
df7499fc 815 // A value key press will cause a WM_KEYDOWN first, then cause a WM_CHAR\r
816 // So if there is no modifier key updated, skip the WM_KEYDOWN even.\r
c9fc89a3 817 //\r
df7499fc 818 if (WinNtGopConvertParamToEfiKey (Private, &wParam, &lParam, &Key)) {\r
df7499fc 819 //\r
820 // Support the partial keystroke, add all keydown event into the queue.\r
821 //\r
822 GopPrivateAddKey (Private, Key);\r
c9fc89a3 823 }\r
df7499fc 824 return 0;\r
c9fc89a3 825\r
df7499fc 826 case WM_KEYUP:\r
827 WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, &lParam, FALSE);\r
c9fc89a3 828 return 0;\r
829\r
830 case WM_CLOSE:\r
831 //\r
832 // This close message is issued by user, core is not aware of this,\r
833 // so don't release the window display resource, just hide the window.\r
834 //\r
835 Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_HIDE);\r
836 return 0;\r
837\r
838 case WM_DESTROY:\r
839 mWinNt->DestroyWindow (hwnd);\r
840 mWinNt->PostQuitMessage (0);\r
841\r
842 mWinNt->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo);\r
843\r
844 mWinNt->ExitThread (0);\r
845 return 0;\r
846\r
847 default:\r
848 break;\r
849 };\r
850\r
851 return mWinNt->DefWindowProc (hwnd, iMsg, wParam, lParam);\r
852}\r
853\r
854\r
855/**\r
856 This thread simulates the end of WinMain () aplication. Each Winow nededs\r
857 to process it's events. The messages are dispatched to\r
858 WinNtGopThreadWindowProc ().\r
859 Be very careful sine WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()\r
860 are running in a seperate thread. We have to do this to process the events.\r
861\r
862 @param lpParameter Handle of window to manage.\r
863\r
864 @return if a WM_QUIT message is returned exit.\r
865\r
866**/\r
867DWORD\r
868WINAPI\r
869WinNtGopThreadWinMain (\r
870 LPVOID lpParameter\r
871 )\r
872{\r
873 MSG Message;\r
874 GOP_PRIVATE_DATA *Private;\r
c9fc89a3 875 RECT Rect;\r
876\r
877 Private = (GOP_PRIVATE_DATA *) lpParameter;\r
878 ASSERT (NULL != Private);\r
879\r
880 //\r
881 // Since each thread has unique private data, save the private data in Thread\r
882 // Local Storage slot. Then the shared global mTlsIndex can be used to get\r
883 // thread specific context.\r
884 //\r
885 Private->WinNtThunk->TlsSetValue (mTlsIndex, Private);\r
886\r
887 Private->ThreadId = Private->WinNtThunk->GetCurrentThreadId ();\r
888\r
889 Private->WindowsClass.cbSize = sizeof (WNDCLASSEX);\r
890 Private->WindowsClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;\r
891 Private->WindowsClass.lpfnWndProc = WinNtGopThreadWindowProc;\r
892 Private->WindowsClass.cbClsExtra = 0;\r
893 Private->WindowsClass.cbWndExtra = 0;\r
894 Private->WindowsClass.hInstance = NULL;\r
895 Private->WindowsClass.hIcon = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION);\r
896 Private->WindowsClass.hCursor = Private->WinNtThunk->LoadCursor (NULL, IDC_ARROW);\r
f66a43b2 897 Private->WindowsClass.hbrBackground = (HBRUSH)(UINTN)COLOR_WINDOW;\r
c9fc89a3 898 Private->WindowsClass.lpszMenuName = NULL;\r
899 Private->WindowsClass.lpszClassName = WIN_NT_GOP_CLASS_NAME;\r
900 Private->WindowsClass.hIconSm = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION);\r
901\r
902 //\r
903 // This call will fail after the first time, but thats O.K. since we only need\r
904 // WIN_NT_GOP_CLASS_NAME to exist to create the window.\r
905 //\r
906 // Note: Multiple instances of this DLL will use the same instance of this\r
907 // Class, including the callback function, unless the Class is unregistered and\r
908 // successfully registered again.\r
909 //\r
a00ec39b 910 Private->WinNtThunk->RegisterClassEx (&Private->WindowsClass);\r
c9fc89a3 911\r
912 //\r
913 // Setting Rect values to allow for the AdjustWindowRect to provide\r
914 // us the correct sizes for the client area when doing the CreateWindowEx\r
915 //\r
916 Rect.top = 0;\r
917 Rect.bottom = Private->GraphicsOutput.Mode->Info->VerticalResolution;\r
918 Rect.left = 0;\r
919 Rect.right = Private->GraphicsOutput.Mode->Info->HorizontalResolution;\r
920\r
921 Private->WinNtThunk->AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0);\r
922\r
923 Private->WindowHandle = Private->WinNtThunk->CreateWindowEx (\r
924 0,\r
925 WIN_NT_GOP_CLASS_NAME,\r
926 Private->WindowName,\r
927 WS_OVERLAPPEDWINDOW,\r
928 CW_USEDEFAULT,\r
929 CW_USEDEFAULT,\r
930 Rect.right - Rect.left,\r
931 Rect.bottom - Rect.top,\r
932 NULL,\r
933 NULL,\r
934 NULL,\r
a00ec39b 935 (VOID **)&Private\r
c9fc89a3 936 );\r
937\r
938 //\r
939 // The reset of this thread is the standard winows program. We need a sperate\r
940 // thread since we must process the message loop to make windows act like\r
941 // windows.\r
942 //\r
943\r
944 Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_SHOW);\r
945 Private->WinNtThunk->UpdateWindow (Private->WindowHandle);\r
946\r
947 //\r
948 // Let the main thread get some work done\r
949 //\r
950 Private->WinNtThunk->ReleaseSemaphore (Private->ThreadInited, 1, NULL);\r
951\r
952 //\r
953 // This is the message loop that all Windows programs need.\r
954 //\r
955 while (Private->WinNtThunk->GetMessage (&Message, Private->WindowHandle, 0, 0)) {\r
956 Private->WinNtThunk->TranslateMessage (&Message);\r
957 Private->WinNtThunk->DispatchMessage (&Message);\r
958 }\r
959\r
f66a43b2 960 return (DWORD)Message.wParam;\r
c9fc89a3 961}\r
962\r
963\r
964/**\r
965 TODO: Add function description\r
966\r
967 @param Private TODO: add argument description\r
968 @param HorizontalResolution TODO: add argument description\r
969 @param VerticalResolution TODO: add argument description\r
970 @param ColorDepth TODO: add argument description\r
971 @param RefreshRate TODO: add argument description\r
972\r
973 @return TODO: add return values\r
974\r
975**/\r
976EFI_STATUS\r
977WinNtGopStartWindow (\r
978 IN GOP_PRIVATE_DATA *Private,\r
979 IN UINT32 HorizontalResolution,\r
980 IN UINT32 VerticalResolution,\r
981 IN UINT32 ColorDepth,\r
982 IN UINT32 RefreshRate\r
983 )\r
984{\r
985 EFI_STATUS Status;\r
986 DWORD NewThreadId;\r
987\r
988 mWinNt = Private->WinNtThunk;\r
989\r
990 //\r
991 // Initialize a Thread Local Storge variable slot. We use TLS to get the\r
992 // correct Private data instance into the windows thread.\r
993 //\r
994 if (mTlsIndex == TLS_OUT_OF_INDEXES) {\r
995 ASSERT (0 == mTlsIndexUseCount);\r
996 mTlsIndex = Private->WinNtThunk->TlsAlloc ();\r
997 }\r
998\r
999 //\r
1000 // always increase the use count!\r
1001 //\r
1002 mTlsIndexUseCount++;\r
1003\r
1004 //\r
1005 // Register to be notified on exit boot services so we can destroy the window.\r
1006 //\r
ae66d8de 1007 Status = gBS->CreateEventEx (\r
1008 EVT_NOTIFY_SIGNAL,\r
c9fc89a3 1009 TPL_CALLBACK,\r
1010 KillNtGopThread,\r
1011 Private,\r
ae66d8de 1012 &gEfiEventExitBootServicesGuid,\r
c9fc89a3 1013 &mGopScreenExitBootServicesEvent\r
1014 );\r
1015\r
1016 Private->ThreadInited = Private->WinNtThunk->CreateSemaphore (NULL, 0, 1, NULL);\r
1017 Private->ThreadHandle = Private->WinNtThunk->CreateThread (\r
1018 NULL,\r
1019 0,\r
1020 WinNtGopThreadWinMain,\r
1021 (VOID *) Private,\r
1022 0,\r
1023 &NewThreadId\r
1024 );\r
1025\r
1026 //\r
1027 // The other thread has entered the windows message loop so we can\r
1028 // continue our initialization.\r
1029 //\r
1030 Private->WinNtThunk->WaitForSingleObject (Private->ThreadInited, INFINITE);\r
1031 Private->WinNtThunk->CloseHandle (Private->ThreadInited);\r
1032\r
1033 return Status;\r
1034}\r
1035\r
1036\r
1037/**\r
1038\r
1039\r
1040 @return None\r
1041\r
1042**/\r
1043// TODO: Private - add argument and description to function comment\r
1044// TODO: EFI_SUCCESS - add return value to function comment\r
1045EFI_STATUS\r
1046WinNtGopConstructor (\r
1047 GOP_PRIVATE_DATA *Private\r
1048 )\r
1049{\r
1050 Private->ModeData = mGopModeData;\r
1051\r
1052 Private->GraphicsOutput.QueryMode = WinNtGopQuerytMode;\r
1053 Private->GraphicsOutput.SetMode = WinNtGopSetMode;\r
1054 Private->GraphicsOutput.Blt = WinNtGopBlt;\r
1055\r
1056 //\r
1057 // Allocate buffer for Graphics Output Protocol mode information\r
1058 //\r
1059 Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));\r
1060 if (Private->GraphicsOutput.Mode == NULL) {\r
1061 return EFI_OUT_OF_RESOURCES;\r
1062 }\r
1063 Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
1064 if (Private->GraphicsOutput.Mode->Info == NULL) {\r
1065 return EFI_OUT_OF_RESOURCES;\r
1066 }\r
1067\r
1068 Private->GraphicsOutput.Mode->MaxMode = sizeof(mGopModeData) / sizeof(GOP_MODE_DATA);\r
1069 //\r
1070 // Till now, we have no idea about the window size.\r
1071 //\r
1072 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1073 Private->GraphicsOutput.Mode->Info->Version = 0;\r
1074 Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;\r
1075 Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;\r
1076 Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;\r
1077 Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1be0dda6 1078 Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;\r
c9fc89a3 1079 Private->GraphicsOutput.Mode->FrameBufferSize = 0;\r
1080\r
1081 Private->HardwareNeedsStarting = TRUE;\r
1082 Private->FillLine = NULL;\r
1083\r
1084 WinNtGopInitializeSimpleTextInForWindow (Private);\r
1085\r
1086 return EFI_SUCCESS;\r
1087}\r
1088\r
1089\r
1090/**\r
1091\r
1092\r
1093 @return None\r
1094\r
1095**/\r
1096// TODO: Private - add argument and description to function comment\r
1097// TODO: EFI_SUCCESS - add return value to function comment\r
1098EFI_STATUS\r
1099WinNtGopDestructor (\r
1100 GOP_PRIVATE_DATA *Private\r
1101 )\r
1102{\r
c9fc89a3 1103 if (!Private->HardwareNeedsStarting) {\r
1104 //\r
1105 // BugBug: Shutdown GOP Hardware and any child devices.\r
1106 //\r
1107 Private->WinNtThunk->SendMessage (Private->WindowHandle, WM_DESTROY, 0, 0);\r
1108 Private->WinNtThunk->CloseHandle (Private->ThreadHandle);\r
1109\r
1110 mTlsIndexUseCount--;\r
1111\r
1112 //\r
1113 // The callback function for another window could still be called,\r
1114 // so we need to make sure there are no more users of mTlsIndex.\r
1115 //\r
1116 if (0 == mTlsIndexUseCount) {\r
1117 ASSERT (TLS_OUT_OF_INDEXES != mTlsIndex);\r
1118\r
1119 Private->WinNtThunk->TlsFree (mTlsIndex);\r
1120 mTlsIndex = TLS_OUT_OF_INDEXES;\r
1121\r
a00ec39b 1122 Private->WinNtThunk->UnregisterClass (\r
1123 Private->WindowsClass.lpszClassName,\r
1124 Private->WindowsClass.hInstance\r
1125 );\r
c9fc89a3 1126 }\r
1127\r
1128 WinNtGopDestroySimpleTextInForWindow (Private);\r
1129 }\r
1130\r
1131 //\r
1132 // Free graphics output protocol occupied resource\r
1133 //\r
1134 if (Private->GraphicsOutput.Mode != NULL) {\r
1135 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
1136 FreePool (Private->GraphicsOutput.Mode->Info);\r
1137 }\r
1138 FreePool (Private->GraphicsOutput.Mode);\r
1139 }\r
1140\r
1141 return EFI_SUCCESS;\r
1142}\r
1143\r
1144\r
1145/**\r
1146 This is the GOP screen's callback notification function for exit-boot-services.\r
1147 All we do here is call WinNtGopDestructor().\r
1148\r
1149 @param Event not used\r
1150 @param Context pointer to the Private structure.\r
1151\r
1152 @return None.\r
1153\r
1154**/\r
c9fc89a3 1155VOID\r
1156EFIAPI\r
1157KillNtGopThread (\r
1158 IN EFI_EVENT Event,\r
1159 IN VOID *Context\r
1160 )\r
1161{\r
a00ec39b 1162 WinNtGopDestructor (Context);\r
c9fc89a3 1163}\r