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