| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2017 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 Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 8 | #include "src/gpu/ops/GrTextureOp.h" | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 9 | #include <new> | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 10 | #include "include/core/SkPoint.h" | 
 | 11 | #include "include/core/SkPoint3.h" | 
 | 12 | #include "include/gpu/GrTexture.h" | 
 | 13 | #include "include/private/GrRecordingContext.h" | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 14 | #include "include/private/SkTo.h" | 
 | 15 | #include "src/core/SkMathPriv.h" | 
 | 16 | #include "src/core/SkMatrixPriv.h" | 
 | 17 | #include "src/core/SkRectPriv.h" | 
 | 18 | #include "src/gpu/GrAppliedClip.h" | 
 | 19 | #include "src/gpu/GrCaps.h" | 
 | 20 | #include "src/gpu/GrDrawOpTest.h" | 
 | 21 | #include "src/gpu/GrGeometryProcessor.h" | 
 | 22 | #include "src/gpu/GrGpu.h" | 
 | 23 | #include "src/gpu/GrMemoryPool.h" | 
 | 24 | #include "src/gpu/GrOpFlushState.h" | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 25 | #include "src/gpu/GrRecordingContextPriv.h" | 
 | 26 | #include "src/gpu/GrResourceProvider.h" | 
 | 27 | #include "src/gpu/GrResourceProviderPriv.h" | 
 | 28 | #include "src/gpu/GrShaderCaps.h" | 
 | 29 | #include "src/gpu/GrTexturePriv.h" | 
| Greg Daniel | f91aeb2 | 2019-06-18 09:58:02 -0400 | [diff] [blame] | 30 | #include "src/gpu/GrTextureProxy.h" | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 31 | #include "src/gpu/SkGr.h" | 
| Michael Ludwig | fd4f4df | 2019-05-29 09:51:09 -0400 | [diff] [blame] | 32 | #include "src/gpu/geometry/GrQuad.h" | 
| Michael Ludwig | d17e05a | 2019-06-04 09:10:34 -0400 | [diff] [blame] | 33 | #include "src/gpu/geometry/GrQuadList.h" | 
| Michael Ludwig | 0f80902 | 2019-06-04 09:14:37 -0400 | [diff] [blame] | 34 | #include "src/gpu/geometry/GrQuadUtils.h" | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 35 | #include "src/gpu/glsl/GrGLSLVarying.h" | 
 | 36 | #include "src/gpu/ops/GrMeshDrawOp.h" | 
 | 37 | #include "src/gpu/ops/GrQuadPerEdgeAA.h" | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 38 |  | 
 | 39 | namespace { | 
 | 40 |  | 
| Michael Ludwig | 460eb5e | 2018-10-29 11:09:29 -0400 | [diff] [blame] | 41 | using Domain = GrQuadPerEdgeAA::Domain; | 
| Michael Ludwig | c182b94 | 2018-11-16 10:27:51 -0500 | [diff] [blame] | 42 | using VertexSpec = GrQuadPerEdgeAA::VertexSpec; | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 43 | using ColorType = GrQuadPerEdgeAA::ColorType; | 
| Brian Salomon | b80ffee | 2018-05-23 16:39:39 -0400 | [diff] [blame] | 44 |  | 
| Brian Salomon | 246bc3d | 2018-12-06 15:33:02 -0500 | [diff] [blame] | 45 | // if normalizing the domain then pass 1/width, 1/height, 1 for iw, ih, h. Otherwise pass | 
 | 46 | // 1, 1, and height. | 
 | 47 | static SkRect compute_domain(Domain domain, GrSamplerState::Filter filter, GrSurfaceOrigin origin, | 
 | 48 |                              const SkRect& srcRect, float iw, float ih, float h) { | 
 | 49 |     static constexpr SkRect kLargeRect = {-100000, -100000, 1000000, 1000000}; | 
| Michael Ludwig | 460eb5e | 2018-10-29 11:09:29 -0400 | [diff] [blame] | 50 |     if (domain == Domain::kNo) { | 
 | 51 |         // Either the quad has no domain constraint and is batched with a domain constrained op | 
 | 52 |         // (in which case we want a domain that doesn't restrict normalized tex coords), or the | 
 | 53 |         // entire op doesn't use the domain, in which case the returned value is ignored. | 
 | 54 |         return kLargeRect; | 
 | 55 |     } | 
 | 56 |  | 
 | 57 |     auto ltrb = Sk4f::Load(&srcRect); | 
 | 58 |     if (filter == GrSamplerState::Filter::kBilerp) { | 
 | 59 |         auto rblt = SkNx_shuffle<2, 3, 0, 1>(ltrb); | 
 | 60 |         auto whwh = (rblt - ltrb).abs(); | 
 | 61 |         auto c = (rblt + ltrb) * 0.5f; | 
 | 62 |         static const Sk4f kOffsets = {0.5f, 0.5f, -0.5f, -0.5f}; | 
 | 63 |         ltrb = (whwh < 1.f).thenElse(c, ltrb + kOffsets); | 
 | 64 |     } | 
 | 65 |     ltrb *= Sk4f(iw, ih, iw, ih); | 
 | 66 |     if (origin == kBottomLeft_GrSurfaceOrigin) { | 
 | 67 |         static const Sk4f kMul = {1.f, -1.f, 1.f, -1.f}; | 
| Brian Salomon | 246bc3d | 2018-12-06 15:33:02 -0500 | [diff] [blame] | 68 |         const Sk4f kAdd = {0.f, h, 0.f, h}; | 
| Michael Ludwig | 460eb5e | 2018-10-29 11:09:29 -0400 | [diff] [blame] | 69 |         ltrb = SkNx_shuffle<0, 3, 2, 1>(kMul * ltrb + kAdd); | 
 | 70 |     } | 
 | 71 |  | 
 | 72 |     SkRect domainRect; | 
 | 73 |     ltrb.store(&domainRect); | 
 | 74 |     return domainRect; | 
 | 75 | } | 
 | 76 |  | 
| Brian Salomon | 246bc3d | 2018-12-06 15:33:02 -0500 | [diff] [blame] | 77 | // If normalizing the src quad then pass 1/width, 1/height, 1 for iw, ih, h. Otherwise pass | 
 | 78 | // 1, 1, and height. | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 79 | static GrQuad compute_src_quad_from_rect(GrSurfaceOrigin origin, const SkRect& srcRect, | 
 | 80 |                                          float iw, float ih, float h) { | 
| Michael Ludwig | 460eb5e | 2018-10-29 11:09:29 -0400 | [diff] [blame] | 81 |     // Convert the pixel-space src rectangle into normalized texture coordinates | 
 | 82 |     SkRect texRect = { | 
 | 83 |         iw * srcRect.fLeft, | 
 | 84 |         ih * srcRect.fTop, | 
 | 85 |         iw * srcRect.fRight, | 
 | 86 |         ih * srcRect.fBottom | 
 | 87 |     }; | 
 | 88 |     if (origin == kBottomLeft_GrSurfaceOrigin) { | 
| Brian Salomon | 246bc3d | 2018-12-06 15:33:02 -0500 | [diff] [blame] | 89 |         texRect.fTop = h - texRect.fTop; | 
 | 90 |         texRect.fBottom = h - texRect.fBottom; | 
| Michael Ludwig | 460eb5e | 2018-10-29 11:09:29 -0400 | [diff] [blame] | 91 |     } | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 92 |     return GrQuad(texRect); | 
| Michael Ludwig | 460eb5e | 2018-10-29 11:09:29 -0400 | [diff] [blame] | 93 | } | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 94 | // Normalizes logical src coords and corrects for origin | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 95 | static GrQuad compute_src_quad(GrSurfaceOrigin origin, const GrQuad& srcQuad, | 
 | 96 |                                float iw, float ih, float h) { | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 97 |     // The src quad should not have any perspective | 
 | 98 |     SkASSERT(!srcQuad.hasPerspective()); | 
| Michael Ludwig | b3461fa | 2019-04-30 11:50:55 -0400 | [diff] [blame] | 99 |     skvx::Vec<4, float> xs = srcQuad.x4f() * iw; | 
 | 100 |     skvx::Vec<4, float> ys = srcQuad.y4f() * ih; | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 101 |     if (origin == kBottomLeft_GrSurfaceOrigin) { | 
 | 102 |         ys = h - ys; | 
 | 103 |     } | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 104 |     return GrQuad(xs, ys, srcQuad.quadType()); | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 105 | } | 
