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