blob: 9e441871099834869060feef8e5dfa3454472674 [file] [log] [blame]
Greg Daniele227fe42019-08-21 13:52:24 -04001/*
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
14sk_sp<GrRenderTask> GrCopyRenderTask::Make(sk_sp<GrSurfaceProxy> srcProxy,
15 const SkIRect& srcRect,
16 sk_sp<GrSurfaceProxy> dstProxy,
Brian Salomone4bce012019-09-20 15:34:23 -040017 const SkIPoint& dstPoint,
18 const GrCaps* caps) {
Greg Daniele227fe42019-08-21 13:52:24 -040019 SkASSERT(dstProxy);
20 SkASSERT(srcProxy);
21 SkIRect clippedSrcRect;
22 SkIPoint clippedDstPoint;
23 // If the rect is outside the srcProxy or dstProxy then we've already succeeded.
Brian Salomon9f2b86c2019-10-22 10:37:46 -040024 if (!GrClipSrcRectAndDstPoint(dstProxy->dimensions(), srcProxy->dimensions(), srcRect, dstPoint,
Greg Daniele227fe42019-08-21 13:52:24 -040025 &clippedSrcRect, &clippedDstPoint)) {
26 return nullptr;
27 }
Brian Salomone4bce012019-09-20 15:34:23 -040028
29 if (caps->isFormatCompressed(dstProxy->backendFormat())) {
Greg Daniele227fe42019-08-21 13:52:24 -040030 return nullptr;
31 }
32
33 SkASSERT(dstProxy->origin() == srcProxy->origin());
34 if (srcProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
35 int rectHeight = clippedSrcRect.height();
36 clippedSrcRect.fTop = srcProxy->height() - clippedSrcRect.fBottom;
37 clippedSrcRect.fBottom = clippedSrcRect.fTop + rectHeight;
38 clippedDstPoint.fY = dstProxy->height() - clippedDstPoint.fY - rectHeight;
39 }
40
41 sk_sp<GrCopyRenderTask> task(new GrCopyRenderTask(
42 std::move(srcProxy), clippedSrcRect, std::move(dstProxy), clippedDstPoint));
43 return task;
44}
45
46GrCopyRenderTask::GrCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
47 const SkIRect& srcRect,
48 sk_sp<GrSurfaceProxy> dstProxy,
49 const SkIPoint& dstPoint)
50 : GrRenderTask(std::move(dstProxy))
51 , fSrcProxy(std::move(srcProxy))
52 , fSrcRect(srcRect)
53 , fDstPoint(dstPoint) {
54 fTarget->setLastRenderTask(this);
55}
56
57void GrCopyRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
58 // This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
Greg Danielf41b2bd2019-08-22 16:19:24 -040059 // fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that
Greg Daniele227fe42019-08-21 13:52:24 -040060 // we read fSrcProxy and copy to fTarget.
61 alloc->addInterval(fSrcProxy.get(), alloc->curOp(), alloc->curOp(),
62 GrResourceAllocator::ActualUse::kYes);
63 alloc->addInterval(fTarget.get(), alloc->curOp(), alloc->curOp(),
64 GrResourceAllocator::ActualUse::kYes);
65 alloc->incOps();
66}
67
68bool GrCopyRenderTask::onExecute(GrOpFlushState* flushState) {
69 if (!fSrcProxy->isInstantiated() || !fTarget->isInstantiated()) {
70 return false;
71 }
72 GrSurface* srcSurface = fSrcProxy->peekSurface();
73 GrSurface* dstSurface = fTarget->peekSurface();
74 if (fSrcProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
75 if (fSrcProxy->height() != srcSurface->height()) {
76 fSrcRect.offset(0, srcSurface->height() - fSrcProxy->height());
77 }
78 if (fTarget->height() != dstSurface->height()) {
79 fDstPoint.fY = fDstPoint.fY + (dstSurface->height() - fTarget->height());
80 }
81 }
82 return flushState->gpu()->copySurface(dstSurface, srcSurface, fSrcRect, fDstPoint);
83}
84