skia2/gm/clockwise.cpp

287 lines
12 KiB
C++
Raw Normal View History

/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm/gm.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GrContext.h"
#include "include/gpu/GrTypes.h"
#include "include/private/GrRecordingContext.h"
#include "include/private/GrTypesPriv.h"
#include "include/private/SkColorData.h"
#include "src/gpu/GrBuffer.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrGpuBuffer.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrOpsRenderPass.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrPrimitiveProcessor.h"
#include "src/gpu/GrProcessor.h"
#include "src/gpu/GrProcessorSet.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrSamplerState.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrShaderVar.h"
#include "src/gpu/GrSurfaceProxy.h"
#include "src/gpu/GrTextureProxy.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/ops/GrDrawOp.h"
#include "src/gpu/ops/GrOp.h"
#include "tools/gpu/ProxyUtils.h"
#include <memory>
#include <utility>
class GrAppliedClip;
class GrGLSLProgramDataManager;
namespace {
static constexpr GrGeometryProcessor::Attribute gVertex =
{"position", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
/**
* This is a GPU-backend specific test. It ensures that SkSL properly identifies clockwise-winding
* triangles (sk_Clockwise), in terms of to Skia device space, in all backends and with all render
* target origins. We draw clockwise triangles green and counter-clockwise red.
*/
class ClockwiseGM : public skiagm::GpuGM {
SkString onShortName() override { return SkString("clockwise"); }
SkISize onISize() override { return {300, 200}; }
void onDraw(GrContext*, GrRenderTargetContext*, SkCanvas*) override;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// SkSL code.
class ClockwiseTestProcessor : public GrGeometryProcessor {
public:
static GrGeometryProcessor* Make(SkArenaAlloc* arena, bool readSkFragCoord) {
return arena->make<ClockwiseTestProcessor>(readSkFragCoord);
}
const char* name() const final { return "ClockwiseTestProcessor"; }
void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {
b->add32(fReadSkFragCoord);
}
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
bool readSkFragCoord() const { return fReadSkFragCoord; }
private:
friend class ::SkArenaAlloc; // for access to ctor
ClockwiseTestProcessor(bool readSkFragCoord)
: GrGeometryProcessor(kClockwiseTestProcessor_ClassID)
, fReadSkFragCoord(readSkFragCoord) {
this->setVertexAttributes(&gVertex, 1);
}
const bool fReadSkFragCoord;
typedef GrGeometryProcessor INHERITED;
};
class GLSLClockwiseTestProcessor : public GrGLSLGeometryProcessor {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
const CoordTransformRange&) override {}
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const ClockwiseTestProcessor& proc = args.fGP.cast<ClockwiseTestProcessor>();
args.fVaryingHandler->emitAttributes(proc);
gpArgs->fPositionVar.set(kFloat2_GrSLType, "position");
args.fFragBuilder->codeAppendf(
"%s = sk_Clockwise ? half4(0,1,0,1) : half4(1,0,0,1);", args.fOutputColor);
if (!proc.readSkFragCoord()) {
args.fFragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
} else {
// Verify layout(origin_upper_left) on gl_FragCoord does not affect gl_FrontFacing.
args.fFragBuilder->codeAppendf("%s = half4(min(half(sk_FragCoord.y), 1));",
args.fOutputCoverage);
}
}
};
GrGLSLPrimitiveProcessor* ClockwiseTestProcessor::createGLSLInstance(
const GrShaderCaps&) const {
return new GLSLClockwiseTestProcessor;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Draw Op.
class ClockwiseTestOp : public GrDrawOp {
public:
DEFINE_OP_CLASS_ID
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
bool readSkFragCoord, int y = 0) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
return pool->allocate<ClockwiseTestOp>(readSkFragCoord, y);
}
private:
ClockwiseTestOp(bool readSkFragCoord, float y)
: GrDrawOp(ClassID())
, fReadSkFragCoord(readSkFragCoord)
, fY(y) {
this->setBounds(SkRect::MakeXYWH(0, fY, 100, 100), HasAABloat::kNo, IsHairline::kNo);
}
const char* name() const override { return "ClockwiseTestOp"; }
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
bool hasMixedSampledCoverage, GrClampType) override {
return GrProcessorSet::EmptySetAnalysis();
}
GrProgramInfo* createProgramInfo(const GrCaps* caps,
SkArenaAlloc* arena,
const GrSurfaceProxyView* writeView,
GrAppliedClip&& appliedClip,
const GrXferProcessor::DstProxyView& dstProxyView) const {
GrGeometryProcessor* geomProc = ClockwiseTestProcessor::Make(arena, fReadSkFragCoord);
return sk_gpu_test::CreateProgramInfo(caps, arena, writeView,
std::move(appliedClip), dstProxyView,
geomProc, SkBlendMode::kPlus,
GrPrimitiveType::kTriangleStrip);
}
GrProgramInfo* createProgramInfo(GrOpFlushState* flushState) const {
return this->createProgramInfo(&flushState->caps(),
flushState->allocator(),
flushState->writeView(),
flushState->detachAppliedClip(),
flushState->dstProxyView());
}
void onPrePrepare(GrRecordingContext* context,
const GrSurfaceProxyView* writeView,
GrAppliedClip* clip,
const GrXferProcessor::DstProxyView& dstProxyView) final {
SkArenaAlloc* arena = context->priv().recordTimeAllocator();
// This is equivalent to a GrOpFlushState::detachAppliedClip
Improve scissor state tracking in GrRTC At a low level, this changes GrScissorState from a rect+bool to a rect+size. The scissor test is considered enablebd if the rect does not fill the device bounds rect specified by the size. This has a number of benefits: 1. We can always access the scissor rect and know that it will be restricted to the render target dimensions. 2. It helps consolidate code that previously had to test the scissor rect and render target bounds separately. 3. The clear operations can now match the proper backing store dimensions of the render target. 4. It makes it easier to reason about scissors applying to the logical dimensions of the render target vs. its backing store dimensions. Originally, I was going to have the extra scissor guards for the logical dimensions be added in a separate CL (with the cleanup for attemptQuadOptimization). However, it became difficult to ensure correct behavior respecting the vulkan render pass bounds without applying this new logic at the same time. So now, with this CL, GrAppliedClips are sized to the backing store dimensions of the render target. GrOpsTasks also clip bounds to the backing store dimensions instead of the logical dimensions (which seems more correct since that's where the auto-clipping happens). Then when we convert a GrClip to a GrAppliedClip, the GrRTC automatically enforces the logical dimensions scissor if we have stencil settings (to ensure the padded pixels don't get corrupted). It also may remove the scissor if the draw was just a color buffer update. Change-Id: I75671c9cc921f4696b1dd5231e02486090aa4282 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/290654 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2020-06-04 17:47:58 +00:00
GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, writeView,
std::move(appliedClip), dstProxyView);
context->priv().recordProgramInfo(fProgramInfo);
}
void onPrepare(GrOpFlushState* flushState) override {
SkPoint vertices[4] = {
{100, fY},
{0, fY+100},
{0, fY},
{100, fY+100},
};
fVertexBuffer = flushState->resourceProvider()->createBuffer(
sizeof(vertices), GrGpuBufferType::kVertex, kStatic_GrAccessPattern, vertices);
}
void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
if (!fVertexBuffer) {
return;
}
if (!fProgramInfo) {
fProgramInfo = this->createProgramInfo(flushState);
}
flushState->bindPipeline(*fProgramInfo, SkRect::MakeXYWH(0, fY, 100, 100));
flushState->bindBuffers(nullptr, nullptr, fVertexBuffer.get());
flushState->draw(4, 0);
}
sk_sp<GrBuffer> fVertexBuffer;
const bool fReadSkFragCoord;
const float fY;
// The program info (and both the GrPipeline and GrPrimitiveProcessor it relies on), when
// allocated, are allocated in either the ddl-record-time or flush-time arena. It is the
// arena's job to free up their memory so we just have a bare programInfo pointer here. We
// don't even store the GrPipeline and GrPrimitiveProcessor pointers here bc they are
// guaranteed to have the same lifetime as the program info.
GrProgramInfo* fProgramInfo = nullptr;
friend class ::GrOpMemoryPool; // for ctor
typedef GrDrawOp INHERITED;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Test.
void ClockwiseGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas) {
Reland "Simplify GrRTC::clean APIs" This reverts commit 4730f29993783fc9e96e45098d7e708fe08f1f26. Reason for revert: Fix WIP Original change's description: > Revert "Simplify GrRTC::clean APIs" > > This reverts commit 6cbd7c2e57af9c499f7e99feb215b890fdd3a10a. > > Reason for revert: mac/generated files failures > > Original change's description: > > Simplify GrRTC::clean APIs > > > > The CanClearFullscreen enum type is removed. Most usages of clear() had > > kYes because a null scissor rect was provided, or had kNo because the > > scissor was really critical to the behavior. A few places did provide a > > scissor and kYes (e.g. for initializing the target). > > > > To simplify this, the public GrRTC has two variants of clear(). One with > > only a color (for fullscreen clears), and one with a rect for partial > > clears. The private API also adds a clearAtLeast() function that replaces > > the several cases where we'd have a scissor but could expand to fullscreen. > > > > I find the current control flow in internalClear() to be hard to > > follow (albeit I was the one to make it that way...), but later CLs > > will improve it. > > > > Bug: skia:10205 > > Change-Id: I87cf8d688c58fbe58ee854fbc4ffe22482d969c6 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/290256 > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I7131df6f5323f4f9c120cbcfd9bc57e627e2eb65 > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: skia:10205 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291842 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> # Not skipping CQ checks because this is a reland. Bug: skia:10205 Change-Id: Id5db153d7c2500279cca8478818b66f67a53e143 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291844 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2020-05-26 20:57:38 +00:00
rtc->clear(SK_PMColor4fBLACK);
// Draw the test directly to the frame buffer.
rtc->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
rtc->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
// Draw the test to an off-screen, top-down render target.
GrColorType rtcColorType = rtc->colorInfo().colorType();
if (auto topLeftRTC = GrRenderTargetContext::Make(
ctx, rtcColorType, nullptr, SkBackingFit::kExact, {100, 200}, 1,
GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin, SkBudgeted::kYes,
nullptr)) {
Reland "Simplify GrRTC::clean APIs" This reverts commit 4730f29993783fc9e96e45098d7e708fe08f1f26. Reason for revert: Fix WIP Original change's description: > Revert "Simplify GrRTC::clean APIs" > > This reverts commit 6cbd7c2e57af9c499f7e99feb215b890fdd3a10a. > > Reason for revert: mac/generated files failures > > Original change's description: > > Simplify GrRTC::clean APIs > > > > The CanClearFullscreen enum type is removed. Most usages of clear() had > > kYes because a null scissor rect was provided, or had kNo because the > > scissor was really critical to the behavior. A few places did provide a > > scissor and kYes (e.g. for initializing the target). > > > > To simplify this, the public GrRTC has two variants of clear(). One with > > only a color (for fullscreen clears), and one with a rect for partial > > clears. The private API also adds a clearAtLeast() function that replaces > > the several cases where we'd have a scissor but could expand to fullscreen. > > > > I find the current control flow in internalClear() to be hard to > > follow (albeit I was the one to make it that way...), but later CLs > > will improve it. > > > > Bug: skia:10205 > > Change-Id: I87cf8d688c58fbe58ee854fbc4ffe22482d969c6 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/290256 > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I7131df6f5323f4f9c120cbcfd9bc57e627e2eb65 > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: skia:10205 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291842 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> # Not skipping CQ checks because this is a reland. Bug: skia:10205 Change-Id: Id5db153d7c2500279cca8478818b66f67a53e143 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291844 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2020-05-26 20:57:38 +00:00
topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
Reland "GrClips provided as pointers to GrRTC" This reverts commit 074414fed53efcab7f33b06454958707419e37d8. Reason for revert: updated to guard against nullptr before calling quickContains(rrect). Original change's description: > Revert "GrClips provided as pointers to GrRTC" > > This reverts commit 226b689471a0fbb7400bc166032458278957541b. > > Reason for revert: Breaks Android roller > > Original change's description: > > GrClips provided as pointers to GrRTC > > > > A null clip represents no high-level clipping is necessary (the implicit > > clip to the render target's logical dimensions is fine). > > > > This also removes GrNoClip and GrFixedClip::Disabled() since they are > > replaced with just nullptr. > > > > By allowing nullptr to represent no intended clipping, it makes it easier > > to require GrClip and GrAppliedClip objects to know about the dimensions > > of the device. If we required a non-null clip object to represent no > > clipping, we'd have to have an instance for each device based on its > > size and that just became cumbersome. > > > > Bug: skia:10205 > > Change-Id: Ie30cc71820b92d99356d393a4c98c8677082e761 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/290539 > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I42c4828bcf016ee3d30d5c20b771be96e125817b > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: skia:10205 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/292856 > Reviewed-by: Weston Tracey <westont@google.com> > Commit-Queue: Weston Tracey <westont@google.com> TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com,westont@google.com # Not skipping CQ checks because this is a reland. Bug: skia:10205 Change-Id: I5715a4de3b7c8847b73020dc4937d3816d879803 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/292876 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2020-05-29 13:54:07 +00:00
rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
{0, 0, 100, 200}, {100, 0, 200, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
nullptr);
}
// Draw the test to an off-screen, bottom-up render target.
if (auto topLeftRTC = GrRenderTargetContext::Make(
ctx, rtcColorType, nullptr, SkBackingFit::kExact, {100, 200}, 1,
GrMipMapped::kNo, GrProtected::kNo, kBottomLeft_GrSurfaceOrigin, SkBudgeted::kYes,
nullptr)) {
Reland "Simplify GrRTC::clean APIs" This reverts commit 4730f29993783fc9e96e45098d7e708fe08f1f26. Reason for revert: Fix WIP Original change's description: > Revert "Simplify GrRTC::clean APIs" > > This reverts commit 6cbd7c2e57af9c499f7e99feb215b890fdd3a10a. > > Reason for revert: mac/generated files failures > > Original change's description: > > Simplify GrRTC::clean APIs > > > > The CanClearFullscreen enum type is removed. Most usages of clear() had > > kYes because a null scissor rect was provided, or had kNo because the > > scissor was really critical to the behavior. A few places did provide a > > scissor and kYes (e.g. for initializing the target). > > > > To simplify this, the public GrRTC has two variants of clear(). One with > > only a color (for fullscreen clears), and one with a rect for partial > > clears. The private API also adds a clearAtLeast() function that replaces > > the several cases where we'd have a scissor but could expand to fullscreen. > > > > I find the current control flow in internalClear() to be hard to > > follow (albeit I was the one to make it that way...), but later CLs > > will improve it. > > > > Bug: skia:10205 > > Change-Id: I87cf8d688c58fbe58ee854fbc4ffe22482d969c6 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/290256 > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I7131df6f5323f4f9c120cbcfd9bc57e627e2eb65 > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: skia:10205 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291842 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> # Not skipping CQ checks because this is a reland. Bug: skia:10205 Change-Id: Id5db153d7c2500279cca8478818b66f67a53e143 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291844 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2020-05-26 20:57:38 +00:00
topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
Reland "GrClips provided as pointers to GrRTC" This reverts commit 074414fed53efcab7f33b06454958707419e37d8. Reason for revert: updated to guard against nullptr before calling quickContains(rrect). Original change's description: > Revert "GrClips provided as pointers to GrRTC" > > This reverts commit 226b689471a0fbb7400bc166032458278957541b. > > Reason for revert: Breaks Android roller > > Original change's description: > > GrClips provided as pointers to GrRTC > > > > A null clip represents no high-level clipping is necessary (the implicit > > clip to the render target's logical dimensions is fine). > > > > This also removes GrNoClip and GrFixedClip::Disabled() since they are > > replaced with just nullptr. > > > > By allowing nullptr to represent no intended clipping, it makes it easier > > to require GrClip and GrAppliedClip objects to know about the dimensions > > of the device. If we required a non-null clip object to represent no > > clipping, we'd have to have an instance for each device based on its > > size and that just became cumbersome. > > > > Bug: skia:10205 > > Change-Id: Ie30cc71820b92d99356d393a4c98c8677082e761 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/290539 > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I42c4828bcf016ee3d30d5c20b771be96e125817b > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: skia:10205 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/292856 > Reviewed-by: Weston Tracey <westont@google.com> > Commit-Queue: Weston Tracey <westont@google.com> TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com,westont@google.com # Not skipping CQ checks because this is a reland. Bug: skia:10205 Change-Id: I5715a4de3b7c8847b73020dc4937d3816d879803 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/292876 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2020-05-29 13:54:07 +00:00
rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
{0, 0, 100, 200}, {200, 0, 300, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
nullptr);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
DEF_GM( return new ClockwiseGM(); )
}