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

#include "src/gpu/ganesh/GrTextureResolveRenderTask.h"

#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrMemoryPool.h"
#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/GrRenderTarget.h"
#include "src/gpu/ganesh/GrResourceAllocator.h"
#include "src/gpu/ganesh/GrTexture.h"

void GrTextureResolveRenderTask::addProxy(GrDrawingManager* drawingMgr,
                                          sk_sp<GrSurfaceProxy> proxyRef,
                                          GrSurfaceProxy::ResolveFlags flags,
                                          const GrCaps& caps) {
    GrSurfaceProxy::ResolveFlags newFlags = flags;
    GrSurfaceProxy* proxy = proxyRef.get();
    Resolve* resolve;
    bool newProxy = false;

    // We might just need to update the flags for an existing dependency.
    if (auto found = std::find(fTargets.begin(), fTargets.end(), proxyRef);
        found != fTargets.end()) {
        size_t index = found - fTargets.begin();
        resolve = &fResolves[index];
        newFlags = ~resolve->fFlags & flags;
        resolve->fFlags |= flags;
    } else {
        // Ensure the last render task that operated on the proxy is closed. That's where msaa and
        // mipmaps should have been marked dirty.
        SkASSERT(!drawingMgr->getLastRenderTask(proxy)
                 || drawingMgr->getLastRenderTask(proxy)->isClosed());
        SkASSERT(GrSurfaceProxy::ResolveFlags::kNone != flags);
        resolve = &fResolves.emplace_back(flags);
        newProxy = true;
    }

    if (GrSurfaceProxy::ResolveFlags::kMSAA & newFlags) {
        GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
        SkASSERT(renderTargetProxy);
        SkASSERT(renderTargetProxy->isMSAADirty());
        resolve->fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
        renderTargetProxy->markMSAAResolved();
    }

    if (GrSurfaceProxy::ResolveFlags::kMipMaps & newFlags) {
        GrTextureProxy* textureProxy = proxy->asTextureProxy();
        SkASSERT(skgpu::Mipmapped::kYes == textureProxy->mipmapped());
        SkASSERT(textureProxy->mipmapsAreDirty());
        textureProxy->markMipmapsClean();
    }

    // We must do this after updating the proxy state because of assertions that the proxy isn't
    // dirty.
    if (newProxy) {
        // Add the proxy as a dependency: We will read the existing contents of this texture while
        // generating mipmap levels and/or resolving MSAA.
        this->addDependency(
                drawingMgr, proxy, skgpu::Mipmapped::kNo, GrTextureResolveManager(nullptr), caps);
        this->addTarget(drawingMgr, GrSurfaceProxyView(std::move(proxyRef)));
    }
}

void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
    // This renderTask doesn't have "normal" ops, however we still need to add intervals so
    // fEndOfOpsTaskOpIndices will remain in sync. We create fake op#'s to capture the fact that we
    // manipulate the resolve proxies.
    auto fakeOp = alloc->curOp();
    SkASSERT(fResolves.size() == this->numTargets());
    for (const sk_sp<GrSurfaceProxy>& target : fTargets) {
        alloc->addInterval(target.get(), fakeOp, fakeOp, GrResourceAllocator::ActualUse::kYes,
                           GrResourceAllocator::AllowRecycling::kYes);
    }
    alloc->incOps();
}

bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
    // Resolve all msaa back-to-back, before regenerating mipmaps.
    SkASSERT(fResolves.size() == this->numTargets());
    for (int i = 0; i < fResolves.size(); ++i) {
        const Resolve& resolve = fResolves[i];
        if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
            GrSurfaceProxy* proxy = this->target(i);
            // peekRenderTarget might be null if there was an instantiation error.
            if (GrRenderTarget* renderTarget = proxy->peekRenderTarget()) {
                flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect);
            }
        }
    }
    // Regenerate all mipmaps back-to-back.
    for (int i = 0; i < fResolves.size(); ++i) {
        const Resolve& resolve = fResolves[i];
        if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) {
            // peekTexture might be null if there was an instantiation error.
            GrTexture* texture = this->target(i)->peekTexture();
            if (texture && texture->mipmapsAreDirty()) {
                flushState->gpu()->regenerateMipMapLevels(texture);
                SkASSERT(!texture->mipmapsAreDirty());
            }
        }
    }

    return true;
}

#ifdef SK_DEBUG
void GrTextureResolveRenderTask::visitProxies_debugOnly(const GrVisitProxyFunc&) const {}
#endif

#if defined(GR_TEST_UTILS)
GrSurfaceProxy::ResolveFlags
GrTextureResolveRenderTask::flagsForProxy(sk_sp<GrSurfaceProxy> proxy) const {
    if (auto found = std::find(fTargets.begin(), fTargets.end(), proxy);
        found != fTargets.end()) {
        return fResolves[found - fTargets.begin()].fFlags;
    }
    return GrSurfaceProxy::ResolveFlags::kNone;
}
#endif
