1/*
2 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "src/gpu/GrCopyRenderTask.h"
9
10#include "src/gpu/GrGpu.h"
11#include "src/gpu/GrOpFlushState.h"
12#include "src/gpu/GrResourceAllocator.h"
13#include "src/gpu/geometry/GrRect.h"
14
15sk_sp<GrRenderTask> GrCopyRenderTask::Make(GrDrawingManager* drawingMgr,
16                                           sk_sp<GrSurfaceProxy> src,
17                                           SkIRect srcRect,
18                                           sk_sp<GrSurfaceProxy> dst,
19                                           SkIPoint dstPoint,
20                                           GrSurfaceOrigin origin) {
21    SkASSERT(src);
22    SkASSERT(dst);
23
24    if (!GrClipSrcRectAndDstPoint(dst->dimensions(),
25                                  src->dimensions(),
26                                  srcRect,
27                                  dstPoint,
28                                  &srcRect,
29                                  &dstPoint)) {
30        return nullptr;
31    }
32
33    return sk_sp<GrRenderTask>(new GrCopyRenderTask(drawingMgr,
34                                                    std::move(src),
35                                                    srcRect,
36                                                    std::move(dst),
37                                                    dstPoint,
38                                                    origin));
39}
40
41GrCopyRenderTask::GrCopyRenderTask(GrDrawingManager* drawingMgr,
42                                   sk_sp<GrSurfaceProxy> src,
43                                   SkIRect srcRect,
44                                   sk_sp<GrSurfaceProxy> dst,
45                                   SkIPoint dstPoint,
46                                   GrSurfaceOrigin origin)
47        : fSrc(std::move(src)), fSrcRect(srcRect), fDstPoint(dstPoint), fOrigin(origin) {
48    this->addTarget(drawingMgr, std::move(dst));
49}
50
51void GrCopyRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
52    if (!fSrc) {
53        alloc->incOps();
54        return;
55    }
56    // This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
57    // fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that
58    // we read fSrcView and copy to target view.
59    alloc->addInterval(fSrc.get(), alloc->curOp(), alloc->curOp(),
60                       GrResourceAllocator::ActualUse::kYes);
61    alloc->addInterval(this->target(0), alloc->curOp(), alloc->curOp(),
62                       GrResourceAllocator::ActualUse::kYes);
63    alloc->incOps();
64}
65
66GrRenderTask::ExpectedOutcome GrCopyRenderTask::onMakeClosed(GrRecordingContext*,
67                                                             SkIRect* targetUpdateBounds) {
68    // We don't expect to be marked skippable before being closed.
69    SkASSERT(fSrc);
70    *targetUpdateBounds = GrNativeRect::MakeIRectRelativeTo(
71            fOrigin,
72            this->target(0)->height(),
73            SkIRect::MakePtSize(fDstPoint, fSrcRect.size()));
74    return ExpectedOutcome::kTargetDirty;
75}
76
77bool GrCopyRenderTask::onExecute(GrOpFlushState* flushState) {
78    if (!fSrc) {
79        // Did nothing, just like we're supposed to.
80        return true;
81    }
82    GrSurfaceProxy* dstProxy = this->target(0);
83    if (!fSrc->isInstantiated() || !dstProxy->isInstantiated()) {
84        return false;
85    }
86    GrSurface* srcSurface = fSrc->peekSurface();
87    GrSurface* dstSurface = dstProxy->peekSurface();
88    SkIRect srcRect = GrNativeRect::MakeIRectRelativeTo(fOrigin, srcSurface->height(), fSrcRect);
89    SkIPoint dstPoint = fDstPoint;
90    if (fOrigin == kBottomLeft_GrSurfaceOrigin) {
91        dstPoint.fY = dstSurface->height() - dstPoint.fY - srcRect.height();
92    }
93    return flushState->gpu()->copySurface(dstSurface, srcSurface, srcRect, dstPoint);
94}
95
96