File: Core\CSharp\System\Windows\Media\Renderer.cs
Project: wpf\src\PresentationCore.csproj (PresentationCore)
//------------------------------------------------------------------------------
//
// <copyright file="Renderer.cs" company="Microsoft">
//    Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// Description:
//      Though called "Renderer", this is used only for the 'rendering
//      to a BitmapImage' case, and not when rendering to an HwndTarget.
//
//------------------------------------------------------------------------------
 
using System;
using System.Windows;
using System.Collections.Generic;
using System.Windows.Threading;
 
using System.Diagnostics;
 
using MS.Internal;
using System.Windows.Media;
using System.Windows.Media.Composition;
 
using MS.Win32;
using System.Security;
using System.Security.Permissions;
 
namespace System.Windows.Media
{
    static internal class Renderer
    {
 
        /// <SecurityNote>
        /// Critical - unmanaged pointer arguments, access critical resources, calls unmanaged code
        /// </SecurityNote>
        [SecurityCritical]
        static public void Render(
            IntPtr pRenderTarget,
            DUCE.Channel channel,
            Visual visual,
            int width,
            int height,
            double dpiX,
            double dpiY)
        {
            Render(pRenderTarget, channel, visual, width, height, dpiX, dpiY, Matrix.Identity, Rect.Empty);
        }
 
        /// <summary>
        /// If fRenderForBitmapEffect is true, the method calls special methods on visual
        /// to render it specifically for an effect to be applied to it. It excludes
        /// properties such as transform, clip, offset and guidelines.
        /// </summary>
        /// <SecurityNote>
        /// Critical - unmanaged pointer arguments, access critical resources, calls unmanaged code
        /// </SecurityNote>
        [SecurityCritical]
        static internal void Render(
            IntPtr pRenderTarget,
            DUCE.Channel channel,
            Visual visual,
            int width,
            int height,
            double dpiX,
            double dpiY,
            Matrix worldTransform,
            Rect windowClip
            )
        {
            DUCE.Resource target =
                new DUCE.Resource();
            DUCE.Resource root =
                new DUCE.Resource();
 
            DUCE.ResourceHandle targetHandle = DUCE.ResourceHandle.Null;
            DUCE.ResourceHandle rootHandle = DUCE.ResourceHandle.Null;
 
            Matrix deviceTransform = new Matrix(
                dpiX * (1.0 / 96.0),    0,
                0,                      dpiY * (1.0 / 96.0),
                0,                      0);
 
            deviceTransform = worldTransform * deviceTransform;
            MatrixTransform mtDeviceTransform = new MatrixTransform(deviceTransform);
 
            DUCE.ResourceHandle deviceTransformHandle =
                ((DUCE.IResource)mtDeviceTransform).AddRefOnChannel(channel);
 
 
            try
            {
                // ------------------------------------------------------------
                //   Create the composition target and root visual resources.
 
                target.CreateOrAddRefOnChannel(target, channel, DUCE.ResourceType.TYPE_GENERICRENDERTARGET);
                targetHandle = target.Handle;
 
                DUCE.CompositionTarget.PrintInitialize(
                    targetHandle,
                    pRenderTarget,
                    width,
                    height,
                    channel);
 
                root.CreateOrAddRefOnChannel(root, channel, DUCE.ResourceType.TYPE_VISUAL);
                rootHandle = root.Handle;
 
                DUCE.CompositionNode.SetTransform(
                    rootHandle,
                    deviceTransformHandle,
                    channel);
 
                DUCE.CompositionTarget.SetRoot(
                    targetHandle,
                    rootHandle,
                    channel);
 
                channel.CloseBatch();
                channel.Commit();
 
 
                // ------------------------------------------------------------
                //   Render the freshly created target.
 
                RenderContext renderContext = new RenderContext();
 
                renderContext.Initialize(channel, rootHandle);
 
                visual.Precompute();
 
                visual.Render(renderContext, 0);
 
                // ------------------------------------------------------------
                //   Flush the channel and present the composition target.
 
                channel.CloseBatch();
                channel.Commit();
                channel.Present();
 
                MediaContext mediaContext = MediaContext.CurrentMediaContext;
                mediaContext.NotifySyncChannelMessage(channel);
 
            }
            finally
            {
                // ------------------------------------------------------------
                //   Clean up and release the root visual.
 
                if (!rootHandle.IsNull)
                {
                    DUCE.CompositionNode.RemoveAllChildren(
                        rootHandle,
                        channel);
 
                    ((DUCE.IResource)visual).ReleaseOnChannel(channel);
 
                    root.ReleaseOnChannel(channel);
                }
 
 
                // ------------------------------------------------------------
                //   Release the world transform.
 
                if (!deviceTransformHandle.IsNull)
                {
                    ((DUCE.IResource)mtDeviceTransform).ReleaseOnChannel(channel);
                }
 
 
                // ------------------------------------------------------------
                //   Clean up and release the composition target.
 
                if (!targetHandle.IsNull)
                {
                    DUCE.CompositionTarget.SetRoot(
                        targetHandle,
                        DUCE.ResourceHandle.Null,
                        channel);
 
                    target.ReleaseOnChannel(channel);
                }
 
                // ------------------------------------------------------------
                //   Flush the channel and present the composition target.
 
                channel.CloseBatch();
                channel.Commit();
                channel.Present();
 
                MediaContext mediaContext = MediaContext.CurrentMediaContext;
                mediaContext.NotifySyncChannelMessage(channel);
            }
        }
    }
}