blob: 76fc161d6e51dd2b4aa97837e2be2014d99026d1 [file] [log] [blame]
/*
* Copyright 2020 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef DrawAtlasPathOp_DEFINED
#define DrawAtlasPathOp_DEFINED
#include "include/core/SkMatrix.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/gpu/GpuTypes.h"
#include "include/private/SkColorData.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/base/SkArenaAlloc.h"
#include "src/core/SkIPoint16.h"
#include "src/gpu/ganesh/GrBuffer.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrGpuBuffer.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/GrProcessorSet.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/ops/AtlasInstancedHelper.h"
#include "src/gpu/ganesh/ops/GrDrawOp.h"
#include "src/gpu/ganesh/ops/GrOp.h"
#include <array>
#include <utility>
class GrAppliedClip;
class GrDstProxyView;
class GrOpFlushState;
class GrProgramInfo;
class GrRecordingContext;
enum class GrXferBarrierFlags;
namespace skgpu::ganesh {
// Fills a rectangle of pixels with a clip against coverage values from an atlas.
class DrawAtlasPathOp final : public GrDrawOp {
public:
DEFINE_OP_CLASS_ID
DrawAtlasPathOp(SkArenaAlloc* arena, const SkIRect& fillBounds, const SkMatrix& localToDevice,
GrPaint&& paint, SkIPoint16 locationInAtlas, const SkIRect& pathDevIBounds,
bool transposedInAtlas, GrSurfaceProxyView atlasView, bool isInverseFill)
: GrDrawOp(ClassID())
, fHeadInstance(arena->make<Instance>(fillBounds, localToDevice, paint.getColor4f(),
locationInAtlas, pathDevIBounds,
transposedInAtlas))
, fTailInstance(&fHeadInstance->fNext)
, fAtlasHelper(std::move(atlasView),
isInverseFill ? AtlasInstancedHelper::ShaderFlags::kCheckBounds |
AtlasInstancedHelper::ShaderFlags::kInvertCoverage
: AtlasInstancedHelper::ShaderFlags::kNone)
, fProcessors(std::move(paint)) {
this->setBounds(SkRect::Make(fillBounds), HasAABloat::kYes, IsHairline::kNo);
}
const char* name() const override { return "DrawAtlasPathOp"; }
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
void visitProxies(const GrVisitProxyFunc& func) const override {
func(fAtlasHelper.proxy(), skgpu::Mipmapped::kNo);
fProcessors.visitProxies(func);
}
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
CombineResult onCombineIfPossible(GrOp*, SkArenaAlloc*, const GrCaps&) override;
void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView& writeView, GrAppliedClip*,
const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override;
void onPrepare(GrOpFlushState*) override;
void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
private:
void prepareProgram(const GrCaps&, SkArenaAlloc*, const GrSurfaceProxyView& writeView,
bool usesMSAASurface, GrAppliedClip&&, const GrDstProxyView&,
GrXferBarrierFlags, GrLoadOp colorLoadOp);
struct Instance {
Instance(const SkIRect& fillIBounds, const SkMatrix& m,
const SkPMColor4f& color, SkIPoint16 locationInAtlas,
const SkIRect& pathDevIBounds, bool transposedInAtlas)
: fFillBounds(fillIBounds)
, fLocalToDeviceIfUsingLocalCoords{m.getScaleX(), m.getSkewY(),
m.getSkewX(), m.getScaleY(),
m.getTranslateX(), m.getTranslateY()}
, fColor(color)
, fAtlasInstance(locationInAtlas, pathDevIBounds, transposedInAtlas) {
}
SkIRect fFillBounds;
std::array<float, 6> fLocalToDeviceIfUsingLocalCoords;
SkPMColor4f fColor;
AtlasInstancedHelper::Instance fAtlasInstance;
Instance* fNext = nullptr;
};
Instance* fHeadInstance;
Instance** fTailInstance;
AtlasInstancedHelper fAtlasHelper;
bool fUsesLocalCoords = false;
int fInstanceCount = 1;
GrProgramInfo* fProgram = nullptr;
sk_sp<const GrBuffer> fInstanceBuffer;
int fBaseInstance;
// Only used if sk_VertexID is not supported.
sk_sp<const GrGpuBuffer> fVertexBufferIfNoIDSupport;
GrProcessorSet fProcessors;
};
} // namespace skgpu::ganesh
#endif // DrawAtlasPathOp_DEFINED