LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu - SkGpuDevice_drawTexture.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 103 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 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 "SkGpuDevice.h"
       9             : 
      10             : #include "GrBlurUtils.h"
      11             : #include "GrCaps.h"
      12             : #include "GrRenderTargetContext.h"
      13             : #include "GrStyle.h"
      14             : #include "GrTextureAdjuster.h"
      15             : #include "SkDraw.h"
      16             : #include "SkGr.h"
      17             : #include "SkMaskFilter.h"
      18             : #include "effects/GrBicubicEffect.h"
      19             : #include "effects/GrSimpleTextureEffect.h"
      20             : #include "effects/GrTextureDomain.h"
      21             : 
      22           0 : static inline bool use_shader(bool textureIsAlphaOnly, const SkPaint& paint) {
      23           0 :     return textureIsAlphaOnly && paint.getShader();
      24             : }
      25             : 
      26             : //////////////////////////////////////////////////////////////////////////////
      27             : //  Helper functions for dropping src rect constraint in bilerp mode.
      28             : 
      29             : static const SkScalar kColorBleedTolerance = 0.001f;
      30             : 
      31           0 : static bool has_aligned_samples(const SkRect& srcRect, const SkRect& transformedRect) {
      32             :     // detect pixel disalignment
      33           0 :     if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) - transformedRect.left()) < kColorBleedTolerance &&
      34           0 :         SkScalarAbs(SkScalarRoundToScalar(transformedRect.top())  - transformedRect.top())  < kColorBleedTolerance &&
      35           0 :         SkScalarAbs(transformedRect.width()  - srcRect.width())  < kColorBleedTolerance &&
      36           0 :         SkScalarAbs(transformedRect.height() - srcRect.height()) < kColorBleedTolerance) {
      37           0 :         return true;
      38             :     }
      39           0 :     return false;
      40             : }
      41             : 
      42           0 : static bool may_color_bleed(const SkRect& srcRect,
      43             :                             const SkRect& transformedRect,
      44             :                             const SkMatrix& m,
      45             :                             bool isMSAA) {
      46             :     // Only gets called if has_aligned_samples returned false.
      47             :     // So we can assume that sampling is axis aligned but not texel aligned.
      48           0 :     SkASSERT(!has_aligned_samples(srcRect, transformedRect));
      49           0 :     SkRect innerSrcRect(srcRect), innerTransformedRect, outerTransformedRect(transformedRect);
      50           0 :     if (isMSAA) {
      51           0 :         innerSrcRect.inset(SK_Scalar1, SK_Scalar1);
      52             :     } else {
      53           0 :         innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf);
      54             :     }
      55           0 :     m.mapRect(&innerTransformedRect, innerSrcRect);
      56             : 
      57             :     // The gap between outerTransformedRect and innerTransformedRect
      58             :     // represents the projection of the source border area, which is
      59             :     // problematic for color bleeding.  We must check whether any
      60             :     // destination pixels sample the border area.
      61           0 :     outerTransformedRect.inset(kColorBleedTolerance, kColorBleedTolerance);
      62           0 :     innerTransformedRect.outset(kColorBleedTolerance, kColorBleedTolerance);
      63             :     SkIRect outer, inner;
      64           0 :     outerTransformedRect.round(&outer);
      65           0 :     innerTransformedRect.round(&inner);
      66             :     // If the inner and outer rects round to the same result, it means the
      67             :     // border does not overlap any pixel centers. Yay!
      68           0 :     return inner != outer;
      69             : }
      70             : 
      71           0 : static bool can_ignore_bilerp_constraint(const GrTextureProducer& producer,
      72             :                                          const SkRect& srcRect,
      73             :                                          const SkMatrix& srcRectToDeviceSpace,
      74             :                                          bool isMSAA) {
      75           0 :     if (srcRectToDeviceSpace.rectStaysRect()) {
      76             :         // sampling is axis-aligned
      77             :         SkRect transformedRect;
      78           0 :         srcRectToDeviceSpace.mapRect(&transformedRect, srcRect);
      79             : 
      80           0 :         if (has_aligned_samples(srcRect, transformedRect) ||
      81           0 :             !may_color_bleed(srcRect, transformedRect, srcRectToDeviceSpace, isMSAA)) {
      82           0 :             return true;
      83             :         }
      84             :     }
      85           0 :     return false;
      86             : }
      87             : 
      88             : //////////////////////////////////////////////////////////////////////////////
      89             : 
      90           0 : void SkGpuDevice::drawTextureProducer(GrTextureProducer* producer,
      91             :                                       const SkRect* srcRect,
      92             :                                       const SkRect* dstRect,
      93             :                                       SkCanvas::SrcRectConstraint constraint,
      94             :                                       const SkMatrix& viewMatrix,
      95             :                                       const GrClip& clip,
      96             :                                       const SkPaint& paint) {
      97             :     // This is the funnel for all non-tiled bitmap/image draw calls. Log a histogram entry.
      98             :     SK_HISTOGRAM_BOOLEAN("DrawTiled", false);
      99             : 
     100             :     // Figure out the actual dst and src rect by clipping the src rect to the bounds of the
     101             :     // adjuster. If the src rect is clipped then the dst rect must be recomputed. Also determine
     102             :     // the matrix that maps the src rect to the dst rect.
     103             :     SkRect clippedSrcRect;
     104             :     SkRect clippedDstRect;
     105           0 :     const SkRect srcBounds = SkRect::MakeIWH(producer->width(), producer->height());
     106             :     SkMatrix srcToDstMatrix;
     107           0 :     if (srcRect) {
     108           0 :         if (!dstRect) {
     109           0 :             dstRect = &srcBounds;
     110             :         }
     111           0 :         if (!srcBounds.contains(*srcRect)) {
     112           0 :             clippedSrcRect = *srcRect;
     113           0 :             if (!clippedSrcRect.intersect(srcBounds)) {
     114           0 :                 return;
     115             :             }
     116           0 :             if (!srcToDstMatrix.setRectToRect(*srcRect, *dstRect, SkMatrix::kFill_ScaleToFit)) {
     117           0 :                 return;
     118             :             }
     119           0 :             srcToDstMatrix.mapRect(&clippedDstRect, clippedSrcRect);
     120             :         } else {
     121           0 :             clippedSrcRect = *srcRect;
     122           0 :             clippedDstRect = *dstRect;
     123           0 :             if (!srcToDstMatrix.setRectToRect(*srcRect, *dstRect, SkMatrix::kFill_ScaleToFit)) {
     124           0 :                 return;
     125             :             }
     126             :         }
     127             :     } else {
     128           0 :         clippedSrcRect = srcBounds;
     129           0 :         if (dstRect) {
     130           0 :             clippedDstRect = *dstRect;
     131           0 :             if (!srcToDstMatrix.setRectToRect(srcBounds, *dstRect, SkMatrix::kFill_ScaleToFit)) {
     132           0 :                 return;
     133             :             }
     134             :         } else {
     135           0 :             clippedDstRect = srcBounds;
     136           0 :             srcToDstMatrix.reset();
     137             :         }
     138             :     }
     139             : 
     140             :     // Now that we have both the view and srcToDst matrices, log our scale factor.
     141           0 :     LogDrawScaleFactor(SkMatrix::Concat(viewMatrix, srcToDstMatrix), paint.getFilterQuality());
     142             : 
     143             :     this->drawTextureProducerImpl(producer, clippedSrcRect, clippedDstRect, constraint, viewMatrix,
     144           0 :                                   srcToDstMatrix, clip, paint);
     145             : }
     146             : 
     147           0 : void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer,
     148             :                                           const SkRect& clippedSrcRect,
     149             :                                           const SkRect& clippedDstRect,
     150             :                                           SkCanvas::SrcRectConstraint constraint,
     151             :                                           const SkMatrix& viewMatrix,
     152             :                                           const SkMatrix& srcToDstMatrix,
     153             :                                           const GrClip& clip,
     154             :                                           const SkPaint& paint) {
     155             :     // Specifying the texture coords as local coordinates is an attempt to enable more GrDrawOp
     156             :     // combining by not baking anything about the srcRect, dstRect, or viewMatrix, into the texture
     157             :     // FP. In the future this should be an opaque optimization enabled by the combination of
     158             :     // GrDrawOp/GP and FP.
     159           0 :     const SkMaskFilter* mf = paint.getMaskFilter();
     160             :     // The shader expects proper local coords, so we can't replace local coords with texture coords
     161             :     // if the shader will be used. If we have a mask filter we will change the underlying geometry
     162             :     // that is rendered.
     163           0 :     bool canUseTextureCoordsAsLocalCoords = !use_shader(producer->isAlphaOnly(), paint) && !mf;
     164             : 
     165             :     bool doBicubic;
     166             :     GrSamplerParams::FilterMode fm =
     167           0 :         GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewMatrix, srcToDstMatrix,
     168           0 :                                         &doBicubic);
     169           0 :     const GrSamplerParams::FilterMode* filterMode = doBicubic ? nullptr : &fm;
     170             : 
     171             :     GrTextureProducer::FilterConstraint constraintMode;
     172           0 :     if (SkCanvas::kFast_SrcRectConstraint == constraint) {
     173           0 :         constraintMode = GrTextureAdjuster::kNo_FilterConstraint;
     174             :     } else {
     175           0 :         constraintMode = GrTextureAdjuster::kYes_FilterConstraint;
     176             :     }
     177             : 
     178             :     // If we have to outset for AA then we will generate texture coords outside the src rect. The
     179             :     // same happens for any mask filter that extends the bounds rendered in the dst.
     180             :     // This is conservative as a mask filter does not have to expand the bounds rendered.
     181           0 :     bool coordsAllInsideSrcRect = !paint.isAntiAlias() && !mf;
     182             : 
     183             :     // Check for optimization to drop the src rect constraint when on bilerp.
     184           0 :     if (filterMode && GrSamplerParams::kBilerp_FilterMode == *filterMode &&
     185           0 :         GrTextureAdjuster::kYes_FilterConstraint == constraintMode && coordsAllInsideSrcRect) {
     186             :         SkMatrix combinedMatrix;
     187           0 :         combinedMatrix.setConcat(viewMatrix, srcToDstMatrix);
     188           0 :         if (can_ignore_bilerp_constraint(*producer, clippedSrcRect, combinedMatrix,
     189           0 :                                          fRenderTargetContext->isUnifiedMultisampled())) {
     190           0 :             constraintMode = GrTextureAdjuster::kNo_FilterConstraint;
     191             :         }
     192             :     }
     193             : 
     194             :     const SkMatrix* textureMatrix;
     195             :     SkMatrix tempMatrix;
     196           0 :     if (canUseTextureCoordsAsLocalCoords) {
     197           0 :         textureMatrix = &SkMatrix::I();
     198             :     } else {
     199           0 :         if (!srcToDstMatrix.invert(&tempMatrix)) {
     200           0 :             return;
     201             :         }
     202           0 :         textureMatrix = &tempMatrix;
     203             :     }
     204             :     sk_sp<GrFragmentProcessor> fp(producer->createFragmentProcessor(
     205             :         *textureMatrix, clippedSrcRect, constraintMode, coordsAllInsideSrcRect, filterMode,
     206           0 :         fRenderTargetContext->getColorSpace()));
     207           0 :     if (!fp) {
     208           0 :         return;
     209             :     }
     210             : 
     211           0 :     GrPaint grPaint;
     212           0 :     if (!SkPaintToGrPaintWithTexture(fContext.get(), fRenderTargetContext.get(), paint, viewMatrix,
     213           0 :                                      fp, producer->isAlphaOnly(), &grPaint)) {
     214           0 :         return;
     215             :     }
     216           0 :     GrAA aa = GrBoolToAA(paint.isAntiAlias());
     217           0 :     if (canUseTextureCoordsAsLocalCoords) {
     218           0 :         fRenderTargetContext->fillRectToRect(clip, std::move(grPaint), aa, viewMatrix,
     219           0 :                                              clippedDstRect, clippedSrcRect);
     220           0 :         return;
     221             :     }
     222             : 
     223           0 :     if (!mf) {
     224           0 :         fRenderTargetContext->drawRect(clip, std::move(grPaint), aa, viewMatrix, clippedDstRect);
     225           0 :         return;
     226             :     }
     227             : 
     228             :     // First see if we can do the draw + mask filter direct to the dst.
     229           0 :     if (viewMatrix.isScaleTranslate()) {
     230             :         SkRect devClippedDstRect;
     231           0 :         viewMatrix.mapRectScaleTranslate(&devClippedDstRect, clippedDstRect);
     232             : 
     233           0 :         SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
     234           0 :         if (mf->directFilterRRectMaskGPU(fContext.get(),
     235             :                                          fRenderTargetContext.get(),
     236           0 :                                          std::move(grPaint),
     237             :                                          clip,
     238             :                                          viewMatrix,
     239             :                                          rec,
     240           0 :                                          SkRRect::MakeRect(clippedDstRect),
     241           0 :                                          SkRRect::MakeRect(devClippedDstRect))) {
     242           0 :             return;
     243             :         }
     244             :     }
     245             : 
     246           0 :     SkPath rectPath;
     247           0 :     rectPath.addRect(clippedDstRect);
     248           0 :     rectPath.setIsVolatile(true);
     249           0 :     GrBlurUtils::drawPathWithMaskFilter(this->context(), fRenderTargetContext.get(), this->clip(),
     250           0 :                                         rectPath, std::move(grPaint), aa, viewMatrix, mf,
     251           0 :                                         GrStyle::SimpleFill(), true);
     252             : }

Generated by: LCOV version 1.13