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