/*
 * 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/GrCopyRenderTask.h"

#include "include/private/base/SkAssert.h"
#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrNativeRect.h"
#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/GrResourceAllocator.h"
#include "src/gpu/ganesh/GrSurface.h"

#include <utility>

class GrDrawingManager;
class GrRecordingContext;

sk_sp<GrRenderTask> GrCopyRenderTask::Make(GrDrawingManager* drawingMgr,
                                           sk_sp<GrSurfaceProxy> dst,
                                           SkIRect dstRect,
                                           sk_sp<GrSurfaceProxy> src,
                                           SkIRect srcRect,
                                           GrSamplerState::Filter filter,
                                           GrSurfaceOrigin origin) {
    SkASSERT(src);
    SkASSERT(dst);

    // canCopySurface() should have returned true, guaranteeing this property.
    SkASSERT(SkIRect::MakeSize(dst->dimensions()).contains(dstRect));
    SkASSERT(SkIRect::MakeSize(src->dimensions()).contains(srcRect));

    return sk_sp<GrRenderTask>(new GrCopyRenderTask(drawingMgr,
                                                    std::move(dst),
                                                    dstRect,
                                                    std::move(src),
                                                    srcRect,
                                                    filter,
                                                    origin));
}

GrCopyRenderTask::GrCopyRenderTask(GrDrawingManager* drawingMgr,
                                   sk_sp<GrSurfaceProxy> dst,
                                   SkIRect dstRect,
                                   sk_sp<GrSurfaceProxy> src,
                                   SkIRect srcRect,
                                   GrSamplerState::Filter filter,
                                   GrSurfaceOrigin origin)
        : fSrc(std::move(src))
        , fSrcRect(srcRect)
        , fDstRect(dstRect)
        , fFilter(filter)
        , fOrigin(origin) {
    this->addTarget(drawingMgr, std::move(dst));
}

void GrCopyRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
    if (!fSrc) {
        alloc->incOps();
        return;
    }
    // This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
    // fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that
    // we read fSrcView and copy to target view.
    alloc->addInterval(fSrc.get(), alloc->curOp(), alloc->curOp(),
                       GrResourceAllocator::ActualUse::kYes,
                       GrResourceAllocator::AllowRecycling::kYes);
    alloc->addInterval(this->target(0), alloc->curOp(), alloc->curOp(),
                       GrResourceAllocator::ActualUse::kYes,
                       GrResourceAllocator::AllowRecycling::kYes);
    alloc->incOps();
}

GrRenderTask::ExpectedOutcome GrCopyRenderTask::onMakeClosed(GrRecordingContext*,
                                                             SkIRect* targetUpdateBounds) {
    // We don't expect to be marked skippable before being closed.
    SkASSERT(fSrc);
    *targetUpdateBounds = GrNativeRect::MakeIRectRelativeTo(
            fOrigin,
            this->target(0)->height(),
            fDstRect);
    return ExpectedOutcome::kTargetDirty;
}

bool GrCopyRenderTask::onExecute(GrOpFlushState* flushState) {
    if (!fSrc) {
        // Did nothing, just like we're supposed to.
        return true;
    }
    GrSurfaceProxy* dstProxy = this->target(0);
    if (!fSrc->isInstantiated() || !dstProxy->isInstantiated()) {
        return false;
    }
    GrSurface* srcSurface = fSrc->peekSurface();
    GrSurface* dstSurface = dstProxy->peekSurface();
    SkIRect srcRect = GrNativeRect::MakeIRectRelativeTo(fOrigin, srcSurface->height(), fSrcRect);
    SkIRect dstRect = GrNativeRect::MakeIRectRelativeTo(fOrigin, dstSurface->height(), fDstRect);
    return flushState->gpu()->copySurface(dstSurface, dstRect, srcSurface, srcRect, fFilter);
}
