[graphite] Implement fullscreen clear as LoadOp

Bug: skia:12466
Change-Id: Ie8bbacd22375b4cb4a5fe7e39055cdba3a3d0896
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/469519
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Jim Van Verth 2021-11-12 15:43:06 -05:00 committed by SkCQ
parent c02dceb227
commit 23dafe81e0
7 changed files with 52 additions and 8 deletions

View File

@ -9,6 +9,7 @@
#define skgpu_CommandBuffer_DEFINED
#include "experimental/graphite/include/private/GraphiteTypesPriv.h"
#include "include/core/SkColor.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/private/SkTArray.h"

View File

@ -143,6 +143,12 @@ SkIRect Device::onDevClipBounds() const {
}
void Device::drawPaint(const SkPaint& paint) {
// TODO: check paint params as well
if (this->clipIsWideOpen()) {
// do fullscreen clear
fDC->clear(paint.getColor4f());
return;
}
SkRect deviceBounds = SkRect::Make(this->devClipBounds());
// TODO: Should be able to get the inverse from the matrix cache
SkM44 devToLocal;

View File

@ -40,7 +40,7 @@ protected:
void onRestore() override {}
bool onClipIsAA() const override { return false; }
bool onClipIsWideOpen() const override { return false; }
bool onClipIsWideOpen() const override { return true; }
ClipType onGetClipType() const override { return ClipType::kRect; }
SkIRect onDevClipBounds() const override;

View File

@ -7,6 +7,8 @@
#include "experimental/graphite/src/DrawContext.h"
#include "include/private/SkColorData.h"
#include "experimental/graphite/src/CommandBuffer.h"
#include "experimental/graphite/src/DrawList.h"
#include "experimental/graphite/src/DrawPass.h"
@ -77,14 +79,29 @@ void DrawContext::strokePath(const Transform& localToDevice,
fPendingDraws->strokePath(localToDevice, shape, stroke, clip, order, paint);
}
void DrawContext::clear(const SkColor4f& clearColor) {
fPendingLoadOp = LoadOp::kClear;
SkPMColor4f pmColor = clearColor.premul();
fPendingClearColor = pmColor.array();
// a fullscreen clear will overwrite anything that came before, so start a new DrawList
// and clear any drawpasses that haven't been snapped yet
fPendingDraws = std::make_unique<DrawList>();
fDrawPasses.clear();
}
void DrawContext::snapDrawPass(Recorder* recorder, const BoundsManager* occlusionCuller) {
if (fPendingDraws->drawCount() == 0) {
return;
}
auto pass = DrawPass::Make(recorder, std::move(fPendingDraws), fTarget, occlusionCuller);
auto pass = DrawPass::Make(recorder, std::move(fPendingDraws), fTarget,
std::make_pair(fPendingLoadOp, fPendingStoreOp), fPendingClearColor,
occlusionCuller);
fDrawPasses.push_back(std::move(pass));
fPendingDraws = std::make_unique<DrawList>();
fPendingLoadOp = LoadOp::kLoad;
fPendingStoreOp = StoreOp::kStore;
}
sk_sp<Task> DrawContext::snapRenderPassTask(Recorder* recorder,
@ -100,8 +117,8 @@ sk_sp<Task> DrawContext::snapRenderPassTask(Recorder* recorder,
SkASSERT(fDrawPasses.size() == 1);
RenderPassDesc desc;
desc.fColorAttachment.fTextureProxy = sk_ref_sp(fDrawPasses[0]->target());
desc.fColorAttachment.fLoadOp = LoadOp::kLoad;
desc.fColorAttachment.fStoreOp = StoreOp::kStore;
std::tie(desc.fColorAttachment.fLoadOp, desc.fColorAttachment.fStoreOp) = fDrawPasses[0]->ops();
desc.fClearColor = fDrawPasses[0]->clearColor();
return RenderPassTask::Make(std::move(fDrawPasses), desc);
}

View File

@ -11,6 +11,7 @@
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "experimental/graphite/include/private/GraphiteTypesPriv.h"
#include "experimental/graphite/src/DrawList.h"
#include "experimental/graphite/src/DrawOrder.h"
@ -48,6 +49,8 @@ public:
// TODO: need color/depth clearing functions (so DCL will probably need those too)
void clear(const SkColor4f& clearColor);
void stencilAndFillPath(const Transform& localToDevice,
const Shape& shape,
const Clip& clip,
@ -98,6 +101,10 @@ private:
// Stores the most immediately recorded draws into the SDC's surface. This list is mutable and
// can be appended to, or have its commands rewritten if they are inlined into a parent SDC.
std::unique_ptr<DrawList> fPendingDraws;
// Load and store information for the current pending draws.
LoadOp fPendingLoadOp = LoadOp::kLoad;
StoreOp fPendingStoreOp = StoreOp::kStore;
std::array<float, 4> fPendingClearColor = { 0, 0, 0, 0 };
// Stores previously snapped DrawPasses of this SDC, or inlined child SDCs whose content
// couldn't have been copied directly to fPendingDraws. While each DrawPass is immutable, the

View File

@ -140,9 +140,12 @@ skgpu::UniformData* lookup(skgpu::Recorder* recorder, uint32_t uniformID) {
} // anonymous namespace
DrawPass::DrawPass(sk_sp<TextureProxy> target, const SkIRect& bounds,
std::pair<LoadOp, StoreOp> ops, std::array<float, 4> clearColor,
bool requiresStencil, bool requiresMSAA)
: fTarget(std::move(target))
, fBounds(bounds)
, fOps(ops)
, fClearColor(clearColor)
, fRequiresStencil(requiresStencil)
, fRequiresMSAA(requiresMSAA) {}
@ -151,6 +154,8 @@ DrawPass::~DrawPass() = default;
std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
std::unique_ptr<DrawList> draws,
sk_sp<TextureProxy> target,
std::pair<LoadOp, StoreOp> ops,
std::array<float, 4> clearColor,
const BoundsManager* occlusionCuller) {
// NOTE: This assert is here to ensure SortKey is as tightly packed as possible. Any change to
// its size should be done with care and good reason. The performance of sorting the keys is
@ -309,7 +314,7 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
passBounds.roundOut();
SkIRect pxPassBounds = SkIRect::MakeLTRB((int) passBounds.left(), (int) passBounds.top(),
(int) passBounds.right(), (int) passBounds.bot());
return std::unique_ptr<DrawPass>(new DrawPass(std::move(target), pxPassBounds,
return std::unique_ptr<DrawPass>(new DrawPass(std::move(target), pxPassBounds, ops, clearColor,
requiresStencil, requiresMSAA));
}

View File

@ -8,9 +8,12 @@
#ifndef skgpu_DrawPass_DEFINED
#define skgpu_DrawPass_DEFINED
#include "include/core/SkColor.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "experimental/graphite/include/private/GraphiteTypesPriv.h"
#include <memory>
namespace skgpu {
@ -41,12 +44,16 @@ public:
static std::unique_ptr<DrawPass> Make(Recorder*,
std::unique_ptr<DrawList>,
sk_sp<TextureProxy>,
std::pair<LoadOp, StoreOp>,
std::array<float, 4> clearColor,
const BoundsManager* occlusionCuller);
// Defined relative to the top-left corner of the surface the DrawPass renders to, and is
// contained within its dimensions.
const SkIRect& bounds() const { return fBounds; }
TextureProxy* target() const { return fTarget.get(); }
std::pair<LoadOp, StoreOp> ops() const { return fOps; }
std::array<float, 4> clearColor() const { return fClearColor; }
bool requiresDstTexture() const { return false; }
bool requiresStencil() const { return fRequiresStencil; }
@ -71,17 +78,18 @@ private:
DrawPass(sk_sp<TextureProxy> target,
const SkIRect& bounds,
std::pair<LoadOp, StoreOp> ops,
std::array<float, 4> clearColor,
bool requiresStencil,
bool requiresMSAA);
sk_sp<TextureProxy> fTarget;
SkIRect fBounds;
std::pair<LoadOp, StoreOp> fOps;
std::array<float, 4> fClearColor;
bool fRequiresStencil;
bool fRequiresMSAA;
// TODO: actually implement this. Will own the results of sorting/culling/merging a DrawList,
// however that is actually specified.
};
} // namespace skgpu