| Michael Ludwig | 460eb5e | 2018-10-29 11:09:29 -0400 | [diff] [blame] | 106 |  | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 107 | /** | 
 | 108 |  * Op that implements GrTextureOp::Make. It draws textured quads. Each quad can modulate against a | 
 | 109 |  * the texture by color. The blend with the destination is always src-over. The edges are non-AA. | 
 | 110 |  */ | 
 | 111 | class TextureOp final : public GrMeshDrawOp { | 
 | 112 | public: | 
| Robert Phillips | b97da53 | 2019-02-12 15:24:12 -0500 | [diff] [blame] | 113 |     static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context, | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 114 |                                           sk_sp<GrTextureProxy> proxy, | 
 | 115 |                                           GrSamplerState::Filter filter, | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 116 |                                           const SkPMColor4f& color, | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 117 |                                           const SkRect& srcRect, | 
 | 118 |                                           const SkRect& dstRect, | 
 | 119 |                                           GrAAType aaType, | 
| Brian Salomon | 2213ee9 | 2018-10-02 10:44:21 -0400 | [diff] [blame] | 120 |                                           GrQuadAAFlags aaFlags, | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 121 |                                           SkCanvas::SrcRectConstraint constraint, | 
| Brian Osman | 2b23c4b | 2018-06-01 12:25:08 -0400 | [diff] [blame] | 122 |                                           const SkMatrix& viewMatrix, | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 123 |                                           sk_sp<GrColorSpaceXform> textureColorSpaceXform) { | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 124 |         GrQuad dstQuad = GrQuad::MakeFromRect(dstRect, viewMatrix); | 
| Robert Phillips | c994a93 | 2018-06-19 13:09:54 -0400 | [diff] [blame] | 125 |  | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 126 |         if (dstQuad.quadType() == GrQuad::Type::kAxisAligned) { | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 127 |             // Disable filtering if possible (note AA optimizations for rects are automatically | 
 | 128 |             // handled above in GrResolveAATypeForQuad). | 
 | 129 |             if (filter != GrSamplerState::Filter::kNearest && | 
 | 130 |                 !GrTextureOp::GetFilterHasEffect(viewMatrix, srcRect, dstRect)) { | 
 | 131 |                 filter = GrSamplerState::Filter::kNearest; | 
 | 132 |             } | 
 | 133 |         } | 
 | 134 |  | 
 | 135 |         GrOpMemoryPool* pool = context->priv().opMemoryPool(); | 
 | 136 |         // srcRect provides both local coords and domain (if needed), so use nullptr for srcQuad | 
| Brian Salomon | 2213ee9 | 2018-10-02 10:44:21 -0400 | [diff] [blame] | 137 |         return pool->allocate<TextureOp>( | 
| Michael Ludwig | 41f395d | 2019-05-23 13:59:45 -0400 | [diff] [blame] | 138 |                 std::move(proxy), filter, color, dstQuad, srcRect, constraint, | 
 | 139 |                 nullptr, aaType, aaFlags, std::move(textureColorSpaceXform)); | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 140 |     } | 
 | 141 |     static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context, | 
 | 142 |                                           sk_sp<GrTextureProxy> proxy, | 
 | 143 |                                           GrSamplerState::Filter filter, | 
 | 144 |                                           const SkPMColor4f& color, | 
 | 145 |                                           const SkPoint srcQuad[4], | 
 | 146 |                                           const SkPoint dstQuad[4], | 
 | 147 |                                           GrAAType aaType, | 
 | 148 |                                           GrQuadAAFlags aaFlags, | 
 | 149 |                                           const SkRect* domain, | 
 | 150 |                                           const SkMatrix& viewMatrix, | 
 | 151 |                                           sk_sp<GrColorSpaceXform> textureColorSpaceXform) { | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 152 |         GrQuad grDstQuad = GrQuad::MakeFromSkQuad(dstQuad, viewMatrix); | 
 | 153 |         GrQuad grSrcQuad = GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()); | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 154 |  | 
 | 155 |         // If constraint remains fast, the value in srcRect will be ignored since srcQuads provides | 
 | 156 |         // the local coordinates and a domain won't be used. | 
 | 157 |         SkRect srcRect = SkRect::MakeEmpty(); | 
 | 158 |         SkCanvas::SrcRectConstraint constraint = SkCanvas::kFast_SrcRectConstraint; | 
 | 159 |         if (domain) { | 
 | 160 |             srcRect = *domain; | 
 | 161 |             constraint = SkCanvas::kStrict_SrcRectConstraint; | 
 | 162 |         } | 
 | 163 |  | 
 | 164 |         GrOpMemoryPool* pool = context->priv().opMemoryPool(); | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 165 |         // Pass domain as srcRect if provided, but send srcQuad as a GrQuad for local coords | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 166 |         return pool->allocate<TextureOp>( | 
| Michael Ludwig | 41f395d | 2019-05-23 13:59:45 -0400 | [diff] [blame] | 167 |                 std::move(proxy), filter, color, grDstQuad, srcRect, constraint, &grSrcQuad, | 
 | 168 |                 aaType, aaFlags, std::move(textureColorSpaceXform)); | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 169 |     } | 
| Robert Phillips | b97da53 | 2019-02-12 15:24:12 -0500 | [diff] [blame] | 170 |     static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context, | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 171 |                                           const GrRenderTargetContext::TextureSetEntry set[], | 
| Brian Salomon | d003d22 | 2018-11-26 13:25:05 -0500 | [diff] [blame] | 172 |                                           int cnt, GrSamplerState::Filter filter, GrAAType aaType, | 
| Michael Ludwig | 31ba718 | 2019-04-03 10:38:06 -0400 | [diff] [blame] | 173 |                                           SkCanvas::SrcRectConstraint constraint, | 
| Brian Salomon | d003d22 | 2018-11-26 13:25:05 -0500 | [diff] [blame] | 174 |                                           const SkMatrix& viewMatrix, | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 175 |                                           sk_sp<GrColorSpaceXform> textureColorSpaceXform) { | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 176 |         size_t size = sizeof(TextureOp) + sizeof(Proxy) * (cnt - 1); | 
| Robert Phillips | 9da87e0 | 2019-02-04 13:26:26 -0500 | [diff] [blame] | 177 |         GrOpMemoryPool* pool = context->priv().opMemoryPool(); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 178 |         void* mem = pool->allocate(size); | 
| Michael Ludwig | 31ba718 | 2019-04-03 10:38:06 -0400 | [diff] [blame] | 179 |         return std::unique_ptr<GrDrawOp>(new (mem) TextureOp( | 
 | 180 |                 set, cnt, filter, aaType, constraint, viewMatrix, | 
 | 181 |                 std::move(textureColorSpaceXform))); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 182 |     } | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 183 |  | 
| Brian Salomon | 336ce7b | 2017-09-08 08:23:58 -0400 | [diff] [blame] | 184 |     ~TextureOp() override { | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 185 |         for (unsigned p = 0; p < fProxyCnt; ++p) { | 
| Robert Phillips | 3d4cac5 | 2019-06-11 08:08:08 -0400 | [diff] [blame] | 186 |             fProxies[p].fProxy->unref(); | 
| Brian Salomon | 336ce7b | 2017-09-08 08:23:58 -0400 | [diff] [blame] | 187 |         } | 
 | 188 |     } | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 189 |  | 
 | 190 |     const char* name() const override { return "TextureOp"; } | 
 | 191 |  | 
| Chris Dalton | 1706cbf | 2019-05-21 19:35:29 -0600 | [diff] [blame] | 192 |     void visitProxies(const VisitProxyFunc& func) const override { | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 193 |         for (unsigned p = 0; p < fProxyCnt; ++p) { | 
| Chris Dalton | 7eb5c0f | 2019-05-23 15:15:47 -0600 | [diff] [blame] | 194 |             bool mipped = (GrSamplerState::Filter::kMipMap == this->filter()); | 
 | 195 |             func(fProxies[p].fProxy, GrMipMapped(mipped)); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 196 |         } | 
 | 197 |     } | 
| Robert Phillips | b493eeb | 2017-09-13 13:10:52 -0400 | [diff] [blame] | 198 |  | 
| Brian Osman | 9a390ac | 2018-11-12 09:47:48 -0500 | [diff] [blame] | 199 | #ifdef SK_DEBUG | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 200 |     SkString dumpInfo() const override { | 
 | 201 |         SkString str; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 202 |         str.appendf("# draws: %d\n", fQuads.count()); | 
 | 203 |         int q = 0; | 
 | 204 |         for (unsigned p = 0; p < fProxyCnt; ++p) { | 
 | 205 |             str.appendf("Proxy ID: %d, Filter: %d\n", fProxies[p].fProxy->uniqueID().asUInt(), | 
 | 206 |                         static_cast<int>(fFilter)); | 
 | 207 |             for (int i = 0; i < fProxies[p].fQuadCnt; ++i, ++q) { | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 208 |                 GrQuad quad = fQuads[q]; | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 209 |                 const ColorDomainAndAA& info = fQuads.metadata(i); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 210 |                 str.appendf( | 
 | 211 |                         "%d: Color: 0x%08x, TexRect [L: %.2f, T: %.2f, R: %.2f, B: %.2f] " | 
 | 212 |                         "Quad [(%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f)]\n", | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 213 |                         i, info.fColor.toBytes_RGBA(), info.fSrcRect.fLeft, info.fSrcRect.fTop, | 
 | 214 |                         info.fSrcRect.fRight, info.fSrcRect.fBottom, quad.point(0).fX, | 
 | 215 |                         quad.point(0).fY, quad.point(1).fX, quad.point(1).fY, | 
 | 216 |                         quad.point(2).fX, quad.point(2).fY, quad.point(3).fX, | 
 | 217 |                         quad.point(3).fY); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 218 |             } | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 219 |         } | 
 | 220 |         str += INHERITED::dumpInfo(); | 
 | 221 |         return str; | 
 | 222 |     } | 
