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