static void TestComputeHistogram()

in winrt/test.internal/graphics/CanvasImageUnitTests.cpp [651:822]


    static void TestComputeHistogram(float dpi)
    {
        auto factory = Make<CanvasImageFactory>();
        auto canvasDevice = Make<StubCanvasDevice>();
        auto d2dContext = Make<MockD2DDeviceContext>();
        auto histogramEffect = Make<MockD2DEffect>();
        auto atlasEffect = Make<MockD2DEffect>();
        auto d2dBitmap = Make<StubD2DBitmap>(D2D1_BITMAP_OPTIONS_NONE, dpi);
        auto canvasBitmap = CreateStubCanvasBitmap(nullptr, d2dBitmap.Get());
        ComPtr<MockD2DEffectThatCountsCalls> dpiCompensator;
        Rect rect{ 1, 2, 3, 4 };
        auto channelSelect = EffectChannelSelect::Green;
        const int numBins = 42;
        ComArray<float> result;

        canvasDevice->GetResourceCreationDeviceContextMethod.SetExpectedCalls(1, [&]
        {
            return DeviceContextLease(d2dContext);
        });

        canvasDevice->LeaseHistogramEffectMethod.SetExpectedCalls(1, [&](ID2D1DeviceContext* context)
        {
            Assert::IsTrue(IsSameInstance(context, d2dContext.Get()));
            return CanvasDevice::HistogramAndAtlasEffects{ histogramEffect, atlasEffect };
        });

        canvasDevice->ReleaseHistogramEffectMethod.SetExpectedCalls(1, [&](CanvasDevice::HistogramAndAtlasEffects releasing)
        {
            Assert::IsTrue(IsSameInstance(histogramEffect.Get(), releasing.HistogramEffect.Get()));
            Assert::IsTrue(IsSameInstance(atlasEffect.Get(), releasing.AtlasEffect.Get()));
        });

        atlasEffect->MockGetOutput = [&](ID2D1Image** output)
        {
            atlasEffect.CopyTo(output);
        };

        int setAtlasInputCallCount = 0;

        atlasEffect->MockSetInput = [&](UINT32 index, ID2D1Image* input)
        {
            Assert::AreEqual(0u, index);

            switch (setAtlasInputCallCount++)
            {
            case 0:
                if (dpiCompensator)
                    Assert::IsTrue(IsSameInstance(dpiCompensator.Get(), input));
                else
                    Assert::IsTrue(IsSameInstance(d2dBitmap.Get(), input));
                break;

            case 1:
                Assert::IsNull(input);
                break;

            default:
                Assert::Fail();
            }
        };

        int setAtlasValueCallCount = 0;

        atlasEffect->MockSetValue = [&](UINT32 index, D2D1_PROPERTY_TYPE type, CONST BYTE* data, UINT32 dataSize)
        {
            switch (setAtlasValueCallCount++)
            {
            case 0:
                Assert::AreEqual<uint32_t>(D2D1_ATLAS_PROP_INPUT_RECT, index);
                Assert::AreEqual<size_t>(sizeof(D2D1_RECT_F), dataSize);
                Assert::AreEqual(*reinterpret_cast<D2D1_RECT_F const*>(data), ToD2DRect(rect));
                break;

            default:
                Assert::Fail();
            }

            return S_OK;
        };

        int setHistogramInputCallCount = 0;

        histogramEffect->MockSetInput = [&](UINT32 index, ID2D1Image* input)
        {
            Assert::AreEqual(0u, index);

            switch (setHistogramInputCallCount++)
            {
            case 0:
                Assert::IsTrue(IsSameInstance(atlasEffect.Get(), input));
                break;

            default:
                Assert::Fail();
            }
        };

        int setHistogramValueCallCount = 0;

        histogramEffect->MockSetValue = [&](UINT32 index, D2D1_PROPERTY_TYPE type, CONST BYTE* data, UINT32 dataSize)
        {
            switch (setHistogramValueCallCount++)
            {
            case 0:
                Assert::AreEqual<uint32_t>(D2D1_HISTOGRAM_PROP_CHANNEL_SELECT, index);
                Assert::AreEqual<size_t>(sizeof(int), dataSize);
                Assert::AreEqual(*reinterpret_cast<int const*>(data), static_cast<int>(channelSelect));
                break;

            case 1:
                Assert::AreEqual<uint32_t>(D2D1_HISTOGRAM_PROP_NUM_BINS, index);
                Assert::AreEqual<size_t>(sizeof(int), dataSize);
                Assert::AreEqual(*reinterpret_cast<int const*>(data), numBins);
                break;

            default:
                Assert::Fail();
            }

            return S_OK;
        };

        histogramEffect->MockGetValue = [&](UINT32 index, D2D1_PROPERTY_TYPE, BYTE*, UINT32 dataSize)
        {
            Assert::AreEqual<uint32_t>(D2D1_HISTOGRAM_PROP_HISTOGRAM_OUTPUT, index);
            Assert::AreEqual<size_t>(numBins * sizeof(float), dataSize);

            return S_OK;
        };

        if (dpi != DEFAULT_DPI)
        {
            d2dContext->CreateEffectMethod.SetExpectedCalls(1, [&](IID const& iid, ID2D1Effect** effect)
            {
                Assert::AreEqual(CLSID_D2D1DpiCompensation, iid);
                Assert::IsNull(dpiCompensator.Get());
                
                dpiCompensator = Make<MockD2DEffectThatCountsCalls>();
                
                dpiCompensator->MockGetOutput = [&](ID2D1Image** output)
                {
                    dpiCompensator.CopyTo(output);
                };

                return dpiCompensator.CopyTo(effect);
            });
        }

        d2dContext->BeginDrawMethod.SetExpectedCalls(1);
        d2dContext->EndDrawMethod.SetExpectedCalls(1);

        d2dContext->DrawImageMethod.SetExpectedCalls(1, [&](ID2D1Image* image, D2D1_POINT_2F const*, D2D1_RECT_F const*, D2D1_INTERPOLATION_MODE actualInterpolation, D2D1_COMPOSITE_MODE)
        {
            Assert::IsTrue(IsSameInstance(histogramEffect.Get(), image));
        });

        ThrowIfFailed(factory->ComputeHistogram(canvasBitmap.Get(), rect, canvasDevice.Get(), channelSelect, numBins, result.GetAddressOfSize(), result.GetAddressOfData()));

        Assert::AreEqual(2, setAtlasInputCallCount);
        Assert::AreEqual(1, setAtlasValueCallCount);
        
        Assert::AreEqual(1, setHistogramInputCallCount);
        Assert::AreEqual(2, setHistogramValueCallCount);

        if (dpiCompensator)
        {
            Assert::IsTrue(IsSameInstance(d2dBitmap.Get(), dpiCompensator->m_inputs[0].Get()));

            Assert::AreEqual(sizeof(Vector2), dpiCompensator->m_properties[D2D1_DPICOMPENSATION_PROP_INPUT_DPI].size());
            Assert::AreEqual(Vector2{ dpi, dpi }, *reinterpret_cast<Vector2*>(dpiCompensator->m_properties[D2D1_DPICOMPENSATION_PROP_INPUT_DPI].data()));
        }
    }