public void Rasterize(ref UIOperationContext context, ref ImperativeRenderer renderer, DecorationSettings settings, ref TData data) { switch (context.Pass) { case RasterizePasses.Below: if (Below != null) { Below(context, ref renderer, settings, ref data); } return; case RasterizePasses.Content: if (Content != null) { Content(context, ref renderer, settings, ref data); } return; case RasterizePasses.Above: if (Above != null) { Above(context, ref renderer, settings, ref data); } return; case RasterizePasses.ContentClip: if (ContentClip != null) { ContentClip(context, ref renderer, settings, ref data); } return; } }
private void NestedContextPassSetup( ref UIOperationContext context, ref RasterizePassSet passSet, ref ImperativeRenderer renderer, ref UIOperationContext passContext, out ImperativeRenderer contentRenderer, out RasterizePassSet childrenPassSet, out UIOperationContext contentContext, int previousStackDepth, ref int newStackDepth ) { renderer.Layer += 1; passContext.Clone(out contentContext); contentRenderer = renderer.MakeSubgroup(); if (ShouldClipContent) { newStackDepth = previousStackDepth + 1; contentRenderer.DepthStencilState = context.UIContext.GetStencilTest(newStackDepth); childrenPassSet = new RasterizePassSet(ref contentRenderer, newStackDepth, passSet.OverlayQueue); } else { contentRenderer.DepthStencilState = (previousStackDepth <= 0) ? DepthStencilState.None : context.UIContext.GetStencilTest(previousStackDepth); childrenPassSet = new RasterizePassSet(ref contentRenderer, newStackDepth, passSet.OverlayQueue); } renderer.Layer += 1; }
private void RasterizeAllPasses(ref UIOperationContext context, ref RectF box, ref RasterizePassSet passSet, bool compositing) { try { if (Appearance.DecorationProvider != null) { UIOperationContext.PushDecorationProvider(ref context, Appearance.DecorationProvider); } var decorations = GetDecorator(context.DecorationProvider, context.DefaultDecorator); var contentBox = GetRect(contentRect: true); var state = GetCurrentState(ref context); var settings = MakeDecorationSettings(ref box, ref contentBox, state, compositing); if (!IsPassDisabled(RasterizePasses.Below, decorations)) { RasterizePass(ref context, ref settings, decorations, compositing, ref passSet, ref passSet.Below, RasterizePasses.Below); } if (!IsPassDisabled(RasterizePasses.Content, decorations)) { RasterizePass(ref context, ref settings, decorations, compositing, ref passSet, ref passSet.Content, RasterizePasses.Content); } if (!IsPassDisabled(RasterizePasses.Above, decorations)) { RasterizePass(ref context, ref settings, decorations, compositing, ref passSet, ref passSet.Above, RasterizePasses.Above); } } finally { if (Appearance.DecorationProvider != null) { UIOperationContext.PopDecorationProvider(ref context); } } }
private void RasterizeComposited(ref UIOperationContext context, ref RectF box, ref RasterizePassSet passSet, float opacity, bool enableCompositor) { // HACK: Create padding around the element for drop shadows var padding = Appearance.Compositor?.Padding ?? Context.CompositorPaddingPx; box.SnapAndInset(out Vector2 tl, out Vector2 br, -padding); // Don't overflow the edges of the canvas with padding, it'd produce garbage pixels var canvasRect = context.UIContext.CanvasRect; canvasRect.Clamp(ref tl); canvasRect.Clamp(ref br); var compositeBox = new RectF(tl, br - tl); var srt = context.UIContext.GetScratchRenderTarget(context.Prepass, ref compositeBox); if (context.RenderTargetStack.Count > 0) { context.RenderTargetStack[context.RenderTargetStack.Count - 1].Dependencies.Add(srt); } context.RenderTargetStack.Add(srt); try { // passSet.Above.RasterizeRectangle(box.Position, box.Extent, 1f, Color.Red * 0.1f); RasterizeIntoPrepass(ref context, passSet, opacity, ref box, ref compositeBox, srt, enableCompositor); // passSet.Above.RasterizeEllipse(box.Center, Vector2.One * 3f, Color.White); } finally { context.RenderTargetStack.RemoveTail(1); context.UIContext.ReleaseScratchRenderTarget(srt.Instance); } }
protected override ControlKey OnGenerateLayoutTree(ref UIOperationContext context, ControlKey parent, ControlKey?existingKey) { var result = base.OnGenerateLayoutTree(ref context, parent, existingKey); context.Layout.SetTag(result, LayoutTags.Spacer); return(result); }
protected override ControlKey OnGenerateLayoutTree(ref UIOperationContext context, ControlKey parent, ControlKey?existingKey) { var decorator = GetDefaultDecorator(context.DecorationProvider); Aligner.ExtraMargins = decorator.Margins; var result = base.OnGenerateLayoutTree(ref context, parent, existingKey); context.Layout.SetTag(result, LayoutTags.Tooltip); return(result); }
private void RasterizeAllPassesTransformed(ref UIOperationContext context, ref RectF box, ref RasterizePassSet passSet) { if (MostRecentCompositeData == null) { MostRecentCompositeData = new CompositionData(); } MostRecentCompositeData.Box = box; var subPassSet = new RasterizePassSet(ref passSet, this, ApplyGlobalTransformMatrix); RasterizeAllPasses(ref context, ref box, ref subPassSet, false); }
void IMetricsProvider.GetContentAdjustment(ref UIOperationContext context, ControlStates state, out Vector2 offset, out Vector2 scale) { if (GetContentAdjustment != null) { GetContentAdjustment(context, state, out offset, out scale); } else { offset = Vector2.Zero; scale = Vector2.One; } }
private void RunPreRasterizeHandlerForHiddenControl(ref UIOperationContext context, ref RectF box) { if (!HasPreRasterizeHandler) { return; } var decorations = GetDecorator(context.DecorationProvider, context.DefaultDecorator); var state = GetCurrentState(ref context) | ControlStates.Invisible; var settings = MakeDecorationSettings(ref box, ref box, state, false); OnPreRasterize(ref context, settings, decorations); }
private void UpdateVisibleRegion(ref UIOperationContext context, ref RectF box) { var vr = context.VisibleRegion; vr.Left = Math.Max(context.VisibleRegion.Left, box.Left - UIContext.VisibilityPadding); vr.Top = Math.Max(context.VisibleRegion.Top, box.Top - UIContext.VisibilityPadding); var right = Math.Min(context.VisibleRegion.Extent.X, box.Extent.X + UIContext.VisibilityPadding); var bottom = Math.Min(context.VisibleRegion.Extent.Y, box.Extent.Y + UIContext.VisibilityPadding); vr.Width = right - vr.Left; vr.Height = bottom - vr.Top; context.VisibleRegion = vr; }
bool IMetricsProvider.GetTextSettings(ref UIOperationContext context, ControlStates state, out Material material, ref Color?color, out Vector4 userData) { if (GetTextSettings != null) { return(GetTextSettings(context, state, out material, ref color, out userData)); } else { material = default; userData = default; return(false); } }
private void RasterizeIntoPrepass( ref UIOperationContext context, RasterizePassSet passSet, float opacity, ref RectF box, ref RectF compositeBox, UIContext.ScratchRenderTarget rt, bool enableCompositor ) { UIOperationContext compositionContext; context.Clone(out compositionContext); compositionContext.Opacity = 1.0f; UpdateVisibleRegion(ref compositionContext, ref box); var newPassSet = new RasterizePassSet(ref rt.Renderer, 0, passSet.OverlayQueue); // newPassSet.Above.RasterizeEllipse(box.Center, Vector2.One * 6f, Color.White * 0.7f); RasterizeAllPasses(ref compositionContext, ref box, ref newPassSet, true); rt.Renderer.Layer += 1; var pos = Appearance.HasTransformMatrix ? Vector2.Zero : compositeBox.Position.Floor(); // FIXME: Is this the right layer? var sourceRect = new Rectangle( (int)compositeBox.Left, (int)compositeBox.Top, (int)compositeBox.Width, (int)compositeBox.Height ); var effectiveOpacity = context.Opacity * opacity; var dc = new BitmapDrawCall( // FIXME rt.Instance.Get(), pos, GameExtensionMethods.BoundsFromRectangle((int)Context.CanvasSize.X, (int)Context.CanvasSize.Y, in sourceRect), new Color(effectiveOpacity, effectiveOpacity, effectiveOpacity, effectiveOpacity), scale: 1.0f / Context.ScratchScaleFactor ); if (Appearance.HasTransformMatrix || enableCompositor) { RasterizeIntoPrepassComposited(ref passSet, ref compositeBox, ref dc, enableCompositor, effectiveOpacity); } else if (Appearance.Overlay) { passSet.OverlayQueue.Add(ref dc); } else { GetMaterialAndBlendStateForCompositing(out Material compositeMaterial, out BlendState compositeBlendState); passSet.Above.Draw( ref dc, material: compositeMaterial, blendState: compositeBlendState ?? RenderStates.PorterDuffOver ); passSet.Above.Layer += 1; } }
private void RasterizeAcceleratorOverlay( UIOperationContext context, ref ImperativeRenderer labelRenderer, ref ImperativeRenderer targetRenderer, Control control, InputID id, bool showFocused = false, Control forControl = null ) { if (id == null) { throw new ArgumentNullException("id"); } var gamePadMode = InputSources.FirstOrDefault() is GamepadVirtualKeyboardAndCursor; OverlayStringBuilder.Clear(); id.Format(OverlayStringBuilder, gamePadMode); RasterizeAcceleratorOverlay( context, ref labelRenderer, ref targetRenderer, control, OverlayStringBuilder, showFocused ); }
private void RasterizeAcceleratorOverlay( UIOperationContext context, ref ImperativeRenderer labelRenderer, ref ImperativeRenderer targetRenderer, AcceleratorInfo accel, bool showFocused = false, Control forControl = null ) { if (accel.Text != null) { RasterizeAcceleratorOverlay( context, ref labelRenderer, ref targetRenderer, accel.Target, accel.Text, showFocused, forControl ); } else { RasterizeAcceleratorOverlay( context, ref labelRenderer, ref targetRenderer, accel.Target, GetInputID(accel.Key, accel.Modifiers), showFocused, forControl ); } }
private void NestedContextPassTeardown( ref UIOperationContext context, ref DecorationSettings settings, IDecorator decorations, ref RasterizePassSet passSet, ref ImperativeRenderer contentRenderer, ref UIOperationContext contentContext, int previousStackDepth ) { // If this is the first stencil pass instead of a nested one, clear the stencil buffer if (passSet.StackDepth < 1) { contentRenderer.Clear(stencil: 0, layer: -9999); } else { // Erase any siblings' clip regions contentRenderer.DepthStencilState = context.UIContext.GetStencilRestore(previousStackDepth); contentRenderer.FillRectangle(new Rectangle(-1, -1, 9999, 9999), Color.Transparent, blendState: RenderStates.DrawNone, layer: -1000); } contentRenderer.DepthStencilState = context.UIContext.GetStencilWrite(previousStackDepth); // FIXME: Separate context? contentContext.Pass = RasterizePasses.ContentClip; // FIXME var temp = settings; ApplyClipMargins(ref contentContext, ref temp.Box); var crLayer = contentRenderer.Layer; contentRenderer.Layer = -999; settings.State = default(ControlStates); decorations?.Rasterize(ref contentContext, ref contentRenderer, temp); contentRenderer.Layer = crLayer; // passSet.NextReferenceStencil = childrenPassSet.NextReferenceStencil; }
public void Rasterize(ref UIOperationContext context, ref ImperativeRenderer renderer) { }
protected override void OnRasterize(ref UIOperationContext context, ref ImperativeRenderer renderer, DecorationSettings settings, IDecorator decorations) { }
protected override ControlKey OnGenerateLayoutTree(ref UIOperationContext context, ControlKey parent, ControlKey?existingKey) { return(ControlKey.Invalid); }
private void RasterizeDebugOverlays(ref UIOperationContext context, ref RasterizePassSet passSet, RectF rect) { if (!ShowDebugBoxes && !ShowDebugBreakMarkers && !ShowDebugMargins && !ShowDebugPadding && !ShowDebugBoxesForLeavesOnly) { return; } var mouseIsOver = rect.Contains(context.MousePosition); var alpha = mouseIsOver ? 1.0f : 0.5f; // HACK: Show outlines for controls that don't have any children or contain the mouse position var isLeaf = (((this as IControlContainer)?.Children?.Count ?? 0) == 0) || mouseIsOver; int?layer = null; if (ShowDebugBoxes || (ShowDebugBoxesForLeavesOnly && isLeaf)) { passSet.Above.RasterizeRectangle( rect.Position, rect.Extent, 0f, 1f, Color.Transparent, Color.Transparent, GetDebugBoxColor(context.Depth) * alpha, layer: layer ); } if (!context.Layout.TryGetFlags(LayoutKey, out ControlFlags flags)) { return; } if (ShowDebugMargins) { RasterizeDebugMargins(ref context, ref passSet, ref rect, context.Layout.GetMargins(LayoutKey), 1f, Color.Green, layer); } if (ShowDebugPadding) { RasterizeDebugMargins(ref context, ref passSet, ref rect, context.Layout.GetPadding(LayoutKey), -1f, Color.Yellow, layer); } if (ShowDebugBreakMarkers && mouseIsOver && flags.IsBreak()) { rect = new RectF( new Vector2(rect.Left - 1.5f, rect.Center.Y - 7.5f), new Vector2(6.5f, 15) ); var facingRight = false; Vector2 a = !facingRight ? rect.Extent : rect.Position, b = !facingRight ? new Vector2(rect.Position.X, rect.Center.Y) : new Vector2(rect.Extent.X, rect.Center.Y), c = !facingRight ? new Vector2(rect.Extent.X, rect.Position.Y) : new Vector2(rect.Position.X, rect.Extent.Y); var arrowColor = flags.IsFlagged(ControlFlags.Layout_ForceBreak) ? Color.White : Color.Yellow; passSet.Above.RasterizeTriangle( a, b, c, radius: 0f, outlineRadius: 1f, innerColor: arrowColor * alpha, outerColor: arrowColor * alpha, outlineColor: Color.Black * (alpha * 0.8f) ); } }
private void RasterizeAcceleratorOverlay( UIOperationContext context, ref ImperativeRenderer labelRenderer, ref ImperativeRenderer targetRenderer, Control control, AbstractString label, bool showFocused = false, Control forControl = null ) { if (control == null) { return; } if (!showFocused && (control == Focused) && !label.IsNull && (label.Length > 0)) { return; } if (label.Length <= 0) { return; } var box = control.GetRect(); if ((box.Width <= 1) || (box.Height <= 1)) { return; } var decorator = Decorations.AcceleratorTarget; var settings = new Decorations.DecorationSettings { Box = box, ContentBox = box }; decorator.Rasterize(ref context, ref targetRenderer, settings); var outlinePadding = 1f; decorator = Decorations.AcceleratorLabel; Color?textColor = null; decorator.GetTextSettings(ref context, default(ControlStates), out Material material, ref textColor, out _); var layout = decorator.GlyphSource.LayoutString(label, buffer: AcceleratorOverlayBuffer); var textScale = 1f; if (layout.Size.X > (box.Width - decorator.Padding.X)) { textScale = Math.Max(0.25f, (box.Width - decorator.Padding.X) / layout.Size.X); } var scaledSize = layout.Size * textScale; var labelTraits = new DenseList <string> { "above" }; var labelPosition = box.Position - new Vector2(0, scaledSize.Y + decorator.Padding.Y + outlinePadding); if (labelPosition.Y <= 0) { labelTraits[0] = "inside"; labelPosition = box.Position; } labelPosition.X = Arithmetic.Clamp(labelPosition.X, 0, CanvasSize.X - scaledSize.X); labelPosition.Y = Math.Max(0, labelPosition.Y); var labelBox = new RectF( labelPosition, scaledSize + decorator.Padding.Size ); if (IsObstructedByAnyPreviousBox(ref labelBox, forControl)) { labelBox.Left = box.Extent.X - labelBox.Width; } if (IsObstructedByAnyPreviousBox(ref labelBox, forControl)) { labelTraits[0] = "below"; labelBox.Left = labelPosition.X; labelBox.Top = box.Extent.Y + 1; // FIXME: Why the +1? } while (IsObstructedByAnyPreviousBox(ref labelBox, forControl)) { labelTraits[0] = "stacked"; labelBox.Left = box.Left; labelBox.Width = box.Width; labelBox.Top = labelBox.Extent.Y + 0.5f; } // HACK var labelContentBox = new RectF( labelBox.Position + new Vector2(decorator.Padding.Left, decorator.Padding.Top), scaledSize ); settings = new Decorations.DecorationSettings { Box = labelBox, ContentBox = box, Traits = labelTraits }; decorator.Rasterize(ref context, ref labelRenderer, settings); labelRenderer.DrawMultiple(layout.DrawCalls, offset: labelContentBox.Position.Floor(), scale: new Vector2(textScale), layer: 1); RasterizedOverlayBoxes.Add(new RasterizedOverlayBox { Control = forControl, ControlBox = box, LabelBox = labelBox }); }
protected virtual void OnRasterize(ref UIOperationContext context, ref ImperativeRenderer renderer, DecorationSettings settings, IDecorator decorations) { decorations?.Rasterize(ref context, ref renderer, settings); }
private void RasterizeAcceleratorOverlay(ref UIOperationContext context, ref ImperativeRenderer renderer) { var activeModal = ActiveModal; Control shiftTab = ResolveProxies(PickRotateFocusTarget(false, -1)), tab = ResolveProxies(PickRotateFocusTarget(false, 1)), ctrlShiftTab = (activeModal?.RetainFocus == true) ? null : ResolveProxies(PickRotateFocusTarget(true, -1)), ctrlTab = (activeModal?.RetainFocus == true) ? null : ResolveProxies(PickRotateFocusTarget(true, 1)); var targetGroup = renderer.MakeSubgroup(); var labelGroup = renderer.MakeSubgroup(); RasterizedOverlayBoxes.Clear(); if (Focused != null) { RasterizedOverlayBoxes.Add(new RasterizedOverlayBox { Control = Focused, ControlBox = Focused.GetRect(contentRect: true) }); } // FIXME: This looks confusing // RasterizeAcceleratorOverlay(context, ref labelGroup, ref targetGroup, Focused, null); var topLevelSource = TopLevelFocused as IAcceleratorSource; if (topLevelSource != null) { labelGroup = renderer.MakeSubgroup(); foreach (var accel in topLevelSource.Accelerators) { RasterizeAcceleratorOverlay(context, ref labelGroup, ref targetGroup, accel, true); } } RasterizeAcceleratorOverlay(context, ref labelGroup, ref targetGroup, tab, FocusForward); if (shiftTab != tab) { RasterizeAcceleratorOverlay(context, ref labelGroup, ref targetGroup, shiftTab, FocusBackward); } if ((ctrlTab != TopLevelFocused) || (ctrlShiftTab != TopLevelFocused)) { if (ctrlTab != tab) { RasterizeAcceleratorOverlay(context, ref labelGroup, ref targetGroup, ctrlTab, WindowFocusForward); } if (ctrlTab != ctrlShiftTab) { RasterizeAcceleratorOverlay(context, ref labelGroup, ref targetGroup, ctrlShiftTab, WindowFocusBackward); } } var focusedSource = Focused as IAcceleratorSource; if ((focusedSource != null) && (focusedSource != topLevelSource)) { labelGroup = renderer.MakeSubgroup(); foreach (var accel in focusedSource.Accelerators) { RasterizeAcceleratorOverlay(context, ref labelGroup, ref targetGroup, accel, true); } } }
public bool Rasterize(ref UIOperationContext context, ref RasterizePassSet passSet, float opacity = 1) { // HACK: Do this first since it fires opacity change events var hidden = false; var tweenOpacity = GetOpacity(context.NowL); opacity *= tweenOpacity; if (opacity <= 0) { hidden = true; } if (!Visible) { hidden = true; } var box = default(RectF); bool isZeroSized = false, isOutOfView = false, transformActive = context.TransformActive || Appearance.HasTransformMatrix; if (IsLayoutInvalid) { hidden = true; } else { box = GetRect(); Vector2 ext = box.Extent, vext = context.VisibleRegion.Extent; // HACK: There might be corner cases where you want to rasterize a zero-sized control... isZeroSized = (box.Width <= 0) || (box.Height <= 0); isOutOfView = (ext.X < context.VisibleRegion.Left) || (ext.Y < context.VisibleRegion.Top) || (box.Left > vext.X) || (box.Top > vext.Y); RasterizeDebugOverlays(ref context, ref passSet, box); } #if DETECT_DOUBLE_RASTERIZE if (!RasterizeIsPending) { throw new Exception("Double rasterize detected"); } RasterizeIsPending = false; #endif if (isZeroSized) { hidden = true; } // Only visibility cull controls that have a parent and aren't overlaid. if (isOutOfView && (WeakParent != null) && !Appearance.Overlay && !transformActive) { hidden = true; } if (hidden) { // HACK: Ensure pre-rasterize handlers run for hidden controls, because the handler // may be doing something important like updating animations or repainting a buffer RunPreRasterizeHandlerForHiddenControl(ref context, ref box); return(false); } Appearance.AutoClearTransform(context.NowL); var enableCompositor = Appearance.Compositor?.WillComposite(this, opacity) == true; var hasTransformMatrix = Appearance.HasTransformMatrix && // HACK: If the current transform matrix is the identity matrix, suppress composition // this allows simple transform animations that end at the identity matrix to work // without explicitly clearing the transform after the animation is over. Appearance.GetTransform(out Matrix transform, context.NowL) && (transform != Matrix.Identity); var needsComposition = NeedsComposition(opacity < 1, hasTransformMatrix) || enableCompositor; var oldOpacity = context.Opacity; var oldTransformActive = context.TransformActive; context.TransformActive = context.TransformActive || hasTransformMatrix; try { if (!needsComposition) { context.Opacity *= opacity; if (hasTransformMatrix) { RasterizeAllPassesTransformed(ref context, ref box, ref passSet); } else { RasterizeAllPasses(ref context, ref box, ref passSet, false); } } else { RasterizeComposited(ref context, ref box, ref passSet, opacity, enableCompositor); } } finally { context.Opacity = oldOpacity; context.TransformActive = oldTransformActive; } return(true); }
protected virtual void OnPreRasterize(ref UIOperationContext context, DecorationSettings settings, IDecorator decorations) { UpdateAnimation(context.NowL); }
private void RasterizeDebugMargins(ref UIOperationContext context, ref RasterizePassSet passSet, ref RectF rect, Margins margins, float direction, Color color, int?layer) { float lineWidth = 1.33f, extentLength = 16f, extentThickness = 0.75f; var exteriorRect = rect; exteriorRect.Left -= margins.Left * direction; exteriorRect.Top -= margins.Top * direction; exteriorRect.Width += margins.X * direction; exteriorRect.Height += margins.Y * direction; var center = rect.Center; if (margins.Left > 0) { passSet.Above.RasterizeRectangle( new Vector2(exteriorRect.Left, center.Y - lineWidth), new Vector2(rect.Left, center.Y + lineWidth), 0, color, layer: layer ); passSet.Above.RasterizeRectangle( new Vector2(exteriorRect.Left, center.Y - extentLength), new Vector2(exteriorRect.Left + extentThickness, center.Y + extentLength), 0, color, layer: layer ); } if (margins.Top > 0) { passSet.Above.RasterizeRectangle( new Vector2(center.X - lineWidth, exteriorRect.Top), new Vector2(center.X + lineWidth, rect.Top), 0, color, layer: layer ); passSet.Above.RasterizeRectangle( new Vector2(center.X - extentLength, exteriorRect.Top), new Vector2(center.X + extentLength, exteriorRect.Top + extentThickness), 0, color, layer: layer ); } if (margins.Right > 0) { passSet.Above.RasterizeRectangle( new Vector2(exteriorRect.Extent.X, center.Y - lineWidth), new Vector2(rect.Extent.X, center.Y + lineWidth), 0, color, layer: layer ); passSet.Above.RasterizeRectangle( new Vector2(exteriorRect.Extent.X, center.Y - extentLength), new Vector2(exteriorRect.Extent.X - extentThickness, center.Y + extentLength), 0, color, layer: layer ); } if (margins.Bottom > 0) { passSet.Above.RasterizeRectangle( new Vector2(center.X - lineWidth, exteriorRect.Extent.Y), new Vector2(center.X + lineWidth, rect.Extent.Y), 0, color, layer: layer ); passSet.Above.RasterizeRectangle( new Vector2(center.X - extentLength, exteriorRect.Extent.Y), new Vector2(center.X + extentLength, exteriorRect.Extent.Y + extentThickness), 0, color, layer: layer ); } }
private void RasterizePass( ref UIOperationContext context, ref DecorationSettings settings, IDecorator decorations, bool compositing, ref RasterizePassSet passSet, ref ImperativeRenderer renderer, RasterizePasses pass ) { UIOperationContext passContext; context.Clone(out passContext); passContext.Pass = pass; var hasNestedContext = (pass == RasterizePasses.Content) && (ShouldClipContent || (HasChildren && CreateNestedContextForChildren)); if (hasNestedContext) { UpdateVisibleRegion(ref passContext, ref settings.Box); } // FIXME: The memset for these actually burns a measurable amount of time ImperativeRenderer contentRenderer; RasterizePassSet childrenPassSet; UIOperationContext contentContext; int previousStackDepth = passSet.StackDepth, newStackDepth = previousStackDepth; // For clipping we need to create a separate batch group that contains all the rasterization work // for our children. At the start of it we'll generate the stencil mask that will be used for our // rendering operation(s). if (hasNestedContext) { NestedContextPassSetup( ref context, ref passSet, ref renderer, ref passContext, out contentRenderer, out childrenPassSet, out contentContext, previousStackDepth, ref newStackDepth ); } else { contentContext = passContext; childrenPassSet = default; contentRenderer = default; } // TODO: all the copying of settings here burns CPU time if (HasPreRasterizeHandler && (pass == RasterizePasses.Content)) { OnPreRasterize(ref contentContext, settings, decorations); } if (hasNestedContext) { OnRasterize(ref contentContext, ref contentRenderer, settings, decorations); } else { OnRasterize(ref contentContext, ref renderer, settings, decorations); } if ((pass == RasterizePasses.Content) && HasChildren) { if (hasNestedContext) { OnRasterizeChildren(ref contentContext, ref childrenPassSet, settings); } else { // FIXME: Save/restore layers? OnRasterizeChildren(ref contentContext, ref passSet, settings); } } if (hasNestedContext) { // GROSS OPTIMIZATION HACK: Detect that any rendering operation(s) occurred inside the // group and if so, set up the stencil mask so that they will be clipped. if (ShouldClipContent && !contentRenderer.Container.IsEmpty) { NestedContextPassTeardown( ref context, ref settings, decorations, ref passSet, ref contentRenderer, ref contentContext, previousStackDepth ); } renderer.Layer += 1; } }
protected virtual void OnRasterizeChildren(ref UIOperationContext context, ref RasterizePassSet passSet, DecorationSettings settings) { }