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