| /* |
| * Copyright 2021 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SurfaceFillContext_DEFINED |
| #define SurfaceFillContext_DEFINED |
| |
| #include "src/gpu/ganesh/SurfaceContext.h" |
| |
| #include "src/gpu/ganesh/ops/OpsTask.h" |
| |
| namespace skgpu::v1 { |
| |
| class SurfaceFillContext : public SurfaceContext { |
| public: |
| SurfaceFillContext(GrRecordingContext* rContext, |
| GrSurfaceProxyView readView, |
| GrSurfaceProxyView writeView, |
| const GrColorInfo& colorInfo); |
| |
| SurfaceFillContext* asFillContext() override { return this; } |
| |
| OpsTask* getOpsTask(); |
| |
| #if GR_TEST_UTILS |
| OpsTask* testingOnly_PeekLastOpsTask() { return fOpsTask.get(); } |
| #endif |
| |
| /** |
| * Provides a performance hint that the render target's contents are allowed |
| * to become undefined. |
| */ |
| void discard(); |
| |
| void resolveMSAA(); |
| |
| /** |
| * Clear the rect of the render target to the given color. |
| * @param rect the rect to clear to |
| * @param color the color to clear to. |
| */ |
| template <SkAlphaType AlphaType> |
| void clear(const SkIRect& rect, const SkRGBA4f<AlphaType>& color) { |
| this->internalClear(&rect, this->adjustColorAlphaType(color)); |
| } |
| |
| /** Clears the entire render target to the color. */ |
| template <SkAlphaType AlphaType> void clear(const SkRGBA4f<AlphaType>& color) { |
| this->internalClear(nullptr, this->adjustColorAlphaType(color)); |
| } |
| |
| /** |
| * Clear at minimum the pixels within 'scissor', but is allowed to clear the full render target |
| * if that is the more performant option. |
| */ |
| template <SkAlphaType AlphaType> |
| void clearAtLeast(const SkIRect& scissor, const SkRGBA4f<AlphaType>& color) { |
| this->internalClear(&scissor, |
| this->adjustColorAlphaType(color), |
| /* upgrade to full */ true); |
| } |
| |
| /** Fills 'dstRect' with 'fp' */ |
| void fillRectWithFP(const SkIRect& dstRect, std::unique_ptr<GrFragmentProcessor>); |
| |
| /** |
| * A convenience version of fillRectWithFP that applies a coordinate transformation via |
| * GrMatrixEffect. |
| */ |
| void fillRectWithFP(const SkIRect& dstRect, |
| const SkMatrix& localMatrix, |
| std::unique_ptr<GrFragmentProcessor>); |
| |
| /** Fills 'dstRect' with 'fp' using a local matrix that maps 'srcRect' to 'dstRect' */ |
| void fillRectToRectWithFP(const SkRect& srcRect, |
| const SkIRect& dstRect, |
| std::unique_ptr<GrFragmentProcessor> fp) { |
| SkMatrix lm = SkMatrix::RectToRect(SkRect::Make(dstRect), srcRect); |
| this->fillRectWithFP(dstRect, lm, std::move(fp)); |
| } |
| |
| /** Fills 'dstRect' with 'fp' using a local matrix that maps 'srcRect' to 'dstRect' */ |
| void fillRectToRectWithFP(const SkIRect& srcRect, |
| const SkIRect& dstRect, |
| std::unique_ptr<GrFragmentProcessor> fp) { |
| this->fillRectToRectWithFP(SkRect::Make(srcRect), dstRect, std::move(fp)); |
| } |
| |
| /** Fills the entire render target with the passed FP. */ |
| void fillWithFP(std::unique_ptr<GrFragmentProcessor> fp) { |
| this->fillRectWithFP(SkIRect::MakeSize(fWriteView.proxy()->dimensions()), std::move(fp)); |
| } |
| |
| /** |
| * A convenience version of fillWithFP that applies a coordinate transformation via |
| * GrMatrixEffect and fills the entire render target. |
| */ |
| void fillWithFP(const SkMatrix& localMatrix, std::unique_ptr<GrFragmentProcessor> fp) { |
| this->fillRectWithFP(SkIRect::MakeSize(fWriteView.proxy()->dimensions()), |
| localMatrix, |
| std::move(fp)); |
| } |
| |
| /** |
| * Draws the src texture with no matrix. The dstRect is the dstPoint with the width and height |
| * of the srcRect. The srcRect and dstRect are clipped to the bounds of the src and dst surfaces |
| * respectively. |
| */ |
| bool blitTexture(GrSurfaceProxyView, |
| const SkIRect& srcRect, |
| const SkIPoint& dstPoint); |
| |
| sk_sp<GrRenderTask> refRenderTask(); |
| |
| int numSamples() const { return this->asRenderTargetProxy()->numSamples(); } |
| bool wrapsVkSecondaryCB() const { return this->asRenderTargetProxy()->wrapsVkSecondaryCB(); } |
| |
| SkArenaAlloc* arenaAlloc() { return this->arenas()->arenaAlloc(); } |
| sktext::gpu::SubRunAllocator* subRunAlloc() { return this->arenas()->subRunAlloc(); } |
| |
| const GrSurfaceProxyView& writeSurfaceView() const { return fWriteView; } |
| |
| protected: |
| OpsTask* replaceOpsTask(); |
| |
| /** |
| * Creates a constant color paint for a clear, using src-over if possible to improve batching. |
| */ |
| static void ClearToGrPaint(std::array<float, 4> color, GrPaint* paint); |
| |
| void addOp(GrOp::Owner); |
| |
| template <SkAlphaType AlphaType> |
| static std::array<float, 4> ConvertColor(SkRGBA4f<AlphaType> color); |
| |
| template <SkAlphaType AlphaType> |
| std::array<float, 4> adjustColorAlphaType(SkRGBA4f<AlphaType> color) const; |
| |
| GrSurfaceProxyView fWriteView; |
| |
| private: |
| sk_sp<GrArenas> arenas() { return fWriteView.proxy()->asRenderTargetProxy()->arenas(); } |
| |
| void addDrawOp(GrOp::Owner); |
| |
| /** Override to be notified in subclass before the current ops task is replaced. */ |
| virtual void willReplaceOpsTask(OpsTask* prevTask, OpsTask* nextTask) {} |
| |
| /** |
| * Override to be called to participate in the decision to discard all previous ops if a |
| * fullscreen clear occurs. |
| */ |
| virtual OpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const { |
| return OpsTask::CanDiscardPreviousOps::kYes; |
| } |
| |
| void internalClear(const SkIRect* scissor, |
| std::array<float, 4> color, |
| bool upgradePartialToFull = false); |
| |
| SkDEBUGCODE(void onValidate() const override;) |
| |
| // The OpsTask can be closed by some other surface context that has picked it up. For this |
| // reason, the OpsTask should only ever be accessed via 'getOpsTask'. |
| sk_sp<OpsTask> fOpsTask; |
| |
| using INHERITED = SurfaceContext; |
| }; |
| |
| template<> |
| inline std::array<float, 4> SurfaceFillContext::ConvertColor<kPremul_SkAlphaType>( |
| SkPMColor4f color) { |
| return color.unpremul().array(); |
| } |
| |
| template<> |
| inline std::array<float, 4> SurfaceFillContext::ConvertColor<kUnpremul_SkAlphaType>( |
| SkColor4f color) { |
| return color.premul().array(); |
| } |
| |
| template <SkAlphaType AlphaType> |
| std::array<float, 4> SurfaceFillContext::adjustColorAlphaType(SkRGBA4f<AlphaType> color) const { |
| if (AlphaType == kUnknown_SkAlphaType || |
| this->colorInfo().alphaType() == kUnknown_SkAlphaType) { |
| return color.array(); |
| } |
| return (AlphaType == this->colorInfo().alphaType()) ? color.array() : ConvertColor(color); |
| } |
| |
| } // namespace skgpu::v1 |
| |
| #endif // SurfaceFillContext_DEFINED |