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