Example #1
0
        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;
            }
        }
Example #2
0
        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
            }
        }