PixelShader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / Effects / PixelShader.cs / 1305600 / PixelShader.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Windows Presentation Foundation
//  Copyright (c) Microsoft Corporation, 2008
//
//  File:       PixelShader.cs 
//-----------------------------------------------------------------------------
 
using System; 
using System.IO;
using MS.Internal; 
using MS.Win32.PresentationCore;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics; 
using System.Reflection;
using System.Collections; 
using System.Globalization; 
using System.Security;
using System.Windows.Media; 
using System.Windows.Media.Animation;
using System.Windows.Media.Composition;
using System.Windows;
using System.Text.RegularExpressions; 
using System.Runtime.InteropServices;
using System.Windows.Markup; 
using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;
using System.Windows.Navigation; 
using System.IO.Packaging;
using MS.Internal.PresentationCore;

namespace System.Windows.Media.Effects 
{
    public sealed partial class PixelShader : Animatable, DUCE.IResource 
    { 
        // Method and not property so we don't need to hang onto the stream.
        public void SetStreamSource(Stream source) 
        {
            WritePreamble();
            LoadPixelShaderFromStreamIntoMemory(source);
            WritePostscript(); 
        }
 
        ///  
        /// The major version of the pixel shader
        ///  
        internal short ShaderMajorVersion
        {
            get;
            private set; 
        }
 
        ///  
        /// The minor version of the pixel shader
        ///  
        internal short ShaderMinorVersion
        {
            get;
            private set; 
        }
 
        ///  
        /// If any PixelShader cannot be processed by the render thread, this
        /// event will be raised. 
        /// 
        public static event EventHandler InvalidPixelShaderEncountered
        {
            add 
            {
                // Just forward to the internal event on MediaContext 
                MediaContext mediaContext = MediaContext.CurrentMediaContext; 
                mediaContext.InvalidPixelShaderEncountered += value;
            } 
            remove
            {
                MediaContext mediaContext = MediaContext.CurrentMediaContext;
                mediaContext.InvalidPixelShaderEncountered -= value; 
            }
        } 
 
        /// 
        /// This method is invoked whenever the source property changes. 
        /// 
        private void UriSourcePropertyChangedHook(DependencyPropertyChangedEventArgs e)
        {
            // Decided against comparing the URI because the user might want to change the shader on the filesystem 
            // and reload it.
 
            // We do not support async loading of shaders here. If that is desired the user needs to use the SetStreamSource 
            // API.
 
            Uri newUri = (Uri)e.NewValue;
            Stream stream = null;

            try { 
                if (newUri != null)
                { 
                    if (!newUri.IsAbsoluteUri) 
                    {
                         newUri = BaseUriHelper.GetResolvedUri(BaseUriHelper.BaseUri, newUri); 
                    }

                    Debug.Assert(newUri.IsAbsoluteUri);
 
                    // Now the URI is an absolute URI.
 
                    // 
                    // Only allow file and pack URIs.
                    if (!newUri.IsFile && 
                        !PackUriHelper.IsPackUri(newUri))
                    {
                        throw new ArgumentException(SR.Get(SRID.Effect_SourceUriMustBeFileOrPack));
                    } 

                    stream = WpfWebRequestHelper.CreateRequestAndGetResponseStream(newUri); 
                } 

                LoadPixelShaderFromStreamIntoMemory(stream); 
            }
            finally
            {
                if (stream != null) 
                {
                    stream.Dispose(); 
                } 
            }
        } 

        /// 
        /// Reads the byte code for the pixel shader into a local byte array. If the stream is null, the byte array
        /// will be empty (length 0). The compositor will use an identity shader. 
        /// 
        ///  
        /// SecurityCritical - because this method sets the critical shader byte code data. 
        /// TreatAsSafe - Demands UI window permission which enforces that the caller is trusted.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void LoadPixelShaderFromStreamIntoMemory(Stream source)
        {
            SecurityHelper.DemandUIWindowPermission(); 

            _shaderBytecode = new SecurityCriticalData(null); 
 
            if (source != null)
            { 
                if (!source.CanSeek)
                {
                    throw new InvalidOperationException(SR.Get(SRID.Effect_ShaderSeekableStream));
                } 

                int len = (int)source.Length;  // only works on seekable streams. 
 
                if (len % sizeof(int) != 0)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.Effect_ShaderBytecodeSize));
                }

                BinaryReader br = new BinaryReader(source); 
                _shaderBytecode = new SecurityCriticalData(new byte[len]);
                int lengthRead = br.Read(_shaderBytecode.Value, 0, (int)len); 
 
