CompositionDrawingSurface CompositionDrawingSurface CompositionDrawingSurface Class

Definition

A drawing surface for interoperation with Direct2D or Direct3D.

public class CompositionDrawingSurface : CompositionObject, ICompositionDrawingSurface, ICompositionDrawingSurface2, ICompositionSurfacepublic class CompositionDrawingSurface : CompositionObject, ICompositionDrawingSurface, ICompositionDrawingSurface2, ICompositionSurfacePublic Class CompositionDrawingSurface Inherits CompositionObject Implements ICompositionDrawingSurface, ICompositionDrawingSurface2, ICompositionSurface
Inheritance
CompositionDrawingSurfaceCompositionDrawingSurfaceCompositionDrawingSurface
Attributes
Windows 10 requirements
Device family
Windows 10 (introduced v10.0.10586.0)
API contract
Windows.Foundation.UniversalApiContract (introduced v2)

Inherited Members

Inherited methods

Inherited properties

Remarks

Examples


#include "stdafx.h"

using namespace Microsoft::WRL;
using namespace Windows::Foundation;
using namespace Windows::Graphics::DirectX;
using namespace Windows::UI::Composition;

// This is an app-provided helper to render lines of text
class SampleText
{
private:
    // The text to draw
    ComPtr<IDWriteTextLayout> _text;

    // The composition surface that we use in the visual tree
    ComPtr<ICompositionDrawingSurfaceInterop> _drawingSurfaceInterop;

    // The device that owns the surface
    ComPtr<ICompositionGraphicsDevice> _compositionGraphicsDevice;

    // For managing our event notifier
    EventRegistrationToken _deviceReplacedEventToken;

public:
    SampleText(IDWriteTextLayout* text, ICompositionGraphicsDevice* compositionGraphicsDevice) :
        _text(text),
        _compositionGraphicsDevice(compositionGraphicsDevice)
    {
        // Create the surface just big enough to hold the formatted text block.
        DWRITE_TEXT_METRICS metrics;
        FailFastOnFailure(text->GetMetrics(&metrics));
        Windows::Foundation::Size surfaceSize = { metrics.width, metrics.height };
        ComPtr<ICompositionDrawingSurface> drawingSurface = _compositionGraphicsDevice->CreateDrawingSurface(
            surfaceSize,
            DirectXPixelFormat::DirectXPixelFormat_B8G8R8A8UIntNormalized,
            DirectXAlphaMode::DirectXAlphaMode_Ignore);

        // Cache the interop pointer, since that's what we always use.
        FailFastOnFailure(drawingSurface.As(&_drawingSurfaceInterop));

        // Draw the text
        DrawText();

        // If the rendering device is lost, the application will recreate and replace it. We then
        // own redrawing our pixels.
        FailFastOnFailure(_compositionGraphicsDevice->add_RenderingDeviceReplaced(
            Callback<RenderingDeviceReplacedEventHandler>([this](
                ICompositionGraphicsDevice* source, IRenderingDeviceReplacedEventArgs* args)
                -> HRESULT
            {
                // Draw the text again
                DrawText();
                return S_OK;
            }).Get(),
            &_deviceReplacedEventToken));
    }

    ~SampleText()
    {
        FailFastOnFailure(_compositionGraphicsDevice->remove_RenderingDeviceReplaced(
            _deviceReplacedEventToken));
    }

    // Return the underlying surface to the caller
    ComPtr<ICompositionSurface> get_Surface()
    {
        // To the caller, the fact that we have a drawing surface is an implementation detail.
        // Return the base interface instead
        ComPtr<ICompositionSurface> surface;
        FailFastOnFailure(_drawingSurfaceInterop.As(&surface));
        return surface;
    }

private:
    // We may detect device loss on BeginDraw calls. This helper handles this condition or other
    // errors.
    bool CheckForDeviceRemoved(HRESULT hr)
    {
        if (SUCCEEDED(hr))
        {
            // Everything is fine -- go ahead and draw
            return true;
        }
        else if (hr == DXGI_ERROR_DEVICE_REMOVED)
        {
            // We can't draw at this time, but this failure is recoverable. Just skip drawing for
            // now. We will be asked to draw again once the Direct3D device is recreated
            return false;
        }
        else
        {
            // Any other error is unexpected and, therefore, fatal
            FailFast();
        }
    }

