ShaderEffect.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / Media / Effects / ShaderEffect.cs / 3 / ShaderEffect.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Windows Presentation Foundation
//  Copyright (c) Microsoft Corporation, 2008
//
//  File:       ShaderEffect.cs 
//-----------------------------------------------------------------------------
 
using System; 
using System.Collections.Generic;
using System.Diagnostics; 
using System.Windows;
using System.Windows.Media;
using System.IO;
using System.Windows.Markup; 
using System.Windows.Media.Composition;
using System.Windows.Media.Media3D; 
using System.Security; 
using System.Security.Permissions;
using System.Runtime.InteropServices; 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;

namespace System.Windows.Media.Effects 
{
    public abstract partial class ShaderEffect : Effect 
    { 
        /// 
        /// Padding is used to specify that an effect's output texture is larger than its input 
        //  texture in a specific direction, e.g. for a drop shadow effect.
        /// 
        protected double PaddingTop
        { 
            get
            { 
                ReadPreamble(); 
                return _topPadding;
            } 
            set
            {
                WritePreamble();
                if (value < 0.0) 
                {
                    throw new ArgumentOutOfRangeException("PaddingTop", value, SR.Get(SRID.Effect_ShaderEffectPadding)); 
                } 
                else
                { 
                    _topPadding = value;
                    RegisterForAsyncUpdateResource();
                }
                WritePostscript(); 
            }
        } 
 
        /// 
        /// Padding is used to specify that an effect's output texture is larger than its input 
        //  texture in a specific direction, e.g. for a drop shadow effect.
        /// 
        protected double PaddingBottom
        { 
            get
            { 
                ReadPreamble(); 
                return _bottomPadding;
            } 
            set
            {
                WritePreamble();
                if (value < 0.0) 
                {
                    throw new ArgumentOutOfRangeException("PaddingBottom", value, SR.Get(SRID.Effect_ShaderEffectPadding)); 
                } 
                else
                { 
                    _bottomPadding = value;
                    RegisterForAsyncUpdateResource();
                }
                WritePostscript(); 
            }
        } 
 
        /// 
        /// Padding is used to specify that an effect's output texture is larger than its input 
        //  texture in a specific direction, e.g. for a drop shadow effect.
        /// 
        protected double PaddingLeft
        { 
            get
            { 
                ReadPreamble(); 
                return _leftPadding;
            } 
            set
            {
                WritePreamble();
                if (value < 0.0) 
                {
                    throw new ArgumentOutOfRangeException("PaddingLeft", value, SR.Get(SRID.Effect_ShaderEffectPadding)); 
                } 
                else
                { 
                    _leftPadding = value;
                    RegisterForAsyncUpdateResource();
                }
                WritePostscript(); 
            }
        } 
 
        /// 
        /// Padding is used to specify that an effect's output texture is larger than its input 
        //  texture in a specific direction, e.g. for a drop shadow effect.
        /// 
        protected double PaddingRight
        { 
            get
            { 
                ReadPreamble(); 
                return _rightPadding;
            } 
            set
            {
                WritePreamble();
                if (value < 0.0) 
                {
                    throw new ArgumentOutOfRangeException("PaddingRight", value, SR.Get(SRID.Effect_ShaderEffectPadding)); 
                } 
                else
                { 
                    _rightPadding = value;
                    RegisterForAsyncUpdateResource();
                }
                WritePostscript(); 
            }
        } 
 
        /// 
        /// To specify a shader constant register to set to the size of the 
        /// destination.  Default is -1, which means to not send any.  Only
        /// intended to be set once, in the constructor, and will fail if set
        /// after the effect is initially processed.
        ///  
        protected int DdxUvDdyUvRegisterIndex
 