                //
                // The first 4 bytes contain version info in the form of 
                // [Minor][Major][xx][xx]
                //
                if (_shaderBytecode.Value != null && _shaderBytecode.Value.Length > 3)
                { 
                    ShaderMajorVersion = _shaderBytecode.Value[1];
                    ShaderMinorVersion = _shaderBytecode.Value[0]; 
                } 
                else
                { 
                    ShaderMajorVersion = ShaderMinorVersion = 0;
                }

                Debug.Assert(len == lengthRead); 
            }
 
            // We received new stream data. Need to register for a async update to update the composition 
            // engine.
            RegisterForAsyncUpdateResource(); 

            //
            // Notify any ShaderEffects listening that the bytecode changed.
            // The bytecode may have changed from a ps_3_0 shader to a ps_2_0 shader, and any 
            // ShaderEffects using this PixelShader need to check that they are using only
            // registers that are valid in ps_2_0. 
            // 
            if (_shaderBytecodeChanged != null)
            { 
                _shaderBytecodeChanged(this, null);
            }
        }
 

        ///  
        ///     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)) 
            {
                checked 
                {
                    DUCE.MILCMD_PIXELSHADER data;
                    data.Type = MILCMD.MilCmdPixelShader;
                    data.Handle = _duceResource.GetHandle(channel); 
                    data.PixelShaderBytecodeSize = (_shaderBytecode.Value == null) ? 0 : (uint)(_shaderBytecode.Value).Length;
                    data.ShaderRenderMode = ShaderRenderMode; 
                    data.CompileSoftwareShader = CompositionResourceManager.BooleanToUInt32(!(ShaderMajorVersion == 3 && ShaderMinorVersion == 0)); 

                    unsafe 
                    {
                        channel.BeginCommand(
                            (byte*)&data,
                            sizeof(DUCE.MILCMD_PIXELSHADER), 
                            (int)data.PixelShaderBytecodeSize);   // extra data
 
                            if (data.PixelShaderBytecodeSize > 0) 
                            {
                                fixed (byte *pPixelShaderBytecode = _shaderBytecode.Value) 
                                {
                                    channel.AppendCommandData(pPixelShaderBytecode, (int)data.PixelShaderBytecodeSize);
                                }
                            } 
                    }
                } 
 
                channel.EndCommand();
            } 
        }

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

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

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


        /// 
        /// Implementation of Freezable.GetCurrentValueAsFrozenCore. 
        /// 
        ///  
        protected override void GetCurrentValueAsFrozenCore(Freezable sourceFreezable) 
        {
            PixelShader shader = (PixelShader)sourceFreezable; 
            base.GetCurrentValueAsFrozenCore(sourceFreezable);
            CopyCommon(shader);
        }
 
        /// 
        /// Clones values that do not have corresponding DPs. 
        ///  
        /// 
        ///  
        /// SecurityCritical - critical because it access the shader byte code which is a critical resource.
        /// TreatAsSafe - this API is not dangereous (and could be exposed publicly) because it copies the shader
        /// byte code from one PixelShader to another. Since the byte code is marked security critical, the source's byte
        /// code is trusted (verified or provided by a trusted caller). There is also no way to modify the byte code during 
        /// the copy.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void CopyCommon(PixelShader shader)
        { 
            byte[] sourceBytecode = shader._shaderBytecode.Value;
            byte[] destinationBytecode = null;

            if (sourceBytecode != null) 
            {
                destinationBytecode = new byte[sourceBytecode.Length]; 
                sourceBytecode.CopyTo(destinationBytecode, 0); 
            }
 
            _shaderBytecode = new SecurityCriticalData(destinationBytecode);
        }

        ///  
        /// We need to ensure that _shaderByteCode contains only trusted data/shader byte code. This can be
        /// achieved via two means: 
        /// 1) Verify the byte code to be safe to run on the GPU. 
        /// 2) The shader byte code has been provided by a trusted source.
        /// Currently 1) is not possible since we have no means to verify shader byte code. Therefore we 
        /// currently require that byte code provided to us can only come from a trusted source.
        /// 
        private SecurityCriticalData _shaderBytecode;
 
        //
        // Introduced with ps_3_0 for ShaderEffect's use 
        // 
        // The scenario is setting up a ShaderEffect with a PixelShader containing a ps_3_0 shader,
        // setting a ps_3_0 only register (int, bool, or float registers 32 and above), then using 
        // ShaderEffect.PixelShader.UriSource (or SetStreamSource) to swap the ps_3_0 shader out
        // for a ps_2_0 one. Now there's a value in a register that doesn't exist in ps_2_0.
        //
        // The fix is to have ShaderEffect listen for this event on its PixelShader, and verifying 
        // that no invalid registers are used when switching a ps_3_0 register to a ps_2_0 one.
        // 
        internal event EventHandler _shaderBytecodeChanged; 
    }
} 


// 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