public void Begin(VisualElement ve) { this.currentElement = ve; this.m_NextMeshWriteDataPoolItem = 0; this.m_SVGBackgroundEntryIndex = -1; this.currentElement.renderChainData.usesLegacyText = (this.currentElement.renderChainData.usesAtlas = (this.currentElement.renderChainData.disableNudging = false)); this.currentElement.renderChainData.displacementUVStart = (this.currentElement.renderChainData.displacementUVEnd = 0); bool flag = (this.currentElement.renderHints & RenderHints.GroupTransform) > RenderHints.None; bool flag2 = flag; if (flag2) { RenderChainCommand renderChainCommand = this.m_Owner.AllocCommand(); renderChainCommand.owner = this.currentElement; renderChainCommand.type = CommandType.PushView; this.m_Entries.Add(new UIRStylePainter.Entry { customCommand = renderChainCommand }); this.m_ClosingInfo.needsClosing = (this.m_ClosingInfo.popViewMatrix = true); } bool flag3 = this.currentElement.hierarchy.parent != null; if (flag3) { this.m_StencilClip = this.currentElement.hierarchy.parent.renderChainData.isStencilClipped; this.m_ClipRectID = (flag ? UIRVEShaderInfoAllocator.infiniteClipRect : this.currentElement.hierarchy.parent.renderChainData.clipRectID); } else { this.m_StencilClip = false; this.m_ClipRectID = UIRVEShaderInfoAllocator.infiniteClipRect; } }
public void ApplyVisualElementClipping() { bool flag = this.currentElement.renderChainData.clipMethod == ClipMethod.Scissor; if (flag) { RenderChainCommand renderChainCommand = this.m_Owner.AllocCommand(); renderChainCommand.type = CommandType.PushScissor; renderChainCommand.owner = this.currentElement; this.m_Entries.Add(new UIRStylePainter.Entry { customCommand = renderChainCommand }); this.m_ClosingInfo.needsClosing = (this.m_ClosingInfo.popScissorClip = true); } else { bool flag2 = this.currentElement.renderChainData.clipMethod == ClipMethod.Stencil; if (flag2) { bool flag3 = UIRUtility.IsVectorImageBackground(this.currentElement); if (flag3) { this.GenerateStencilClipEntryForSVGBackground(); } else { this.GenerateStencilClipEntryForRoundedRectBackground(); } } } this.m_ClipRectID = this.currentElement.renderChainData.clipRectID; }
public void Begin(VisualElement ve) { currentElement = ve; m_NextMeshWriteDataPoolItem = 0; m_SVGBackgroundEntryIndex = -1; currentElement.renderChainData.usesLegacyText = currentElement.renderChainData.disableNudging = false; currentElement.renderChainData.displacementUVStart = currentElement.renderChainData.displacementUVEnd = 0; bool isGroupTransform = (currentElement.renderHints & RenderHints.GroupTransform) != 0; if (isGroupTransform) { var cmd = m_Owner.AllocCommand(); cmd.owner = currentElement; cmd.type = CommandType.PushView; m_Entries.Add(new Entry() { customCommand = cmd }); m_ClosingInfo.needsClosing = m_ClosingInfo.popViewMatrix = true; } if (currentElement.hierarchy.parent != null) { m_StencilClip = currentElement.hierarchy.parent.renderChainData.isStencilClipped; m_ClipRectID = isGroupTransform ? UIRVEShaderInfoAllocator.infiniteClipRect : currentElement.hierarchy.parent.renderChainData.clipRectID; } else { m_StencilClip = false; m_ClipRectID = UIRVEShaderInfoAllocator.infiniteClipRect; } if (ve.subRenderTargetMode != VisualElement.RenderTargetMode.None) { var cmd = m_Owner.AllocCommand(); cmd.owner = currentElement; cmd.type = CommandType.PushRenderTexture; m_Entries.Add(new Entry() { customCommand = cmd }); m_ClosingInfo.needsClosing = m_ClosingInfo.blitAndPopRenderTexture = true; m_ClosingInfo.RestoreStencilClip = m_StencilClip; m_StencilClip = false; } if (ve.defaultMaterial != null) { var cmd = m_Owner.AllocCommand(); cmd.owner = currentElement; cmd.type = CommandType.PushDefaultMaterial; cmd.state.material = ve.defaultMaterial; m_Entries.Add(new Entry() { customCommand = cmd }); m_ClosingInfo.needsClosing = m_ClosingInfo.PopDefaultMaterial = true; } }
static void DepthFirstOnClippingChanged(RenderChain renderChain, VisualElement parent, VisualElement ve, uint dirtyID, bool hierarchical, bool isRootOfChange, // MUST be true on the root call. bool isPendingHierarchicalRepaint, // MUST be false on the root call. bool inheritedClipRectIDChanged, // MUST be false on the root call. bool inheritedMaskingChanged, // MUST be false on the root call. UIRenderDevice device, ref ChainBuilderStats stats) { bool upToDate = dirtyID == ve.renderChainData.dirtyID; if (upToDate && !inheritedClipRectIDChanged && !inheritedMaskingChanged) { return; } ve.renderChainData.dirtyID = dirtyID; // Prevent reprocessing of the same element in the same pass if (!isRootOfChange) { stats.recursiveClipUpdatesExpanded++; } isPendingHierarchicalRepaint |= (ve.renderChainData.dirtiedValues & RenderDataDirtyTypes.VisualsHierarchy) != 0; // Internal operations (done in this call) to do: bool mustUpdateClipRectID = hierarchical || isRootOfChange || inheritedClipRectIDChanged; bool mustUpdateClippingMethod = hierarchical || isRootOfChange; bool mustUpdateChildrenMasking = hierarchical || isRootOfChange || inheritedMaskingChanged; // External operations (done by recursion or postponed) to do: bool mustRepaintThis = false; bool mustRepaintHierarchy = false; bool mustProcessSizeChange = false; // mustRecurse implies recursing on all children, but doesn't force anything beyond them. // hierarchical implies recursing on all descendants // As a result, hierarchical implies mustRecurse bool mustRecurse = hierarchical; ClipMethod oldClippingMethod = ve.renderChainData.clipMethod; ClipMethod newClippingMethod = mustUpdateClippingMethod ? DetermineSelfClipMethod(renderChain, ve) : oldClippingMethod; // Shader discard support bool clipRectIDChanged = false; if (mustUpdateClipRectID) { BMPAlloc newClipRectID = ve.renderChainData.clipRectID; if (newClippingMethod == ClipMethod.ShaderDiscard) { if (!RenderChainVEData.AllocatesID(ve.renderChainData.clipRectID)) { newClipRectID = renderChain.shaderInfoAllocator.AllocClipRect(); if (!newClipRectID.IsValid()) { newClippingMethod = ClipMethod.Scissor; // Fallback to scissor since we couldn't allocate a clipRectID // Both shader discard and scisorring work with world-clip rectangles, so no need // to inherit any clipRectIDs for such elements, our own scissor rect clips up correctly newClipRectID = UIRVEShaderInfoAllocator.infiniteClipRect; } } } else { if (RenderChainVEData.AllocatesID(ve.renderChainData.clipRectID)) { renderChain.shaderInfoAllocator.FreeClipRect(ve.renderChainData.clipRectID); } // Inherit parent's clipRectID if possible. // Group transforms shouldn't inherit the clipRectID since they have a new frame of reference, // they provide a new baseline with the _PixelClipRect instead. if ((ve.renderHints & RenderHints.GroupTransform) == 0) { newClipRectID = ((newClippingMethod != ClipMethod.Scissor) && (parent != null)) ? parent.renderChainData.clipRectID : UIRVEShaderInfoAllocator.infiniteClipRect; newClipRectID.ownedState = OwnedState.Inherited; } } clipRectIDChanged = !ve.renderChainData.clipRectID.Equals(newClipRectID); Debug.Assert((ve.renderHints & RenderHints.GroupTransform) == 0 || !clipRectIDChanged); ve.renderChainData.clipRectID = newClipRectID; } bool maskingChanged = false; if (oldClippingMethod != newClippingMethod) { ve.renderChainData.clipMethod = newClippingMethod; if (oldClippingMethod == ClipMethod.Stencil || newClippingMethod == ClipMethod.Stencil) { maskingChanged = true; mustUpdateChildrenMasking = true; } if (oldClippingMethod == ClipMethod.Scissor || newClippingMethod == ClipMethod.Scissor) { // We need to add/remove scissor push/pop commands mustRepaintThis = true; } if (newClippingMethod == ClipMethod.ShaderDiscard || oldClippingMethod == ClipMethod.ShaderDiscard && RenderChainVEData.AllocatesID(ve.renderChainData.clipRectID)) { // We must update the clipping rects. mustProcessSizeChange = true; } } if (clipRectIDChanged) { // Our children MUST update their render data clipRectIDs mustRecurse = true; // Our children MUST update their vertex clipRectIDs mustRepaintHierarchy = true; } if (mustUpdateChildrenMasking) { int newChildrenMaskDepth = 0; int newChildrenStencilRef = 0; if (parent != null) { newChildrenMaskDepth = parent.renderChainData.childrenMaskDepth; newChildrenStencilRef = parent.renderChainData.childrenStencilRef; if (newClippingMethod == ClipMethod.Stencil) { if (newChildrenMaskDepth > newChildrenStencilRef) { ++newChildrenStencilRef; } ++newChildrenMaskDepth; } // When applying the MaskContainer hint, we skip because the last depth level because even though we // could technically increase the reference value, it would be useless since there won't be more // deeply nested masks that could benefit from it. if ((ve.renderHints & RenderHints.MaskContainer) == RenderHints.MaskContainer && newChildrenMaskDepth < UIRUtility.k_MaxMaskDepth) { newChildrenStencilRef = newChildrenMaskDepth; } } if (ve.renderChainData.childrenMaskDepth != newChildrenMaskDepth || ve.renderChainData.childrenStencilRef != newChildrenStencilRef) { maskingChanged = true; } ve.renderChainData.childrenMaskDepth = newChildrenMaskDepth; ve.renderChainData.childrenStencilRef = newChildrenStencilRef; } if (maskingChanged) { mustRecurse = true; // Our children must update their inherited state. // These optimizations would allow to skip repainting the hierarchy: // a) We could update the stencilRef in the commands without repainting // b) The winding order could be reversed without repainting (when required) // In the meantime, we have no other choice but to request a hierarchical repaint. mustRepaintHierarchy = true; } if ((mustRepaintThis || mustRepaintHierarchy) && !isPendingHierarchicalRepaint) { renderChain.UIEOnVisualsChanged(ve, mustRepaintHierarchy); isPendingHierarchicalRepaint = true; } if (mustProcessSizeChange) { renderChain.UIEOnTransformOrSizeChanged(ve, false, true); } if (mustRecurse) { int childrenCount = ve.hierarchy.childCount; for (int i = 0; i < childrenCount; i++) { DepthFirstOnClippingChanged( renderChain, ve, ve.hierarchy[i], dirtyID, // Having to recurse doesn't mean that we need to process ALL descendants. For example, the // propagation of the transformId may stop if a group or a bone is encountered. hierarchical, false, isPendingHierarchicalRepaint, clipRectIDChanged, maskingChanged, device, ref stats); } } }
public void Begin(VisualElement ve) { currentElement = ve; m_NextMeshWriteDataPoolItem = 0; m_SVGBackgroundEntryIndex = -1; currentElement.renderChainData.displacementUVStart = currentElement.renderChainData.displacementUVEnd = 0; m_MaskDepth = 0; m_StencilRef = 0; VisualElement parent = currentElement.hierarchy.parent; if (parent != null) { m_MaskDepth = parent.renderChainData.childrenMaskDepth; m_StencilRef = parent.renderChainData.childrenStencilRef; } bool isGroupTransform = (currentElement.renderHints & RenderHints.GroupTransform) != 0; if (isGroupTransform) { var cmd = m_Owner.AllocCommand(); cmd.owner = currentElement; cmd.type = CommandType.PushView; m_Entries.Add(new Entry() { customCommand = cmd }); m_ClosingInfo.needsClosing = m_ClosingInfo.popViewMatrix = true; } if (parent != null) { m_ClipRectID = isGroupTransform ? UIRVEShaderInfoAllocator.infiniteClipRect : parent.renderChainData.clipRectID; } else { m_ClipRectID = UIRVEShaderInfoAllocator.infiniteClipRect; } if (ve.subRenderTargetMode != VisualElement.RenderTargetMode.None) { var cmd = m_Owner.AllocCommand(); cmd.owner = currentElement; cmd.type = CommandType.PushRenderTexture; m_Entries.Add(new Entry() { customCommand = cmd }); m_ClosingInfo.needsClosing = m_ClosingInfo.blitAndPopRenderTexture = true; if (m_MaskDepth > 0 || m_StencilRef > 0) { Debug.LogError("The RenderTargetMode feature must not be used within a stencil mask."); } } if (ve.defaultMaterial != null) { var cmd = m_Owner.AllocCommand(); cmd.owner = currentElement; cmd.type = CommandType.PushDefaultMaterial; cmd.state.material = ve.defaultMaterial; m_Entries.Add(new Entry() { customCommand = cmd }); m_ClosingInfo.needsClosing = m_ClosingInfo.PopDefaultMaterial = true; } if (meshGenerationContext.hasPainter2D) { meshGenerationContext.painter2D.Reset(); // Reset vector API before client usage } }