blob: a93a94e73bb20a1953ff17336fd56a3e8156b858 [file] [log] [blame]
Chris Dalton49d14e92018-07-27 12:38:35 -06001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9
10#include "GrClip.h"
11#include "GrContext.h"
12#include "GrGpuCommandBuffer.h"
13#include "GrMemoryPool.h"
14#include "GrOpFlushState.h"
15#include "GrRenderTargetContext.h"
16#include "GrRenderTargetContextPriv.h"
17#include "GrRenderTarget.h"
18#include "glsl/GrGLSLFragmentShaderBuilder.h"
19#include "glsl/GrGLSLGeometryProcessor.h"
20#include "glsl/GrGLSLVarying.h"
21#include "glsl/GrGLSLVertexGeoBuilder.h"
22
23namespace skiagm {
24
Brian Osmand4c29702018-09-14 16:16:55 -040025static constexpr GrGeometryProcessor::Attribute gVertex =
26 {"vertex", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
Chris Dalton49d14e92018-07-27 12:38:35 -060027
28/**
29 * This is a GPU-backend specific test. It ensures that SkSL properly identifies clockwise-winding
30 * triangles (sk_Clockwise), in terms of to Skia device space, in all backends and with all render
31 * target origins. We draw clockwise triangles green and counter-clockwise red.
32 */
Chris Dalton3a778372019-02-07 15:23:36 -070033class ClockwiseGM : public GpuGM {
Chris Dalton49d14e92018-07-27 12:38:35 -060034private:
35 SkString onShortName() final { return SkString("clockwise"); }
36 SkISize onISize() override { return SkISize::Make(300, 200); }
Chris Dalton3a778372019-02-07 15:23:36 -070037 void onDraw(GrContext*, GrRenderTargetContext*, SkCanvas*) override;
Chris Dalton49d14e92018-07-27 12:38:35 -060038};
39
40////////////////////////////////////////////////////////////////////////////////////////////////////
41// SkSL code.
42
43class ClockwiseTestProcessor : public GrGeometryProcessor {
44public:
45 ClockwiseTestProcessor(bool readSkFragCoord)
46 : GrGeometryProcessor(kClockwiseTestProcessor_ClassID)
47 , fReadSkFragCoord(readSkFragCoord) {
Brian Osmanf04fb3c2018-11-12 15:34:00 -050048 this->setVertexAttributes(&gVertex, 1);
Chris Dalton49d14e92018-07-27 12:38:35 -060049 }
50 const char* name() const override { return "ClockwiseTestProcessor"; }
51 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {
52 b->add32(fReadSkFragCoord);
53 }
54 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
55
56private:
Chris Dalton49d14e92018-07-27 12:38:35 -060057 const bool fReadSkFragCoord;
58
59 friend class GLSLClockwiseTestProcessor;
60};
61
62class GLSLClockwiseTestProcessor : public GrGLSLGeometryProcessor {
63 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
64 FPCoordTransformIter&& transformIter) override {}
65
66 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
67 const ClockwiseTestProcessor& proc = args.fGP.cast<ClockwiseTestProcessor>();
68 args.fVaryingHandler->emitAttributes(proc);
69 gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
70 args.fFragBuilder->codeAppendf(
71 "%s = sk_Clockwise ? half4(0,1,0,1) : half4(1,0,0,1);", args.fOutputColor);
72 if (!proc.fReadSkFragCoord) {
73 args.fFragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
74 } else {
75 // Verify layout(origin_upper_left) on gl_FragCoord does not affect gl_FrontFacing.
Ethan Nicholase1f55022019-02-05 17:17:40 -050076 args.fFragBuilder->codeAppendf("%s = half4(min(half(sk_FragCoord.y), 1));",
Chris Dalton49d14e92018-07-27 12:38:35 -060077 args.fOutputCoverage);
78 }
79 }
80};
81
82GrGLSLPrimitiveProcessor* ClockwiseTestProcessor::createGLSLInstance(
83 const GrShaderCaps&) const {
84 return new GLSLClockwiseTestProcessor;
85}
86
87////////////////////////////////////////////////////////////////////////////////////////////////////
88// Draw Op.
89
90class ClockwiseTestOp : public GrDrawOp {
91public:
92 DEFINE_OP_CLASS_ID
93
94 static std::unique_ptr<GrDrawOp> Make(GrContext* context, bool readSkFragCoord, int y = 0) {
Robert Phillips9da87e02019-02-04 13:26:26 -050095 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Chris Dalton49d14e92018-07-27 12:38:35 -060096 return pool->allocate<ClockwiseTestOp>(readSkFragCoord, y);
97 }
98
99private:
100 ClockwiseTestOp(bool readSkFragCoord, float y)
101 : GrDrawOp(ClassID()), fReadSkFragCoord(readSkFragCoord), fY(y) {
102 this->setBounds(SkRect::MakeIWH(300, 100), HasAABloat::kNo, IsZeroArea::kNo);
103 }
104
105 const char* name() const override { return "ClockwiseTestOp"; }
106 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Chris Dalton4b62aed2019-01-15 11:53:00 -0700107 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*) override {
108 return GrProcessorSet::EmptySetAnalysis();
Chris Dalton49d14e92018-07-27 12:38:35 -0600109 }
Chris Dalton49d14e92018-07-27 12:38:35 -0600110 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500111 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
Chris Dalton49d14e92018-07-27 12:38:35 -0600112 SkPoint vertices[4] = {
113 {100, fY},
114 {0, fY+100},
115 {0, fY},
116 {100, fY+100},
117 };
Brian Salomon12d22642019-01-29 14:38:50 -0500118 sk_sp<const GrBuffer> vertexBuffer(flushState->resourceProvider()->createBuffer(
Brian Salomondbf70722019-02-07 11:31:24 -0500119 sizeof(vertices), GrGpuBufferType::kVertex, kStatic_GrAccessPattern, vertices));
Chris Dalton79f99f72018-07-27 14:15:10 -0600120 if (!vertexBuffer) {
121 return;
122 }
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500123 GrPipeline pipeline(GrScissorTest::kDisabled, SkBlendMode::kPlus);
Chris Dalton49d14e92018-07-27 12:38:35 -0600124 GrMesh mesh(GrPrimitiveType::kTriangleStrip);
125 mesh.setNonIndexedNonInstanced(4);
Brian Salomon12d22642019-01-29 14:38:50 -0500126 mesh.setVertexData(std::move(vertexBuffer));
Chris Dalton49d14e92018-07-27 12:38:35 -0600127 flushState->rtCommandBuffer()->draw(ClockwiseTestProcessor(fReadSkFragCoord), pipeline,
128 nullptr, nullptr, &mesh, 1, SkRect::MakeIWH(100, 100));
129 }
130
131 const bool fReadSkFragCoord;
132 const float fY;
133
134 friend class ::GrOpMemoryPool; // for ctor
135};
136
137////////////////////////////////////////////////////////////////////////////////////////////////////
138// Test.
139
Chris Dalton3a778372019-02-07 15:23:36 -0700140void ClockwiseGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas) {
Brian Osman9a9baae2018-11-05 15:06:26 -0500141 rtc->clear(nullptr, { 0, 0, 0, 1 }, GrRenderTargetContext::CanClearFullscreen::kYes);
Chris Dalton49d14e92018-07-27 12:38:35 -0600142
143 // Draw the test directly to the frame buffer.
144 rtc->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
145 rtc->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
146
147 // Draw the test to an off-screen, top-down render target.
Robert Phillips9da87e02019-02-04 13:26:26 -0500148 if (auto topLeftRTC = ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500149 rtc->asSurfaceProxy()->backendFormat(), SkBackingFit::kExact, 100, 200,
150 rtc->asSurfaceProxy()->config(), nullptr, 1, GrMipMapped::kNo,
151 kTopLeft_GrSurfaceOrigin, nullptr, SkBudgeted::kYes)) {
Brian Osman9a9baae2018-11-05 15:06:26 -0500152 topLeftRTC->clear(nullptr, SK_PMColor4fTRANSPARENT,
153 GrRenderTargetContext::CanClearFullscreen::kYes);
Chris Dalton49d14e92018-07-27 12:38:35 -0600154 topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
155 topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
156 rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()),
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500157 GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
158 SK_PMColor4fWHITE, {0, 0, 100, 200},
Brian Salomon2213ee92018-10-02 10:44:21 -0400159 {100, 0, 200, 200}, GrQuadAAFlags::kNone,
Chris Dalton49d14e92018-07-27 12:38:35 -0600160 SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
Brian Osman3d139a42018-11-19 10:42:10 -0500161 nullptr);
Chris Dalton49d14e92018-07-27 12:38:35 -0600162 }
163
164 // Draw the test to an off-screen, bottom-up render target.
Robert Phillips9da87e02019-02-04 13:26:26 -0500165 if (auto topLeftRTC = ctx->priv().makeDeferredRenderTargetContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500166 rtc->asSurfaceProxy()->backendFormat(), SkBackingFit::kExact, 100, 200,
167 rtc->asSurfaceProxy()->config(), nullptr, 1, GrMipMapped::kNo,
168 kBottomLeft_GrSurfaceOrigin, nullptr, SkBudgeted::kYes)) {
Brian Osman9a9baae2018-11-05 15:06:26 -0500169 topLeftRTC->clear(nullptr, SK_PMColor4fTRANSPARENT,
170 GrRenderTargetContext::CanClearFullscreen::kYes);
Chris Dalton49d14e92018-07-27 12:38:35 -0600171 topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
172 topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
173 rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()),
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500174 GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
175 SK_PMColor4fWHITE, {0, 0, 100, 200},
Brian Salomon2213ee92018-10-02 10:44:21 -0400176 {200, 0, 300, 200}, GrQuadAAFlags::kNone,
Chris Dalton49d14e92018-07-27 12:38:35 -0600177 SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
Brian Osman3d139a42018-11-19 10:42:10 -0500178 nullptr);
Chris Dalton49d14e92018-07-27 12:38:35 -0600179 }
180}
181
182////////////////////////////////////////////////////////////////////////////////////////////////////
183
184DEF_GM( return new ClockwiseGM(); )
185
186}