    // Renders the text into our composition surface
    void DrawText()
    {
        // Begin our update of the surface pixels. If this is our first update, we are required
        // to specify the entire surface, which nullptr is shorthand for (but, as it works out,
        // any time we make an update we touch the entire surface, so we always pass nullptr).
        ComPtr<ID2D1DeviceContext> d2dDeviceContext;
        POINT offset;
        if (CheckForDeviceRemoved(_drawingSurfaceInterop->BeginDraw(nullptr,
            __uuidof(ID2D1DeviceContext), &d2dDeviceContext, &offset)))
        {
            // Create a solid color brush for the text. A more sophisticated application might want
            // to cache and reuse a brush across all text elements instead, taking care to recreate
            // it in the event of device removed.
            ComPtr<ID2D1SolidColorBrush> brush;
            FailFastOnFailure(d2dDeviceContext->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::Black, 1.0f), &brush));

            // Draw the line of text at the specified offset, which corresponds to the top-left
            // corner of our drawing surface. Notice we don't call BeginDraw on the D2D device
            // context; this has already been done for us by the composition API.
            d2dDeviceContext->DrawTextLayout(D2D1::Point2F(offset.x, offset.y), _text.Get(),
                brush.Get());

            // Our update is done. EndDraw never indicates rendering device removed, so any
            // failure here is unexpected and, therefore, fatal.
            FailFastOnFailure(_drawingSurfaceInterop->EndDraw());
        }
    }
};

class SampleApp
{
    ComPtr<ICompositor> _compositor;
    ComPtr<ID2D1Device> _d2dDevice;
    ComPtr<ICompositionGraphicsDevice> _compositionGraphicsDevice;
    std::vector<ComPtr<SampleText>> _textSurfaces;

public:
    // Run once when the application starts up
    void Initialize(ICompositor* compositor)
    {
        // Cache the compositor (created outside of this method)
        _compositor = compositor;

        // Create a Direct2D device (helper implementation not shown here)
        FailFastOnFailure(CreateDirect2DDevice(&_d2dDevice));

        // To create a composition graphics device, we need to QI for another interface
        ComPtr<ICompositorInterop> compositorInterop;
        FailFastOnFailure(_compositor.As(&compositorInterop));

        // Create a graphics device backed by our D3D device
        FailFastOnFailure(compositorInterop->CreateGraphicsDevice(
            _d2dDevice.Get(),
            &_compositionGraphicsDevice));
    }

    // Called when Direct3D signals the device lost event
    void OnDirect3DDeviceLost()
    {
        // Create a new device
        FailFastOnFailure(CreateDirect2DDevice(_d2dDevice.ReleaseAndGetAddressOf()));

        // Restore our composition graphics device to good health
        ComPtr<ICompositionGraphicsDeviceInterop> compositionGraphicsDeviceInterop;
        FailFastOnFailure(_compositionGraphicsDevice.As(&compositionGraphicsDeviceInterop));
        FailFastOnFailure(compositionGraphicsDeviceInterop->SetRenderingDevice(_d2dDevice.Get()));
    }

    // Create a surface that is asynchronously filled with an image
    ComPtr<ICompositionSurface> CreateSurfaceFromTextLayout(IDWriteTextLayout* text)
    {
        // Create our wrapper object that will handle downloading and decoding the image (assume
        // throwing new here)
        SampleText* textSurface = new SampleText(text, _compositionGraphicsDevice.Get());

        // Keep our image alive
        _textSurfaces.push_back(textSurface);

        // The caller is only interested in the underlying surface
        return textSurface->get_Surface();
    }

    // Create a visual that holds an image
    ComPtr<IVisual> CreateVisualFromTextLayout(IDWriteTextLayout* text)
    {
        // Create a sprite visual
        ComPtr<ISpriteVisual> spriteVisual;
        FailFastOnFailure(_compositor->CreateSpriteVisual(&spriteVisual));

        // The sprite visual needs a brush to hold the image
        ComPtr<ICompositionSurfaceBrush> surfaceBrush;
        FailFastOnFailure(_compositor->CreateSurfaceBrushWithSurface(
            CreateSurfaceFromTextLayout(text).Get(),
            &surfaceBrush));

        // Associate the brush with the visual
        ComPtr<ICompositionBrush> brush;
        FailFastOnFailure(surfaceBrush.As(&brush));
        FailFastOnFailure(spriteVisual->put_Brush(brush.Get()));

        // Return the visual to the caller as the base class
        ComPtr<IVisual> visual;
        FailFastOnFailure(spriteVisual.As(&visual));

        return visual;
    }

private:
    // This helper (implementation not shown here) creates a Direct2D device and registers
    // for a device loss notification on the underlying Direct3D device. When that notification is
    // raised, assume the OnDirect3DDeviceLost method is called.
    HRESULT CreateDirect2DDevice(ID2D1Device** ppDevice);
};

