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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 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 "GrBlurUtils.h"
       9             : #include "GrRenderTargetContext.h"
      10             : #include "GrCaps.h"
      11             : #include "GrContext.h"
      12             : #include "GrContextPriv.h"
      13             : #include "GrFixedClip.h"
      14             : #include "GrRenderTargetContextPriv.h"
      15             : #include "GrResourceProvider.h"
      16             : #include "effects/GrSimpleTextureEffect.h"
      17             : #include "GrStyle.h"
      18             : #include "GrTexture.h"
      19             : #include "GrTextureProxy.h"
      20             : #include "SkDraw.h"
      21             : #include "SkGr.h"
      22             : #include "SkMaskFilter.h"
      23             : #include "SkPaint.h"
      24             : #include "SkTLazy.h"
      25             : 
      26           0 : static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& rect) {
      27           0 :     return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBounds, rect);
      28             : }
      29             : 
      30             : // Draw a mask using the supplied paint. Since the coverage/geometry
      31             : // is already burnt into the mask this boils down to a rect draw.
      32             : // Return true if the mask was successfully drawn.
      33           0 : static bool draw_mask(GrRenderTargetContext* renderTargetContext,
      34             :                       const GrClip& clip,
      35             :                       const SkMatrix& viewMatrix,
      36             :                       const SkIRect& maskRect,
      37             :                       GrPaint&& paint,
      38             :                       sk_sp<GrTextureProxy> mask) {
      39             :     SkMatrix inverse;
      40           0 :     if (!viewMatrix.invert(&inverse)) {
      41           0 :         return false;
      42             :     }
      43             : 
      44           0 :     GrResourceProvider* resourceProvider = renderTargetContext->resourceProvider();
      45             : 
      46           0 :     SkMatrix matrix = SkMatrix::MakeTrans(-SkIntToScalar(maskRect.fLeft),
      47           0 :                                           -SkIntToScalar(maskRect.fTop));
      48           0 :     matrix.preConcat(viewMatrix);
      49           0 :     paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(resourceProvider,
      50           0 :                                                                    std::move(mask),
      51           0 :                                                                    nullptr, matrix));
      52             : 
      53           0 :     renderTargetContext->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
      54           0 :                                                  SkRect::Make(maskRect), inverse);
      55           0 :     return true;
      56             : }
      57             : 
      58           0 : static bool sw_draw_with_mask_filter(GrContext* context,
      59             :                                      GrRenderTargetContext* renderTargetContext,
      60             :                                      const GrClip& clipData,
      61             :                                      const SkMatrix& viewMatrix,
      62             :                                      const SkPath& devPath,
      63             :                                      const SkMaskFilter* filter,
      64             :                                      const SkIRect& clipBounds,
      65             :                                      GrPaint&& paint,
      66             :                                      SkStrokeRec::InitStyle fillOrHairline) {
      67           0 :     SkMask  srcM, dstM;
      68           0 :     if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM,
      69             :                             SkMask::kComputeBoundsAndRenderImage_CreateMode, fillOrHairline)) {
      70           0 :         return false;
      71             :     }
      72           0 :     SkAutoMaskFreeImage autoSrc(srcM.fImage);
      73             : 
      74           0 :     if (!filter->filterMask(&dstM, srcM, viewMatrix, nullptr)) {
      75           0 :         return false;
      76             :     }
      77             :     // this will free-up dstM when we're done (allocated in filterMask())
      78           0 :     SkAutoMaskFreeImage autoDst(dstM.fImage);
      79             : 
      80           0 :     if (clip_bounds_quick_reject(clipBounds, dstM.fBounds)) {
      81           0 :         return false;
      82             :     }
      83             : 
      84             :     // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
      85             :     // the current clip (and identity matrix) and GrPaint settings
      86           0 :     GrSurfaceDesc desc;
      87           0 :     desc.fOrigin = kTopLeft_GrSurfaceOrigin;
      88           0 :     desc.fWidth = dstM.fBounds.width();
      89           0 :     desc.fHeight = dstM.fBounds.height();
      90           0 :     desc.fConfig = kAlpha_8_GrPixelConfig;
      91             : 
      92           0 :     sk_sp<GrSurfaceContext> sContext = context->contextPriv().makeDeferredSurfaceContext(
      93             :                                                         desc,
      94             :                                                         SkBackingFit::kApprox,
      95           0 :                                                         SkBudgeted::kYes);
      96           0 :     if (!sContext) {
      97           0 :         return false;
      98             :     }
      99             : 
     100           0 :     SkImageInfo ii = SkImageInfo::MakeA8(desc.fWidth, desc.fHeight);
     101           0 :     if (!sContext->writePixels(ii, dstM.fImage, dstM.fRowBytes, 0, 0)) {
     102           0 :         return false;
     103             :     }
     104             : 
     105             :     return draw_mask(renderTargetContext, clipData, viewMatrix,
     106           0 :                      dstM.fBounds, std::move(paint), sContext->asTextureProxyRef());
     107             : }
     108             : 
     109             : // Create a mask of 'devPath' and place the result in 'mask'.
     110           0 : static sk_sp<GrTextureProxy> create_mask_GPU(GrContext* context,
     111             :                                              const SkIRect& maskRect,
     112             :                                              const SkPath& devPath,
     113             :                                              SkStrokeRec::InitStyle fillOrHairline,
     114             :                                              GrAA aa,
     115             :                                              int sampleCnt) {
     116           0 :     if (GrAA::kNo == aa) {
     117             :         // Don't need MSAA if mask isn't AA
     118           0 :         sampleCnt = 0;
     119             :     }
     120             : 
     121             :     sk_sp<GrRenderTargetContext> rtContext(context->makeDeferredRenderTargetContextWithFallback(
     122             :         SkBackingFit::kApprox, maskRect.width(), maskRect.height(), kAlpha_8_GrPixelConfig, nullptr,
     123           0 :         sampleCnt));
     124           0 :     if (!rtContext) {
     125           0 :         return nullptr;
     126             :     }
     127             : 
     128           0 :     rtContext->priv().absClear(nullptr, 0x0);
     129             : 
     130           0 :     GrPaint maskPaint;
     131           0 :     maskPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
     132             : 
     133             :     // setup new clip
     134           0 :     const SkIRect clipRect = SkIRect::MakeWH(maskRect.width(), maskRect.height());
     135           0 :     GrFixedClip clip(clipRect);
     136             : 
     137             :     // Draw the mask into maskTexture with the path's integerized top-left at
     138             :     // the origin using maskPaint.
     139             :     SkMatrix translate;
     140           0 :     translate.setTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop));
     141           0 :     rtContext->drawPath(clip, std::move(maskPaint), aa, translate, devPath,
     142           0 :                         GrStyle(fillOrHairline));
     143           0 :     return rtContext->asTextureProxyRef();
     144             : }
     145             : 
     146           0 : static void draw_path_with_mask_filter(GrContext* context,
     147             :                                        GrRenderTargetContext* renderTargetContext,
     148             :                                        const GrClip& clip,
     149             :                                        GrPaint&& paint,
     150             :                                        GrAA aa,
     151             :                                        const SkMatrix& viewMatrix,
     152             :                                        const SkMaskFilter* maskFilter,
     153             :                                        const GrStyle& style,
     154             :                                        const SkPath* path,
     155             :                                        bool pathIsMutable) {
     156           0 :     SkASSERT(maskFilter);
     157             : 
     158             :     SkIRect clipBounds;
     159           0 :     clip.getConservativeBounds(renderTargetContext->width(),
     160             :                                renderTargetContext->height(),
     161           0 :                                &clipBounds);
     162           0 :     SkTLazy<SkPath> tmpPath;
     163             :     SkStrokeRec::InitStyle fillOrHairline;
     164             : 
     165             :     // We just fully apply the style here.
     166           0 :     if (style.applies()) {
     167           0 :         SkScalar scale = GrStyle::MatrixToScaleFactor(viewMatrix);
     168           0 :         if (0 == scale || !style.applyToPath(tmpPath.init(), &fillOrHairline, *path, scale)) {
     169           0 :             return;
     170             :         }
     171           0 :         pathIsMutable = true;
     172           0 :         path = tmpPath.get();
     173           0 :     } else if (style.isSimpleHairline()) {
     174           0 :         fillOrHairline = SkStrokeRec::kHairline_InitStyle;
     175             :     } else {
     176           0 :         SkASSERT(style.isSimpleFill());
     177           0 :         fillOrHairline = SkStrokeRec::kFill_InitStyle;
     178             :     }
     179             : 
     180             :     // transform the path into device space
     181           0 :     if (!viewMatrix.isIdentity()) {
     182             :         SkPath* result;
     183           0 :         if (pathIsMutable) {
     184           0 :             result = const_cast<SkPath*>(path);
     185             :         } else {
     186           0 :             if (!tmpPath.isValid()) {
     187           0 :                 tmpPath.init();
     188             :             }
     189           0 :             result = tmpPath.get();
     190             :         }
     191           0 :         path->transform(viewMatrix, result);
     192           0 :         path = result;
     193           0 :         result->setIsVolatile(true);
     194           0 :         pathIsMutable = true;
     195             :     }
     196             : 
     197             :     SkRect maskRect;
     198           0 :     if (maskFilter->canFilterMaskGPU(SkRRect::MakeRect(path->getBounds()),
     199             :                                      clipBounds,
     200             :                                      viewMatrix,
     201           0 :                                      &maskRect)) {
     202             :         // This mask will ultimately be drawn as a non-AA rect (see draw_mask).
     203             :         // Non-AA rects have a bad habit of snapping arbitrarily. Integerize here
     204             :         // so the mask draws in a reproducible manner.
     205             :         SkIRect finalIRect;
     206           0 :         maskRect.roundOut(&finalIRect);
     207           0 :         if (clip_bounds_quick_reject(clipBounds, finalIRect)) {
     208             :             // clipped out
     209           0 :             return;
     210             :         }
     211             : 
     212           0 :         if (maskFilter->directFilterMaskGPU(context,
     213             :                                             renderTargetContext,
     214           0 :                                             std::move(paint),
     215             :                                             clip,
     216             :                                             viewMatrix,
     217           0 :                                             SkStrokeRec(fillOrHairline),
     218           0 :                                             *path)) {
     219             :             // the mask filter was able to draw itself directly, so there's nothing
     220             :             // left to do.
     221           0 :             return;
     222             :         }
     223             : 
     224             :         sk_sp<GrTextureProxy> maskProxy(create_mask_GPU(context,
     225             :                                                         finalIRect,
     226             :                                                         *path,
     227             :                                                         fillOrHairline,
     228             :                                                         aa,
     229           0 :                                                         renderTargetContext->numColorSamples()));
     230           0 :         if (maskProxy) {
     231             :             sk_sp<GrTextureProxy> filtered = maskFilter->filterMaskGPU(context,
     232           0 :                                                                        std::move(maskProxy),
     233             :                                                                        viewMatrix,
     234           0 :                                                                        finalIRect);
     235           0 :             if (filtered) {
     236           0 :                 if (draw_mask(renderTargetContext, clip, viewMatrix,
     237           0 :                               finalIRect, std::move(paint), std::move(filtered))) {
     238             :                     // This path is completely drawn
     239           0 :                     return;
     240             :                 }
     241             :             }
     242             :         }
     243             :     }
     244             : 
     245             :     sw_draw_with_mask_filter(context, renderTargetContext, clip, viewMatrix, *path, maskFilter,
     246           0 :                              clipBounds, std::move(paint), fillOrHairline);
     247             : }
     248             : 
     249           0 : void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
     250             :                                          GrRenderTargetContext* renderTargetContext,
     251             :                                          const GrClip& clip,
     252             :                                          const SkPath& path,
     253             :                                          GrPaint&& paint,
     254             :                                          GrAA aa,
     255             :                                          const SkMatrix& viewMatrix,
     256             :                                          const SkMaskFilter* mf,
     257             :                                          const GrStyle& style,
     258             :                                          bool pathIsMutable) {
     259           0 :     draw_path_with_mask_filter(context, renderTargetContext, clip, std::move(paint), aa, viewMatrix,
     260           0 :                                mf, style, &path, pathIsMutable);
     261           0 : }
     262             : 
     263           0 : void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
     264             :                                          GrRenderTargetContext* renderTargetContext,
     265             :                                          const GrClip& clip,
     266             :                                          const SkPath& origPath,
     267             :                                          const SkPaint& paint,
     268             :                                          const SkMatrix& origViewMatrix,
     269             :                                          const SkMatrix* prePathMatrix,
     270             :                                          const SkIRect& clipBounds,
     271             :                                          bool pathIsMutable) {
     272           0 :     SkASSERT(!pathIsMutable || origPath.isVolatile());
     273             : 
     274           0 :     GrStyle style(paint);
     275             :     // If we have a prematrix, apply it to the path, optimizing for the case
     276             :     // where the original path can in fact be modified in place (even though
     277             :     // its parameter type is const).
     278             : 
     279           0 :     const SkPath* path = &origPath;
     280           0 :     SkTLazy<SkPath> tmpPath;
     281             : 
     282           0 :     SkMatrix viewMatrix = origViewMatrix;
     283             : 
     284           0 :     if (prePathMatrix) {
     285             :         // Styling, blurs, and shading are supposed to be applied *after* the prePathMatrix.
     286           0 :         if (!paint.getMaskFilter() && !paint.getShader() && !style.applies()) {
     287           0 :             viewMatrix.preConcat(*prePathMatrix);
     288             :         } else {
     289           0 :             SkPath* result = pathIsMutable ? const_cast<SkPath*>(path) : tmpPath.init();
     290           0 :             pathIsMutable = true;
     291           0 :             path->transform(*prePathMatrix, result);
     292           0 :             path = result;
     293           0 :             result->setIsVolatile(true);
     294             :         }
     295             :     }
     296             :     // at this point we're done with prePathMatrix
     297           0 :     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
     298             : 
     299           0 :     GrPaint grPaint;
     300           0 :     if (!SkPaintToGrPaint(context, renderTargetContext, paint, viewMatrix, &grPaint)) {
     301           0 :         return;
     302             :     }
     303           0 :     GrAA aa = GrBoolToAA(paint.isAntiAlias());
     304           0 :     SkMaskFilter* mf = paint.getMaskFilter();
     305           0 :     if (mf && !mf->asFragmentProcessor(nullptr, nullptr, viewMatrix)) {
     306             :         // The MaskFilter wasn't already handled in SkPaintToGrPaint
     307           0 :         draw_path_with_mask_filter(context, renderTargetContext, clip, std::move(grPaint), aa,
     308           0 :                                    viewMatrix, mf, style, path, pathIsMutable);
     309             :     } else {
     310           0 :         renderTargetContext->drawPath(clip, std::move(grPaint), aa, viewMatrix, *path, style);
     311             :     }
     312             : }

Generated by: LCOV version 1.13