How to draw WinRT::Windows::UI::Composition::Visual on bitmap

213 Views Asked by At

I am trying to draw cppwinrt Lottie animation into my Direct2D app, but can't understand how to do this...

It's possible draw this animation (WinRT::Windows::UI::Composition::Visual) and get data without xaml::Controls and windows?

I have loaded Lottie animation:

auto bmv = winrt::make<AnimatedVisuals::LottieLogo1>();
auto avptr = bmv.TryCreateAnimatedVisual(compositor, diags);
        
m_visual = avptr.RootVisual();

auto progressAnimation = compositor.CreateScalarKeyFrameAnimation();
progressAnimation.Duration(std::chrono::seconds(5));
        progressAnimation.IterationBehavior(winrt::Windows::UI::Composition::AnimationIterationBehavior::Forever);
        progressAnimation.Direction(winrt::Windows::UI::Composition::AnimationDirection::Alternate);
auto linearEasing = compositor.CreateLinearEasingFunction();
progressAnimation.InsertKeyFrame(0, 0, linearEasing);
progressAnimation.InsertKeyFrame(1, 1, linearEasing);

m_visual.Properties().StartAnimation(L"Progress", progressAnimation);

and now I need to draw this animation on the d2dbitmap or get pixels.

I tried to create the framepool but frames not arrived:

winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice m_device;{auto d3dDevice = CreateD3DDevice();auto dxgiDevice = d3dDevice.as<IDXGIDevice>();if (dxgiDevice){hr = CreateDirect3DDevice(dxgiDevice.get(), &m_device);}}
    m_framePool = winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool::Create(
        m_device,
        winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
        3,
        winrt::Windows::Graphics::SizeInt32({ 400, 400 }));
m_session = m_framePool.CreateCaptureSession(winrt::Windows::Graphics::Capture::GraphicsCaptureItem::CreateFromVisual(m_visual));
m_frameArrived = m_framePool.FrameArrived(winrt::auto_revoke, { this, &CLottie::OnFrameArrived });
m_session.StartCapture();

It's possible draw this animation and get data without xaml::Controls and windows?

UPDATE:

auto controller = CreateDispatcherQueueController();

winrt::Windows::UI::Composition::Compositor compositor{};   

CComPtr<ABI::Windows::UI::Composition::ICompositorInterop> compositorInterop;

        hr = winrt::get_unknown(compositor)->QueryInterface(&compositorInterop);
        winrt::com_ptr<ABI::Windows::UI::Composition::ICompositionGraphicsDevice> device = nullptr;

        hr = compositorInterop->CreateGraphicsDevice(direct2dDevice, device.put());
        auto gDevice = device.as<winrt::Windows::UI::Composition::CompositionGraphicsDevice>();

        winrt::Windows::Foundation::Size surfaceSize{ 400, 400 };
        winrt::Windows::UI::Composition::CompositionDrawingSurface surface = gDevice.CreateDrawingSurface(surfaceSize,
            winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
            winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);

        auto brush = compositor.CreateSurfaceBrush(surface);
        float width = 400.0f, height = 400.0f;

        winrt::Windows::UI::Composition::SpriteVisual visual = compositor.CreateSpriteVisual();
        visual.Brush(brush);
        visual.Size({ width, height });

        winrt::Windows::UI::Composition::ShapeVisual shape = compositor.CreateShapeVisual();
        shape.Size({ 100.0f,100.0f });
        auto circleGeometry = compositor.CreateEllipseGeometry();
        circleGeometry.Radius(winrt::Windows::Foundation::Numerics::float2(30, 30));
        auto circleShape = compositor.CreateSpriteShape(circleGeometry);
        circleShape.FillBrush(compositor.CreateColorBrush(winrt::Windows::UI::Colors::Orange()));
        circleShape.Offset(winrt::Windows::Foundation::Numerics::float2(50, 50));
        shape.Shapes().Append(circleShape);
        visual.Children().InsertAtTop(shape);

        auto surfaceInterop = surface.as<ABI::Windows::UI::Composition::ICompositionDrawingSurfaceInterop>();

        CComPtr<ID2D1DeviceContext> dc;
        POINT offset = {};

        hr = surfaceInterop->BeginDraw(nullptr,
            __uuidof(dc),
            reinterpret_cast<void**>(&dc),
            &offset);

        CComPtr<ID2D1Bitmap1> bitmap = nullptr;
        D2D1_BITMAP_PROPERTIES1 prop;
        prop.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
        prop.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
        prop.dpiX = 96;
        prop.dpiY = 96;
        prop.bitmapOptions = D2D1_BITMAP_OPTIONS_CPU_READ | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
        prop.colorContext = NULL;

        hr = dc->CreateBitmap(D2D1::SizeU(width, height), NULL, 0, prop, &bitmap);

        hr = bitmap->CopyFromRenderTarget(NULL, dc, NULL);

        hr = surfaceInterop->EndDraw();
0

There are 0 best solutions below