VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxVgaDxe/VBoxVgaUgaDraw.c@ 75851

Last change on this file since 75851 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.5 KB
Line 
1/* $Id: VBoxVgaUgaDraw.c 69500 2017-10-28 15:14:05Z vboxsync $ */
2/** @file
3 * VBoxVgaUgaDraw.c
4 */
5
6/*
7 * Copyright (C) 2009-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*
28 This code is based on:
29
30 This file produces the graphics abstraction of UGA Draw. It is called by
31 VBoxVga.c file which deals with the EFI 1.1 driver model.
32 This file just does graphics.
33
34 Copyright (c) 2006, Intel Corporation
35 All rights reserved. This program and the accompanying materials
36 are licensed and made available under the terms and conditions of the BSD License
37 which accompanies this distribution. The full text of the license may be found at
38 http://opensource.org/licenses/bsd-license.php
39
40 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
41 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
42
43*/
44
45#include "VBoxVga.h"
46
47//
48// UGA Draw Protocol Member Functions
49//
50EFI_STATUS
51EFIAPI
52VBoxVgaUgaDrawGetMode (
53 IN EFI_UGA_DRAW_PROTOCOL *This,
54 OUT UINT32 *HorizontalResolution,
55 OUT UINT32 *VerticalResolution,
56 OUT UINT32 *ColorDepth,
57 OUT UINT32 *RefreshRate
58 )
59{
60 VBOX_VGA_PRIVATE_DATA *Private;
61
62 Private = VBOX_VGA_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
63
64 if (Private->HardwareNeedsStarting) {
65 return EFI_NOT_STARTED;
66 }
67
68 if ((HorizontalResolution == NULL) ||
69 (VerticalResolution == NULL) ||
70 (ColorDepth == NULL) ||
71 (RefreshRate == NULL)) {
72 return EFI_INVALID_PARAMETER;
73 }
74
75 *HorizontalResolution = Private->ModeData[Private->CurrentMode].HorizontalResolution;
76 *VerticalResolution = Private->ModeData[Private->CurrentMode].VerticalResolution;
77 *ColorDepth = Private->ModeData[Private->CurrentMode].ColorDepth;
78 *RefreshRate = Private->ModeData[Private->CurrentMode].RefreshRate;
79 return EFI_SUCCESS;
80}
81
82EFI_STATUS
83EFIAPI
84VBoxVgaUgaDrawSetMode (
85 IN EFI_UGA_DRAW_PROTOCOL *This,
86 IN UINT32 HorizontalResolution,
87 IN UINT32 VerticalResolution,
88 IN UINT32 ColorDepth,
89 IN UINT32 RefreshRate
90 )
91{
92 VBOX_VGA_PRIVATE_DATA *Private;
93 UINTN Index;
94
95 DEBUG((DEBUG_INFO, "%a:%d VIDEO: %dx%d %d bpp\n", __FILE__, __LINE__, HorizontalResolution, VerticalResolution, ColorDepth));
96 Private = VBOX_VGA_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
97
98 for (Index = 0; Index < Private->MaxMode; Index++) {
99
100 if (HorizontalResolution != Private->ModeData[Index].HorizontalResolution) {
101 continue;
102 }
103
104 if (VerticalResolution != Private->ModeData[Index].VerticalResolution) {
105 continue;
106 }
107
108 if (ColorDepth != Private->ModeData[Index].ColorDepth) {
109 continue;
110 }
111
112#if 0
113 if (RefreshRate != Private->ModeData[Index].RefreshRate) {
114 continue;
115 }
116#endif
117
118 InitializeGraphicsMode (Private, &VBoxVgaVideoModes[Private->ModeData[Index].ModeNumber]);
119
120 Private->CurrentMode = Index;
121
122 Private->HardwareNeedsStarting = FALSE;
123
124 /* update current mode */
125 Private->CurrentMode = Index;
126 return EFI_SUCCESS;
127 }
128
129 return EFI_NOT_FOUND;
130}
131
132EFI_STATUS
133EFIAPI
134VBoxVgaUgaDrawBlt (
135 IN EFI_UGA_DRAW_PROTOCOL *This,
136 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
137 IN EFI_UGA_BLT_OPERATION BltOperation,
138 IN UINTN SourceX,
139 IN UINTN SourceY,
140 IN UINTN DestinationX,
141 IN UINTN DestinationY,
142 IN UINTN Width,
143 IN UINTN Height,
144 IN UINTN Delta
145 )
146{
147 VBOX_VGA_PRIVATE_DATA *Private;
148 EFI_TPL OriginalTPL;
149 UINTN DstY;
150 UINTN SrcY;
151 UINTN ScreenWidth;
152 UINTN ScreenHeight;
153 EFI_STATUS Status;
154
155 Private = VBOX_VGA_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
156 ScreenWidth = Private->ModeData[Private->CurrentMode].HorizontalResolution;
157 ScreenHeight = Private->ModeData[Private->CurrentMode].VerticalResolution;
158
159 if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {
160 return EFI_INVALID_PARAMETER;
161 }
162
163 if (Width == 0 || Height == 0) {
164 return EFI_INVALID_PARAMETER;
165 }
166
167 //
168 // If Delta is zero, then the entire BltBuffer is being used, so Delta
169 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
170 // the number of bytes in each row can be computed.
171 //
172 if (Delta == 0) {
173 Delta = Width * sizeof (EFI_UGA_PIXEL);
174 }
175 // code below assumes a Delta value in pixels, not bytes
176 Delta /= sizeof (EFI_UGA_PIXEL);
177
178 //
179 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
180 // are valid for the operation and the current screen geometry.
181 //
182 if (BltOperation == EfiUgaVideoToBltBuffer || BltOperation == EfiUgaVideoToVideo) {
183 if (SourceY + Height > ScreenHeight) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 if (SourceX + Width > ScreenWidth) {
188 return EFI_INVALID_PARAMETER;
189 }
190 }
191 if (BltOperation == EfiUgaBltBufferToVideo || BltOperation == EfiUgaVideoToVideo || BltOperation == EfiUgaVideoFill) {
192 if (DestinationY + Height > ScreenHeight) {
193 return EFI_INVALID_PARAMETER;
194 }
195
196 if (DestinationX + Width > ScreenWidth) {
197 return EFI_INVALID_PARAMETER;
198 }
199 }
200
201 //
202 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
203 // We would not want a timer based event (Cursor, ...) to come in while we are
204 // doing this operation.
205 //
206 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
207
208 switch (BltOperation) {
209 case EfiUgaVideoToBltBuffer:
210 //
211 // Video to BltBuffer: Source is Video, destination is BltBuffer
212 //
213 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
214 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_UGA_PIXEL
215 Status = Private->PciIo->Mem.Read (
216 Private->PciIo,
217 EfiPciIoWidthUint32,
218 0,
219 ((SrcY * ScreenWidth) + SourceX) * 4,
220 Width,
221 BltBuffer + (DstY * Delta) + DestinationX
222 );
223 ASSERT_EFI_ERROR((Status));
224 }
225 break;
226
227 case EfiUgaBltBufferToVideo:
228 //
229 // BltBuffer to Video: Source is BltBuffer, destination is Video
230 //
231 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
232 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_UGA_PIXEL
233 Status = Private->PciIo->Mem.Write (
234 Private->PciIo,
235 EfiPciIoWidthUint32,
236 0,
237 ((DstY * ScreenWidth) + DestinationX) * 4,
238 Width,
239 BltBuffer + (SrcY * Delta) + SourceX
240 );
241 ASSERT_EFI_ERROR((Status));
242 }
243 break;
244
245 case EfiUgaVideoToVideo:
246 //
247 // Video to Video: Source is Video, destination is Video
248 //
249 if (DestinationY <= SourceY) {
250 // forward copy
251 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
252 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_UGA_PIXEL
253 Status = Private->PciIo->CopyMem (
254 Private->PciIo,
255 EfiPciIoWidthUint32,
256 0,
257 ((DstY * ScreenWidth) + DestinationX) * 4,
258 0,
259 ((SrcY * ScreenWidth) + SourceX) * 4,
260 Width
261 );
262 ASSERT_EFI_ERROR((Status));
263 }
264 } else {
265 // reverse copy
266 for (SrcY = SourceY + Height - 1, DstY = DestinationY + Height - 1; SrcY >= SourceY && SrcY <= SourceY + Height - 1; SrcY--, DstY--) {
267 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthUint32) and format matches EFI_UGA_PIXEL
268 Status = Private->PciIo->CopyMem (
269 Private->PciIo,
270 EfiPciIoWidthUint32,
271 0,
272 ((DstY * ScreenWidth) + DestinationX) * 4,
273 0,
274 ((SrcY * ScreenWidth) + SourceX) * 4,
275 Width
276 );
277 ASSERT_EFI_ERROR((Status));
278 }
279 }
280 break;
281
282 case EfiUgaVideoFill:
283 //
284 // Video Fill: Source is BltBuffer, destination is Video
285 //
286 if (DestinationX == 0 && Width == ScreenWidth) {
287 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthFillUint32) and format matches EFI_UGA_PIXEL
288 Status = Private->PciIo->Mem.Write (
289 Private->PciIo,
290 EfiPciIoWidthFillUint32,
291 0,
292 DestinationY * ScreenWidth * 4,
293 (Width * Height),
294 BltBuffer
295 );
296 ASSERT_EFI_ERROR((Status));
297 } else {
298 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
299 /// @todo assumes that color depth is 32 (*4, EfiPciIoWidthFillUint32) and format matches EFI_UGA_PIXEL
300 Private->PciIo->Mem.Write (
301 Private->PciIo,
302 EfiPciIoWidthFillUint32,
303 0,
304 ((DstY * ScreenWidth) + DestinationX) * 4,
305 Width,
306 BltBuffer
307 );
308 }
309 }
310 break;
311
312 default:
313 ASSERT (FALSE);
314 }
315
316 gBS->RestoreTPL (OriginalTPL);
317
318 return EFI_SUCCESS;
319}
320
321//
322// Construction and Destruction functions
323//
324EFI_STATUS
325VBoxVgaUgaDrawConstructor (
326 VBOX_VGA_PRIVATE_DATA *Private
327 )
328{
329 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
330 UINT32 Index;
331 UINT32 HorizontalResolution = 1024;
332 UINT32 VerticalResolution = 768;
333 UINT32 ColorDepth = 32;
334
335 //
336 // Fill in Private->UgaDraw protocol
337 //
338 UgaDraw = &Private->UgaDraw;
339
340 UgaDraw->GetMode = VBoxVgaUgaDrawGetMode;
341 UgaDraw->SetMode = VBoxVgaUgaDrawSetMode;
342 UgaDraw->Blt = VBoxVgaUgaDrawBlt;
343
344 //
345 // Initialize the private data
346 //
347 Private->CurrentMode = 0;
348 Private->HardwareNeedsStarting = TRUE;
349
350 //
351 // Initialize the hardware
352 //
353 VBoxVgaGetVmVariable(EFI_INFO_INDEX_HORIZONTAL_RESOLUTION, (CHAR8 *)&HorizontalResolution,
354 sizeof(HorizontalResolution));
355 VBoxVgaGetVmVariable(EFI_INFO_INDEX_VERTICAL_RESOLUTION, (CHAR8 *)&VerticalResolution,
356 sizeof(VerticalResolution));
357 for (Index = 0; Index < Private->MaxMode; Index++)
358 {
359 if ( HorizontalResolution == Private->ModeData[Index].HorizontalResolution
360 && VerticalResolution == Private->ModeData[Index].VerticalResolution
361 && ColorDepth == Private->ModeData[Index].ColorDepth)
362 break;
363 }
364 // not found? try mode number
365 if (Index >= Private->MaxMode)
366 {
367 VBoxVgaGetVmVariable(EFI_INFO_INDEX_GRAPHICS_MODE, (CHAR8 *)&Index, sizeof(Index));
368 // try with mode 2 (usually 1024x768) as a fallback
369 if (Index >= Private->MaxMode)
370 Index = 2;
371 // try with mode 0 (usually 640x480) as a fallback
372 if (Index >= Private->MaxMode)
373 Index = 0;
374
375 // get the resolution from the mode if valid
376 if (Index < Private->MaxMode)
377 {
378 HorizontalResolution = Private->ModeData[Index].HorizontalResolution;
379 VerticalResolution = Private->ModeData[Index].VerticalResolution;
380 ColorDepth = Private->ModeData[Index].ColorDepth;
381 }
382 }
383
384 // skip mode setting completely if there is no valid mode
385 if (Index >= Private->MaxMode)
386 return EFI_UNSUPPORTED;
387
388 UgaDraw->SetMode (
389 UgaDraw,
390 HorizontalResolution,
391 VerticalResolution,
392 ColorDepth,
393 60
394 );
395
396 DrawLogo (
397 Private,
398 Private->ModeData[Private->CurrentMode].HorizontalResolution,
399 Private->ModeData[Private->CurrentMode].VerticalResolution
400 );
401
402 PcdSet32(PcdVideoHorizontalResolution, HorizontalResolution);
403 PcdSet32(PcdVideoVerticalResolution, VerticalResolution);
404
405 return EFI_SUCCESS;
406}
407
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette