1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC 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 "include/gpu/GrDirectContext.h" 9cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h" 10cb93a386Sopenharmony_ci#include "src/gpu/GrColorSpaceXform.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h" 14cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrQuad.h" 15cb93a386Sopenharmony_ci#include "src/gpu/ops/OpsTask.h" 16cb93a386Sopenharmony_ci#include "src/gpu/ops/TextureOp.h" 17cb93a386Sopenharmony_ci#include "tests/Test.h" 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ciclass OpsTaskTestingAccess { 20cb93a386Sopenharmony_cipublic: 21cb93a386Sopenharmony_ci typedef skgpu::v1::OpsTask::OpChain OpChain; 22cb93a386Sopenharmony_ci}; 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_cistatic void check_chain(OpsTaskTestingAccess::OpChain* chain, SkRect firstRect, SkRect lastRect, 25cb93a386Sopenharmony_ci int expectedNumOps) { 26cb93a386Sopenharmony_ci int actualNumOps = 0; 27cb93a386Sopenharmony_ci for (const auto& op : GrOp::ChainRange<>(chain->head())) { 28cb93a386Sopenharmony_ci ++actualNumOps; 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci if (actualNumOps == 1) { 31cb93a386Sopenharmony_ci SkAssertResult(op.bounds() == firstRect.makeOutset(0.5f, 0.5f)); 32cb93a386Sopenharmony_ci } else if (actualNumOps == expectedNumOps) { 33cb93a386Sopenharmony_ci SkAssertResult(op.bounds() == lastRect.makeOutset(0.5f, 0.5f)); 34cb93a386Sopenharmony_ci } 35cb93a386Sopenharmony_ci } 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ci SkAssertResult(actualNumOps == expectedNumOps); 38cb93a386Sopenharmony_ci} 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_cistatic sk_sp<GrSurfaceProxy> create_proxy(GrRecordingContext* rContext) { 41cb93a386Sopenharmony_ci const GrCaps* caps = rContext->priv().caps(); 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci static constexpr SkISize kDimensions = {16, 16}; 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888, 46cb93a386Sopenharmony_ci GrRenderable::kYes); 47cb93a386Sopenharmony_ci return rContext->priv().proxyProvider()->createProxy( 48cb93a386Sopenharmony_ci format, kDimensions, GrRenderable::kYes, 1, GrMipmapped::kNo, SkBackingFit::kExact, 49cb93a386Sopenharmony_ci SkBudgeted::kNo, GrProtected::kNo, GrInternalSurfaceFlags::kNone); 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_cistatic GrOp::Owner create_op(GrDirectContext* dContext, SkRect rect, 53cb93a386Sopenharmony_ci const GrSurfaceProxyView& proxyView, bool isAA) { 54cb93a386Sopenharmony_ci DrawQuad quad; 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci quad.fDevice = GrQuad::MakeFromRect(rect.makeOutset(0.5f, 0.5f), SkMatrix::I()); 57cb93a386Sopenharmony_ci quad.fLocal = GrQuad(rect); 58cb93a386Sopenharmony_ci quad.fEdgeFlags = isAA ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone; 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci return skgpu::v1::TextureOp::Make(dContext, 61cb93a386Sopenharmony_ci proxyView, 62cb93a386Sopenharmony_ci kPremul_SkAlphaType, 63cb93a386Sopenharmony_ci nullptr, 64cb93a386Sopenharmony_ci GrSamplerState::Filter::kNearest, 65cb93a386Sopenharmony_ci GrSamplerState::MipmapMode::kNone, 66cb93a386Sopenharmony_ci {1.f, 1.f, 1.f, 1.f}, 67cb93a386Sopenharmony_ci skgpu::v1::TextureOp::Saturate::kYes, 68cb93a386Sopenharmony_ci SkBlendMode::kSrcOver, 69cb93a386Sopenharmony_ci isAA ? GrAAType::kCoverage 70cb93a386Sopenharmony_ci : GrAAType::kNone, 71cb93a386Sopenharmony_ci &quad, 72cb93a386Sopenharmony_ci nullptr); 73cb93a386Sopenharmony_ci} 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci// This unit test exercises the crbug.com/1112259 case. 76cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(TextureOpTest, reporter, ctxInfo) { 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci GrDirectContext* dContext = ctxInfo.directContext(); 79cb93a386Sopenharmony_ci const GrCaps* caps = dContext->priv().caps(); 80cb93a386Sopenharmony_ci SkArenaAlloc arena{nullptr, 0, 1024}; 81cb93a386Sopenharmony_ci auto auditTrail = dContext->priv().auditTrail(); 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci if (!caps->dynamicStateArrayGeometryProcessorTextureSupport()) { 84cb93a386Sopenharmony_ci // This test requires chaining 85cb93a386Sopenharmony_ci return; 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci GrSurfaceProxyView proxyViewA(create_proxy(dContext), 89cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 90cb93a386Sopenharmony_ci GrSwizzle::RGBA()); 91cb93a386Sopenharmony_ci GrSurfaceProxyView proxyViewB(create_proxy(dContext), 92cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 93cb93a386Sopenharmony_ci GrSwizzle::RGBA()); 94cb93a386Sopenharmony_ci GrSurfaceProxyView proxyViewC(create_proxy(dContext), 95cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 96cb93a386Sopenharmony_ci GrSwizzle::RGBA()); 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci static const SkRect kOpARect{ 0, 0, 16, 16 }; 99cb93a386Sopenharmony_ci static const SkRect kOpBRect{ 32, 0, 48, 16 }; 100cb93a386Sopenharmony_ci static const SkRect kOpCRect{ 0, 32, 16, 48 }; 101cb93a386Sopenharmony_ci static const SkRect kOpDRect{ 32, 32, 48, 48 }; 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci // opA & opB can chain together but can't merge bc they have different proxies 104cb93a386Sopenharmony_ci GrOp::Owner opA = create_op(dContext, kOpARect, proxyViewA, false); 105cb93a386Sopenharmony_ci GrOp::Owner opB = create_op(dContext, kOpBRect, proxyViewB, false); 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci GrAppliedClip noClip = GrAppliedClip::Disabled(); 108cb93a386Sopenharmony_ci OpsTaskTestingAccess::OpChain chain1(std::move(opA), GrProcessorSet::EmptySetAnalysis(), 109cb93a386Sopenharmony_ci &noClip, nullptr); 110cb93a386Sopenharmony_ci chain1.appendOp(std::move(opB), GrProcessorSet::EmptySetAnalysis(), nullptr, &noClip, *caps, 111cb93a386Sopenharmony_ci &arena, dContext->priv().auditTrail()); 112cb93a386Sopenharmony_ci check_chain(&chain1, kOpARect, kOpBRect, 2); 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci // opC & opD can also chain together but can't merge (bc, again, they have different 115cb93a386Sopenharmony_ci // proxies). Note, however, that opA and opD do share a proxy so can be merged if opA's 116cb93a386Sopenharmony_ci // anti-aliasing is upgraded to coverage. 117cb93a386Sopenharmony_ci GrOp::Owner opC = create_op(dContext, kOpCRect, proxyViewC, true); 118cb93a386Sopenharmony_ci GrOp::Owner opD = create_op(dContext, kOpDRect, proxyViewA, true); 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci OpsTaskTestingAccess::OpChain chain2(std::move(opC), GrProcessorSet::EmptySetAnalysis(), 121cb93a386Sopenharmony_ci &noClip, nullptr); 122cb93a386Sopenharmony_ci chain2.appendOp(std::move(opD), GrProcessorSet::EmptySetAnalysis(), nullptr, &noClip, *caps, 123cb93a386Sopenharmony_ci &arena, auditTrail); 124cb93a386Sopenharmony_ci check_chain(&chain2, kOpCRect, kOpDRect, 2); 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci // opA and opD, now in separate chains, can merge when the two chains are combined while 127cb93a386Sopenharmony_ci // opB and opC can still only chain. 128cb93a386Sopenharmony_ci chain1.prependChain(&chain2, *caps, &arena, auditTrail); 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci // We should end up with the chain 131cb93a386Sopenharmony_ci // opC - opD/opA - opB 132cb93a386Sopenharmony_ci check_chain(&chain1, kOpCRect, kOpBRect, 3); 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci chain1.deleteOps(); 135cb93a386Sopenharmony_ci} 136