| Brian Osman | 9a390ac | 2018-11-12 09:47:48 -0500 | [diff] [blame] | 223 | #endif | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 224 |  | 
| Brian Osman | 5ced0bf | 2019-03-15 10:15:29 -0400 | [diff] [blame] | 225 |     GrProcessorSet::Analysis finalize( | 
| Brian Osman | 8fa7ab4 | 2019-03-18 10:22:42 -0400 | [diff] [blame] | 226 |             const GrCaps& caps, const GrAppliedClip*, GrFSAAType, GrClampType clampType) override { | 
| Brian Osman | 8fa7ab4 | 2019-03-18 10:22:42 -0400 | [diff] [blame] | 227 |         fColorType = static_cast<unsigned>(ColorType::kNone); | 
 | 228 |         for (int q = 0; q < fQuads.count(); ++q) { | 
 | 229 |             const ColorDomainAndAA& info = fQuads.metadata(q); | 
 | 230 |             auto colorType = GrQuadPerEdgeAA::MinColorType(info.fColor, clampType, caps); | 
 | 231 |             fColorType = SkTMax(fColorType, static_cast<unsigned>(colorType)); | 
 | 232 |         } | 
| Chris Dalton | 4b62aed | 2019-01-15 11:53:00 -0700 | [diff] [blame] | 233 |         return GrProcessorSet::EmptySetAnalysis(); | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 234 |     } | 
 | 235 |  | 
| Brian Salomon | 485b8c6 | 2018-01-12 15:11:06 -0500 | [diff] [blame] | 236 |     FixedFunctionFlags fixedFunctionFlags() const override { | 
 | 237 |         return this->aaType() == GrAAType::kMSAA ? FixedFunctionFlags::kUsesHWAA | 
 | 238 |                                                  : FixedFunctionFlags::kNone; | 
 | 239 |     } | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 240 |  | 
 | 241 |     DEFINE_OP_CLASS_ID | 
 | 242 |  | 
 | 243 | private: | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 244 |     friend class ::GrOpMemoryPool; | 
| Brian Salomon | 762d5e7 | 2017-12-01 10:25:08 -0500 | [diff] [blame] | 245 |  | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 246 |     // dstQuad and dstQuadType should be the geometry transformed by the view matrix. | 
 | 247 |     // srcRect represents original src rect and will be used as the domain when constraint is strict | 
 | 248 |     // If srcQuad is provided, it will be used for the local coords instead of srcRect, although | 
 | 249 |     // srcRect will still specify the domain constraint if needed. | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 250 |     TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, const SkPMColor4f& color, | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 251 |               const GrQuad& dstQuad, const SkRect& srcRect, | 
 | 252 |               SkCanvas::SrcRectConstraint constraint, const GrQuad* srcQuad, GrAAType aaType, | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 253 |               GrQuadAAFlags aaFlags, sk_sp<GrColorSpaceXform> textureColorSpaceXform) | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 254 |             : INHERITED(ClassID()) | 
| Brian Osman | 3ebd354 | 2018-07-30 14:36:53 -0400 | [diff] [blame] | 255 |             , fTextureColorSpaceXform(std::move(textureColorSpaceXform)) | 
| Robert Phillips | 3d4cac5 | 2019-06-11 08:08:08 -0400 | [diff] [blame] | 256 |             , fFilter(static_cast<unsigned>(filter)) { | 
| Michael Ludwig | 6bee776 | 2018-10-19 09:50:36 -0400 | [diff] [blame] | 257 |         // Clean up disparities between the overall aa type and edge configuration and apply | 
 | 258 |         // optimizations based on the rect and matrix when appropriate | 
| Michael Ludwig | 0f80902 | 2019-06-04 09:14:37 -0400 | [diff] [blame] | 259 |         GrQuadUtils::ResolveAAType(aaType, aaFlags, dstQuad, &aaType, &aaFlags); | 
| Michael Ludwig | 6bee776 | 2018-10-19 09:50:36 -0400 | [diff] [blame] | 260 |         fAAType = static_cast<unsigned>(aaType); | 
 | 261 |  | 
| Brian Salomon | f170904 | 2018-10-03 11:57:00 -0400 | [diff] [blame] | 262 |         // We expect our caller to have already caught this optimization. | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 263 |         SkASSERT(!srcRect.contains(proxy->getWorstCaseBoundsRect()) || | 
| Brian Salomon | f170904 | 2018-10-03 11:57:00 -0400 | [diff] [blame] | 264 |                  constraint == SkCanvas::kFast_SrcRectConstraint); | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 265 |  | 
| Brian Salomon | f09abc5 | 2018-10-03 15:59:04 -0400 | [diff] [blame] | 266 |         // We may have had a strict constraint with nearest filter solely due to possible AA bloat. | 
 | 267 |         // If we don't have (or determined we don't need) coverage AA then we can skip using a | 
 | 268 |         // domain. | 
 | 269 |         if (constraint == SkCanvas::kStrict_SrcRectConstraint && | 
| Brian Salomon | 0087c83 | 2018-10-15 14:48:20 -0400 | [diff] [blame] | 270 |             this->filter() == GrSamplerState::Filter::kNearest && | 
| Michael Ludwig | 6bee776 | 2018-10-19 09:50:36 -0400 | [diff] [blame] | 271 |             aaType != GrAAType::kCoverage) { | 
| Brian Salomon | f09abc5 | 2018-10-03 15:59:04 -0400 | [diff] [blame] | 272 |             constraint = SkCanvas::kFast_SrcRectConstraint; | 
 | 273 |         } | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 274 |  | 
 | 275 |         Domain domain = constraint == SkCanvas::kStrict_SrcRectConstraint ? Domain::kYes | 
 | 276 |                                                                           : Domain::kNo; | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 277 |         // Initially, if srcQuad is provided it will always be at index 0 of fSrcQuads | 
| Michael Ludwig | 41f395d | 2019-05-23 13:59:45 -0400 | [diff] [blame] | 278 |         fQuads.push_back(dstQuad, {color, srcRect, srcQuad ? 0 : -1, domain, aaFlags}); | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 279 |         if (srcQuad) { | 
| Michael Ludwig | 41f395d | 2019-05-23 13:59:45 -0400 | [diff] [blame] | 280 |             fSrcQuads.push_back(*srcQuad); | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 281 |         } | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 282 |         fProxyCnt = 1; | 
 | 283 |         fProxies[0] = {proxy.release(), 1}; | 
| Michael Ludwig | 41f395d | 2019-05-23 13:59:45 -0400 | [diff] [blame] | 284 |         this->setBounds(dstQuad.bounds(), HasAABloat(aaType == GrAAType::kCoverage), | 
 | 285 |                         IsZeroArea::kNo); | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 286 |         fDomain = static_cast<unsigned>(domain); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 287 |     } | 
 | 288 |     TextureOp(const GrRenderTargetContext::TextureSetEntry set[], int cnt, | 
| Michael Ludwig | 31ba718 | 2019-04-03 10:38:06 -0400 | [diff] [blame] | 289 |               GrSamplerState::Filter filter, GrAAType aaType, | 
 | 290 |               SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix, | 
| Brian Salomon | d003d22 | 2018-11-26 13:25:05 -0500 | [diff] [blame] | 291 |               sk_sp<GrColorSpaceXform> textureColorSpaceXform) | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 292 |             : INHERITED(ClassID()) | 
 | 293 |             , fTextureColorSpaceXform(std::move(textureColorSpaceXform)) | 