        { 
            get
            { 
                ReadPreamble();
                return _ddxUvDdyUvRegisterIndex;
            }
 
            set
            { 
                WritePreamble(); 
                if (_sentFirstTime)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Effect_ShaderDdxUvDdyUvRegisterIndex));
                }
                _ddxUvDdyUvRegisterIndex = value;
                WritePostscript(); 
            }
        } 
 
        /// 
        /// Tells the Effect that the shader constant or sampler corresponding 
        /// to the specified DependencyProperty needs to be updated.
        /// 
        protected void UpdateShaderValue(DependencyProperty dp)
        { 
            if (dp != null)
            { 
                WritePreamble(); 
                object val = this.GetValue(dp);
                var metadata = dp.GetMetadata(this); 
                if (metadata != null)
                {
                    var callback = metadata.PropertyChangedCallback;
                    if (callback != null) 
                    {
                        callback(this, new DependencyPropertyChangedEventArgs(dp, val, val)); 
                    } 
                }
                WritePostscript(); 
            }
        }

        ///  
        /// Construct a PropertyChangedCallback which, when invoked, will result in the DP being
        /// associated with the specified shader constant register index. 
        ///  
        protected static PropertyChangedCallback PixelShaderConstantCallback(int floatRegisterIndex)
        { 
            return
                (obj, args) =>
                {
                    ShaderEffect eff = obj as ShaderEffect; 
                    if (eff != null)
                    { 
                        eff.UpdateShaderConstant(args.Property, args.NewValue, floatRegisterIndex); 
                    }
                }; 
        }

        /// 
        /// Construct a PropertyChangedCallback which, when invoked, will result 
        /// in the DP being associated with the specified shader sampler
        /// register index. Expected to be called on a Brush-valued 
        /// DependencyProperty. 
        /// 
        protected static PropertyChangedCallback PixelShaderSamplerCallback(int samplerRegisterIndex) 
        {
            return PixelShaderSamplerCallback(samplerRegisterIndex, _defaultSamplingMode);
        }
 
        /// 
        /// Construct a PropertyChangedCallback which, when invoked, will result 
        /// in the DP being associated with the specified shader sampler 
        /// register index. Expected to be called on a Brush-valued
        /// DependencyProperty. 
        /// 
        protected static PropertyChangedCallback PixelShaderSamplerCallback(int samplerRegisterIndex, SamplingMode samplingMode)
        {
            return 
                (obj, args) =>
                { 
                    ShaderEffect eff = obj as ShaderEffect; 
                    if (eff != null)
                    { 
                        if (args.IsAValueChange)
                        {
                            eff.UpdateShaderSampler(args.Property, args.NewValue, samplerRegisterIndex, samplingMode);
                        } 
                    }
                }; 
        } 

        ///  
        /// Helper for defining Brush-valued DependencyProperties to associate with a
        /// sampler register in the PixelShader.
        /// 
        protected static DependencyProperty RegisterPixelShaderSamplerProperty(string dpName, 
                                                                               Type ownerType,
                                                                               int samplerRegisterIndex) 
        { 
            return RegisterPixelShaderSamplerProperty(dpName, ownerType, samplerRegisterIndex, _defaultSamplingMode);
        } 

        /// 
        /// Helper for defining Brush-valued DependencyProperties to associate with a
        /// sampler register in the PixelShader. 
        /// 
        protected static DependencyProperty RegisterPixelShaderSamplerProperty(string dpName, 
                                                                               Type ownerType, 
                                                                               int samplerRegisterIndex,
                                                                               SamplingMode samplingMode) 
        {
            return
                DependencyProperty.Register(dpName, typeof(Brush), ownerType,
                                            new UIPropertyMetadata(Effect.ImplicitInput, 
                                                                   PixelShaderSamplerCallback(samplerRegisterIndex,
                                                                                              samplingMode))); 
        } 

 
        // Updates the shader constant referred to by the DP.  Converts to the
        // form that the HLSL shaders want, and stores that value, since it will
        // be sent on every update.
        // We WritePreamble/Postscript here since this method is called by the user with the callback 
        // created in PixelShaderConstantCallback.
        private void UpdateShaderConstant(DependencyProperty dp, object newValue, int registerIndex) 
        { 
            WritePreamble();
            Type t = DetermineShaderConstantType(dp.PropertyType); 

            if (t == null)
            {
                throw new InvalidOperationException(SR.Get(SRID.Effect_ShaderConstantType, dp.PropertyType.Name)); 
            }
            else 
            { 
                int registerMax = 32;
                if (registerIndex >= registerMax || registerIndex < 0) 
                {
                    throw new ArgumentException(SR.Get(SRID.Effect_ShaderConstantRegisterLimit), "dp");
                }
 
                if (t == typeof(float))
                { 
                    MilColorF fourTuple; 
                    ConvertValueToMilColorF(newValue, out fourTuple);
                    StashInPosition(ref _floatRegisters, registerIndex, fourTuple, 32, ref _floatCount); 
                }
                else
                {
                    // We should convert all acceptable types to float. 
                    Debug.Assert(false);
                } 
            } 

            // Propagate dirty 
            this.PropertyChanged(dp);
            WritePostscript();
        }
 

        // Updates the shader sampler referred to by the DP.  Converts to the 
        // form that the HLSL shaders want, and stores that value, since it will 
        // be sent on every update.
        // We WritePreamble/Postscript here since this method is called by the user with the callback 
        // created in PixelShaderSamplerCallback.
        private void UpdateShaderSampler(DependencyProperty dp, object newValue, int registerIndex, SamplingMode samplingMode)
        {
            WritePreamble(); 

            if (newValue != null) 
            { 
                if (!(typeof(VisualBrush).IsInstanceOfType(newValue) ||
                      typeof(ImplicitInputBrush).IsInstanceOfType(newValue) || 
                      typeof(ImageBrush).IsInstanceOfType(newValue))
                      )
                {
                    // Note that if the type of the brush is ImplicitInputBrush and the value is non null, the value is actually 
                    // Effect.ImplicitInput. This is because ImplicitInputBrush is internal and the user can only get to the singleton
                    // Effect.ImplicitInput. 
                    throw new ArgumentException(SR.Get(SRID.Effect_ShaderSamplerType), "dp"); 
                }
            } 

            // PS2.0 allows max 16, but some cards seem to have trouble with 16 samplers being set.
            // Restricting to 4 for now.
            if (registerIndex >= 4 || registerIndex < 0)  // allow -1 for default 
            {
                throw new ArgumentException(SR.Get(SRID.Effect_ShaderSamplerRegisterLimit)); 
            } 

            SamplerData sd = new SamplerData() 
                {
                    _brush = (Brush)newValue,
                    _samplingMode = samplingMode
                }; 

            StashSamplerDataInPosition(registerIndex, sd, 16); 
 
            // Propagate dirty
            this.PropertyChanged(dp); 
            WritePostscript();
        }

 
        // Ensures that list is extended to 'position', and that
        // the specified value is inserted there.  For lists of value types. 
        private static void StashInPosition(ref List list, int position, T value, int maxIndex, ref int count) where T : struct 
        {
            if (list == null) 
            {
                list = new List(maxIndex);
            }
 
            if (list.Count <= position)
            { 
                int numToAdd = position - list.Count + 1; 
                for (int i = 0; i < numToAdd; i++)
                { 
                    list.Add((T?)null);
                }
            }
 
            if (!list[position].HasValue)
            { 
                // Going from null to having a value, so increment count 
                count++;
            } 

            list[position] = value;
        }
 
        // Ensures that _samplerData is extended to 'position', and that
        // the specified value is inserted there. 
        private void StashSamplerDataInPosition(int position, SamplerData newSampler, int maxIndex) 
        {
            if (_samplerData == null) 
            {
                _samplerData = new List(maxIndex);
            }
 
            if (_samplerData.Count <= position)
            { 
                int numToAdd = position - _samplerData.Count + 1; 
                for (int i = 0; i < numToAdd; i++)
                { 
                    _samplerData.Add((SamplerData?)null);
                }
            }
 
            if (!_samplerData[position].HasValue)
            { 
                // Going from null to having a value, so increment count 
                _samplerCount++;
            } 

            System.Windows.Threading.Dispatcher dispatcher = this.Dispatcher;

            // Release the old value if it is a resource on channel.  AddRef the 
            // new value.
            if (dispatcher != null) 
            { 
                SamplerData? oldSampler = _samplerData[position];
                Brush oldBrush = null; 
                if (oldSampler.HasValue)
                {
                    SamplerData ss = oldSampler.Value;
 
                    oldBrush = ss._brush;
                } 
 
                Brush newBrush = newSampler._brush;
 
                DUCE.IResource targetResource = (DUCE.IResource)this;
                using (CompositionEngineLock.Acquire())
                {
                    int channelCount = targetResource.GetChannelCount(); 

                    for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) 
                    { 
                        DUCE.Channel channel = targetResource.GetChannel(channelIndex);
                        Debug.Assert(!channel.IsOutOfBandChannel); 
                        Debug.Assert(!targetResource.GetHandle(channel).IsNull);
                        ReleaseResource(oldBrush,channel);
                        AddRefResource(newBrush,channel);
                    } 
                }
            } 
 
            _samplerData[position] = newSampler;
        } 

        /// 
        ///     Critical: This code accesses unsafe code blocks
        ///     TreatAsSafe: This code does is safe to call and calling a channel with pointers is ok 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private void ManualUpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) 
        {
            // If we're told we can skip the channel check, then we must be on channel 
            Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel));

            if (skipOnChannelCheck || _duceResource.IsOnChannel(channel))
            { 
                if (PixelShader == null)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Effect_ShaderPixelShaderSet)); 
                }
 
                checked
                {
                    DUCE.MILCMD_SHADEREFFECT data;
                    data.Type = MILCMD.MilCmdShaderEffect; 
                    data.Handle = _duceResource.GetHandle(channel);
 
                    data.TopPadding = _topPadding; 
                    data.BottomPadding = _bottomPadding;
                    data.LeftPadding = _leftPadding; 
                    data.RightPadding = _rightPadding;

                    data.DdxUvDdyUvRegisterIndex = this.DdxUvDdyUvRegisterIndex;
                    data.hPixelShader = ((DUCE.IResource)PixelShader).GetHandle(channel); 

                    unsafe 
                    { 
                        data.ShaderConstantFloatRegistersSize     = (uint)(sizeof(Int16) * _floatCount);
                        data.DependencyPropertyFloatValuesSize    = (uint)(4 * sizeof(Single) * _floatCount); 
                        data.ShaderSamplerRegistrationInfoSize    = (uint)(2 * sizeof(uint) * _samplerCount); // 2 pieces of data per sampler.
                        data.DependencyPropertySamplerValuesSize  = (uint)(1 * sizeof(DUCE.ResourceHandle) * _samplerCount);

                        channel.BeginCommand( 
                            (byte*)&data,
                            sizeof(DUCE.MILCMD_SHADEREFFECT), 
                            (int)(data.ShaderConstantFloatRegistersSize + 
                                  data.DependencyPropertyFloatValuesSize +
                                  data.ShaderSamplerRegistrationInfoSize + 
                                  data.DependencyPropertySamplerValuesSize )
                            );

                        // Arrays appear in this order: 
                        // 1) float register indices
                        // 2) float dp values 
                        // 3) sampler registration info 
                        // 4) sampler dp values
 
                        // 1) float register indices
                        AppendRegisters(channel, _floatRegisters);

                        // 2) float dp values 
                        if (_floatRegisters != null)
                        { 
                            for (int i = 0; i < _floatRegisters.Count; i++) 
                            {
                                MilColorF? v = _floatRegisters[i]; 
                                if (v.HasValue)
                                {
                                    MilColorF valueToPush = v.Value;
                                    channel.AppendCommandData((byte*)&valueToPush, sizeof(MilColorF)); 
                                }
                            } 
                        } 

                        // 3) sampler registration info 
                        if (_samplerCount > 0)
                        {
                            int count = _samplerData.Count;
                            for (int i = 0; i < count; i++) 
                            {
                                SamplerData? ssn = _samplerData[i]; 
                                if (ssn.HasValue) 
                                {
                                    SamplerData ss = ssn.Value; 

                                    // add as a 2-tuple (SamplerRegisterIndex,
                                    // SamplingMode)
 
                                    channel.AppendCommandData((byte*)&i, sizeof(int));
 
                                    int value = (int)(ss._samplingMode); 
                                    channel.AppendCommandData((byte*)&value, sizeof(int));
                                } 
                            }
                        }

 
                        // 4) sampler dp values
                        if (_samplerCount > 0) 
                        { 
                            for (int i = 0; i < _samplerData.Count; i++)
                            { 
                                SamplerData? ssn = _samplerData[i];
                                if (ssn.HasValue)
                                {
                                    SamplerData ss = ssn.Value; 

                                    // Making this assumption by storing a collection of 
                                    // handles as an Int32Collection 
                                    Debug.Assert(sizeof(DUCE.ResourceHandle) == sizeof(Int32));
 
                                    DUCE.ResourceHandle hBrush = ss._brush != null
                                        ? ((DUCE.IResource)ss._brush).GetHandle(channel)
                                        : DUCE.ResourceHandle.Null;
 
                                    Debug.Assert(!hBrush.IsNull || ss._brush == null, "If brush isn't null, hBrush better not be");
 
                                    channel.AppendCommandData((byte*)&hBrush, sizeof(DUCE.ResourceHandle)); 
                                }
 
                            }
                        }

                        // That's it... 
                        channel.EndCommand();
                    } 
                } 
            }
        } 

        // write the non-null values of the list of nullables to the command data.
        /// 
        ///     Critical: This code accesses unsafe code blocks 
        ///     TreatAsSafe: This code does is safe to call and calling a channel with pointers is ok
        ///  
        [SecurityCritical,SecurityTreatAsSafe] 
        private void AppendRegisters(DUCE.Channel channel, List list) where T : struct
        { 
            if (list != null)
            {
                unsafe
                { 
                    for (int i = 0; i < list.Count; i++)
                    { 
                        T? v = list[i]; 
                        if (v.HasValue)
                        { 
                            Int16 regIndex = (Int16)i;  // put onto stack so next &-operator compiles
                            channel.AppendCommandData((byte*)®Index, sizeof(Int16));
                        }
                    } 
                }
            } 
        } 

 
        // Written by hand to include management of input Brushes (which aren't DPs).
        internal override DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel)
        {
            if (_duceResource.CreateOrAddRefOnChannel(channel, System.Windows.Media.Composition.DUCE.ResourceType.TYPE_SHADEREFFECT)) 
            {
                // Ensures brushes are property instantiated into Duce resources. 
                if (_samplerCount > 0) 
                {
                    int numSamplers = _samplerData.Count; 
                    for (int i = 0; i < numSamplers; i++)
                    {
                        SamplerData? ssn = _samplerData[i];
                        if (ssn.HasValue) 
                        {
                            SamplerData ss = ssn.Value; 
 
                            DUCE.IResource brush = ss._brush as DUCE.IResource;
                            if (brush != null) 
                            {
                                brush.AddRefOnChannel(channel);
                            }
                        } 
                    }
                } 
 
                PixelShader vPixelShader = PixelShader;
                if (vPixelShader != null) ((DUCE.IResource)vPixelShader).AddRefOnChannel(channel); 

                AddRefOnChannelAnimations(channel);

 
                UpdateResource(channel, true /* skip "on channel" check - we already know that we're on channel */ );
            } 
 
            return _duceResource.GetHandle(channel);
        } 


        // Written by hand to include management of input Brushes (which aren't DPs).
        internal override void ReleaseOnChannelCore(DUCE.Channel channel) 
        {
            Debug.Assert(_duceResource.IsOnChannel(channel)); 
 
            if (_duceResource.ReleaseOnChannel(channel))
            { 
                // Ensure that brushes are released.
                if (_samplerCount > 0)
                {
                    int numSamplers = _samplerData.Count; 
                    for (int i = 0; i < numSamplers; i++)
                    { 
                        SamplerData? ssn = _samplerData[i]; 
                        if (ssn.HasValue)
                        { 
                            SamplerData ss = ssn.Value;

                            DUCE.IResource brush = ss._brush as DUCE.IResource;
                            if (brush != null) 
                            {
                                brush.ReleaseOnChannel(channel); 
                            } 
                        }
                    } 
                }

                PixelShader vPixelShader = PixelShader;
                if (vPixelShader != null) ((DUCE.IResource)vPixelShader).ReleaseOnChannel(channel); 

                ReleaseOnChannelAnimations(channel); 
 
            }
 
        }


        // Shader constants can be coerced into 4-tuples of floats only, at this time. 
        // Determine which type the incoming type can go to, if any.
        internal static Type DetermineShaderConstantType(Type type) 
        { 
            Type result = null;
            if (type == typeof(double) || 
                type == typeof(float) ||
                type == typeof(Color) ||
                type == typeof(Point) ||
                type == typeof(Size) || 
                type == typeof(Vector) ||
                type == typeof(Point3D) || 
                type == typeof(Vector3D) || 
                type == typeof(Point4D))
            { 
                result = typeof(float);
            }

            return result; 
        }
 
 
        // Convert to float four tuple
        internal static void ConvertValueToMilColorF(object value, out MilColorF newVal) 
        {
            Type t = value.GetType();

            // Fill in four-tuples.  Always fill in 1.0's for where there are 
            // empty slots, to avoid division by zero on vector operations that
            // these values are subjected to. 
 
            // Should order these in terms of most likely to be hit first.
            if (t == typeof(double) || t == typeof(float)) 
            {
                float fVal = (t == typeof(double)) ? (float)(double)value : (float)value;

                // Scalars extend out to fill entire vector. 
                newVal.r = newVal.g = newVal.b = newVal.a = fVal;
            } 
            else if (t == typeof(Color)) 
            {
                Color col = (Color)value; 
                newVal.r = (float)col.R / 255f;
                newVal.g = (float)col.G / 255f;
                newVal.b = (float)col.B / 255f;
                newVal.a = (float)col.A / 255f; 
            }
            else if (t == typeof(Point)) 
            { 
                Point p = (Point)value;
                newVal.r = (float)p.X; 
                newVal.g = (float)p.Y;
                newVal.b = 1f;
                newVal.a = 1f;
            } 
            else if (t == typeof(Size))
            { 
                Size s = (Size)value; 
                newVal.r = (float)s.Width;
                newVal.g = (float)s.Height; 
                newVal.b = 1f;
                newVal.a = 1f;
            }
            else if (t == typeof(Vector)) 
            {
                Vector v = (Vector)value; 
                newVal.r = (float)v.X; 
                newVal.g = (float)v.Y;
                newVal.b = 1f; 
                newVal.a = 1f;
            }
            else if (t == typeof(Point3D))
            { 
                Point3D p = (Point3D)value;
                newVal.r = (float)p.X; 
                newVal.g = (float)p.Y; 
                newVal.b = (float)p.Z;
                newVal.a = 1f; 
            }
            else if (t == typeof(Vector3D))
            {
                Vector3D v = (Vector3D)value; 
                newVal.r = (float)v.X;
                newVal.g = (float)v.Y; 
                newVal.b = (float)v.Z; 
                newVal.a = 1f;
            } 
            else if (t == typeof(Point4D))
            {
                Point4D p = (Point4D)value;
                newVal.r = (float)p.X; 
                newVal.g = (float)p.Y;
                newVal.b = (float)p.Z; 
                newVal.a = (float)p.W; 
            }
            else 
            {
                // We should never hit this case, since we check the type using DetermineShaderConstantType
                // before we call this method.
                Debug.Assert(false); 
                newVal.r = newVal.b = newVal.g = newVal.a = 1f;
 
            } 

        } 


        /// 
        /// Implementation of Freezable.CloneCore. 
        /// 
        ///  
        protected override void CloneCore(Freezable sourceFreezable) 
        {
            ShaderEffect effect = (ShaderEffect)sourceFreezable; 
            base.CloneCore(sourceFreezable);
            CopyCommon(effect);
        }
 

        ///  
        /// Implementation of Freezable.CloneCurrentValueCore. 
        /// 
        ///  
        protected override void CloneCurrentValueCore(Freezable sourceFreezable)
        {
            ShaderEffect effect = (ShaderEffect)sourceFreezable;
            base.CloneCurrentValueCore(sourceFreezable); 
            CopyCommon(effect);
        } 
 

        ///  
        /// Implementation of Freezable.GetAsFrozenCore.
        /// 
        /// 
        protected override void GetAsFrozenCore(Freezable sourceFreezable) 
        {
            ShaderEffect effect = (ShaderEffect)sourceFreezable; 
            base.GetAsFrozenCore(sourceFreezable); 
            CopyCommon(effect);
        } 


        /// 
        /// Implementation of Freezable.GetCurrentValueAsFrozenCore. 
        /// 
        ///  
        protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable) 
        {
            ShaderEffect effect = (ShaderEffect)sourceFreezable; 
            base.GetCurrentValueAsFrozenCore(sourceFreezable);
            CopyCommon(effect);
        }
 
        /// 
        /// Clones values that do not have corresponding DPs. 
        ///  
        /// 
        private void CopyCommon(ShaderEffect effect) 
        {
            _topPadding = effect._topPadding;
            _bottomPadding = effect._bottomPadding;
            _leftPadding = effect._leftPadding; 
            _rightPadding = effect._rightPadding;
            if (_floatRegisters != null) 
            { 
                _floatRegisters = new List(effect._floatRegisters);
            } 
            if (_samplerData != null)
            {
                _samplerData = new List(effect._samplerData);
            } 
            _floatCount = effect._floatCount;
            _samplerCount = effect._samplerCount; 
            _ddxUvDdyUvRegisterIndex = effect._ddxUvDdyUvRegisterIndex; 
            _sentFirstTime = effect._sentFirstTime;
        } 


        private struct SamplerData
        { 
            public Brush _brush;
            public SamplingMode _samplingMode; 
        } 

        private const SamplingMode _defaultSamplingMode = SamplingMode.Auto; 

        // Instance data
        private double _topPadding = 0.0;
        private double _bottomPadding = 0.0; 
        private double _leftPadding = 0.0;
        private double _rightPadding = 0.0; 
        private List    _floatRegisters = null; 
        private List  _samplerData = null;
        private int                 _floatCount = 0; 
        private int                 _samplerCount = 0;

        private int  _ddxUvDdyUvRegisterIndex = -1;
        private bool _sentFirstTime = false; 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  Microsoft Windows Presentation Foundation
