LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/effects/shadows - SkAmbientShadowMaskFilter.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 109 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2017 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "SkAmbientShadowMaskFilter.h"
       9             : #include "SkReadBuffer.h"
      10             : #include "SkStringUtils.h"
      11             : #include "SkWriteBuffer.h"
      12             : 
      13             : #if SK_SUPPORT_GPU
      14             : #include "GrContext.h"
      15             : #include "GrRenderTargetContext.h"
      16             : #include "GrFragmentProcessor.h"
      17             : #include "GrStyle.h"
      18             : #include "GrTexture.h"
      19             : #include "GrTextureProxy.h"
      20             : #include "SkStrokeRec.h"
      21             : #endif
      22             : 
      23           0 : class SkAmbientShadowMaskFilterImpl : public SkMaskFilter {
      24             : public:
      25             :     SkAmbientShadowMaskFilterImpl(SkScalar occluderHeight, SkScalar ambientAlpha, uint32_t flags);
      26             : 
      27             :     // overrides from SkMaskFilter
      28             :     SkMask::Format getFormat() const override;
      29             :     bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
      30             :                     SkIPoint* margin) const override;
      31             : 
      32             : #if SK_SUPPORT_GPU
      33             :     bool canFilterMaskGPU(const SkRRect& devRRect,
      34             :                           const SkIRect& clipBounds,
      35             :                           const SkMatrix& ctm,
      36             :                           SkRect* maskRect) const override;
      37             :     bool directFilterMaskGPU(GrContext*,
      38             :                              GrRenderTargetContext* drawContext,
      39             :                              GrPaint&&,
      40             :                              const GrClip&,
      41             :                              const SkMatrix& viewMatrix,
      42             :                              const SkStrokeRec& strokeRec,
      43             :                              const SkPath& path) const override;
      44             :     bool directFilterRRectMaskGPU(GrContext*,
      45             :                                   GrRenderTargetContext* drawContext,
      46             :                                   GrPaint&&,
      47             :                                   const GrClip&,
      48             :                                   const SkMatrix& viewMatrix,
      49             :                                   const SkStrokeRec& strokeRec,
      50             :                                   const SkRRect& rrect,
      51             :                                   const SkRRect& devRRect) const override;
      52             :     sk_sp<GrTextureProxy> filterMaskGPU(GrContext*,
      53             :                                         sk_sp<GrTextureProxy> srcProxy,
      54             :                                         const SkMatrix& ctm,
      55             :                                         const SkIRect& maskRect) const override;
      56             : #endif
      57             : 
      58             :     void computeFastBounds(const SkRect&, SkRect*) const override;
      59             : 
      60             :     SK_TO_STRING_OVERRIDE()
      61           0 :     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAmbientShadowMaskFilterImpl)
      62             : 
      63             : private:
      64             :     SkScalar fOccluderHeight;
      65             :     SkScalar fAmbientAlpha;
      66             :     uint32_t fFlags;
      67             : 
      68             :     SkAmbientShadowMaskFilterImpl(SkReadBuffer&);
      69             :     void flatten(SkWriteBuffer&) const override;
      70             : 
      71             :     friend class SkAmbientShadowMaskFilter;
      72             : 
      73             :     typedef SkMaskFilter INHERITED;
      74             : };
      75             : 
      76           0 : sk_sp<SkMaskFilter> SkAmbientShadowMaskFilter::Make(SkScalar occluderHeight, SkScalar ambientAlpha,
      77             :                                                     uint32_t flags) {
      78             :     // add some param checks here for early exit
      79             : 
      80             :     return sk_sp<SkMaskFilter>(new SkAmbientShadowMaskFilterImpl(occluderHeight, ambientAlpha,
      81           0 :                                                                  flags));
      82             : }
      83             : 
      84             : ///////////////////////////////////////////////////////////////////////////////////////////////////
      85             : 
      86           0 : SkAmbientShadowMaskFilterImpl::SkAmbientShadowMaskFilterImpl(SkScalar occluderHeight,
      87             :                                                              SkScalar ambientAlpha,
      88           0 :                                                              uint32_t flags)
      89             :     : fOccluderHeight(occluderHeight)
      90             :     , fAmbientAlpha(ambientAlpha)
      91           0 :     , fFlags(flags) {
      92           0 :     SkASSERT(fOccluderHeight > 0);
      93           0 :     SkASSERT(fAmbientAlpha >= 0);
      94           0 : }
      95             : 
      96           0 : SkMask::Format SkAmbientShadowMaskFilterImpl::getFormat() const {
      97           0 :     return SkMask::kA8_Format;
      98             : }
      99             : 
     100           0 : bool SkAmbientShadowMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
     101             :                                                const SkMatrix& matrix,
     102             :                                                SkIPoint* margin) const {
     103             :     // TODO something
     104           0 :     return false;
     105             : }
     106             : 
     107           0 : void SkAmbientShadowMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) const {
     108             :     // TODO compute based on ambient data
     109           0 :     dst->set(src.fLeft, src.fTop, src.fRight, src.fBottom);
     110           0 : }
     111             : 
     112           0 : sk_sp<SkFlattenable> SkAmbientShadowMaskFilterImpl::CreateProc(SkReadBuffer& buffer) {
     113           0 :     const SkScalar occluderHeight = buffer.readScalar();
     114           0 :     const SkScalar ambientAlpha = buffer.readScalar();
     115           0 :     const uint32_t flags = buffer.readUInt();
     116             : 
     117           0 :     return SkAmbientShadowMaskFilter::Make(occluderHeight, ambientAlpha, flags);
     118             : }
     119             : 
     120           0 : void SkAmbientShadowMaskFilterImpl::flatten(SkWriteBuffer& buffer) const {
     121           0 :     buffer.writeScalar(fOccluderHeight);
     122           0 :     buffer.writeScalar(fAmbientAlpha);
     123           0 :     buffer.writeUInt(fFlags);
     124           0 : }
     125             : 
     126             : #if SK_SUPPORT_GPU
     127             : 
     128             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     129             : 
     130           0 : bool SkAmbientShadowMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect,
     131             :                                                      const SkIRect& clipBounds,
     132             :                                                      const SkMatrix& ctm,
     133             :                                                      SkRect* maskRect) const {
     134             :     // TODO
     135           0 :     *maskRect = devRRect.rect();
     136           0 :     return true;
     137             : }
     138             : 
     139             : static const float kHeightFactor = 1.0f / 128.0f;
     140             : static const float kGeomFactor = 64.0f;
     141             : 
     142           0 : bool SkAmbientShadowMaskFilterImpl::directFilterMaskGPU(GrContext* context,
     143             :                                                         GrRenderTargetContext* rtContext,
     144             :                                                         GrPaint&& paint,
     145             :                                                         const GrClip& clip,
     146             :                                                         const SkMatrix& viewMatrix,
     147             :                                                         const SkStrokeRec& strokeRec,
     148             :                                                         const SkPath& path) const {
     149           0 :     SkASSERT(rtContext);
     150             :     // TODO: this will not handle local coordinates properly
     151             : 
     152           0 :     if (fAmbientAlpha <= 0.0f) {
     153           0 :         return true;
     154             :     }
     155             : 
     156             :     // only convex paths for now
     157           0 :     if (!path.isConvex()) {
     158           0 :         return false;
     159             :     }
     160             : 
     161           0 :     if (strokeRec.getStyle() != SkStrokeRec::kFill_Style) {
     162           0 :         return false;
     163             :     }
     164             : 
     165             :     // if circle
     166             :     // TODO: switch to SkScalarNearlyEqual when either oval renderer is updated or we
     167             :     // have our own GeometryProc.
     168           0 :     if (path.isOval(nullptr) && path.getBounds().width() == path.getBounds().height()) {
     169           0 :         SkRRect rrect = SkRRect::MakeOval(path.getBounds());
     170           0 :         return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip,
     171           0 :                                               SkMatrix::I(), strokeRec, rrect, rrect);
     172           0 :     } else if (path.isRect(nullptr)) {
     173           0 :         SkRRect rrect = SkRRect::MakeRect(path.getBounds());
     174           0 :         return this->directFilterRRectMaskGPU(context, rtContext, std::move(paint), clip,
     175           0 :                                               SkMatrix::I(), strokeRec, rrect, rrect);
     176             :     }
     177             : 
     178             :     // TODO
     179           0 :     return false;
     180             : }
     181             : 
     182           0 : bool SkAmbientShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
     183             :                                                              GrRenderTargetContext* rtContext,
     184             :                                                              GrPaint&& paint,
     185             :                                                              const GrClip& clip,
     186             :                                                              const SkMatrix& viewMatrix,
     187             :                                                              const SkStrokeRec& strokeRec,
     188             :                                                              const SkRRect& rrect,
     189             :                                                              const SkRRect& devRRect) const {
     190             :     // It's likely the caller has already done these checks, but we have to be sure.
     191             :     // TODO: support analytic blurring of general rrect
     192             : 
     193             :     // Fast path only supports filled rrects for now.
     194             :     // TODO: fill and stroke as well.
     195           0 :     if (SkStrokeRec::kFill_Style != strokeRec.getStyle()) {
     196           0 :         return false;
     197             :     }
     198             :     // Fast path only supports simple rrects with circular corners.
     199           0 :     SkASSERT(devRRect.allCornersCircular());
     200           0 :     if (!rrect.isRect() && !rrect.isOval() && !rrect.isSimple()) {
     201           0 :         return false;
     202             :     }
     203             :     // Fast path only supports uniform scale.
     204             :     SkScalar scaleFactors[2];
     205           0 :     if (!viewMatrix.getMinMaxScales(scaleFactors)) {
     206             :         // matrix is degenerate
     207           0 :         return false;
     208             :     }
     209           0 :     if (scaleFactors[0] != scaleFactors[1]) {
     210           0 :         return false;
     211             :     }
     212           0 :     SkScalar scaleFactor = scaleFactors[0];
     213             : 
     214             :     // For all of these, we need to ensure we have a rrect with radius >= 0.5f in device space
     215           0 :     const SkScalar minRadius = 0.5f / scaleFactor;
     216           0 :     bool isRect = rrect.getSimpleRadii().fX <= minRadius;
     217             : 
     218             :     // TODO: take flags into account when generating shadow data
     219             : 
     220           0 :     if (fAmbientAlpha > 0.0f) {
     221           0 :         SkScalar srcSpaceAmbientRadius = fOccluderHeight * kHeightFactor * kGeomFactor;
     222           0 :         const float umbraAlpha = (1.0f + SkTMax(fOccluderHeight * kHeightFactor, 0.0f));
     223           0 :         const SkScalar strokeWidth = srcSpaceAmbientRadius * umbraAlpha;
     224             : 
     225             :         // For the ambient rrect, we outset the offset rect by srcSpaceAmbientRadius
     226             :         // minus half the strokeWidth to get our stroke shape.
     227           0 :         SkScalar ambientPathOutset = SkTMax(srcSpaceAmbientRadius - strokeWidth * 0.5f,
     228           0 :                                             minRadius);
     229             : 
     230           0 :         SkRRect ambientRRect;
     231           0 :         if (isRect) {
     232           0 :             const SkRect temp = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
     233           0 :             ambientRRect = SkRRect::MakeRectXY(temp, ambientPathOutset, ambientPathOutset);
     234             :         } else {
     235           0 :              rrect.outset(ambientPathOutset, ambientPathOutset, &ambientRRect);
     236             :         }
     237             : 
     238           0 :         const SkScalar devSpaceAmbientRadius = strokeWidth * scaleFactor;
     239             : 
     240           0 :         GrPaint newPaint(paint);
     241           0 :         GrColor4f color = newPaint.getColor4f();
     242           0 :         color.fRGBA[3] *= fAmbientAlpha;
     243           0 :         newPaint.setColor4f(color);
     244           0 :         SkStrokeRec ambientStrokeRec(SkStrokeRec::kHairline_InitStyle);
     245           0 :         ambientStrokeRec.setStrokeStyle(strokeWidth, false);
     246             : 
     247           0 :         rtContext->drawShadowRRect(clip, std::move(newPaint), viewMatrix, ambientRRect,
     248             :                                    devSpaceAmbientRadius,
     249           0 :                                    GrStyle(ambientStrokeRec, nullptr));
     250             :     }
     251             : 
     252           0 :     return true;
     253             : }
     254             : 
     255           0 : sk_sp<GrTextureProxy> SkAmbientShadowMaskFilterImpl::filterMaskGPU(GrContext*,
     256             :                                                                    sk_sp<GrTextureProxy> srcProxy,
     257             :                                                                    const SkMatrix& ctm,
     258             :                                                                    const SkIRect& maskRect) const {
     259             :     // This filter is generative and doesn't operate on pre-existing masks
     260           0 :     return nullptr;
     261             : }
     262             : 
     263             : #endif // SK_SUPPORT_GPU
     264             : 
     265             : #ifndef SK_IGNORE_TO_STRING
     266           0 : void SkAmbientShadowMaskFilterImpl::toString(SkString* str) const {
     267           0 :     str->append("SkAmbientShadowMaskFilterImpl: (");
     268             : 
     269           0 :     str->append("occluderHeight: ");
     270           0 :     str->appendScalar(fOccluderHeight);
     271           0 :     str->append(" ");
     272             : 
     273           0 :     str->append("ambientAlpha: ");
     274           0 :     str->appendScalar(fAmbientAlpha);
     275           0 :     str->append(" ");
     276             : 
     277           0 :     str->append("flags: (");
     278           0 :     if (fFlags) {
     279           0 :         bool needSeparator = false;
     280           0 :         SkAddFlagToString(str,
     281           0 :                           SkToBool(fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag),
     282           0 :                           "TransparentOccluder", &needSeparator);
     283           0 :         SkAddFlagToString(str,
     284           0 :                           SkToBool(fFlags & SkShadowFlags::kGaussianEdge_ShadowFlag),
     285           0 :                           "GaussianEdge", &needSeparator);
     286           0 :         SkAddFlagToString(str,
     287           0 :                           SkToBool(fFlags & SkShadowFlags::kLargerUmbra_ShadowFlag),
     288           0 :                           "LargerUmbra", &needSeparator);
     289             :     } else {
     290           0 :         str->append("None");
     291             :     }
     292           0 :     str->append("))");
     293           0 : }
     294             : #endif
     295             : 
     296           0 : SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkAmbientShadowMaskFilter)
     297           0 : SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAmbientShadowMaskFilterImpl)
     298           0 : SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END

Generated by: LCOV version 1.13