OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OpenCanopy.c
Go to the documentation of this file.
1
8#include <Uefi.h>
9
12
13#include <Library/BaseLib.h>
14#include <Library/BaseMemoryLib.h>
15#include <Library/BaseOverflowLib.h>
16#include <Library/BmpSupportLib.h>
17#include <Library/DebugLib.h>
18#include <Library/MemoryAllocationLib.h>
19#include <Library/MtrrLib.h>
22#include <Library/OcCpuLib.h>
23#include <Library/OcPngLib.h>
24#include <Library/TimerLib.h>
25#include <Library/UefiBootServicesTableLib.h>
26
27#include "OpenCanopy.h"
28#include "GuiIo.h"
29#include "GuiApp.h"
30#include "Views/BootPicker.h"
31#include "Blending.h"
32
33typedef struct {
34 UINT32 X;
35 UINT32 Y;
36 UINT32 Width;
37 UINT32 Height;
39
40//
41// I/O contexts
42//
44GLOBAL_REMOVE_IF_UNREFERENCED GUI_POINTER_CONTEXT *mPointerContext = NULL;
45GLOBAL_REMOVE_IF_UNREFERENCED GUI_KEY_CONTEXT *mKeyContext = NULL;
46//
47// Screen buffer information
48//
49STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL *mScreenBuffer = NULL;
50STATIC UINT32 mScreenBufferDelta = 0;
51//
52// Frame timing information (60 FPS)
53//
54STATIC UINT64 mDeltaTscTarget = 0;
55STATIC UINT64 mStartTsc = 0;
56//
57// Drawing rectangles information
58//
59STATIC UINT8 mNumValidDrawReqs = 0;
61 { 0 }
62};
63
64STATIC UINT32 mPointerOldDrawBaseX = 0;
65STATIC UINT32 mPointerOldDrawBaseY = 0;
66STATIC UINT32 mPointerOldDrawWidth = 0;
67STATIC UINT32 mPointerOldDrawHeight = 0;
68
69#define PIXEL_TO_UINT32(Pixel) \
70 ((UINT32) SIGNATURE_32 ((Pixel)->Blue, (Pixel)->Green, (Pixel)->Red, (Pixel)->Reserved))
71
72BOOLEAN
74 IN INT64 ChildOffset,
75 IN UINT32 ChildLength,
76 IN OUT UINT32 *ReqOffset,
77 IN OUT UINT32 *ReqLength
78 )
79{
80 INT64 OffsetDelta;
81 UINT32 NewOffset;
82 UINT32 NewLength;
83
84 ASSERT (ReqOffset != NULL);
85 ASSERT (ReqLength != NULL);
86
87 NewOffset = *ReqOffset;
88 NewLength = *ReqLength;
89
90 OffsetDelta = NewOffset - ChildOffset;
91
92 if (OffsetDelta >= 0) {
93 //
94 // The requested offset starts within or past the child.
95 //
96 if (ChildLength <= OffsetDelta) {
97 //
98 // The requested offset starts past the child.
99 //
100 return FALSE;
101 }
102
103 //
104 // The requested offset starts within the child.
105 //
106 NewOffset = (UINT32)OffsetDelta;
107 NewLength = MIN (NewLength, (UINT32)(ChildLength - OffsetDelta));
108 } else {
109 //
110 // The requested offset starts before the child.
111 //
112 if (NewLength <= -OffsetDelta) {
113 //
114 // The requested offset ends before the child.
115 //
116 return FALSE;
117 }
118
119 //
120 // The requested offset ends within the child.
121 //
122 NewOffset = 0;
123 NewLength = MIN ((UINT32)(NewLength + OffsetDelta), ChildLength);
124 }
125
126 ASSERT (ChildOffset + ChildLength > 0);
127 ASSERT (NewLength > 0);
128 ASSERT (NewOffset + NewLength <= ChildLength);
129
130 *ReqOffset = NewOffset;
131 *ReqLength = NewLength;
132
133 return TRUE;
134}
135
136VOID
138 IN OUT GUI_OBJ *This,
139 IN OUT GUI_DRAWING_CONTEXT *DrawContext,
140 IN BOOT_PICKER_GUI_CONTEXT *Context,
141 IN INT64 BaseX,
142 IN INT64 BaseY,
143 IN UINT32 OffsetX,
144 IN UINT32 OffsetY,
145 IN UINT32 Width,
146 IN UINT32 Height,
147 IN UINT8 Opacity
148 )
149{
150 BOOLEAN Result;
151
152 UINTN Index;
153 GUI_OBJ_CHILD *Child;
154
155 UINT32 ChildDrawOffsetX;
156 UINT32 ChildDrawOffsetY;
157 UINT32 ChildDrawWidth;
158 UINT32 ChildDrawHeight;
159 UINT8 ChildOpacity;
160
161 ASSERT (This != NULL);
162 ASSERT (OffsetX < This->Width);
163 ASSERT (OffsetY < This->Height);
164 ASSERT (Width > 0);
165 ASSERT (Height > 0);
166 ASSERT (Width <= This->Width);
167 ASSERT (Height <= This->Height);
168 ASSERT (DrawContext != NULL);
169
170 for (Index = 0; Index < This->NumChildren; ++Index) {
171 Child = This->Children[Index];
172
173 ChildDrawOffsetX = OffsetX;
174 ChildDrawWidth = Width;
175 Result = GuiClipChildBounds (
176 Child->Obj.OffsetX,
177 Child->Obj.Width,
178 &ChildDrawOffsetX,
179 &ChildDrawWidth
180 );
181 if (!Result) {
182 continue;
183 }
184
185 ChildDrawOffsetY = OffsetY;
186 ChildDrawHeight = Height;
187 Result = GuiClipChildBounds (
188 Child->Obj.OffsetY,
189 Child->Obj.Height,
190 &ChildDrawOffsetY,
191 &ChildDrawHeight
192 );
193 if (!Result) {
194 continue;
195 }
196
197 if (Opacity == 0xFF) {
198 ChildOpacity = Child->Obj.Opacity;
199 } else if (Child->Obj.Opacity == 0xFF) {
200 ChildOpacity = Opacity;
201 } else {
202 ChildOpacity = RGB_APPLY_OPACITY (Child->Obj.Opacity, Opacity);
203 }
204
205 ASSERT (ChildDrawOffsetX + ChildDrawWidth <= Child->Obj.Width);
206 ASSERT (ChildDrawOffsetY + ChildDrawHeight <= Child->Obj.Height);
207 ASSERT (ChildDrawWidth > 0);
208 ASSERT (ChildDrawHeight > 0);
209 ASSERT (Child->Obj.Draw != NULL);
210 Child->Obj.Draw (
211 &Child->Obj,
212 DrawContext,
213 Context,
214 BaseX + Child->Obj.OffsetX,
215 BaseY + Child->Obj.OffsetY,
216 ChildDrawOffsetX,
217 ChildDrawOffsetY,
218 ChildDrawWidth,
219 ChildDrawHeight,
220 ChildOpacity
221 );
222 }
223}
224
225GUI_OBJ *
227 IN OUT GUI_OBJ *This,
228 IN OUT GUI_DRAWING_CONTEXT *DrawContext,
229 IN BOOT_PICKER_GUI_CONTEXT *Context,
230 IN INT64 BaseX,
231 IN INT64 BaseY,
232 IN CONST GUI_PTR_EVENT *Event
233 )
234{
235 UINTN Index;
236 GUI_OBJ *Obj;
237 GUI_OBJ_CHILD *Child;
238
239 ASSERT (This != NULL);
240 ASSERT (Event->Pos.Pos.X >= BaseX);
241 ASSERT (Event->Pos.Pos.Y >= BaseY);
242 ASSERT (This->Width > Event->Pos.Pos.X - BaseX);
243 ASSERT (This->Height > Event->Pos.Pos.Y - BaseY);
244 ASSERT (DrawContext != NULL);
245 //
246 // Pointer event propagation is backwards due to forwards draw order.
247 //
248 for (Index = This->NumChildren; Index > 0; --Index) {
249 Child = This->Children[Index - 1];
250 if ( (Event->Pos.Pos.X - BaseX < Child->Obj.OffsetX)
251 || (Event->Pos.Pos.X - BaseX >= Child->Obj.OffsetX + Child->Obj.Width)
252 || (Event->Pos.Pos.Y - BaseY < Child->Obj.OffsetY)
253 || (Event->Pos.Pos.Y - BaseY >= Child->Obj.OffsetY + Child->Obj.Height))
254 {
255 continue;
256 }
257
258 ASSERT (Child->Obj.PtrEvent != NULL);
259 Obj = Child->Obj.PtrEvent (
260 &Child->Obj,
261 DrawContext,
262 Context,
263 BaseX + Child->Obj.OffsetX,
264 BaseY + Child->Obj.OffsetY,
265 Event
266 );
267 if (Obj != NULL) {
268 return Obj;
269 }
270 }
271
272 return NULL;
273}
274
275VOID
277 IN CONST EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Colour,
278 IN OUT GUI_DRAWING_CONTEXT *DrawContext,
279 IN UINT32 PosX,
280 IN UINT32 PosY,
281 IN UINT32 Width,
282 IN UINT32 Height
283 )
284{
285 UINT32 RowIndex;
286 UINT32 TargetRowOffset;
287
288 ASSERT (Colour != NULL);
289 ASSERT (DrawContext != NULL);
290 ASSERT (Width > 0);
291 ASSERT (Height > 0);
292 //
293 // Screen cropping happens in GuiRequestDrawCrop().
294 //
295 ASSERT (DrawContext->Screen.Width >= PosX);
296 ASSERT (DrawContext->Screen.Height >= PosY);
297 ASSERT (PosX + Width <= DrawContext->Screen.Width);
298 ASSERT (PosY + Height <= DrawContext->Screen.Height);
299 //
300 // Iterate over each row of the request.
301 //
302 for (
303 RowIndex = 0,
304 TargetRowOffset = PosY * DrawContext->Screen.Width;
305 RowIndex < Height;
306 ++RowIndex,
307 TargetRowOffset += DrawContext->Screen.Width
308 )
309 {
310 //
311 // Populate the row pixel-by-pixel with Source's (0,0).
312 //
313 SetMem32 (
314 &mScreenBuffer[TargetRowOffset + PosX],
315 Width * sizeof (UINT32),
316 PIXEL_TO_UINT32 (Colour)
317 );
318 }
319
320 //
321 // TODO: Support opaque fill?
322 //
323
324 #if 0
325 //
326 // Iterate over each row of the request.
327 //
328 for (
329 RowIndex = 0,
330 TargetRowOffset = PosY * DrawContext->Screen.Width;
331 RowIndex < Height;
332 ++RowIndex,
333 TargetRowOffset += DrawContext->Screen.Width
334 )
335 {
336 //
337 // Blend the row pixel-by-pixel with Source's (0,0).
338 //
339 for (
340 TargetColumnOffset = PosY;
341 TargetColumnOffset < PosY + Width;
342 ++TargetColumnOffset
343 )
344 {
345 TargetPixel = &mScreenBuffer[TargetRowOffset + TargetColumnOffset];
346 GuiBlendPixel (TargetPixel, &Image->Buffer[0], Opacity);
347 }
348 }
349
350 #endif
351}
352
353VOID
355 IN CONST GUI_IMAGE *Image,
356 IN UINT8 Opacity,
357 IN OUT GUI_DRAWING_CONTEXT *DrawContext,
358 IN INT64 BaseX,
359 IN INT64 BaseY,
360 IN UINT32 OffsetX,
361 IN UINT32 OffsetY,
362 IN UINT32 Width,
363 IN UINT32 Height
364 )
365{
366 UINT32 PosX;
367 UINT32 PosY;
368
369 UINT32 RowIndex;
370 UINT32 SourceRowOffset;
371 UINT32 TargetRowOffset;
372 UINT32 SourceColumnOffset;
373 UINT32 TargetColumnOffset;
374 CONST EFI_GRAPHICS_OUTPUT_BLT_PIXEL *SourcePixel;
375 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TargetPixel;
376
377 ASSERT (Image != NULL);
378 ASSERT (DrawContext != NULL);
379 ASSERT (BaseX + OffsetX >= 0);
380 ASSERT (BaseY + OffsetY >= 0);
381 ASSERT (Width > 0);
382 ASSERT (Height > 0);
383 ASSERT (BaseX + OffsetX + Width >= 0);
384 ASSERT (BaseY + OffsetY + Height >= 0);
385 ASSERT (BaseX + OffsetX + Width <= MAX_UINT32);
386 ASSERT (BaseY + OffsetY + Height <= MAX_UINT32);
387
388 PosX = (UINT32)(BaseX + OffsetX);
389 PosY = (UINT32)(BaseY + OffsetY);
390 //
391 // Screen cropping happens in GuiRequestDrawCrop().
392 //
393 ASSERT (DrawContext->Screen.Width >= PosX);
394 ASSERT (DrawContext->Screen.Height >= PosY);
395 ASSERT (PosX + Width <= DrawContext->Screen.Width);
396 ASSERT (PosY + Height <= DrawContext->Screen.Height);
397
398 if (Opacity == 0) {
399 return;
400 }
401
402 ASSERT (Image->Width > OffsetX);
403 ASSERT (Image->Height > OffsetY);
404 //
405 // Only crop to the image's dimensions when not using fill-drawing.
406 //
407 Width = MIN (Width, Image->Width - OffsetX);
408 Height = MIN (Height, Image->Height - OffsetY);
409 if ((Width == 0) || (Height == 0)) {
410 return;
411 }
412
413 ASSERT (Image->Buffer != NULL);
414
415 if (Opacity == 0xFF) {
416 //
417 // Iterate over each row of the request.
418 //
419 for (
420 RowIndex = 0,
421 SourceRowOffset = OffsetY * Image->Width,
422 TargetRowOffset = PosY * DrawContext->Screen.Width;
423 RowIndex < Height;
424 ++RowIndex,
425 SourceRowOffset += Image->Width,
426 TargetRowOffset += DrawContext->Screen.Width
427 )
428 {
429 //
430 // Blend the row pixel-by-pixel.
431 //
432 for (
433 TargetColumnOffset = PosX, SourceColumnOffset = OffsetX;
434 TargetColumnOffset < PosX + Width;
435 ++TargetColumnOffset, ++SourceColumnOffset
436 )
437 {
438 TargetPixel = &mScreenBuffer[TargetRowOffset + TargetColumnOffset];
439 SourcePixel = &Image->Buffer[SourceRowOffset + SourceColumnOffset];
440 GuiBlendPixelSolid (TargetPixel, SourcePixel);
441 }
442 }
443 } else {
444 //
445 // Iterate over each row of the request.
446 //
447 for (
448 RowIndex = 0,
449 SourceRowOffset = OffsetY * Image->Width,
450 TargetRowOffset = PosY * DrawContext->Screen.Width;
451 RowIndex < Height;
452 ++RowIndex,
453 SourceRowOffset += Image->Width,
454 TargetRowOffset += DrawContext->Screen.Width
455 )
456 {
457 //
458 // Blend the row pixel-by-pixel.
459 //
460 for (
461 TargetColumnOffset = PosX, SourceColumnOffset = OffsetX;
462 TargetColumnOffset < PosX + Width;
463 ++TargetColumnOffset, ++SourceColumnOffset
464 )
465 {
466 TargetPixel = &mScreenBuffer[TargetRowOffset + TargetColumnOffset];
467 SourcePixel = &Image->Buffer[SourceRowOffset + SourceColumnOffset];
468 GuiBlendPixelOpaque (TargetPixel, SourcePixel, Opacity);
469 }
470 }
471 }
472}
473
474VOID
476 IN UINT32 PosX,
477 IN UINT32 PosY,
478 IN UINT32 Width,
479 IN UINT32 Height
480 )
481{
482 UINTN Index;
483
484 UINT32 ThisArea;
485 UINT32 ThisMaxXPlus1;
486 UINT32 ThisMaxYPlus1;
487
488 UINT32 ReqMaxXPlus1;
489 UINT32 ReqMaxYPlus1;
490 UINT32 ReqArea;
491
492 UINT32 CombX;
493 UINT32 CombY;
494 UINT32 CombWidth;
495 UINT32 CombHeight;
496 UINT32 CombArea;
497
498 ThisMaxXPlus1 = PosX + Width;
499 ThisMaxYPlus1 = PosY + Height;
500
501 ThisArea = Width * Height;
502
503 for (Index = 0; Index < mNumValidDrawReqs; ++Index) {
504 //
505 // Calculate several dimensions to determine whether to merge the two
506 // draw requests for improved flushing performance.
507 //
508 ReqMaxXPlus1 = mDrawRequests[Index].X + mDrawRequests[Index].Width;
509 ReqMaxYPlus1 = mDrawRequests[Index].Y + mDrawRequests[Index].Height;
510 ReqArea = mDrawRequests[Index].Width * mDrawRequests[Index].Height;
511
512 if (mDrawRequests[Index].X < PosX) {
513 CombX = mDrawRequests[Index].X;
514 } else {
515 CombX = PosX;
516 }
517
518 if (ReqMaxXPlus1 > ThisMaxXPlus1) {
519 CombWidth = ReqMaxXPlus1;
520 } else {
521 CombWidth = ThisMaxXPlus1;
522 }
523
524 CombWidth -= CombX;
525
526 if (mDrawRequests[Index].Y < PosY) {
527 CombY = mDrawRequests[Index].Y;
528 } else {
529 CombY = PosY;
530 }
531
532 if (ReqMaxYPlus1 > ThisMaxYPlus1) {
533 CombHeight = ReqMaxYPlus1;
534 } else {
535 CombHeight = ThisMaxYPlus1;
536 }
537
538 CombHeight -= CombY;
539
540 CombArea = CombWidth * CombHeight;
541 //
542 // Two requests are merged when the overarching rectangle is not bigger than
543 // the two separate rectangles (not accounting for the overlap, as it would
544 // be drawn twice).
545 //
546 // TODO: Profile a good constant factor?
547 //
548 if (ThisArea + ReqArea >= CombArea) {
549 mDrawRequests[Index].X = CombX;
550 mDrawRequests[Index].Y = CombY;
551 mDrawRequests[Index].Width = CombWidth;
552 mDrawRequests[Index].Height = CombHeight;
553 return;
554 }
555 }
556
558 ASSERT (FALSE);
559 return;
560 }
561
567}
568
569VOID
571 IN OUT GUI_DRAWING_CONTEXT *DrawContext,
572 IN INT64 X,
573 IN INT64 Y,
574 IN UINT32 Width,
575 IN UINT32 Height
576 )
577{
578 UINT32 PosX;
579 UINT32 PosY;
580 INT64 EffWidth;
581 INT64 EffHeight;
582
583 ASSERT (DrawContext != NULL);
584
585 EffWidth = Width;
586 EffHeight = Height;
587 //
588 // Only draw the onscreen parts.
589 //
590 if (X >= 0) {
591 PosX = (UINT32)X;
592 } else {
593 EffWidth += X;
594 PosX = 0;
595 }
596
597 if (Y >= 0) {
598 PosY = (UINT32)Y;
599 } else {
600 EffHeight += Y;
601 PosY = 0;
602 }
603
604 EffWidth = MIN (EffWidth, (INT64)DrawContext->Screen.Width - PosX);
605 EffHeight = MIN (EffHeight, (INT64)DrawContext->Screen.Height - PosY);
606
607 if ((EffWidth <= 0) || (EffHeight <= 0)) {
608 return;
609 }
610
611 GuiRequestDraw (PosX, PosY, (UINT32)EffWidth, (UINT32)EffHeight);
612}
613
614VOID
616 IN OUT GUI_DRAWING_CONTEXT *DrawContext
617 )
618{
619 CONST GUI_IMAGE *CursorImage;
620 UINT32 MaxWidth;
621 UINT32 MaxHeight;
622 GUI_PTR_POSITION PointerPos;
623
624 INT64 BaseX;
625 INT64 BaseY;
626 UINT32 ImageOffsetX;
627 UINT32 ImageOffsetY;
628 UINT32 DrawBaseX;
629 UINT32 DrawBaseY;
630
631 ASSERT (DrawContext != NULL);
632
633 ASSERT (DrawContext->GetCursorImage != NULL);
634 CursorImage = DrawContext->GetCursorImage (DrawContext->GuiContext);
635 ASSERT (CursorImage != NULL);
636 //
637 // Poll the current cursor position late to reduce input lag.
638 //
640
641 ASSERT (PointerPos.Pos.X < DrawContext->Screen.Width);
642 ASSERT (PointerPos.Pos.Y < DrawContext->Screen.Height);
643
644 //
645 // Unconditionally draw the cursor to increase frametime consistency and
646 // prevent situational hiding.
647 //
648 // The original area of the cursor is restored at the beginning of the main
649 // drawing loop.
650 //
651
652 //
653 // Draw the new cursor at the new position.
654 //
655
656 BaseX = (INT64)PointerPos.Pos.X - BOOT_CURSOR_OFFSET * DrawContext->Scale;
657 if (BaseX < 0) {
658 ImageOffsetX = (UINT32)-BaseX;
659 DrawBaseX = 0;
660 } else {
661 ImageOffsetX = 0;
662 DrawBaseX = (UINT32)BaseX;
663 }
664
665 //
666 // MaxWidth/Height are for subsequent GuiDrawToBuffer, but also for
667 // saved PointerOldDraw size below; so we replicate out here clipping
668 // which is done inside GuiDrawToBuffer, in order to only redraw the
669 // minimum required.
670 // BaseX/Y may be negative but will then add, and will not overflow
671 // when within valid bounds.
672 //
673 MaxWidth = MIN (CursorImage->Width - ImageOffsetX, (UINT32)(DrawContext->Screen.Width - BaseX));
674
675 BaseY = (INT64)PointerPos.Pos.Y - BOOT_CURSOR_OFFSET * DrawContext->Scale;
676 if (BaseY < 0) {
677 ImageOffsetY = (UINT32)-BaseY;
678 DrawBaseY = 0;
679 } else {
680 ImageOffsetY = 0;
681 DrawBaseY = (UINT32)BaseY;
682 }
683
684 MaxHeight = MIN (CursorImage->Height - ImageOffsetY, (UINT32)(DrawContext->Screen.Height - BaseY));
685
687 CursorImage,
688 DrawContext->CursorOpacity,
689 DrawContext,
690 BaseX,
691 BaseY,
692 ImageOffsetX,
693 ImageOffsetY,
694 MaxWidth,
695 MaxHeight
696 );
697 //
698 // Queue a draw request for the newly drawn cursor.
699 //
701 DrawBaseX,
702 DrawBaseY,
703 MaxWidth,
704 MaxHeight
705 );
706
707 mPointerOldDrawBaseX = DrawBaseX;
708 mPointerOldDrawBaseY = DrawBaseY;
709 mPointerOldDrawWidth = MaxWidth;
710 mPointerOldDrawHeight = MaxHeight;
711}
712
722STATIC
723UINT64
725 IN UINT64 Delay
726 )
727{
728 UINT64 Ticks;
729 UINT64 Tsc;
730
731 //
732 // The target timer count is calculated here
733 //
734 Ticks = AsmReadTsc () + Delay;
735
736 //
737 // Wait until time out
738 // Timer wrap-arounds are NOT handled correctly by this function.
739 // Thus, this function must be called within 10 years of reset since
740 // Intel guarantees a minimum of 10 years before the TSC wraps.
741 //
742 while ((Tsc = AsmReadTsc ()) < Ticks) {
743 CpuPause ();
744 }
745
746 return Tsc;
747}
748
749VOID
751 IN OUT GUI_DRAWING_CONTEXT *DrawContext
752 )
753{
754 UINTN Index;
755 UINTN ReverseIndex;
756
757 UINT64 EndTsc;
758 UINT64 DeltaTsc;
759
760 ASSERT (DrawContext != NULL);
761 ASSERT (DrawContext->Screen.OffsetX == 0);
762 ASSERT (DrawContext->Screen.OffsetY == 0);
763 ASSERT (DrawContext->Screen.Draw != NULL);
764 for (Index = 0; Index < mNumValidDrawReqs; ++Index) {
765 DrawContext->Screen.Draw (
766 &DrawContext->Screen,
767 DrawContext,
768 DrawContext->GuiContext,
769 0,
770 0,
771 mDrawRequests[Index].X,
772 mDrawRequests[Index].Y,
773 mDrawRequests[Index].Width,
774 mDrawRequests[Index].Height,
775 DrawContext->Screen.Opacity
776 );
777 }
778
779 EndTsc = AsmReadTsc ();
780 DeltaTsc = EndTsc - mStartTsc;
781 if (DeltaTsc < mDeltaTscTarget) {
782 EndTsc = InternalCpuDelayTsc (mDeltaTscTarget - DeltaTsc);
783 }
784
785 if (mPointerContext != NULL) {
786 GuiOverlayPointer (DrawContext);
787 }
788
789 //
790 // FIXME: Reversing the blit order here has several benefits, due to the implicit
791 // old-before-new ordering which has been used when making the draw requests. The whole
792 // screen is updated in the memory buffer (by redrawing just the changing parts), then
793 // these parts are transferred one by one to the video memory.
794 // Due to lack of vsync in UEFI, any point through this transfer can be visible on screen.
795 // Reversing the blit order means:
796 // - Combined old+new mouse pointer area can no longer show part of moving text one frame
797 // ahead of the rest (see REF); moving text may instead 'tear' mouse, but this is
798 // much less visible
799 // - If mouse pointer is moving fast (old+new area is not merged), new pointer
800 // is always added before old pointer is removed, avoiding mouse disappearing
801 // - (A similar logic to the preceding should apply e.g. to the moving OS selector too)
802 // So reversing here gives a 'free' small but visible improvement in the display, given the
803 // current draw order; but a better full fix would be to specify explicit ordering
804 // requirements with each draw request, which would allow the best blit order to get this
805 // same improvement to be calculated independently of the order in which requests are added.
806 // REF: https://github.com/acidanthera/bugtracker/issues/1852
807 //
808 for (Index = 0; Index < mNumValidDrawReqs; ++Index) {
809 ReverseIndex = mNumValidDrawReqs - Index - 1;
813 EfiBltBufferToVideo,
814 mDrawRequests[ReverseIndex].X,
815 mDrawRequests[ReverseIndex].Y,
816 mDrawRequests[ReverseIndex].X,
817 mDrawRequests[ReverseIndex].Y,
818 mDrawRequests[ReverseIndex].Width,
819 mDrawRequests[ReverseIndex].Height,
821 );
822 }
823
825 //
826 // Explicitly include BLT time in the timing calculation.
827 // FIXME: GOP takes inconsistently long depending on dimensions.
828 //
829 mStartTsc = EndTsc;
830}
831
832VOID
834 IN OUT GUI_DRAWING_CONTEXT *DrawContext
835 )
836{
837 ASSERT (DrawContext != NULL);
838
840
841 GuiRequestDraw (0, 0, DrawContext->Screen.Width, DrawContext->Screen.Height);
842 GuiFlushScreen (DrawContext);
843}
844
845EFI_STATUS
847 IN BOOT_PICKER_GUI_CONTEXT *GuiContext,
848 IN INT32 CursorOffsetX,
849 IN INT32 CursorOffsetY
850 )
851{
852 CONST EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *OutputInfo;
853 INT64 CursorX;
854 INT64 CursorY;
855
856 mOutputContext = GuiOutputConstruct (GuiContext->Scale);
857 if (mOutputContext == NULL) {
858 DEBUG ((DEBUG_WARN, "OCUI: Failed to initialise output\n"));
859 return EFI_UNSUPPORTED;
860 }
861
862 OutputInfo = GuiOutputGetInfo (mOutputContext);
863 ASSERT (OutputInfo != NULL);
864
865 if ((GuiContext->PickerContext->PickerAttributes & OC_ATTR_USE_POINTER_CONTROL) != 0) {
866 CursorX = (INT64)CursorOffsetX + OutputInfo->HorizontalResolution / 2;
867 if (CursorX < 0) {
868 CursorX = 0;
869 } else if (CursorX > OutputInfo->HorizontalResolution - 1) {
870 CursorX = OutputInfo->HorizontalResolution - 1;
871 }
872
873 CursorY = (INT64)CursorOffsetY + OutputInfo->VerticalResolution / 2;
874 if (CursorY < 0) {
875 CursorY = 0;
876 } else if (CursorY > OutputInfo->VerticalResolution - 1) {
877 CursorY = OutputInfo->VerticalResolution - 1;
878 }
879
881 (UINT32)CursorX,
882 (UINT32)CursorY,
883 OutputInfo->HorizontalResolution,
884 OutputInfo->VerticalResolution,
885 GuiContext->Scale
886 );
887 if (mPointerContext == NULL) {
888 DEBUG ((DEBUG_WARN, "OCUI: Failed to initialise pointer\n"));
889 }
890 }
891
892 mKeyContext = GuiKeyConstruct (GuiContext->PickerContext);
893 if (mKeyContext == NULL) {
894 DEBUG ((DEBUG_WARN, "OCUI: Failed to initialise key input\n"));
895 }
896
897 if ((mPointerContext == NULL) && (mKeyContext == NULL)) {
899 return EFI_UNSUPPORTED;
900 }
901
902 mScreenBufferDelta = OutputInfo->HorizontalResolution * sizeof (*mScreenBuffer);
903 mScreenBuffer = AllocatePool (OutputInfo->VerticalResolution * mScreenBufferDelta);
904 if (mScreenBuffer == NULL) {
905 DEBUG ((DEBUG_WARN, "OCUI: GUI alloc failure\n"));
907 return EFI_OUT_OF_RESOURCES;
908 }
909
910 MtrrSetMemoryAttribute (
911 (EFI_PHYSICAL_ADDRESS)(UINTN)mScreenBuffer,
912 mScreenBufferDelta * OutputInfo->VerticalResolution,
913 CacheWriteBack
914 );
915
917
918 return EFI_SUCCESS;
919}
920
921VOID
923 VOID
924 )
925{
926 if (mOutputContext != NULL) {
928 mOutputContext = NULL;
929 }
930
931 if (mPointerContext != NULL) {
933 mPointerContext = NULL;
934 }
935
936 if (mKeyContext != NULL) {
938 mKeyContext = NULL;
939 }
940}
941
942VOID
944 OUT GUI_DRAWING_CONTEXT *DrawContext,
945 IN BOOT_PICKER_GUI_CONTEXT *GuiContext,
946 IN CONST GUI_VIEW_CONTEXT *ViewContext
947 )
948{
949 CONST EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *OutputInfo;
950
951 ASSERT (DrawContext != NULL);
952
953 OutputInfo = GuiOutputGetInfo (mOutputContext);
954 ASSERT (OutputInfo != NULL);
955
956 DrawContext->CursorOpacity = 0xFF;
957 DrawContext->Scale = GuiContext->Scale;
958
959 DrawContext->Screen.OffsetX = 0;
960 DrawContext->Screen.OffsetY = 0;
961 DrawContext->Screen.Width = OutputInfo->HorizontalResolution;
962 DrawContext->Screen.Height = OutputInfo->VerticalResolution;
963 DrawContext->Screen.Opacity = 0xFF;
964 DrawContext->Screen.Draw = ViewContext->Draw;
965 DrawContext->Screen.KeyEvent = ViewContext->KeyEvent;
966 DrawContext->Screen.PtrEvent = ViewContext->PtrEvent;
967 DrawContext->Screen.NumChildren = ViewContext->NumChildren;
968 DrawContext->Screen.Children = ViewContext->Children;
969
970 DrawContext->GetCursorImage = ViewContext->GetCursorImage;
971 DrawContext->ExitLoop = ViewContext->ExitLoop;
972 DrawContext->GuiContext = GuiContext;
973 InitializeListHead (&DrawContext->Animations);
974}
975
976VOID
978 IN OUT GUI_DRAWING_CONTEXT *DrawContext,
979 OUT BOOT_PICKER_GUI_CONTEXT *GuiContext
980 )
981{
982 GUI_PTR_POSITION CursorPosition;
983 CONST EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *OutputInfo;
984
985 if (mPointerContext != NULL) {
986 OutputInfo = GuiOutputGetInfo (mOutputContext);
987 GuiPointerGetPosition (mPointerContext, &CursorPosition);
988 GuiContext->CursorOffsetX = (INT32)((INT64)CursorPosition.Pos.X - OutputInfo->HorizontalResolution / 2);
989 GuiContext->CursorOffsetY = (INT32)((INT64)CursorPosition.Pos.Y - OutputInfo->VerticalResolution / 2);
990 }
991
992 ZeroMem (DrawContext, sizeof (*DrawContext));
993}
994
995VOID
997 IN GUI_OBJ *This,
998 IN GUI_DRAWING_CONTEXT *DrawContext,
999 OUT INT64 *BaseX,
1000 OUT INT64 *BaseY
1001 )
1002{
1003 GUI_OBJ *Obj;
1004 GUI_OBJ_CHILD *ChildObj;
1005 INT64 X;
1006 INT64 Y;
1007 UINT32 Index;
1008
1009 ASSERT (This != NULL);
1010 ASSERT (DrawContext != NULL);
1011 ASSERT (DrawContext->Screen.OffsetX == 0);
1012 ASSERT (DrawContext->Screen.OffsetY == 0);
1013 ASSERT (BaseX != NULL);
1014 ASSERT (BaseY != NULL);
1015
1016 X = 0;
1017 Y = 0;
1018 Obj = This;
1019 do {
1020 X += Obj->OffsetX;
1021 Y += Obj->OffsetY;
1022
1023 ChildObj = BASE_CR (Obj, GUI_OBJ_CHILD, Obj);
1024 Obj = ChildObj->Parent;
1025
1026 DEBUG_CODE_BEGIN ();
1027 if (Obj != NULL) {
1028 for (Index = 0; Index < Obj->NumChildren; ++Index) {
1029 if (Obj->Children[Index] == ChildObj) {
1030 break;
1031 }
1032 }
1033
1034 ASSERT (Index != Obj->NumChildren);
1035 }
1036
1037 DEBUG_CODE_END ();
1038 } while (Obj != NULL);
1039
1040 DEBUG_CODE_BEGIN ();
1041 for (Index = 0; Index < DrawContext->Screen.NumChildren; ++Index) {
1042 if (DrawContext->Screen.Children[Index] == ChildObj) {
1043 break;
1044 }
1045 }
1046
1047 ASSERT (Index != DrawContext->Screen.NumChildren);
1048 DEBUG_CODE_END ();
1049
1050 *BaseX = X;
1051 *BaseY = Y;
1052}
1053
1054VOID
1056 IN OUT GUI_DRAWING_CONTEXT *DrawContext
1057 )
1058{
1059 BOOLEAN Result;
1060
1061 GUI_KEY_EVENT KeyEvent;
1062 GUI_PTR_EVENT PointerEvent;
1063 GUI_OBJ *TempObject;
1064 GUI_OBJ *HoldObject;
1065 INT64 HoldObjBaseX;
1066 INT64 HoldObjBaseY;
1067 CONST LIST_ENTRY *AnimEntry;
1068 GUI_ANIMATION *Animation;
1069 UINT64 LoopStartTsc;
1070 UINT64 LastTsc;
1071 UINT64 NewLastTsc;
1072
1073 ASSERT (DrawContext != NULL);
1074
1076 DrawContext->FrameTime = 0;
1077 HoldObject = NULL;
1078 //
1079 // Clear previous inputs.
1080 //
1081 if (mPointerContext != NULL) {
1083 }
1084
1086
1087 //
1088 // Pointer state will be implicitly initialised on the first call in the loop.
1089 //
1090
1091 //
1092 // Main drawing loop, time and derieve sub-frequencies as required.
1093 //
1094 LastTsc = LoopStartTsc = mStartTsc = AsmReadTsc ();
1095 do {
1096 if (mPointerContext != NULL) {
1097 //
1098 // Restore the rectangle previously covered by the cursor.
1099 // The new cursor is drawn right before flushing the screen.
1100 //
1106 );
1107 //
1108 // Process pointer events.
1109 //
1110 Result = GuiPointerGetEvent (mPointerContext, &PointerEvent);
1111 if (Result) {
1112 if (PointerEvent.Type == GuiPointerPrimaryUp) {
1113 //
1114 // 'Button down' must have caught and set an interaction object, but
1115 // it may be NULL for objects that solely delegate pointer events.
1116 //
1117 if (HoldObject != NULL) {
1119 HoldObject,
1120 DrawContext,
1121 &HoldObjBaseX,
1122 &HoldObjBaseY
1123 );
1124 HoldObject->PtrEvent (
1125 HoldObject,
1126 DrawContext,
1127 DrawContext->GuiContext,
1128 HoldObjBaseX,
1129 HoldObjBaseY,
1130 &PointerEvent
1131 );
1132 HoldObject = NULL;
1133 }
1134 } else {
1135 //
1136 // HoldObject == NULL cannot be tested here as double-click may arrive
1137 // before button up.
1138 //
1139 ASSERT (PointerEvent.Type != GuiPointerPrimaryUp);
1140 TempObject = DrawContext->Screen.PtrEvent (
1141 &DrawContext->Screen,
1142 DrawContext,
1143 DrawContext->GuiContext,
1144 0,
1145 0,
1146 &PointerEvent
1147 );
1148 if (PointerEvent.Type == GuiPointerPrimaryDown) {
1149 HoldObject = TempObject;
1150 }
1151 }
1152
1153 //
1154 // If detected pointer press then disable menu timeout
1155 //
1156 if (DrawContext->TimeOutSeconds > 0) {
1157 //
1158 // Voice only unrelated key press.
1159 //
1160 if ( !DrawContext->GuiContext->ReadyToBoot
1161 && DrawContext->GuiContext->PickerContext->PickerAudioAssist)
1162 {
1163 DrawContext->GuiContext->PickerContext->PlayAudioFile (
1164 DrawContext->GuiContext->PickerContext,
1167 FALSE
1168 );
1169 }
1170
1171 DrawContext->TimeOutSeconds = 0;
1172 }
1173 } else if (HoldObject != NULL) {
1174 //
1175 // If there are no events to process, update the cursor position with
1176 // the interaction object for visual effects.
1177 //
1178 PointerEvent.Type = GuiPointerPrimaryDown;
1179 GuiPointerGetPosition (mPointerContext, &PointerEvent.Pos);
1181 HoldObject,
1182 DrawContext,
1183 &HoldObjBaseX,
1184 &HoldObjBaseY
1185 );
1186 HoldObject->PtrEvent (
1187 HoldObject,
1188 DrawContext,
1189 DrawContext->GuiContext,
1190 HoldObjBaseX,
1191 HoldObjBaseY,
1192 &PointerEvent
1193 );
1194 }
1195 }
1196
1197 if (mKeyContext != NULL) {
1198 //
1199 // Process key events. Only allow one key at a time for now.
1200 //
1201 Result = GuiKeyGetEvent (mKeyContext, &KeyEvent);
1202 if (Result) {
1203 DrawContext->Screen.KeyEvent (
1204 &DrawContext->Screen,
1205 DrawContext,
1206 DrawContext->GuiContext,
1207 &KeyEvent
1208 );
1209 //
1210 // If detected key press then disable menu timeout
1211 //
1212 if (DrawContext->TimeOutSeconds > 0) {
1213 //
1214 // Voice only unrelated key press.
1215 //
1216 if ( !DrawContext->GuiContext->ReadyToBoot
1217 && DrawContext->GuiContext->PickerContext->PickerAudioAssist)
1218 {
1219 DrawContext->GuiContext->PickerContext->PlayAudioFile (
1220 DrawContext->GuiContext->PickerContext,
1223 FALSE
1224 );
1225 }
1226
1227 DrawContext->TimeOutSeconds = 0;
1228 }
1229 }
1230 }
1231
1232 //
1233 // Process queued animations.
1234 //
1235 AnimEntry = GetFirstNode (&DrawContext->Animations);
1236 while (!IsNull (&DrawContext->Animations, AnimEntry)) {
1237 Animation = BASE_CR (AnimEntry, GUI_ANIMATION, Link);
1238 Result = Animation->Animate (Animation->Context, DrawContext, DrawContext->FrameTime);
1239
1240 AnimEntry = GetNextNode (&DrawContext->Animations, AnimEntry);
1241
1242 if (Result) {
1243 RemoveEntryList (&Animation->Link);
1244 InitializeListHead (&Animation->Link);
1245 }
1246 }
1247
1248 ++DrawContext->FrameTime;
1249 //
1250 // Flush the changes performed in this refresh iteration.
1251 //
1252 GuiFlushScreen (DrawContext);
1253
1254 NewLastTsc = AsmReadTsc ();
1255
1256 if ( (DrawContext->GuiContext->AudioPlaybackTimeout >= 0)
1257 && DrawContext->GuiContext->PickerContext->PickerAudioAssist)
1258 {
1259 DrawContext->GuiContext->AudioPlaybackTimeout -= (INT32)(DivU64x32 (
1260 GetTimeInNanoSecond (NewLastTsc - LastTsc),
1261 1000000
1262 ));
1263 if (DrawContext->GuiContext->AudioPlaybackTimeout <= 0) {
1264 switch (DrawContext->GuiContext->VoAction) {
1266 {
1267 DrawContext->GuiContext->PickerContext->PlayAudioFile (
1268 DrawContext->GuiContext->PickerContext,
1271 FALSE
1272 );
1273 DrawContext->GuiContext->PickerContext->PlayAudioEntry (
1274 DrawContext->GuiContext->PickerContext,
1275 DrawContext->GuiContext->BootEntry
1276 );
1277 break;
1278 }
1279
1281 {
1282 DrawContext->GuiContext->PickerContext->PlayAudioFile (
1283 DrawContext->GuiContext->PickerContext,
1286 TRUE
1287 );
1288 break;
1289 }
1290
1292 {
1293 DrawContext->GuiContext->PickerContext->PlayAudioFile (
1294 DrawContext->GuiContext->PickerContext,
1297 FALSE
1298 );
1299 DrawContext->GuiContext->PickerContext->PlayAudioFile (
1300 DrawContext->GuiContext->PickerContext,
1303 TRUE
1304 );
1305 break;
1306 }
1307
1309 {
1310 DrawContext->GuiContext->PickerContext->PlayAudioFile (
1311 DrawContext->GuiContext->PickerContext,
1314 FALSE
1315 );
1316 DrawContext->GuiContext->PickerContext->PlayAudioFile (
1317 DrawContext->GuiContext->PickerContext,
1320 TRUE
1321 );
1322 break;
1323 }
1324
1325 default:
1326 {
1327 ASSERT (FALSE);
1328 break;
1329 }
1330 }
1331
1332 //
1333 // Avoid playing twice if we reach precisely 0.
1334 //
1335 DrawContext->GuiContext->AudioPlaybackTimeout = -1;
1336 }
1337 }
1338
1339 //
1340 // Exit early if reach timer timeout and timer isn't disabled due to key event
1341 //
1342 if ( (DrawContext->TimeOutSeconds > 0)
1343 && (GetTimeInNanoSecond (NewLastTsc - LoopStartTsc) >= DrawContext->TimeOutSeconds * 1000000000ULL))
1344 {
1345 if (DrawContext->GuiContext->PickerContext->PickerAudioAssist) {
1346 DrawContext->GuiContext->PickerContext->PlayAudioFile (
1347 DrawContext->GuiContext->PickerContext,
1350 FALSE
1351 );
1352 }
1353
1354 DrawContext->GuiContext->ReadyToBoot = TRUE;
1355 break;
1356 }
1357
1358 LastTsc = NewLastTsc;
1359 } while (!DrawContext->ExitLoop (DrawContext, DrawContext->GuiContext));
1360}
1361
1362VOID
1364 IN OUT GUI_DRAWING_CONTEXT *DrawContext,
1365 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Pixel
1366 )
1367{
1368 GuiOutputBlt (
1370 Pixel,
1371 EfiBltVideoFill,
1372 0,
1373 0,
1374 0,
1375 0,
1376 DrawContext->Screen.Width,
1377 DrawContext->Screen.Height,
1378 0
1379 );
1380}
1381
1385STATIC
1386INT32
1388 IN INT32 x
1389 )
1390{
1391 //
1392 // S(x) = x * ( (3<<p) - (x*x>>r) ) >> s
1393 // n : Q-pos for quarter circle 13
1394 // A : Q-pos for output 12
1395 // p : Q-pos for parentheses intermediate 15
1396 // r = 2n-p 11
1397 // s = A-1-p-n 17
1398 //
1399 STATIC CONST INT32 n = 13;
1400 STATIC CONST INT32 p = 15;
1401 STATIC CONST INT32 r = 11;
1402 STATIC CONST INT32 s = 17;
1403
1404 x = x << (30 - n); // shift to full s32 range (Q13->Q30)
1405
1406 if ((x ^ (x << 1)) < 0) {
1407 // test for quadrant 1 or 2
1408 x = (1 << 31) - x;
1409 }
1410
1411 x = x >> (30 - n);
1412
1413 return x * ((3 << p) - (x * x >> r)) >> s;
1414}
1415
1416UINT32
1418 IN CONST GUI_INTERPOLATION *Interpol,
1419 IN UINT64 CurrentTime
1420 )
1421{
1422 INT32 AnimTime;
1423 UINT32 DeltaTime;
1424
1425 ASSERT (Interpol != NULL);
1426 ASSERT (Interpol->Duration > 0);
1427
1428 STATIC CONST UINT32 InterpolFpTimeFactor = 1U << 12U;
1429
1430 if (CurrentTime <= Interpol->StartTime) {
1431 return Interpol->StartValue;
1432 }
1433
1434 DeltaTime = (UINT32)(CurrentTime - Interpol->StartTime);
1435
1436 if (DeltaTime >= Interpol->Duration) {
1437 return Interpol->EndValue;
1438 }
1439
1440 AnimTime = (INT32)DivU64x64Remainder ((UINT64)InterpolFpTimeFactor * DeltaTime, Interpol->Duration, NULL);
1441 if (Interpol->Type == GuiInterpolTypeSmooth) {
1442 //
1443 // One InterpolFpTimeFactor unit corresponds to 45 degrees in the unit circle. Divide
1444 // the time by two because the integral of sin from 0 to Pi is equal to 2,
1445 // i.e. double speed.
1446 //
1447 AnimTime = isin_S3 (4 * AnimTime / 2);
1448 //
1449 // FP-square to further smoothen the animation.
1450 //
1451 AnimTime = (AnimTime * AnimTime) / InterpolFpTimeFactor;
1452 } else {
1453 ASSERT (Interpol->Type == GuiInterpolTypeLinear);
1454 }
1455
1456 return (Interpol->EndValue * AnimTime
1457 + (Interpol->StartValue * (InterpolFpTimeFactor - AnimTime)))
1458 / InterpolFpTimeFactor;
1459}
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
VOID GuiBlendPixelSolid(IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackPixel, IN CONST EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FrontPixel)
Definition Blending.c:98
VOID GuiBlendPixel(IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackPixel, IN CONST EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FrontPixel, IN UINT8 Opacity)
Definition Blending.c:126
VOID GuiBlendPixelOpaque(IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackPixel, IN CONST EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FrontPixel, IN UINT8 Opacity)
Definition Blending.c:60
#define RGB_APPLY_OPACITY(Rgba, Opacity)
Definition Blending.h:11
UINT16 x
Definition BmfFile.h:83
@ CanopyVoFocusRestart
Definition GuiApp.h:113
@ CanopyVoFocusShutDown
Definition GuiApp.h:112
@ CanopyVoSelectedEntry
Definition GuiApp.h:110
@ CanopyVoFocusPassword
Definition GuiApp.h:111
#define BOOT_CURSOR_OFFSET
Definition GuiApp.h:16
VOID GuiOutputDestruct(IN GUI_OUTPUT_CONTEXT *Context)
VOID GuiPointerReset(IN OUT GUI_POINTER_CONTEXT *Context)
CONST EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * GuiOutputGetInfo(IN GUI_OUTPUT_CONTEXT *Context)
BOOLEAN GuiKeyGetEvent(IN OUT GUI_KEY_CONTEXT *Context, OUT GUI_KEY_EVENT *Event)
GUI_KEY_CONTEXT * GuiKeyConstruct(IN OC_PICKER_CONTEXT *PickerContext)
VOID GuiPointerGetPosition(IN OUT GUI_POINTER_CONTEXT *Context, OUT GUI_PTR_POSITION *Position)
VOID EFIAPI GuiKeyReset(IN OUT GUI_KEY_CONTEXT *Context)
VOID GuiKeyDestruct(IN GUI_KEY_CONTEXT *Context)
GUI_OUTPUT_CONTEXT * GuiOutputConstruct(IN UINT32 Scale)
Definition OutputStGop.c:50
GUI_POINTER_CONTEXT * GuiPointerConstruct(IN UINT32 DefaultX, IN UINT32 DefaultY, IN UINT32 Width, IN UINT32 Height, IN UINT8 UiScale)
VOID GuiPointerDestruct(IN GUI_POINTER_CONTEXT *Context)
EFI_STATUS EFIAPI GuiOutputBlt(IN GUI_OUTPUT_CONTEXT *Context, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, IN UINTN SourceX, IN UINTN SourceY, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height, IN UINTN Delta OPTIONAL)
Definition OutputStGop.c:84
BOOLEAN GuiPointerGetEvent(IN OUT GUI_POINTER_CONTEXT *Context, OUT GUI_PTR_EVENT *Event)
#define OC_VOICE_OVER_AUDIO_FILE_TIMEOUT
Definition OcAudio.h:72
#define OC_VOICE_OVER_AUDIO_FILE_SELECTED
Definition OcAudio.h:67
#define OC_VOICE_OVER_AUDIO_FILE_ABORT_TIMEOUT
Definition OcAudio.h:43
#define OC_VOICE_OVER_AUDIO_FILE_ENTER_PASSWORD
Definition OcAudio.h:47
#define OC_VOICE_OVER_AUDIO_FILE_RESTART
Definition OcAudio.h:66
#define OC_VOICE_OVER_AUDIO_FILE_SHUT_DOWN
Definition OcAudio.h:69
#define OC_VOICE_OVER_AUDIO_BASE_TYPE_OPEN_CORE
Definition OcAudio.h:38
#define OC_ATTR_USE_POINTER_CONTROL
UINT64 OcGetTSCFrequency(VOID)
STATIC UINT64 mStartTsc
Definition OpenCanopy.c:55
VOID GuiRedrawAndFlushScreen(IN OUT GUI_DRAWING_CONTEXT *DrawContext)
Definition OpenCanopy.c:833
STATIC UINT32 mPointerOldDrawBaseX
Definition OpenCanopy.c:64
VOID GuiDrawToBuffer(IN CONST GUI_IMAGE *Image, IN UINT8 Opacity, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN INT64 BaseX, IN INT64 BaseY, IN UINT32 OffsetX, IN UINT32 OffsetY, IN UINT32 Width, IN UINT32 Height)
Definition OpenCanopy.c:354
STATIC UINT8 mNumValidDrawReqs
Definition OpenCanopy.c:59
VOID GuiRequestDraw(IN UINT32 PosX, IN UINT32 PosY, IN UINT32 Width, IN UINT32 Height)
Definition OpenCanopy.c:475
STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL * mScreenBuffer
Definition OpenCanopy.c:49
STATIC INT32 isin_S3(IN INT32 x)
STATIC UINT32 mPointerOldDrawWidth
Definition OpenCanopy.c:66
VOID GuiDrawToBufferFill(IN CONST EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Colour, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN UINT32 PosX, IN UINT32 PosY, IN UINT32 Width, IN UINT32 Height)
Definition OpenCanopy.c:276
VOID GuiClearScreen(IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Pixel)
BOOLEAN GuiClipChildBounds(IN INT64 ChildOffset, IN UINT32 ChildLength, IN OUT UINT32 *ReqOffset, IN OUT UINT32 *ReqLength)
Definition OpenCanopy.c:73
VOID GuiRequestDrawCrop(IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN INT64 X, IN INT64 Y, IN UINT32 Width, IN UINT32 Height)
Definition OpenCanopy.c:570
EFI_STATUS GuiLibConstruct(IN BOOT_PICKER_GUI_CONTEXT *GuiContext, IN INT32 CursorOffsetX, IN INT32 CursorOffsetY)
Definition OpenCanopy.c:846
STATIC UINT64 InternalCpuDelayTsc(IN UINT64 Delay)
Definition OpenCanopy.c:724
VOID GuiDrawLoop(IN OUT GUI_DRAWING_CONTEXT *DrawContext)
VOID GuiViewDeinitialize(IN OUT GUI_DRAWING_CONTEXT *DrawContext, OUT BOOT_PICKER_GUI_CONTEXT *GuiContext)
Definition OpenCanopy.c:977
STATIC UINT64 mDeltaTscTarget
Definition OpenCanopy.c:54
VOID GuiOverlayPointer(IN OUT GUI_DRAWING_CONTEXT *DrawContext)
Definition OpenCanopy.c:615
STATIC GUI_DRAW_REQUEST mDrawRequests[6]
Definition OpenCanopy.c:60
GUI_OBJ * GuiObjDelegatePtrEvent(IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN INT64 BaseX, IN INT64 BaseY, IN CONST GUI_PTR_EVENT *Event)
Definition OpenCanopy.c:226
#define PIXEL_TO_UINT32(Pixel)
Definition OpenCanopy.c:69
GLOBAL_REMOVE_IF_UNREFERENCED GUI_POINTER_CONTEXT * mPointerContext
Definition OpenCanopy.c:44
VOID GuiFlushScreen(IN OUT GUI_DRAWING_CONTEXT *DrawContext)
Definition OpenCanopy.c:750
STATIC UINT32 mScreenBufferDelta
Definition OpenCanopy.c:50
UINT32 GuiGetInterpolatedValue(IN CONST GUI_INTERPOLATION *Interpol, IN UINT64 CurrentTime)
STATIC GUI_OUTPUT_CONTEXT * mOutputContext
Definition OpenCanopy.c:43
VOID GuiViewInitialize(OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *GuiContext, IN CONST GUI_VIEW_CONTEXT *ViewContext)
Definition OpenCanopy.c:943
VOID GuiLibDestruct(VOID)
Definition OpenCanopy.c:922
VOID GuiGetBaseCoords(IN GUI_OBJ *This, IN GUI_DRAWING_CONTEXT *DrawContext, OUT INT64 *BaseX, OUT INT64 *BaseY)
Definition OpenCanopy.c:996
VOID GuiObjDrawDelegate(IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN INT64 BaseX, IN INT64 BaseY, IN UINT32 OffsetX, IN UINT32 OffsetY, IN UINT32 Width, IN UINT32 Height, IN UINT8 Opacity)
Definition OpenCanopy.c:137
GLOBAL_REMOVE_IF_UNREFERENCED GUI_KEY_CONTEXT * mKeyContext
Definition OpenCanopy.c:45
STATIC UINT32 mPointerOldDrawBaseY
Definition OpenCanopy.c:65
STATIC UINT32 mPointerOldDrawHeight
Definition OpenCanopy.c:67
@ GuiPointerPrimaryUp
Definition OpenCanopy.h:23
@ GuiPointerPrimaryDown
Definition OpenCanopy.h:22
@ GuiInterpolTypeLinear
Definition OpenCanopy.h:348
@ GuiInterpolTypeSmooth
Definition OpenCanopy.h:349
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
Definition UserMath.c:59
UINT64 EFIAPI AsmReadTsc(VOID)
Definition UserMisc.c:232
VOID EFIAPI CpuPause(VOID)
Definition UserMisc.c:22
UINT64 EFIAPI GetTimeInNanoSecond(IN UINT64 Ticks)
#define ASSERT(x)
Definition coder.h:55
#define MIN(a, b)
Definition deflate.c:1673
#define DivU64x32(x, y, z)
GUI_ANIMATE Animate
Definition OpenCanopy.h:102
LIST_ENTRY Link
Definition OpenCanopy.h:100
GUI_OBJ * Parent
Definition OpenCanopy.h:123
GUI_OBJ_DRAW Draw
Definition OpenCanopy.h:113
INT64 OffsetX
Definition OpenCanopy.h:108
UINT32 NumChildren
Definition OpenCanopy.h:117
UINT32 Height
Definition OpenCanopy.h:111
UINT8 Opacity
Definition OpenCanopy.h:112
INT64 OffsetY
Definition OpenCanopy.h:109
GUI_OBJ_PTR_EVENT PtrEvent
Definition OpenCanopy.h:115
GUI_OBJ_CHILD ** Children
Definition OpenCanopy.h:118
UINT32 Width
Definition OpenCanopy.h:110
GUI_PTR_POSITION Pos
Definition OpenCanopy.h:37
struct GUI_PTR_POSITION::@111 Pos