//  Copyright (c) Microsoft Corporation, 2008
//
//  File:       ShaderEffect.cs 
//-----------------------------------------------------------------------------
 
using System; 
using System.Collections.Generic;
using System.Diagnostics; 
using System.Windows;
using System.Windows.Media;
using System.IO;
using System.Windows.Markup; 
using System.Windows.Media.Composition;
using System.Windows.Media.Media3D; 
using System.Security; 
using System.Security.Permissions;
using System.Runtime.InteropServices; 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;

namespace System.Windows.Media.Effects 
{
    public abstract partial class ShaderEffect : Effect 
    { 
        /// 
        /// Padding is used to specify that an effect's output texture is larger than its input 
        //  texture in a specific direction, e.g. for a drop shadow effect.
        /// 
        protected double PaddingTop
        { 
            get
            { 
                ReadPreamble(); 
                return _topPadding;
            } 
            set
            {
                WritePreamble();
                if (value < 0.0) 
                {
                    throw new ArgumentOutOfRangeException("PaddingTop", value, SR.Get(SRID.Effect_ShaderEffectPadding)); 
                } 
                else
                { 
                    _topPadding = value;
                    RegisterForAsyncUpdateResource();
                }
                WritePostscript(); 
            }
        } 
 
        /// 
        /// Padding is used to specify that an effect's output texture is larger than its input 
        //  texture in a specific direction, e.g. for a drop shadow effect.
        /// 
        protected double PaddingBottom
        { 
            get
            { 
                ReadPreamble(); 
                return _bottomPadding;
            } 
            set
            {
                WritePreamble();
                if (value < 0.0) 
                {
                    throw new ArgumentOutOfRangeException("PaddingBottom", value, SR.Get(SRID.Effect_ShaderEffectPadding)); 
                } 
                else
                { 
                    _bottomPadding = value;
                    RegisterForAsyncUpdateResource();
                }
                WritePostscript(); 
            }
        } 
 
