internal static uint DepthFirstOnChildRemoving(RenderChain renderChain, VisualElement ve) { // Recurse on children int childrenCount = ve.hierarchy.childCount - 1; uint deepCount = 0; while (childrenCount >= 0) { deepCount += DepthFirstOnChildRemoving(renderChain, ve.hierarchy[childrenCount--]); } if (ve.renderChainData.isInChain) { renderChain.ChildWillBeRemoved(ve); CommandGenerator.ResetCommands(renderChain, ve); renderChain.ResetTextures(ve); ve.renderChainData.isInChain = false; ve.renderChainData.clipMethod = ClipMethod.Undetermined; if (ve.renderChainData.next != null) { ve.renderChainData.next.renderChainData.prev = ve.renderChainData.prev; } if (ve.renderChainData.prev != null) { ve.renderChainData.prev.renderChainData.next = ve.renderChainData.next; } if (RenderChainVEData.AllocatesID(ve.renderChainData.textCoreSettingsID)) { renderChain.shaderInfoAllocator.FreeTextCoreSettings(ve.renderChainData.textCoreSettingsID); ve.renderChainData.textCoreSettingsID = UIRVEShaderInfoAllocator.defaultTextCoreSettings; } if (RenderChainVEData.AllocatesID(ve.renderChainData.opacityID)) { renderChain.shaderInfoAllocator.FreeOpacity(ve.renderChainData.opacityID); ve.renderChainData.opacityID = UIRVEShaderInfoAllocator.fullOpacity; } if (RenderChainVEData.AllocatesID(ve.renderChainData.colorID)) { renderChain.shaderInfoAllocator.FreeColor(ve.renderChainData.colorID); ve.renderChainData.colorID = BMPAlloc.Invalid; } if (RenderChainVEData.AllocatesID(ve.renderChainData.backgroundColorID)) { renderChain.shaderInfoAllocator.FreeColor(ve.renderChainData.backgroundColorID); ve.renderChainData.backgroundColorID = BMPAlloc.Invalid; } if (RenderChainVEData.AllocatesID(ve.renderChainData.borderLeftColorID)) { renderChain.shaderInfoAllocator.FreeColor(ve.renderChainData.borderLeftColorID); ve.renderChainData.borderLeftColorID = BMPAlloc.Invalid; } if (RenderChainVEData.AllocatesID(ve.renderChainData.borderTopColorID)) { renderChain.shaderInfoAllocator.FreeColor(ve.renderChainData.borderTopColorID); ve.renderChainData.borderTopColorID = BMPAlloc.Invalid; } if (RenderChainVEData.AllocatesID(ve.renderChainData.borderRightColorID)) { renderChain.shaderInfoAllocator.FreeColor(ve.renderChainData.borderRightColorID); ve.renderChainData.borderRightColorID = BMPAlloc.Invalid; } if (RenderChainVEData.AllocatesID(ve.renderChainData.borderBottomColorID)) { renderChain.shaderInfoAllocator.FreeColor(ve.renderChainData.borderBottomColorID); ve.renderChainData.borderBottomColorID = BMPAlloc.Invalid; } if (RenderChainVEData.AllocatesID(ve.renderChainData.tintColorID)) { renderChain.shaderInfoAllocator.FreeColor(ve.renderChainData.tintColorID); ve.renderChainData.tintColorID = BMPAlloc.Invalid; } if (RenderChainVEData.AllocatesID(ve.renderChainData.clipRectID)) { renderChain.shaderInfoAllocator.FreeClipRect(ve.renderChainData.clipRectID); ve.renderChainData.clipRectID = UIRVEShaderInfoAllocator.infiniteClipRect; } if (RenderChainVEData.AllocatesID(ve.renderChainData.transformID)) { renderChain.shaderInfoAllocator.FreeTransform(ve.renderChainData.transformID); ve.renderChainData.transformID = UIRVEShaderInfoAllocator.identityTransform; } ve.renderChainData.boneTransformAncestor = ve.renderChainData.groupTransformAncestor = null; if (ve.renderChainData.closingData != null) { renderChain.device.Free(ve.renderChainData.closingData); ve.renderChainData.closingData = null; } if (ve.renderChainData.data != null) { renderChain.device.Free(ve.renderChainData.data); ve.renderChainData.data = null; } } return(deepCount + 1); }
static void DepthFirstOnTransformOrSizeChanged(RenderChain renderChain, VisualElement parent, VisualElement ve, uint dirtyID, UIRenderDevice device, bool isAncestorOfChangeSkinned, bool transformChanged, ref ChainBuilderStats stats) { if (dirtyID == ve.renderChainData.dirtyID) { return; } stats.recursiveTransformUpdatesExpanded++; transformChanged |= (ve.renderChainData.dirtiedValues & RenderDataDirtyTypes.Transform) != 0; if (RenderChainVEData.AllocatesID(ve.renderChainData.clipRectID)) { renderChain.shaderInfoAllocator.SetClipRectValue(ve.renderChainData.clipRectID, GetClipRectIDClipInfo(ve)); } if (transformChanged && UpdateLocalFlipsWinding(ve)) { renderChain.UIEOnVisualsChanged(ve, true); } bool dirtyHasBeenResolved = true; if (RenderChainVEData.AllocatesID(ve.renderChainData.transformID)) { renderChain.shaderInfoAllocator.SetTransformValue(ve.renderChainData.transformID, GetTransformIDTransformInfo(ve)); isAncestorOfChangeSkinned = true; stats.boneTransformed++; } else if (!transformChanged) { // Only the clip info had to be updated, we can skip the other cases which are for transform changes only. } else if ((ve.renderHints & RenderHints.GroupTransform) != 0) { stats.groupTransformElementsChanged++; } else if (isAncestorOfChangeSkinned) { // Children of a bone element inherit the transform data change automatically when the root updates that data, no need to do anything for children Debug.Assert(RenderChainVEData.InheritsID(ve.renderChainData.transformID)); // The element MUST have a transformID that has been inherited from an ancestor dirtyHasBeenResolved = false; // We just skipped processing, if another later transform change is queued on this element this pass then we should still process it stats.skipTransformed++; } else if ((ve.renderChainData.dirtiedValues & (RenderDataDirtyTypes.Visuals | RenderDataDirtyTypes.VisualsHierarchy)) == 0 && (ve.renderChainData.data != null)) { // If a visual update will happen, then skip work here as the visual update will incorporate the transformed vertices if (!ve.renderChainData.disableNudging && CommandGenerator.NudgeVerticesToNewSpace(ve, renderChain, device)) { stats.nudgeTransformed++; } else { renderChain.UIEOnVisualsChanged(ve, false); // Nudging not allowed, so do a full visual repaint stats.visualUpdateTransformed++; } } if (dirtyHasBeenResolved) { ve.renderChainData.dirtyID = dirtyID; // Prevent reprocessing of the same element in the same pass } // Make sure to pre-evaluate world transform and clip now so we don't do it at render time if (renderChain.drawInCameras) { ve.EnsureWorldTransformAndClipUpToDate(); } if ((ve.renderHints & RenderHints.GroupTransform) == 0) { // Recurse on children int childrenCount = ve.hierarchy.childCount; for (int i = 0; i < childrenCount; i++) { DepthFirstOnTransformOrSizeChanged(renderChain, ve, ve.hierarchy[i], dirtyID, device, isAncestorOfChangeSkinned, transformChanged, ref stats); } } }
static void DepthFirstOnVisualsChanged(RenderChain renderChain, VisualElement ve, uint dirtyID, bool parentHierarchyHidden, bool hierarchical, ref ChainBuilderStats stats) { if (dirtyID == ve.renderChainData.dirtyID) { return; } ve.renderChainData.dirtyID = dirtyID; // Prevent reprocessing of the same element in the same pass if (hierarchical) { stats.recursiveVisualUpdatesExpanded++; } bool wasHierarchyHidden = ve.renderChainData.isHierarchyHidden; ve.renderChainData.isHierarchyHidden = parentHierarchyHidden || IsElementHierarchyHidden(ve); if (wasHierarchyHidden != ve.renderChainData.isHierarchyHidden) { hierarchical = true; } if (!hierarchical && (ve.renderChainData.dirtiedValues & RenderDataDirtyTypes.AllVisuals) == RenderDataDirtyTypes.VisualsOpacityId) { stats.opacityIdUpdates++; CommandGenerator.UpdateOpacityId(ve, renderChain); return; } UpdateWorldFlipsWinding(ve); Debug.Assert(ve.renderChainData.clipMethod != ClipMethod.Undetermined); Debug.Assert(RenderChainVEData.AllocatesID(ve.renderChainData.transformID) || ve.hierarchy.parent == null || ve.renderChainData.transformID.Equals(ve.hierarchy.parent.renderChainData.transformID) || (ve.renderHints & RenderHints.GroupTransform) != 0); if (ve is TextElement) { RenderEvents.UpdateTextCoreSettings(renderChain, ve); } if ((ve.renderHints & RenderHints.DynamicColor) == RenderHints.DynamicColor) { SetColorValues(renderChain, ve); } UIRStylePainter.ClosingInfo closingInfo = CommandGenerator.PaintElement(renderChain, ve, ref stats); if (hierarchical) { // Recurse on children int childrenCount = ve.hierarchy.childCount; for (int i = 0; i < childrenCount; i++) { DepthFirstOnVisualsChanged(renderChain, ve.hierarchy[i], dirtyID, ve.renderChainData.isHierarchyHidden, true, ref stats); } } // By closing the element after its children, we can ensure closing data is allocated // at a time that would maintain continuity in the index buffer if (closingInfo.needsClosing) { CommandGenerator.ClosePaintElement(ve, closingInfo, renderChain, ref stats); } }