Properties

AlphaMode AlphaMode AlphaMode

The alpha mode of the drawing surface.

public DirectXAlphaMode AlphaMode { get; }public DirectXAlphaMode AlphaMode { get; }Public ReadOnly Property AlphaMode As DirectXAlphaMode
Value
DirectXAlphaMode DirectXAlphaMode DirectXAlphaMode

The alpha mode of the drawing surface.

Attributes

PixelFormat PixelFormat PixelFormat

The pixel format of the drawing surface.

public DirectXPixelFormat PixelFormat { get; }public DirectXPixelFormat PixelFormat { get; }Public ReadOnly Property PixelFormat As DirectXPixelFormat
Value
DirectXPixelFormat DirectXPixelFormat DirectXPixelFormat

The pixel format of the drawing surface.

Attributes

Size Size Size

The size of the drawing surface.

public Size Size { get; }public Size Size { get; }Public ReadOnly Property Size As Size
Value
Size Size Size

The size of the drawing surface.

Attributes

SizeInt32 SizeInt32 SizeInt32

The size of the drawing surface.

public SizeInt32 SizeInt32 { get; }public SizeInt32 SizeInt32 { get; }Public ReadOnly Property SizeInt32 As SizeInt32
Value
SizeInt32 SizeInt32 SizeInt32

The size of the drawing surface.

Attributes

Methods

Resize(SizeInt32) Resize(SizeInt32) Resize(SizeInt32)

Resizes the drawing surface to the specified size.

public void Resize(SizeInt32 sizePixels)public void Resize(SizeInt32 sizePixels)Public Function Resize(sizePixels As SizeInt32) As void
Parameters
sizePixels
SizeInt32 SizeInt32 SizeInt32

The new size in pixels for the drawing surface.

Attributes

Scroll(PointInt32) Scroll(PointInt32) Scroll(PointInt32)

Scrolls the drawing surface.

public void Scroll(PointInt32 offset)public void Scroll(PointInt32 offset)Public Function Scroll(offset As PointInt32) As void
Parameters
offset
PointInt32 PointInt32 PointInt32

The scrolling offset.

Attributes

Scroll(PointInt32, RectInt32) Scroll(PointInt32, RectInt32) Scroll(PointInt32, RectInt32)

Scrolls the drawing surface.

public void Scroll(PointInt32 offset, RectInt32 scrollRect)public void Scroll(PointInt32 offset, RectInt32 scrollRect)Public Function Scroll(offset As PointInt32, scrollRect As RectInt32) As void
Parameters
offset
PointInt32 PointInt32 PointInt32

The scrolling offset.

scrollRect
RectInt32 RectInt32 RectInt32

The scrolling rectangle.

Attributes

ScrollWithClip(PointInt32, RectInt32) ScrollWithClip(PointInt32, RectInt32) ScrollWithClip(PointInt32, RectInt32)

Scrolls the drawing surface using the specified clip rectangle.

public void ScrollWithClip(PointInt32 offset, RectInt32 clipRect)public void ScrollWithClip(PointInt32 offset, RectInt32 clipRect)Public Function ScrollWithClip(offset As PointInt32, clipRect As RectInt32) As void
Parameters
offset
PointInt32 PointInt32 PointInt32

The scrolling offset.

clipRect
RectInt32 RectInt32 RectInt32

The clipping rectangle to apply.

Attributes

ScrollWithClip(PointInt32, RectInt32, RectInt32) ScrollWithClip(PointInt32, RectInt32, RectInt32) ScrollWithClip(PointInt32, RectInt32, RectInt32)

Scrolls the drawing surface with the specified clip rectangle.

public void ScrollWithClip(PointInt32 offset, RectInt32 clipRect, RectInt32 scrollRect)public void ScrollWithClip(PointInt32 offset, RectInt32 clipRect, RectInt32 scrollRect)Public Function ScrollWithClip(offset As PointInt32, clipRect As RectInt32, scrollRect As RectInt32) As void
Parameters
offset
PointInt32 PointInt32 PointInt32

The scrolling offset.

clipRect
RectInt32 RectInt32 RectInt32

The clipping rectangle to apply.

scrollRect
RectInt32 RectInt32 RectInt32

The scrolling rectangle.

Attributes