        /// 
        /// Padding is used to specify that an effect's output texture is larger than its input 
        //  texture in a specific direction, e.g. for a drop shadow effect.
        /// 
        protected double PaddingLeft
        { 
            get
            { 
                ReadPreamble(); 
                return _leftPadding;
            } 
            set
            {
                WritePreamble();
                if (value < 0.0) 
                {
                    throw new ArgumentOutOfRangeException("PaddingLeft", value, SR.Get(SRID.Effect_ShaderEffectPadding)); 
                } 
                else
                { 
                    _leftPadding = value;
                    RegisterForAsyncUpdateResource();
                }
                WritePostscript(); 
            }
        } 
 
        /// 
        /// Padding is used to specify that an effect's output texture is larger than its input 
        //  texture in a specific direction, e.g. for a drop shadow effect.
        /// 
        protected double PaddingRight
        { 
            get
            { 
                ReadPreamble(); 
                return _rightPadding;
            } 
            set
            {
                WritePreamble();
                if (value < 0.0) 
                {
                    throw new ArgumentOutOfRangeException("PaddingRight", value, SR.Get(SRID.Effect_ShaderEffectPadding)); 
                } 
                else
                { 
                    _rightPadding = value;
                    RegisterForAsyncUpdateResource();
                }
                WritePostscript(); 
            }
        } 
 
