VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware2/VBoxPkg/VBoxVgaDxe/VBoxVgaUgaDraw.c@ 33540

Last change on this file since 33540 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/* $Id: VBoxVgaUgaDraw.c 33540 2010-10-28 09:27:05Z vboxsync $ */
2/** @file
3 * VBoxVgaUgaDraw.c
4 */
5
6/*
7 * Copyright (C) 2009-2010 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
18/*
19 This code is based on:
20
21 This file produces the graphics abstraction of UGA Draw. It is called by
22 VBoxVga.c file which deals with the EFI 1.1 driver model.
23 This file just does graphics.
24
25 Copyright (c) 2006, Intel Corporation
26 All rights reserved. This program and the accompanying materials
27 are licensed and made available under the terms and conditions of the BSD License
28 which accompanies this distribution. The full text of the license may be found at
29 http://opensource.org/licenses/bsd-license.php
30
31 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
32 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
33
34*/
35
36#include "VBoxVga.h"
37
38//
39// UGA Draw Protocol Member Functions
40//
41EFI_STATUS
42EFIAPI
43VBoxVgaUgaDrawGetMode (
44 IN EFI_UGA_DRAW_PROTOCOL *This,
45 OUT UINT32 *HorizontalResolution,
46 OUT UINT32 *VerticalResolution,
47 OUT UINT32 *ColorDepth,
48 OUT UINT32 *RefreshRate
49 )
50{
51 VBOX_VGA_PRIVATE_DATA *Private;
52
53 Private = VBOX_VGA_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
54
55 if (Private->HardwareNeedsStarting) {
56 return EFI_NOT_STARTED;
57 }
58
59 if ((HorizontalResolution == NULL) ||
60 (VerticalResolution == NULL) ||
61 (ColorDepth == NULL) ||
62 (RefreshRate == NULL)) {
63 return EFI_INVALID_PARAMETER;
64 }
65
66 *HorizontalResolution = Private->ModeData[Private->CurrentMode].HorizontalResolution;
67 *VerticalResolution = Private->ModeData[Private->CurrentMode].VerticalResolution;
68 *ColorDepth = Private->ModeData[Private->CurrentMode].ColorDepth;
69 *RefreshRate = Private->ModeData[Private->CurrentMode].RefreshRate;
70 return EFI_SUCCESS;
71}
72
73EFI_STATUS
74EFIAPI
75VBoxVgaUgaDrawSetMode (
76 IN EFI_UGA_DRAW_PROTOCOL *This,
77 IN UINT32 HorizontalResolution,
78 IN UINT32 VerticalResolution,
79 IN UINT32 ColorDepth,
80 IN UINT32 RefreshRate
81 )
82{
83 VBOX_VGA_PRIVATE_DATA *Private;
84 UINTN Index;
85
86 DEBUG((DEBUG_INFO, "%a:%d VIDEO: %dx%d %d bpp\n", __FILE__, __LINE__, HorizontalResolution, VerticalResolution, ColorDepth));
87 Private = VBOX_VGA_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
88
89 for (Index = 0; Index < Private->MaxMode; Index++) {
90
91 if (HorizontalResolution != Private->ModeData[Index].HorizontalResolution) {
92 continue;
93 }
94
95 if (VerticalResolution != Private->ModeData[Index].VerticalResolution) {
96 continue;
97 }
98
99 if (ColorDepth != Private->ModeData[Index].ColorDepth) {
100 continue;
101 }
102
103#if 0
104 if (RefreshRate != Private->ModeData[Index].RefreshRate) {
105 continue;
106 }
107#endif
108
109 if (Private->LineBuffer) {
110 gBS->FreePool (Private->LineBuffer);
111 }
112
113 Private->LineBuffer = NULL;
114 Private->LineBuffer = AllocatePool (HorizontalResolution * 4);
115 if (Private->LineBuffer == NULL) {
116 return EFI_OUT_OF_RESOURCES;
117 }
118
119 InitializeGraphicsMode (Private, &VBoxVgaVideoModes[Private->ModeData[Index].ModeNumber]);
120 if (Private->TmpBuf)
121 FreePool(Private->TmpBuf);
122 Private->TmpBuf = AllocatePool(Private->ModeData[Index].HorizontalResolution * Private->ModeData[Index].VerticalResolution * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
123
124 Private->CurrentMode = Index;
125
126 Private->HardwareNeedsStarting = FALSE;
127
128 /* update current mode */
129 Private->CurrentMode = Index;
130 return EFI_SUCCESS;
131 }
132
133 return EFI_NOT_FOUND;
134}
135
136EFI_STATUS
137EFIAPI
138VBoxVgaUgaDrawBlt (
139 IN EFI_UGA_DRAW_PROTOCOL *This,
140 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
141 IN EFI_UGA_BLT_OPERATION BltOperation,
142 IN UINTN SourceX,
143 IN UINTN SourceY,
144 IN UINTN DestinationX,
145 IN UINTN DestinationY,
146 IN UINTN Width,
147 IN UINTN Height,
148 IN UINTN Delta
149 )
150{
151 VBOX_VGA_PRIVATE_DATA *Private;
152 EFI_TPL OriginalTPL;
153 UINTN DstY;
154 UINTN SrcY;
155 EFI_UGA_PIXEL *Blt;
156 UINTN X;
157 UINTN ScreenWidth;
158 UINTN Offset;
159 UINTN SourceOffset;
160 UINTN ScreenHeight;
161
162 Private = VBOX_VGA_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
163
164 if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {
165 return EFI_INVALID_PARAMETER;
166 }
167
168 if (Width == 0 || Height == 0) {
169 return EFI_INVALID_PARAMETER;
170 }
171
172 //
173 // If Delta is zero, then the entire BltBuffer is being used, so Delta
174 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
175 // the number of bytes in each row can be computed.
176 //
177 if (Delta == 0) {
178 Delta = Width * sizeof (EFI_UGA_PIXEL);
179 }
180 Delta /= sizeof (EFI_UGA_PIXEL);
181
182 //
183 // We need to fill the Virtual Screen buffer with the blt data.
184 // The virtual screen is upside down, as the first row is the bootom row of
185 // the image.
186 //
187
188 //
189 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
190 // are valid for the operation and the current screen geometry.
191 //
192 if (BltOperation == EfiUgaVideoToBltBuffer) {
193 //
194 // Video to BltBuffer: Source is Video, destination is BltBuffer
195 //
196 if (SourceY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
197 return EFI_INVALID_PARAMETER;
198 }
199
200 if (SourceX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
201 return EFI_INVALID_PARAMETER;
202 }
203 } else {
204 //
205 // BltBuffer to Video: Source is BltBuffer, destination is Video
206 //
207 if (DestinationY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
208 return EFI_INVALID_PARAMETER;
209 }
210
211 if (DestinationX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
212 return EFI_INVALID_PARAMETER;
213 }
214 }
215 //
216 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
217 // We would not want a timer based event (Cursor, ...) to come in while we are
218 // doing this operation.
219 //
220 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
221
222 switch (BltOperation) {
223 case EfiUgaVideoToBltBuffer:
224 //
225 // Video to BltBuffer: Source is Video, destination is BltBuffer
226 //
227 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
228
229 Offset = (SrcY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + SourceX;
230 Private->PciIo->Mem.Read (
231 Private->PciIo,
232 EfiPciIoWidthUint32,
233 0,
234 Offset * 4,
235 Width,
236 Private->LineBuffer
237 );
238
239 for (X = 0; X < Width; X++) {
240 Blt = (EFI_UGA_PIXEL *) ((UINT32 *) BltBuffer + (DstY * Delta) + (DestinationX + X));
241
242 *(UINT32 *)Blt = Private->LineBuffer[X];
243 }
244 }
245 break;
246
247 case EfiUgaVideoToVideo:
248 //
249 // Perform hardware acceleration for Video to Video operations
250 //
251 ScreenWidth = Private->ModeData[Private->CurrentMode].HorizontalResolution;
252 ScreenHeight = Private->ModeData[Private->CurrentMode].VerticalResolution;
253 SourceOffset = (SourceY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (SourceX);
254 Offset = (DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (DestinationX);
255 VBoxVgaUgaDrawBlt(This, (EFI_UGA_PIXEL *)Private->TmpBuf, EfiUgaVideoToBltBuffer, SourceX, SourceY, 0, 0, ScreenWidth - SourceX, ScreenHeight - SourceY, 0);
256 VBoxVgaUgaDrawBlt(This, (EFI_UGA_PIXEL *)Private->TmpBuf, EfiUgaBltBufferToVideo, 0, 0, DestinationX, DestinationY, ScreenWidth - SourceX, ScreenHeight - SourceY, 0);
257 break;
258
259 case EfiUgaVideoFill:
260 Blt = BltBuffer;
261
262 if (DestinationX == 0 && Width == Private->ModeData[Private->CurrentMode].HorizontalResolution) {
263 Offset = DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution;
264 Private->PciIo->Mem.Write (
265 Private->PciIo,
266 EfiPciIoWidthFillUint32,
267 0,
268 Offset * 4,
269 (Width * Height) ,
270 Blt
271 );
272 } else {
273 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
274 Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
275 Private->PciIo->Mem.Write (
276 Private->PciIo,
277 EfiPciIoWidthFillUint32,
278 0,
279 Offset * 4,
280 Width,
281 Blt
282 );
283 }
284 }
285 break;
286
287 case EfiUgaBltBufferToVideo:
288 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
289
290 for (X = 0; X < Width; X++) {
291 Blt = (EFI_UGA_PIXEL *) ((UINT32 *) BltBuffer + (SrcY * Delta) + (SourceX + X));
292 Private->LineBuffer[X] = *(UINT32 *)Blt;
293 }
294
295 Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
296
297 Private->PciIo->Mem.Write (
298 Private->PciIo,
299 EfiPciIoWidthUint32,
300 0,
301 Offset * 4,
302 Width,
303 Private->LineBuffer
304 );
305 }
306 break;
307
308 default:
309 break;
310 }
311
312 gBS->RestoreTPL (OriginalTPL);
313
314 return EFI_SUCCESS;
315}
316
317//
318// Construction and Destruction functions
319//
320EFI_STATUS
321VBoxVgaUgaDrawConstructor (
322 VBOX_VGA_PRIVATE_DATA *Private
323 )
324{
325 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
326
327 //
328 // Fill in Private->UgaDraw protocol
329 //
330 UgaDraw = &Private->UgaDraw;
331
332 UgaDraw->GetMode = VBoxVgaUgaDrawGetMode;
333 UgaDraw->SetMode = VBoxVgaUgaDrawSetMode;
334 UgaDraw->Blt = VBoxVgaUgaDrawBlt;
335
336 //
337 // Initialize the private data
338 //
339 Private->CurrentMode = 0;
340 Private->HardwareNeedsStarting = TRUE;
341 Private->LineBuffer = NULL;
342
343 //
344 // Initialize the hardware
345 //
346 UgaDraw->SetMode (
347 UgaDraw,
348 Private->ModeData[Private->CurrentMode].HorizontalResolution,
349 Private->ModeData[Private->CurrentMode].VerticalResolution,
350 Private->ModeData[Private->CurrentMode].ColorDepth,
351 Private->ModeData[Private->CurrentMode].RefreshRate
352 );
353 DrawLogo (
354 Private,
355 Private->ModeData[Private->CurrentMode].HorizontalResolution,
356 Private->ModeData[Private->CurrentMode].VerticalResolution
357 );
358
359 return EFI_SUCCESS;
360}
361
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