LcdGraphicsOutputBlt.c 16 KB

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