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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2010 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 "SkGr.h"
       9             : 
      10             : #include "GrBitmapTextureMaker.h"
      11             : #include "GrCaps.h"
      12             : #include "GrContext.h"
      13             : #include "GrGpuResourcePriv.h"
      14             : #include "GrRenderTargetContext.h"
      15             : #include "GrResourceProvider.h"
      16             : #include "GrTextureProxy.h"
      17             : #include "GrTypes.h"
      18             : #include "GrXferProcessor.h"
      19             : 
      20             : #include "SkAutoMalloc.h"
      21             : #include "SkBlendModePriv.h"
      22             : #include "SkCanvas.h"
      23             : #include "SkColorFilter.h"
      24             : #include "SkConvertPixels.h"
      25             : #include "SkData.h"
      26             : #include "SkImageInfoPriv.h"
      27             : #include "SkMaskFilter.h"
      28             : #include "SkMessageBus.h"
      29             : #include "SkMipMap.h"
      30             : #include "SkPM4fPriv.h"
      31             : #include "SkPixelRef.h"
      32             : #include "SkResourceCache.h"
      33             : #include "SkTemplates.h"
      34             : #include "effects/GrBicubicEffect.h"
      35             : #include "effects/GrConstColorProcessor.h"
      36             : #include "effects/GrDitherEffect.h"
      37             : #include "effects/GrPorterDuffXferProcessor.h"
      38             : #include "effects/GrXfermodeFragmentProcessor.h"
      39             : 
      40             : #ifndef SK_IGNORE_ETC1_SUPPORT
      41             : #  include "etc1.h"
      42             : #endif
      43             : 
      44           0 : GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info, const GrCaps& caps) {
      45           0 :     GrSurfaceDesc desc;
      46           0 :     desc.fFlags = kNone_GrSurfaceFlags;
      47           0 :     desc.fWidth = info.width();
      48           0 :     desc.fHeight = info.height();
      49           0 :     desc.fConfig = SkImageInfo2GrPixelConfig(info, caps);
      50           0 :     desc.fSampleCnt = 0;
      51           0 :     return desc;
      52             : }
      53             : 
      54           0 : void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
      55           0 :     SkASSERT(key);
      56           0 :     SkASSERT(imageID);
      57           0 :     SkASSERT(!imageBounds.isEmpty());
      58           0 :     static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
      59           0 :     GrUniqueKey::Builder builder(key, kImageIDDomain, 5);
      60           0 :     builder[0] = imageID;
      61           0 :     builder[1] = imageBounds.fLeft;
      62           0 :     builder[2] = imageBounds.fTop;
      63           0 :     builder[3] = imageBounds.fRight;
      64           0 :     builder[4] = imageBounds.fBottom;
      65           0 : }
      66             : 
      67           0 : GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
      68             :                                                  int expectedW, int expectedH,
      69             :                                                  const void** outStartOfDataToUpload) {
      70           0 :     *outStartOfDataToUpload = nullptr;
      71             : #ifndef SK_IGNORE_ETC1_SUPPORT
      72             :     if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) {
      73             :         return kUnknown_GrPixelConfig;
      74             :     }
      75             : 
      76             :     const uint8_t* bytes = data->bytes();
      77             :     if (data->size() > ETC_PKM_HEADER_SIZE && etc1_pkm_is_valid(bytes)) {
      78             :         // Does the data match the dimensions of the bitmap? If not,
      79             :         // then we don't know how to scale the image to match it...
      80             :         if (etc1_pkm_get_width(bytes) != (unsigned)expectedW ||
      81             :             etc1_pkm_get_height(bytes) != (unsigned)expectedH)
      82             :         {
      83             :             return kUnknown_GrPixelConfig;
      84             :         }
      85             : 
      86             :         *outStartOfDataToUpload = bytes + ETC_PKM_HEADER_SIZE;
      87             :         return kETC1_GrPixelConfig;
      88             :     }
      89             : #endif
      90           0 :     return kUnknown_GrPixelConfig;
      91             : }
      92             : 
      93             : //////////////////////////////////////////////////////////////////////////////
      94           0 : sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrResourceProvider* resourceProvider,
      95             :                                                    const SkBitmap& bitmap) {
      96           0 :     SkAutoLockPixels alp(bitmap);
      97           0 :     if (!bitmap.readyToDraw()) {
      98           0 :         return nullptr;
      99             :     }
     100           0 :     SkPixmap pixmap;
     101           0 :     if (!bitmap.peekPixels(&pixmap)) {
     102           0 :         return nullptr;
     103             :     }
     104           0 :     return GrUploadPixmapToTextureProxy(resourceProvider, pixmap, SkBudgeted::kYes);
     105             : }
     106             : 
     107           0 : static const SkPixmap* compute_desc(const GrCaps& caps, const SkPixmap& pixmap,
     108             :                                     GrSurfaceDesc* desc,
     109             :                                     SkBitmap* tmpBitmap, SkPixmap* tmpPixmap) {
     110           0 :     const SkPixmap* pmap = &pixmap;
     111             : 
     112           0 :     *desc = GrImageInfoToSurfaceDesc(pixmap.info(), caps);
     113             : 
     114             :     // TODO: We're checking for srgbSupport, but we can then end up picking sBGRA as our pixel
     115             :     // config (which may not be supported). We need better fallback management here.
     116           0 :     SkColorSpace* colorSpace = pixmap.colorSpace();
     117             : 
     118           0 :     if (caps.srgbSupport() &&
     119           0 :         colorSpace && colorSpace->gammaCloseToSRGB() && !GrPixelConfigIsSRGB(desc->fConfig)) {
     120             :         // We were supplied an sRGB-like color space, but we don't have a suitable pixel config.
     121             :         // Convert to 8888 sRGB so we can handle the data correctly. The raster backend doesn't
     122             :         // handle sRGB Index8 -> sRGB 8888 correctly (yet), so lie about both the source and
     123             :         // destination (claim they're linear):
     124             :         SkImageInfo linSrcInfo = SkImageInfo::Make(pixmap.width(), pixmap.height(),
     125           0 :                                                    pixmap.colorType(), pixmap.alphaType());
     126           0 :         SkPixmap linSrcPixmap(linSrcInfo, pixmap.addr(), pixmap.rowBytes(), pixmap.ctable());
     127             : 
     128             :         SkImageInfo dstInfo = SkImageInfo::Make(pixmap.width(), pixmap.height(),
     129             :                                                 kN32_SkColorType, kPremul_SkAlphaType,
     130           0 :                                                 pixmap.info().refColorSpace());
     131             : 
     132           0 :         tmpBitmap->allocPixels(dstInfo);
     133             : 
     134           0 :         SkImageInfo linDstInfo = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height());
     135           0 :         if (!linSrcPixmap.readPixels(linDstInfo, tmpBitmap->getPixels(), tmpBitmap->rowBytes())) {
     136           0 :             return nullptr;
     137             :         }
     138           0 :         if (!tmpBitmap->peekPixels(tmpPixmap)) {
     139           0 :             return nullptr;
     140             :         }
     141           0 :         pmap = tmpPixmap;
     142             :         // must rebuild desc, since we've forced the info to be N32
     143           0 :         *desc = GrImageInfoToSurfaceDesc(pmap->info(), caps);
     144           0 :     } else if (kIndex_8_SkColorType == pixmap.colorType()) {
     145           0 :         SkImageInfo info = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height());
     146           0 :         tmpBitmap->allocPixels(info);
     147           0 :         if (!pixmap.readPixels(info, tmpBitmap->getPixels(), tmpBitmap->rowBytes())) {
     148           0 :             return nullptr;
     149             :         }
     150           0 :         if (!tmpBitmap->peekPixels(tmpPixmap)) {
     151           0 :             return nullptr;
     152             :         }
     153           0 :         pmap = tmpPixmap;
     154             :         // must rebuild desc, since we've forced the info to be N32
     155           0 :         *desc = GrImageInfoToSurfaceDesc(pmap->info(), caps);
     156             :     }
     157             : 
     158           0 :     return pmap;
     159             : }
     160             : 
     161           0 : sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxyNoCheck(GrResourceProvider* resourceProvider,
     162             :                                                           const SkPixmap& pixmap,
     163             :                                                           SkBudgeted budgeted) {
     164           0 :     SkBitmap tmpBitmap;
     165           0 :     SkPixmap tmpPixmap;
     166           0 :     GrSurfaceDesc desc;
     167             : 
     168           0 :     if (const SkPixmap* pmap = compute_desc(*resourceProvider->caps(), pixmap, &desc,
     169           0 :                                             &tmpBitmap, &tmpPixmap)) {
     170             :         return GrSurfaceProxy::MakeDeferred(resourceProvider, desc,
     171           0 :                                             budgeted, pmap->addr(), pmap->rowBytes());
     172             :     }
     173             : 
     174           0 :     return nullptr;
     175             : }
     176             : 
     177           0 : sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxy(GrResourceProvider* resourceProvider,
     178             :                                                    const SkPixmap& pixmap,
     179             :                                                    SkBudgeted budgeted) {
     180           0 :     if (!SkImageInfoIsValid(pixmap.info())) {
     181           0 :         return nullptr;
     182             :     }
     183             : 
     184           0 :     return GrUploadPixmapToTextureProxyNoCheck(resourceProvider, pixmap, budgeted);
     185             : }
     186             : 
     187             : ////////////////////////////////////////////////////////////////////////////////
     188             : 
     189           0 : void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef) {
     190           0 :     class Invalidator : public SkPixelRef::GenIDChangeListener {
     191             :     public:
     192           0 :         explicit Invalidator(const GrUniqueKey& key) : fMsg(key) {}
     193             :     private:
     194             :         GrUniqueKeyInvalidatedMessage fMsg;
     195             : 
     196           0 :         void onChange() override { SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); }
     197             :     };
     198             : 
     199           0 :     pixelRef->addGenIDChangeListener(new Invalidator(key));
     200           0 : }
     201             : 
     202           0 : sk_sp<GrTextureProxy> GrGenerateMipMapsAndUploadToTextureProxy(GrContext* ctx,
     203             :                                                                const SkBitmap& bitmap,
     204             :                                                                SkColorSpace* dstColorSpace) {
     205             :     SkDestinationSurfaceColorMode colorMode = dstColorSpace
     206           0 :         ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
     207           0 :         : SkDestinationSurfaceColorMode::kLegacy;
     208             : 
     209           0 :     if (!SkImageInfoIsValid(bitmap.info())) {
     210           0 :         return nullptr;
     211             :     }
     212             : 
     213           0 :     GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info(), *ctx->caps());
     214             : 
     215           0 :     SkAutoPixmapUnlock srcUnlocker;
     216           0 :     if (!bitmap.requestLock(&srcUnlocker)) {
     217           0 :         return nullptr;
     218             :     }
     219           0 :     const SkPixmap& pixmap = srcUnlocker.pixmap();
     220             :     // Try to catch where we might have returned nullptr for src crbug.com/492818
     221           0 :     if (nullptr == pixmap.addr()) {
     222           0 :         sk_throw();
     223             :     }
     224             : 
     225           0 :     std::unique_ptr<SkMipMap> mipmaps(SkMipMap::Build(pixmap, colorMode, nullptr));
     226           0 :     if (!mipmaps) {
     227           0 :         return nullptr;
     228             :     }
     229             : 
     230           0 :     const int mipLevelCount = mipmaps->countLevels() + 1;
     231           0 :     if (mipLevelCount < 1) {
     232           0 :         return nullptr;
     233             :     }
     234             : 
     235           0 :     const bool isMipMapped = mipLevelCount > 1;
     236           0 :     desc.fIsMipMapped = isMipMapped;
     237             : 
     238           0 :     std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
     239             : 
     240           0 :     texels[0].fPixels = pixmap.addr();
     241           0 :     texels[0].fRowBytes = pixmap.rowBytes();
     242             : 
     243           0 :     for (int i = 1; i < mipLevelCount; ++i) {
     244           0 :         SkMipMap::Level generatedMipLevel;
     245           0 :         mipmaps->getLevel(i - 1, &generatedMipLevel);
     246           0 :         texels[i].fPixels = generatedMipLevel.fPixmap.addr();
     247           0 :         texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
     248             :     }
     249             : 
     250             :     return ctx->resourceProvider()->createMipMappedTexture(desc,
     251             :                                                            SkBudgeted::kYes,
     252           0 :                                                            texels.get(),
     253             :                                                            mipLevelCount,
     254           0 :                                                            0, colorMode);
     255             : }
     256             : 
     257           0 : sk_sp<GrTextureProxy> GrUploadMipMapToTextureProxy(GrContext* ctx, const SkImageInfo& info,
     258             :                                                    const GrMipLevel* texels,
     259             :                                                    int mipLevelCount,
     260             :                                                    SkDestinationSurfaceColorMode colorMode) {
     261           0 :     if (!SkImageInfoIsValid(info)) {
     262           0 :         return nullptr;
     263             :     }
     264             : 
     265           0 :     const GrCaps* caps = ctx->caps();
     266           0 :     return ctx->resourceProvider()->createMipMappedTexture(GrImageInfoToSurfaceDesc(info, *caps),
     267             :                                                            SkBudgeted::kYes, texels,
     268           0 :                                                            mipLevelCount, 0, colorMode);
     269             : }
     270             : 
     271           0 : sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrContext* ctx,
     272             :                                                     const SkBitmap& bitmap,
     273             :                                                     const GrSamplerParams& params,
     274             :                                                     SkScalar scaleAdjust[2]) {
     275             :     // Caller doesn't care about the texture's color space (they can always get it from the bitmap)
     276           0 :     return GrBitmapTextureMaker(ctx, bitmap).refTextureProxyForParams(params, nullptr,
     277           0 :                                                                       nullptr, scaleAdjust);
     278             : }
     279             : 
     280           0 : sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrResourceProvider* resourceProvider,
     281             :                                               const SkBitmap& bitmap) {
     282           0 :     GrUniqueKey originalKey;
     283             : 
     284           0 :     if (!bitmap.isVolatile()) {
     285           0 :         SkIPoint origin = bitmap.pixelRefOrigin();
     286           0 :         SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(), bitmap.height());
     287           0 :         GrMakeKeyFromImageID(&originalKey, bitmap.pixelRef()->getGenerationID(), subset);
     288             :     }
     289             : 
     290           0 :     sk_sp<GrTextureProxy> proxy;
     291             : 
     292           0 :     if (originalKey.isValid()) {
     293           0 :         proxy = resourceProvider->findProxyByUniqueKey(originalKey);
     294             :     }
     295           0 :     if (!proxy) {
     296           0 :         proxy = GrUploadBitmapToTextureProxy(resourceProvider, bitmap);
     297           0 :         if (proxy && originalKey.isValid()) {
     298           0 :             resourceProvider->assignUniqueKeyToProxy(originalKey, proxy.get());
     299             :             // MDB TODO (caching): this has to play nice with the GrSurfaceProxy's caching
     300           0 :             GrInstallBitmapUniqueKeyInvalidator(originalKey, bitmap.pixelRef());
     301             :         }
     302             :     }
     303             : 
     304           0 :     return proxy;
     305             : }
     306             : 
     307             : ///////////////////////////////////////////////////////////////////////////////
     308             : 
     309           0 : GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
     310             :     // We want to premultiply after linearizing, so this is easy:
     311           0 :     return SkColorToUnpremulGrColor4f(c, dstColorSpace).premul();
     312             : }
     313             : 
     314           0 : GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace) {
     315           0 :     if (dstColorSpace) {
     316           0 :         auto srgbColorSpace = SkColorSpace::MakeSRGB();
     317           0 :         auto gamutXform = GrColorSpaceXform::Make(srgbColorSpace.get(), dstColorSpace);
     318           0 :         return SkColorToUnpremulGrColor4f(c, dstColorSpace, gamutXform.get());
     319             :     } else {
     320           0 :         return SkColorToUnpremulGrColor4f(c, nullptr, nullptr);
     321             :     }
     322             : }
     323             : 
     324           0 : GrColor4f SkColorToPremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
     325             :                                    GrColorSpaceXform* gamutXform) {
     326             :     // We want to premultiply after linearizing, so this is easy:
     327           0 :     return SkColorToUnpremulGrColor4f(c, dstColorSpace, gamutXform).premul();
     328             : }
     329             : 
     330           0 : GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace,
     331             :                                      GrColorSpaceXform* gamutXform) {
     332             :     // You can't be color-space aware in legacy mode
     333           0 :     SkASSERT(dstColorSpace || !gamutXform);
     334             : 
     335           0 :     GrColor4f color;
     336           0 :     if (dstColorSpace) {
     337             :         // SkColor4f::FromColor does sRGB -> Linear
     338           0 :         color = GrColor4f::FromSkColor4f(SkColor4f::FromColor(c));
     339             :     } else {
     340             :         // GrColor4f::FromGrColor just multiplies by 1/255
     341           0 :         color = GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c));
     342             :     }
     343             : 
     344           0 :     if (gamutXform) {
     345           0 :         color = gamutXform->apply(color);
     346             :     }
     347             : 
     348           0 :     return color;
     349             : }
     350             : 
     351             : ///////////////////////////////////////////////////////////////////////////////
     352             : 
     353           0 : GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps) {
     354             :     // We intentionally ignore profile type for non-8888 formats. Anything we can't support
     355             :     // in hardware will be expanded to sRGB 8888 in GrUploadPixmapToTexture.
     356           0 :     SkColorSpace* cs = info.colorSpace();
     357           0 :     switch (info.colorType()) {
     358             :         case kUnknown_SkColorType:
     359           0 :             return kUnknown_GrPixelConfig;
     360             :         case kAlpha_8_SkColorType:
     361           0 :             return kAlpha_8_GrPixelConfig;
     362             :         case kRGB_565_SkColorType:
     363           0 :             return kRGB_565_GrPixelConfig;
     364             :         case kARGB_4444_SkColorType:
     365           0 :             return kRGBA_4444_GrPixelConfig;
     366             :         case kRGBA_8888_SkColorType:
     367           0 :             return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
     368           0 :                    ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
     369             :         case kBGRA_8888_SkColorType:
     370           0 :             return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
     371           0 :                    ? kSBGRA_8888_GrPixelConfig : kBGRA_8888_GrPixelConfig;
     372             :         case kIndex_8_SkColorType:
     373           0 :             return kSkia8888_GrPixelConfig;
     374             :         case kGray_8_SkColorType:
     375           0 :             return kGray_8_GrPixelConfig;
     376             :         case kRGBA_F16_SkColorType:
     377           0 :             return kRGBA_half_GrPixelConfig;
     378             :     }
     379           0 :     SkASSERT(0);    // shouldn't get here
     380           0 :     return kUnknown_GrPixelConfig;
     381             : }
     382             : 
     383           0 : bool GrPixelConfigToColorType(GrPixelConfig config, SkColorType* ctOut) {
     384             :     SkColorType ct;
     385           0 :     switch (config) {
     386             :         case kAlpha_8_GrPixelConfig:
     387           0 :             ct = kAlpha_8_SkColorType;
     388           0 :             break;
     389             :         case kGray_8_GrPixelConfig:
     390           0 :             ct = kGray_8_SkColorType;
     391           0 :             break;
     392             :         case kRGB_565_GrPixelConfig:
     393           0 :             ct = kRGB_565_SkColorType;
     394           0 :             break;
     395             :         case kRGBA_4444_GrPixelConfig:
     396           0 :             ct = kARGB_4444_SkColorType;
     397           0 :             break;
     398             :         case kRGBA_8888_GrPixelConfig:
     399           0 :             ct = kRGBA_8888_SkColorType;
     400           0 :             break;
     401             :         case kBGRA_8888_GrPixelConfig:
     402           0 :             ct = kBGRA_8888_SkColorType;
     403           0 :             break;
     404             :         case kSRGBA_8888_GrPixelConfig:
     405           0 :             ct = kRGBA_8888_SkColorType;
     406           0 :             break;
     407             :         case kSBGRA_8888_GrPixelConfig:
     408           0 :             ct = kBGRA_8888_SkColorType;
     409           0 :             break;
     410             :         case kRGBA_half_GrPixelConfig:
     411           0 :             ct = kRGBA_F16_SkColorType;
     412           0 :             break;
     413             :         default:
     414           0 :             return false;
     415             :     }
     416           0 :     if (ctOut) {
     417           0 :         *ctOut = ct;
     418             :     }
     419           0 :     return true;
     420             : }
     421             : 
     422           0 : GrPixelConfig GrRenderableConfigForColorSpace(const SkColorSpace* colorSpace) {
     423           0 :     if (!colorSpace) {
     424           0 :         return kRGBA_8888_GrPixelConfig;
     425           0 :     } else if (colorSpace->gammaIsLinear()) {
     426           0 :         return kRGBA_half_GrPixelConfig;
     427           0 :     } else if (colorSpace->gammaCloseToSRGB()) {
     428           0 :         return kSRGBA_8888_GrPixelConfig;
     429             :     } else {
     430           0 :         SkDEBUGFAIL("No renderable config exists for color space with strange gamma");
     431           0 :         return kUnknown_GrPixelConfig;
     432             :     }
     433             : }
     434             : 
     435             : ////////////////////////////////////////////////////////////////////////////////////////////////
     436             : 
     437           0 : static inline bool blend_requires_shader(const SkBlendMode mode, bool primitiveIsSrc) {
     438           0 :     if (primitiveIsSrc) {
     439           0 :         return SkBlendMode::kSrc != mode;
     440             :     } else {
     441           0 :         return SkBlendMode::kDst != mode;
     442             :     }
     443             : }
     444             : 
     445           0 : static inline bool skpaint_to_grpaint_impl(GrContext* context,
     446             :                                            GrRenderTargetContext* rtc,
     447             :                                            const SkPaint& skPaint,
     448             :                                            const SkMatrix& viewM,
     449             :                                            sk_sp<GrFragmentProcessor>* shaderProcessor,
     450             :                                            SkBlendMode* primColorMode,
     451             :                                            bool primitiveIsSrc,
     452             :                                            GrPaint* grPaint) {
     453           0 :     grPaint->setAllowSRGBInputs(rtc->isGammaCorrect());
     454             : 
     455             :     // Convert SkPaint color to 4f format, including optional linearizing and gamut conversion.
     456             :     GrColor4f origColor = SkColorToUnpremulGrColor4f(skPaint.getColor(), rtc->getColorSpace(),
     457           0 :                                                      rtc->getColorXformFromSRGB());
     458             : 
     459             :     // Setup the initial color considering the shader, the SkPaint color, and the presence or not
     460             :     // of per-vertex colors.
     461           0 :     sk_sp<GrFragmentProcessor> shaderFP;
     462           0 :     if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc)) {
     463           0 :         if (shaderProcessor) {
     464           0 :             shaderFP = *shaderProcessor;
     465           0 :         } else if (const SkShader* shader = skPaint.getShader()) {
     466           0 :             shaderFP = shader->asFragmentProcessor(SkShader::AsFPArgs(context, &viewM, nullptr,
     467             :                                                                       skPaint.getFilterQuality(),
     468           0 :                                                                       rtc->getColorSpace()));
     469           0 :             if (!shaderFP) {
     470           0 :                 return false;
     471             :             }
     472             :         }
     473             :     }
     474             : 
     475             :     // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
     476             :     // a known constant value. In that case we can simply apply a color filter during this
     477             :     // conversion without converting the color filter to a GrFragmentProcessor.
     478           0 :     bool applyColorFilterToPaintColor = false;
     479           0 :     if (shaderFP) {
     480           0 :         if (primColorMode) {
     481             :             // There is a blend between the primitive color and the shader color. The shader sees
     482             :             // the opaque paint color. The shader's output is blended using the provided mode by
     483             :             // the primitive color. The blended color is then modulated by the paint's alpha.
     484             : 
     485             :             // The geometry processor will insert the primitive color to start the color chain, so
     486             :             // the GrPaint color will be ignored.
     487             : 
     488           0 :             GrColor4f shaderInput = origColor.opaque();
     489           0 :             shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput);
     490           0 :             if (primitiveIsSrc) {
     491           0 :                 shaderFP = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(shaderFP),
     492           0 :                                                                              *primColorMode);
     493             :             } else {
     494           0 :                 shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP),
     495           0 :                                                                              *primColorMode);
     496             :             }
     497             :             // The above may return null if compose results in a pass through of the prim color.
     498           0 :             if (shaderFP) {
     499           0 :                 grPaint->addColorFragmentProcessor(shaderFP);
     500             :             }
     501             : 
     502             :             // We can ignore origColor here - alpha is unchanged by gamma
     503           0 :             GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
     504           0 :             if (GrColor_WHITE != paintAlpha) {
     505             :                 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
     506             :                 // color channels. It's value should be treated as the same in ANY color space.
     507           0 :                 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
     508             :                     GrColor4f::FromGrColor(paintAlpha),
     509           0 :                     GrConstColorProcessor::kModulateRGBA_InputMode));
     510             :             }
     511             :         } else {
     512             :             // The shader's FP sees the paint unpremul color
     513           0 :             grPaint->setColor4f(origColor);
     514           0 :             grPaint->addColorFragmentProcessor(std::move(shaderFP));
     515             :         }
     516             :     } else {
     517           0 :         if (primColorMode) {
     518             :             // There is a blend between the primitive color and the paint color. The blend considers
     519             :             // the opaque paint color. The paint's alpha is applied to the post-blended color.
     520             :             sk_sp<GrFragmentProcessor> processor(
     521             :                 GrConstColorProcessor::Make(origColor.opaque(),
     522           0 :                                             GrConstColorProcessor::kIgnore_InputMode));
     523           0 :             if (primitiveIsSrc) {
     524           0 :                 processor = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(processor),
     525           0 :                                                                               *primColorMode);
     526             :             } else {
     527           0 :                 processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
     528           0 :                                                                               *primColorMode);
     529             :             }
     530           0 :             if (processor) {
     531           0 :                 grPaint->addColorFragmentProcessor(std::move(processor));
     532             :             }
     533             : 
     534           0 :             grPaint->setColor4f(origColor.opaque());
     535             : 
     536             :             // We can ignore origColor here - alpha is unchanged by gamma
     537           0 :             GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
     538           0 :             if (GrColor_WHITE != paintAlpha) {
     539             :                 // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
     540             :                 // color channels. It's value should be treated as the same in ANY color space.
     541           0 :                 grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
     542             :                     GrColor4f::FromGrColor(paintAlpha),
     543           0 :                     GrConstColorProcessor::kModulateRGBA_InputMode));
     544             :             }
     545             :         } else {
     546             :             // No shader, no primitive color.
     547           0 :             grPaint->setColor4f(origColor.premul());
     548           0 :             applyColorFilterToPaintColor = true;
     549             :         }
     550             :     }
     551             : 
     552           0 :     SkColorFilter* colorFilter = skPaint.getColorFilter();
     553           0 :     if (colorFilter) {
     554           0 :         if (applyColorFilterToPaintColor) {
     555             :             // If we're in legacy mode, we *must* avoid using the 4f version of the color filter,
     556             :             // because that will combine with the linearized version of the stored color.
     557           0 :             if (rtc->isGammaCorrect()) {
     558           0 :                 grPaint->setColor4f(GrColor4f::FromSkColor4f(
     559           0 :                     colorFilter->filterColor4f(origColor.toSkColor4f())).premul());
     560             :             } else {
     561           0 :                 grPaint->setColor4f(SkColorToPremulGrColor4f(
     562           0 :                     colorFilter->filterColor(skPaint.getColor()), nullptr, nullptr));
     563             :             }
     564             :         } else {
     565             :             sk_sp<GrFragmentProcessor> cfFP(colorFilter->asFragmentProcessor(context,
     566           0 :                                                                              rtc->getColorSpace()));
     567           0 :             if (cfFP) {
     568           0 :                 grPaint->addColorFragmentProcessor(std::move(cfFP));
     569             :             } else {
     570           0 :                 return false;
     571             :             }
     572             :         }
     573             :     }
     574             : 
     575           0 :     SkMaskFilter* maskFilter = skPaint.getMaskFilter();
     576           0 :     if (maskFilter) {
     577             :         GrFragmentProcessor* mfFP;
     578           0 :         if (maskFilter->asFragmentProcessor(&mfFP, nullptr, viewM)) {
     579           0 :             grPaint->addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor>(mfFP));
     580             :         }
     581             :     }
     582             : 
     583             :     // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on
     584             :     // the GrPaint to also be null (also kSrcOver).
     585           0 :     SkASSERT(!grPaint->getXPFactory());
     586           0 :     if (!skPaint.isSrcOver()) {
     587           0 :         grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode()));
     588             :     }
     589             : 
     590             : #ifndef SK_IGNORE_GPU_DITHER
     591           0 :     if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0 && !rtc->isGammaCorrect()) {
     592           0 :         grPaint->addColorFragmentProcessor(GrDitherEffect::Make());
     593             :     }
     594             : #endif
     595           0 :     return true;
     596             : }
     597             : 
     598           0 : bool SkPaintToGrPaint(GrContext* context, GrRenderTargetContext* rtc, const SkPaint& skPaint,
     599             :                       const SkMatrix& viewM, GrPaint* grPaint) {
     600           0 :     return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, nullptr, false, grPaint);
     601             : }
     602             : 
     603             : /** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
     604           0 : bool SkPaintToGrPaintReplaceShader(GrContext* context,
     605             :                                    GrRenderTargetContext* rtc,
     606             :                                    const SkPaint& skPaint,
     607             :                                    sk_sp<GrFragmentProcessor> shaderFP,
     608             :                                    GrPaint* grPaint) {
     609           0 :     if (!shaderFP) {
     610           0 :         return false;
     611             :     }
     612           0 :     return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), &shaderFP, nullptr, false,
     613           0 :                                    grPaint);
     614             : }
     615             : 
     616             : /** Ignores the SkShader (if any) on skPaint. */
     617           0 : bool SkPaintToGrPaintNoShader(GrContext* context,
     618             :                               GrRenderTargetContext* rtc,
     619             :                               const SkPaint& skPaint,
     620             :                               GrPaint* grPaint) {
     621             :     // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
     622           0 :     static sk_sp<GrFragmentProcessor> kNullShaderFP(nullptr);
     623             :     static sk_sp<GrFragmentProcessor>* kIgnoreShader = &kNullShaderFP;
     624           0 :     return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), kIgnoreShader, nullptr,
     625           0 :                                    false, grPaint);
     626             : }
     627             : 
     628             : /** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
     629             : be setup as a vertex attribute using the specified SkBlendMode. */
     630           0 : bool SkPaintToGrPaintWithXfermode(GrContext* context,
     631             :                                   GrRenderTargetContext* rtc,
     632             :                                   const SkPaint& skPaint,
     633             :                                   const SkMatrix& viewM,
     634             :                                   SkBlendMode primColorMode,
     635             :                                   bool primitiveIsSrc,
     636             :                                   GrPaint* grPaint) {
     637           0 :     return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, &primColorMode,
     638           0 :                                    primitiveIsSrc, grPaint);
     639             : }
     640             : 
     641           0 : bool SkPaintToGrPaintWithTexture(GrContext* context,
     642             :                                  GrRenderTargetContext* rtc,
     643             :                                  const SkPaint& paint,
     644             :                                  const SkMatrix& viewM,
     645             :                                  sk_sp<GrFragmentProcessor> fp,
     646             :                                  bool textureIsAlphaOnly,
     647             :                                  GrPaint* grPaint) {
     648           0 :     sk_sp<GrFragmentProcessor> shaderFP;
     649           0 :     if (textureIsAlphaOnly) {
     650           0 :         if (const SkShader* shader = paint.getShader()) {
     651           0 :             shaderFP = shader->asFragmentProcessor(SkShader::AsFPArgs(context,
     652             :                                                                       &viewM,
     653             :                                                                       nullptr,
     654             :                                                                       paint.getFilterQuality(),
     655           0 :                                                                       rtc->getColorSpace()));
     656           0 :             if (!shaderFP) {
     657           0 :                 return false;
     658             :             }
     659           0 :             sk_sp<GrFragmentProcessor> fpSeries[] = { std::move(shaderFP), std::move(fp) };
     660           0 :             shaderFP = GrFragmentProcessor::RunInSeries(fpSeries, 2);
     661             :         } else {
     662           0 :             shaderFP = GrFragmentProcessor::MakeInputPremulAndMulByOutput(fp);
     663             :         }
     664             :     } else {
     665           0 :         shaderFP = GrFragmentProcessor::MulOutputByInputAlpha(fp);
     666             :     }
     667             : 
     668           0 :     return SkPaintToGrPaintReplaceShader(context, rtc, paint, std::move(shaderFP), grPaint);
     669             : }
     670             : 
     671             : 
     672             : ////////////////////////////////////////////////////////////////////////////////////////////////
     673             : 
     674           0 : GrSamplerParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality paintFilterQuality,
     675             :                                                             const SkMatrix& viewM,
     676             :                                                             const SkMatrix& localM,
     677             :                                                             bool* doBicubic) {
     678           0 :     *doBicubic = false;
     679             :     GrSamplerParams::FilterMode textureFilterMode;
     680           0 :     switch (paintFilterQuality) {
     681             :         case kNone_SkFilterQuality:
     682           0 :             textureFilterMode = GrSamplerParams::kNone_FilterMode;
     683           0 :             break;
     684             :         case kLow_SkFilterQuality:
     685           0 :             textureFilterMode = GrSamplerParams::kBilerp_FilterMode;
     686           0 :             break;
     687             :         case kMedium_SkFilterQuality: {
     688             :             SkMatrix matrix;
     689           0 :             matrix.setConcat(viewM, localM);
     690           0 :             if (matrix.getMinScale() < SK_Scalar1) {
     691           0 :                 textureFilterMode = GrSamplerParams::kMipMap_FilterMode;
     692             :             } else {
     693             :                 // Don't trigger MIP level generation unnecessarily.
     694           0 :                 textureFilterMode = GrSamplerParams::kBilerp_FilterMode;
     695             :             }
     696           0 :             break;
     697             :         }
     698             :         case kHigh_SkFilterQuality: {
     699             :             SkMatrix matrix;
     700           0 :             matrix.setConcat(viewM, localM);
     701           0 :             *doBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
     702           0 :             break;
     703             :         }
     704             :         default:
     705             :             // Should be unreachable.  If not, fall back to mipmaps.
     706           0 :             textureFilterMode = GrSamplerParams::kMipMap_FilterMode;
     707           0 :             break;
     708             : 
     709             :     }
     710           0 :     return textureFilterMode;
     711             : }

Generated by: LCOV version 1.13