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