13c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth/* 22103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth * Copyright 2017 Google Inc. 33c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth * 43c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth * Use of this source code is governed by a BSD-style license that can be 53c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth * found in the LICENSE file. 63c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth */ 73c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 82103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth#include "SkSpotShadowMaskFilter.h" 93c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "SkReadBuffer.h" 103c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "SkStringUtils.h" 113c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "SkWriteBuffer.h" 123c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 133c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#if SK_SUPPORT_GPU 143c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrContext.h" 153c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrRenderTargetContext.h" 163c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrFragmentProcessor.h" 173c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrStyle.h" 183c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "GrTexture.h" 194a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips#include "GrTextureProxy.h" 203c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#include "SkStrokeRec.h" 213c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#endif 223c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 232103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthclass SkSpotShadowMaskFilterImpl : public SkMaskFilter { 243c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthpublic: 252103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkSpotShadowMaskFilterImpl(SkScalar occluderHeight, const SkPoint3& lightPos, 262103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkScalar lightRadius, SkScalar spotAlpha, uint32_t flags); 273c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 283c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // overrides from SkMaskFilter 293c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkMask::Format getFormat() const override; 303c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, 313c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkIPoint* margin) const override; 323c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 333c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#if SK_SUPPORT_GPU 343c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth bool canFilterMaskGPU(const SkRRect& devRRect, 353c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkIRect& clipBounds, 363c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkMatrix& ctm, 373c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkRect* maskRect) const override; 38d3749485db2de966a80e39669a49192fc7c0bd9dRobert Phillips bool directFilterMaskGPU(GrContext*, 393c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth GrRenderTargetContext* drawContext, 4082f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon GrPaint&&, 413c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const GrClip&, 423c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkMatrix& viewMatrix, 433c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkStrokeRec& strokeRec, 443c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkPath& path) const override; 453c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth bool directFilterRRectMaskGPU(GrContext*, 463c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth GrRenderTargetContext* drawContext, 4782f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon GrPaint&&, 483c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const GrClip&, 493c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkMatrix& viewMatrix, 503c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkStrokeRec& strokeRec, 513c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkRRect& rrect, 523c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkRRect& devRRect) const override; 534a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips sk_sp<GrTextureProxy> filterMaskGPU(GrContext*, 544a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips sk_sp<GrTextureProxy> srcProxy, 554a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips const SkMatrix& ctm, 564a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips const SkIRect& maskRect) const override; 573c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#endif 583c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 593c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth void computeFastBounds(const SkRect&, SkRect*) const override; 603c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 613c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SK_TO_STRING_OVERRIDE() 622103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpotShadowMaskFilterImpl) 633c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 643c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verthprivate: 653c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar fOccluderHeight; 663c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkPoint3 fLightPos; 673c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar fLightRadius; 683c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar fSpotAlpha; 693c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth uint32_t fFlags; 703c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 712103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkSpotShadowMaskFilterImpl(SkReadBuffer&); 723c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth void flatten(SkWriteBuffer&) const override; 733c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 742103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth friend class SkSpotShadowMaskFilter; 753c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 763c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth typedef SkMaskFilter INHERITED; 773c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth}; 783c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 792103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthsk_sp<SkMaskFilter> SkSpotShadowMaskFilter::Make(SkScalar occluderHeight, const SkPoint3& lightPos, 802103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkScalar lightRadius, SkScalar spotAlpha, 812103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth uint32_t flags) { 823c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // add some param checks here for early exit 833c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 842103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth return sk_sp<SkMaskFilter>(new SkSpotShadowMaskFilterImpl(occluderHeight, lightPos, 852103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth lightRadius, spotAlpha, flags)); 863c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 873c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 883c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth/////////////////////////////////////////////////////////////////////////////////////////////////// 893c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 902103cf0ff09763aeaa35508734f765aec9b75665Jim Van VerthSkSpotShadowMaskFilterImpl::SkSpotShadowMaskFilterImpl(SkScalar occluderHeight, 912103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkPoint3& lightPos, 922103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkScalar lightRadius, 932103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkScalar spotAlpha, 942103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth uint32_t flags) 953c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth : fOccluderHeight(occluderHeight) 963c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth , fLightPos(lightPos) 973c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth , fLightRadius(lightRadius) 983c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth , fSpotAlpha(spotAlpha) 993c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth , fFlags(flags) { 1003c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkASSERT(fOccluderHeight > 0); 1013c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkASSERT(fLightPos.z() > 0 && fLightPos.z() > fOccluderHeight); 1023c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkASSERT(fLightRadius > 0); 1033c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkASSERT(fSpotAlpha >= 0); 1043c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 1053c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1062103cf0ff09763aeaa35508734f765aec9b75665Jim Van VerthSkMask::Format SkSpotShadowMaskFilterImpl::getFormat() const { 1073c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth return SkMask::kA8_Format; 1083c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 1093c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1102103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthbool SkSpotShadowMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, 1112103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkMatrix& matrix, 1122103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkIPoint* margin) const { 1133c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // TODO something 1143c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth return false; 1153c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 1163c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1172103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthvoid SkSpotShadowMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) const { 1183c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // TODO compute based on ambient + spot data 1193c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth dst->set(src.fLeft, src.fTop, src.fRight, src.fBottom); 1203c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 1213c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1222103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthsk_sp<SkFlattenable> SkSpotShadowMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { 1233c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkScalar occluderHeight = buffer.readScalar(); 1243c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkScalar lightX = buffer.readScalar(); 1253c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkScalar lightY = buffer.readScalar(); 1263c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkScalar lightZ = buffer.readScalar(); 1273c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkPoint3 lightPos = SkPoint3::Make(lightX, lightY, lightZ); 1283c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkScalar lightRadius = buffer.readScalar(); 1293c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkScalar spotAlpha = buffer.readScalar(); 1303c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const uint32_t flags = buffer.readUInt(); 1313c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1322103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth return SkSpotShadowMaskFilter::Make(occluderHeight, lightPos, lightRadius, 1332103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth spotAlpha, flags); 1343c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 1353c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1362103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthvoid SkSpotShadowMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { 1373c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth buffer.writeScalar(fOccluderHeight); 1383c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth buffer.writeScalar(fLightPos.fX); 1393c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth buffer.writeScalar(fLightPos.fY); 1403c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth buffer.writeScalar(fLightPos.fZ); 1413c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth buffer.writeScalar(fLightRadius); 1423c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth buffer.writeScalar(fSpotAlpha); 1433c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth buffer.writeUInt(fFlags); 1443c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 1453c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1463c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#if SK_SUPPORT_GPU 1473c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1483c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth/////////////////////////////////////////////////////////////////////////////////////////////////// 1493c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1502103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthbool SkSpotShadowMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, 1512103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkIRect& clipBounds, 1522103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkMatrix& ctm, 1532103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkRect* maskRect) const { 1543c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // TODO 1553c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth *maskRect = devRRect.rect(); 1563c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth return true; 1573c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 1583c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 159d3749485db2de966a80e39669a49192fc7c0bd9dRobert Phillipsbool SkSpotShadowMaskFilterImpl::directFilterMaskGPU(GrContext* context, 16091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth GrRenderTargetContext* rtContext, 1612103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth GrPaint&& paint, 1622103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const GrClip& clip, 1632103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkMatrix& viewMatrix, 1642103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkStrokeRec& strokeRec, 1652103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkPath& path) const { 16691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkASSERT(rtContext); 1673c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // TODO: this will not handle local coordinates properly 1683c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 16991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fSpotAlpha <= 0.0f) { 17091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return true; 17191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 17291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 17391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // only convex paths for now 17491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (!path.isConvex()) { 17591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return false; 17691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 17791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 17891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (strokeRec.getStyle() != SkStrokeRec::kFill_Style) { 17991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return false; 18091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 18191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1823c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // if circle 1833c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // TODO: switch to SkScalarNearlyEqual when either oval renderer is updated or we 1843c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // have our own GeometryProc. 1853c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (path.isOval(nullptr) && path.getBounds().width() == path.getBounds().height()) { 1863c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkRRect rrect = SkRRect::MakeOval(path.getBounds()); 187d3749485db2de966a80e39669a49192fc7c0bd9dRobert Phillips return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip, 18882f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon SkMatrix::I(), strokeRec, rrect, rrect); 1893c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } else if (path.isRect(nullptr)) { 1903c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkRRect rrect = SkRRect::MakeRect(path.getBounds()); 191d3749485db2de966a80e39669a49192fc7c0bd9dRobert Phillips return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip, 19282f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon SkMatrix::I(), strokeRec, rrect, rrect); 1933c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 19491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 195efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verth return false; 1963c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 1973c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 1982103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthbool SkSpotShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*, 1992103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth GrRenderTargetContext* rtContext, 2002103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth GrPaint&& paint, 2012103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const GrClip& clip, 2022103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkMatrix& viewMatrix, 2032103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkStrokeRec& strokeRec, 2042103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkRRect& rrect, 2052103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkRRect& devRRect) const { 2063c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // It's likely the caller has already done these checks, but we have to be sure. 2073c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // TODO: support analytic blurring of general rrect 2083c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2093c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // Fast path only supports filled rrects for now. 2103c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // TODO: fill and stroke as well. 2113c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (SkStrokeRec::kFill_Style != strokeRec.getStyle()) { 2123c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth return false; 2133c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 2143c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // Fast path only supports simple rrects with circular corners. 2153c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkASSERT(devRRect.allCornersCircular()); 2163c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (!rrect.isRect() && !rrect.isOval() && !rrect.isSimple()) { 2173c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth return false; 2183c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 2193c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // Fast path only supports uniform scale. 2203c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar scaleFactors[2]; 2213c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (!viewMatrix.getMinMaxScales(scaleFactors)) { 2223c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // matrix is degenerate 2233c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth return false; 2243c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 2253c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (scaleFactors[0] != scaleFactors[1]) { 2263c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth return false; 2273c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 2283c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar scaleFactor = scaleFactors[0]; 2293c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2303c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // For all of these, we need to ensure we have a rrect with radius >= 0.5f in device space 2313c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkScalar minRadius = 0.5f / scaleFactor; 2323c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth bool isRect = rrect.getSimpleRadii().fX <= minRadius; 2333c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2343c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // TODO: take flags into account when generating shadow data 2353c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2363c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (fSpotAlpha > 0.0f) { 2373c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth float zRatio = SkTPin(fOccluderHeight / (fLightPos.fZ - fOccluderHeight), 0.0f, 0.95f); 2383c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2393c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar srcSpaceSpotRadius = 2.0f * fLightRadius * zRatio; 2403c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2413c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkRRect spotRRect; 2423c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (isRect) { 2433c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth spotRRect = SkRRect::MakeRectXY(rrect.rect(), minRadius, minRadius); 2443c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } else { 2453c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth spotRRect = rrect; 2463c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 2473c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2483c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkRRect spotShadowRRect; 2493c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // Compute the scale and translation for the spot shadow. 2503c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkScalar scale = fLightPos.fZ / (fLightPos.fZ - fOccluderHeight); 2513c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth spotRRect.transform(SkMatrix::MakeScale(scale, scale), &spotShadowRRect); 2523c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2533c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkPoint center = SkPoint::Make(spotShadowRRect.rect().centerX(), 2543c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth spotShadowRRect.rect().centerY()); 2553c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkMatrix ctmInverse; 2563c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (!viewMatrix.invert(&ctmInverse)) { 2573c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkDebugf("Matrix is degenerate. Will not render spot shadow!\n"); 2583c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth //**** TODO: this is not good 2593c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth return true; 2603c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 2613c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkPoint lightPos2D = SkPoint::Make(fLightPos.fX, fLightPos.fY); 2623c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth ctmInverse.mapPoints(&lightPos2D, 1); 2633c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkPoint spotOffset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX), 2643c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth zRatio*(center.fY - lightPos2D.fY)); 2653c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2663c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // We want to extend the stroked area in so that it meets up with the caster 2673c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // geometry. The stroked geometry will, by definition already be inset half the 2683c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // stroke width but we also have to account for the scaling. 2693c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar scaleOffset = (scale - 1.0f) * SkTMax(SkTMax(SkTAbs(rrect.rect().fLeft), 2703c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkTAbs(rrect.rect().fRight)), 2713c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkTMax(SkTAbs(rrect.rect().fTop), 2723c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkTAbs(rrect.rect().fBottom))); 273c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth SkScalar insetAmount = spotOffset.length() - (0.5f * srcSpaceSpotRadius) + scaleOffset; 2743c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 2753c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // Compute area 2763c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar strokeWidth = srcSpaceSpotRadius + insetAmount; 2773c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar strokedArea = 2.0f*strokeWidth * 2783c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth (spotShadowRRect.width() + spotShadowRRect.height()); 2793c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar filledArea = (spotShadowRRect.height() + srcSpaceSpotRadius) * 2803c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth (spotShadowRRect.width() + srcSpaceSpotRadius); 2813c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 28282f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon GrColor4f color = paint.getColor4f(); 283c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth color.fRGBA[3] *= fSpotAlpha; 28482f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon paint.setColor4f(color); 28582f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon 2863c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkStrokeRec spotStrokeRec(SkStrokeRec::kFill_InitStyle); 2873c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // If the area of the stroked geometry is larger than the fill geometry, 2883c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // or if the caster is transparent, just fill it. 2893c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (strokedArea > filledArea || 2902103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag) { 2913c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth spotStrokeRec.setStrokeStyle(srcSpaceSpotRadius, true); 2923c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } else { 2933c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // Since we can't have unequal strokes, inset the shadow rect so the inner 2943c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // and outer edges of the stroke will land where we want. 2953c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkRect insetRect = spotShadowRRect.rect().makeInset(insetAmount / 2.0f, 2963c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth insetAmount / 2.0f); 2973c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkScalar insetRad = SkTMax(spotShadowRRect.getSimpleRadii().fX - insetAmount / 2.0f, 2983c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth minRadius); 2993c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth spotShadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad); 3003c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth spotStrokeRec.setStrokeStyle(strokeWidth, false); 3013c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 3023c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3033c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth // handle scale of radius and pad due to CTM 3043c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor; 3053c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 306c59034145862bf6dc0c503cb1e47eecd321ffa8cJim Van Verth spotShadowRRect.offset(spotOffset.fX, spotOffset.fY); 3073c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3082103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth rtContext->drawShadowRRect(clip, std::move(paint), viewMatrix, spotShadowRRect, 3092103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth devSpaceSpotRadius, GrStyle(spotStrokeRec, nullptr)); 3103c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 3113c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3123c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth return true; 3133c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 3143c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3152103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthsk_sp<GrTextureProxy> SkSpotShadowMaskFilterImpl::filterMaskGPU(GrContext*, 3162103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth sk_sp<GrTextureProxy> srcProxy, 3172103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkMatrix& ctm, 3182103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth const SkIRect& maskRect) const { 319e305cc1f2a44e47d6a0dcc0ff34e2692349aed5dRobert Phillips // This filter is generative and doesn't operate on pre-existing masks 3204a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips return nullptr; 3213c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 3223c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3233c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#endif 3243c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3253c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#ifndef SK_IGNORE_TO_STRING 3262103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verthvoid SkSpotShadowMaskFilterImpl::toString(SkString* str) const { 3272103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth str->append("SkSpotShadowMaskFilterImpl: ("); 3283c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3293c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append("occluderHeight: "); 3303c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->appendScalar(fOccluderHeight); 3313c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append(" "); 3323c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3333c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append("lightPos: ("); 3343c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->appendScalar(fLightPos.fX); 3353c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append(", "); 3363c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->appendScalar(fLightPos.fY); 3373c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append(", "); 3383c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->appendScalar(fLightPos.fZ); 3393c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append(") "); 3403c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3413c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append("lightRadius: "); 3423c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->appendScalar(fLightRadius); 3433c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append(" "); 3443c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3453c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append("spotAlpha: "); 3463c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->appendScalar(fSpotAlpha); 3473c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append(" "); 3483c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3493c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append("flags: ("); 3503c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth if (fFlags) { 3513c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth bool needSeparator = false; 3523c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkAddFlagToString(str, 3532103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkToBool(fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag), 3543c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth "TransparentOccluder", &needSeparator); 3553c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkAddFlagToString(str, 3562103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkToBool(fFlags & SkShadowFlags::kGaussianEdge_ShadowFlag), 3573c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth "GaussianEdge", &needSeparator); 3583c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth SkAddFlagToString(str, 3592103cf0ff09763aeaa35508734f765aec9b75665Jim Van Verth SkToBool(fFlags & SkShadowFlags::kLargerUmbra_ShadowFlag), 3603c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth "LargerUmbra", &needSeparator); 3613c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } else { 3623c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append("None"); 3633c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth } 3643c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth str->append("))"); 3653c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth} 3663c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth#endif 3673c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van Verth 3682103cf0ff09763aeaa35508734f765aec9b75665Jim Van VerthSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkSpotShadowMaskFilter) 3692103cf0ff09763aeaa35508734f765aec9b75665Jim Van VerthSK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpotShadowMaskFilterImpl) 3703c1b7db2432d136df0fc50c2e3ee0b3792b01dd6Jim Van VerthSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 371