| Robert Phillips | 3d4cac5 | 2019-06-11 08:08:08 -0400 | [diff] [blame] | 294 |             , fFilter(static_cast<unsigned>(filter)) { | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 295 |         fProxyCnt = SkToUInt(cnt); | 
 | 296 |         SkRect bounds = SkRectPriv::MakeLargestInverted(); | 
| Michael Ludwig | 6bee776 | 2018-10-19 09:50:36 -0400 | [diff] [blame] | 297 |         GrAAType overallAAType = GrAAType::kNone; // aa type maximally compatible with all dst rects | 
| Brian Salomon | 0087c83 | 2018-10-15 14:48:20 -0400 | [diff] [blame] | 298 |         bool mustFilter = false; | 
| Michael Ludwig | 7ae2ab5 | 2019-03-05 16:00:20 -0500 | [diff] [blame] | 299 |         // Most dst rects are transformed by the same view matrix, so their quad types start | 
 | 300 |         // identical, unless an entry provides a dstClip or additional transform that changes it. | 
 | 301 |         // The quad list will automatically adapt to that. | 
| Michael Ludwig | 41f395d | 2019-05-23 13:59:45 -0400 | [diff] [blame] | 302 |         fQuads.reserve(cnt, viewMatrix.hasPerspective()); | 
| Brian Salomon | 1d83542 | 2019-03-13 16:11:44 -0400 | [diff] [blame] | 303 |         bool allOpaque = true; | 
| Michael Ludwig | 31ba718 | 2019-04-03 10:38:06 -0400 | [diff] [blame] | 304 |         Domain netDomain = Domain::kNo; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 305 |         for (unsigned p = 0; p < fProxyCnt; ++p) { | 
 | 306 |             fProxies[p].fProxy = SkRef(set[p].fProxy.get()); | 
 | 307 |             fProxies[p].fQuadCnt = 1; | 
 | 308 |             SkASSERT(fProxies[p].fProxy->textureType() == fProxies[0].fProxy->textureType()); | 
 | 309 |             SkASSERT(fProxies[p].fProxy->config() == fProxies[0].fProxy->config()); | 
| Michael Ludwig | ce62dec | 2019-02-19 11:48:46 -0500 | [diff] [blame] | 310 |  | 
| Michael Ludwig | 7ae2ab5 | 2019-03-05 16:00:20 -0500 | [diff] [blame] | 311 |             SkMatrix ctm = viewMatrix; | 
 | 312 |             if (set[p].fPreViewMatrix) { | 
 | 313 |                 ctm.preConcat(*set[p].fPreViewMatrix); | 
 | 314 |             } | 
 | 315 |  | 
| Michael Ludwig | ce62dec | 2019-02-19 11:48:46 -0500 | [diff] [blame] | 316 |             // Use dstRect unless dstClip is provided, which is assumed to be a quad | 
| Michael Ludwig | 1433cfd | 2019-02-27 17:12:30 -0500 | [diff] [blame] | 317 |             auto quad = set[p].fDstClipQuad == nullptr ? | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 318 |                     GrQuad::MakeFromRect(set[p].fDstRect, ctm) : | 
 | 319 |                     GrQuad::MakeFromSkQuad(set[p].fDstClipQuad, ctm); | 
| Michael Ludwig | ce62dec | 2019-02-19 11:48:46 -0500 | [diff] [blame] | 320 |  | 
| Michael Ludwig | 41f395d | 2019-05-23 13:59:45 -0400 | [diff] [blame] | 321 |             bounds.joinPossiblyEmptyRect(quad.bounds()); | 
| Michael Ludwig | 6bee776 | 2018-10-19 09:50:36 -0400 | [diff] [blame] | 322 |             GrQuadAAFlags aaFlags; | 
 | 323 |             // Don't update the overall aaType, might be inappropriate for some of the quads | 
 | 324 |             GrAAType aaForQuad; | 
| Michael Ludwig | 0f80902 | 2019-06-04 09:14:37 -0400 | [diff] [blame] | 325 |             GrQuadUtils::ResolveAAType(aaType, set[p].fAAFlags, quad, &aaForQuad, &aaFlags); | 
| Michael Ludwig | 6bee776 | 2018-10-19 09:50:36 -0400 | [diff] [blame] | 326 |             // Resolve sets aaForQuad to aaType or None, there is never a change between aa methods | 
 | 327 |             SkASSERT(aaForQuad == GrAAType::kNone || aaForQuad == aaType); | 
 | 328 |             if (overallAAType == GrAAType::kNone && aaForQuad != GrAAType::kNone) { | 
 | 329 |                 overallAAType = aaType; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 330 |             } | 
| Brian Salomon | 0087c83 | 2018-10-15 14:48:20 -0400 | [diff] [blame] | 331 |             if (!mustFilter && this->filter() != GrSamplerState::Filter::kNearest) { | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 332 |                 mustFilter = quad.quadType() != GrQuad::Type::kAxisAligned || | 
| Michael Ludwig | 7ae2ab5 | 2019-03-05 16:00:20 -0500 | [diff] [blame] | 333 |                              GrTextureOp::GetFilterHasEffect(ctm, set[p].fSrcRect, | 
| Michael Ludwig | a3c45c7 | 2019-01-17 17:26:48 -0500 | [diff] [blame] | 334 |                                                              set[p].fDstRect); | 
| Brian Salomon | 0087c83 | 2018-10-15 14:48:20 -0400 | [diff] [blame] | 335 |             } | 
| Michael Ludwig | 31ba718 | 2019-04-03 10:38:06 -0400 | [diff] [blame] | 336 |             Domain domainForQuad = Domain::kNo; | 
 | 337 |             if (constraint == SkCanvas::kStrict_SrcRectConstraint) { | 
 | 338 |                 // Check (briefly) if the strict constraint is needed for this set entry | 
 | 339 |                 if (!set[p].fSrcRect.contains(fProxies[p].fProxy->getWorstCaseBoundsRect()) && | 
 | 340 |                     (mustFilter || aaForQuad == GrAAType::kCoverage)) { | 
 | 341 |                     // Can't rely on hardware clamping and the draw will access outer texels | 
 | 342 |                     // for AA and/or bilerp | 
 | 343 |                     netDomain = Domain::kYes; | 
 | 344 |                     domainForQuad = Domain::kYes; | 
 | 345 |                 } | 
 | 346 |             } | 
| Brian Salomon | d003d22 | 2018-11-26 13:25:05 -0500 | [diff] [blame] | 347 |             float alpha = SkTPin(set[p].fAlpha, 0.f, 1.f); | 
| Brian Salomon | 1d83542 | 2019-03-13 16:11:44 -0400 | [diff] [blame] | 348 |             allOpaque &= (1.f == alpha); | 
| Brian Salomon | d003d22 | 2018-11-26 13:25:05 -0500 | [diff] [blame] | 349 |             SkPMColor4f color{alpha, alpha, alpha, alpha}; | 
| Michael Ludwig | ce62dec | 2019-02-19 11:48:46 -0500 | [diff] [blame] | 350 |             int srcQuadIndex = -1; | 
| Michael Ludwig | 1433cfd | 2019-02-27 17:12:30 -0500 | [diff] [blame] | 351 |             if (set[p].fDstClipQuad) { | 
| Michael Ludwig | ce62dec | 2019-02-19 11:48:46 -0500 | [diff] [blame] | 352 |                 // Derive new source coordinates that match dstClip's relative locations in dstRect, | 
 | 353 |                 // but with respect to srcRect | 
 | 354 |                 SkPoint srcQuad[4]; | 
| Michael Ludwig | 1433cfd | 2019-02-27 17:12:30 -0500 | [diff] [blame] | 355 |                 GrMapRectPoints(set[p].fDstRect, set[p].fSrcRect, set[p].fDstClipQuad, srcQuad, 4); | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 356 |                 fSrcQuads.push_back(GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I())); | 
| Michael Ludwig | ce62dec | 2019-02-19 11:48:46 -0500 | [diff] [blame] | 357 |                 srcQuadIndex = fSrcQuads.count() - 1; | 
 | 358 |             } | 
| Michael Ludwig | 41f395d | 2019-05-23 13:59:45 -0400 | [diff] [blame] | 359 |             fQuads.push_back(quad, {color, set[p].fSrcRect, srcQuadIndex, domainForQuad, aaFlags}); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 360 |         } | 
| Michael Ludwig | 6bee776 | 2018-10-19 09:50:36 -0400 | [diff] [blame] | 361 |         fAAType = static_cast<unsigned>(overallAAType); | 
| Brian Salomon | 0087c83 | 2018-10-15 14:48:20 -0400 | [diff] [blame] | 362 |         if (!mustFilter) { | 
 | 363 |             fFilter = static_cast<unsigned>(GrSamplerState::Filter::kNearest); | 
 | 364 |         } | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 365 |         this->setBounds(bounds, HasAABloat(this->aaType() == GrAAType::kCoverage), IsZeroArea::kNo); | 
| Michael Ludwig | 31ba718 | 2019-04-03 10:38:06 -0400 | [diff] [blame] | 366 |         fDomain = static_cast<unsigned>(netDomain); | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 367 |     } | 
 | 368 |  | 
| Brian Salomon | 574d616 | 2018-11-19 16:57:25 -0500 | [diff] [blame] | 369 |     void tess(void* v, const VertexSpec& spec, const GrTextureProxy* proxy, int start, | 
 | 370 |               int cnt) const { | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 371 |         TRACE_EVENT0("skia", TRACE_FUNC); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 372 |         auto origin = proxy->origin(); | 
 | 373 |         const auto* texture = proxy->peekTexture(); | 
| Brian Salomon | 246bc3d | 2018-12-06 15:33:02 -0500 | [diff] [blame] | 374 |         float iw, ih, h; | 
 | 375 |         if (proxy->textureType() == GrTextureType::kRectangle) { | 
 | 376 |             iw = ih = 1.f; | 
 | 377 |             h = texture->height(); | 
 | 378 |         } else { | 
 | 379 |             iw = 1.f / texture->width(); | 
 | 380 |             ih = 1.f / texture->height(); | 
 | 381 |             h = 1.f; | 
 | 382 |         } | 
| Brian Salomon | 7eae3e0 | 2018-08-07 14:02:38 +0000 | [diff] [blame] | 383 |  | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 384 |         for (int i = start; i < start + cnt; ++i) { | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 385 |             const GrQuad& device = fQuads[i]; | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 386 |             const ColorDomainAndAA& info = fQuads.metadata(i); | 
 | 387 |  | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 388 |             GrQuad srcQuad = info.fSrcQuadIndex >= 0 ? | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 389 |                     compute_src_quad(origin, fSrcQuads[info.fSrcQuadIndex], iw, ih, h) : | 
 | 390 |                     compute_src_quad_from_rect(origin, info.fSrcRect, iw, ih, h); | 
| Brian Salomon | 246bc3d | 2018-12-06 15:33:02 -0500 | [diff] [blame] | 391 |             SkRect domain = | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 392 |                     compute_domain(info.domain(), this->filter(), origin, info.fSrcRect, iw, ih, h); | 
 | 393 |             v = GrQuadPerEdgeAA::Tessellate(v, spec, device, info.fColor, srcQuad, domain, | 
 | 394 |                                             info.aaFlags()); | 
| Brian Salomon | 17031a7 | 2018-05-22 14:14:07 -0400 | [diff] [blame] | 395 |         } | 
 | 396 |     } | 
 | 397 |  | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 398 |     void onPrepareDraws(Target* target) override { | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 399 |         TRACE_EVENT0("skia", TRACE_FUNC); | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 400 |         GrQuad::Type quadType = GrQuad::Type::kAxisAligned; | 
 | 401 |         GrQuad::Type srcQuadType = GrQuad::Type::kAxisAligned; | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 402 |         Domain domain = Domain::kNo; | 
| Brian Salomon | 1d83542 | 2019-03-13 16:11:44 -0400 | [diff] [blame] | 403 |         ColorType colorType = ColorType::kNone; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 404 |         int numProxies = 0; | 
| Brian Salomon | 4b8178f | 2018-10-12 13:18:27 -0400 | [diff] [blame] | 405 |         int numTotalQuads = 0; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 406 |         auto textureType = fProxies[0].fProxy->textureType(); | 
 | 407 |         auto config = fProxies[0].fProxy->config(); | 
| Greg Daniel | 2c3398d | 2019-06-19 11:58:01 -0400 | [diff] [blame^] | 408 |         const GrSwizzle& swizzle = fProxies[0].fProxy->textureSwizzle(); | 
| Brian Salomon | ae7d770 | 2018-10-14 15:05:45 -0400 | [diff] [blame] | 409 |         GrAAType aaType = this->aaType(); | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 410 |         for (const auto& op : ChainRange<TextureOp>(this)) { | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 411 |             if (op.fQuads.quadType() > quadType) { | 
 | 412 |                 quadType = op.fQuads.quadType(); | 
| Michael Ludwig | f995c05 | 2018-11-26 15:24:29 -0500 | [diff] [blame] | 413 |             } | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 414 |             if (op.fSrcQuads.quadType() > srcQuadType) { | 
 | 415 |                 // Should only become more general if there are quads to use instead of fSrcRect | 
 | 416 |                 SkASSERT(op.fSrcQuads.count() > 0); | 
 | 417 |                 srcQuadType = op.fSrcQuads.quadType(); | 
 | 418 |             } | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 419 |             if (op.fDomain) { | 
 | 420 |                 domain = Domain::kYes; | 
 | 421 |             } | 
| Brian Salomon | 1d83542 | 2019-03-13 16:11:44 -0400 | [diff] [blame] | 422 |             colorType = SkTMax(colorType, static_cast<ColorType>(op.fColorType)); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 423 |             numProxies += op.fProxyCnt; | 
 | 424 |             for (unsigned p = 0; p < op.fProxyCnt; ++p) { | 
| Brian Salomon | 4b8178f | 2018-10-12 13:18:27 -0400 | [diff] [blame] | 425 |                 numTotalQuads += op.fProxies[p].fQuadCnt; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 426 |                 auto* proxy = op.fProxies[p].fProxy; | 
| Robert Phillips | 12c4629 | 2019-04-23 07:36:17 -0400 | [diff] [blame] | 427 |                 if (!proxy->isInstantiated()) { | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 428 |                     return; | 
 | 429 |                 } | 
 | 430 |                 SkASSERT(proxy->config() == config); | 
 | 431 |                 SkASSERT(proxy->textureType() == textureType); | 
| Greg Daniel | 2c3398d | 2019-06-19 11:58:01 -0400 | [diff] [blame^] | 432 |                 SkASSERT(proxy->textureSwizzle() == swizzle); | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 433 |             } | 
| Brian Salomon | ae7d770 | 2018-10-14 15:05:45 -0400 | [diff] [blame] | 434 |             if (op.aaType() == GrAAType::kCoverage) { | 
 | 435 |                 SkASSERT(aaType == GrAAType::kCoverage || aaType == GrAAType::kNone); | 
 | 436 |                 aaType = GrAAType::kCoverage; | 
 | 437 |             } | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 438 |         } | 
| Brian Salomon | 336ce7b | 2017-09-08 08:23:58 -0400 | [diff] [blame] | 439 |  | 
| Brian Salomon | 1d83542 | 2019-03-13 16:11:44 -0400 | [diff] [blame] | 440 |         VertexSpec vertexSpec(quadType, colorType, srcQuadType, /* hasLocal */ true, domain, aaType, | 
| Michael Ludwig | 93aeba0 | 2018-12-21 09:50:31 -0500 | [diff] [blame] | 441 |                               /* alpha as coverage */ true); | 
| Michael Ludwig | c182b94 | 2018-11-16 10:27:51 -0500 | [diff] [blame] | 442 |  | 
| Greg Daniel | 7a82edf | 2018-12-04 10:54:34 -0500 | [diff] [blame] | 443 |         GrSamplerState samplerState = GrSamplerState(GrSamplerState::WrapMode::kClamp, | 
 | 444 |                                                      this->filter()); | 
 | 445 |         GrGpu* gpu = target->resourceProvider()->priv().gpu(); | 
 | 446 |         uint32_t extraSamplerKey = gpu->getExtraSamplerKeyForProgram( | 
 | 447 |                 samplerState, fProxies[0].fProxy->backendFormat()); | 
 | 448 |  | 
| Michael Ludwig | 467994d | 2018-12-03 14:58:31 +0000 | [diff] [blame] | 449 |         sk_sp<GrGeometryProcessor> gp = GrQuadPerEdgeAA::MakeTexturedProcessor( | 
 | 450 |                 vertexSpec, *target->caps().shaderCaps(), | 
| Greg Daniel | 2c3398d | 2019-06-19 11:58:01 -0400 | [diff] [blame^] | 451 |                 textureType, config, samplerState, swizzle, extraSamplerKey, | 
| Greg Daniel | 7a82edf | 2018-12-04 10:54:34 -0500 | [diff] [blame] | 452 |                 std::move(fTextureColorSpaceXform)); | 
 | 453 |  | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 454 |         // We'll use a dynamic state array for the GP textures when there are multiple ops. | 
 | 455 |         // Otherwise, we use fixed dynamic state to specify the single op's proxy. | 
 | 456 |         GrPipeline::DynamicStateArrays* dynamicStateArrays = nullptr; | 
 | 457 |         GrPipeline::FixedDynamicState* fixedDynamicState; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 458 |         if (numProxies > 1) { | 
 | 459 |             dynamicStateArrays = target->allocDynamicStateArrays(numProxies, 1, false); | 
| Chris Dalton | 07cdcfc9 | 2019-02-26 11:13:22 -0700 | [diff] [blame] | 460 |             fixedDynamicState = target->makeFixedDynamicState(0); | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 461 |         } else { | 
| Chris Dalton | 07cdcfc9 | 2019-02-26 11:13:22 -0700 | [diff] [blame] | 462 |             fixedDynamicState = target->makeFixedDynamicState(1); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 463 |             fixedDynamicState->fPrimitiveProcessorTextures[0] = fProxies[0].fProxy; | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 464 |         } | 
| Brian Salomon | 92be2f7 | 2018-06-19 14:33:47 -0400 | [diff] [blame] | 465 |  | 
| Michael Ludwig | c182b94 | 2018-11-16 10:27:51 -0500 | [diff] [blame] | 466 |         size_t vertexSize = gp->vertexStride(); | 
| Brian Salomon | 92be2f7 | 2018-06-19 14:33:47 -0400 | [diff] [blame] | 467 |  | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 468 |         GrMesh* meshes = target->allocMeshes(numProxies); | 
| Brian Salomon | 12d2264 | 2019-01-29 14:38:50 -0500 | [diff] [blame] | 469 |         sk_sp<const GrBuffer> vbuffer; | 
| Brian Salomon | 4b8178f | 2018-10-12 13:18:27 -0400 | [diff] [blame] | 470 |         int vertexOffsetInBuffer = 0; | 
| Michael Ludwig | 93aeba0 | 2018-12-21 09:50:31 -0500 | [diff] [blame] | 471 |         int numQuadVerticesLeft = numTotalQuads * vertexSpec.verticesPerQuad(); | 
| Brian Salomon | 4b8178f | 2018-10-12 13:18:27 -0400 | [diff] [blame] | 472 |         int numAllocatedVertices = 0; | 
 | 473 |         void* vdata = nullptr; | 
 | 474 |  | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 475 |         int m = 0; | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 476 |         for (const auto& op : ChainRange<TextureOp>(this)) { | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 477 |             int q = 0; | 
 | 478 |             for (unsigned p = 0; p < op.fProxyCnt; ++p) { | 
 | 479 |                 int quadCnt = op.fProxies[p].fQuadCnt; | 
 | 480 |                 auto* proxy = op.fProxies[p].fProxy; | 
| Michael Ludwig | 93aeba0 | 2018-12-21 09:50:31 -0500 | [diff] [blame] | 481 |                 int meshVertexCnt = quadCnt * vertexSpec.verticesPerQuad(); | 
| Brian Salomon | 4b8178f | 2018-10-12 13:18:27 -0400 | [diff] [blame] | 482 |                 if (numAllocatedVertices < meshVertexCnt) { | 
 | 483 |                     vdata = target->makeVertexSpaceAtLeast( | 
 | 484 |                             vertexSize, meshVertexCnt, numQuadVerticesLeft, &vbuffer, | 
 | 485 |                             &vertexOffsetInBuffer, &numAllocatedVertices); | 
 | 486 |                     SkASSERT(numAllocatedVertices <= numQuadVerticesLeft); | 
 | 487 |                     if (!vdata) { | 
 | 488 |                         SkDebugf("Could not allocate vertices\n"); | 
 | 489 |                         return; | 
 | 490 |                     } | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 491 |                 } | 
| Brian Salomon | 4b8178f | 2018-10-12 13:18:27 -0400 | [diff] [blame] | 492 |                 SkASSERT(numAllocatedVertices >= meshVertexCnt); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 493 |  | 
| Michael Ludwig | c182b94 | 2018-11-16 10:27:51 -0500 | [diff] [blame] | 494 |                 op.tess(vdata, vertexSpec, proxy, q, quadCnt); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 495 |  | 
| Michael Ludwig | 93aeba0 | 2018-12-21 09:50:31 -0500 | [diff] [blame] | 496 |                 if (!GrQuadPerEdgeAA::ConfigureMeshIndices(target, &(meshes[m]), vertexSpec, | 
 | 497 |                                                            quadCnt)) { | 
 | 498 |                     SkDebugf("Could not allocate indices"); | 
 | 499 |                     return; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 500 |                 } | 
| Brian Salomon | 4b8178f | 2018-10-12 13:18:27 -0400 | [diff] [blame] | 501 |                 meshes[m].setVertexData(vbuffer, vertexOffsetInBuffer); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 502 |                 if (dynamicStateArrays) { | 
 | 503 |                     dynamicStateArrays->fPrimitiveProcessorTextures[m] = proxy; | 
 | 504 |                 } | 
 | 505 |                 ++m; | 
| Brian Salomon | 4b8178f | 2018-10-12 13:18:27 -0400 | [diff] [blame] | 506 |                 numAllocatedVertices -= meshVertexCnt; | 
 | 507 |                 numQuadVerticesLeft -= meshVertexCnt; | 
 | 508 |                 vertexOffsetInBuffer += meshVertexCnt; | 
 | 509 |                 vdata = reinterpret_cast<char*>(vdata) + vertexSize * meshVertexCnt; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 510 |                 q += quadCnt; | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 511 |             } | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 512 |         } | 
| Brian Salomon | 4b8178f | 2018-10-12 13:18:27 -0400 | [diff] [blame] | 513 |         SkASSERT(!numQuadVerticesLeft); | 
 | 514 |         SkASSERT(!numAllocatedVertices); | 
| Chris Dalton | 07cdcfc9 | 2019-02-26 11:13:22 -0700 | [diff] [blame] | 515 |         target->recordDraw( | 
 | 516 |                 std::move(gp), meshes, numProxies, fixedDynamicState, dynamicStateArrays); | 
 | 517 |     } | 
 | 518 |  | 
 | 519 |     void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override { | 
 | 520 |         auto pipelineFlags = (GrAAType::kMSAA == this->aaType()) | 
| Chris Dalton | baa1b35 | 2019-04-03 12:03:00 -0600 | [diff] [blame] | 521 |                 ? GrPipeline::InputFlags::kHWAntialias | 
 | 522 |                 : GrPipeline::InputFlags::kNone; | 
| Chris Dalton | 07cdcfc9 | 2019-02-26 11:13:22 -0700 | [diff] [blame] | 523 |         flushState->executeDrawsAndUploadsForMeshDrawOp( | 
 | 524 |                 this, chainBounds, GrProcessorSet::MakeEmptySet(), pipelineFlags); | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 525 |     } | 
 | 526 |  | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 527 |     CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override { | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 528 |         TRACE_EVENT0("skia", TRACE_FUNC); | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 529 |         const auto* that = t->cast<TextureOp>(); | 
| Michael Ludwig | 2929f51 | 2019-04-19 13:05:56 -0400 | [diff] [blame] | 530 |         if (fDomain != that->fDomain) { | 
 | 531 |             // It is technically possible to combine operations across domain modes, but performance | 
 | 532 |             // testing suggests it's better to make more draw calls where some take advantage of | 
 | 533 |             // the more optimal shader path without coordinate clamping. | 
 | 534 |             return CombineResult::kCannotCombine; | 
 | 535 |         } | 
| Brian Osman | 3ebd354 | 2018-07-30 14:36:53 -0400 | [diff] [blame] | 536 |         if (!GrColorSpaceXform::Equals(fTextureColorSpaceXform.get(), | 
 | 537 |                                        that->fTextureColorSpaceXform.get())) { | 
| Brian Salomon | 7eae3e0 | 2018-08-07 14:02:38 +0000 | [diff] [blame] | 538 |             return CombineResult::kCannotCombine; | 
| Brian Osman | 3ebd354 | 2018-07-30 14:36:53 -0400 | [diff] [blame] | 539 |         } | 
| Brian Salomon | ae7d770 | 2018-10-14 15:05:45 -0400 | [diff] [blame] | 540 |         bool upgradeToCoverageAAOnMerge = false; | 
| Brian Salomon | 485b8c6 | 2018-01-12 15:11:06 -0500 | [diff] [blame] | 541 |         if (this->aaType() != that->aaType()) { | 
| Brian Salomon | ae7d770 | 2018-10-14 15:05:45 -0400 | [diff] [blame] | 542 |             if (!((this->aaType() == GrAAType::kCoverage && that->aaType() == GrAAType::kNone) || | 
 | 543 |                   (that->aaType() == GrAAType::kCoverage && this->aaType() == GrAAType::kNone))) { | 
 | 544 |                 return CombineResult::kCannotCombine; | 
 | 545 |             } | 
 | 546 |             upgradeToCoverageAAOnMerge = true; | 
| Brian Salomon | b5ef1f9 | 2018-01-11 11:46:21 -0500 | [diff] [blame] | 547 |         } | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 548 |         if (fFilter != that->fFilter) { | 
 | 549 |             return CombineResult::kCannotCombine; | 
 | 550 |         } | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 551 |         auto thisProxy = fProxies[0].fProxy; | 
 | 552 |         auto thatProxy = that->fProxies[0].fProxy; | 
 | 553 |         if (fProxyCnt > 1 || that->fProxyCnt > 1 || | 
| Brian Salomon | 588cec7 | 2018-11-14 13:56:37 -0500 | [diff] [blame] | 554 |             thisProxy->uniqueID() != thatProxy->uniqueID()) { | 
 | 555 |             // We can't merge across different proxies. Check if 'this' can be chained with 'that'. | 
| Greg Daniel | 45723ac | 2018-11-30 10:12:43 -0500 | [diff] [blame] | 556 |             if (GrTextureProxy::ProxiesAreCompatibleAsDynamicState(thisProxy, thatProxy) && | 
| Brian Salomon | f723264 | 2018-09-19 08:58:08 -0400 | [diff] [blame] | 557 |                 caps.dynamicStateArrayGeometryProcessorTextureSupport()) { | 
 | 558 |                 return CombineResult::kMayChain; | 
 | 559 |             } | 
| Brian Salomon | 7eae3e0 | 2018-08-07 14:02:38 +0000 | [diff] [blame] | 560 |             return CombineResult::kCannotCombine; | 
| Brian Salomon | 336ce7b | 2017-09-08 08:23:58 -0400 | [diff] [blame] | 561 |         } | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 562 |  | 
| Brian Salomon | b80ffee | 2018-05-23 16:39:39 -0400 | [diff] [blame] | 563 |         fDomain |= that->fDomain; | 
| Brian Salomon | 1d83542 | 2019-03-13 16:11:44 -0400 | [diff] [blame] | 564 |         fColorType = SkTMax(fColorType, that->fColorType); | 
| Brian Salomon | ae7d770 | 2018-10-14 15:05:45 -0400 | [diff] [blame] | 565 |         if (upgradeToCoverageAAOnMerge) { | 
 | 566 |             fAAType = static_cast<unsigned>(GrAAType::kCoverage); | 
 | 567 |         } | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 568 |  | 
 | 569 |         // Concatenate quad lists together, updating the fSrcQuadIndex in the appended quads | 
 | 570 |         // to account for the new starting index in fSrcQuads | 
 | 571 |         int srcQuadOffset = fSrcQuads.count(); | 
 | 572 |         int oldQuadCount = fQuads.count(); | 
 | 573 |  | 
 | 574 |         fSrcQuads.concat(that->fSrcQuads); | 
 | 575 |         fQuads.concat(that->fQuads); | 
 | 576 |         fProxies[0].fQuadCnt += that->fQuads.count(); | 
 | 577 |  | 
 | 578 |         if (that->fSrcQuads.count() > 0) { | 
 | 579 |             // Some of the concatenated quads pointed to fSrcQuads, so adjust the indices for the | 
 | 580 |             // newly appended quads | 
 | 581 |             for (int i = oldQuadCount; i < fQuads.count(); ++i) { | 
 | 582 |                 if (fQuads.metadata(i).fSrcQuadIndex >= 0) { | 
 | 583 |                     fQuads.metadata(i).fSrcQuadIndex += srcQuadOffset; | 
 | 584 |                 } | 
 | 585 |             } | 
 | 586 |         } | 
 | 587 |  | 
 | 588 |         // Confirm all tracked state makes sense when in debug builds | 
 | 589 | #ifdef SK_DEBUG | 
 | 590 |         SkASSERT(fSrcQuads.count() <= fQuads.count()); | 
 | 591 |         for (int i = 0; i < fQuads.count(); ++i) { | 
 | 592 |             int srcIndex = fQuads.metadata(i).fSrcQuadIndex; | 
 | 593 |             if (srcIndex >= 0) { | 
 | 594 |                 // Make sure it points to a valid index, in the right region of the list | 
 | 595 |                 SkASSERT(srcIndex < fSrcQuads.count()); | 
 | 596 |                 SkASSERT((i < oldQuadCount && srcIndex < srcQuadOffset) || | 
 | 597 |                          (i >= oldQuadCount && srcIndex >= srcQuadOffset)); | 
 | 598 |             } | 
 | 599 |         } | 
 | 600 | #endif | 
| Brian Salomon | 7eae3e0 | 2018-08-07 14:02:38 +0000 | [diff] [blame] | 601 |         return CombineResult::kMerged; | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 602 |     } | 
 | 603 |  | 
| Brian Salomon | 485b8c6 | 2018-01-12 15:11:06 -0500 | [diff] [blame] | 604 |     GrAAType aaType() const { return static_cast<GrAAType>(fAAType); } | 
| Brian Salomon | 0087c83 | 2018-10-15 14:48:20 -0400 | [diff] [blame] | 605 |     GrSamplerState::Filter filter() const { return static_cast<GrSamplerState::Filter>(fFilter); } | 
| Brian Salomon | b5ef1f9 | 2018-01-11 11:46:21 -0500 | [diff] [blame] | 606 |  | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 607 |     struct ColorDomainAndAA { | 
 | 608 |         // Special constructor to convert enums into the packed bits, which should not delete | 
 | 609 |         // the implicit move constructor (but it does require us to declare an empty ctor for | 
 | 610 |         // use with the GrTQuadList). | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 611 |         ColorDomainAndAA(const SkPMColor4f& color, const SkRect& srcRect, int srcQuadIndex, | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 612 |                          Domain hasDomain, GrQuadAAFlags aaFlags) | 
 | 613 |                 : fColor(color) | 
 | 614 |                 , fSrcRect(srcRect) | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 615 |                 , fSrcQuadIndex(srcQuadIndex) | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 616 |                 , fHasDomain(static_cast<unsigned>(hasDomain)) | 
| Brian Salomon | 2213ee9 | 2018-10-02 10:44:21 -0400 | [diff] [blame] | 617 |                 , fAAFlags(static_cast<unsigned>(aaFlags)) { | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 618 |             SkASSERT(fHasDomain == static_cast<unsigned>(hasDomain)); | 
| Brian Salomon | 2213ee9 | 2018-10-02 10:44:21 -0400 | [diff] [blame] | 619 |             SkASSERT(fAAFlags == static_cast<unsigned>(aaFlags)); | 
 | 620 |         } | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 621 |         ColorDomainAndAA() = default; | 
| Michael Ludwig | 23d8943e | 2019-01-04 14:51:40 +0000 | [diff] [blame] | 622 |  | 
| Michael Ludwig | 23d8943e | 2019-01-04 14:51:40 +0000 | [diff] [blame] | 623 |         SkPMColor4f fColor; | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 624 |         // Even if fSrcQuadIndex provides source coords, use fSrcRect for domain constraint | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 625 |         SkRect fSrcRect; | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 626 |         // If >= 0, use to access fSrcQuads instead of fSrcRect for the source coordinates | 
 | 627 |         int fSrcQuadIndex; | 
| Michael Ludwig | 23d8943e | 2019-01-04 14:51:40 +0000 | [diff] [blame] | 628 |         unsigned fHasDomain : 1; | 
 | 629 |         unsigned fAAFlags : 4; | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 630 |  | 
 | 631 |         Domain domain() const { return Domain(fHasDomain); } | 
 | 632 |         GrQuadAAFlags aaFlags() const { return static_cast<GrQuadAAFlags>(fAAFlags); } | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 633 |     }; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 634 |     struct Proxy { | 
 | 635 |         GrTextureProxy* fProxy; | 
 | 636 |         int fQuadCnt; | 
 | 637 |     }; | 
| Michael Ludwig | c96fc37 | 2019-01-08 15:46:15 -0500 | [diff] [blame] | 638 |     GrTQuadList<ColorDomainAndAA> fQuads; | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 639 |     // The majority of texture ops will not track a complete src quad so this is indexed separately | 
 | 640 |     // and may be of different size to fQuads. | 
 | 641 |     GrQuadList fSrcQuads; | 
| Brian Osman | 3ebd354 | 2018-07-30 14:36:53 -0400 | [diff] [blame] | 642 |     sk_sp<GrColorSpaceXform> fTextureColorSpaceXform; | 
| Brian Salomon | 0087c83 | 2018-10-15 14:48:20 -0400 | [diff] [blame] | 643 |     unsigned fFilter : 2; | 
| Brian Salomon | 485b8c6 | 2018-01-12 15:11:06 -0500 | [diff] [blame] | 644 |     unsigned fAAType : 2; | 
| Brian Salomon | b80ffee | 2018-05-23 16:39:39 -0400 | [diff] [blame] | 645 |     unsigned fDomain : 1; | 
| Brian Salomon | 1d83542 | 2019-03-13 16:11:44 -0400 | [diff] [blame] | 646 |     unsigned fColorType : 2; | 
 | 647 |     GR_STATIC_ASSERT(GrQuadPerEdgeAA::kColorTypeCount <= 4); | 
| Robert Phillips | 3d4cac5 | 2019-06-11 08:08:08 -0400 | [diff] [blame] | 648 |     unsigned fProxyCnt : 32 - 7; | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 649 |     Proxy fProxies[1]; | 
| Brian Salomon | 336ce7b | 2017-09-08 08:23:58 -0400 | [diff] [blame] | 650 |  | 
| Michael Ludwig | de4c58c | 2019-06-04 09:12:59 -0400 | [diff] [blame] | 651 |     static_assert(GrQuad::kTypeCount <= 4, "GrQuad::Type does not fit in 2 bits"); | 
| Michael Ludwig | f995c05 | 2018-11-26 15:24:29 -0500 | [diff] [blame] | 652 |  | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 653 |     typedef GrMeshDrawOp INHERITED; | 
 | 654 | }; | 
 | 655 |  | 
 | 656 | }  // anonymous namespace | 
 | 657 |  | 
 | 658 | namespace GrTextureOp { | 
 | 659 |  | 
| Robert Phillips | b97da53 | 2019-02-12 15:24:12 -0500 | [diff] [blame] | 660 | std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context, | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 661 |                                sk_sp<GrTextureProxy> proxy, | 
 | 662 |                                GrSamplerState::Filter filter, | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 663 |                                const SkPMColor4f& color, | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 664 |                                const SkRect& srcRect, | 
 | 665 |                                const SkRect& dstRect, | 
 | 666 |                                GrAAType aaType, | 
| Brian Salomon | 2213ee9 | 2018-10-02 10:44:21 -0400 | [diff] [blame] | 667 |                                GrQuadAAFlags aaFlags, | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 668 |                                SkCanvas::SrcRectConstraint constraint, | 
 | 669 |                                const SkMatrix& viewMatrix, | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 670 |                                sk_sp<GrColorSpaceXform> textureColorSpaceXform) { | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 671 |     return TextureOp::Make(context, std::move(proxy), filter, color, srcRect, dstRect, aaType, | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 672 |                            aaFlags, constraint, viewMatrix, std::move(textureColorSpaceXform)); | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 673 | } | 
 | 674 |  | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 675 | std::unique_ptr<GrDrawOp> MakeQuad(GrRecordingContext* context, | 
 | 676 |                                   sk_sp<GrTextureProxy> proxy, | 
 | 677 |                                   GrSamplerState::Filter filter, | 
 | 678 |                                   const SkPMColor4f& color, | 
 | 679 |                                   const SkPoint srcQuad[4], | 
 | 680 |                                   const SkPoint dstQuad[4], | 
 | 681 |                                   GrAAType aaType, | 
 | 682 |                                   GrQuadAAFlags aaFlags, | 
 | 683 |                                   const SkRect* domain, | 
 | 684 |                                   const SkMatrix& viewMatrix, | 
 | 685 |                                   sk_sp<GrColorSpaceXform> textureXform) { | 
 | 686 |     return TextureOp::Make(context, std::move(proxy), filter, color, srcQuad, dstQuad, aaType, | 
 | 687 |                            aaFlags, domain, viewMatrix, std::move(textureXform)); | 
 | 688 | } | 
 | 689 |  | 
 | 690 | std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context, | 
 | 691 |                                   const GrRenderTargetContext::TextureSetEntry set[], | 
 | 692 |                                   int cnt, | 
 | 693 |                                   GrSamplerState::Filter filter, | 
 | 694 |                                   GrAAType aaType, | 
| Michael Ludwig | 31ba718 | 2019-04-03 10:38:06 -0400 | [diff] [blame] | 695 |                                   SkCanvas::SrcRectConstraint constraint, | 
| Michael Ludwig | 009b92e | 2019-02-15 16:03:53 -0500 | [diff] [blame] | 696 |                                   const SkMatrix& viewMatrix, | 
 | 697 |                                   sk_sp<GrColorSpaceXform> textureColorSpaceXform) { | 
| Michael Ludwig | 31ba718 | 2019-04-03 10:38:06 -0400 | [diff] [blame] | 698 |     return TextureOp::Make(context, set, cnt, filter, aaType, constraint, viewMatrix, | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 699 |                            std::move(textureColorSpaceXform)); | 
| Brian Salomon | d7065e7 | 2018-10-12 11:42:02 -0400 | [diff] [blame] | 700 | } | 
 | 701 |  | 
| Michael Ludwig | a3c45c7 | 2019-01-17 17:26:48 -0500 | [diff] [blame] | 702 | bool GetFilterHasEffect(const SkMatrix& viewMatrix, const SkRect& srcRect, const SkRect& dstRect) { | 
 | 703 |     // Hypothetically we could disable bilerp filtering when flipping or rotating 90 degrees, but | 
 | 704 |     // that makes the math harder and we don't want to increase the overhead of the checks | 
 | 705 |     if (!viewMatrix.isScaleTranslate() || | 
 | 706 |         viewMatrix.getScaleX() < 0.0f || viewMatrix.getScaleY() < 0.0f) { | 
 | 707 |         return true; | 
 | 708 |     } | 
 | 709 |  | 
 | 710 |     // Given the matrix conditions ensured above, this computes the device space coordinates for | 
 | 711 |     // the top left corner of dstRect and its size. | 
 | 712 |     SkScalar dw = viewMatrix.getScaleX() * dstRect.width(); | 
 | 713 |     SkScalar dh = viewMatrix.getScaleY() * dstRect.height(); | 
 | 714 |     SkScalar dl = viewMatrix.getScaleX() * dstRect.fLeft + viewMatrix.getTranslateX(); | 
 | 715 |     SkScalar dt = viewMatrix.getScaleY() * dstRect.fTop + viewMatrix.getTranslateY(); | 
 | 716 |  | 
 | 717 |     // Disable filtering when there is no scaling of the src rect and the src rect and dst rect | 
 | 718 |     // align fractionally. If we allow inverted src rects this logic needs to consider that. | 
 | 719 |     SkASSERT(srcRect.isSorted()); | 
 | 720 |     return dw != srcRect.width() || dh != srcRect.height() || | 
 | 721 |            SkScalarFraction(dl) != SkScalarFraction(srcRect.fLeft) || | 
 | 722 |            SkScalarFraction(dt) != SkScalarFraction(srcRect.fTop); | 
 | 723 | } | 
 | 724 |  | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 725 | }  // namespace GrTextureOp | 
 | 726 |  | 
 | 727 | #if GR_TEST_UTILS | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 728 | #include "include/private/GrRecordingContext.h" | 
 | 729 | #include "src/gpu/GrProxyProvider.h" | 
 | 730 | #include "src/gpu/GrRecordingContextPriv.h" | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 731 |  | 
 | 732 | GR_DRAW_OP_TEST_DEFINE(TextureOp) { | 
 | 733 |     GrSurfaceDesc desc; | 
 | 734 |     desc.fConfig = kRGBA_8888_GrPixelConfig; | 
 | 735 |     desc.fHeight = random->nextULessThan(90) + 10; | 
 | 736 |     desc.fWidth = random->nextULessThan(90) + 10; | 
| Brian Salomon | 2a4f983 | 2018-03-03 22:43:43 -0500 | [diff] [blame] | 737 |     auto origin = random->nextBool() ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin; | 
| Greg Daniel | 09c9400 | 2018-06-08 22:11:51 +0000 | [diff] [blame] | 738 |     GrMipMapped mipMapped = random->nextBool() ? GrMipMapped::kYes : GrMipMapped::kNo; | 
 | 739 |     SkBackingFit fit = SkBackingFit::kExact; | 
 | 740 |     if (mipMapped == GrMipMapped::kNo) { | 
 | 741 |         fit = random->nextBool() ? SkBackingFit::kApprox : SkBackingFit::kExact; | 
 | 742 |     } | 
| Robert Phillips | 0bd24dc | 2018-01-16 08:06:32 -0500 | [diff] [blame] | 743 |  | 
| Greg Daniel | 4065d45 | 2018-11-16 15:43:41 -0500 | [diff] [blame] | 744 |     const GrBackendFormat format = | 
| Robert Phillips | 9da87e0 | 2019-02-04 13:26:26 -0500 | [diff] [blame] | 745 |             context->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType); | 
| Greg Daniel | 4065d45 | 2018-11-16 15:43:41 -0500 | [diff] [blame] | 746 |  | 
| Robert Phillips | 9da87e0 | 2019-02-04 13:26:26 -0500 | [diff] [blame] | 747 |     GrProxyProvider* proxyProvider = context->priv().proxyProvider(); | 
| Greg Daniel | 4065d45 | 2018-11-16 15:43:41 -0500 | [diff] [blame] | 748 |     sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(format, desc, origin, mipMapped, fit, | 
| Greg Daniel | 09c9400 | 2018-06-08 22:11:51 +0000 | [diff] [blame] | 749 |                                                              SkBudgeted::kNo, | 
 | 750 |                                                              GrInternalSurfaceFlags::kNone); | 
| Robert Phillips | 0bd24dc | 2018-01-16 08:06:32 -0500 | [diff] [blame] | 751 |  | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 752 |     SkRect rect = GrTest::TestRect(random); | 
 | 753 |     SkRect srcRect; | 
 | 754 |     srcRect.fLeft = random->nextRangeScalar(0.f, proxy->width() / 2.f); | 
 | 755 |     srcRect.fRight = random->nextRangeScalar(0.f, proxy->width()) + proxy->width() / 2.f; | 
 | 756 |     srcRect.fTop = random->nextRangeScalar(0.f, proxy->height() / 2.f); | 
 | 757 |     srcRect.fBottom = random->nextRangeScalar(0.f, proxy->height()) + proxy->height() / 2.f; | 
 | 758 |     SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random); | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 759 |     SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(SkColorToPremulGrColor(random->nextU())); | 
| Brian Salomon | 2bbdcc4 | 2017-09-07 12:36:34 -0400 | [diff] [blame] | 760 |     GrSamplerState::Filter filter = (GrSamplerState::Filter)random->nextULessThan( | 
 | 761 |             static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1); | 
| Greg Daniel | 09c9400 | 2018-06-08 22:11:51 +0000 | [diff] [blame] | 762 |     while (mipMapped == GrMipMapped::kNo && filter == GrSamplerState::Filter::kMipMap) { | 
 | 763 |         filter = (GrSamplerState::Filter)random->nextULessThan( | 
 | 764 |                 static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1); | 
 | 765 |     } | 
| Brian Osman | 3ebd354 | 2018-07-30 14:36:53 -0400 | [diff] [blame] | 766 |     auto texXform = GrTest::TestColorXform(random); | 
| Brian Salomon | 485b8c6 | 2018-01-12 15:11:06 -0500 | [diff] [blame] | 767 |     GrAAType aaType = GrAAType::kNone; | 
 | 768 |     if (random->nextBool()) { | 
 | 769 |         aaType = (fsaaType == GrFSAAType::kUnifiedMSAA) ? GrAAType::kMSAA : GrAAType::kCoverage; | 
 | 770 |     } | 
| Brian Salomon | 2213ee9 | 2018-10-02 10:44:21 -0400 | [diff] [blame] | 771 |     GrQuadAAFlags aaFlags = GrQuadAAFlags::kNone; | 
 | 772 |     aaFlags |= random->nextBool() ? GrQuadAAFlags::kLeft : GrQuadAAFlags::kNone; | 
 | 773 |     aaFlags |= random->nextBool() ? GrQuadAAFlags::kTop : GrQuadAAFlags::kNone; | 
 | 774 |     aaFlags |= random->nextBool() ? GrQuadAAFlags::kRight : GrQuadAAFlags::kNone; | 
 | 775 |     aaFlags |= random->nextBool() ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone; | 
| Brian Salomon | b80ffee | 2018-05-23 16:39:39 -0400 | [diff] [blame] | 776 |     auto constraint = random->nextBool() ? SkCanvas::kStrict_SrcRectConstraint | 
 | 777 |                                          : SkCanvas::kFast_SrcRectConstraint; | 
| Robert Phillips | 7c525e6 | 2018-06-12 10:11:12 -0400 | [diff] [blame] | 778 |     return GrTextureOp::Make(context, std::move(proxy), filter, color, srcRect, rect, aaType, | 
| Brian Osman | 3d139a4 | 2018-11-19 10:42:10 -0500 | [diff] [blame] | 779 |                              aaFlags, constraint, viewMatrix, std::move(texXform)); | 
| Brian Salomon | 3416969 | 2017-08-28 15:32:01 -0400 | [diff] [blame] | 780 | } | 
 | 781 |  | 
 | 782 | #endif |