blob: 5ffd0fce685adad355f63d819a4e928124fa3a1a [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -04009#include "include/core/SkBlendMode.h"
10#include "include/core/SkCanvas.h"
11#include "include/core/SkColorSpace.h"
12#include "include/core/SkMatrix.h"
13#include "include/core/SkPoint.h"
14#include "include/core/SkRect.h"
15#include "include/core/SkRefCnt.h"
16#include "include/core/SkSize.h"
17#include "include/core/SkString.h"
18#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "include/gpu/GrContext.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040020#include "include/gpu/GrSamplerState.h"
21#include "include/gpu/GrTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050022#include "include/private/GrRecordingContext.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040023#include "include/private/GrTypesPriv.h"
24#include "include/private/SkColorData.h"
25#include "src/gpu/GrBuffer.h"
26#include "src/gpu/GrCaps.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "src/gpu/GrClip.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040028#include "src/gpu/GrColorSpaceXform.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050029#include "src/gpu/GrContextPriv.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040030#include "src/gpu/GrGeometryProcessor.h"
31#include "src/gpu/GrGpuBuffer.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050032#include "src/gpu/GrGpuCommandBuffer.h"
33#include "src/gpu/GrMemoryPool.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040034#include "src/gpu/GrMesh.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050035#include "src/gpu/GrOpFlushState.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040036#include "src/gpu/GrPipeline.h"
37#include "src/gpu/GrPrimitiveProcessor.h"
38#include "src/gpu/GrProcessor.h"
39#include "src/gpu/GrProcessorSet.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050040#include "src/gpu/GrRecordingContextPriv.h"
41#include "src/gpu/GrRenderTargetContext.h"
42#include "src/gpu/GrRenderTargetContextPriv.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040043#include "src/gpu/GrResourceProvider.h"
44#include "src/gpu/GrShaderCaps.h"
45#include "src/gpu/GrShaderVar.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040046#include "src/gpu/GrSurfaceProxy.h"
47#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050048#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
49#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040050#include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050051#include "src/gpu/glsl/GrGLSLVarying.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040052#include "src/gpu/ops/GrDrawOp.h"
53#include "src/gpu/ops/GrOp.h"
54
55#include <memory>
56#include <utility>
57
58class GrAppliedClip;
59class GrGLSLProgramDataManager;
Chris Dalton49d14e92018-07-27 12:38:35 -060060
61namespace skiagm {
62
Brian Osmand4c29702018-09-14 16:16:55 -040063static constexpr GrGeometryProcessor::Attribute gVertex =
Stephen White1e1ad8d2019-06-19 14:19:47 -040064 {"position", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
Chris Dalton49d14e92018-07-27 12:38:35 -060065
66/**
67 * This is a GPU-backend specific test. It ensures that SkSL properly identifies clockwise-winding
68 * triangles (sk_Clockwise), in terms of to Skia device space, in all backends and with all render
69 * target origins. We draw clockwise triangles green and counter-clockwise red.
70 */
Chris Dalton3a778372019-02-07 15:23:36 -070071class ClockwiseGM : public GpuGM {
Chris Dalton49d14e92018-07-27 12:38:35 -060072private:
73 SkString onShortName() final { return SkString("clockwise"); }
74 SkISize onISize() override { return SkISize::Make(300, 200); }
Chris Dalton3a778372019-02-07 15:23:36 -070075 void onDraw(GrContext*, GrRenderTargetContext*, SkCanvas*) override;
Chris Dalton49d14e92018-07-27 12:38:35 -060076};
77
78////////////////////////////////////////////////////////////////////////////////////////////////////
79// SkSL code.
80
81class ClockwiseTestProcessor : public GrGeometryProcessor {
82public:
83 ClockwiseTestProcessor(bool readSkFragCoord)
84 : GrGeometryProcessor(kClockwiseTestProcessor_ClassID)
85 , fReadSkFragCoord(readSkFragCoord) {
Brian Osmanf04fb3c2018-11-12 15:34:00 -050086 this->setVertexAttributes(&gVertex, 1);
Chris Dalton49d14e92018-07-27 12:38:35 -060087 }
88 const char* name() const override { return "ClockwiseTestProcessor"; }
89 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {
90 b->add32(fReadSkFragCoord);
91 }
92 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
93
94private:
Chris Dalton49d14e92018-07-27 12:38:35 -060095 const bool fReadSkFragCoord;
96
97 friend class GLSLClockwiseTestProcessor;
98};
99
100class GLSLClockwiseTestProcessor : public GrGLSLGeometryProcessor {
101 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
102 FPCoordTransformIter&& transformIter) override {}
103
104 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
105 const ClockwiseTestProcessor& proc = args.fGP.cast<ClockwiseTestProcessor>();
106 args.fVaryingHandler->emitAttributes(proc);
Stephen White1e1ad8d2019-06-19 14:19:47 -0400107 gpArgs->fPositionVar.set(kFloat2_GrSLType, "position");
Chris Dalton49d14e92018-07-27 12:38:35 -0600108 args.fFragBuilder->codeAppendf(
109 "%s = sk_Clockwise ? half4(0,1,0,1) : half4(1,0,0,1);", args.fOutputColor);
110 if (!proc.fReadSkFragCoord) {
111 args.fFragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
112 } else {
113 // Verify layout(origin_upper_left) on gl_FragCoord does not affect gl_FrontFacing.
Ethan Nicholase1f55022019-02-05 17:17:40 -0500114 args.fFragBuilder->codeAppendf("%s = half4(min(half(sk_FragCoord.y), 1));",
Chris Dalton49d14e92018-07-27 12:38:35 -0600115 args.fOutputCoverage);
116 }
117 }
118};
119
120GrGLSLPrimitiveProcessor* ClockwiseTestProcessor::createGLSLInstance(
121 const GrShaderCaps&) const {
122 return new GLSLClockwiseTestProcessor;
123}
124
125////////////////////////////////////////////////////////////////////////////////////////////////////
126// Draw Op.
127
128class ClockwiseTestOp : public GrDrawOp {
129public:
130 DEFINE_OP_CLASS_ID
131
Robert Phillipsbe9aff22019-02-15 11:33:22 -0500132 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
133 bool readSkFragCoord, int y = 0) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500134 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Chris Dalton49d14e92018-07-27 12:38:35 -0600135 return pool->allocate<ClockwiseTestOp>(readSkFragCoord, y);
136 }
137
138private:
139 ClockwiseTestOp(bool readSkFragCoord, float y)
140 : GrDrawOp(ClassID()), fReadSkFragCoord(readSkFragCoord), fY(y) {
141 this->setBounds(SkRect::MakeIWH(300, 100), HasAABloat::kNo, IsZeroArea::kNo);
142 }
143
144 const char* name() const override { return "ClockwiseTestOp"; }
145 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Chris Dalton6ce447a2019-06-23 18:07:38 -0600146 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
147 bool hasMixedSampledCoverage, GrClampType) override {
Chris Dalton4b62aed2019-01-15 11:53:00 -0700148 return GrProcessorSet::EmptySetAnalysis();
Chris Dalton49d14e92018-07-27 12:38:35 -0600149 }
Chris Dalton49d14e92018-07-27 12:38:35 -0600150 void onPrepare(GrOpFlushState*) override {}
Brian Salomon588cec72018-11-14 13:56:37 -0500151 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
Chris Dalton49d14e92018-07-27 12:38:35 -0600152 SkPoint vertices[4] = {
153 {100, fY},
154 {0, fY+100},
155 {0, fY},
156 {100, fY+100},
157 };
Brian Salomon12d22642019-01-29 14:38:50 -0500158 sk_sp<const GrBuffer> vertexBuffer(flushState->resourceProvider()->createBuffer(
Brian Salomondbf70722019-02-07 11:31:24 -0500159 sizeof(vertices), GrGpuBufferType::kVertex, kStatic_GrAccessPattern, vertices));
Chris Dalton79f99f72018-07-27 14:15:10 -0600160 if (!vertexBuffer) {
161 return;
162 }
Greg Daniel2c3398d2019-06-19 11:58:01 -0400163 GrPipeline pipeline(GrScissorTest::kDisabled, SkBlendMode::kPlus,
164 flushState->drawOpArgs().fOutputSwizzle);
Chris Dalton49d14e92018-07-27 12:38:35 -0600165 GrMesh mesh(GrPrimitiveType::kTriangleStrip);
166 mesh.setNonIndexedNonInstanced(4);
Brian Salomon12d22642019-01-29 14:38:50 -0500167 mesh.setVertexData(std::move(vertexBuffer));
Chris Dalton49d14e92018-07-27 12:38:35 -0600168 flushState->rtCommandBuffer()->draw(ClockwiseTestProcessor(fReadSkFragCoord), pipeline,
169 nullptr, nullptr, &mesh, 1, SkRect::MakeIWH(100, 100));
170 }
171
172 const bool fReadSkFragCoord;
173 const float fY;
174
175 friend class ::GrOpMemoryPool; // for ctor
176};
177
178////////////////////////////////////////////////////////////////////////////////////////////////////
179// Test.
180
Chris Dalton3a778372019-02-07 15:23:36 -0700181void ClockwiseGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas) {
Brian Osman9a9baae2018-11-05 15:06:26 -0500182 rtc->clear(nullptr, { 0, 0, 0, 1 }, GrRenderTargetContext::CanClearFullscreen::kYes);
Chris Dalton49d14e92018-07-27 12:38:35 -0600183
184 // Draw the test directly to the frame buffer.
185 rtc->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
186 rtc->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
187
188 // Draw the test to an off-screen, top-down render target.
Robert Phillips9da87e02019-02-04 13:26:26 -0500189 if (auto topLeftRTC = ctx->priv().makeDeferredRenderTargetContext(
Brian Salomond6287472019-06-24 15:50:07 -0400190 rtc->asSurfaceProxy()->backendFormat(), SkBackingFit::kExact, 100, 200,
191 rtc->asSurfaceProxy()->config(), rtc->colorSpaceInfo().colorType(), nullptr, 1,
192 GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin, nullptr, SkBudgeted::kYes)) {
Brian Osman9a9baae2018-11-05 15:06:26 -0500193 topLeftRTC->clear(nullptr, SK_PMColor4fTRANSPARENT,
194 GrRenderTargetContext::CanClearFullscreen::kYes);
Chris Dalton49d14e92018-07-27 12:38:35 -0600195 topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
196 topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
197 rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()),
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500198 GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
199 SK_PMColor4fWHITE, {0, 0, 100, 200},
Michael Ludwig136f45a2019-02-19 11:44:41 -0500200 {100, 0, 200, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
Chris Dalton49d14e92018-07-27 12:38:35 -0600201 SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
Brian Osman3d139a42018-11-19 10:42:10 -0500202 nullptr);
Chris Dalton49d14e92018-07-27 12:38:35 -0600203 }
204
205 // Draw the test to an off-screen, bottom-up render target.
Robert Phillips9da87e02019-02-04 13:26:26 -0500206 if (auto topLeftRTC = ctx->priv().makeDeferredRenderTargetContext(
Brian Salomond6287472019-06-24 15:50:07 -0400207 rtc->asSurfaceProxy()->backendFormat(), SkBackingFit::kExact, 100, 200,
208 rtc->asSurfaceProxy()->config(), rtc->colorSpaceInfo().colorType(), nullptr, 1,
209 GrMipMapped::kNo, kBottomLeft_GrSurfaceOrigin, nullptr, SkBudgeted::kYes)) {
Brian Osman9a9baae2018-11-05 15:06:26 -0500210 topLeftRTC->clear(nullptr, SK_PMColor4fTRANSPARENT,
211 GrRenderTargetContext::CanClearFullscreen::kYes);
Chris Dalton49d14e92018-07-27 12:38:35 -0600212 topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
213 topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
214 rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()),
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500215 GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
216 SK_PMColor4fWHITE, {0, 0, 100, 200},
Michael Ludwig136f45a2019-02-19 11:44:41 -0500217 {200, 0, 300, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
Chris Dalton49d14e92018-07-27 12:38:35 -0600218 SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
Brian Osman3d139a42018-11-19 10:42:10 -0500219 nullptr);
Chris Dalton49d14e92018-07-27 12:38:35 -0600220 }
221}
222
223////////////////////////////////////////////////////////////////////////////////////////////////////
224
225DEF_GM( return new ClockwiseGM(); )
226
227}