]>
Commit | Line | Data |
---|---|---|
1 | /** @file | |
2 | ||
3 | Copyright (c) 2011, ARM Ltd. All rights reserved.<BR> | |
4 | This program and the accompanying materials | |
5 | are licensed and made available under the terms and conditions of the BSD License | |
6 | which accompanies this distribution. The full text of the license may be found at | |
7 | http://opensource.org/licenses/bsd-license.php | |
8 | ||
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
11 | ||
12 | **/ | |
13 | ||
14 | #include <PiDxe.h> | |
15 | #include <Library/BaseMemoryLib.h> | |
16 | #include <Library/DevicePathLib.h> | |
17 | #include <Library/UefiBootServicesTableLib.h> | |
18 | #include <Library/UefiRuntimeServicesTableLib.h> | |
19 | #include <Library/MemoryAllocationLib.h> | |
20 | ||
21 | #include <Guid/GlobalVariable.h> | |
22 | ||
23 | #include "LcdGraphicsOutputDxe.h" | |
24 | ||
25 | extern BOOLEAN mDisplayInitialized; | |
26 | ||
27 | // | |
28 | // Function Definitions | |
29 | // | |
30 | ||
31 | STATIC | |
32 | EFI_STATUS | |
33 | VideoCopyNoHorizontalOverlap ( | |
34 | IN UINTN BitsPerPixel, | |
35 | IN volatile VOID *FrameBufferBase, | |
36 | IN UINT32 HorizontalResolution, | |
37 | IN UINTN SourceX, | |
38 | IN UINTN SourceY, | |
39 | IN UINTN DestinationX, | |
40 | IN UINTN DestinationY, | |
41 | IN UINTN Width, | |
42 | IN UINTN Height | |
43 | ) | |
44 | { | |
45 | EFI_STATUS Status = EFI_SUCCESS; | |
46 | UINTN SourceLine; | |
47 | UINTN DestinationLine; | |
48 | UINTN WidthInBytes; | |
49 | UINTN LineCount; | |
50 | INTN Step; | |
51 | VOID *SourceAddr; | |
52 | VOID *DestinationAddr; | |
53 | ||
54 | if( DestinationY <= SourceY ) { | |
55 | // scrolling up (or horizontally but without overlap) | |
56 | SourceLine = SourceY; | |
57 | DestinationLine = DestinationY; | |
58 | Step = 1; | |
59 | } else { | |
60 | // scrolling down | |
61 | SourceLine = SourceY + Height; | |
62 | DestinationLine = DestinationY + Height; | |
63 | Step = -1; | |
64 | } | |
65 | ||
66 | WidthInBytes = Width * 2; | |
67 | ||
68 | for( LineCount = 0; LineCount < Height; LineCount++ ) { | |
69 | // Update the start addresses of source & destination using 16bit pointer arithmetic | |
70 | SourceAddr = (VOID *)((UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX ); | |
71 | DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX); | |
72 | ||
73 | // Copy the entire line Y from video ram to the temp buffer | |
74 | CopyMem( DestinationAddr, SourceAddr, WidthInBytes); | |
75 | ||
76 | // Update the line numbers | |
77 | SourceLine += Step; | |
78 | DestinationLine += Step; | |
79 | } | |
80 | ||
81 | return Status; | |
82 | } | |
83 | ||
84 | STATIC | |
85 | EFI_STATUS | |
86 | VideoCopyHorizontalOverlap ( | |
87 | IN UINTN BitsPerPixel, | |
88 | IN volatile VOID *FrameBufferBase, | |
89 | UINT32 HorizontalResolution, | |
90 | IN UINTN SourceX, | |
91 | IN UINTN SourceY, | |
92 | IN UINTN DestinationX, | |
93 | IN UINTN DestinationY, | |
94 | IN UINTN Width, | |
95 | IN UINTN Height | |
96 | ) | |
97 | { | |
98 | EFI_STATUS Status = EFI_SUCCESS; | |
99 | ||
100 | UINT16 *PixelBuffer16bit; | |
101 | UINT16 *SourcePixel16bit; | |
102 | UINT16 *DestinationPixel16bit; | |
103 | ||
104 | UINT32 SourcePixelY; | |
105 | UINT32 DestinationPixelY; | |
106 | UINTN SizeIn16Bits; | |
107 | ||
108 | // Allocate a temporary buffer | |
109 | PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16)); | |
110 | ||
111 | if (PixelBuffer16bit == NULL) { | |
112 | Status = EFI_OUT_OF_RESOURCES; | |
113 | goto EXIT; | |
114 | } | |
115 | ||
116 | // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer | |
117 | ||
118 | SizeIn16Bits = Width * 2; | |
119 | ||
120 | for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit; | |
121 | SourcePixelY < SourceY + Height; | |
122 | SourcePixelY++, DestinationPixel16bit += Width) | |
123 | { | |
124 | // Calculate the source address: | |
125 | SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX; | |
126 | ||
127 | // Copy the entire line Y from Video to the temp buffer | |
128 | CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits); | |
129 | } | |
130 | ||
131 | // Copy from the temp buffer into the destination area of the Video Memory | |
132 | ||
133 | for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit; | |
134 | DestinationPixelY < DestinationY + Height; | |
135 | DestinationPixelY++, SourcePixel16bit += Width) | |
136 | { | |
137 | // Calculate the target address: | |
138 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX); | |
139 | ||
140 | // Copy the entire line Y from the temp buffer to Video | |
141 | CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits); | |
142 | } | |
143 | ||
144 | // Free the allocated memory | |
145 | FreePool((VOID *) PixelBuffer16bit); | |
146 | ||
147 | ||
148 | EXIT: | |
149 | return Status; | |
150 | } | |
151 | ||
152 | STATIC | |
153 | EFI_STATUS | |
154 | BltVideoFill ( | |
155 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
156 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel, OPTIONAL | |
157 | IN UINTN SourceX, | |
158 | IN UINTN SourceY, | |
159 | IN UINTN DestinationX, | |
160 | IN UINTN DestinationY, | |
161 | IN UINTN Width, | |
162 | IN UINTN Height, | |
163 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
164 | ) | |
165 | { | |
166 | EFI_PIXEL_BITMASK* PixelInformation; | |
167 | EFI_STATUS Status; | |
168 | UINT32 HorizontalResolution; | |
169 | VOID *FrameBufferBase; | |
170 | UINT16 *DestinationPixel16bit; | |
171 | UINT16 Pixel16bit; | |
172 | UINT32 DestinationPixelX; | |
173 | UINT32 DestinationLine; | |
174 | ||
175 | Status = EFI_SUCCESS; | |
176 | PixelInformation = &This->Mode->Info->PixelInformation; | |
177 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
178 | HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
179 | ||
180 | // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel | |
181 | Pixel16bit = (UINT16) ( | |
182 | ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask ) | |
183 | | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask ) | |
184 | | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
185 | ); | |
186 | ||
187 | // Copy the SourcePixel into every pixel inside the target rectangle | |
188 | for (DestinationLine = DestinationY; | |
189 | DestinationLine < DestinationY + Height; | |
190 | DestinationLine++) | |
191 | { | |
192 | for (DestinationPixelX = DestinationX; | |
193 | DestinationPixelX < DestinationX + Width; | |
194 | DestinationPixelX++) | |
195 | { | |
196 | // Calculate the target address: | |
197 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
198 | ||
199 | // Copy the pixel into the new target | |
200 | *DestinationPixel16bit = Pixel16bit; | |
201 | } | |
202 | } | |
203 | ||
204 | ||
205 | return Status; | |
206 | } | |
207 | ||
208 | STATIC | |
209 | EFI_STATUS | |
210 | BltVideoToBltBuffer ( | |
211 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
212 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
213 | IN UINTN SourceX, | |
214 | IN UINTN SourceY, | |
215 | IN UINTN DestinationX, | |
216 | IN UINTN DestinationY, | |
217 | IN UINTN Width, | |
218 | IN UINTN Height, | |
219 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
220 | ) | |
221 | { | |
222 | EFI_STATUS Status; | |
223 | UINT32 HorizontalResolution; | |
224 | EFI_PIXEL_BITMASK *PixelInformation; | |
225 | EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel; | |
226 | VOID *FrameBufferBase; | |
227 | UINT16 *SourcePixel16bit; | |
228 | UINT16 Pixel16bit; | |
229 | UINT32 SourcePixelX; | |
230 | UINT32 SourceLine; | |
231 | UINT32 DestinationPixelX; | |
232 | UINT32 DestinationLine; | |
233 | UINT32 BltBufferHorizontalResolution; | |
234 | ||
235 | Status = EFI_SUCCESS; | |
236 | PixelInformation = &This->Mode->Info->PixelInformation; | |
237 | HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
238 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
239 | ||
240 | if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { | |
241 | // Delta is not zero and it is different from the width. | |
242 | // Divide it by the size of a pixel to find out the buffer's horizontal resolution. | |
243 | BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
244 | } else { | |
245 | BltBufferHorizontalResolution = Width; | |
246 | } | |
247 | ||
248 | // Access each pixel inside the Video Memory | |
249 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
250 | SourceLine < SourceY + Height; | |
251 | SourceLine++, DestinationLine++) | |
252 | { | |
253 | for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
254 | SourcePixelX < SourceX + Width; | |
255 | SourcePixelX++, DestinationPixelX++) | |
256 | { | |
257 | // Calculate the source and target addresses: | |
258 | SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX; | |
259 | EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX; | |
260 | ||
261 | // Snapshot the pixel from the video buffer once, to speed up the operation. | |
262 | // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations. | |
263 | Pixel16bit = *SourcePixel16bit; | |
264 | ||
265 | // Copy the pixel into the new target | |
266 | EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 8 ); | |
267 | EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 3 ); | |
268 | EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 ); | |
269 | } | |
270 | } | |
271 | ||
272 | return Status; | |
273 | } | |
274 | ||
275 | STATIC | |
276 | EFI_STATUS | |
277 | BltBufferToVideo ( | |
278 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
279 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
280 | IN UINTN SourceX, | |
281 | IN UINTN SourceY, | |
282 | IN UINTN DestinationX, | |
283 | IN UINTN DestinationY, | |
284 | IN UINTN Width, | |
285 | IN UINTN Height, | |
286 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
287 | ) | |
288 | { | |
289 | EFI_STATUS Status; | |
290 | UINT32 HorizontalResolution; | |
291 | EFI_PIXEL_BITMASK *PixelInformation; | |
292 | EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel; | |
293 | VOID *FrameBufferBase; | |
294 | UINT16 *DestinationPixel16bit; | |
295 | UINT32 SourcePixelX; | |
296 | UINT32 SourceLine; | |
297 | UINT32 DestinationPixelX; | |
298 | UINT32 DestinationLine; | |
299 | UINT32 BltBufferHorizontalResolution; | |
300 | ||
301 | Status = EFI_SUCCESS; | |
302 | PixelInformation = &This->Mode->Info->PixelInformation; | |
303 | HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
304 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
305 | ||
306 | if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { | |
307 | // Delta is not zero and it is different from the width. | |
308 | // Divide it by the size of a pixel to find out the buffer's horizontal resolution. | |
309 | BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
310 | } else { | |
311 | BltBufferHorizontalResolution = Width; | |
312 | } | |
313 | ||
314 | // Access each pixel inside the BltBuffer Memory | |
315 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
316 | SourceLine < SourceY + Height; | |
317 | SourceLine++, DestinationLine++) { | |
318 | ||
319 | for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
320 | SourcePixelX < SourceX + Width; | |
321 | SourcePixelX++, DestinationPixelX++) | |
322 | { | |
323 | // Calculate the source and target addresses: | |
324 | EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX; | |
325 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
326 | ||
327 | // Copy the pixel into the new target | |
328 | // Only the most significant bits will be copied across: | |
329 | // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits | |
330 | *DestinationPixel16bit = (UINT16) ( | |
331 | ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask ) | |
332 | | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask ) | |
333 | | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
334 | ); | |
335 | } | |
336 | } | |
337 | ||
338 | return Status; | |
339 | } | |
340 | ||
341 | STATIC | |
342 | EFI_STATUS | |
343 | BltVideoToVideo ( | |
344 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
345 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
346 | IN UINTN SourceX, | |
347 | IN UINTN SourceY, | |
348 | IN UINTN DestinationX, | |
349 | IN UINTN DestinationY, | |
350 | IN UINTN Width, | |
351 | IN UINTN Height, | |
352 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
353 | ) | |
354 | { | |
355 | EFI_STATUS Status; | |
356 | UINT32 HorizontalResolution; | |
357 | UINTN BitsPerPixel; | |
358 | VOID *FrameBufferBase; | |
359 | ||
360 | BitsPerPixel = 16; | |
361 | ||
362 | HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
363 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
364 | ||
365 | // | |
366 | // BltVideo to BltVideo: | |
367 | // | |
368 | // Source is the Video Memory, | |
369 | // Destination is the Video Memory | |
370 | ||
371 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
372 | ||
373 | // The UEFI spec currently states: | |
374 | // "There is no limitation on the overlapping of the source and destination rectangles" | |
375 | // Therefore, we must be careful to avoid overwriting the source data | |
376 | if( SourceY == DestinationY ) { | |
377 | // Copying within the same height, e.g. horizontal shift | |
378 | if( SourceX == DestinationX ) { | |
379 | // Nothing to do | |
380 | Status = EFI_SUCCESS; | |
381 | } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) { | |
382 | // There is overlap | |
383 | Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); | |
384 | } else { | |
385 | // No overlap | |
386 | Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); | |
387 | } | |
388 | } else { | |
389 | // Copying from different heights | |
390 | Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); | |
391 | } | |
392 | ||
393 | return Status; | |
394 | } | |
395 | ||
396 | EFI_STATUS | |
397 | EFIAPI | |
398 | LcdGraphicsBlt ( | |
399 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
400 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
401 | IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, | |
402 | IN UINTN SourceX, | |
403 | IN UINTN SourceY, | |
404 | IN UINTN DestinationX, | |
405 | IN UINTN DestinationY, | |
406 | IN UINTN Width, | |
407 | IN UINTN Height, | |
408 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
409 | ) | |
410 | { | |
411 | EFI_STATUS Status; | |
412 | LCD_INSTANCE *Instance; | |
413 | ||
414 | Instance = LCD_INSTANCE_FROM_GOP_THIS(This); | |
415 | ||
416 | if (!mDisplayInitialized) { | |
417 | InitializeDisplay (Instance); | |
418 | } | |
419 | ||
420 | switch (BltOperation) { | |
421 | case EfiBltVideoFill: | |
422 | Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
423 | break; | |
424 | ||
425 | case EfiBltVideoToBltBuffer: | |
426 | Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
427 | break; | |
428 | ||
429 | case EfiBltBufferToVideo: | |
430 | Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
431 | break; | |
432 | ||
433 | case EfiBltVideoToVideo: | |
434 | Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
435 | break; | |
436 | ||
437 | case EfiGraphicsOutputBltOperationMax: | |
438 | default: | |
439 | DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n")); | |
440 | Status = EFI_INVALID_PARAMETER; | |
441 | break; | |
442 | } | |
443 | ||
444 | return Status; | |
445 | } |