| /* | |
| * 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); | |
| } |