        /// 
        /// To specify a shader constant register to set to the size of the 
        /// destination.  Default is -1, which means to not send any.  Only
        /// intended to be set once, in the constructor, and will fail if set
        /// after the effect is initially processed.
        ///  
        protected int DdxUvDdyUvRegisterIndex
 
        { 
            get
            { 
                ReadPreamble();
                return _ddxUvDdyUvRegisterIndex;
            }
 
            set
            { 
                WritePreamble(); 
                if (_sentFirstTime)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Effect_ShaderDdxUvDdyUvRegisterIndex));
                }
                _ddxUvDdyUvRegisterIndex = value;
                WritePostscript(); 
            }
        } 
 
        /// 
        /// Tells the Effect that the shader constant or sampler corresponding 
        /// to the specified DependencyProperty needs to be updated.
        /// 
        protected void UpdateShaderValue(DependencyProperty dp)
        { 
            if (dp != null)
            { 
                WritePreamble(); 
                object val = this.GetValue(dp);
                var metadata = dp.GetMetadata(this); 
                if (metadata != null)
                {
                    var callback = metadata.PropertyChangedCallback;
                    if (callback != null) 
                    {
                        callback(this, new DependencyPropertyChangedEventArgs(dp, val, val)); 
                    } 
                }
                WritePostscript(); 
            }
        }

        ///  
        /// Construct a PropertyChangedCallback which, when invoked, will result in the DP being
        /// associated with the specified shader constant register index. 
        ///  
        protected static PropertyChangedCallback PixelShaderConstantCallback(int floatRegisterIndex)
        { 
            return
                (obj, args) =>
                {
                    ShaderEffect eff = obj as ShaderEffect; 
                    if (eff != null)
                    { 
                        eff.UpdateShaderConstant(args.Property, args.NewValue, floatRegisterIndex); 
                    }
                }; 
        }

        /// 
        /// Construct a PropertyChangedCallback which, when invoked, will result 
        /// in the DP being associated with the specified shader sampler
        /// register index. Expected to be called on a Brush-valued 
        /// DependencyProperty. 
        /// 
        protected static PropertyChangedCallback PixelShaderSamplerCallback(int samplerRegisterIndex) 
        {
            return PixelShaderSamplerCallback(samplerRegisterIndex, _defaultSamplingMode);
        }
 
        /// 
        /// Construct a PropertyChangedCallback which, when invoked, will result 
        /// in the DP being associated with the specified shader sampler 
        /// register index. Expected to be called on a Brush-valued
        /// DependencyProperty. 
        /// 
        protected static PropertyChangedCallback PixelShaderSamplerCallback(int samplerRegisterIndex, SamplingMode samplingMode)
        {
            return 
                (obj, args) =>
                { 
                    ShaderEffect eff = obj as ShaderEffect; 
                    if (eff != null)
                    { 
                        if (args.IsAValueChange)
                        {
                            eff.UpdateShaderSampler(args.Property, args.NewValue, samplerRegisterIndex, samplingMode);
                        } 
                    }
                }; 
        } 

        ///  
        /// Helper for defining Brush-valued DependencyProperties to associate with a
        /// sampler register in the PixelShader.
        /// 
        protected static DependencyProperty RegisterPixelShaderSamplerProperty(string dpName, 
                                                                               Type ownerType,
                                                                               int samplerRegisterIndex) 
        { 
            return RegisterPixelShaderSamplerProperty(dpName, ownerType, samplerRegisterIndex, _defaultSamplingMode);
        } 

        /// 
        /// Helper for defining Brush-valued DependencyProperties to associate with a
        /// sampler register in the PixelShader. 
        /// 
        protected static DependencyProperty RegisterPixelShaderSamplerProperty(string dpName, 
                                                                               Type ownerType, 
                                                                               int samplerRegisterIndex,
                                                                               SamplingMode samplingMode) 
        {
            return
                DependencyProperty.Register(dpName, typeof(Brush), ownerType,
                                            new UIPropertyMetadata(Effect.ImplicitInput, 
                                                                   PixelShaderSamplerCallback(samplerRegisterIndex,
                                                                                              samplingMode))); 
        } 

 
        // Updates the shader constant referred to by the DP.  Converts to the
        // form that the HLSL shaders want, and stores that value, since it will
        // be sent on every update.
        // We WritePreamble/Postscript here since this method is called by the user with the callback 
        // created in PixelShaderConstantCallback.
        private void UpdateShaderConstant(DependencyProperty dp, object newValue, int registerIndex) 
        { 
            WritePreamble();
            Type t = DetermineShaderConstantType(dp.PropertyType); 

            if (t == null)
            {
                throw new InvalidOperationException(SR.Get(SRID.Effect_ShaderConstantType, dp.PropertyType.Name)); 
            }
            else 
            { 
                int registerMax = 32;
                if (registerIndex >= registerMax || registerIndex < 0) 
                {
                    throw new ArgumentException(SR.Get(SRID.Effect_ShaderConstantRegisterLimit), "dp");
                }
 
                if (t == typeof(float))
                { 
                    MilColorF fourTuple; 
                    ConvertValueToMilColorF(newValue, out fourTuple);
                    StashInPosition(ref _floatRegisters, registerIndex, fourTuple, 32, ref _floatCount); 
                }
                else
                {
                    // We should convert all acceptable types to float. 
                    Debug.Assert(false);
                } 
            } 

            // Propagate dirty 
            this.PropertyChanged(dp);
            WritePostscript();
        }
 

        // Updates the shader sampler referred to by the DP.  Converts to the 
        // form that the HLSL shaders want, and stores that value, since it will 
        // be sent on every update.
        // We WritePreamble/Postscript here since this method is called by the user with the callback 
        // created in PixelShaderSamplerCallback.
        private void UpdateShaderSampler(DependencyProperty dp, object newValue, int registerIndex, SamplingMode samplingMode)
        {
            WritePreamble(); 

            if (newValue != null) 
            { 
                if (!(typeof(VisualBrush).IsInstanceOfType(newValue) ||
                      typeof(ImplicitInputBrush).IsInstanceOfType(newValue) || 
                      typeof(ImageBrush).IsInstanceOfType(newValue))
                      )
                {
                    // Note that if the type of the brush is ImplicitInputBrush and the value is non null, the value is actually 
                    // Effect.ImplicitInput. This is because ImplicitInputBrush is internal and the user can only get to the singleton
                    // Effect.ImplicitInput. 
                    throw new ArgumentException(SR.Get(SRID.Effect_ShaderSamplerType), "dp"); 
                }
            } 

            // PS2.0 allows max 16, but some cards seem to have trouble with 16 samplers being set.
            // Restricting to 4 for now.
            if (registerIndex >= 4 || registerIndex < 0)  // allow -1 for default 
            {
                throw new ArgumentException(SR.Get(SRID.Effect_ShaderSamplerRegisterLimit)); 
            } 

            SamplerData sd = new SamplerData() 
                {
                    _brush = (Brush)newValue,
                    _samplingMode = samplingMode
                }; 

            StashSamplerDataInPosition(registerIndex, sd, 16); 
 
            // Propagate dirty
            this.PropertyChanged(dp); 
            WritePostscript();
        }

 
        // Ensures that list is extended to 'position', and that
        // the specified value is inserted there.  For lists of value types. 
        private static void StashInPosition(ref List list, int position, T value, int maxIndex, ref int count) where T : struct 
        {
            if (list == null) 
            {
                list = new List(maxIndex);
            }
 
            if (list.Count <= position)
            { 
                int numToAdd = position - list.Count + 1; 
                for (int i = 0; i < numToAdd; i++)
                { 
                    list.Add((T?)null);
                }
            }
 
            if (!list[position].HasValue)
            { 
                // Going from null to having a value, so increment count 
                count++;
            } 

            list[position] = value;
        }
 
        // Ensures that _samplerData is extended to 'position', and that
        // the specified value is inserted there. 
        private void StashSamplerDataInPosition(int position, SamplerData newSampler, int maxIndex) 
        {
            if (_samplerData == null) 
            {
                _samplerData = new List(maxIndex);
            }
 
            if (_samplerData.Count <= position)
            { 
                int numToAdd = position - _samplerData.Count + 1; 
                for (int i = 0; i < numToAdd; i++)
                { 
                    _samplerData.Add((SamplerData?)null);
                }
            }
 
            if (!_samplerData[position].HasValue)
            { 
                // Going from null to having a value, so increment count 
                _samplerCount++;
            } 

            System.Windows.Threading.Dispatcher dispatcher = this.Dispatcher;

            // Release the old value if it is a resource on channel.  AddRef the 
            // new value.
            if (dispatcher != null) 
            { 
                SamplerData? oldSampler = _samplerData[position];
                Brush oldBrush = null; 
                if (oldSampler.HasValue)
                {
                    SamplerData ss = oldSampler.Value;
 
                    oldBrush = ss._brush;
                } 
 
                Brush newBrush = newSampler._brush;
 
                DUCE.IResource targetResource = (DUCE.IResource)this;
                using (CompositionEngineLock.Acquire())
                {
                    int channelCount = targetResource.GetChannelCount(); 

                    for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) 
                    { 
                        DUCE.Channel channel = targetResource.GetChannel(channelIndex);
                        Debug.Assert(!channel.IsOutOfBandChannel); 
                        Debug.Assert(!targetResource.GetHandle(channel).IsNull);
                        ReleaseResource(oldBrush,channel);
                        AddRefResource(newBrush,channel);
                    } 
                }
            } 
 
            _samplerData[position] = newSampler;
        } 

        /// 
        ///     Critical: This code accesses unsafe code blocks
        ///     TreatAsSafe: This code does is safe to call and calling a channel with pointers is ok 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private void ManualUpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) 
        {
            // If we're told we can skip the channel check, then we must be on channel 
            Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel));

            if (skipOnChannelCheck || _duceResource.IsOnChannel(channel))
            { 
                if (PixelShader == null)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Effect_ShaderPixelShaderSet)); 
                }
 
                checked
                {
                    DUCE.MILCMD_SHADEREFFECT data;
                    data.Type = MILCMD.MilCmdShaderEffect; 
                    data.Handle = _duceResource.GetHandle(channel);
 
                    data.TopPadding = _topPadding; 
                    data.BottomPadding = _bottomPadding;
                    data.LeftPadding = _leftPadding; 
                    data.RightPadding = _rightPadding;

                    data.DdxUvDdyUvRegisterIndex = this.DdxUvDdyUvRegisterIndex;
                    data.hPixelShader = ((DUCE.IResource)PixelShader).GetHandle(channel); 

                    unsafe 
                    { 
                        data.ShaderConstantFloatRegistersSize     = (uint)(sizeof(Int16) * _floatCount);
                        data.DependencyPropertyFloatValuesSize    = (uint)(4 * sizeof(Single) * _floatCount); 
                        data.ShaderSamplerRegistrationInfoSize    = (uint)(2 * sizeof(uint) * _samplerCount); // 2 pieces of data per sampler.
                        data.DependencyPropertySamplerValuesSize  = (uint)(1 * sizeof(DUCE.ResourceHandle) * _samplerCount);

                        channel.BeginCommand( 
                            (byte*)&data,
                            sizeof(DUCE.MILCMD_SHADEREFFECT), 
                            (int)(data.ShaderConstantFloatRegistersSize + 
                                  data.DependencyPropertyFloatValuesSize +
                                  data.ShaderSamplerRegistrationInfoSize + 
                                  data.DependencyPropertySamplerValuesSize )
                            );

                        // Arrays appear in this order: 
                        // 1) float register indices
                        // 2) float dp values 
                        // 3) sampler registration info 
                        // 4) sampler dp values
 
                        // 1) float register indices
                        AppendRegisters(channel, _floatRegisters);

                        // 2) float dp values 
                        if (_floatRegisters != null)
                        { 
                            for (int i = 0; i < _floatRegisters.Count; i++) 
                            {
                                MilColorF? v = _floatRegisters[i]; 
                                if (v.HasValue)
                                {
                                    MilColorF valueToPush = v.Value;
                                    channel.AppendCommandData((byte*)&valueToPush, sizeof(MilColorF)); 
                                }
                            } 
                        } 

                        // 3) sampler registration info 
                        if (_samplerCount > 0)
                        {
                            int count = _samplerData.Count;
                            for (int i = 0; i < count; i++) 
                            {
                                SamplerData? ssn = _samplerData[i]; 
                                if (ssn.HasValue) 
                                {
                                    SamplerData ss = ssn.Value; 

                                    // add as a 2-tuple (SamplerRegisterIndex,
                                    // SamplingMode)
 
                                    channel.AppendCommandData((byte*)&i, sizeof(int));
 
                                    int value = (int)(ss._samplingMode); 
                                    channel.AppendCommandData((byte*)&value, sizeof(int));
                                } 
                            }
                        }

 
                        // 4) sampler dp values
                        if (_samplerCount > 0) 
                        { 
                            for (int i = 0; i < _samplerData.Count; i++)
                            { 
                                SamplerData? ssn = _samplerData[i];
                                if (ssn.HasValue)
                                {
                                    SamplerData ss = ssn.Value; 

                                    // Making this assumption by storing a collection of 
                                    // handles as an Int32Collection 
                                    Debug.Assert(sizeof(DUCE.ResourceHandle) == sizeof(Int32));
 
                                    DUCE.ResourceHandle hBrush = ss._brush != null
                                        ? ((DUCE.IResource)ss._brush).GetHandle(channel)
                                        : DUCE.ResourceHandle.Null;
 
                                    Debug.Assert(!hBrush.IsNull || ss._brush == null, "If brush isn't null, hBrush better not be");
 
                                    channel.AppendCommandData((byte*)&hBrush, sizeof(DUCE.ResourceHandle)); 
                                }
 
                            }
                        }

                        // That's it... 
                        channel.EndCommand();
                    } 
                } 
            }
        } 

        // write the non-null values of the list of nullables to the command data.
        /// 
        ///     Critical: This code accesses unsafe code blocks 
        ///     TreatAsSafe: This code does is safe to call and calling a channel with pointers is ok
        ///  
        [SecurityCritical,SecurityTreatAsSafe] 
        private void AppendRegisters(DUCE.Channel channel, List list) where T : struct
        { 
            if (list != null)
            {
                unsafe
                { 
                    for (int i = 0; i < list.Count; i++)
                    { 
                        T? v = list[i]; 
                        if (v.HasValue)
                        { 
                            Int16 regIndex = (Int16)i;  // put onto stack so next &-operator compiles
                            channel.AppendCommandData((byte*)®Index, sizeof(Int16));
                        }
                    } 
                }
            } 
        } 

 
        // Written by hand to include management of input Brushes (which aren't DPs).
        internal override DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel)
        {
            if (_duceResource.CreateOrAddRefOnChannel(channel, System.Windows.Media.Composition.DUCE.ResourceType.TYPE_SHADEREFFECT)) 
            {
                // Ensures brushes are property instantiated into Duce resources. 
                if (_samplerCount > 0) 
                {
                    int numSamplers = _samplerData.Count; 
                    for (int i = 0; i < numSamplers; i++)
                    {
                        SamplerData? ssn = _samplerData[i];
                        if (ssn.HasValue) 
                        {
                            SamplerData ss = ssn.Value; 
 
                            DUCE.IResource brush = ss._brush as DUCE.IResource;
                            if (brush != null) 
                            {
                                brush.AddRefOnChannel(channel);
                            }
                        } 
                    }
                } 
 
                PixelShader vPixelShader = PixelShader;
                if (vPixelShader != null) ((DUCE.IResource)vPixelShader).AddRefOnChannel(channel); 

                AddRefOnChannelAnimations(channel);

 
                UpdateResource(channel, true /* skip "on channel" check - we already know that we're on channel */ );
            } 
 
            return _duceResource.GetHandle(channel);
        } 


        // Written by hand to include management of input Brushes (which aren't DPs).
        internal override void ReleaseOnChannelCore(DUCE.Channel channel) 
        {
            Debug.Assert(_duceResource.IsOnChannel(channel)); 
 
            if (_duceResource.ReleaseOnChannel(channel))
            { 
                // Ensure that brushes are released.
                if (_samplerCount > 0)
                {
                    int numSamplers = _samplerData.Count; 
                    for (int i = 0; i < numSamplers; i++)
                    { 
                        SamplerData? ssn = _samplerData[i]; 
                        if (ssn.HasValue)
                        { 
                            SamplerData ss = ssn.Value;

                            DUCE.IResource brush = ss._brush as DUCE.IResource;
                            if (brush != null) 
                            {
                                brush.ReleaseOnChannel(channel); 
                            } 
                        }
                    } 
                }

                PixelShader vPixelShader = PixelShader;
                if (vPixelShader != null) ((DUCE.IResource)vPixelShader).ReleaseOnChannel(channel); 

                ReleaseOnChannelAnimations(channel); 
 
            }
 
        }


        // Shader constants can be coerced into 4-tuples of floats only, at this time. 
        // Determine which type the incoming type can go to, if any.
        internal static Type DetermineShaderConstantType(Type type) 
        { 
            Type result = null;
            if (type == typeof(double) || 
                type == typeof(float) ||
                type == typeof(Color) ||
                type == typeof(Point) ||
                type == typeof(Size) || 
                type == typeof(Vector) ||
                type == typeof(Point3D) || 
                type == typeof(Vector3D) || 
                type == typeof(Point4D))
            { 
                result = typeof(float);
            }

            return result; 
        }
 
 
        // Convert to float four tuple
        internal static void ConvertValueToMilColorF(object value, out MilColorF newVal) 
        {
            Type t = value.GetType();

            // Fill in four-tuples.  Always fill in 1.0's for where there are 
            // empty slots, to avoid division by zero on vector operations that
            // these values are subjected to. 
 
            // Should order these in terms of most likely to be hit first.
            if (t == typeof(double) || t == typeof(float)) 
            {
                float fVal = (t == typeof(double)) ? (float)(double)value : (float)value;

                // Scalars extend out to fill entire vector. 
                newVal.r = newVal.g = newVal.b = newVal.a = fVal;
            } 
            else if (t == typeof(Color)) 
            {
                Color col = (Color)value; 
                newVal.r = (float)col.R / 255f;
                newVal.g = (float)col.G / 255f;
                newVal.b = (float)col.B / 255f;
                newVal.a = (float)col.A / 255f; 
            }
            else if (t == typeof(Point)) 
            { 
                Point p = (Point)value;
                newVal.r = (float)p.X; 
                newVal.g = (float)p.Y;
                newVal.b = 1f;
                newVal.a = 1f;
            } 
            else if (t == typeof(Size))
            { 
                Size s = (Size)value; 
                newVal.r = (float)s.Width;
                newVal.g = (float)s.Height; 
                newVal.b = 1f;
                newVal.a = 1f;
            }
            else if (t == typeof(Vector)) 
            {
                Vector v = (Vector)value; 
                newVal.r = (float)v.X; 
                newVal.g = (float)v.Y;
                newVal.b = 1f; 
                newVal.a = 1f;
            }
            else if (t == typeof(Point3D))
            { 
                Point3D p = (Point3D)value;
                newVal.r = (float)p.X; 
                newVal.g = (float)p.Y; 
                newVal.b = (float)p.Z;
                newVal.a = 1f; 
            }
            else if (t == typeof(Vector3D))
            {
                Vector3D v = (Vector3D)value; 
                newVal.r = (float)v.X;
                newVal.g = (float)v.Y; 
                newVal.b = (float)v.Z; 
                newVal.a = 1f;
            } 
            else if (t == typeof(Point4D))
            {
                Point4D p = (Point4D)value;
                newVal.r = (float)p.X; 
                newVal.g = (float)p.Y;
                newVal.b = (float)p.Z; 
                newVal.a = (float)p.W; 
            }
            else 
            {
                // We should never hit this case, since we check the type using DetermineShaderConstantType
                // before we call this method.
                Debug.Assert(false); 
                newVal.r = newVal.b = newVal.g = newVal.a = 1f;
 
            } 

        } 


        /// 
        /// Implementation of Freezable.CloneCore. 
        /// 
        ///  
        protected override void CloneCore(Freezable sourceFreezable) 
        {
            ShaderEffect effect = (ShaderEffect)sourceFreezable; 
            base.CloneCore(sourceFreezable);
            CopyCommon(effect);
        }
 

        ///  
        /// Implementation of Freezable.CloneCurrentValueCore. 
        /// 
        ///  
        protected override void CloneCurrentValueCore(Freezable sourceFreezable)
        {
            ShaderEffect effect = (ShaderEffect)sourceFreezable;
            base.CloneCurrentValueCore(sourceFreezable); 
            CopyCommon(effect);
        } 
 

        ///  
        /// Implementation of Freezable.GetAsFrozenCore.
        /// 
        /// 
        protected override void GetAsFrozenCore(Freezable sourceFreezable) 
        {
            ShaderEffect effect = (ShaderEffect)sourceFreezable; 
            base.GetAsFrozenCore(sourceFreezable); 
            CopyCommon(effect);
        } 


        /// 
        /// Implementation of Freezable.GetCurrentValueAsFrozenCore. 
        /// 
        ///  
        protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable) 
        {
            ShaderEffect effect = (ShaderEffect)sourceFreezable; 
            base.GetCurrentValueAsFrozenCore(sourceFreezable);
            CopyCommon(effect);
        }
 
        /// 
        /// Clones values that do not have corresponding DPs. 
        ///  
        /// 
        private void CopyCommon(ShaderEffect effect) 
        {
            _topPadding = effect._topPadding;
            _bottomPadding = effect._bottomPadding;
            _leftPadding = effect._leftPadding; 
            _rightPadding = effect._rightPadding;
            if (_floatRegisters != null) 
            { 
                _floatRegisters = new List(effect._floatRegisters);
            } 
            if (_samplerData != null)
            {
                _samplerData = new List(effect._samplerData);
            } 
            _floatCount = effect._floatCount;
            _samplerCount = effect._samplerCount; 
            _ddxUvDdyUvRegisterIndex = effect._ddxUvDdyUvRegisterIndex; 
            _sentFirstTime = effect._sentFirstTime;
        } 


        private struct SamplerData
        { 
            public Brush _brush;
            public SamplingMode _samplingMode; 
        } 

        private const SamplingMode _defaultSamplingMode = SamplingMode.Auto; 

        // Instance data
        private double _topPadding = 0.0;
        private double _bottomPadding = 0.0; 
        private double _leftPadding = 0.0;
        private double _rightPadding = 0.0; 
        private List    _floatRegisters = null; 
        private List  _samplerData = null;
        private int                 _floatCount = 0; 
        private int                 _samplerCount = 0;

        private int  _ddxUvDdyUvRegisterIndex = -1;
        private bool _sentFirstTime = false; 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK