1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkDrawable.h" 11cb93a386Sopenharmony_ci#include "include/core/SkLog.h" 12cb93a386Sopenharmony_ci#include "include/core/SkVertices.h" 13cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSemaphore.h" 14cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 15cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h" 16cb93a386Sopenharmony_ci#include "include/private/GrImageContext.h" 17cb93a386Sopenharmony_ci#include "include/private/SkShadowFlags.h" 18cb93a386Sopenharmony_ci#include "include/private/SkVx.h" 19cb93a386Sopenharmony_ci#include "include/utils/SkShadowUtils.h" 20cb93a386Sopenharmony_ci#include "src/core/SkAutoPixmapStorage.h" 21cb93a386Sopenharmony_ci#include "src/core/SkConvertPixels.h" 22cb93a386Sopenharmony_ci#include "src/core/SkDrawProcs.h" 23cb93a386Sopenharmony_ci#include "src/core/SkDrawShadowInfo.h" 24cb93a386Sopenharmony_ci#include "src/core/SkGlyphRunPainter.h" 25cb93a386Sopenharmony_ci#include "src/core/SkLatticeIter.h" 26cb93a386Sopenharmony_ci#include "src/core/SkMatrixPriv.h" 27cb93a386Sopenharmony_ci#include "src/core/SkMatrixProvider.h" 28cb93a386Sopenharmony_ci#include "src/core/SkRRectPriv.h" 29cb93a386Sopenharmony_ci#include "src/gpu/GrAppliedClip.h" 30cb93a386Sopenharmony_ci#include "src/gpu/GrAttachment.h" 31cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h" 32cb93a386Sopenharmony_ci#include "src/gpu/GrClip.h" 33cb93a386Sopenharmony_ci#include "src/gpu/GrColor.h" 34cb93a386Sopenharmony_ci#include "src/gpu/GrDataUtils.h" 35cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 36cb93a386Sopenharmony_ci#include "src/gpu/GrDrawingManager.h" 37cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResourcePriv.h" 38cb93a386Sopenharmony_ci#include "src/gpu/GrImageContextPriv.h" 39cb93a386Sopenharmony_ci#include "src/gpu/GrImageInfo.h" 40cb93a386Sopenharmony_ci#include "src/gpu/GrMemoryPool.h" 41cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h" 42cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h" 43cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 44cb93a386Sopenharmony_ci#include "src/gpu/GrSemaphore.h" 45cb93a386Sopenharmony_ci#include "src/gpu/GrStencilSettings.h" 46cb93a386Sopenharmony_ci#include "src/gpu/GrStyle.h" 47cb93a386Sopenharmony_ci#include "src/gpu/GrTracing.h" 48cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h" 49cb93a386Sopenharmony_ci#include "src/gpu/effects/GrBicubicEffect.h" 50cb93a386Sopenharmony_ci#include "src/gpu/effects/GrBlendFragmentProcessor.h" 51cb93a386Sopenharmony_ci#include "src/gpu/effects/GrDisableColorXP.h" 52cb93a386Sopenharmony_ci#include "src/gpu/effects/GrRRectEffect.h" 53cb93a386Sopenharmony_ci#include "src/gpu/effects/GrTextureEffect.h" 54cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrQuad.h" 55cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrQuadUtils.h" 56cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrStyledShape.h" 57cb93a386Sopenharmony_ci#include "src/gpu/ops/BlurOp.h" 58cb93a386Sopenharmony_ci#include "src/gpu/ops/ClearOp.h" 59cb93a386Sopenharmony_ci#include "src/gpu/ops/DrawAtlasOp.h" 60cb93a386Sopenharmony_ci#include "src/gpu/ops/DrawVerticesOp.h" 61cb93a386Sopenharmony_ci#include "src/gpu/ops/DrawableOp.h" 62cb93a386Sopenharmony_ci#include "src/gpu/ops/FillRRectOp.h" 63cb93a386Sopenharmony_ci#include "src/gpu/ops/FillRectOp.h" 64cb93a386Sopenharmony_ci#include "src/gpu/ops/GrDrawOp.h" 65cb93a386Sopenharmony_ci#include "src/gpu/ops/GrOp.h" 66cb93a386Sopenharmony_ci#include "src/gpu/ops/GrOvalOpFactory.h" 67cb93a386Sopenharmony_ci#include "src/gpu/ops/LatticeOp.h" 68cb93a386Sopenharmony_ci#include "src/gpu/ops/RegionOp.h" 69cb93a386Sopenharmony_ci#include "src/gpu/ops/ShadowRRectOp.h" 70cb93a386Sopenharmony_ci#include "src/gpu/ops/StrokeRectOp.h" 71cb93a386Sopenharmony_ci#include "src/gpu/ops/TextureOp.h" 72cb93a386Sopenharmony_ci#include "src/gpu/text/GrSDFTControl.h" 73cb93a386Sopenharmony_ci#include "src/gpu/text/GrTextBlobCache.h" 74cb93a386Sopenharmony_ci#include "src/gpu/v1/PathRenderer.h" 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext()) 77cb93a386Sopenharmony_ci#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner()) 78cb93a386Sopenharmony_ci#define RETURN_IF_ABANDONED if (fContext->abandoned()) { return; } 79cb93a386Sopenharmony_ci#define RETURN_FALSE_IF_ABANDONED if (fContext->abandoned()) { return false; } 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_cinamespace { 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_civoid op_bounds(SkRect* bounds, const GrOp* op) { 86cb93a386Sopenharmony_ci *bounds = op->bounds(); 87cb93a386Sopenharmony_ci if (op->hasZeroArea()) { 88cb93a386Sopenharmony_ci if (op->hasAABloat()) { 89cb93a386Sopenharmony_ci bounds->outset(0.5f, 0.5f); 90cb93a386Sopenharmony_ci } else { 91cb93a386Sopenharmony_ci // We don't know which way the particular GPU will snap lines or points at integer 92cb93a386Sopenharmony_ci // coords. So we ensure that the bounds is large enough for either snap. 93cb93a386Sopenharmony_ci SkRect before = *bounds; 94cb93a386Sopenharmony_ci bounds->roundOut(bounds); 95cb93a386Sopenharmony_ci if (bounds->fLeft == before.fLeft) { 96cb93a386Sopenharmony_ci bounds->fLeft -= 1; 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci if (bounds->fTop == before.fTop) { 99cb93a386Sopenharmony_ci bounds->fTop -= 1; 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci if (bounds->fRight == before.fRight) { 102cb93a386Sopenharmony_ci bounds->fRight += 1; 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci if (bounds->fBottom == before.fBottom) { 105cb93a386Sopenharmony_ci bounds->fBottom += 1; 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci} 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci} // anonymous namespace 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_cinamespace skgpu::v1 { 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ciusing DoSimplify = GrStyledShape::DoSimplify; 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ciclass AutoCheckFlush { 118cb93a386Sopenharmony_cipublic: 119cb93a386Sopenharmony_ci AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) { 120cb93a386Sopenharmony_ci SkASSERT(fDrawingManager); 121cb93a386Sopenharmony_ci } 122cb93a386Sopenharmony_ci ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); } 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ciprivate: 125cb93a386Sopenharmony_ci GrDrawingManager* fDrawingManager; 126cb93a386Sopenharmony_ci}; 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make(GrRecordingContext* rContext, 129cb93a386Sopenharmony_ci GrColorType colorType, 130cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> proxy, 131cb93a386Sopenharmony_ci sk_sp<SkColorSpace> colorSpace, 132cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 133cb93a386Sopenharmony_ci const SkSurfaceProps& surfaceProps, 134cb93a386Sopenharmony_ci bool flushTimeOpsTask) { 135cb93a386Sopenharmony_ci if (!rContext || !proxy || colorType == GrColorType::kUnknown) { 136cb93a386Sopenharmony_ci return nullptr; 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci const GrBackendFormat& format = proxy->backendFormat(); 140cb93a386Sopenharmony_ci GrSwizzle readSwizzle = rContext->priv().caps()->getReadSwizzle(format, colorType); 141cb93a386Sopenharmony_ci GrSwizzle writeSwizzle = rContext->priv().caps()->getWriteSwizzle(format, colorType); 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci GrSurfaceProxyView readView ( proxy, origin, readSwizzle); 144cb93a386Sopenharmony_ci GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle); 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci return std::make_unique<SurfaceDrawContext>(rContext, 147cb93a386Sopenharmony_ci std::move(readView), 148cb93a386Sopenharmony_ci std::move(writeView), 149cb93a386Sopenharmony_ci colorType, 150cb93a386Sopenharmony_ci std::move(colorSpace), 151cb93a386Sopenharmony_ci surfaceProps, 152cb93a386Sopenharmony_ci flushTimeOpsTask); 153cb93a386Sopenharmony_ci} 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make( 156cb93a386Sopenharmony_ci GrRecordingContext* rContext, 157cb93a386Sopenharmony_ci sk_sp<SkColorSpace> colorSpace, 158cb93a386Sopenharmony_ci SkBackingFit fit, 159cb93a386Sopenharmony_ci SkISize dimensions, 160cb93a386Sopenharmony_ci const GrBackendFormat& format, 161cb93a386Sopenharmony_ci int sampleCnt, 162cb93a386Sopenharmony_ci GrMipmapped mipMapped, 163cb93a386Sopenharmony_ci GrProtected isProtected, 164cb93a386Sopenharmony_ci GrSwizzle readSwizzle, 165cb93a386Sopenharmony_ci GrSwizzle writeSwizzle, 166cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 167cb93a386Sopenharmony_ci SkBudgeted budgeted, 168cb93a386Sopenharmony_ci const SkSurfaceProps& surfaceProps) { 169cb93a386Sopenharmony_ci // It is probably not necessary to check if the context is abandoned here since uses of the 170cb93a386Sopenharmony_ci // SurfaceDrawContext which need the context will mostly likely fail later on without an 171cb93a386Sopenharmony_ci // issue. However having this hear adds some reassurance in case there is a path doesn't handle 172cb93a386Sopenharmony_ci // an abandoned context correctly. It also lets us early out of some extra work. 173cb93a386Sopenharmony_ci if (rContext->abandoned()) { 174cb93a386Sopenharmony_ci return nullptr; 175cb93a386Sopenharmony_ci } 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> proxy = rContext->priv().proxyProvider()->createProxy( 178cb93a386Sopenharmony_ci format, 179cb93a386Sopenharmony_ci dimensions, 180cb93a386Sopenharmony_ci GrRenderable::kYes, 181cb93a386Sopenharmony_ci sampleCnt, 182cb93a386Sopenharmony_ci mipMapped, 183cb93a386Sopenharmony_ci fit, 184cb93a386Sopenharmony_ci budgeted, 185cb93a386Sopenharmony_ci isProtected); 186cb93a386Sopenharmony_ci if (!proxy) { 187cb93a386Sopenharmony_ci return nullptr; 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_ci GrSurfaceProxyView readView ( proxy, origin, readSwizzle); 191cb93a386Sopenharmony_ci GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle); 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci auto sdc = std::make_unique<SurfaceDrawContext>(rContext, 194cb93a386Sopenharmony_ci std::move(readView), 195cb93a386Sopenharmony_ci std::move(writeView), 196cb93a386Sopenharmony_ci GrColorType::kUnknown, 197cb93a386Sopenharmony_ci std::move(colorSpace), 198cb93a386Sopenharmony_ci surfaceProps); 199cb93a386Sopenharmony_ci sdc->discard(); 200cb93a386Sopenharmony_ci return sdc; 201cb93a386Sopenharmony_ci} 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make( 204cb93a386Sopenharmony_ci GrRecordingContext* rContext, 205cb93a386Sopenharmony_ci GrColorType colorType, 206cb93a386Sopenharmony_ci sk_sp<SkColorSpace> colorSpace, 207cb93a386Sopenharmony_ci SkBackingFit fit, 208cb93a386Sopenharmony_ci SkISize dimensions, 209cb93a386Sopenharmony_ci const SkSurfaceProps& surfaceProps, 210cb93a386Sopenharmony_ci int sampleCnt, 211cb93a386Sopenharmony_ci GrMipmapped mipMapped, 212cb93a386Sopenharmony_ci GrProtected isProtected, 213cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 214cb93a386Sopenharmony_ci SkBudgeted budgeted) { 215cb93a386Sopenharmony_ci if (!rContext) { 216cb93a386Sopenharmony_ci return nullptr; 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci auto format = rContext->priv().caps()->getDefaultBackendFormat(colorType, GrRenderable::kYes); 220cb93a386Sopenharmony_ci if (!format.isValid()) { 221cb93a386Sopenharmony_ci return nullptr; 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> proxy = rContext->priv().proxyProvider()->createProxy(format, 224cb93a386Sopenharmony_ci dimensions, 225cb93a386Sopenharmony_ci GrRenderable::kYes, 226cb93a386Sopenharmony_ci sampleCnt, 227cb93a386Sopenharmony_ci mipMapped, 228cb93a386Sopenharmony_ci fit, 229cb93a386Sopenharmony_ci budgeted, 230cb93a386Sopenharmony_ci isProtected); 231cb93a386Sopenharmony_ci if (!proxy) { 232cb93a386Sopenharmony_ci return nullptr; 233cb93a386Sopenharmony_ci } 234cb93a386Sopenharmony_ci 235cb93a386Sopenharmony_ci return SurfaceDrawContext::Make(rContext, 236cb93a386Sopenharmony_ci colorType, 237cb93a386Sopenharmony_ci std::move(proxy), 238cb93a386Sopenharmony_ci std::move(colorSpace), 239cb93a386Sopenharmony_ci origin, 240cb93a386Sopenharmony_ci surfaceProps); 241cb93a386Sopenharmony_ci} 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::MakeWithFallback( 244cb93a386Sopenharmony_ci GrRecordingContext* rContext, 245cb93a386Sopenharmony_ci GrColorType colorType, 246cb93a386Sopenharmony_ci sk_sp<SkColorSpace> colorSpace, 247cb93a386Sopenharmony_ci SkBackingFit fit, 248cb93a386Sopenharmony_ci SkISize dimensions, 249cb93a386Sopenharmony_ci const SkSurfaceProps& surfaceProps, 250cb93a386Sopenharmony_ci int sampleCnt, 251cb93a386Sopenharmony_ci GrMipmapped mipMapped, 252cb93a386Sopenharmony_ci GrProtected isProtected, 253cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 254cb93a386Sopenharmony_ci SkBudgeted budgeted) { 255cb93a386Sopenharmony_ci const GrCaps* caps = rContext->priv().caps(); 256cb93a386Sopenharmony_ci auto [ct, _] = caps->getFallbackColorTypeAndFormat(colorType, sampleCnt); 257cb93a386Sopenharmony_ci if (ct == GrColorType::kUnknown) { 258cb93a386Sopenharmony_ci return nullptr; 259cb93a386Sopenharmony_ci } 260cb93a386Sopenharmony_ci return SurfaceDrawContext::Make(rContext, ct, colorSpace, fit, dimensions, surfaceProps, 261cb93a386Sopenharmony_ci sampleCnt, mipMapped, isProtected, origin, budgeted); 262cb93a386Sopenharmony_ci} 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::MakeFromBackendTexture( 265cb93a386Sopenharmony_ci GrRecordingContext* rContext, 266cb93a386Sopenharmony_ci GrColorType colorType, 267cb93a386Sopenharmony_ci sk_sp<SkColorSpace> colorSpace, 268cb93a386Sopenharmony_ci const GrBackendTexture& tex, 269cb93a386Sopenharmony_ci int sampleCnt, 270cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 271cb93a386Sopenharmony_ci const SkSurfaceProps& surfaceProps, 272cb93a386Sopenharmony_ci sk_sp<GrRefCntedCallback> releaseHelper) { 273cb93a386Sopenharmony_ci SkASSERT(sampleCnt > 0); 274cb93a386Sopenharmony_ci sk_sp<GrTextureProxy> proxy(rContext->priv().proxyProvider()->wrapRenderableBackendTexture( 275cb93a386Sopenharmony_ci tex, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, 276cb93a386Sopenharmony_ci std::move(releaseHelper))); 277cb93a386Sopenharmony_ci if (!proxy) { 278cb93a386Sopenharmony_ci return nullptr; 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci 281cb93a386Sopenharmony_ci return SurfaceDrawContext::Make(rContext, colorType, std::move(proxy), std::move(colorSpace), 282cb93a386Sopenharmony_ci origin, surfaceProps); 283cb93a386Sopenharmony_ci} 284cb93a386Sopenharmony_ci 285cb93a386Sopenharmony_ci// In MDB mode the reffing of the 'getLastOpsTask' call's result allows in-progress 286cb93a386Sopenharmony_ci// OpsTask to be picked up and added to by SurfaceDrawContexts lower in the call 287cb93a386Sopenharmony_ci// stack. When this occurs with a closed OpsTask, a new one will be allocated 288cb93a386Sopenharmony_ci// when the surfaceDrawContext attempts to use it (via getOpsTask). 289cb93a386Sopenharmony_ciSurfaceDrawContext::SurfaceDrawContext(GrRecordingContext* rContext, 290cb93a386Sopenharmony_ci GrSurfaceProxyView readView, 291cb93a386Sopenharmony_ci GrSurfaceProxyView writeView, 292cb93a386Sopenharmony_ci GrColorType colorType, 293cb93a386Sopenharmony_ci sk_sp<SkColorSpace> colorSpace, 294cb93a386Sopenharmony_ci const SkSurfaceProps& surfaceProps, 295cb93a386Sopenharmony_ci bool flushTimeOpsTask) 296cb93a386Sopenharmony_ci : SurfaceFillContext(rContext, 297cb93a386Sopenharmony_ci std::move(readView), 298cb93a386Sopenharmony_ci std::move(writeView), 299cb93a386Sopenharmony_ci {colorType, kPremul_SkAlphaType, std::move(colorSpace)}, 300cb93a386Sopenharmony_ci flushTimeOpsTask) 301cb93a386Sopenharmony_ci , fSurfaceProps(surfaceProps) 302cb93a386Sopenharmony_ci , fCanUseDynamicMSAA( 303cb93a386Sopenharmony_ci (fSurfaceProps.flags() & SkSurfaceProps::kDynamicMSAA_Flag) && 304cb93a386Sopenharmony_ci rContext->priv().caps()->supportsDynamicMSAA(this->asRenderTargetProxy())) 305cb93a386Sopenharmony_ci , fGlyphPainter(*this) { 306cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 307cb93a386Sopenharmony_ci} 308cb93a386Sopenharmony_ci 309cb93a386Sopenharmony_ciSurfaceDrawContext::~SurfaceDrawContext() { 310cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 311cb93a386Sopenharmony_ci} 312cb93a386Sopenharmony_ci 313cb93a386Sopenharmony_civoid SurfaceDrawContext::willReplaceOpsTask(OpsTask* prevTask, OpsTask* nextTask) { 314cb93a386Sopenharmony_ci if (prevTask && fNeedsStencil) { 315cb93a386Sopenharmony_ci // Store the stencil values in memory upon completion of fOpsTask. 316cb93a386Sopenharmony_ci prevTask->setMustPreserveStencil(); 317cb93a386Sopenharmony_ci // Reload the stencil buffer content at the beginning of newOpsTask. 318cb93a386Sopenharmony_ci // FIXME: Could the topo sort insert a task between these two that modifies the stencil 319cb93a386Sopenharmony_ci // values? 320cb93a386Sopenharmony_ci nextTask->setInitialStencilContent(OpsTask::StencilContent::kPreserved); 321cb93a386Sopenharmony_ci } 322cb93a386Sopenharmony_ci#if GR_GPU_STATS && GR_TEST_UTILS 323cb93a386Sopenharmony_ci if (fCanUseDynamicMSAA) { 324cb93a386Sopenharmony_ci fContext->priv().dmsaaStats().fNumRenderPasses++; 325cb93a386Sopenharmony_ci } 326cb93a386Sopenharmony_ci#endif 327cb93a386Sopenharmony_ci} 328cb93a386Sopenharmony_ci 329cb93a386Sopenharmony_civoid SurfaceDrawContext::drawGlyphRunListNoCache(const GrClip* clip, 330cb93a386Sopenharmony_ci const SkMatrixProvider& viewMatrix, 331cb93a386Sopenharmony_ci const SkGlyphRunList& glyphRunList, 332cb93a386Sopenharmony_ci const SkPaint& paint) { 333cb93a386Sopenharmony_ci GrSDFTControl control = 334cb93a386Sopenharmony_ci fContext->priv().getSDFTControl(fSurfaceProps.isUseDeviceIndependentFonts()); 335cb93a386Sopenharmony_ci const SkPoint drawOrigin = glyphRunList.origin(); 336cb93a386Sopenharmony_ci SkMatrix drawMatrix = viewMatrix.localToDevice(); 337cb93a386Sopenharmony_ci drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y()); 338cb93a386Sopenharmony_ci GrSubRunAllocator* const alloc = this->subRunAlloc(); 339cb93a386Sopenharmony_ci 340cb93a386Sopenharmony_ci GrSubRunNoCachePainter painter{this, alloc, clip, viewMatrix, glyphRunList, paint}; 341cb93a386Sopenharmony_ci for (auto& glyphRun : glyphRunList) { 342cb93a386Sopenharmony_ci // Make and add the text ops. 343cb93a386Sopenharmony_ci fGlyphPainter.processGlyphRun(glyphRun, 344cb93a386Sopenharmony_ci drawMatrix, 345cb93a386Sopenharmony_ci paint, 346cb93a386Sopenharmony_ci control, 347cb93a386Sopenharmony_ci &painter); 348cb93a386Sopenharmony_ci } 349cb93a386Sopenharmony_ci} 350cb93a386Sopenharmony_ci 351cb93a386Sopenharmony_civoid SurfaceDrawContext::drawGlyphRunListWithCache(const GrClip* clip, 352cb93a386Sopenharmony_ci const SkMatrixProvider& viewMatrix, 353cb93a386Sopenharmony_ci const SkGlyphRunList& glyphRunList, 354cb93a386Sopenharmony_ci const SkPaint& paint) { 355cb93a386Sopenharmony_ci SkMatrix drawMatrix(viewMatrix.localToDevice()); 356cb93a386Sopenharmony_ci drawMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y()); 357cb93a386Sopenharmony_ci 358cb93a386Sopenharmony_ci GrSDFTControl control = 359cb93a386Sopenharmony_ci this->recordingContext()->priv().getSDFTControl( 360cb93a386Sopenharmony_ci this->surfaceProps().isUseDeviceIndependentFonts()); 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_ci auto [canCache, key] = GrTextBlob::Key::Make(glyphRunList, 363cb93a386Sopenharmony_ci paint, 364cb93a386Sopenharmony_ci fSurfaceProps, 365cb93a386Sopenharmony_ci this->colorInfo(), 366cb93a386Sopenharmony_ci drawMatrix, 367cb93a386Sopenharmony_ci control); 368cb93a386Sopenharmony_ci 369cb93a386Sopenharmony_ci sk_sp<GrTextBlob> blob; 370cb93a386Sopenharmony_ci GrTextBlobCache* textBlobCache = fContext->priv().getTextBlobCache(); 371cb93a386Sopenharmony_ci if (canCache) { 372cb93a386Sopenharmony_ci blob = textBlobCache->find(key); 373cb93a386Sopenharmony_ci } 374cb93a386Sopenharmony_ci 375cb93a386Sopenharmony_ci if (blob == nullptr || !blob->canReuse(paint, drawMatrix)) { 376cb93a386Sopenharmony_ci if (blob != nullptr) { 377cb93a386Sopenharmony_ci // We have to remake the blob because changes may invalidate our masks. 378cb93a386Sopenharmony_ci // TODO we could probably get away with reuse most of the time if the pointer is unique, 379cb93a386Sopenharmony_ci // but we'd have to clear the SubRun information 380cb93a386Sopenharmony_ci textBlobCache->remove(blob.get()); 381cb93a386Sopenharmony_ci } 382cb93a386Sopenharmony_ci 383cb93a386Sopenharmony_ci blob = GrTextBlob::Make(glyphRunList, paint, drawMatrix, control, &fGlyphPainter); 384cb93a386Sopenharmony_ci 385cb93a386Sopenharmony_ci if (canCache) { 386cb93a386Sopenharmony_ci blob->addKey(key); 387cb93a386Sopenharmony_ci // The blob may already have been created on a different thread. Use the first one 388cb93a386Sopenharmony_ci // that was there. 389cb93a386Sopenharmony_ci blob = textBlobCache->addOrReturnExisting(glyphRunList, blob); 390cb93a386Sopenharmony_ci } 391cb93a386Sopenharmony_ci } 392cb93a386Sopenharmony_ci 393cb93a386Sopenharmony_ci for (const GrSubRun& subRun : blob->subRunList()) { 394cb93a386Sopenharmony_ci subRun.draw(clip, viewMatrix, glyphRunList, paint, this); 395cb93a386Sopenharmony_ci } 396cb93a386Sopenharmony_ci} 397cb93a386Sopenharmony_ci 398cb93a386Sopenharmony_ci// choose to use the GrTextBlob cache or not. 399cb93a386Sopenharmony_cibool gGrDrawTextNoCache = false; 400cb93a386Sopenharmony_civoid SurfaceDrawContext::drawGlyphRunList(const GrClip* clip, 401cb93a386Sopenharmony_ci const SkMatrixProvider& viewMatrix, 402cb93a386Sopenharmony_ci const SkGlyphRunList& glyphRunList, 403cb93a386Sopenharmony_ci const SkPaint& paint) { 404cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 405cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 406cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 407cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawGlyphRunList", fContext); 408cb93a386Sopenharmony_ci 409cb93a386Sopenharmony_ci // Drawing text can cause us to do inline uploads. This is not supported for wrapped vulkan 410cb93a386Sopenharmony_ci // secondary command buffers because it would require stopping and starting a render pass which 411cb93a386Sopenharmony_ci // we don't have access to. 412cb93a386Sopenharmony_ci if (this->wrapsVkSecondaryCB()) { 413cb93a386Sopenharmony_ci return; 414cb93a386Sopenharmony_ci } 415cb93a386Sopenharmony_ci 416cb93a386Sopenharmony_ci if (gGrDrawTextNoCache || glyphRunList.blob() == nullptr) { 417cb93a386Sopenharmony_ci // If the glyphRunList does not have an associated text blob, then it was created by one of 418cb93a386Sopenharmony_ci // the direct draw APIs (drawGlyphs, etc.). There is no need to create a GrTextBlob just 419cb93a386Sopenharmony_ci // build the sub run directly and place it in the op. 420cb93a386Sopenharmony_ci this->drawGlyphRunListNoCache(clip, viewMatrix, glyphRunList, paint); 421cb93a386Sopenharmony_ci } else { 422cb93a386Sopenharmony_ci this->drawGlyphRunListWithCache(clip, viewMatrix, glyphRunList, paint); 423cb93a386Sopenharmony_ci } 424cb93a386Sopenharmony_ci} 425cb93a386Sopenharmony_ci 426cb93a386Sopenharmony_civoid SurfaceDrawContext::drawPaint(const GrClip* clip, 427cb93a386Sopenharmony_ci GrPaint&& paint, 428cb93a386Sopenharmony_ci const SkMatrix& viewMatrix) { 429cb93a386Sopenharmony_ci // Start with the render target, since that is the maximum content we could possibly fill. 430cb93a386Sopenharmony_ci // drawFilledQuad() will automatically restrict it to clip bounds for us if possible. 431cb93a386Sopenharmony_ci if (!paint.numTotalFragmentProcessors()) { 432cb93a386Sopenharmony_ci // The paint is trivial so we won't need to use local coordinates, so skip calculating the 433cb93a386Sopenharmony_ci // inverse view matrix. 434cb93a386Sopenharmony_ci SkRect r = this->asSurfaceProxy()->getBoundsRect(); 435cb93a386Sopenharmony_ci this->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), r, r); 436cb93a386Sopenharmony_ci } else { 437cb93a386Sopenharmony_ci // Use the inverse view matrix to arrive at appropriate local coordinates for the paint. 438cb93a386Sopenharmony_ci SkMatrix localMatrix; 439cb93a386Sopenharmony_ci if (!viewMatrix.invert(&localMatrix)) { 440cb93a386Sopenharmony_ci return; 441cb93a386Sopenharmony_ci } 442cb93a386Sopenharmony_ci SkIRect bounds = SkIRect::MakeSize(this->asSurfaceProxy()->dimensions()); 443cb93a386Sopenharmony_ci this->fillPixelsWithLocalMatrix(clip, std::move(paint), bounds, localMatrix); 444cb93a386Sopenharmony_ci } 445cb93a386Sopenharmony_ci} 446cb93a386Sopenharmony_ci 447cb93a386Sopenharmony_cienum class SurfaceDrawContext::QuadOptimization { 448cb93a386Sopenharmony_ci // The rect to draw doesn't intersect clip or render target, so no draw op should be added 449cb93a386Sopenharmony_ci kDiscarded, 450cb93a386Sopenharmony_ci // The rect to draw was converted to some other op and appended to the oplist, so no additional 451cb93a386Sopenharmony_ci // op is necessary. Currently this can convert it to a clear op or a rrect op. Only valid if 452cb93a386Sopenharmony_ci // a constColor is provided. 453cb93a386Sopenharmony_ci kSubmitted, 454cb93a386Sopenharmony_ci // The clip was folded into the device quad, with updated edge flags and local coords, and 455cb93a386Sopenharmony_ci // caller is responsible for adding an appropriate op. 456cb93a386Sopenharmony_ci kClipApplied, 457cb93a386Sopenharmony_ci // No change to clip, but quad updated to better fit clip/render target, and caller is 458cb93a386Sopenharmony_ci // responsible for adding an appropriate op. 459cb93a386Sopenharmony_ci kCropped 460cb93a386Sopenharmony_ci}; 461cb93a386Sopenharmony_ci 462cb93a386Sopenharmony_ciSurfaceDrawContext::QuadOptimization SurfaceDrawContext::attemptQuadOptimization( 463cb93a386Sopenharmony_ci const GrClip* clip, const GrUserStencilSettings* stencilSettings, GrAA* aa, DrawQuad* quad, 464cb93a386Sopenharmony_ci GrPaint* paint) { 465cb93a386Sopenharmony_ci // Optimization requirements: 466cb93a386Sopenharmony_ci // 1. kDiscard applies when clip bounds and quad bounds do not intersect 467cb93a386Sopenharmony_ci // 2a. kSubmitted applies when constColor and final geom is pixel aligned rect; 468cb93a386Sopenharmony_ci // pixel aligned rect requires rect clip and (rect quad or quad covers clip) OR 469cb93a386Sopenharmony_ci // 2b. kSubmitted applies when constColor and rrect clip and quad covers clip 470cb93a386Sopenharmony_ci // 4. kClipApplied applies when rect clip and (rect quad or quad covers clip) 471cb93a386Sopenharmony_ci // 5. kCropped in all other scenarios (although a crop may be a no-op) 472cb93a386Sopenharmony_ci const SkPMColor4f* constColor = nullptr; 473cb93a386Sopenharmony_ci SkPMColor4f paintColor; 474cb93a386Sopenharmony_ci if (!stencilSettings && paint && !paint->hasCoverageFragmentProcessor() && 475cb93a386Sopenharmony_ci paint->isConstantBlendedColor(&paintColor)) { 476cb93a386Sopenharmony_ci // Only consider clears/rrects when it's easy to guarantee 100% fill with single color 477cb93a386Sopenharmony_ci constColor = &paintColor; 478cb93a386Sopenharmony_ci } 479cb93a386Sopenharmony_ci 480cb93a386Sopenharmony_ci // Save the old AA flags since CropToRect will modify 'quad' and if kCropped is returned, it's 481cb93a386Sopenharmony_ci // better to just keep the old flags instead of introducing mixed edge flags. 482cb93a386Sopenharmony_ci GrQuadAAFlags oldFlags = quad->fEdgeFlags; 483cb93a386Sopenharmony_ci 484cb93a386Sopenharmony_ci // Use the logical size of the render target, which allows for "fullscreen" clears even if 485cb93a386Sopenharmony_ci // the render target has an approximate backing fit 486cb93a386Sopenharmony_ci SkRect rtRect = this->asSurfaceProxy()->getBoundsRect(); 487cb93a386Sopenharmony_ci 488cb93a386Sopenharmony_ci // For historical reasons, we assume AA for exact bounds checking in IsOutsideClip. 489cb93a386Sopenharmony_ci // TODO(michaelludwig) - Hopefully that can be revisited when the clipping optimizations are 490cb93a386Sopenharmony_ci // refactored to work better with round rects and dmsaa. 491cb93a386Sopenharmony_ci SkRect drawBounds = quad->fDevice.bounds(); 492cb93a386Sopenharmony_ci if (!quad->fDevice.isFinite() || drawBounds.isEmpty() || 493cb93a386Sopenharmony_ci GrClip::IsOutsideClip(SkIRect::MakeSize(this->dimensions()), drawBounds, GrAA::kYes)) { 494cb93a386Sopenharmony_ci return QuadOptimization::kDiscarded; 495cb93a386Sopenharmony_ci } else if (GrQuadUtils::WillUseHairline(quad->fDevice, GrAAType::kCoverage, quad->fEdgeFlags)) { 496cb93a386Sopenharmony_ci // Don't try to apply the clip early if we know rendering will use hairline methods, as this 497cb93a386Sopenharmony_ci // has an effect on the op bounds not otherwise taken into account in this function. 498cb93a386Sopenharmony_ci return QuadOptimization::kCropped; 499cb93a386Sopenharmony_ci } 500cb93a386Sopenharmony_ci 501cb93a386Sopenharmony_ci auto conservativeCrop = [&]() { 502cb93a386Sopenharmony_ci static constexpr int kLargeDrawLimit = 15000; 503cb93a386Sopenharmony_ci // Crop the quad to the render target. This doesn't change the visual results of drawing but 504cb93a386Sopenharmony_ci // is meant to help numerical stability for excessively large draws. 505cb93a386Sopenharmony_ci if (drawBounds.width() > kLargeDrawLimit || drawBounds.height() > kLargeDrawLimit) { 506cb93a386Sopenharmony_ci GrQuadUtils::CropToRect(rtRect, *aa, quad, /* compute local */ !constColor); 507cb93a386Sopenharmony_ci } 508cb93a386Sopenharmony_ci }; 509cb93a386Sopenharmony_ci 510cb93a386Sopenharmony_ci bool simpleColor = !stencilSettings && constColor; 511cb93a386Sopenharmony_ci GrClip::PreClipResult result = clip ? clip->preApply(drawBounds, *aa) 512cb93a386Sopenharmony_ci : GrClip::PreClipResult(GrClip::Effect::kUnclipped); 513cb93a386Sopenharmony_ci switch(result.fEffect) { 514cb93a386Sopenharmony_ci case GrClip::Effect::kClippedOut: 515cb93a386Sopenharmony_ci return QuadOptimization::kDiscarded; 516cb93a386Sopenharmony_ci case GrClip::Effect::kUnclipped: 517cb93a386Sopenharmony_ci if (!simpleColor) { 518cb93a386Sopenharmony_ci conservativeCrop(); 519cb93a386Sopenharmony_ci return QuadOptimization::kClipApplied; 520cb93a386Sopenharmony_ci } else { 521cb93a386Sopenharmony_ci // Update result to store the render target bounds in order and then fall 522cb93a386Sopenharmony_ci // through to attempt the draw->native clear optimization 523cb93a386Sopenharmony_ci result = GrClip::PreClipResult(SkRRect::MakeRect(rtRect), *aa); 524cb93a386Sopenharmony_ci } 525cb93a386Sopenharmony_ci break; 526cb93a386Sopenharmony_ci case GrClip::Effect::kClipped: 527cb93a386Sopenharmony_ci if (!result.fIsRRect || (stencilSettings && result.fAA != *aa) || 528cb93a386Sopenharmony_ci (!result.fRRect.isRect() && !simpleColor)) { 529cb93a386Sopenharmony_ci // The clip and draw state are too complicated to try and reduce 530cb93a386Sopenharmony_ci conservativeCrop(); 531cb93a386Sopenharmony_ci return QuadOptimization::kCropped; 532cb93a386Sopenharmony_ci } // Else fall through to attempt to combine the draw and clip geometry together 533cb93a386Sopenharmony_ci break; 534cb93a386Sopenharmony_ci default: 535cb93a386Sopenharmony_ci SkUNREACHABLE; 536cb93a386Sopenharmony_ci } 537cb93a386Sopenharmony_ci 538cb93a386Sopenharmony_ci // If we reached here, we know we're an axis-aligned clip that is either a rect or a round rect, 539cb93a386Sopenharmony_ci // so we can potentially combine it with the draw geometry so that no clipping is needed. 540cb93a386Sopenharmony_ci SkASSERT(result.fEffect == GrClip::Effect::kClipped && result.fIsRRect); 541cb93a386Sopenharmony_ci SkRect clippedBounds = result.fRRect.getBounds(); 542cb93a386Sopenharmony_ci clippedBounds.intersect(rtRect); 543cb93a386Sopenharmony_ci if (!drawBounds.intersect(clippedBounds)) { 544cb93a386Sopenharmony_ci // Our fractional bounds aren't actually inside the clip. GrClip::preApply() can sometimes 545cb93a386Sopenharmony_ci // think in terms of rounded-out bounds. Discard the draw. 546cb93a386Sopenharmony_ci return QuadOptimization::kDiscarded; 547cb93a386Sopenharmony_ci } 548cb93a386Sopenharmony_ci // Guard against the clipped draw turning into a hairline draw after intersection 549cb93a386Sopenharmony_ci if (drawBounds.width() < 1.f || drawBounds.height() < 1.f) { 550cb93a386Sopenharmony_ci return QuadOptimization::kCropped; 551cb93a386Sopenharmony_ci } 552cb93a386Sopenharmony_ci 553cb93a386Sopenharmony_ci if (result.fRRect.isRect()) { 554cb93a386Sopenharmony_ci // No rounded corners, so we might be able to become a native clear or we might be able to 555cb93a386Sopenharmony_ci // modify geometry and edge flags to represent intersected shape of clip and draw. 556cb93a386Sopenharmony_ci if (GrQuadUtils::CropToRect(clippedBounds, result.fAA, quad, 557cb93a386Sopenharmony_ci /*compute local*/ !constColor)) { 558cb93a386Sopenharmony_ci if (simpleColor && quad->fDevice.quadType() == GrQuad::Type::kAxisAligned) { 559cb93a386Sopenharmony_ci // Clear optimization is possible 560cb93a386Sopenharmony_ci drawBounds = quad->fDevice.bounds(); 561cb93a386Sopenharmony_ci if (drawBounds.contains(rtRect)) { 562cb93a386Sopenharmony_ci // Fullscreen clear 563cb93a386Sopenharmony_ci this->clear(*constColor); 564cb93a386Sopenharmony_ci return QuadOptimization::kSubmitted; 565cb93a386Sopenharmony_ci } else if (GrClip::IsPixelAligned(drawBounds) && 566cb93a386Sopenharmony_ci drawBounds.width() > 256 && drawBounds.height() > 256) { 567cb93a386Sopenharmony_ci // Scissor + clear (round shouldn't do anything since we are pixel aligned) 568cb93a386Sopenharmony_ci SkIRect scissorRect; 569cb93a386Sopenharmony_ci drawBounds.round(&scissorRect); 570cb93a386Sopenharmony_ci this->clear(scissorRect, *constColor); 571cb93a386Sopenharmony_ci return QuadOptimization::kSubmitted; 572cb93a386Sopenharmony_ci } 573cb93a386Sopenharmony_ci } 574cb93a386Sopenharmony_ci 575cb93a386Sopenharmony_ci // else the draw and clip were combined so just update the AA to reflect combination 576cb93a386Sopenharmony_ci if (*aa == GrAA::kNo && result.fAA == GrAA::kYes && 577cb93a386Sopenharmony_ci quad->fEdgeFlags != GrQuadAAFlags::kNone) { 578cb93a386Sopenharmony_ci // The clip was anti-aliased and now the draw needs to be upgraded to AA to 579cb93a386Sopenharmony_ci // properly reflect the smooth edge of the clip. 580cb93a386Sopenharmony_ci *aa = GrAA::kYes; 581cb93a386Sopenharmony_ci } 582cb93a386Sopenharmony_ci // We intentionally do not downgrade AA here because we don't know if we need to 583cb93a386Sopenharmony_ci // preserve MSAA (see GrQuadAAFlags docs). But later in the pipeline, the ops can 584cb93a386Sopenharmony_ci // use GrResolveAATypeForQuad() to turn off coverage AA when all flags are off. 585cb93a386Sopenharmony_ci // deviceQuad is exactly the intersection of original quad and clip, so it can be 586cb93a386Sopenharmony_ci // drawn with no clip (submitted by caller) 587cb93a386Sopenharmony_ci return QuadOptimization::kClipApplied; 588cb93a386Sopenharmony_ci } 589cb93a386Sopenharmony_ci } else { 590cb93a386Sopenharmony_ci // Rounded corners and constant filled color (limit ourselves to solid colors because 591cb93a386Sopenharmony_ci // there is no way to use custom local coordinates with drawRRect). 592cb93a386Sopenharmony_ci SkASSERT(simpleColor); 593cb93a386Sopenharmony_ci if (GrQuadUtils::CropToRect(clippedBounds, result.fAA, quad, 594cb93a386Sopenharmony_ci /* compute local */ false) && 595cb93a386Sopenharmony_ci quad->fDevice.quadType() == GrQuad::Type::kAxisAligned && 596cb93a386Sopenharmony_ci quad->fDevice.bounds().contains(clippedBounds)) { 597cb93a386Sopenharmony_ci // Since the cropped quad became a rectangle which covered the bounds of the rrect, 598cb93a386Sopenharmony_ci // we can draw the rrect directly and ignore the edge flags 599cb93a386Sopenharmony_ci this->drawRRect(nullptr, std::move(*paint), result.fAA, SkMatrix::I(), result.fRRect, 600cb93a386Sopenharmony_ci GrStyle::SimpleFill()); 601cb93a386Sopenharmony_ci return QuadOptimization::kSubmitted; 602cb93a386Sopenharmony_ci } 603cb93a386Sopenharmony_ci } 604cb93a386Sopenharmony_ci 605cb93a386Sopenharmony_ci // The quads have been updated to better fit the clip bounds, but can't get rid of 606cb93a386Sopenharmony_ci // the clip entirely 607cb93a386Sopenharmony_ci quad->fEdgeFlags = oldFlags; 608cb93a386Sopenharmony_ci return QuadOptimization::kCropped; 609cb93a386Sopenharmony_ci} 610cb93a386Sopenharmony_ci 611cb93a386Sopenharmony_civoid SurfaceDrawContext::drawFilledQuad(const GrClip* clip, 612cb93a386Sopenharmony_ci GrPaint&& paint, 613cb93a386Sopenharmony_ci GrAA aa, 614cb93a386Sopenharmony_ci DrawQuad* quad, 615cb93a386Sopenharmony_ci const GrUserStencilSettings* ss) { 616cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 617cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 618cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 619cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawFilledQuad", fContext); 620cb93a386Sopenharmony_ci 621cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 622cb93a386Sopenharmony_ci 623cb93a386Sopenharmony_ci QuadOptimization opt = this->attemptQuadOptimization(clip, ss, &aa, quad, &paint); 624cb93a386Sopenharmony_ci if (opt >= QuadOptimization::kClipApplied) { 625cb93a386Sopenharmony_ci // These optimizations require caller to add an op themselves 626cb93a386Sopenharmony_ci const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip; 627cb93a386Sopenharmony_ci GrAAType aaType; 628cb93a386Sopenharmony_ci if (ss) { 629cb93a386Sopenharmony_ci aaType = (aa == GrAA::kYes) ? GrAAType::kMSAA : GrAAType::kNone; 630cb93a386Sopenharmony_ci } else if (fCanUseDynamicMSAA && aa == GrAA::kNo) { 631cb93a386Sopenharmony_ci // The SkGpuDevice ensures GrAA is always kYes when using dmsaa. If the caller calls 632cb93a386Sopenharmony_ci // into here with GrAA::kNo, trust that they know what they're doing and that the 633cb93a386Sopenharmony_ci // rendering will be equal with or without msaa. 634cb93a386Sopenharmony_ci aaType = GrAAType::kNone; 635cb93a386Sopenharmony_ci } else { 636cb93a386Sopenharmony_ci aaType = this->chooseAAType(aa); 637cb93a386Sopenharmony_ci } 638cb93a386Sopenharmony_ci this->addDrawOp(finalClip, FillRectOp::Make(fContext, std::move(paint), aaType, 639cb93a386Sopenharmony_ci quad, ss)); 640cb93a386Sopenharmony_ci } 641cb93a386Sopenharmony_ci // All other optimization levels were completely handled inside attempt(), so no extra op needed 642cb93a386Sopenharmony_ci} 643cb93a386Sopenharmony_ci 644cb93a386Sopenharmony_civoid SurfaceDrawContext::drawTexture(const GrClip* clip, 645cb93a386Sopenharmony_ci GrSurfaceProxyView view, 646cb93a386Sopenharmony_ci SkAlphaType srcAlphaType, 647cb93a386Sopenharmony_ci GrSamplerState::Filter filter, 648cb93a386Sopenharmony_ci GrSamplerState::MipmapMode mm, 649cb93a386Sopenharmony_ci SkBlendMode blendMode, 650cb93a386Sopenharmony_ci const SkPMColor4f& color, 651cb93a386Sopenharmony_ci const SkRect& srcRect, 652cb93a386Sopenharmony_ci const SkRect& dstRect, 653cb93a386Sopenharmony_ci GrAA aa, 654cb93a386Sopenharmony_ci GrQuadAAFlags edgeAA, 655cb93a386Sopenharmony_ci SkCanvas::SrcRectConstraint constraint, 656cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 657cb93a386Sopenharmony_ci sk_sp<GrColorSpaceXform> colorSpaceXform) { 658cb93a386Sopenharmony_ci // If we are using dmsaa then go through FillRRectOp (via fillRectToRect). 659cb93a386Sopenharmony_ci if ((this->alwaysAntialias() || this->caps()->reducedShaderMode()) && aa == GrAA::kYes) { 660cb93a386Sopenharmony_ci GrPaint paint; 661cb93a386Sopenharmony_ci paint.setColor4f(color); 662cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> fp; 663cb93a386Sopenharmony_ci if (constraint == SkCanvas::kStrict_SrcRectConstraint) { 664cb93a386Sopenharmony_ci fp = GrTextureEffect::MakeSubset(view, srcAlphaType, SkMatrix::I(), 665cb93a386Sopenharmony_ci GrSamplerState(filter, mm), srcRect, 666cb93a386Sopenharmony_ci *this->caps()); 667cb93a386Sopenharmony_ci } else { 668cb93a386Sopenharmony_ci fp = GrTextureEffect::Make(view, srcAlphaType, SkMatrix::I(), filter, mm); 669cb93a386Sopenharmony_ci } 670cb93a386Sopenharmony_ci if (colorSpaceXform) { 671cb93a386Sopenharmony_ci fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(colorSpaceXform)); 672cb93a386Sopenharmony_ci } 673cb93a386Sopenharmony_ci fp = GrBlendFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kModulate); 674cb93a386Sopenharmony_ci paint.setColorFragmentProcessor(std::move(fp)); 675cb93a386Sopenharmony_ci if (blendMode != SkBlendMode::kSrcOver) { 676cb93a386Sopenharmony_ci paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode)); 677cb93a386Sopenharmony_ci } 678cb93a386Sopenharmony_ci this->fillRectToRect(clip, std::move(paint), GrAA::kYes, viewMatrix, dstRect, srcRect); 679cb93a386Sopenharmony_ci return; 680cb93a386Sopenharmony_ci } 681cb93a386Sopenharmony_ci 682cb93a386Sopenharmony_ci const SkRect* subset = constraint == SkCanvas::kStrict_SrcRectConstraint ? 683cb93a386Sopenharmony_ci &srcRect : nullptr; 684cb93a386Sopenharmony_ci DrawQuad quad{GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect), edgeAA}; 685cb93a386Sopenharmony_ci 686cb93a386Sopenharmony_ci this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(colorSpaceXform), filter, 687cb93a386Sopenharmony_ci mm, color, blendMode, aa, &quad, subset); 688cb93a386Sopenharmony_ci} 689cb93a386Sopenharmony_ci 690cb93a386Sopenharmony_civoid SurfaceDrawContext::drawTexturedQuad(const GrClip* clip, 691cb93a386Sopenharmony_ci GrSurfaceProxyView proxyView, 692cb93a386Sopenharmony_ci SkAlphaType srcAlphaType, 693cb93a386Sopenharmony_ci sk_sp<GrColorSpaceXform> textureXform, 694cb93a386Sopenharmony_ci GrSamplerState::Filter filter, 695cb93a386Sopenharmony_ci GrSamplerState::MipmapMode mm, 696cb93a386Sopenharmony_ci const SkPMColor4f& color, 697cb93a386Sopenharmony_ci SkBlendMode blendMode, 698cb93a386Sopenharmony_ci GrAA aa, 699cb93a386Sopenharmony_ci DrawQuad* quad, 700cb93a386Sopenharmony_ci const SkRect* subset) { 701cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 702cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 703cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 704cb93a386Sopenharmony_ci SkASSERT(proxyView.asTextureProxy()); 705cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawTexturedQuad", fContext); 706cb93a386Sopenharmony_ci 707cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_ci // Functionally this is very similar to drawFilledQuad except that there's no constColor to 710cb93a386Sopenharmony_ci // enable the kSubmitted optimizations, no stencil settings support, and its a TextureOp. 711cb93a386Sopenharmony_ci QuadOptimization opt = this->attemptQuadOptimization(clip, nullptr/*stencil*/, &aa, quad, 712cb93a386Sopenharmony_ci nullptr/*paint*/); 713cb93a386Sopenharmony_ci 714cb93a386Sopenharmony_ci SkASSERT(opt != QuadOptimization::kSubmitted); 715cb93a386Sopenharmony_ci if (opt != QuadOptimization::kDiscarded) { 716cb93a386Sopenharmony_ci // And the texture op if not discarded 717cb93a386Sopenharmony_ci const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip; 718cb93a386Sopenharmony_ci GrAAType aaType = this->chooseAAType(aa); 719cb93a386Sopenharmony_ci auto clampType = GrColorTypeClampType(this->colorInfo().colorType()); 720cb93a386Sopenharmony_ci auto saturate = clampType == GrClampType::kManual ? TextureOp::Saturate::kYes 721cb93a386Sopenharmony_ci : TextureOp::Saturate::kNo; 722cb93a386Sopenharmony_ci // Use the provided subset, although hypothetically we could detect that the cropped local 723cb93a386Sopenharmony_ci // quad is sufficiently inside the subset and the constraint could be dropped. 724cb93a386Sopenharmony_ci this->addDrawOp(finalClip, 725cb93a386Sopenharmony_ci TextureOp::Make(fContext, std::move(proxyView), srcAlphaType, 726cb93a386Sopenharmony_ci std::move(textureXform), filter, mm, color, saturate, 727cb93a386Sopenharmony_ci blendMode, aaType, quad, subset)); 728cb93a386Sopenharmony_ci } 729cb93a386Sopenharmony_ci} 730cb93a386Sopenharmony_ci 731cb93a386Sopenharmony_civoid SurfaceDrawContext::drawRect(const GrClip* clip, 732cb93a386Sopenharmony_ci GrPaint&& paint, 733cb93a386Sopenharmony_ci GrAA aa, 734cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 735cb93a386Sopenharmony_ci const SkRect& rect, 736cb93a386Sopenharmony_ci const GrStyle* style) { 737cb93a386Sopenharmony_ci if (!style) { 738cb93a386Sopenharmony_ci style = &GrStyle::SimpleFill(); 739cb93a386Sopenharmony_ci } 740cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 741cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 742cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 743cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawRect", fContext); 744cb93a386Sopenharmony_ci 745cb93a386Sopenharmony_ci // Path effects should've been devolved to a path in SkGpuDevice 746cb93a386Sopenharmony_ci SkASSERT(!style->pathEffect()); 747cb93a386Sopenharmony_ci 748cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 749cb93a386Sopenharmony_ci 750cb93a386Sopenharmony_ci const SkStrokeRec& stroke = style->strokeRec(); 751cb93a386Sopenharmony_ci if (stroke.getStyle() == SkStrokeRec::kFill_Style) { 752cb93a386Sopenharmony_ci // Fills the rect, using rect as its own local coordinates 753cb93a386Sopenharmony_ci this->fillRectToRect(clip, std::move(paint), aa, viewMatrix, rect, rect); 754cb93a386Sopenharmony_ci return; 755cb93a386Sopenharmony_ci } else if ((stroke.getStyle() == SkStrokeRec::kStroke_Style || 756cb93a386Sopenharmony_ci stroke.getStyle() == SkStrokeRec::kHairline_Style) && 757cb93a386Sopenharmony_ci rect.width() && 758cb93a386Sopenharmony_ci rect.height() && 759cb93a386Sopenharmony_ci !this->caps()->reducedShaderMode()) { 760cb93a386Sopenharmony_ci // Only use the StrokeRectOp for non-empty rectangles. Empty rectangles will be processed by 761cb93a386Sopenharmony_ci // GrStyledShape to handle stroke caps and dashing properly. 762cb93a386Sopenharmony_ci // 763cb93a386Sopenharmony_ci // http://skbug.com/12206 -- there is a double-blend issue with the bevel version of 764cb93a386Sopenharmony_ci // AAStrokeRectOp, and if we increase the AA bloat for MSAA it becomes more pronounced. 765cb93a386Sopenharmony_ci // Don't use the bevel version with DMSAA. 766cb93a386Sopenharmony_ci GrAAType aaType = (fCanUseDynamicMSAA && 767cb93a386Sopenharmony_ci stroke.getJoin() == SkPaint::kMiter_Join && 768cb93a386Sopenharmony_ci stroke.getMiter() >= SK_ScalarSqrt2) ? GrAAType::kCoverage 769cb93a386Sopenharmony_ci : this->chooseAAType(aa); 770cb93a386Sopenharmony_ci GrOp::Owner op = StrokeRectOp::Make(fContext, std::move(paint), aaType, viewMatrix, 771cb93a386Sopenharmony_ci rect, stroke); 772cb93a386Sopenharmony_ci // op may be null if the stroke is not supported or if using coverage aa and the view matrix 773cb93a386Sopenharmony_ci // does not preserve rectangles. 774cb93a386Sopenharmony_ci if (op) { 775cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 776cb93a386Sopenharmony_ci return; 777cb93a386Sopenharmony_ci } 778cb93a386Sopenharmony_ci } 779cb93a386Sopenharmony_ci assert_alive(paint); 780cb93a386Sopenharmony_ci this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, 781cb93a386Sopenharmony_ci GrStyledShape(rect, *style, DoSimplify::kNo)); 782cb93a386Sopenharmony_ci} 783cb93a386Sopenharmony_ci 784cb93a386Sopenharmony_civoid SurfaceDrawContext::fillRectToRect(const GrClip* clip, 785cb93a386Sopenharmony_ci GrPaint&& paint, 786cb93a386Sopenharmony_ci GrAA aa, 787cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 788cb93a386Sopenharmony_ci const SkRect& rectToDraw, 789cb93a386Sopenharmony_ci const SkRect& localRect) { 790cb93a386Sopenharmony_ci DrawQuad quad{GrQuad::MakeFromRect(rectToDraw, viewMatrix), GrQuad(localRect), 791cb93a386Sopenharmony_ci aa == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone}; 792cb93a386Sopenharmony_ci 793cb93a386Sopenharmony_ci // If we are using dmsaa then attempt to draw the rect with FillRRectOp. 794cb93a386Sopenharmony_ci if ((fContext->priv().caps()->reducedShaderMode() || this->alwaysAntialias()) && 795cb93a386Sopenharmony_ci this->caps()->drawInstancedSupport() && 796cb93a386Sopenharmony_ci aa == GrAA::kYes) { // If aa is kNo when using dmsaa, the rect is axis aligned. Don't use 797cb93a386Sopenharmony_ci // FillRRectOp because it might require dual source blending. 798cb93a386Sopenharmony_ci // http://skbug.com/11756 799cb93a386Sopenharmony_ci QuadOptimization opt = this->attemptQuadOptimization(clip, nullptr/*stencil*/, &aa, &quad, 800cb93a386Sopenharmony_ci &paint); 801cb93a386Sopenharmony_ci if (opt < QuadOptimization::kClipApplied) { 802cb93a386Sopenharmony_ci // The optimization was completely handled inside attempt(). 803cb93a386Sopenharmony_ci return; 804cb93a386Sopenharmony_ci } 805cb93a386Sopenharmony_ci 806cb93a386Sopenharmony_ci SkRect croppedRect, croppedLocal{}; 807cb93a386Sopenharmony_ci const GrClip* optimizedClip = clip; 808cb93a386Sopenharmony_ci if (clip && viewMatrix.isScaleTranslate() && quad.fDevice.asRect(&croppedRect) && 809cb93a386Sopenharmony_ci (!paint.usesLocalCoords() || quad.fLocal.asRect(&croppedLocal))) { 810cb93a386Sopenharmony_ci // The cropped quad is still a rect, and our view matrix preserves rects. Map it back 811cb93a386Sopenharmony_ci // to pre-matrix space. 812cb93a386Sopenharmony_ci SkMatrix inverse; 813cb93a386Sopenharmony_ci if (!viewMatrix.invert(&inverse)) { 814cb93a386Sopenharmony_ci return; 815cb93a386Sopenharmony_ci } 816cb93a386Sopenharmony_ci SkASSERT(inverse.rectStaysRect()); 817cb93a386Sopenharmony_ci inverse.mapRect(&croppedRect); 818cb93a386Sopenharmony_ci if (opt == QuadOptimization::kClipApplied) { 819cb93a386Sopenharmony_ci optimizedClip = nullptr; 820cb93a386Sopenharmony_ci } 821cb93a386Sopenharmony_ci } else { 822cb93a386Sopenharmony_ci // Even if attemptQuadOptimization gave us an optimized quad, FillRRectOp needs a rect 823cb93a386Sopenharmony_ci // in pre-matrix space, so use the original rect. Also preserve the original clip. 824cb93a386Sopenharmony_ci croppedRect = rectToDraw; 825cb93a386Sopenharmony_ci croppedLocal = localRect; 826cb93a386Sopenharmony_ci } 827cb93a386Sopenharmony_ci 828cb93a386Sopenharmony_ci if (auto op = FillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint), 829cb93a386Sopenharmony_ci viewMatrix, SkRRect::MakeRect(croppedRect), croppedLocal, 830cb93a386Sopenharmony_ci GrAA::kYes)) { 831cb93a386Sopenharmony_ci this->addDrawOp(optimizedClip, std::move(op)); 832cb93a386Sopenharmony_ci return; 833cb93a386Sopenharmony_ci } 834cb93a386Sopenharmony_ci } 835cb93a386Sopenharmony_ci 836cb93a386Sopenharmony_ci assert_alive(paint); 837cb93a386Sopenharmony_ci this->drawFilledQuad(clip, std::move(paint), aa, &quad); 838cb93a386Sopenharmony_ci} 839cb93a386Sopenharmony_ci 840cb93a386Sopenharmony_civoid SurfaceDrawContext::drawQuadSet(const GrClip* clip, 841cb93a386Sopenharmony_ci GrPaint&& paint, 842cb93a386Sopenharmony_ci GrAA aa, 843cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 844cb93a386Sopenharmony_ci const GrQuadSetEntry quads[], 845cb93a386Sopenharmony_ci int cnt) { 846cb93a386Sopenharmony_ci GrAAType aaType = this->chooseAAType(aa); 847cb93a386Sopenharmony_ci 848cb93a386Sopenharmony_ci FillRectOp::AddFillRectOps(this, clip, fContext, std::move(paint), aaType, viewMatrix, 849cb93a386Sopenharmony_ci quads, cnt); 850cb93a386Sopenharmony_ci} 851cb93a386Sopenharmony_ci 852cb93a386Sopenharmony_ciint SurfaceDrawContext::maxWindowRectangles() const { 853cb93a386Sopenharmony_ci return this->asRenderTargetProxy()->maxWindowRectangles(*this->caps()); 854cb93a386Sopenharmony_ci} 855cb93a386Sopenharmony_ci 856cb93a386Sopenharmony_ciOpsTask::CanDiscardPreviousOps SurfaceDrawContext::canDiscardPreviousOpsOnFullClear() const { 857cb93a386Sopenharmony_ci#if GR_TEST_UTILS 858cb93a386Sopenharmony_ci if (fPreserveOpsOnFullClear_TestingOnly) { 859cb93a386Sopenharmony_ci return OpsTask::CanDiscardPreviousOps::kNo; 860cb93a386Sopenharmony_ci } 861cb93a386Sopenharmony_ci#endif 862cb93a386Sopenharmony_ci // Regardless of how the clear is implemented (native clear or a fullscreen quad), all prior ops 863cb93a386Sopenharmony_ci // would normally be overwritten. The one exception is if the render target context is marked as 864cb93a386Sopenharmony_ci // needing a stencil buffer then there may be a prior op that writes to the stencil buffer. 865cb93a386Sopenharmony_ci // Although the clear will ignore the stencil buffer, following draw ops may not so we can't get 866cb93a386Sopenharmony_ci // rid of all the preceding ops. Beware! If we ever add any ops that have a side effect beyond 867cb93a386Sopenharmony_ci // modifying the stencil buffer we will need a more elaborate tracking system (skbug.com/7002). 868cb93a386Sopenharmony_ci return OpsTask::CanDiscardPreviousOps(!fNeedsStencil); 869cb93a386Sopenharmony_ci} 870cb93a386Sopenharmony_ci 871cb93a386Sopenharmony_civoid SurfaceDrawContext::setNeedsStencil() { 872cb93a386Sopenharmony_ci // Don't clear stencil until after we've set fNeedsStencil. This ensures we don't loop forever 873cb93a386Sopenharmony_ci // in the event that there are driver bugs and we need to clear as a draw. 874cb93a386Sopenharmony_ci bool hasInitializedStencil = fNeedsStencil; 875cb93a386Sopenharmony_ci fNeedsStencil = true; 876cb93a386Sopenharmony_ci if (!hasInitializedStencil) { 877cb93a386Sopenharmony_ci this->asRenderTargetProxy()->setNeedsStencil(); 878cb93a386Sopenharmony_ci if (this->caps()->performStencilClearsAsDraws()) { 879cb93a386Sopenharmony_ci // There is a driver bug with clearing stencil. We must use an op to manually clear the 880cb93a386Sopenharmony_ci // stencil buffer before the op that required 'setNeedsStencil'. 881cb93a386Sopenharmony_ci this->internalStencilClear(nullptr, /* inside mask */ false); 882cb93a386Sopenharmony_ci } else { 883cb93a386Sopenharmony_ci this->getOpsTask()->setInitialStencilContent( 884cb93a386Sopenharmony_ci OpsTask::StencilContent::kUserBitsCleared); 885cb93a386Sopenharmony_ci } 886cb93a386Sopenharmony_ci } 887cb93a386Sopenharmony_ci} 888cb93a386Sopenharmony_ci 889cb93a386Sopenharmony_civoid SurfaceDrawContext::internalStencilClear(const SkIRect* scissor, bool insideStencilMask) { 890cb93a386Sopenharmony_ci this->setNeedsStencil(); 891cb93a386Sopenharmony_ci 892cb93a386Sopenharmony_ci GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions()); 893cb93a386Sopenharmony_ci if (scissor && !scissorState.set(*scissor)) { 894cb93a386Sopenharmony_ci // The requested clear region is off screen, so nothing to do. 895cb93a386Sopenharmony_ci return; 896cb93a386Sopenharmony_ci } 897cb93a386Sopenharmony_ci 898cb93a386Sopenharmony_ci bool clearWithDraw = this->caps()->performStencilClearsAsDraws() || 899cb93a386Sopenharmony_ci (scissorState.enabled() && this->caps()->performPartialClearsAsDraws()); 900cb93a386Sopenharmony_ci if (clearWithDraw) { 901cb93a386Sopenharmony_ci const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask); 902cb93a386Sopenharmony_ci 903cb93a386Sopenharmony_ci // Configure the paint to have no impact on the color buffer 904cb93a386Sopenharmony_ci GrPaint paint; 905cb93a386Sopenharmony_ci paint.setXPFactory(GrDisableColorXPFactory::Get()); 906cb93a386Sopenharmony_ci this->addDrawOp(nullptr, 907cb93a386Sopenharmony_ci FillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(), 908cb93a386Sopenharmony_ci SkRect::Make(scissorState.rect()), ss)); 909cb93a386Sopenharmony_ci } else { 910cb93a386Sopenharmony_ci this->addOp(ClearOp::MakeStencilClip(fContext, scissorState, insideStencilMask)); 911cb93a386Sopenharmony_ci } 912cb93a386Sopenharmony_ci} 913cb93a386Sopenharmony_ci 914cb93a386Sopenharmony_cibool SurfaceDrawContext::stencilPath(const GrHardClip* clip, 915cb93a386Sopenharmony_ci GrAA doStencilMSAA, 916cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 917cb93a386Sopenharmony_ci const SkPath& path) { 918cb93a386Sopenharmony_ci SkIRect clipBounds = clip ? clip->getConservativeBounds() 919cb93a386Sopenharmony_ci : SkIRect::MakeSize(this->dimensions()); 920cb93a386Sopenharmony_ci GrStyledShape shape(path, GrStyledShape::DoSimplify::kNo); 921cb93a386Sopenharmony_ci 922cb93a386Sopenharmony_ci PathRenderer::CanDrawPathArgs canDrawArgs; 923cb93a386Sopenharmony_ci canDrawArgs.fCaps = fContext->priv().caps(); 924cb93a386Sopenharmony_ci canDrawArgs.fProxy = this->asRenderTargetProxy(); 925cb93a386Sopenharmony_ci canDrawArgs.fClipConservativeBounds = &clipBounds; 926cb93a386Sopenharmony_ci canDrawArgs.fViewMatrix = &viewMatrix; 927cb93a386Sopenharmony_ci canDrawArgs.fShape = &shape; 928cb93a386Sopenharmony_ci canDrawArgs.fPaint = nullptr; 929cb93a386Sopenharmony_ci canDrawArgs.fSurfaceProps = &fSurfaceProps; 930cb93a386Sopenharmony_ci canDrawArgs.fAAType = (doStencilMSAA == GrAA::kYes) ? GrAAType::kMSAA : GrAAType::kNone; 931cb93a386Sopenharmony_ci canDrawArgs.fHasUserStencilSettings = false; 932cb93a386Sopenharmony_ci auto pr = this->drawingManager()->getPathRenderer(canDrawArgs, 933cb93a386Sopenharmony_ci false, 934cb93a386Sopenharmony_ci PathRendererChain::DrawType::kStencil); 935cb93a386Sopenharmony_ci if (!pr) { 936cb93a386Sopenharmony_ci SkDebugf("WARNING: No path renderer to stencil path.\n"); 937cb93a386Sopenharmony_ci return false; 938cb93a386Sopenharmony_ci } 939cb93a386Sopenharmony_ci 940cb93a386Sopenharmony_ci PathRenderer::StencilPathArgs args; 941cb93a386Sopenharmony_ci args.fContext = fContext; 942cb93a386Sopenharmony_ci args.fSurfaceDrawContext = this; 943cb93a386Sopenharmony_ci args.fClip = clip; 944cb93a386Sopenharmony_ci args.fClipConservativeBounds = &clipBounds; 945cb93a386Sopenharmony_ci args.fViewMatrix = &viewMatrix; 946cb93a386Sopenharmony_ci args.fShape = &shape; 947cb93a386Sopenharmony_ci args.fDoStencilMSAA = doStencilMSAA; 948cb93a386Sopenharmony_ci pr->stencilPath(args); 949cb93a386Sopenharmony_ci return true; 950cb93a386Sopenharmony_ci} 951cb93a386Sopenharmony_ci 952cb93a386Sopenharmony_civoid SurfaceDrawContext::drawTextureSet(const GrClip* clip, 953cb93a386Sopenharmony_ci GrTextureSetEntry set[], 954cb93a386Sopenharmony_ci int cnt, 955cb93a386Sopenharmony_ci int proxyRunCnt, 956cb93a386Sopenharmony_ci GrSamplerState::Filter filter, 957cb93a386Sopenharmony_ci GrSamplerState::MipmapMode mm, 958cb93a386Sopenharmony_ci SkBlendMode mode, 959cb93a386Sopenharmony_ci GrAA aa, 960cb93a386Sopenharmony_ci SkCanvas::SrcRectConstraint constraint, 961cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 962cb93a386Sopenharmony_ci sk_sp<GrColorSpaceXform> texXform) { 963cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 964cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 965cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 966cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawTextureSet", fContext); 967cb93a386Sopenharmony_ci 968cb93a386Sopenharmony_ci // Create the minimum number of GrTextureOps needed to draw this set. Individual 969cb93a386Sopenharmony_ci // GrTextureOps can rebind the texture between draws thus avoiding GrPaint (re)creation. 970cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 971cb93a386Sopenharmony_ci GrAAType aaType = this->chooseAAType(aa); 972cb93a386Sopenharmony_ci auto clampType = GrColorTypeClampType(this->colorInfo().colorType()); 973cb93a386Sopenharmony_ci auto saturate = clampType == GrClampType::kManual ? TextureOp::Saturate::kYes 974cb93a386Sopenharmony_ci : TextureOp::Saturate::kNo; 975cb93a386Sopenharmony_ci TextureOp::AddTextureSetOps(this, clip, fContext, set, cnt, proxyRunCnt, filter, mm, saturate, 976cb93a386Sopenharmony_ci mode, aaType, constraint, viewMatrix, std::move(texXform)); 977cb93a386Sopenharmony_ci} 978cb93a386Sopenharmony_ci 979cb93a386Sopenharmony_civoid SurfaceDrawContext::drawVertices(const GrClip* clip, 980cb93a386Sopenharmony_ci GrPaint&& paint, 981cb93a386Sopenharmony_ci const SkMatrixProvider& matrixProvider, 982cb93a386Sopenharmony_ci sk_sp<SkVertices> vertices, 983cb93a386Sopenharmony_ci GrPrimitiveType* overridePrimType) { 984cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 985cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 986cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 987cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawVertices", fContext); 988cb93a386Sopenharmony_ci 989cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 990cb93a386Sopenharmony_ci 991cb93a386Sopenharmony_ci SkASSERT(vertices); 992cb93a386Sopenharmony_ci GrAAType aaType = fCanUseDynamicMSAA ? GrAAType::kMSAA : this->chooseAAType(GrAA::kNo); 993cb93a386Sopenharmony_ci GrOp::Owner op = DrawVerticesOp::Make(fContext, 994cb93a386Sopenharmony_ci std::move(paint), 995cb93a386Sopenharmony_ci std::move(vertices), 996cb93a386Sopenharmony_ci matrixProvider, 997cb93a386Sopenharmony_ci aaType, 998cb93a386Sopenharmony_ci this->colorInfo().refColorSpaceXformFromSRGB(), 999cb93a386Sopenharmony_ci overridePrimType); 1000cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1001cb93a386Sopenharmony_ci} 1002cb93a386Sopenharmony_ci 1003cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1004cb93a386Sopenharmony_ci 1005cb93a386Sopenharmony_civoid SurfaceDrawContext::drawAtlas(const GrClip* clip, 1006cb93a386Sopenharmony_ci GrPaint&& paint, 1007cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1008cb93a386Sopenharmony_ci int spriteCount, 1009cb93a386Sopenharmony_ci const SkRSXform xform[], 1010cb93a386Sopenharmony_ci const SkRect texRect[], 1011cb93a386Sopenharmony_ci const SkColor colors[]) { 1012cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1013cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 1014cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1015cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawAtlas", fContext); 1016cb93a386Sopenharmony_ci 1017cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 1018cb93a386Sopenharmony_ci 1019cb93a386Sopenharmony_ci GrAAType aaType = this->chooseAAType(GrAA::kNo); 1020cb93a386Sopenharmony_ci GrOp::Owner op = DrawAtlasOp::Make(fContext, std::move(paint), viewMatrix, 1021cb93a386Sopenharmony_ci aaType, spriteCount, xform, texRect, colors); 1022cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1023cb93a386Sopenharmony_ci} 1024cb93a386Sopenharmony_ci 1025cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1026cb93a386Sopenharmony_ci 1027cb93a386Sopenharmony_civoid SurfaceDrawContext::drawRRect(const GrClip* origClip, 1028cb93a386Sopenharmony_ci GrPaint&& paint, 1029cb93a386Sopenharmony_ci GrAA aa, 1030cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1031cb93a386Sopenharmony_ci const SkRRect& rrect, 1032cb93a386Sopenharmony_ci const GrStyle& style) { 1033cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1034cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 1035cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1036cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawRRect", fContext); 1037cb93a386Sopenharmony_ci 1038cb93a386Sopenharmony_ci SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice 1039cb93a386Sopenharmony_ci 1040cb93a386Sopenharmony_ci const SkStrokeRec& stroke = style.strokeRec(); 1041cb93a386Sopenharmony_ci if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.isEmpty()) { 1042cb93a386Sopenharmony_ci return; 1043cb93a386Sopenharmony_ci } 1044cb93a386Sopenharmony_ci 1045cb93a386Sopenharmony_ci const GrClip* clip = origClip; 1046cb93a386Sopenharmony_ci // It is not uncommon to clip to a round rect and then draw that same round rect. Since our 1047cb93a386Sopenharmony_ci // lower level clip code works from op bounds, which are SkRects, it doesn't detect that the 1048cb93a386Sopenharmony_ci // clip can be ignored. The following test attempts to mitigate the stencil clip cost but only 1049cb93a386Sopenharmony_ci // works for axis-aligned round rects. This also only works for filled rrects since the stroke 1050cb93a386Sopenharmony_ci // width outsets beyond the rrect itself. 1051cb93a386Sopenharmony_ci // TODO: skbug.com/10462 - There was mixed performance wins and regressions when this 1052cb93a386Sopenharmony_ci // optimization was turned on outside of Android Framework. I (michaelludwig) believe this is 1053cb93a386Sopenharmony_ci // do to the overhead in determining if an SkClipStack is just a rrect. Once that is improved, 1054cb93a386Sopenharmony_ci // re-enable this and see if we avoid the regressions. 1055cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 1056cb93a386Sopenharmony_ci SkRRect devRRect; 1057cb93a386Sopenharmony_ci if (clip && stroke.getStyle() == SkStrokeRec::kFill_Style && 1058cb93a386Sopenharmony_ci rrect.transform(viewMatrix, &devRRect)) { 1059cb93a386Sopenharmony_ci GrClip::PreClipResult result = clip->preApply(devRRect.getBounds(), aa); 1060cb93a386Sopenharmony_ci switch(result.fEffect) { 1061cb93a386Sopenharmony_ci case GrClip::Effect::kClippedOut: 1062cb93a386Sopenharmony_ci return; 1063cb93a386Sopenharmony_ci case GrClip::Effect::kUnclipped: 1064cb93a386Sopenharmony_ci clip = nullptr; 1065cb93a386Sopenharmony_ci break; 1066cb93a386Sopenharmony_ci case GrClip::Effect::kClipped: 1067cb93a386Sopenharmony_ci // Currently there's no general-purpose rrect-to-rrect contains function, and if we 1068cb93a386Sopenharmony_ci // got here, we know the devRRect's bounds aren't fully contained by the clip. 1069cb93a386Sopenharmony_ci // Testing for equality between the two is a reasonable stop-gap for now. 1070cb93a386Sopenharmony_ci if (result.fIsRRect && result.fRRect == devRRect) { 1071cb93a386Sopenharmony_ci // NOTE: On the android framework, we allow this optimization even when the clip 1072cb93a386Sopenharmony_ci // is non-AA and the draw is AA. 1073cb93a386Sopenharmony_ci if (result.fAA == aa || (result.fAA == GrAA::kNo && aa == GrAA::kYes)) { 1074cb93a386Sopenharmony_ci clip = nullptr; 1075cb93a386Sopenharmony_ci } 1076cb93a386Sopenharmony_ci } 1077cb93a386Sopenharmony_ci break; 1078cb93a386Sopenharmony_ci default: 1079cb93a386Sopenharmony_ci SkUNREACHABLE; 1080cb93a386Sopenharmony_ci } 1081cb93a386Sopenharmony_ci } 1082cb93a386Sopenharmony_ci#endif 1083cb93a386Sopenharmony_ci 1084cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 1085cb93a386Sopenharmony_ci 1086cb93a386Sopenharmony_ci GrAAType aaType = this->chooseAAType(aa); 1087cb93a386Sopenharmony_ci 1088cb93a386Sopenharmony_ci GrOp::Owner op; 1089cb93a386Sopenharmony_ci if (aaType == GrAAType::kCoverage && 1090cb93a386Sopenharmony_ci !fCanUseDynamicMSAA && 1091cb93a386Sopenharmony_ci !this->caps()->reducedShaderMode() && 1092cb93a386Sopenharmony_ci rrect.isSimple() && 1093cb93a386Sopenharmony_ci rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY && 1094cb93a386Sopenharmony_ci viewMatrix.rectStaysRect() && viewMatrix.isSimilarity()) { 1095cb93a386Sopenharmony_ci // In specific cases we use a dedicated circular round rect op to try and get better perf. 1096cb93a386Sopenharmony_ci assert_alive(paint); 1097cb93a386Sopenharmony_ci op = GrOvalOpFactory::MakeCircularRRectOp(fContext, std::move(paint), viewMatrix, rrect, 1098cb93a386Sopenharmony_ci stroke, this->caps()->shaderCaps()); 1099cb93a386Sopenharmony_ci } 1100cb93a386Sopenharmony_ci if (!op && style.isSimpleFill()) { 1101cb93a386Sopenharmony_ci assert_alive(paint); 1102cb93a386Sopenharmony_ci op = FillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint), viewMatrix, rrect, 1103cb93a386Sopenharmony_ci rrect.rect(), GrAA(aaType != GrAAType::kNone)); 1104cb93a386Sopenharmony_ci } 1105cb93a386Sopenharmony_ci if (!op && (aaType == GrAAType::kCoverage || fCanUseDynamicMSAA)) { 1106cb93a386Sopenharmony_ci assert_alive(paint); 1107cb93a386Sopenharmony_ci op = GrOvalOpFactory::MakeRRectOp( 1108cb93a386Sopenharmony_ci fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps()); 1109cb93a386Sopenharmony_ci } 1110cb93a386Sopenharmony_ci if (op) { 1111cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1112cb93a386Sopenharmony_ci return; 1113cb93a386Sopenharmony_ci } 1114cb93a386Sopenharmony_ci 1115cb93a386Sopenharmony_ci assert_alive(paint); 1116cb93a386Sopenharmony_ci this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, 1117cb93a386Sopenharmony_ci GrStyledShape(rrect, style, DoSimplify::kNo)); 1118cb93a386Sopenharmony_ci} 1119cb93a386Sopenharmony_ci 1120cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1121cb93a386Sopenharmony_ci 1122cb93a386Sopenharmony_cibool SurfaceDrawContext::drawFastShadow(const GrClip* clip, 1123cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1124cb93a386Sopenharmony_ci const SkPath& path, 1125cb93a386Sopenharmony_ci const SkDrawShadowRec& rec) { 1126cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1127cb93a386Sopenharmony_ci if (fContext->abandoned()) { 1128cb93a386Sopenharmony_ci return true; 1129cb93a386Sopenharmony_ci } 1130cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1131cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawFastShadow", fContext); 1132cb93a386Sopenharmony_ci 1133cb93a386Sopenharmony_ci // check z plane 1134cb93a386Sopenharmony_ci bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) || 1135cb93a386Sopenharmony_ci !SkScalarNearlyZero(rec.fZPlaneParams.fY)); 1136cb93a386Sopenharmony_ci bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag); 1137cb93a386Sopenharmony_ci if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) { 1138cb93a386Sopenharmony_ci return false; 1139cb93a386Sopenharmony_ci } 1140cb93a386Sopenharmony_ci 1141cb93a386Sopenharmony_ci SkRRect rrect; 1142cb93a386Sopenharmony_ci SkRect rect; 1143cb93a386Sopenharmony_ci // we can only handle rects, circles, and simple rrects with circular corners 1144cb93a386Sopenharmony_ci bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsNearlySimpleCircular(rrect) && 1145cb93a386Sopenharmony_ci rrect.getSimpleRadii().fX > SK_ScalarNearlyZero; 1146cb93a386Sopenharmony_ci if (!isRRect && 1147cb93a386Sopenharmony_ci path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) && 1148cb93a386Sopenharmony_ci rect.width() > SK_ScalarNearlyZero) { 1149cb93a386Sopenharmony_ci rrect.setOval(rect); 1150cb93a386Sopenharmony_ci isRRect = true; 1151cb93a386Sopenharmony_ci } 1152cb93a386Sopenharmony_ci if (!isRRect && path.isRect(&rect)) { 1153cb93a386Sopenharmony_ci rrect.setRect(rect); 1154cb93a386Sopenharmony_ci isRRect = true; 1155cb93a386Sopenharmony_ci } 1156cb93a386Sopenharmony_ci 1157cb93a386Sopenharmony_ci if (!isRRect) { 1158cb93a386Sopenharmony_ci return false; 1159cb93a386Sopenharmony_ci } 1160cb93a386Sopenharmony_ci 1161cb93a386Sopenharmony_ci if (rrect.isEmpty()) { 1162cb93a386Sopenharmony_ci return true; 1163cb93a386Sopenharmony_ci } 1164cb93a386Sopenharmony_ci 1165cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 1166cb93a386Sopenharmony_ci 1167cb93a386Sopenharmony_ci SkPoint3 devLightPos = rec.fLightPos; 1168cb93a386Sopenharmony_ci bool directional = SkToBool(rec.fFlags & kDirectionalLight_ShadowFlag); 1169cb93a386Sopenharmony_ci if (!directional) { 1170cb93a386Sopenharmony_ci // transform light 1171cb93a386Sopenharmony_ci viewMatrix.mapPoints((SkPoint*)&devLightPos.fX, 1); 1172cb93a386Sopenharmony_ci } 1173cb93a386Sopenharmony_ci 1174cb93a386Sopenharmony_ci // 1/scale 1175cb93a386Sopenharmony_ci SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ? 1176cb93a386Sopenharmony_ci SkScalarInvert(SkScalarAbs(viewMatrix[SkMatrix::kMScaleX])) : 1177cb93a386Sopenharmony_ci sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] + 1178cb93a386Sopenharmony_ci viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]); 1179cb93a386Sopenharmony_ci 1180cb93a386Sopenharmony_ci SkScalar occluderHeight = rec.fZPlaneParams.fZ; 1181cb93a386Sopenharmony_ci bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag); 1182cb93a386Sopenharmony_ci 1183cb93a386Sopenharmony_ci if (SkColorGetA(rec.fAmbientColor) > 0) { 1184cb93a386Sopenharmony_ci SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight); 1185cb93a386Sopenharmony_ci const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight); 1186cb93a386Sopenharmony_ci const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha; 1187cb93a386Sopenharmony_ci 1188cb93a386Sopenharmony_ci // Outset the shadow rrect to the border of the penumbra 1189cb93a386Sopenharmony_ci SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale; 1190cb93a386Sopenharmony_ci SkRRect ambientRRect; 1191cb93a386Sopenharmony_ci SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset); 1192cb93a386Sopenharmony_ci // If the rrect was an oval then its outset will also be one. 1193cb93a386Sopenharmony_ci // We set it explicitly to avoid errors. 1194cb93a386Sopenharmony_ci if (rrect.isOval()) { 1195cb93a386Sopenharmony_ci ambientRRect = SkRRect::MakeOval(outsetRect); 1196cb93a386Sopenharmony_ci } else { 1197cb93a386Sopenharmony_ci SkScalar outsetRad = SkRRectPriv::GetSimpleRadii(rrect).fX + ambientPathOutset; 1198cb93a386Sopenharmony_ci ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad); 1199cb93a386Sopenharmony_ci } 1200cb93a386Sopenharmony_ci 1201cb93a386Sopenharmony_ci GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor); 1202cb93a386Sopenharmony_ci if (transparent) { 1203cb93a386Sopenharmony_ci // set a large inset to force a fill 1204cb93a386Sopenharmony_ci devSpaceInsetWidth = ambientRRect.width(); 1205cb93a386Sopenharmony_ci } 1206cb93a386Sopenharmony_ci 1207cb93a386Sopenharmony_ci GrOp::Owner op = ShadowRRectOp::Make(fContext, 1208cb93a386Sopenharmony_ci ambientColor, 1209cb93a386Sopenharmony_ci viewMatrix, 1210cb93a386Sopenharmony_ci ambientRRect, 1211cb93a386Sopenharmony_ci devSpaceAmbientBlur, 1212cb93a386Sopenharmony_ci devSpaceInsetWidth); 1213cb93a386Sopenharmony_ci if (op) { 1214cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1215cb93a386Sopenharmony_ci } 1216cb93a386Sopenharmony_ci } 1217cb93a386Sopenharmony_ci 1218cb93a386Sopenharmony_ci if (SkColorGetA(rec.fSpotColor) > 0) { 1219cb93a386Sopenharmony_ci SkScalar devSpaceSpotBlur; 1220cb93a386Sopenharmony_ci SkScalar spotScale; 1221cb93a386Sopenharmony_ci SkVector spotOffset; 1222cb93a386Sopenharmony_ci if (directional) { 1223cb93a386Sopenharmony_ci SkDrawShadowMetrics::GetDirectionalParams(occluderHeight, devLightPos.fX, 1224cb93a386Sopenharmony_ci devLightPos.fY, devLightPos.fZ, 1225cb93a386Sopenharmony_ci rec.fLightRadius, &devSpaceSpotBlur, 1226cb93a386Sopenharmony_ci &spotScale, &spotOffset); 1227cb93a386Sopenharmony_ci } else { 1228cb93a386Sopenharmony_ci SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY, 1229cb93a386Sopenharmony_ci devLightPos.fZ, rec.fLightRadius, 1230cb93a386Sopenharmony_ci &devSpaceSpotBlur, &spotScale, &spotOffset, rec.isLimitElevation); 1231cb93a386Sopenharmony_ci } 1232cb93a386Sopenharmony_ci // handle scale of radius due to CTM 1233cb93a386Sopenharmony_ci const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale; 1234cb93a386Sopenharmony_ci 1235cb93a386Sopenharmony_ci // Adjust translate for the effect of the scale. 1236cb93a386Sopenharmony_ci spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX]; 1237cb93a386Sopenharmony_ci spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY]; 1238cb93a386Sopenharmony_ci // This offset is in dev space, need to transform it into source space. 1239cb93a386Sopenharmony_ci SkMatrix ctmInverse; 1240cb93a386Sopenharmony_ci if (viewMatrix.invert(&ctmInverse)) { 1241cb93a386Sopenharmony_ci ctmInverse.mapPoints(&spotOffset, 1); 1242cb93a386Sopenharmony_ci } else { 1243cb93a386Sopenharmony_ci // Since the matrix is a similarity, this should never happen, but just in case... 1244cb93a386Sopenharmony_ci SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n"); 1245cb93a386Sopenharmony_ci SkASSERT(false); 1246cb93a386Sopenharmony_ci } 1247cb93a386Sopenharmony_ci 1248cb93a386Sopenharmony_ci // Compute the transformed shadow rrect 1249cb93a386Sopenharmony_ci SkRRect spotShadowRRect; 1250cb93a386Sopenharmony_ci SkMatrix shadowTransform; 1251cb93a386Sopenharmony_ci shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY); 1252cb93a386Sopenharmony_ci rrect.transform(shadowTransform, &spotShadowRRect); 1253cb93a386Sopenharmony_ci SkScalar spotRadius = spotShadowRRect.getSimpleRadii().fX; 1254cb93a386Sopenharmony_ci 1255cb93a386Sopenharmony_ci // Compute the insetWidth 1256cb93a386Sopenharmony_ci SkScalar blurOutset = srcSpaceSpotBlur; 1257cb93a386Sopenharmony_ci SkScalar insetWidth = blurOutset; 1258cb93a386Sopenharmony_ci if (transparent) { 1259cb93a386Sopenharmony_ci // If transparent, just do a fill 1260cb93a386Sopenharmony_ci insetWidth += spotShadowRRect.width(); 1261cb93a386Sopenharmony_ci } else { 1262cb93a386Sopenharmony_ci // For shadows, instead of using a stroke we specify an inset from the penumbra 1263cb93a386Sopenharmony_ci // border. We want to extend this inset area so that it meets up with the caster 1264cb93a386Sopenharmony_ci // geometry. The inset geometry will by default already be inset by the blur width. 1265cb93a386Sopenharmony_ci // 1266cb93a386Sopenharmony_ci // We compare the min and max corners inset by the radius between the original 1267cb93a386Sopenharmony_ci // rrect and the shadow rrect. The distance between the two plus the difference 1268cb93a386Sopenharmony_ci // between the scaled radius and the original radius gives the distance from the 1269cb93a386Sopenharmony_ci // transformed shadow shape to the original shape in that corner. The max 1270cb93a386Sopenharmony_ci // of these gives the maximum distance we need to cover. 1271cb93a386Sopenharmony_ci // 1272cb93a386Sopenharmony_ci // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to 1273cb93a386Sopenharmony_ci // that to get the full insetWidth. 1274cb93a386Sopenharmony_ci SkScalar maxOffset; 1275cb93a386Sopenharmony_ci if (rrect.isRect()) { 1276cb93a386Sopenharmony_ci // Manhattan distance works better for rects 1277cb93a386Sopenharmony_ci maxOffset = std::max(std::max(SkTAbs(spotShadowRRect.rect().fLeft - 1278cb93a386Sopenharmony_ci rrect.rect().fLeft), 1279cb93a386Sopenharmony_ci SkTAbs(spotShadowRRect.rect().fTop - 1280cb93a386Sopenharmony_ci rrect.rect().fTop)), 1281cb93a386Sopenharmony_ci std::max(SkTAbs(spotShadowRRect.rect().fRight - 1282cb93a386Sopenharmony_ci rrect.rect().fRight), 1283cb93a386Sopenharmony_ci SkTAbs(spotShadowRRect.rect().fBottom - 1284cb93a386Sopenharmony_ci rrect.rect().fBottom))); 1285cb93a386Sopenharmony_ci } else { 1286cb93a386Sopenharmony_ci SkScalar dr = spotRadius - SkRRectPriv::GetSimpleRadii(rrect).fX; 1287cb93a386Sopenharmony_ci SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft - 1288cb93a386Sopenharmony_ci rrect.rect().fLeft + dr, 1289cb93a386Sopenharmony_ci spotShadowRRect.rect().fTop - 1290cb93a386Sopenharmony_ci rrect.rect().fTop + dr); 1291cb93a386Sopenharmony_ci SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight - 1292cb93a386Sopenharmony_ci rrect.rect().fRight - dr, 1293cb93a386Sopenharmony_ci spotShadowRRect.rect().fBottom - 1294cb93a386Sopenharmony_ci rrect.rect().fBottom - dr); 1295cb93a386Sopenharmony_ci maxOffset = SkScalarSqrt(std::max(SkPointPriv::LengthSqd(upperLeftOffset), 1296cb93a386Sopenharmony_ci SkPointPriv::LengthSqd(lowerRightOffset))) + dr; 1297cb93a386Sopenharmony_ci } 1298cb93a386Sopenharmony_ci insetWidth += std::max(blurOutset, maxOffset); 1299cb93a386Sopenharmony_ci } 1300cb93a386Sopenharmony_ci 1301cb93a386Sopenharmony_ci // Outset the shadow rrect to the border of the penumbra 1302cb93a386Sopenharmony_ci SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset); 1303cb93a386Sopenharmony_ci if (spotShadowRRect.isOval()) { 1304cb93a386Sopenharmony_ci spotShadowRRect = SkRRect::MakeOval(outsetRect); 1305cb93a386Sopenharmony_ci } else { 1306cb93a386Sopenharmony_ci SkScalar outsetRad = spotRadius + blurOutset; 1307cb93a386Sopenharmony_ci spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad); 1308cb93a386Sopenharmony_ci } 1309cb93a386Sopenharmony_ci 1310cb93a386Sopenharmony_ci GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor); 1311cb93a386Sopenharmony_ci 1312cb93a386Sopenharmony_ci GrOp::Owner op = ShadowRRectOp::Make(fContext, 1313cb93a386Sopenharmony_ci spotColor, 1314cb93a386Sopenharmony_ci viewMatrix, 1315cb93a386Sopenharmony_ci spotShadowRRect, 1316cb93a386Sopenharmony_ci 2.0f * devSpaceSpotBlur, 1317cb93a386Sopenharmony_ci insetWidth); 1318cb93a386Sopenharmony_ci if (op) { 1319cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1320cb93a386Sopenharmony_ci } 1321cb93a386Sopenharmony_ci } 1322cb93a386Sopenharmony_ci 1323cb93a386Sopenharmony_ci return true; 1324cb93a386Sopenharmony_ci} 1325cb93a386Sopenharmony_ci 1326cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1327cb93a386Sopenharmony_ci 1328cb93a386Sopenharmony_civoid SurfaceDrawContext::drawRegion(const GrClip* clip, 1329cb93a386Sopenharmony_ci GrPaint&& paint, 1330cb93a386Sopenharmony_ci GrAA aa, 1331cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1332cb93a386Sopenharmony_ci const SkRegion& region, 1333cb93a386Sopenharmony_ci const GrStyle& style, 1334cb93a386Sopenharmony_ci const GrUserStencilSettings* ss) { 1335cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1336cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 1337cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1338cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawRegion", fContext); 1339cb93a386Sopenharmony_ci 1340cb93a386Sopenharmony_ci if (GrAA::kYes == aa) { 1341cb93a386Sopenharmony_ci // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix 1342cb93a386Sopenharmony_ci // to see whether aa is really required. 1343cb93a386Sopenharmony_ci if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) && 1344cb93a386Sopenharmony_ci SkScalarIsInt(viewMatrix.getTranslateX()) && 1345cb93a386Sopenharmony_ci SkScalarIsInt(viewMatrix.getTranslateY())) { 1346cb93a386Sopenharmony_ci aa = GrAA::kNo; 1347cb93a386Sopenharmony_ci } 1348cb93a386Sopenharmony_ci } 1349cb93a386Sopenharmony_ci bool complexStyle = !style.isSimpleFill(); 1350cb93a386Sopenharmony_ci if (complexStyle || GrAA::kYes == aa) { 1351cb93a386Sopenharmony_ci SkPath path; 1352cb93a386Sopenharmony_ci region.getBoundaryPath(&path); 1353cb93a386Sopenharmony_ci path.setIsVolatile(true); 1354cb93a386Sopenharmony_ci 1355cb93a386Sopenharmony_ci return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style); 1356cb93a386Sopenharmony_ci } 1357cb93a386Sopenharmony_ci 1358cb93a386Sopenharmony_ci GrAAType aaType = (this->numSamples() > 1) ? GrAAType::kMSAA : GrAAType::kNone; 1359cb93a386Sopenharmony_ci GrOp::Owner op = RegionOp::Make(fContext, std::move(paint), viewMatrix, region, aaType, ss); 1360cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1361cb93a386Sopenharmony_ci} 1362cb93a386Sopenharmony_ci 1363cb93a386Sopenharmony_civoid SurfaceDrawContext::drawOval(const GrClip* clip, 1364cb93a386Sopenharmony_ci GrPaint&& paint, 1365cb93a386Sopenharmony_ci GrAA aa, 1366cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1367cb93a386Sopenharmony_ci const SkRect& oval, 1368cb93a386Sopenharmony_ci const GrStyle& style) { 1369cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1370cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 1371cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1372cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawOval", fContext); 1373cb93a386Sopenharmony_ci 1374cb93a386Sopenharmony_ci const SkStrokeRec& stroke = style.strokeRec(); 1375cb93a386Sopenharmony_ci 1376cb93a386Sopenharmony_ci if (oval.isEmpty() && !style.pathEffect()) { 1377cb93a386Sopenharmony_ci if (stroke.getStyle() == SkStrokeRec::kFill_Style) { 1378cb93a386Sopenharmony_ci return; 1379cb93a386Sopenharmony_ci } 1380cb93a386Sopenharmony_ci 1381cb93a386Sopenharmony_ci this->drawRect(clip, std::move(paint), aa, viewMatrix, oval, &style); 1382cb93a386Sopenharmony_ci return; 1383cb93a386Sopenharmony_ci } 1384cb93a386Sopenharmony_ci 1385cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 1386cb93a386Sopenharmony_ci 1387cb93a386Sopenharmony_ci GrAAType aaType = this->chooseAAType(aa); 1388cb93a386Sopenharmony_ci 1389cb93a386Sopenharmony_ci GrOp::Owner op; 1390cb93a386Sopenharmony_ci if (aaType == GrAAType::kCoverage && 1391cb93a386Sopenharmony_ci !fCanUseDynamicMSAA && 1392cb93a386Sopenharmony_ci !this->caps()->reducedShaderMode() && 1393cb93a386Sopenharmony_ci oval.width() > SK_ScalarNearlyZero && 1394cb93a386Sopenharmony_ci oval.width() == oval.height() && 1395cb93a386Sopenharmony_ci viewMatrix.isSimilarity()) { 1396cb93a386Sopenharmony_ci // In specific cases we use a dedicated circle op to try and get better perf. 1397cb93a386Sopenharmony_ci assert_alive(paint); 1398cb93a386Sopenharmony_ci op = GrOvalOpFactory::MakeCircleOp(fContext, std::move(paint), viewMatrix, oval, style, 1399cb93a386Sopenharmony_ci this->caps()->shaderCaps()); 1400cb93a386Sopenharmony_ci } 1401cb93a386Sopenharmony_ci if (!op && style.isSimpleFill()) { 1402cb93a386Sopenharmony_ci // FillRRectOp has special geometry and a fragment-shader branch to conditionally evaluate 1403cb93a386Sopenharmony_ci // the arc equation. This same special geometry and fragment branch also turn out to be a 1404cb93a386Sopenharmony_ci // substantial optimization for drawing ovals (namely, by not evaluating the arc equation 1405cb93a386Sopenharmony_ci // inside the oval's inner diamond). Given these optimizations, it's a clear win to draw 1406cb93a386Sopenharmony_ci // ovals the exact same way we do round rects. 1407cb93a386Sopenharmony_ci assert_alive(paint); 1408cb93a386Sopenharmony_ci op = FillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint), viewMatrix, 1409cb93a386Sopenharmony_ci SkRRect::MakeOval(oval), oval, GrAA(aaType != GrAAType::kNone)); 1410cb93a386Sopenharmony_ci } 1411cb93a386Sopenharmony_ci if (!op && (aaType == GrAAType::kCoverage || fCanUseDynamicMSAA)) { 1412cb93a386Sopenharmony_ci assert_alive(paint); 1413cb93a386Sopenharmony_ci op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval, style, 1414cb93a386Sopenharmony_ci this->caps()->shaderCaps()); 1415cb93a386Sopenharmony_ci } 1416cb93a386Sopenharmony_ci if (op) { 1417cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1418cb93a386Sopenharmony_ci return; 1419cb93a386Sopenharmony_ci } 1420cb93a386Sopenharmony_ci 1421cb93a386Sopenharmony_ci assert_alive(paint); 1422cb93a386Sopenharmony_ci this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, 1423cb93a386Sopenharmony_ci GrStyledShape(SkRRect::MakeOval(oval), SkPathDirection::kCW, 2, 1424cb93a386Sopenharmony_ci false, style, DoSimplify::kNo)); 1425cb93a386Sopenharmony_ci} 1426cb93a386Sopenharmony_ci 1427cb93a386Sopenharmony_civoid SurfaceDrawContext::drawArc(const GrClip* clip, 1428cb93a386Sopenharmony_ci GrPaint&& paint, 1429cb93a386Sopenharmony_ci GrAA aa, 1430cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1431cb93a386Sopenharmony_ci const SkRect& oval, 1432cb93a386Sopenharmony_ci SkScalar startAngle, 1433cb93a386Sopenharmony_ci SkScalar sweepAngle, 1434cb93a386Sopenharmony_ci bool useCenter, 1435cb93a386Sopenharmony_ci const GrStyle& style) { 1436cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1437cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 1438cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1439cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawArc", fContext); 1440cb93a386Sopenharmony_ci 1441cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 1442cb93a386Sopenharmony_ci 1443cb93a386Sopenharmony_ci GrAAType aaType = this->chooseAAType(aa); 1444cb93a386Sopenharmony_ci if (aaType == GrAAType::kCoverage) { 1445cb93a386Sopenharmony_ci const GrShaderCaps* shaderCaps = this->caps()->shaderCaps(); 1446cb93a386Sopenharmony_ci GrOp::Owner op = GrOvalOpFactory::MakeArcOp(fContext, 1447cb93a386Sopenharmony_ci std::move(paint), 1448cb93a386Sopenharmony_ci viewMatrix, 1449cb93a386Sopenharmony_ci oval, 1450cb93a386Sopenharmony_ci startAngle, 1451cb93a386Sopenharmony_ci sweepAngle, 1452cb93a386Sopenharmony_ci useCenter, 1453cb93a386Sopenharmony_ci style, 1454cb93a386Sopenharmony_ci shaderCaps); 1455cb93a386Sopenharmony_ci if (op) { 1456cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1457cb93a386Sopenharmony_ci return; 1458cb93a386Sopenharmony_ci } 1459cb93a386Sopenharmony_ci assert_alive(paint); 1460cb93a386Sopenharmony_ci } 1461cb93a386Sopenharmony_ci this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, 1462cb93a386Sopenharmony_ci GrStyledShape::MakeArc(oval, startAngle, sweepAngle, useCenter, 1463cb93a386Sopenharmony_ci style, DoSimplify::kNo)); 1464cb93a386Sopenharmony_ci} 1465cb93a386Sopenharmony_ci 1466cb93a386Sopenharmony_civoid SurfaceDrawContext::drawImageLattice(const GrClip* clip, 1467cb93a386Sopenharmony_ci GrPaint&& paint, 1468cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1469cb93a386Sopenharmony_ci GrSurfaceProxyView view, 1470cb93a386Sopenharmony_ci SkAlphaType alphaType, 1471cb93a386Sopenharmony_ci sk_sp<GrColorSpaceXform> csxf, 1472cb93a386Sopenharmony_ci GrSamplerState::Filter filter, 1473cb93a386Sopenharmony_ci std::unique_ptr<SkLatticeIter> iter, 1474cb93a386Sopenharmony_ci const SkRect& dst) { 1475cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1476cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 1477cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1478cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawImageLattice", fContext); 1479cb93a386Sopenharmony_ci 1480cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 1481cb93a386Sopenharmony_ci 1482cb93a386Sopenharmony_ci GrOp::Owner op = 1483cb93a386Sopenharmony_ci LatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(view), 1484cb93a386Sopenharmony_ci alphaType, std::move(csxf), filter, std::move(iter), dst); 1485cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1486cb93a386Sopenharmony_ci} 1487cb93a386Sopenharmony_ci 1488cb93a386Sopenharmony_civoid SurfaceDrawContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable, 1489cb93a386Sopenharmony_ci const SkRect& bounds) { 1490cb93a386Sopenharmony_ci GrOp::Owner op(DrawableOp::Make(fContext, std::move(drawable), bounds)); 1491cb93a386Sopenharmony_ci SkASSERT(op); 1492cb93a386Sopenharmony_ci this->addOp(std::move(op)); 1493cb93a386Sopenharmony_ci} 1494cb93a386Sopenharmony_ci 1495cb93a386Sopenharmony_civoid SurfaceDrawContext::setLastClip(uint32_t clipStackGenID, 1496cb93a386Sopenharmony_ci const SkIRect& devClipBounds, 1497cb93a386Sopenharmony_ci int numClipAnalyticElements) { 1498cb93a386Sopenharmony_ci auto opsTask = this->getOpsTask(); 1499cb93a386Sopenharmony_ci opsTask->fLastClipStackGenID = clipStackGenID; 1500cb93a386Sopenharmony_ci opsTask->fLastDevClipBounds = devClipBounds; 1501cb93a386Sopenharmony_ci opsTask->fLastClipNumAnalyticElements = numClipAnalyticElements; 1502cb93a386Sopenharmony_ci} 1503cb93a386Sopenharmony_ci 1504cb93a386Sopenharmony_cibool SurfaceDrawContext::mustRenderClip(uint32_t clipStackGenID, 1505cb93a386Sopenharmony_ci const SkIRect& devClipBounds, 1506cb93a386Sopenharmony_ci int numClipAnalyticElements) { 1507cb93a386Sopenharmony_ci auto opsTask = this->getOpsTask(); 1508cb93a386Sopenharmony_ci return opsTask->fLastClipStackGenID != clipStackGenID || 1509cb93a386Sopenharmony_ci !opsTask->fLastDevClipBounds.contains(devClipBounds) || 1510cb93a386Sopenharmony_ci opsTask->fLastClipNumAnalyticElements != numClipAnalyticElements; 1511cb93a386Sopenharmony_ci} 1512cb93a386Sopenharmony_ci 1513cb93a386Sopenharmony_cibool SurfaceDrawContext::waitOnSemaphores(int numSemaphores, 1514cb93a386Sopenharmony_ci const GrBackendSemaphore waitSemaphores[], 1515cb93a386Sopenharmony_ci bool deleteSemaphoresAfterWait) { 1516cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1517cb93a386Sopenharmony_ci RETURN_FALSE_IF_ABANDONED 1518cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1519cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "waitOnSemaphores", fContext); 1520cb93a386Sopenharmony_ci 1521cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 1522cb93a386Sopenharmony_ci 1523cb93a386Sopenharmony_ci if (numSemaphores && !this->caps()->semaphoreSupport()) { 1524cb93a386Sopenharmony_ci return false; 1525cb93a386Sopenharmony_ci } 1526cb93a386Sopenharmony_ci 1527cb93a386Sopenharmony_ci auto direct = fContext->asDirectContext(); 1528cb93a386Sopenharmony_ci if (!direct) { 1529cb93a386Sopenharmony_ci return false; 1530cb93a386Sopenharmony_ci } 1531cb93a386Sopenharmony_ci 1532cb93a386Sopenharmony_ci auto resourceProvider = direct->priv().resourceProvider(); 1533cb93a386Sopenharmony_ci 1534cb93a386Sopenharmony_ci GrWrapOwnership ownership = 1535cb93a386Sopenharmony_ci deleteSemaphoresAfterWait ? kAdopt_GrWrapOwnership : kBorrow_GrWrapOwnership; 1536cb93a386Sopenharmony_ci 1537cb93a386Sopenharmony_ci std::unique_ptr<std::unique_ptr<GrSemaphore>[]> grSemaphores( 1538cb93a386Sopenharmony_ci new std::unique_ptr<GrSemaphore>[numSemaphores]); 1539cb93a386Sopenharmony_ci for (int i = 0; i < numSemaphores; ++i) { 1540cb93a386Sopenharmony_ci grSemaphores[i] = resourceProvider->wrapBackendSemaphore(waitSemaphores[i], 1541cb93a386Sopenharmony_ci GrSemaphoreWrapType::kWillWait, 1542cb93a386Sopenharmony_ci ownership); 1543cb93a386Sopenharmony_ci } 1544cb93a386Sopenharmony_ci this->drawingManager()->newWaitRenderTask(this->asSurfaceProxyRef(), std::move(grSemaphores), 1545cb93a386Sopenharmony_ci numSemaphores); 1546cb93a386Sopenharmony_ci return true; 1547cb93a386Sopenharmony_ci} 1548cb93a386Sopenharmony_ci 1549cb93a386Sopenharmony_civoid SurfaceDrawContext::drawPath(const GrClip* clip, 1550cb93a386Sopenharmony_ci GrPaint&& paint, 1551cb93a386Sopenharmony_ci GrAA aa, 1552cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1553cb93a386Sopenharmony_ci const SkPath& path, 1554cb93a386Sopenharmony_ci const GrStyle& style) { 1555cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1556cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 1557cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1558cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawPath", fContext); 1559cb93a386Sopenharmony_ci 1560cb93a386Sopenharmony_ci GrStyledShape shape(path, style, DoSimplify::kNo); 1561cb93a386Sopenharmony_ci this->drawShape(clip, std::move(paint), aa, viewMatrix, std::move(shape)); 1562cb93a386Sopenharmony_ci} 1563cb93a386Sopenharmony_ci 1564cb93a386Sopenharmony_civoid SurfaceDrawContext::drawShape(const GrClip* clip, 1565cb93a386Sopenharmony_ci GrPaint&& paint, 1566cb93a386Sopenharmony_ci GrAA aa, 1567cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1568cb93a386Sopenharmony_ci GrStyledShape&& shape) { 1569cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1570cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 1571cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1572cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawShape", fContext); 1573cb93a386Sopenharmony_ci 1574cb93a386Sopenharmony_ci if (shape.isEmpty()) { 1575cb93a386Sopenharmony_ci if (shape.inverseFilled()) { 1576cb93a386Sopenharmony_ci this->drawPaint(clip, std::move(paint), viewMatrix); 1577cb93a386Sopenharmony_ci } 1578cb93a386Sopenharmony_ci return; 1579cb93a386Sopenharmony_ci } 1580cb93a386Sopenharmony_ci 1581cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 1582cb93a386Sopenharmony_ci 1583cb93a386Sopenharmony_ci // If we get here in drawShape(), we definitely need to use path rendering 1584cb93a386Sopenharmony_ci this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, std::move(shape), 1585cb93a386Sopenharmony_ci /* attemptDrawSimple */ true); 1586cb93a386Sopenharmony_ci} 1587cb93a386Sopenharmony_ci 1588cb93a386Sopenharmony_cistatic SkIRect get_clip_bounds(const SurfaceDrawContext* sdc, const GrClip* clip) { 1589cb93a386Sopenharmony_ci return clip ? clip->getConservativeBounds() : SkIRect::MakeWH(sdc->width(), sdc->height()); 1590cb93a386Sopenharmony_ci} 1591cb93a386Sopenharmony_ci 1592cb93a386Sopenharmony_cibool SurfaceDrawContext::drawAndStencilPath(const GrHardClip* clip, 1593cb93a386Sopenharmony_ci const GrUserStencilSettings* ss, 1594cb93a386Sopenharmony_ci SkRegion::Op op, 1595cb93a386Sopenharmony_ci bool invert, 1596cb93a386Sopenharmony_ci GrAA aa, 1597cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1598cb93a386Sopenharmony_ci const SkPath& path) { 1599cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1600cb93a386Sopenharmony_ci RETURN_FALSE_IF_ABANDONED 1601cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1602cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawAndStencilPath", fContext); 1603cb93a386Sopenharmony_ci 1604cb93a386Sopenharmony_ci if (path.isEmpty() && path.isInverseFillType()) { 1605cb93a386Sopenharmony_ci GrPaint paint; 1606cb93a386Sopenharmony_ci paint.setCoverageSetOpXPFactory(op, invert); 1607cb93a386Sopenharmony_ci this->stencilRect(clip, ss, std::move(paint), GrAA::kNo, SkMatrix::I(), 1608cb93a386Sopenharmony_ci SkRect::Make(this->dimensions())); 1609cb93a386Sopenharmony_ci return true; 1610cb93a386Sopenharmony_ci } 1611cb93a386Sopenharmony_ci 1612cb93a386Sopenharmony_ci AutoCheckFlush acf(this->drawingManager()); 1613cb93a386Sopenharmony_ci 1614cb93a386Sopenharmony_ci // An Assumption here is that path renderer would use some form of tweaking 1615cb93a386Sopenharmony_ci // the src color (either the input alpha or in the frag shader) to implement 1616cb93a386Sopenharmony_ci // aa. If we have some future driver-mojo path AA that can do the right 1617cb93a386Sopenharmony_ci // thing WRT to the blend then we'll need some query on the PR. 1618cb93a386Sopenharmony_ci GrAAType aaType = this->chooseAAType(aa); 1619cb93a386Sopenharmony_ci bool hasUserStencilSettings = !ss->isUnused(); 1620cb93a386Sopenharmony_ci 1621cb93a386Sopenharmony_ci SkIRect clipConservativeBounds = get_clip_bounds(this, clip); 1622cb93a386Sopenharmony_ci 1623cb93a386Sopenharmony_ci GrPaint paint; 1624cb93a386Sopenharmony_ci paint.setCoverageSetOpXPFactory(op, invert); 1625cb93a386Sopenharmony_ci 1626cb93a386Sopenharmony_ci GrStyledShape shape(path, GrStyle::SimpleFill()); 1627cb93a386Sopenharmony_ci PathRenderer::CanDrawPathArgs canDrawArgs; 1628cb93a386Sopenharmony_ci canDrawArgs.fCaps = this->caps(); 1629cb93a386Sopenharmony_ci canDrawArgs.fProxy = this->asRenderTargetProxy(); 1630cb93a386Sopenharmony_ci canDrawArgs.fViewMatrix = &viewMatrix; 1631cb93a386Sopenharmony_ci canDrawArgs.fShape = &shape; 1632cb93a386Sopenharmony_ci canDrawArgs.fPaint = &paint; 1633cb93a386Sopenharmony_ci canDrawArgs.fSurfaceProps = &fSurfaceProps; 1634cb93a386Sopenharmony_ci canDrawArgs.fClipConservativeBounds = &clipConservativeBounds; 1635cb93a386Sopenharmony_ci canDrawArgs.fAAType = aaType; 1636cb93a386Sopenharmony_ci canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings; 1637cb93a386Sopenharmony_ci 1638cb93a386Sopenharmony_ci using DrawType = PathRendererChain::DrawType; 1639cb93a386Sopenharmony_ci 1640cb93a386Sopenharmony_ci // Don't allow the SW renderer 1641cb93a386Sopenharmony_ci auto pr = this->drawingManager()->getPathRenderer(canDrawArgs, 1642cb93a386Sopenharmony_ci false, 1643cb93a386Sopenharmony_ci DrawType::kStencilAndColor); 1644cb93a386Sopenharmony_ci if (!pr) { 1645cb93a386Sopenharmony_ci return false; 1646cb93a386Sopenharmony_ci } 1647cb93a386Sopenharmony_ci 1648cb93a386Sopenharmony_ci PathRenderer::DrawPathArgs args{this->drawingManager()->getContext(), 1649cb93a386Sopenharmony_ci std::move(paint), 1650cb93a386Sopenharmony_ci ss, 1651cb93a386Sopenharmony_ci this, 1652cb93a386Sopenharmony_ci clip, 1653cb93a386Sopenharmony_ci &clipConservativeBounds, 1654cb93a386Sopenharmony_ci &viewMatrix, 1655cb93a386Sopenharmony_ci &shape, 1656cb93a386Sopenharmony_ci aaType, 1657cb93a386Sopenharmony_ci this->colorInfo().isLinearlyBlended()}; 1658cb93a386Sopenharmony_ci pr->drawPath(args); 1659cb93a386Sopenharmony_ci return true; 1660cb93a386Sopenharmony_ci} 1661cb93a386Sopenharmony_ci 1662cb93a386Sopenharmony_ciSkBudgeted SurfaceDrawContext::isBudgeted() const { 1663cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1664cb93a386Sopenharmony_ci 1665cb93a386Sopenharmony_ci if (fContext->abandoned()) { 1666cb93a386Sopenharmony_ci return SkBudgeted::kNo; 1667cb93a386Sopenharmony_ci } 1668cb93a386Sopenharmony_ci 1669cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1670cb93a386Sopenharmony_ci 1671cb93a386Sopenharmony_ci return this->asSurfaceProxy()->isBudgeted(); 1672cb93a386Sopenharmony_ci} 1673cb93a386Sopenharmony_ci 1674cb93a386Sopenharmony_civoid SurfaceDrawContext::drawStrokedLine(const GrClip* clip, 1675cb93a386Sopenharmony_ci GrPaint&& paint, 1676cb93a386Sopenharmony_ci GrAA aa, 1677cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1678cb93a386Sopenharmony_ci const SkPoint points[2], 1679cb93a386Sopenharmony_ci const SkStrokeRec& stroke) { 1680cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1681cb93a386Sopenharmony_ci 1682cb93a386Sopenharmony_ci SkASSERT(stroke.getStyle() == SkStrokeRec::kStroke_Style); 1683cb93a386Sopenharmony_ci SkASSERT(stroke.getWidth() > 0); 1684cb93a386Sopenharmony_ci // Adding support for round capping would require a 1685cb93a386Sopenharmony_ci // SurfaceDrawContext::fillRRectWithLocalMatrix entry point 1686cb93a386Sopenharmony_ci SkASSERT(SkPaint::kRound_Cap != stroke.getCap()); 1687cb93a386Sopenharmony_ci 1688cb93a386Sopenharmony_ci const SkScalar halfWidth = 0.5f * stroke.getWidth(); 1689cb93a386Sopenharmony_ci if (halfWidth <= 0.f) { 1690cb93a386Sopenharmony_ci // Prevents underflow when stroke width is epsilon > 0 (so technically not a hairline). 1691cb93a386Sopenharmony_ci // The CTM would need to have a scale near 1/epsilon in order for this to have meaningful 1692cb93a386Sopenharmony_ci // coverage (although that would likely overflow elsewhere and cause the draw to drop due 1693cb93a386Sopenharmony_ci // to non-finite bounds). At any other scale, this line is so thin, it's coverage is 1694cb93a386Sopenharmony_ci // negligible, so discarding the draw is visually equivalent. 1695cb93a386Sopenharmony_ci return; 1696cb93a386Sopenharmony_ci } 1697cb93a386Sopenharmony_ci 1698cb93a386Sopenharmony_ci SkVector parallel = points[1] - points[0]; 1699cb93a386Sopenharmony_ci 1700cb93a386Sopenharmony_ci if (!SkPoint::Normalize(¶llel)) { 1701cb93a386Sopenharmony_ci parallel.fX = 1.0f; 1702cb93a386Sopenharmony_ci parallel.fY = 0.0f; 1703cb93a386Sopenharmony_ci } 1704cb93a386Sopenharmony_ci parallel *= halfWidth; 1705cb93a386Sopenharmony_ci 1706cb93a386Sopenharmony_ci SkVector ortho = { parallel.fY, -parallel.fX }; 1707cb93a386Sopenharmony_ci if (SkPaint::kButt_Cap == stroke.getCap()) { 1708cb93a386Sopenharmony_ci // No extra extension for butt caps 1709cb93a386Sopenharmony_ci parallel = {0.f, 0.f}; 1710cb93a386Sopenharmony_ci } 1711cb93a386Sopenharmony_ci // Order is TL, TR, BR, BL where arbitrarily "down" is p0 to p1 and "right" is positive 1712cb93a386Sopenharmony_ci SkPoint corners[4] = { points[0] - ortho - parallel, 1713cb93a386Sopenharmony_ci points[0] + ortho - parallel, 1714cb93a386Sopenharmony_ci points[1] + ortho + parallel, 1715cb93a386Sopenharmony_ci points[1] - ortho + parallel }; 1716cb93a386Sopenharmony_ci 1717cb93a386Sopenharmony_ci GrQuadAAFlags edgeAA = (aa == GrAA::kYes) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone; 1718cb93a386Sopenharmony_ci this->fillQuadWithEdgeAA(clip, std::move(paint), aa, edgeAA, viewMatrix, corners, nullptr); 1719cb93a386Sopenharmony_ci} 1720cb93a386Sopenharmony_ci 1721cb93a386Sopenharmony_cibool SurfaceDrawContext::drawSimpleShape(const GrClip* clip, 1722cb93a386Sopenharmony_ci GrPaint* paint, 1723cb93a386Sopenharmony_ci GrAA aa, 1724cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1725cb93a386Sopenharmony_ci const GrStyledShape& shape) { 1726cb93a386Sopenharmony_ci if (!shape.style().hasPathEffect()) { 1727cb93a386Sopenharmony_ci GrAAType aaType = this->chooseAAType(aa); 1728cb93a386Sopenharmony_ci SkPoint linePts[2]; 1729cb93a386Sopenharmony_ci SkRRect rrect; 1730cb93a386Sopenharmony_ci // We can ignore the starting point and direction since there is no path effect. 1731cb93a386Sopenharmony_ci bool inverted; 1732cb93a386Sopenharmony_ci if (shape.asLine(linePts, &inverted) && !inverted && 1733cb93a386Sopenharmony_ci shape.style().strokeRec().getStyle() == SkStrokeRec::kStroke_Style && 1734cb93a386Sopenharmony_ci shape.style().strokeRec().getCap() != SkPaint::kRound_Cap) { 1735cb93a386Sopenharmony_ci // The stroked line is an oriented rectangle, which looks the same or better (if 1736cb93a386Sopenharmony_ci // perspective) compared to path rendering. The exception is subpixel/hairline lines 1737cb93a386Sopenharmony_ci // that are non-AA or MSAA, in which case the default path renderer achieves higher 1738cb93a386Sopenharmony_ci // quality. 1739cb93a386Sopenharmony_ci // FIXME(michaelludwig): If the fill rect op could take an external coverage, or checks 1740cb93a386Sopenharmony_ci // for and outsets thin non-aa rects to 1px, the path renderer could be skipped. 1741cb93a386Sopenharmony_ci SkScalar coverage; 1742cb93a386Sopenharmony_ci if (aaType == GrAAType::kCoverage || 1743cb93a386Sopenharmony_ci !SkDrawTreatAAStrokeAsHairline(shape.style().strokeRec().getWidth(), viewMatrix, 1744cb93a386Sopenharmony_ci &coverage)) { 1745cb93a386Sopenharmony_ci this->drawStrokedLine(clip, std::move(*paint), aa, viewMatrix, linePts, 1746cb93a386Sopenharmony_ci shape.style().strokeRec()); 1747cb93a386Sopenharmony_ci return true; 1748cb93a386Sopenharmony_ci } 1749cb93a386Sopenharmony_ci } else if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) { 1750cb93a386Sopenharmony_ci if (rrect.isRect()) { 1751cb93a386Sopenharmony_ci this->drawRect(clip, std::move(*paint), aa, viewMatrix, rrect.rect(), 1752cb93a386Sopenharmony_ci &shape.style()); 1753cb93a386Sopenharmony_ci return true; 1754cb93a386Sopenharmony_ci } else if (rrect.isOval()) { 1755cb93a386Sopenharmony_ci this->drawOval(clip, std::move(*paint), aa, viewMatrix, rrect.rect(), 1756cb93a386Sopenharmony_ci shape.style()); 1757cb93a386Sopenharmony_ci return true; 1758cb93a386Sopenharmony_ci } 1759cb93a386Sopenharmony_ci this->drawRRect(clip, std::move(*paint), aa, viewMatrix, rrect, shape.style()); 1760cb93a386Sopenharmony_ci return true; 1761cb93a386Sopenharmony_ci } else if (GrAAType::kCoverage == aaType && 1762cb93a386Sopenharmony_ci shape.style().isSimpleFill() && 1763cb93a386Sopenharmony_ci viewMatrix.rectStaysRect() && 1764cb93a386Sopenharmony_ci !this->caps()->reducedShaderMode()) { 1765cb93a386Sopenharmony_ci // TODO: the rectStaysRect restriction could be lifted if we were willing to apply the 1766cb93a386Sopenharmony_ci // matrix to all the points individually rather than just to the rect 1767cb93a386Sopenharmony_ci SkRect rects[2]; 1768cb93a386Sopenharmony_ci if (shape.asNestedRects(rects)) { 1769cb93a386Sopenharmony_ci // Concave AA paths are expensive - try to avoid them for special cases 1770cb93a386Sopenharmony_ci GrOp::Owner op = StrokeRectOp::MakeNested(fContext, std::move(*paint), 1771cb93a386Sopenharmony_ci viewMatrix, rects); 1772cb93a386Sopenharmony_ci if (op) { 1773cb93a386Sopenharmony_ci this->addDrawOp(clip, std::move(op)); 1774cb93a386Sopenharmony_ci return true; 1775cb93a386Sopenharmony_ci } 1776cb93a386Sopenharmony_ci // Fall through to let path renderer handle subpixel nested rects with unequal 1777cb93a386Sopenharmony_ci // stroke widths along X/Y. 1778cb93a386Sopenharmony_ci } 1779cb93a386Sopenharmony_ci } 1780cb93a386Sopenharmony_ci } 1781cb93a386Sopenharmony_ci return false; 1782cb93a386Sopenharmony_ci} 1783cb93a386Sopenharmony_ci 1784cb93a386Sopenharmony_civoid SurfaceDrawContext::drawShapeUsingPathRenderer(const GrClip* clip, 1785cb93a386Sopenharmony_ci GrPaint&& paint, 1786cb93a386Sopenharmony_ci GrAA aa, 1787cb93a386Sopenharmony_ci const SkMatrix& viewMatrix, 1788cb93a386Sopenharmony_ci GrStyledShape&& shape, 1789cb93a386Sopenharmony_ci bool attemptDrawSimple) { 1790cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1791cb93a386Sopenharmony_ci RETURN_IF_ABANDONED 1792cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "internalDrawPath", fContext); 1793cb93a386Sopenharmony_ci 1794cb93a386Sopenharmony_ci if (!viewMatrix.isFinite() || !shape.bounds().isFinite()) { 1795cb93a386Sopenharmony_ci return; 1796cb93a386Sopenharmony_ci } 1797cb93a386Sopenharmony_ci 1798cb93a386Sopenharmony_ci SkIRect clipConservativeBounds = get_clip_bounds(this, clip); 1799cb93a386Sopenharmony_ci 1800cb93a386Sopenharmony_ci // Always allow paths to trigger DMSAA. 1801cb93a386Sopenharmony_ci GrAAType aaType = fCanUseDynamicMSAA ? GrAAType::kMSAA : this->chooseAAType(aa); 1802cb93a386Sopenharmony_ci 1803cb93a386Sopenharmony_ci PathRenderer::CanDrawPathArgs canDrawArgs; 1804cb93a386Sopenharmony_ci canDrawArgs.fCaps = this->caps(); 1805cb93a386Sopenharmony_ci canDrawArgs.fProxy = this->asRenderTargetProxy(); 1806cb93a386Sopenharmony_ci canDrawArgs.fViewMatrix = &viewMatrix; 1807cb93a386Sopenharmony_ci canDrawArgs.fShape = &shape; 1808cb93a386Sopenharmony_ci canDrawArgs.fPaint = &paint; 1809cb93a386Sopenharmony_ci canDrawArgs.fSurfaceProps = &fSurfaceProps; 1810cb93a386Sopenharmony_ci canDrawArgs.fClipConservativeBounds = &clipConservativeBounds; 1811cb93a386Sopenharmony_ci canDrawArgs.fHasUserStencilSettings = false; 1812cb93a386Sopenharmony_ci canDrawArgs.fAAType = aaType; 1813cb93a386Sopenharmony_ci 1814cb93a386Sopenharmony_ci constexpr static bool kDisallowSWPathRenderer = false; 1815cb93a386Sopenharmony_ci constexpr static bool kAllowSWPathRenderer = true; 1816cb93a386Sopenharmony_ci using DrawType = PathRendererChain::DrawType; 1817cb93a386Sopenharmony_ci 1818cb93a386Sopenharmony_ci PathRenderer* pr = nullptr; 1819cb93a386Sopenharmony_ci 1820cb93a386Sopenharmony_ci if (!shape.style().strokeRec().isFillStyle() && !shape.isEmpty()) { 1821cb93a386Sopenharmony_ci // Give the tessellation path renderer a chance to claim this stroke before we simplify it. 1822cb93a386Sopenharmony_ci PathRenderer* tess = this->drawingManager()->getTessellationPathRenderer(); 1823cb93a386Sopenharmony_ci if (tess && tess->canDrawPath(canDrawArgs) == PathRenderer::CanDrawPath::kYes) { 1824cb93a386Sopenharmony_ci pr = tess; 1825cb93a386Sopenharmony_ci } 1826cb93a386Sopenharmony_ci } 1827cb93a386Sopenharmony_ci 1828cb93a386Sopenharmony_ci if (!pr) { 1829cb93a386Sopenharmony_ci // The shape isn't a stroke that can be drawn directly. Simplify if possible. 1830cb93a386Sopenharmony_ci shape.simplify(); 1831cb93a386Sopenharmony_ci 1832cb93a386Sopenharmony_ci if (shape.isEmpty() && !shape.inverseFilled()) { 1833cb93a386Sopenharmony_ci return; 1834cb93a386Sopenharmony_ci } 1835cb93a386Sopenharmony_ci 1836cb93a386Sopenharmony_ci if (attemptDrawSimple || shape.simplified()) { 1837cb93a386Sopenharmony_ci // Usually we enter drawShapeUsingPathRenderer() because the shape+style was too complex 1838cb93a386Sopenharmony_ci // for dedicated draw ops. However, if GrStyledShape was able to reduce something we 1839cb93a386Sopenharmony_ci // ought to try again instead of going right to path rendering. 1840cb93a386Sopenharmony_ci if (this->drawSimpleShape(clip, &paint, aa, viewMatrix, shape)) { 1841cb93a386Sopenharmony_ci return; 1842cb93a386Sopenharmony_ci } 1843cb93a386Sopenharmony_ci } 1844cb93a386Sopenharmony_ci 1845cb93a386Sopenharmony_ci // Try a 1st time without applying any of the style to the geometry (and barring sw) 1846cb93a386Sopenharmony_ci pr = this->drawingManager()->getPathRenderer(canDrawArgs, kDisallowSWPathRenderer, 1847cb93a386Sopenharmony_ci DrawType::kColor); 1848cb93a386Sopenharmony_ci } 1849cb93a386Sopenharmony_ci 1850cb93a386Sopenharmony_ci SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix); 1851cb93a386Sopenharmony_ci if (styleScale == 0.0f) { 1852cb93a386Sopenharmony_ci return; 1853cb93a386Sopenharmony_ci } 1854cb93a386Sopenharmony_ci 1855cb93a386Sopenharmony_ci if (!pr && shape.style().pathEffect()) { 1856cb93a386Sopenharmony_ci // It didn't work above, so try again with the path effect applied. 1857cb93a386Sopenharmony_ci shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale); 1858cb93a386Sopenharmony_ci if (shape.isEmpty()) { 1859cb93a386Sopenharmony_ci return; 1860cb93a386Sopenharmony_ci } 1861cb93a386Sopenharmony_ci pr = this->drawingManager()->getPathRenderer(canDrawArgs, kDisallowSWPathRenderer, 1862cb93a386Sopenharmony_ci DrawType::kColor); 1863cb93a386Sopenharmony_ci } 1864cb93a386Sopenharmony_ci if (!pr) { 1865cb93a386Sopenharmony_ci if (shape.style().applies()) { 1866cb93a386Sopenharmony_ci shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale); 1867cb93a386Sopenharmony_ci if (shape.isEmpty()) { 1868cb93a386Sopenharmony_ci return; 1869cb93a386Sopenharmony_ci } 1870cb93a386Sopenharmony_ci // This time, allow SW renderer 1871cb93a386Sopenharmony_ci pr = this->drawingManager()->getPathRenderer(canDrawArgs, kAllowSWPathRenderer, 1872cb93a386Sopenharmony_ci DrawType::kColor); 1873cb93a386Sopenharmony_ci } else { 1874cb93a386Sopenharmony_ci pr = this->drawingManager()->getSoftwarePathRenderer(); 1875cb93a386Sopenharmony_ci#if GR_PATH_RENDERER_SPEW 1876cb93a386Sopenharmony_ci SkDebugf("falling back to: %s\n", pr->name()); 1877cb93a386Sopenharmony_ci#endif 1878cb93a386Sopenharmony_ci } 1879cb93a386Sopenharmony_ci } 1880cb93a386Sopenharmony_ci 1881cb93a386Sopenharmony_ci if (!pr) { 1882cb93a386Sopenharmony_ci#ifdef SK_DEBUG 1883cb93a386Sopenharmony_ci SkDebugf("Unable to find path renderer compatible with path.\n"); 1884cb93a386Sopenharmony_ci#endif 1885cb93a386Sopenharmony_ci return; 1886cb93a386Sopenharmony_ci } 1887cb93a386Sopenharmony_ci 1888cb93a386Sopenharmony_ci PathRenderer::DrawPathArgs args{this->drawingManager()->getContext(), 1889cb93a386Sopenharmony_ci std::move(paint), 1890cb93a386Sopenharmony_ci &GrUserStencilSettings::kUnused, 1891cb93a386Sopenharmony_ci this, 1892cb93a386Sopenharmony_ci clip, 1893cb93a386Sopenharmony_ci &clipConservativeBounds, 1894cb93a386Sopenharmony_ci &viewMatrix, 1895cb93a386Sopenharmony_ci canDrawArgs.fShape, 1896cb93a386Sopenharmony_ci aaType, 1897cb93a386Sopenharmony_ci this->colorInfo().isLinearlyBlended()}; 1898cb93a386Sopenharmony_ci pr->drawPath(args); 1899cb93a386Sopenharmony_ci} 1900cb93a386Sopenharmony_ci 1901cb93a386Sopenharmony_civoid SurfaceDrawContext::addDrawOp(const GrClip* clip, 1902cb93a386Sopenharmony_ci GrOp::Owner op, 1903cb93a386Sopenharmony_ci const std::function<WillAddOpFn>& willAddFn) { 1904cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1905cb93a386Sopenharmony_ci if (fContext->abandoned()) { 1906cb93a386Sopenharmony_ci return; 1907cb93a386Sopenharmony_ci } 1908cb93a386Sopenharmony_ci GrDrawOp* drawOp = (GrDrawOp*)op.get(); 1909cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 1910cb93a386Sopenharmony_ci SkDEBUGCODE(drawOp->fAddDrawOpCalled = true;) 1911cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "addDrawOp", fContext); 1912cb93a386Sopenharmony_ci 1913cb93a386Sopenharmony_ci // Setup clip 1914cb93a386Sopenharmony_ci SkRect bounds; 1915cb93a386Sopenharmony_ci op_bounds(&bounds, op.get()); 1916cb93a386Sopenharmony_ci GrAppliedClip appliedClip(this->dimensions(), this->asSurfaceProxy()->backingStoreDimensions()); 1917cb93a386Sopenharmony_ci const bool opUsesMSAA = drawOp->usesMSAA(); 1918cb93a386Sopenharmony_ci bool skipDraw = false; 1919cb93a386Sopenharmony_ci if (clip) { 1920cb93a386Sopenharmony_ci // Have a complex clip, so defer to its early clip culling 1921cb93a386Sopenharmony_ci GrAAType aaType; 1922cb93a386Sopenharmony_ci if (opUsesMSAA) { 1923cb93a386Sopenharmony_ci aaType = GrAAType::kMSAA; 1924cb93a386Sopenharmony_ci } else { 1925cb93a386Sopenharmony_ci aaType = op->hasAABloat() ? GrAAType::kCoverage : GrAAType::kNone; 1926cb93a386Sopenharmony_ci } 1927cb93a386Sopenharmony_ci skipDraw = clip->apply(fContext, this, drawOp, aaType, 1928cb93a386Sopenharmony_ci &appliedClip, &bounds) == GrClip::Effect::kClippedOut; 1929cb93a386Sopenharmony_ci } else { 1930cb93a386Sopenharmony_ci // No clipping, so just clip the bounds against the logical render target dimensions 1931cb93a386Sopenharmony_ci skipDraw = !bounds.intersect(this->asSurfaceProxy()->getBoundsRect()); 1932cb93a386Sopenharmony_ci } 1933cb93a386Sopenharmony_ci 1934cb93a386Sopenharmony_ci if (skipDraw) { 1935cb93a386Sopenharmony_ci return; 1936cb93a386Sopenharmony_ci } 1937cb93a386Sopenharmony_ci 1938cb93a386Sopenharmony_ci GrClampType clampType = GrColorTypeClampType(this->colorInfo().colorType()); 1939cb93a386Sopenharmony_ci GrProcessorSet::Analysis analysis = drawOp->finalize(*this->caps(), &appliedClip, clampType); 1940cb93a386Sopenharmony_ci 1941cb93a386Sopenharmony_ci const bool opUsesStencil = drawOp->usesStencil(); 1942cb93a386Sopenharmony_ci 1943cb93a386Sopenharmony_ci // Always trigger DMSAA when there is stencil. This ensures stencil contents get properly 1944cb93a386Sopenharmony_ci // preserved between render passes, if needed. 1945cb93a386Sopenharmony_ci const bool drawNeedsMSAA = opUsesMSAA || (fCanUseDynamicMSAA && opUsesStencil); 1946cb93a386Sopenharmony_ci 1947cb93a386Sopenharmony_ci // Must be called before setDstProxyView so that it sees the final bounds of the op. 1948cb93a386Sopenharmony_ci op->setClippedBounds(bounds); 1949cb93a386Sopenharmony_ci 1950cb93a386Sopenharmony_ci // Determine if the Op will trigger the use of a separate DMSAA attachment that requires manual 1951cb93a386Sopenharmony_ci // resolves. 1952cb93a386Sopenharmony_ci // TODO: Currently usesAttachmentIfDMSAA checks if this is a textureProxy or not. This check is 1953cb93a386Sopenharmony_ci // really only for GL which uses a normal texture sampling when using barriers. For Vulkan it 1954cb93a386Sopenharmony_ci // is possible to use the msaa buffer as an input attachment even if this is not a texture. 1955cb93a386Sopenharmony_ci // However, support for that is not fully implemented yet in Vulkan. Once it is, this check 1956cb93a386Sopenharmony_ci // should change to a virtual caps check that returns whether we need to break up an OpsTask 1957cb93a386Sopenharmony_ci // if it has barriers and we are about to promote to MSAA. 1958cb93a386Sopenharmony_ci bool usesAttachmentIfDMSAA = 1959cb93a386Sopenharmony_ci fCanUseDynamicMSAA && 1960cb93a386Sopenharmony_ci (!this->caps()->msaaResolvesAutomatically() || !this->asTextureProxy()); 1961cb93a386Sopenharmony_ci bool opRequiresDMSAAAttachment = usesAttachmentIfDMSAA && drawNeedsMSAA; 1962cb93a386Sopenharmony_ci bool opTriggersDMSAAAttachment = 1963cb93a386Sopenharmony_ci opRequiresDMSAAAttachment && !this->getOpsTask()->usesMSAASurface(); 1964cb93a386Sopenharmony_ci if (opTriggersDMSAAAttachment) { 1965cb93a386Sopenharmony_ci // This will be the op that actually triggers use of a DMSAA attachment. Texture barriers 1966cb93a386Sopenharmony_ci // can't be moved to a DMSAA attachment, so if there already are any on the current opsTask 1967cb93a386Sopenharmony_ci // then we need to split. 1968cb93a386Sopenharmony_ci if (this->getOpsTask()->renderPassXferBarriers() & GrXferBarrierFlags::kTexture) { 1969cb93a386Sopenharmony_ci SkASSERT(!this->getOpsTask()->isColorNoOp()); 1970cb93a386Sopenharmony_ci this->replaceOpsTask()->setCannotMergeBackward(); 1971cb93a386Sopenharmony_ci } 1972cb93a386Sopenharmony_ci } 1973cb93a386Sopenharmony_ci 1974cb93a386Sopenharmony_ci GrDstProxyView dstProxyView; 1975cb93a386Sopenharmony_ci if (analysis.requiresDstTexture()) { 1976cb93a386Sopenharmony_ci if (!this->setupDstProxyView(drawOp->bounds(), drawNeedsMSAA, &dstProxyView)) { 1977cb93a386Sopenharmony_ci return; 1978cb93a386Sopenharmony_ci } 1979cb93a386Sopenharmony_ci#ifdef SK_DEBUG 1980cb93a386Sopenharmony_ci if (fCanUseDynamicMSAA && drawNeedsMSAA && !this->caps()->msaaResolvesAutomatically()) { 1981cb93a386Sopenharmony_ci // Since we aren't literally writing to the render target texture while using a DMSAA 1982cb93a386Sopenharmony_ci // attachment, we need to resolve that texture before sampling it. Ensure the current 1983cb93a386Sopenharmony_ci // opsTask got closed off in order to initiate an implicit resolve. 1984cb93a386Sopenharmony_ci SkASSERT(this->getOpsTask()->isEmpty()); 1985cb93a386Sopenharmony_ci } 1986cb93a386Sopenharmony_ci#endif 1987cb93a386Sopenharmony_ci } 1988cb93a386Sopenharmony_ci 1989cb93a386Sopenharmony_ci auto opsTask = this->getOpsTask(); 1990cb93a386Sopenharmony_ci if (willAddFn) { 1991cb93a386Sopenharmony_ci willAddFn(op.get(), opsTask->uniqueID()); 1992cb93a386Sopenharmony_ci } 1993cb93a386Sopenharmony_ci 1994cb93a386Sopenharmony_ci // Note if the op needs stencil. Stencil clipping already called setNeedsStencil for itself, if 1995cb93a386Sopenharmony_ci // needed. 1996cb93a386Sopenharmony_ci if (opUsesStencil) { 1997cb93a386Sopenharmony_ci this->setNeedsStencil(); 1998cb93a386Sopenharmony_ci } 1999cb93a386Sopenharmony_ci 2000cb93a386Sopenharmony_ci#if GR_GPU_STATS && GR_TEST_UTILS 2001cb93a386Sopenharmony_ci if (fCanUseDynamicMSAA && drawNeedsMSAA) { 2002cb93a386Sopenharmony_ci if (!opsTask->usesMSAASurface()) { 2003cb93a386Sopenharmony_ci fContext->priv().dmsaaStats().fNumMultisampleRenderPasses++; 2004cb93a386Sopenharmony_ci } 2005cb93a386Sopenharmony_ci fContext->priv().dmsaaStats().fTriggerCounts[op->name()]++; 2006cb93a386Sopenharmony_ci } 2007cb93a386Sopenharmony_ci#endif 2008cb93a386Sopenharmony_ci auto direct = fContext->priv().asDirectContext(); 2009cb93a386Sopenharmony_ci if (direct && op) { 2010cb93a386Sopenharmony_ci op->setGrOpTag(direct->getCurrentGrResourceTag()); 2011cb93a386Sopenharmony_ci } 2012cb93a386Sopenharmony_ci opsTask->addDrawOp(this->drawingManager(), std::move(op), drawNeedsMSAA, analysis, 2013cb93a386Sopenharmony_ci std::move(appliedClip), dstProxyView, 2014cb93a386Sopenharmony_ci GrTextureResolveManager(this->drawingManager()), *this->caps()); 2015cb93a386Sopenharmony_ci 2016cb93a386Sopenharmony_ci#ifdef SK_DEBUG 2017cb93a386Sopenharmony_ci if (fCanUseDynamicMSAA && drawNeedsMSAA) { 2018cb93a386Sopenharmony_ci SkASSERT(opsTask->usesMSAASurface()); 2019cb93a386Sopenharmony_ci } 2020cb93a386Sopenharmony_ci#endif 2021cb93a386Sopenharmony_ci} 2022cb93a386Sopenharmony_ci 2023cb93a386Sopenharmony_cibool SurfaceDrawContext::setupDstProxyView(const SkRect& opBounds, 2024cb93a386Sopenharmony_ci bool opRequiresMSAA, 2025cb93a386Sopenharmony_ci GrDstProxyView* dstProxyView) { 2026cb93a386Sopenharmony_ci // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we 2027cb93a386Sopenharmony_ci // don't actually have a VkImage to make a copy of. Additionally we don't have the power to 2028cb93a386Sopenharmony_ci // start and stop the render pass in order to make the copy. 2029cb93a386Sopenharmony_ci if (this->asRenderTargetProxy()->wrapsVkSecondaryCB()) { 2030cb93a386Sopenharmony_ci return false; 2031cb93a386Sopenharmony_ci } 2032cb93a386Sopenharmony_ci 2033cb93a386Sopenharmony_ci // First get the dstSampleFlags as if we will put the draw into the current OpsTask 2034cb93a386Sopenharmony_ci auto dstSampleFlags = this->caps()->getDstSampleFlagsForProxy( 2035cb93a386Sopenharmony_ci this->asRenderTargetProxy(), this->getOpsTask()->usesMSAASurface() || opRequiresMSAA); 2036cb93a386Sopenharmony_ci 2037cb93a386Sopenharmony_ci // If we don't have barriers for this draw then we will definitely be breaking up the OpsTask. 2038cb93a386Sopenharmony_ci // However, if using dynamic MSAA, the new OpsTask will not have MSAA already enabled on it 2039cb93a386Sopenharmony_ci // and that may allow us to use texture barriers. So we check if we can use barriers on the new 2040cb93a386Sopenharmony_ci // ops task and then break it up if so. 2041cb93a386Sopenharmony_ci if (!(dstSampleFlags & GrDstSampleFlags::kRequiresTextureBarrier) && 2042cb93a386Sopenharmony_ci fCanUseDynamicMSAA && this->getOpsTask()->usesMSAASurface() && !opRequiresMSAA) { 2043cb93a386Sopenharmony_ci auto newFlags = 2044cb93a386Sopenharmony_ci this->caps()->getDstSampleFlagsForProxy(this->asRenderTargetProxy(), 2045cb93a386Sopenharmony_ci false/*=opRequiresMSAA*/); 2046cb93a386Sopenharmony_ci if (newFlags & GrDstSampleFlags::kRequiresTextureBarrier) { 2047cb93a386Sopenharmony_ci // We can't have an empty ops task if we are in DMSAA and the ops task already returns 2048cb93a386Sopenharmony_ci // true for usesMSAASurface. 2049cb93a386Sopenharmony_ci SkASSERT(!this->getOpsTask()->isColorNoOp()); 2050cb93a386Sopenharmony_ci this->replaceOpsTask()->setCannotMergeBackward(); 2051cb93a386Sopenharmony_ci dstSampleFlags = newFlags; 2052cb93a386Sopenharmony_ci } 2053cb93a386Sopenharmony_ci } 2054cb93a386Sopenharmony_ci 2055cb93a386Sopenharmony_ci if (dstSampleFlags & GrDstSampleFlags::kRequiresTextureBarrier) { 2056cb93a386Sopenharmony_ci // If we require a barrier to sample the dst it means we are sampling the RT itself 2057cb93a386Sopenharmony_ci // either as a texture or input attachment. In this case we don't need to break up the 2058cb93a386Sopenharmony_ci // OpsTask. 2059cb93a386Sopenharmony_ci dstProxyView->setProxyView(this->readSurfaceView()); 2060cb93a386Sopenharmony_ci dstProxyView->setOffset(0, 0); 2061cb93a386Sopenharmony_ci dstProxyView->setDstSampleFlags(dstSampleFlags); 2062cb93a386Sopenharmony_ci return true; 2063cb93a386Sopenharmony_ci } 2064cb93a386Sopenharmony_ci SkASSERT(dstSampleFlags == GrDstSampleFlags::kNone); 2065cb93a386Sopenharmony_ci 2066cb93a386Sopenharmony_ci // We are using a different surface from the main color attachment to sample the dst from. If we 2067cb93a386Sopenharmony_ci // are in DMSAA we can just use the single sampled RT texture itself. Otherwise, we must do a 2068cb93a386Sopenharmony_ci // copy. 2069cb93a386Sopenharmony_ci // We do have to check if we ended up here becasue we don't have texture barriers but do have 2070cb93a386Sopenharmony_ci // msaaResolvesAutomatically (i.e. render-to-msaa-texture). In that case there will be no op or 2071cb93a386Sopenharmony_ci // barrier between draws to flush the render target before being used as a texture in the next 2072cb93a386Sopenharmony_ci // draw. So in that case we just fall through to doing a copy. 2073cb93a386Sopenharmony_ci if (fCanUseDynamicMSAA && opRequiresMSAA && this->asTextureProxy() && 2074cb93a386Sopenharmony_ci !this->caps()->msaaResolvesAutomatically() && 2075cb93a386Sopenharmony_ci this->caps()->dmsaaResolveCanBeUsedAsTextureInSameRenderPass()) { 2076cb93a386Sopenharmony_ci this->replaceOpsTaskIfModifiesColor()->setCannotMergeBackward(); 2077cb93a386Sopenharmony_ci dstProxyView->setProxyView(this->readSurfaceView()); 2078cb93a386Sopenharmony_ci dstProxyView->setOffset(0, 0); 2079cb93a386Sopenharmony_ci dstProxyView->setDstSampleFlags(dstSampleFlags); 2080cb93a386Sopenharmony_ci return true; 2081cb93a386Sopenharmony_ci } 2082cb93a386Sopenharmony_ci 2083cb93a386Sopenharmony_ci // Now we fallback to doing a copy. 2084cb93a386Sopenharmony_ci 2085cb93a386Sopenharmony_ci GrColorType colorType = this->colorInfo().colorType(); 2086cb93a386Sopenharmony_ci // MSAA consideration: When there is support for reading MSAA samples in the shader we could 2087cb93a386Sopenharmony_ci // have per-sample dst values by making the copy multisampled. 2088cb93a386Sopenharmony_ci GrCaps::DstCopyRestrictions restrictions = this->caps()->getDstCopyRestrictions( 2089cb93a386Sopenharmony_ci this->asRenderTargetProxy(), colorType); 2090cb93a386Sopenharmony_ci 2091cb93a386Sopenharmony_ci SkIRect copyRect = SkIRect::MakeSize(this->asSurfaceProxy()->backingStoreDimensions()); 2092cb93a386Sopenharmony_ci if (!restrictions.fMustCopyWholeSrc) { 2093cb93a386Sopenharmony_ci // If we don't need the whole source, restrict to the op's bounds. We add an extra pixel 2094cb93a386Sopenharmony_ci // of padding to account for AA bloat and the unpredictable rounding of coords near pixel 2095cb93a386Sopenharmony_ci // centers during rasterization. 2096cb93a386Sopenharmony_ci SkIRect conservativeDrawBounds = opBounds.roundOut(); 2097cb93a386Sopenharmony_ci conservativeDrawBounds.outset(1, 1); 2098cb93a386Sopenharmony_ci SkAssertResult(copyRect.intersect(conservativeDrawBounds)); 2099cb93a386Sopenharmony_ci } 2100cb93a386Sopenharmony_ci 2101cb93a386Sopenharmony_ci SkIPoint dstOffset; 2102cb93a386Sopenharmony_ci SkBackingFit fit; 2103cb93a386Sopenharmony_ci if (restrictions.fRectsMustMatch == GrSurfaceProxy::RectsMustMatch::kYes) { 2104cb93a386Sopenharmony_ci dstOffset = {0, 0}; 2105cb93a386Sopenharmony_ci fit = SkBackingFit::kExact; 2106cb93a386Sopenharmony_ci } else { 2107cb93a386Sopenharmony_ci dstOffset = {copyRect.fLeft, copyRect.fTop}; 2108cb93a386Sopenharmony_ci fit = SkBackingFit::kApprox; 2109cb93a386Sopenharmony_ci } 2110cb93a386Sopenharmony_ci auto copy = GrSurfaceProxy::Copy(fContext, 2111cb93a386Sopenharmony_ci this->asSurfaceProxyRef(), 2112cb93a386Sopenharmony_ci this->origin(), 2113cb93a386Sopenharmony_ci GrMipmapped::kNo, 2114cb93a386Sopenharmony_ci copyRect, 2115cb93a386Sopenharmony_ci fit, 2116cb93a386Sopenharmony_ci SkBudgeted::kYes, 2117cb93a386Sopenharmony_ci restrictions.fRectsMustMatch); 2118cb93a386Sopenharmony_ci SkASSERT(copy); 2119cb93a386Sopenharmony_ci 2120cb93a386Sopenharmony_ci dstProxyView->setProxyView({std::move(copy), this->origin(), this->readSwizzle()}); 2121cb93a386Sopenharmony_ci dstProxyView->setOffset(dstOffset); 2122cb93a386Sopenharmony_ci dstProxyView->setDstSampleFlags(dstSampleFlags); 2123cb93a386Sopenharmony_ci return true; 2124cb93a386Sopenharmony_ci} 2125cb93a386Sopenharmony_ci 2126cb93a386Sopenharmony_ciOpsTask* SurfaceDrawContext::replaceOpsTaskIfModifiesColor() { 2127cb93a386Sopenharmony_ci if (!this->getOpsTask()->isColorNoOp()) { 2128cb93a386Sopenharmony_ci this->replaceOpsTask(); 2129cb93a386Sopenharmony_ci } 2130cb93a386Sopenharmony_ci return this->getOpsTask(); 2131cb93a386Sopenharmony_ci} 2132cb93a386Sopenharmony_ci 2133cb93a386Sopenharmony_cibool SurfaceDrawContext::drawBlurImage(GrSurfaceProxyView proxyView, const SkBlurArg& blurArg) 2134cb93a386Sopenharmony_ci{ 2135cb93a386Sopenharmony_ci if (!this->caps()->supportsHpsBlur(&proxyView)) { 2136cb93a386Sopenharmony_ci SK_LOGD("ERROR: check HpsBlur fail.\n"); 2137cb93a386Sopenharmony_ci return false; 2138cb93a386Sopenharmony_ci } 2139cb93a386Sopenharmony_ci this->addOp(GrOp::Make<BlurOp>(fContext, std::move(proxyView), blurArg)); 2140cb93a386Sopenharmony_ci return true; 2141cb93a386Sopenharmony_ci} 2142cb93a386Sopenharmony_ci 2143cb93a386Sopenharmony_ci} // namespace skgpu::v1 2144