/*
 * 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"

#include "GrContextPriv.h"
#include "GrPendingIOResource.h"
#include "GrProxyProvider.h"
#include "GrRenderTargetProxy.h"
#include "GrResourceProvider.h"
#include "GrSurfaceProxy.h"
#include "GrTexture.h"
#include "GrTextureProxy.h"

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

    return -1; // no backing GrSurface
}

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

    return fPendingReads;
}

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

    return fPendingWrites;
}

static const int kWidthHeight = 128;

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

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

static sk_sp<GrTextureProxy> make_deferred(GrProxyProvider* proxyProvider, const GrCaps* caps) {
    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = kWidthHeight;
    desc.fHeight = kWidthHeight;
    desc.fConfig = kRGBA_8888_GrPixelConfig;

    const GrBackendFormat format = caps->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
    return proxyProvider->createProxy(format, desc, kBottomLeft_GrSurfaceOrigin,
                                      SkBackingFit::kApprox, SkBudgeted::kYes,
                                      GrInternalSurfaceFlags::kNoPendingIO);
}

static sk_sp<GrTextureProxy> make_wrapped(GrProxyProvider* proxyProvider, const GrCaps* caps) {
    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = kWidthHeight;
    desc.fHeight = kWidthHeight;
    desc.fConfig = kRGBA_8888_GrPixelConfig;

    return proxyProvider->testingOnly_createInstantiatedProxy(
            desc, kBottomLeft_GrSurfaceOrigin, SkBackingFit::kExact, SkBudgeted::kNo);
}

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

    for (auto make : { make_deferred, make_wrapped }) {
        // A single write
        {
            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider, caps));
            if (proxy.get()) {
                GrPendingIOResource<GrSurfaceProxy, kWrite_GrIOType> fWrite(proxy.get());

                static const int kExpectedReads = 0;
                static const int kExpectedWrites = 1;

                int backingRefs = proxy->isWrapped_ForTesting() ? 1 : -1;

                check_refs(reporter, proxy.get(), 1, backingRefs, kExpectedReads, kExpectedWrites);

                proxy->instantiate(resourceProvider);

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

        // A single read
        {
            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider, caps));
            if (proxy.get()) {
                GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fRead(proxy.get());

                static const int kExpectedReads = 1;
                static const int kExpectedWrites = 0;

                int backingRefs = proxy->isWrapped_ForTesting() ? 1 : -1;

                check_refs(reporter, proxy.get(), 1, backingRefs, kExpectedReads, kExpectedWrites);

                proxy->instantiate(resourceProvider);

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

        // A single read/write pair
        {
            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider, caps));
            if (proxy.get()) {
                GrPendingIOResource<GrSurfaceProxy, kRW_GrIOType> fRW(proxy.get());

                static const int kExpectedReads = 1;
                static const int kExpectedWrites = 1;

                int backingRefs = proxy->isWrapped_ForTesting() ? 1 : -1;

                check_refs(reporter, proxy.get(), 1, backingRefs, kExpectedReads, kExpectedWrites);

                proxy->instantiate(resourceProvider);

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

        // Multiple normal refs
        {
            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider, caps));
            if (proxy.get()) {
                proxy->ref();
                proxy->ref();

                static const int kExpectedReads = 0;
                static const int kExpectedWrites = 0;

                int backingRefs = proxy->isWrapped_ForTesting() ? 3 : -1;

                check_refs(reporter, proxy.get(), 3, backingRefs, kExpectedReads, kExpectedWrites);

                proxy->instantiate(resourceProvider);

                // In the deferred case, this checks that the refs transferred to the GrSurface
                check_refs(reporter, proxy.get(), 3, 3, kExpectedReads, kExpectedWrites);

                proxy->unref();
                proxy->unref();
            }
        }

        // Continue using (reffing) proxy after instantiation
        {
            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider, caps));
            if (proxy.get()) {
                proxy->ref();

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

                static const int kExpectedWrites = 1;

                int backingRefs = proxy->isWrapped_ForTesting() ? 2 : -1;

                check_refs(reporter, proxy.get(), 2, backingRefs, 0, kExpectedWrites);

                proxy->instantiate(resourceProvider);

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

                proxy->unref();
                check_refs(reporter, proxy.get(), 1, 1, 0, kExpectedWrites);

                GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fRead(proxy.get());
                check_refs(reporter, proxy.get(), 1, 1, 1, kExpectedWrites);
            }
        }
    }
}
