]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/EmuGopDxe/GopScreen.c
EmulatorPkg/EmuGopDxe: Set ModeInfo after Open successfully
[mirror_edk2.git] / EmulatorPkg / EmuGopDxe / GopScreen.c
CommitLineData
79e4f2a5
RN
1/*++ @file\r
2\r
b422b0fc 3Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>\r
79e4f2a5 4Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.\r
e3ba31da 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
79e4f2a5
RN
6\r
7Module Name:\r
8\r
9 EmuGopScreen.c\r
10\r
11Abstract:\r
12\r
13 This file produces the graphics abstration of UGA. It is called by\r
14 EmuGopDriver.c file which deals with the EFI 1.1 driver model.\r
15 This file just does graphics.\r
16\r
17**/\r
18\r
19#include "Gop.h"\r
20\r
a550d468 21EFI_EVENT mGopScreenExitBootServicesEvent;\r
79e4f2a5 22\r
a550d468
MK
23GOP_MODE_DATA mGopModeData[] = {\r
24 { 800, 600, 0, 0 },\r
25 { 640, 480, 0, 0 },\r
26 { 720, 400, 0, 0 },\r
27 { 1024, 768, 0, 0 },\r
28 { 1280, 1024, 0, 0 }\r
29};\r
79e4f2a5
RN
30\r
31/**\r
32 Returns information for an available graphics mode that the graphics device\r
33 and the set of active video output devices supports.\r
34\r
35 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.\r
36 @param ModeNumber The mode number to return information on.\r
37 @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer.\r
38 @param Info A pointer to callee allocated buffer that returns information about ModeNumber.\r
39\r
40 @retval EFI_SUCCESS Mode information returned.\r
41 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.\r
42 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode.\r
43 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
44 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
45\r
46**/\r
47EFI_STATUS\r
48EFIAPI\r
49EmuGopQuerytMode (\r
50 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
51 IN UINT32 ModeNumber,\r
52 OUT UINTN *SizeOfInfo,\r
53 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
54 )\r
55{\r
56 GOP_PRIVATE_DATA *Private;\r
57\r
58 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
59\r
a550d468 60 if ((Info == NULL) || (SizeOfInfo == NULL) || ((UINTN)ModeNumber >= This->Mode->MaxMode)) {\r
79e4f2a5
RN
61 return EFI_INVALID_PARAMETER;\r
62 }\r
63\r
64 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
65 if (*Info == NULL) {\r
66 return EFI_OUT_OF_RESOURCES;\r
67 }\r
68\r
69 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
70\r
a550d468 71 (*Info)->Version = 0;\r
79e4f2a5
RN
72 (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;\r
73 (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution;\r
a550d468
MK
74 (*Info)->PixelFormat = PixelBltOnly;\r
75 (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;\r
79e4f2a5
RN
76\r
77 return EFI_SUCCESS;\r
78}\r
79\r
79e4f2a5
RN
80/**\r
81 Set the video device into the specified mode and clears the visible portions of\r
82 the output display to black.\r
83\r
84 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.\r
85 @param ModeNumber Abstraction that defines the current video mode.\r
86\r
87 @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected.\r
88 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.\r
89 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
90\r
91**/\r
92EFI_STATUS\r
93EFIAPI\r
94EmuGopSetMode (\r
95 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
96 IN UINT32 ModeNumber\r
97 )\r
98{\r
a550d468
MK
99 EFI_STATUS Status;\r
100 GOP_PRIVATE_DATA *Private;\r
101 GOP_MODE_DATA *ModeData;\r
102 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;\r
79e4f2a5
RN
103\r
104 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
105\r
106 if (ModeNumber >= This->Mode->MaxMode) {\r
107 return EFI_UNSUPPORTED;\r
108 }\r
109\r
b422b0fc 110 ModeData = &Private->ModeData[ModeNumber];\r
79e4f2a5
RN
111\r
112 if (Private->HardwareNeedsStarting) {\r
113 Status = EmuGopStartWindow (\r
a550d468
MK
114 Private,\r
115 ModeData->HorizontalResolution,\r
116 ModeData->VerticalResolution,\r
117 ModeData->ColorDepth,\r
118 ModeData->RefreshRate\r
119 );\r
79e4f2a5
RN
120 if (EFI_ERROR (Status)) {\r
121 return EFI_DEVICE_ERROR;\r
122 }\r
123\r
124 Private->HardwareNeedsStarting = FALSE;\r
125 }\r
126\r
b422b0fc
GJ
127 This->Mode->Mode = ModeNumber;\r
128 Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
129 Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
130 Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;\r
131\r
a550d468
MK
132 Status = Private->EmuGraphicsWindow->Size (\r
133 Private->EmuGraphicsWindow,\r
134 ModeData->HorizontalResolution,\r
135 ModeData->VerticalResolution\r
136 );\r
79e4f2a5 137\r
ce8c1d92
RN
138 Fill.Red = 0;\r
139 Fill.Green = 0;\r
140 Fill.Blue = 0;\r
79e4f2a5
RN
141 This->Blt (\r
142 This,\r
143 &Fill,\r
144 EfiBltVideoFill,\r
145 0,\r
146 0,\r
147 0,\r
148 0,\r
149 ModeData->HorizontalResolution,\r
150 ModeData->VerticalResolution,\r
151 ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
152 );\r
153 return EFI_SUCCESS;\r
154}\r
155\r
79e4f2a5
RN
156/**\r
157 Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.\r
158\r
159 @param This Protocol instance pointer.\r
160 @param BltBuffer Buffer containing data to blit into video buffer. This\r
161 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
162 @param BltOperation Operation to perform on BlitBuffer and video memory\r
163 @param SourceX X coordinate of source for the BltBuffer.\r
164 @param SourceY Y coordinate of source for the BltBuffer.\r
165 @param DestinationX X coordinate of destination for the BltBuffer.\r
166 @param DestinationY Y coordinate of destination for the BltBuffer.\r
167 @param Width Width of rectangle in BltBuffer in pixels.\r
168 @param Height Hight of rectangle in BltBuffer in pixels.\r
169 @param Delta OPTIONAL\r
170\r
171 @retval EFI_SUCCESS The Blt operation completed.\r
172 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
f034c05c 173 @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video buffer.\r
79e4f2a5
RN
174\r
175**/\r
176EFI_STATUS\r
177EFIAPI\r
178EmuGopBlt (\r
a550d468
MK
179 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
180 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
181 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
182 IN UINTN SourceX,\r
183 IN UINTN SourceY,\r
184 IN UINTN DestinationX,\r
185 IN UINTN DestinationY,\r
186 IN UINTN Width,\r
187 IN UINTN Height,\r
188 IN UINTN Delta OPTIONAL\r
79e4f2a5
RN
189 )\r
190{\r
a550d468
MK
191 GOP_PRIVATE_DATA *Private;\r
192 EFI_TPL OriginalTPL;\r
193 EFI_STATUS Status;\r
194 EMU_GRAPHICS_WINDOWS__BLT_ARGS GopBltArgs;\r
79e4f2a5
RN
195\r
196 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
197\r
198 if ((UINT32)BltOperation >= EfiGraphicsOutputBltOperationMax) {\r
199 return EFI_INVALID_PARAMETER;\r
200 }\r
201\r
a550d468 202 if ((Width == 0) || (Height == 0)) {\r
79e4f2a5
RN
203 return EFI_INVALID_PARAMETER;\r
204 }\r
a550d468 205\r
79e4f2a5
RN
206 //\r
207 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
208 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
209 // the number of bytes in each row can be computed.\r
210 //\r
211 if (Delta == 0) {\r
212 Delta = Width * sizeof (EFI_UGA_PIXEL);\r
213 }\r
214\r
215 //\r
216 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
217 // We would not want a timer based event (Cursor, ...) to come in while we are\r
218 // doing this operation.\r
219 //\r
220 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
221\r
222 //\r
223 // Pack UGA Draw protocol parameters to EMU_GRAPHICS_WINDOWS__BLT_ARGS structure to adapt to\r
224 // GopBlt() API of Unix UGA IO protocol.\r
225 //\r
226 GopBltArgs.DestinationX = DestinationX;\r
227 GopBltArgs.DestinationY = DestinationY;\r
228 GopBltArgs.Height = Height;\r
229 GopBltArgs.Width = Width;\r
230 GopBltArgs.SourceX = SourceX;\r
231 GopBltArgs.SourceY = SourceY;\r
232 GopBltArgs.Delta = Delta;\r
a550d468
MK
233 Status = Private->EmuGraphicsWindow->Blt (\r
234 Private->EmuGraphicsWindow,\r
235 (EFI_UGA_PIXEL *)BltBuffer,\r
236 (EFI_UGA_BLT_OPERATION)BltOperation,\r
237 &GopBltArgs\r
238 );\r
79e4f2a5
RN
239\r
240 gBS->RestoreTPL (OriginalTPL);\r
241\r
242 return Status;\r
243}\r
244\r
79e4f2a5
RN
245//\r
246// Construction and Destruction functions\r
247//\r
248\r
249EFI_STATUS\r
250EmuGopSupported (\r
251 IN EMU_IO_THUNK_PROTOCOL *EmuIoThunk\r
252 )\r
253{\r
254 //\r
255 // Check to see if the IO abstraction represents a device type we support.\r
256 //\r
257 // This would be replaced a check of PCI subsystem ID, etc.\r
258 //\r
259 if (!CompareGuid (EmuIoThunk->Protocol, &gEmuGraphicsWindowProtocolGuid)) {\r
260 return EFI_UNSUPPORTED;\r
261 }\r
262\r
263 return EFI_SUCCESS;\r
264}\r
265\r
79e4f2a5
RN
266EFI_STATUS\r
267EmuGopStartWindow (\r
a550d468
MK
268 IN GOP_PRIVATE_DATA *Private,\r
269 IN UINT32 HorizontalResolution,\r
270 IN UINT32 VerticalResolution,\r
271 IN UINT32 ColorDepth,\r
272 IN UINT32 RefreshRate\r
79e4f2a5
RN
273 )\r
274{\r
a550d468 275 EFI_STATUS Status;\r
79e4f2a5
RN
276\r
277 //\r
278 // Register to be notified on exit boot services so we can destroy the window.\r
279 //\r
280 Status = gBS->CreateEvent (\r
281 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
282 TPL_CALLBACK,\r
283 ShutdownGopEvent,\r
284 Private,\r
285 &mGopScreenExitBootServicesEvent\r
286 );\r
287\r
288 Status = Private->EmuIoThunk->Open (Private->EmuIoThunk);\r
289 if (!EFI_ERROR (Status)) {\r
290 Private->EmuGraphicsWindow = Private->EmuIoThunk->Interface;\r
291\r
292 // Register callback to support RegisterKeyNotify()\r
a550d468
MK
293 Status = Private->EmuGraphicsWindow->RegisterKeyNotify (\r
294 Private->EmuGraphicsWindow,\r
295 GopPrivateMakeCallbackFunction,\r
296 GopPrivateBreakCallbackFunction,\r
297 Private\r
298 );\r
79e4f2a5
RN
299 ASSERT_EFI_ERROR (Status);\r
300 }\r
a550d468 301\r
79e4f2a5
RN
302 return Status;\r
303}\r
304\r
305EFI_STATUS\r
306EmuGopConstructor (\r
a550d468 307 GOP_PRIVATE_DATA *Private\r
79e4f2a5
RN
308 )\r
309{\r
310 Private->ModeData = mGopModeData;\r
311\r
a550d468
MK
312 Private->GraphicsOutput.QueryMode = EmuGopQuerytMode;\r
313 Private->GraphicsOutput.SetMode = EmuGopSetMode;\r
314 Private->GraphicsOutput.Blt = EmuGopBlt;\r
79e4f2a5
RN
315\r
316 //\r
317 // Allocate buffer for Graphics Output Protocol mode information\r
318 //\r
319 Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));\r
320 if (Private->GraphicsOutput.Mode == NULL) {\r
321 return EFI_OUT_OF_RESOURCES;\r
322 }\r
a550d468 323\r
79e4f2a5
RN
324 Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
325 if (Private->GraphicsOutput.Mode->Info == NULL) {\r
326 return EFI_OUT_OF_RESOURCES;\r
327 }\r
328\r
a550d468 329 Private->GraphicsOutput.Mode->MaxMode = sizeof (mGopModeData) / sizeof (GOP_MODE_DATA);\r
79e4f2a5
RN
330 //\r
331 // Till now, we have no idea about the window size.\r
332 //\r
a550d468
MK
333 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
334 Private->GraphicsOutput.Mode->Info->Version = 0;\r
79e4f2a5 335 Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;\r
a550d468
MK
336 Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;\r
337 Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;\r
338 Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
339 Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)(UINTN)NULL;\r
340 Private->GraphicsOutput.Mode->FrameBufferSize = 0;\r
79e4f2a5 341\r
a550d468
MK
342 Private->HardwareNeedsStarting = TRUE;\r
343 Private->EmuGraphicsWindow = NULL;\r
79e4f2a5
RN
344\r
345 EmuGopInitializeSimpleTextInForWindow (Private);\r
346\r
347 EmuGopInitializeSimplePointerForWindow (Private);\r
348\r
349 return EFI_SUCCESS;\r
350}\r
351\r
79e4f2a5
RN
352EFI_STATUS\r
353EmuGopDestructor (\r
a550d468 354 GOP_PRIVATE_DATA *Private\r
79e4f2a5
RN
355 )\r
356{\r
357 if (!Private->HardwareNeedsStarting) {\r
358 Private->EmuIoThunk->Close (Private->EmuIoThunk);\r
359 Private->EmuGraphicsWindow = NULL;\r
360 }\r
361\r
362 //\r
363 // Free graphics output protocol occupied resource\r
364 //\r
365 if (Private->GraphicsOutput.Mode != NULL) {\r
366 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
367 FreePool (Private->GraphicsOutput.Mode->Info);\r
368 }\r
a550d468 369\r
79e4f2a5
RN
370 FreePool (Private->GraphicsOutput.Mode);\r
371 }\r
372\r
373 return EFI_SUCCESS;\r
374}\r
375\r
79e4f2a5
RN
376VOID\r
377EFIAPI\r
378ShutdownGopEvent (\r
379 IN EFI_EVENT Event,\r
380 IN VOID *Context\r
381 )\r
a550d468 382\r
79e4f2a5
RN
383/*++\r
384\r
385Routine Description:\r
386\r
387 This is the UGA screen's callback notification function for exit-boot-services.\r
388 All we do here is call EmuGopDestructor().\r
389\r
390Arguments:\r
391\r
392 Event - not used\r
393 Context - pointer to the Private structure.\r
394\r
395Returns:\r
396\r
397 None.\r
398\r
399**/\r
400{\r
401 EmuGopDestructor (Context);\r
402}\r