/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This is a GPU-backend specific test.

#include "Test.h"

#if SK_SUPPORT_GPU
#include "GrRenderTargetPriv.h"
#include "GrRenderTargetProxy.h"
#include "GrResourceProvider.h"
#include "GrSurfaceProxy.h"
#include "GrTextureProxy.h"

int32_t GrIORefProxy::getProxyRefCnt_TestOnly() const {
    return fRefCnt;
}

int32_t GrIORefProxy::getBackingRefCnt_TestOnly() const {
    if (fTarget) {
        return fTarget->fRefCnt;
    }

    return fRefCnt;
}

int32_t GrIORefProxy::getPendingReadCnt_TestOnly() const {
    if (fTarget) {
        SkASSERT(!fPendingReads);
        return fTarget->fPendingReads;
    }

    return fPendingReads;
}

int32_t GrIORefProxy::getPendingWriteCnt_TestOnly() const {
    if (fTarget) {
        SkASSERT(!fPendingWrites);
        return fTarget->fPendingWrites;
    }

    return fPendingWrites;
}

static const int kWidthHeight = 128;

static void check_refs(skiatest::Reporter* reporter,
                       GrSurfaceProxy* proxy,
                       int32_t expectedProxyRefs,
                       int32_t expectedBackingRefs,
                       int32_t expectedNumReads,
                       int32_t expectedNumWrites) {
    REPORTER_ASSERT(reporter, proxy->getProxyRefCnt_TestOnly() == expectedProxyRefs);
    REPORTER_ASSERT(reporter, proxy->getBackingRefCnt_TestOnly() == expectedBackingRefs);
    REPORTER_ASSERT(reporter, proxy->getPendingReadCnt_TestOnly() == expectedNumReads);
    REPORTER_ASSERT(reporter, proxy->getPendingWriteCnt_TestOnly() == expectedNumWrites);

    SkASSERT(proxy->getProxyRefCnt_TestOnly() == expectedProxyRefs);
    SkASSERT(proxy->getBackingRefCnt_TestOnly() == expectedBackingRefs);
    SkASSERT(proxy->getPendingReadCnt_TestOnly() == expectedNumReads);
    SkASSERT(proxy->getPendingWriteCnt_TestOnly() == expectedNumWrites);
}

static sk_sp<GrSurfaceProxy> make_deferred(GrResourceProvider* provider) {
    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = kWidthHeight;
    desc.fHeight = kWidthHeight;
    desc.fConfig = kRGBA_8888_GrPixelConfig;

    return GrSurfaceProxy::MakeDeferred(provider, desc,
                                        SkBackingFit::kApprox, SkBudgeted::kYes);
}

static sk_sp<GrSurfaceProxy> make_wrapped(GrResourceProvider* provider) {
    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = kWidthHeight;
    desc.fHeight = kWidthHeight;
    desc.fConfig = kRGBA_8888_GrPixelConfig;

    sk_sp<GrTexture> tex(provider->createTexture(desc, SkBudgeted::kNo));

    // Flush the IOWrite from the initial discard or it will confuse the later ref count checks
    tex->flushWrites();

    return GrSurfaceProxy::MakeWrapped(std::move(tex));
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ProxyRefTest, reporter, ctxInfo) {
    GrResourceProvider* provider = ctxInfo.grContext()->resourceProvider();
    const GrCaps& caps = *ctxInfo.grContext()->caps();

    // Currently the op itself takes a pending write and the render target op list does as well.
    static const int kWritesForDiscard = 2;
    for (auto make : { make_deferred, make_wrapped }) {
        // A single write
        {
            sk_sp<GrSurfaceProxy> sProxy((*make)(provider));

            GrPendingIOResource<GrSurfaceProxy, kWrite_GrIOType> fWrite(sProxy.get());

            check_refs(reporter, sProxy.get(), 1, 1, 0, 1);

            // In the deferred case, the discard op created on instantiation adds an
            // extra ref and write
            bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() &&
                                       caps.discardRenderTargetSupport();
            int expectedWrites = 1 + (proxyGetsDiscardRef ? kWritesForDiscard : 0);

            sProxy->instantiate(provider);

            // In the deferred case, this checks that the refs transfered to the GrSurface
            check_refs(reporter, sProxy.get(), 1, 1, 0, expectedWrites);
        }

        // A single read
        {
            sk_sp<GrSurfaceProxy> sProxy((*make)(provider));

            GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fRead(sProxy.get());

            check_refs(reporter, sProxy.get(), 1, 1, 1, 0);

            // In the deferred case, the discard op created on instantiation adds an
            // extra ref and write
            bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() &&
                                       caps.discardRenderTargetSupport();
            int expectedWrites = proxyGetsDiscardRef ? kWritesForDiscard : 0;

            sProxy->instantiate(provider);

            // In the deferred case, this checks that the refs transfered to the GrSurface
            check_refs(reporter, sProxy.get(), 1, 1, 1, expectedWrites);
        }

        // A single read/write pair
        {
            sk_sp<GrSurfaceProxy> sProxy((*make)(provider));

            GrPendingIOResource<GrSurfaceProxy, kRW_GrIOType> fRW(sProxy.get());

            check_refs(reporter, sProxy.get(), 1, 1, 1, 1);

            // In the deferred case, the discard op created on instantiation adds an
            // extra ref and write
            bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() &&
                                       caps.discardRenderTargetSupport();
            int expectedWrites = 1 + (proxyGetsDiscardRef ? kWritesForDiscard : 0);

            sProxy->instantiate(provider);

            // In the deferred case, this checks that the refs transferred to the GrSurface
            check_refs(reporter, sProxy.get(), 1, 1, 1, expectedWrites);
        }

        // Multiple normal refs
        {
            sk_sp<GrSurfaceProxy> sProxy((*make)(provider));
            sProxy->ref();
            sProxy->ref();

            check_refs(reporter, sProxy.get(), 3, 3, 0, 0);

            bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() &&
                                       caps.discardRenderTargetSupport();
            int expectedWrites = proxyGetsDiscardRef ? kWritesForDiscard : 0;

            sProxy->instantiate(provider);

            // In the deferred case, this checks that the refs transferred to the GrSurface
            check_refs(reporter, sProxy.get(), 3, 3, 0, expectedWrites);

            sProxy->unref();
            sProxy->unref();
        }

        // Continue using (reffing) proxy after instantiation
        {
            sk_sp<GrSurfaceProxy> sProxy((*make)(provider));
            sProxy->ref();

            GrPendingIOResource<GrSurfaceProxy, kWrite_GrIOType> fWrite(sProxy.get());

            check_refs(reporter, sProxy.get(), 2, 2, 0, 1);

            bool proxyGetsDiscardRef = !sProxy->isWrapped_ForTesting() &&
                                       caps.discardRenderTargetSupport();
            int expectedWrites = 1 + (proxyGetsDiscardRef ? kWritesForDiscard : 0);

            sProxy->instantiate(provider);

            // In the deferred case, this checks that the refs transfered to the GrSurface
            check_refs(reporter, sProxy.get(), 2, 2, 0, expectedWrites);

            sProxy->unref();
            check_refs(reporter, sProxy.get(), 1, 1, 0, expectedWrites);

            GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fRead(sProxy.get());
            check_refs(reporter, sProxy.get(), 1, 1, 1, expectedWrites);
        }
    }
}
#endif
