]>
Commit | Line | Data |
---|---|---|
7d0f2f23 | 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/PcdLib.h> | |
16 | #include <Library/DebugLib.h> | |
17 | #include <Library/BaseMemoryLib.h> | |
18 | #include <Library/DevicePathLib.h> | |
19 | #include <Library/UefiBootServicesTableLib.h> | |
20 | #include <Library/UefiRuntimeServicesTableLib.h> | |
21 | #include <Library/MemoryAllocationLib.h> | |
22 | ||
23 | #include <Guid/GlobalVariable.h> | |
24 | ||
7d0f2f23 | 25 | #include "LcdGraphicsOutputDxe.h" |
26 | ||
27 | extern BOOLEAN mDisplayInitialized; | |
28 | ||
29 | // | |
30 | // Function Definitions | |
31 | // | |
32 | ||
33 | STATIC | |
34 | EFI_STATUS | |
35 | VideoCopyNoHorizontalOverlap ( | |
36 | IN UINTN BitsPerPixel, | |
37 | IN volatile VOID *FrameBufferBase, | |
38 | IN UINT32 HorizontalResolution, | |
39 | IN UINTN SourceX, | |
40 | IN UINTN SourceY, | |
41 | IN UINTN DestinationX, | |
42 | IN UINTN DestinationY, | |
43 | IN UINTN Width, | |
44 | IN UINTN Height | |
45 | ) | |
46 | { | |
47 | EFI_STATUS Status = EFI_SUCCESS; | |
48 | UINTN SourceLine; | |
49 | UINTN DestinationLine; | |
50 | UINTN WidthInBytes; | |
51 | UINTN LineCount; | |
52 | INTN Step; | |
53 | VOID *SourceAddr; | |
54 | VOID *DestinationAddr; | |
55 | ||
56 | if( DestinationY <= SourceY ) { | |
57 | // scrolling up (or horizontally but without overlap) | |
58 | SourceLine = SourceY; | |
59 | DestinationLine = DestinationY; | |
60 | Step = 1; | |
61 | } else { | |
62 | // scrolling down | |
63 | SourceLine = SourceY + Height; | |
64 | DestinationLine = DestinationY + Height; | |
65 | Step = -1; | |
66 | } | |
67 | ||
68 | switch (BitsPerPixel) { | |
69 | ||
70 | case LCD_BITS_PER_PIXEL_24: | |
71 | ||
72 | WidthInBytes = Width * 4; | |
73 | ||
74 | for( LineCount = 0; LineCount < Height; LineCount++ ) { | |
75 | // Update the start addresses of source & destination using 32bit pointer arithmetic | |
76 | SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX ); | |
77 | DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX); | |
78 | ||
79 | // Copy the entire line Y from video ram to the temp buffer | |
80 | CopyMem( DestinationAddr, SourceAddr, WidthInBytes); | |
81 | ||
82 | // Update the line numbers | |
83 | SourceLine += Step; | |
84 | DestinationLine += Step; | |
85 | } | |
86 | break; | |
87 | ||
88 | case LCD_BITS_PER_PIXEL_16_555: | |
89 | case LCD_BITS_PER_PIXEL_16_565: | |
90 | case LCD_BITS_PER_PIXEL_12_444: | |
91 | ||
92 | WidthInBytes = Width * 2; | |
93 | ||
94 | for( LineCount = 0; LineCount < Height; LineCount++ ) { | |
95 | // Update the start addresses of source & destination using 16bit pointer arithmetic | |
96 | SourceAddr = (VOID *)((UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX ); | |
97 | DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX); | |
98 | ||
99 | // Copy the entire line Y from video ram to the temp buffer | |
100 | CopyMem( DestinationAddr, SourceAddr, WidthInBytes); | |
101 | ||
102 | // Update the line numbers | |
103 | SourceLine += Step; | |
104 | DestinationLine += Step; | |
105 | } | |
106 | break; | |
107 | ||
108 | case LCD_BITS_PER_PIXEL_8: | |
109 | case LCD_BITS_PER_PIXEL_4: | |
110 | case LCD_BITS_PER_PIXEL_2: | |
111 | case LCD_BITS_PER_PIXEL_1: | |
112 | default: | |
113 | // Can't handle this case | |
114 | DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
115 | Status = EFI_INVALID_PARAMETER; | |
116 | goto EXIT; | |
117 | // break; | |
118 | ||
119 | } | |
120 | ||
121 | EXIT: | |
122 | return Status; | |
123 | } | |
124 | ||
125 | STATIC | |
126 | EFI_STATUS | |
127 | VideoCopyHorizontalOverlap ( | |
128 | IN UINTN BitsPerPixel, | |
129 | IN volatile VOID *FrameBufferBase, | |
130 | UINT32 HorizontalResolution, | |
131 | IN UINTN SourceX, | |
132 | IN UINTN SourceY, | |
133 | IN UINTN DestinationX, | |
134 | IN UINTN DestinationY, | |
135 | IN UINTN Width, | |
136 | IN UINTN Height | |
137 | ) | |
138 | { | |
139 | EFI_STATUS Status = EFI_SUCCESS; | |
140 | ||
141 | UINT32 *PixelBuffer32bit; | |
142 | UINT32 *SourcePixel32bit; | |
143 | UINT32 *DestinationPixel32bit; | |
144 | ||
145 | UINT16 *PixelBuffer16bit; | |
146 | UINT16 *SourcePixel16bit; | |
147 | UINT16 *DestinationPixel16bit; | |
148 | ||
149 | UINT32 SourcePixelY; | |
150 | UINT32 DestinationPixelY; | |
151 | UINTN SizeIn32Bits; | |
152 | UINTN SizeIn16Bits; | |
153 | ||
154 | switch (BitsPerPixel) { | |
155 | ||
156 | case LCD_BITS_PER_PIXEL_24: | |
157 | // Allocate a temporary buffer | |
158 | ||
159 | PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32)); | |
160 | ||
161 | if (PixelBuffer32bit == NULL) { | |
162 | Status = EFI_OUT_OF_RESOURCES; | |
163 | goto EXIT; | |
164 | } | |
165 | ||
166 | SizeIn32Bits = Width * 4; | |
167 | ||
168 | // Copy from the video ram (source region) to a temp buffer | |
169 | for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit; | |
170 | SourcePixelY < SourceY + Height; | |
171 | SourcePixelY++, DestinationPixel32bit += Width) | |
172 | { | |
173 | // Update the start address of line Y (source) | |
174 | SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX; | |
175 | ||
176 | // Copy the entire line Y from video ram to the temp buffer | |
177 | CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits); | |
178 | } | |
179 | ||
180 | // Copy from the temp buffer to the video ram (destination region) | |
181 | for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit; | |
182 | DestinationPixelY < DestinationY + Height; | |
183 | DestinationPixelY++, SourcePixel32bit += Width) | |
184 | { | |
185 | // Update the start address of line Y (target) | |
186 | DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX; | |
187 | ||
188 | // Copy the entire line Y from the temp buffer to video ram | |
189 | CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits); | |
190 | } | |
191 | ||
192 | // Free up the allocated memory | |
193 | FreePool((VOID *) PixelBuffer32bit); | |
194 | ||
195 | break; | |
196 | ||
197 | ||
198 | case LCD_BITS_PER_PIXEL_16_555: | |
199 | case LCD_BITS_PER_PIXEL_16_565: | |
200 | case LCD_BITS_PER_PIXEL_12_444: | |
201 | // Allocate a temporary buffer | |
202 | PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16)); | |
203 | ||
204 | if (PixelBuffer16bit == NULL) { | |
205 | Status = EFI_OUT_OF_RESOURCES; | |
206 | goto EXIT; | |
207 | } | |
208 | ||
209 | // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer | |
210 | ||
211 | SizeIn16Bits = Width * 2; | |
212 | ||
213 | for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit; | |
214 | SourcePixelY < SourceY + Height; | |
215 | SourcePixelY++, DestinationPixel16bit += Width) | |
216 | { | |
217 | // Calculate the source address: | |
218 | SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX; | |
219 | ||
220 | // Copy the entire line Y from Video to the temp buffer | |
221 | CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits); | |
222 | } | |
223 | ||
224 | // Copy from the temp buffer into the destination area of the Video Memory | |
225 | ||
226 | for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit; | |
227 | DestinationPixelY < DestinationY + Height; | |
228 | DestinationPixelY++, SourcePixel16bit += Width) | |
229 | { | |
230 | // Calculate the target address: | |
231 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX); | |
232 | ||
233 | // Copy the entire line Y from the temp buffer to Video | |
234 | CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits); | |
235 | } | |
236 | ||
237 | // Free the allocated memory | |
238 | FreePool((VOID *) PixelBuffer16bit); | |
239 | ||
240 | break; | |
241 | ||
242 | ||
243 | case LCD_BITS_PER_PIXEL_8: | |
244 | case LCD_BITS_PER_PIXEL_4: | |
245 | case LCD_BITS_PER_PIXEL_2: | |
246 | case LCD_BITS_PER_PIXEL_1: | |
247 | default: | |
248 | // Can't handle this case | |
249 | DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
250 | Status = EFI_INVALID_PARAMETER; | |
251 | goto EXIT; | |
252 | // break; | |
253 | ||
254 | } | |
255 | ||
256 | EXIT: | |
257 | return Status; | |
258 | } | |
259 | ||
260 | STATIC | |
261 | EFI_STATUS | |
262 | BltVideoFill ( | |
263 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
264 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel, OPTIONAL | |
265 | IN UINTN SourceX, | |
266 | IN UINTN SourceY, | |
267 | IN UINTN DestinationX, | |
268 | IN UINTN DestinationY, | |
269 | IN UINTN Width, | |
270 | IN UINTN Height, | |
271 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
272 | ) | |
273 | { | |
274 | EFI_PIXEL_BITMASK* PixelInformation; | |
275 | EFI_STATUS Status; | |
276 | UINT32 HorizontalResolution; | |
277 | LCD_BPP BitsPerPixel; | |
278 | VOID *FrameBufferBase; | |
279 | VOID *DestinationAddr; | |
280 | UINT16 *DestinationPixel16bit; | |
281 | UINT16 Pixel16bit; | |
282 | UINT32 DestinationPixelX; | |
283 | UINT32 DestinationLine; | |
284 | UINTN WidthInBytes; | |
285 | ||
286 | Status = EFI_SUCCESS; | |
287 | PixelInformation = &This->Mode->Info->PixelInformation; | |
288 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
289 | HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
290 | ||
291 | LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel); | |
292 | ||
293 | switch (BitsPerPixel) { | |
294 | case LCD_BITS_PER_PIXEL_24: | |
295 | WidthInBytes = Width * 4; | |
296 | ||
297 | // Copy the SourcePixel into every pixel inside the target rectangle | |
298 | for (DestinationLine = DestinationY; | |
299 | DestinationLine < DestinationY + Height; | |
300 | DestinationLine++) | |
301 | { | |
302 | // Calculate the target address using 32bit pointer arithmetic: | |
303 | DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX); | |
304 | ||
305 | // Fill the entire line | |
306 | SetMemN( DestinationAddr, WidthInBytes, *((UINTN *)EfiSourcePixel)); | |
307 | } | |
308 | break; | |
309 | ||
310 | case LCD_BITS_PER_PIXEL_16_555: | |
311 | // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel | |
312 | Pixel16bit = (UINT16) ( | |
313 | ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask ) | |
314 | | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask ) | |
315 | | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
316 | // | ( 0 & PixelInformation->ReservedMask ) | |
317 | ); | |
318 | ||
319 | // Copy the SourcePixel into every pixel inside the target rectangle | |
320 | for (DestinationLine = DestinationY; | |
321 | DestinationLine < DestinationY + Height; | |
322 | DestinationLine++) | |
323 | { | |
324 | for (DestinationPixelX = DestinationX; | |
325 | DestinationPixelX < DestinationX + Width; | |
326 | DestinationPixelX++) | |
327 | { | |
328 | // Calculate the target address: | |
329 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
330 | ||
331 | // Copy the pixel into the new target | |
332 | *DestinationPixel16bit = Pixel16bit; | |
333 | } | |
334 | } | |
335 | break; | |
336 | ||
337 | case LCD_BITS_PER_PIXEL_16_565: | |
338 | // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel | |
339 | Pixel16bit = (UINT16) ( | |
340 | ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask ) | |
341 | | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask ) | |
342 | | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
343 | ); | |
344 | ||
345 | // Copy the SourcePixel into every pixel inside the target rectangle | |
346 | for (DestinationLine = DestinationY; | |
347 | DestinationLine < DestinationY + Height; | |
348 | DestinationLine++) | |
349 | { | |
350 | for (DestinationPixelX = DestinationX; | |
351 | DestinationPixelX < DestinationX + Width; | |
352 | DestinationPixelX++) | |
353 | { | |
354 | // Calculate the target address: | |
355 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
356 | ||
357 | // Copy the pixel into the new target | |
358 | *DestinationPixel16bit = Pixel16bit; | |
359 | } | |
360 | } | |
361 | break; | |
362 | ||
363 | case LCD_BITS_PER_PIXEL_12_444: | |
364 | // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel | |
365 | Pixel16bit = (UINT16) ( | |
366 | ( (EfiSourcePixel->Red >> 4) & PixelInformation->RedMask ) | |
367 | | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask ) | |
368 | | ( (EfiSourcePixel->Blue << 4) & PixelInformation->BlueMask ) | |
369 | ); | |
370 | ||
371 | // Copy the SourcePixel into every pixel inside the target rectangle | |
372 | for (DestinationLine = DestinationY; | |
373 | DestinationLine < DestinationY + Height; | |
374 | DestinationLine++) | |
375 | { | |
376 | for (DestinationPixelX = DestinationX; | |
377 | DestinationPixelX < DestinationX + Width; | |
378 | DestinationPixelX++) | |
379 | { | |
380 | // Calculate the target address: | |
381 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
382 | ||
383 | // Copy the pixel into the new target | |
384 | *DestinationPixel16bit = Pixel16bit; | |
385 | } | |
386 | } | |
387 | break; | |
388 | ||
389 | case LCD_BITS_PER_PIXEL_8: | |
390 | case LCD_BITS_PER_PIXEL_4: | |
391 | case LCD_BITS_PER_PIXEL_2: | |
392 | case LCD_BITS_PER_PIXEL_1: | |
393 | default: | |
394 | // Can't handle this case | |
395 | DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoFill: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
396 | Status = EFI_INVALID_PARAMETER; | |
397 | break; | |
398 | } | |
399 | ||
400 | return Status; | |
401 | } | |
402 | ||
403 | STATIC | |
404 | EFI_STATUS | |
405 | BltVideoToBltBuffer ( | |
406 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
407 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
408 | IN UINTN SourceX, | |
409 | IN UINTN SourceY, | |
410 | IN UINTN DestinationX, | |
411 | IN UINTN DestinationY, | |
412 | IN UINTN Width, | |
413 | IN UINTN Height, | |
414 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
415 | ) | |
416 | { | |
417 | EFI_STATUS Status; | |
418 | UINT32 HorizontalResolution; | |
419 | LCD_BPP BitsPerPixel; | |
420 | EFI_PIXEL_BITMASK *PixelInformation; | |
421 | EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel; | |
422 | VOID *FrameBufferBase; | |
423 | VOID *SourceAddr; | |
424 | VOID *DestinationAddr; | |
425 | UINT16 *SourcePixel16bit; | |
426 | UINT16 Pixel16bit; | |
427 | UINT32 SourcePixelX; | |
428 | UINT32 SourceLine; | |
429 | UINT32 DestinationPixelX; | |
430 | UINT32 DestinationLine; | |
431 | UINT32 BltBufferHorizontalResolution; | |
432 | UINTN WidthInBytes; | |
433 | ||
434 | Status = EFI_SUCCESS; | |
435 | PixelInformation = &This->Mode->Info->PixelInformation; | |
436 | HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
437 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
438 | ||
439 | if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { | |
440 | // Delta is not zero and it is different from the width. | |
441 | // Divide it by the size of a pixel to find out the buffer's horizontal resolution. | |
442 | BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
443 | } else { | |
444 | BltBufferHorizontalResolution = Width; | |
445 | } | |
446 | ||
447 | LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel); | |
448 | ||
449 | switch (BitsPerPixel) { | |
450 | case LCD_BITS_PER_PIXEL_24: | |
451 | WidthInBytes = Width * 4; | |
452 | ||
453 | // Access each line inside the Video Memory | |
454 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
455 | SourceLine < SourceY + Height; | |
456 | SourceLine++, DestinationLine++) | |
457 | { | |
458 | // Calculate the source and target addresses using 32bit pointer arithmetic: | |
459 | SourceAddr = (VOID *)((UINT32 *)FrameBufferBase + SourceLine * HorizontalResolution + SourceX ); | |
460 | DestinationAddr = (VOID *)((UINT32 *)BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationX); | |
461 | ||
462 | // Copy the entire line | |
463 | CopyMem( DestinationAddr, SourceAddr, WidthInBytes); | |
464 | } | |
465 | break; | |
466 | ||
467 | case LCD_BITS_PER_PIXEL_16_555: | |
468 | // Access each pixel inside the Video Memory | |
469 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
470 | SourceLine < SourceY + Height; | |
471 | SourceLine++, DestinationLine++) | |
472 | { | |
473 | for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
474 | SourcePixelX < SourceX + Width; | |
475 | SourcePixelX++, DestinationPixelX++) | |
476 | { | |
477 | // Calculate the source and target addresses: | |
478 | SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX; | |
479 | EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX; | |
480 | ||
481 | // Snapshot the pixel from the video buffer once, to speed up the operation. | |
482 | // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations. | |
483 | Pixel16bit = *SourcePixel16bit; | |
484 | ||
485 | // Copy the pixel into the new target | |
486 | EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 7 ); | |
487 | EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 2); | |
488 | EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 ); | |
489 | // EfiDestinationPixel->Reserved = (UINT8) 0; | |
490 | } | |
491 | } | |
492 | break; | |
493 | ||
494 | case LCD_BITS_PER_PIXEL_16_565: | |
495 | // Access each pixel inside the Video Memory | |
496 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
497 | SourceLine < SourceY + Height; | |
498 | SourceLine++, DestinationLine++) | |
499 | { | |
500 | for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
501 | SourcePixelX < SourceX + Width; | |
502 | SourcePixelX++, DestinationPixelX++) | |
503 | { | |
504 | // Calculate the source and target addresses: | |
505 | SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX; | |
506 | EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX; | |
507 | ||
508 | // Snapshot the pixel from the video buffer once, to speed up the operation. | |
509 | // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations. | |
510 | Pixel16bit = *SourcePixel16bit; | |
511 | ||
512 | // Copy the pixel into the new target | |
513 | // There is no info for the Reserved byte, so we set it to zero | |
514 | EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 8 ); | |
515 | EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) >> 3); | |
516 | EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 3 ); | |
517 | // EfiDestinationPixel->Reserved = (UINT8) 0; | |
518 | } | |
519 | } | |
520 | break; | |
521 | ||
522 | case LCD_BITS_PER_PIXEL_12_444: | |
523 | // Access each pixel inside the Video Memory | |
524 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
525 | SourceLine < SourceY + Height; | |
526 | SourceLine++, DestinationLine++) | |
527 | { | |
528 | for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
529 | SourcePixelX < SourceX + Width; | |
530 | SourcePixelX++, DestinationPixelX++) | |
531 | { | |
532 | // Calculate the source and target addresses: | |
533 | SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX; | |
534 | EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX; | |
535 | ||
536 | // Snapshot the pixel from the video buffer once, to speed up the operation. | |
537 | // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations. | |
538 | Pixel16bit = *SourcePixel16bit; | |
539 | ||
540 | // Copy the pixel into the new target | |
541 | EfiDestinationPixel->Red = (UINT8) ( (Pixel16bit & PixelInformation->RedMask ) >> 4 ); | |
542 | EfiDestinationPixel->Green = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask ) ); | |
543 | EfiDestinationPixel->Blue = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask ) << 4 ); | |
544 | // EfiDestinationPixel->Reserved = (UINT8) 0; | |
545 | } | |
546 | } | |
547 | break; | |
548 | ||
549 | case LCD_BITS_PER_PIXEL_8: | |
550 | case LCD_BITS_PER_PIXEL_4: | |
551 | case LCD_BITS_PER_PIXEL_2: | |
552 | case LCD_BITS_PER_PIXEL_1: | |
553 | default: | |
554 | // Can't handle this case | |
555 | DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
556 | Status = EFI_INVALID_PARAMETER; | |
557 | break; | |
558 | } | |
559 | return Status; | |
560 | } | |
561 | ||
562 | STATIC | |
563 | EFI_STATUS | |
564 | BltBufferToVideo ( | |
565 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
566 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
567 | IN UINTN SourceX, | |
568 | IN UINTN SourceY, | |
569 | IN UINTN DestinationX, | |
570 | IN UINTN DestinationY, | |
571 | IN UINTN Width, | |
572 | IN UINTN Height, | |
573 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
574 | ) | |
575 | { | |
576 | EFI_STATUS Status; | |
577 | UINT32 HorizontalResolution; | |
578 | LCD_BPP BitsPerPixel; | |
579 | EFI_PIXEL_BITMASK *PixelInformation; | |
580 | EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel; | |
581 | VOID *FrameBufferBase; | |
582 | VOID *SourceAddr; | |
583 | VOID *DestinationAddr; | |
584 | UINT16 *DestinationPixel16bit; | |
585 | UINT32 SourcePixelX; | |
586 | UINT32 SourceLine; | |
587 | UINT32 DestinationPixelX; | |
588 | UINT32 DestinationLine; | |
589 | UINT32 BltBufferHorizontalResolution; | |
590 | UINTN WidthInBytes; | |
591 | ||
592 | Status = EFI_SUCCESS; | |
593 | PixelInformation = &This->Mode->Info->PixelInformation; | |
594 | HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
595 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
596 | ||
597 | if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { | |
598 | // Delta is not zero and it is different from the width. | |
599 | // Divide it by the size of a pixel to find out the buffer's horizontal resolution. | |
600 | BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); | |
601 | } else { | |
602 | BltBufferHorizontalResolution = Width; | |
603 | } | |
604 | ||
605 | LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel); | |
606 | ||
607 | switch (BitsPerPixel) { | |
608 | case LCD_BITS_PER_PIXEL_24: | |
609 | WidthInBytes = Width * 4; | |
610 | ||
611 | // Access each pixel inside the BltBuffer Memory | |
612 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
613 | SourceLine < SourceY + Height; | |
614 | SourceLine++, DestinationLine++) | |
615 | { | |
616 | // Calculate the source and target addresses using 32bit pointer arithmetic: | |
617 | SourceAddr = (VOID *)((UINT32 *)BltBuffer + SourceLine * BltBufferHorizontalResolution + SourceX ); | |
618 | DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX); | |
619 | ||
620 | // Copy the entire row Y | |
621 | CopyMem( DestinationAddr, SourceAddr, WidthInBytes); | |
622 | } | |
623 | break; | |
624 | ||
625 | case LCD_BITS_PER_PIXEL_16_555: | |
626 | // Access each pixel inside the BltBuffer Memory | |
627 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
628 | SourceLine < SourceY + Height; | |
629 | SourceLine++, DestinationLine++) { | |
630 | ||
631 | for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
632 | SourcePixelX < SourceX + Width; | |
633 | SourcePixelX++, DestinationPixelX++) | |
634 | { | |
635 | // Calculate the source and target addresses: | |
636 | EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX; | |
637 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
638 | ||
639 | // Copy the pixel into the new target | |
640 | // Only the most significant bits will be copied across: | |
641 | // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits | |
642 | *DestinationPixel16bit = (UINT16) ( | |
643 | ( (EfiSourcePixel->Red << 7) & PixelInformation->RedMask ) | |
644 | | ( (EfiSourcePixel->Green << 2) & PixelInformation->GreenMask ) | |
645 | | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
646 | // | ( 0 & PixelInformation->ReservedMask ) | |
647 | ); | |
648 | } | |
649 | } | |
650 | break; | |
651 | ||
652 | case LCD_BITS_PER_PIXEL_16_565: | |
653 | // Access each pixel inside the BltBuffer Memory | |
654 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
655 | SourceLine < SourceY + Height; | |
656 | SourceLine++, DestinationLine++) { | |
657 | ||
658 | for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
659 | SourcePixelX < SourceX + Width; | |
660 | SourcePixelX++, DestinationPixelX++) | |
661 | { | |
662 | // Calculate the source and target addresses: | |
663 | EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX; | |
664 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
665 | ||
666 | // Copy the pixel into the new target | |
667 | // Only the most significant bits will be copied across: | |
668 | // To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2 least significant bits | |
669 | // There is no room for the Reserved byte so we ignore that completely | |
670 | *DestinationPixel16bit = (UINT16) ( | |
671 | ( (EfiSourcePixel->Red << 8) & PixelInformation->RedMask ) | |
672 | | ( (EfiSourcePixel->Green << 3) & PixelInformation->GreenMask ) | |
673 | | ( (EfiSourcePixel->Blue >> 3) & PixelInformation->BlueMask ) | |
674 | ); | |
675 | } | |
676 | } | |
677 | break; | |
678 | ||
679 | case LCD_BITS_PER_PIXEL_12_444: | |
680 | // Access each pixel inside the BltBuffer Memory | |
681 | for (SourceLine = SourceY, DestinationLine = DestinationY; | |
682 | SourceLine < SourceY + Height; | |
683 | SourceLine++, DestinationLine++) { | |
684 | ||
685 | for (SourcePixelX = SourceX, DestinationPixelX = DestinationX; | |
686 | SourcePixelX < SourceX + Width; | |
687 | SourcePixelX++, DestinationPixelX++) | |
688 | { | |
689 | // Calculate the source and target addresses: | |
690 | EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX; | |
691 | DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX; | |
692 | ||
693 | // Copy the pixel into the new target | |
694 | // Only the most significant bits will be copied across: | |
695 | // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits | |
696 | *DestinationPixel16bit = (UINT16) ( | |
697 | ( (EfiSourcePixel->Red << 4) & PixelInformation->RedMask ) | |
698 | | ( (EfiSourcePixel->Green ) & PixelInformation->GreenMask ) | |
699 | | ( (EfiSourcePixel->Blue >> 4) & PixelInformation->BlueMask ) | |
700 | // | ( 0 & PixelInformation->ReservedMask ) | |
701 | ); | |
702 | } | |
703 | } | |
704 | break; | |
705 | ||
706 | case LCD_BITS_PER_PIXEL_8: | |
707 | case LCD_BITS_PER_PIXEL_4: | |
708 | case LCD_BITS_PER_PIXEL_2: | |
709 | case LCD_BITS_PER_PIXEL_1: | |
710 | default: | |
711 | // Can't handle this case | |
712 | DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel)); | |
713 | Status = EFI_INVALID_PARAMETER; | |
714 | break; | |
715 | } | |
716 | return Status; | |
717 | } | |
718 | ||
719 | STATIC | |
720 | EFI_STATUS | |
721 | BltVideoToVideo ( | |
722 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
723 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
724 | IN UINTN SourceX, | |
725 | IN UINTN SourceY, | |
726 | IN UINTN DestinationX, | |
727 | IN UINTN DestinationY, | |
728 | IN UINTN Width, | |
729 | IN UINTN Height, | |
730 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
731 | ) | |
732 | { | |
733 | EFI_STATUS Status; | |
734 | UINT32 HorizontalResolution; | |
735 | LCD_BPP BitsPerPixel; | |
736 | VOID *FrameBufferBase; | |
737 | ||
738 | HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
739 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
740 | ||
741 | // | |
742 | // BltVideo to BltVideo: | |
743 | // | |
744 | // Source is the Video Memory, | |
745 | // Destination is the Video Memory | |
746 | ||
747 | LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel); | |
748 | FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase)); | |
749 | ||
750 | // The UEFI spec currently states: | |
751 | // "There is no limitation on the overlapping of the source and destination rectangles" | |
752 | // Therefore, we must be careful to avoid overwriting the source data | |
753 | if( SourceY == DestinationY ) { | |
754 | // Copying within the same height, e.g. horizontal shift | |
755 | if( SourceX == DestinationX ) { | |
756 | // Nothing to do | |
757 | Status = EFI_SUCCESS; | |
758 | } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) { | |
759 | // There is overlap | |
760 | Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); | |
761 | } else { | |
762 | // No overlap | |
763 | Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); | |
764 | } | |
765 | } else { | |
766 | // Copying from different heights | |
767 | Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height ); | |
768 | } | |
769 | ||
770 | return Status; | |
771 | } | |
772 | ||
773 | /*************************************** | |
774 | * GraphicsOutput Protocol function, mapping to | |
775 | * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt | |
776 | * | |
777 | * PRESUMES: 1 pixel = 4 bytes (32bits) | |
778 | * ***************************************/ | |
779 | EFI_STATUS | |
780 | EFIAPI | |
781 | LcdGraphicsBlt ( | |
782 | IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, | |
783 | IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL | |
784 | IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, | |
785 | IN UINTN SourceX, | |
786 | IN UINTN SourceY, | |
787 | IN UINTN DestinationX, | |
788 | IN UINTN DestinationY, | |
789 | IN UINTN Width, | |
790 | IN UINTN Height, | |
791 | IN UINTN Delta OPTIONAL // Number of BYTES in a row of the BltBuffer | |
792 | ) | |
793 | { | |
794 | EFI_STATUS Status; | |
795 | UINT32 HorizontalResolution; | |
796 | UINT32 VerticalResolution; | |
797 | LCD_INSTANCE* Instance; | |
798 | ||
799 | Instance = LCD_INSTANCE_FROM_GOP_THIS(This); | |
800 | ||
801 | // Setup the hardware if not already done | |
802 | if (!mDisplayInitialized) { | |
803 | Status = InitializeDisplay (Instance); | |
804 | if (EFI_ERROR(Status)) { | |
805 | goto EXIT; | |
806 | } | |
807 | } | |
808 | ||
809 | HorizontalResolution = This->Mode->Info->HorizontalResolution; | |
810 | VerticalResolution = This->Mode->Info->VerticalResolution; | |
811 | ||
812 | DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n", | |
813 | BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution)); | |
814 | ||
815 | // Check we have reasonable parameters | |
816 | if (Width == 0 || Height == 0) { | |
817 | DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" )); | |
818 | Status = EFI_INVALID_PARAMETER; | |
819 | goto EXIT; | |
820 | } | |
821 | ||
822 | if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) { | |
823 | ASSERT( BltBuffer != NULL); | |
824 | } | |
825 | ||
826 | /*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) { | |
827 | DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" )); | |
828 | Status = EFI_INVALID_PARAMETER; | |
829 | goto EXIT; | |
830 | }*/ | |
831 | ||
832 | // If we are reading data out of the video buffer, check that the source area is within the display limits | |
833 | if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) { | |
834 | if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) { | |
835 | DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" )); | |
836 | DEBUG((DEBUG_INFO, " - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution )); | |
837 | DEBUG((DEBUG_INFO, " - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution )); | |
838 | Status = EFI_INVALID_PARAMETER; | |
839 | goto EXIT; | |
840 | } | |
841 | } | |
842 | ||
843 | // If we are writing data into the video buffer, that the destination area is within the display limits | |
844 | if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) { | |
845 | if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) { | |
846 | DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" )); | |
847 | DEBUG((DEBUG_INFO, " - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution )); | |
848 | DEBUG((DEBUG_INFO, " - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution )); | |
849 | Status = EFI_INVALID_PARAMETER; | |
850 | goto EXIT; | |
851 | } | |
852 | } | |
853 | ||
854 | // | |
855 | // Perform the Block Transfer Operation | |
856 | // | |
857 | ||
858 | switch (BltOperation) { | |
859 | case EfiBltVideoFill: | |
860 | Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
861 | break; | |
862 | ||
863 | case EfiBltVideoToBltBuffer: | |
864 | Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
865 | break; | |
866 | ||
867 | case EfiBltBufferToVideo: | |
868 | Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
869 | break; | |
870 | ||
871 | case EfiBltVideoToVideo: | |
872 | Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); | |
873 | break; | |
874 | ||
875 | case EfiGraphicsOutputBltOperationMax: | |
876 | default: | |
877 | DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n")); | |
878 | Status = EFI_INVALID_PARAMETER; | |
879 | break; | |
880 | } | |
881 | ||
882 | EXIT: | |
883 | return Status; | |
884 | } |