Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2020 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 "src/gpu/tessellate/GrDrawAtlasPathOp.h" |
| 9 | |
| 10 | #include "src/gpu/GrOpFlushState.h" |
| 11 | #include "src/gpu/GrOpsRenderPass.h" |
| 12 | #include "src/gpu/GrProgramInfo.h" |
| 13 | #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" |
| 14 | #include "src/gpu/glsl/GrGLSLGeometryProcessor.h" |
| 15 | #include "src/gpu/glsl/GrGLSLVarying.h" |
| 16 | #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" |
| 17 | |
| 18 | namespace { |
| 19 | |
| 20 | constexpr static GrGeometryProcessor::Attribute kInstanceAttribs[] = { |
Chris Dalton | d2dc8dd | 2020-05-19 16:32:02 -0600 | [diff] [blame] | 21 | {"dev_xywh", kInt4_GrVertexAttribType, kInt4_GrSLType}, |
| 22 | {"atlas_xy", kInt2_GrVertexAttribType, kInt2_GrSLType}, |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 23 | {"color", kFloat4_GrVertexAttribType, kHalf4_GrSLType}, |
| 24 | {"viewmatrix_scaleskew", kFloat4_GrVertexAttribType, kFloat4_GrSLType}, |
| 25 | {"viewmatrix_trans", kFloat2_GrVertexAttribType, kFloat2_GrSLType}}; |
| 26 | |
| 27 | class DrawAtlasPathShader : public GrGeometryProcessor { |
| 28 | public: |
| 29 | DrawAtlasPathShader(const GrTextureProxy* atlasProxy, GrSwizzle swizzle, bool usesLocalCoords) |
| 30 | : GrGeometryProcessor(kDrawAtlasPathShader_ClassID) |
| 31 | , fAtlasAccess(GrSamplerState::Filter::kNearest, atlasProxy->backendFormat(), swizzle) |
| 32 | , fAtlasDimensions(atlasProxy->backingStoreDimensions()) |
| 33 | , fUsesLocalCoords(usesLocalCoords) { |
| 34 | int numInstanceAttribs = SK_ARRAY_COUNT(kInstanceAttribs); |
| 35 | if (!fUsesLocalCoords) { |
| 36 | numInstanceAttribs -= 2; |
| 37 | } |
| 38 | this->setInstanceAttributes(kInstanceAttribs, numInstanceAttribs); |
| 39 | this->setTextureSamplerCnt(1); |
| 40 | } |
| 41 | |
| 42 | private: |
| 43 | const char* name() const override { return "DrawAtlasPathShader"; } |
| 44 | void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { |
| 45 | b->add32(fUsesLocalCoords); |
| 46 | } |
| 47 | const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; } |
| 48 | GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; |
| 49 | |
| 50 | const TextureSampler fAtlasAccess; |
| 51 | const SkISize fAtlasDimensions; |
| 52 | const bool fUsesLocalCoords; |
| 53 | |
| 54 | class Impl; |
| 55 | }; |
| 56 | |
| 57 | class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor { |
| 58 | void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { |
| 59 | const auto& shader = args.fGP.cast<DrawAtlasPathShader>(); |
| 60 | args.fVaryingHandler->emitAttributes(shader); |
| 61 | |
| 62 | GrGLSLVarying atlasCoord(kFloat2_GrSLType); |
| 63 | args.fVaryingHandler->addVarying("atlascoord", &atlasCoord); |
| 64 | |
| 65 | GrGLSLVarying color(kHalf4_GrSLType); |
| 66 | args.fVaryingHandler->addPassThroughAttribute( |
| 67 | kInstanceAttribs[2], args.fOutputColor, |
| 68 | GrGLSLVaryingHandler::Interpolation::kCanBeFlat); |
| 69 | |
| 70 | const char* atlasAdjust; |
| 71 | fAtlasAdjustUniform = args.fUniformHandler->addUniform( |
Ethan Nicholas | 16464c3 | 2020-04-06 13:53:05 -0400 | [diff] [blame] | 72 | nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "atlas_adjust", &atlasAdjust); |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 73 | |
| 74 | args.fVertBuilder->codeAppendf(R"( |
| 75 | float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1); |
Chris Dalton | d2dc8dd | 2020-05-19 16:32:02 -0600 | [diff] [blame] | 76 | float2 devtopleft = float2(dev_xywh.xy); |
| 77 | float2 devcoord = abs(float2(dev_xywh.zw)) * T + devtopleft; |
| 78 | float2 atlascoord = devcoord - devtopleft; |
| 79 | if (dev_xywh.w < 0) { // Negative height indicates that the path is transposed. |
| 80 | atlascoord = atlascoord.yx; |
| 81 | } |
| 82 | atlascoord += atlas_xy; |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 83 | %s = atlascoord * %s;)", |
| 84 | atlasCoord.vsOut(), atlasAdjust); |
| 85 | |
| 86 | gpArgs->fPositionVar.set(kFloat2_GrSLType, "devcoord"); |
| 87 | |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 88 | if (shader.fUsesLocalCoords) { |
| 89 | args.fVertBuilder->codeAppendf(R"( |
| 90 | float2x2 M = float2x2(viewmatrix_scaleskew); |
| 91 | float2 localcoord = inverse(M) * (devcoord - viewmatrix_trans);)"); |
Michael Ludwig | 553db62 | 2020-06-19 10:47:30 -0400 | [diff] [blame] | 92 | gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord"); |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 93 | } |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 94 | |
| 95 | args.fFragBuilder->codeAppendf("%s = ", args.fOutputCoverage); |
| 96 | args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn()); |
| 97 | args.fFragBuilder->codeAppendf(".aaaa;"); |
| 98 | } |
| 99 | |
Brian Osman | 609f159 | 2020-07-01 15:14:39 -0400 | [diff] [blame] | 100 | void setData(const GrGLSLProgramDataManager& pdman, |
| 101 | const GrPrimitiveProcessor& primProc) override { |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 102 | const SkISize& dimensions = primProc.cast<DrawAtlasPathShader>().fAtlasDimensions; |
| 103 | pdman.set2f(fAtlasAdjustUniform, 1.f / dimensions.width(), 1.f / dimensions.height()); |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform; |
| 107 | }; |
| 108 | |
| 109 | GrGLSLPrimitiveProcessor* DrawAtlasPathShader::createGLSLInstance(const GrShaderCaps&) const { |
| 110 | return new Impl(); |
| 111 | } |
| 112 | |
| 113 | } // namespace |
| 114 | |
| 115 | GrProcessorSet::Analysis GrDrawAtlasPathOp::finalize(const GrCaps& caps, const GrAppliedClip* clip, |
| 116 | bool hasMixedSampledCoverage, |
| 117 | GrClampType clampType) { |
| 118 | const GrProcessorSet::Analysis& analysis = fProcessors.finalize( |
| 119 | fInstanceList.fInstance.fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip, |
| 120 | &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps, clampType, |
| 121 | &fInstanceList.fInstance.fColor); |
| 122 | fUsesLocalCoords = analysis.usesLocalCoords(); |
| 123 | return analysis; |
| 124 | } |
| 125 | |
| 126 | GrOp::CombineResult GrDrawAtlasPathOp::onCombineIfPossible( |
| 127 | GrOp* op, GrRecordingContext::Arenas* arenas, const GrCaps&) { |
| 128 | auto* that = op->cast<GrDrawAtlasPathOp>(); |
| 129 | SkASSERT(fAtlasProxy == that->fAtlasProxy); |
| 130 | SkASSERT(fEnableHWAA == that->fEnableHWAA); |
| 131 | |
| 132 | if (fProcessors != that->fProcessors) { |
| 133 | return CombineResult::kCannotCombine; |
| 134 | } |
| 135 | |
| 136 | SkASSERT(fUsesLocalCoords == that->fUsesLocalCoords); |
| 137 | auto* copy = arenas->recordTimeAllocator()->make<InstanceList>(that->fInstanceList); |
| 138 | *fInstanceTail = copy; |
| 139 | fInstanceTail = (!copy->fNext) ? ©->fNext : that->fInstanceTail; |
| 140 | fInstanceCount += that->fInstanceCount; |
| 141 | return CombineResult::kMerged; |
| 142 | } |
| 143 | |
Robert Phillips | c655c3a | 2020-03-18 13:23:45 -0400 | [diff] [blame] | 144 | void GrDrawAtlasPathOp::onPrePrepare(GrRecordingContext*, |
Brian Salomon | 8afde5f | 2020-04-01 16:22:00 -0400 | [diff] [blame] | 145 | const GrSurfaceProxyView* writeView, |
Robert Phillips | c655c3a | 2020-03-18 13:23:45 -0400 | [diff] [blame] | 146 | GrAppliedClip*, |
Greg Daniel | d358cbe | 2020-09-11 09:33:54 -0400 | [diff] [blame] | 147 | const GrXferProcessor::DstProxyView&, |
| 148 | GrXferBarrierFlags renderPassXferBarriers) {} |
Robert Phillips | c655c3a | 2020-03-18 13:23:45 -0400 | [diff] [blame] | 149 | |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 150 | void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* state) { |
| 151 | size_t instanceStride = Instance::Stride(fUsesLocalCoords); |
| 152 | if (char* instanceData = (char*)state->makeVertexSpace( |
| 153 | instanceStride, fInstanceCount, &fInstanceBuffer, &fBaseInstance)) { |
| 154 | SkDEBUGCODE(char* end = instanceData + fInstanceCount * instanceStride); |
| 155 | for (const InstanceList* list = &fInstanceList; list; list = list->fNext) { |
| 156 | memcpy(instanceData, &list->fInstance, instanceStride); |
| 157 | instanceData += instanceStride; |
| 158 | } |
| 159 | SkASSERT(instanceData == end); |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | void GrDrawAtlasPathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) { |
| 164 | SkASSERT(fAtlasProxy->isInstantiated()); |
| 165 | |
| 166 | GrPipeline::InitArgs initArgs; |
| 167 | if (fEnableHWAA) { |
| 168 | initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias; |
| 169 | } |
| 170 | initArgs.fCaps = &state->caps(); |
| 171 | initArgs.fDstProxyView = state->drawOpArgs().dstProxyView(); |
Brian Salomon | 982f546 | 2020-03-30 12:52:33 -0400 | [diff] [blame] | 172 | initArgs.fWriteSwizzle = state->drawOpArgs().writeSwizzle(); |
Chris Dalton | aa0e45c | 2020-03-16 10:05:11 -0600 | [diff] [blame] | 173 | GrPipeline pipeline(initArgs, std::move(fProcessors), state->detachAppliedClip()); |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 174 | |
| 175 | GrSwizzle swizzle = state->caps().getReadSwizzle(fAtlasProxy->backendFormat(), |
| 176 | GrColorType::kAlpha_8); |
Chris Dalton | 012f849 | 2020-03-05 11:49:15 -0700 | [diff] [blame] | 177 | |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 178 | DrawAtlasPathShader shader(fAtlasProxy.get(), swizzle, fUsesLocalCoords); |
| 179 | SkASSERT(shader.instanceStride() == Instance::Stride(fUsesLocalCoords)); |
| 180 | |
| 181 | GrProgramInfo programInfo(state->proxy()->numSamples(), state->proxy()->numStencilSamples(), |
Brian Salomon | 8afde5f | 2020-04-01 16:22:00 -0400 | [diff] [blame] | 182 | state->proxy()->backendFormat(), state->writeView()->origin(), |
Chris Dalton | 1b6a43c | 2020-09-25 12:21:18 -0600 | [diff] [blame^] | 183 | &pipeline, &GrUserStencilSettings::kUnused, &shader, |
| 184 | GrPrimitiveType::kTriangleStrip, 0, state->renderPassBarriers()); |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 185 | |
Chris Dalton | aa0e45c | 2020-03-16 10:05:11 -0600 | [diff] [blame] | 186 | state->bindPipelineAndScissorClip(programInfo, this->bounds()); |
| 187 | state->bindTextures(shader, *fAtlasProxy, pipeline); |
Greg Daniel | 426274b | 2020-07-20 11:37:38 -0400 | [diff] [blame] | 188 | state->bindBuffers(nullptr, std::move(fInstanceBuffer), nullptr); |
Chris Dalton | aa0e45c | 2020-03-16 10:05:11 -0600 | [diff] [blame] | 189 | state->drawInstanced(fInstanceCount, fBaseInstance, 4, 0); |
Chris Dalton | 4e99853 | 2020-02-10 11:06:42 -0700 | [diff] [blame] | 190 | } |