| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkGpuDevice.h" | 8 #include "SkGpuDevice.h" |
| 9 | 9 |
| 10 #include "GrBlurUtils.h" |
| 10 #include "GrContext.h" | 11 #include "GrContext.h" |
| 11 #include "GrDrawContext.h" | 12 #include "GrDrawContext.h" |
| 12 #include "GrGpu.h" | 13 #include "GrGpu.h" |
| 13 #include "GrGpuResourcePriv.h" | 14 #include "GrGpuResourcePriv.h" |
| 14 #include "GrLayerHoister.h" | 15 #include "GrLayerHoister.h" |
| 15 #include "GrRecordReplaceDraw.h" | 16 #include "GrRecordReplaceDraw.h" |
| 16 #include "GrStrokeInfo.h" | 17 #include "GrStrokeInfo.h" |
| 17 #include "GrTextContext.h" | 18 #include "GrTextContext.h" |
| 18 #include "GrTracing.h" | 19 #include "GrTracing.h" |
| 19 #include "SkCanvasPriv.h" | 20 #include "SkCanvasPriv.h" |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 fNeedClear = flags & kNeedClear_Flag; | 161 fNeedClear = flags & kNeedClear_Flag; |
| 161 | 162 |
| 162 fRenderTarget = SkRef(rt); | 163 fRenderTarget = SkRef(rt); |
| 163 | 164 |
| 164 SkImageInfo info = rt->surfacePriv().info().makeWH(width, height); | 165 SkImageInfo info = rt->surfacePriv().info().makeWH(width, height); |
| 165 SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, rt)); | 166 SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, rt)); |
| 166 fLegacyBitmap.setInfo(info); | 167 fLegacyBitmap.setInfo(info); |
| 167 fLegacyBitmap.setPixelRef(pr)->unref(); | 168 fLegacyBitmap.setPixelRef(pr)->unref(); |
| 168 | 169 |
| 169 bool useDFT = fSurfaceProps.isUseDistanceFieldFonts(); | 170 bool useDFT = fSurfaceProps.isUseDistanceFieldFonts(); |
| 170 fTextContext = fContext->createTextContext(fRenderTarget, this, this->getLea
kyProperties(), | 171 fTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProp
erties(), useDFT); |
| 171 useDFT); | |
| 172 fDrawContext.reset(SkRef(fContext->drawContext())); | 172 fDrawContext.reset(SkRef(fContext->drawContext())); |
| 173 } | 173 } |
| 174 | 174 |
| 175 GrRenderTarget* SkGpuDevice::CreateRenderTarget(GrContext* context, SkSurface::B
udgeted budgeted, | 175 GrRenderTarget* SkGpuDevice::CreateRenderTarget(GrContext* context, SkSurface::B
udgeted budgeted, |
| 176 const SkImageInfo& origInfo, int
sampleCount) { | 176 const SkImageInfo& origInfo, int
sampleCount) { |
| 177 if (kUnknown_SkColorType == origInfo.colorType() || | 177 if (kUnknown_SkColorType == origInfo.colorType() || |
| 178 origInfo.width() < 0 || origInfo.height() < 0) { | 178 origInfo.width() < 0 || origInfo.height() < 0) { |
| 179 return NULL; | 179 return NULL; |
| 180 } | 180 } |
| 181 | 181 |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 return; | 619 return; |
| 620 } | 620 } |
| 621 | 621 |
| 622 fDrawContext->drawOval(fRenderTarget, fClip, grPaint, *draw.fMatrix, oval, s
trokeInfo); | 622 fDrawContext->drawOval(fRenderTarget, fClip, grPaint, *draw.fMatrix, oval, s
trokeInfo); |
| 623 } | 623 } |
| 624 | 624 |
| 625 #include "SkMaskFilter.h" | 625 #include "SkMaskFilter.h" |
| 626 | 626 |
| 627 /////////////////////////////////////////////////////////////////////////////// | 627 /////////////////////////////////////////////////////////////////////////////// |
| 628 | 628 |
| 629 // helpers for applying mask filters | 629 static SkBitmap wrap_texture(GrTexture* texture, int width, int height) { |
| 630 namespace { | |
| 631 | |
| 632 // Draw a mask using the supplied paint. Since the coverage/geometry | |
| 633 // is already burnt into the mask this boils down to a rect draw. | |
| 634 // Return true if the mask was successfully drawn. | |
| 635 bool draw_mask(GrDrawContext* drawContext, | |
| 636 GrRenderTarget* rt, | |
| 637 const GrClip& clip, | |
| 638 const SkMatrix& viewMatrix, | |
| 639 const SkRect& maskRect, | |
| 640 GrPaint* grp, | |
| 641 GrTexture* mask) { | |
| 642 SkMatrix matrix; | |
| 643 matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop); | |
| 644 matrix.postIDiv(mask->width(), mask->height()); | |
| 645 | |
| 646 grp->addCoverageProcessor(GrSimpleTextureEffect::Create(mask, matrix, | |
| 647 kDevice_GrCoordSet))
->unref(); | |
| 648 | |
| 649 SkMatrix inverse; | |
| 650 if (!viewMatrix.invert(&inverse)) { | |
| 651 return false; | |
| 652 } | |
| 653 drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), mas
kRect, inverse); | |
| 654 return true; | |
| 655 } | |
| 656 | |
| 657 static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& r
ect) { | |
| 658 return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBo
unds, rect); | |
| 659 } | |
| 660 | |
| 661 bool draw_with_mask_filter(GrDrawContext* drawContext, | |
| 662 GrTextureProvider* textureProvider, | |
| 663 GrRenderTarget* rt, | |
| 664 const GrClip& clipData, | |
| 665 const SkMatrix& viewMatrix, | |
| 666 const SkPath& devPath, | |
| 667 SkMaskFilter* filter, | |
| 668 const SkIRect& clipBounds, | |
| 669 GrPaint* grp, | |
| 670 SkPaint::Style style) { | |
| 671 SkMask srcM, dstM; | |
| 672 | |
| 673 if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM, | |
| 674 SkMask::kComputeBoundsAndRenderImage_CreateMode, sty
le)) { | |
| 675 return false; | |
| 676 } | |
| 677 SkAutoMaskFreeImage autoSrc(srcM.fImage); | |
| 678 | |
| 679 if (!filter->filterMask(&dstM, srcM, viewMatrix, NULL)) { | |
| 680 return false; | |
| 681 } | |
| 682 // this will free-up dstM when we're done (allocated in filterMask()) | |
| 683 SkAutoMaskFreeImage autoDst(dstM.fImage); | |
| 684 | |
| 685 if (clip_bounds_quick_reject(clipBounds, dstM.fBounds)) { | |
| 686 return false; | |
| 687 } | |
| 688 | |
| 689 // we now have a device-aligned 8bit mask in dstM, ready to be drawn using | |
| 690 // the current clip (and identity matrix) and GrPaint settings | |
| 691 GrSurfaceDesc desc; | |
| 692 desc.fWidth = dstM.fBounds.width(); | |
| 693 desc.fHeight = dstM.fBounds.height(); | |
| 694 desc.fConfig = kAlpha_8_GrPixelConfig; | |
| 695 | |
| 696 SkAutoTUnref<GrTexture> texture(textureProvider->refScratchTexture( | |
| 697 desc, GrTextureProvider::kApprox_ScratchTexMatch)); | |
| 698 if (!texture) { | |
| 699 return false; | |
| 700 } | |
| 701 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, | |
| 702 dstM.fImage, dstM.fRowBytes); | |
| 703 | |
| 704 SkRect maskRect = SkRect::Make(dstM.fBounds); | |
| 705 | |
| 706 return draw_mask(drawContext, rt, clipData, viewMatrix, maskRect, grp, textu
re); | |
| 707 } | |
| 708 | |
| 709 // Create a mask of 'devPath' and place the result in 'mask'. | |
| 710 GrTexture* create_mask_GPU(GrContext* context, | |
| 711 const SkRect& maskRect, | |
| 712 const SkPath& devPath, | |
| 713 const GrStrokeInfo& strokeInfo, | |
| 714 bool doAA, | |
| 715 int sampleCnt) { | |
| 716 GrSurfaceDesc desc; | |
| 717 desc.fFlags = kRenderTarget_GrSurfaceFlag; | |
| 718 desc.fWidth = SkScalarCeilToInt(maskRect.width()); | |
| 719 desc.fHeight = SkScalarCeilToInt(maskRect.height()); | |
| 720 desc.fSampleCnt = doAA ? sampleCnt : 0; | |
| 721 // We actually only need A8, but it often isn't supported as a | |
| 722 // render target so default to RGBA_8888 | |
| 723 desc.fConfig = kRGBA_8888_GrPixelConfig; | |
| 724 | |
| 725 if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, | |
| 726 desc.fSampleCnt > 0)) { | |
| 727 desc.fConfig = kAlpha_8_GrPixelConfig; | |
| 728 } | |
| 729 | |
| 730 GrTexture* mask = context->textureProvider()->refScratchTexture( | |
| 731 desc, GrTextureProvider::kApprox_ScratchTexMatch); | |
| 732 if (NULL == mask) { | |
| 733 return NULL; | |
| 734 } | |
| 735 | |
| 736 SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height()); | |
| 737 | |
| 738 GrDrawContext* drawContext = context->drawContext(); | |
| 739 if (!drawContext) { | |
| 740 return NULL; | |
| 741 } | |
| 742 | |
| 743 drawContext->clear(mask->asRenderTarget(), NULL, 0x0, true); | |
| 744 | |
| 745 GrPaint tempPaint; | |
| 746 tempPaint.setAntiAlias(doAA); | |
| 747 tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); | |
| 748 | |
| 749 // setup new clip | |
| 750 GrClip clip(clipRect); | |
| 751 | |
| 752 // Draw the mask into maskTexture with the path's top-left at the origin usi
ng tempPaint. | |
| 753 SkMatrix translate; | |
| 754 translate.setTranslate(-maskRect.fLeft, -maskRect.fTop); | |
| 755 drawContext->drawPath(mask->asRenderTarget(), clip, tempPaint, translate, de
vPath, strokeInfo); | |
| 756 return mask; | |
| 757 } | |
| 758 | |
| 759 SkBitmap wrap_texture(GrTexture* texture, int width, int height) { | |
| 760 SkBitmap result; | 630 SkBitmap result; |
| 761 result.setInfo(SkImageInfo::MakeN32Premul(width, height)); | 631 result.setInfo(SkImageInfo::MakeN32Premul(width, height)); |
| 762 result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unre
f(); | 632 result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unre
f(); |
| 763 return result; | 633 return result; |
| 764 } | 634 } |
| 765 | 635 |
| 766 }; | |
| 767 | |
| 768 void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, | 636 void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, |
| 769 const SkPaint& paint, const SkMatrix* prePathMatrix, | 637 const SkPaint& paint, const SkMatrix* prePathMatrix, |
| 770 bool pathIsMutable) { | 638 bool pathIsMutable) { |
| 771 CHECK_FOR_ANNOTATION(paint); | 639 CHECK_FOR_ANNOTATION(paint); |
| 772 CHECK_SHOULD_DRAW(draw); | 640 CHECK_SHOULD_DRAW(draw); |
| 773 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPath", fContext); | 641 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPath", fContext); |
| 774 | 642 |
| 775 return this->internalDrawPath(origSrcPath, paint, *draw.fMatrix, prePathMatr
ix, | 643 GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext, fRenderTarget, |
| 776 draw.fClip->getBounds(), pathIsMutable); | 644 fClip, origSrcPath, paint, |
| 777 } | 645 *draw.fMatrix, prePathMatrix, |
| 778 | 646 draw.fClip->getBounds(), pathIsMutable); |
| 779 void SkGpuDevice::internalDrawPath(const SkPath& origSrcPath, const SkPaint& pai
nt, | |
| 780 const SkMatrix& origViewMatrix, const SkMatri
x* prePathMatrix, | |
| 781 const SkIRect& clipBounds, bool pathIsMutable
) { | |
| 782 SkASSERT(!pathIsMutable || origSrcPath.isVolatile()); | |
| 783 | |
| 784 GrStrokeInfo strokeInfo(paint); | |
| 785 | |
| 786 // If we have a prematrix, apply it to the path, optimizing for the case | |
| 787 // where the original path can in fact be modified in place (even though | |
| 788 // its parameter type is const). | |
| 789 SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath); | |
| 790 SkTLazy<SkPath> tmpPath; | |
| 791 SkTLazy<SkPath> effectPath; | |
| 792 SkPathEffect* pathEffect = paint.getPathEffect(); | |
| 793 | |
| 794 SkMatrix viewMatrix = origViewMatrix; | |
| 795 | |
| 796 if (prePathMatrix) { | |
| 797 // stroking, path effects, and blurs are supposed to be applied *after*
the prePathMatrix. | |
| 798 // The pre-path-matrix also should not affect shading. | |
| 799 if (NULL == paint.getMaskFilter() && NULL == pathEffect && NULL == paint
.getShader() && | |
| 800 (strokeInfo.isFillStyle() || strokeInfo.isHairlineStyle())) { | |
| 801 viewMatrix.preConcat(*prePathMatrix); | |
| 802 } else { | |
| 803 SkPath* result = pathPtr; | |
| 804 | |
| 805 if (!pathIsMutable) { | |
| 806 result = tmpPath.init(); | |
| 807 result->setIsVolatile(true); | |
| 808 pathIsMutable = true; | |
| 809 } | |
| 810 // should I push prePathMatrix on our MV stack temporarily, instead | |
| 811 // of applying it here? See SkDraw.cpp | |
| 812 pathPtr->transform(*prePathMatrix, result); | |
| 813 pathPtr = result; | |
| 814 } | |
| 815 } | |
| 816 // at this point we're done with prePathMatrix | |
| 817 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) | |
| 818 | |
| 819 GrPaint grPaint; | |
| 820 if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, viewMatrix, true
, &grPaint)) { | |
| 821 return; | |
| 822 } | |
| 823 | |
| 824 const SkRect* cullRect = NULL; // TODO: what is our bounds? | |
| 825 if (!strokeInfo.isDashed() && pathEffect && pathEffect->filterPath(effectPat
h.init(), *pathPtr, | |
| 826 &strokeIn
fo, cullRect)) { | |
| 827 pathPtr = effectPath.get(); | |
| 828 pathIsMutable = true; | |
| 829 } | |
| 830 | |
| 831 if (paint.getMaskFilter()) { | |
| 832 if (!strokeInfo.isHairlineStyle()) { | |
| 833 SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init(); | |
| 834 if (strokeInfo.isDashed()) { | |
| 835 if (pathEffect->filterPath(strokedPath, *pathPtr, &strokeInfo, c
ullRect)) { | |
| 836 pathPtr = strokedPath; | |
| 837 pathIsMutable = true; | |
| 838 } | |
| 839 strokeInfo.removeDash(); | |
| 840 } | |
| 841 if (strokeInfo.applyToPath(strokedPath, *pathPtr)) { | |
| 842 pathPtr = strokedPath; | |
| 843 pathIsMutable = true; | |
| 844 strokeInfo.setFillStyle(); | |
| 845 } | |
| 846 } | |
| 847 | |
| 848 // avoid possibly allocating a new path in transform if we can | |
| 849 SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init(); | |
| 850 if (!pathIsMutable) { | |
| 851 devPathPtr->setIsVolatile(true); | |
| 852 } | |
| 853 | |
| 854 // transform the path into device space | |
| 855 pathPtr->transform(viewMatrix, devPathPtr); | |
| 856 | |
| 857 SkRect maskRect; | |
| 858 if (paint.getMaskFilter()->canFilterMaskGPU(devPathPtr->getBounds(), | |
| 859 clipBounds, | |
| 860 viewMatrix, | |
| 861 &maskRect)) { | |
| 862 SkIRect finalIRect; | |
| 863 maskRect.roundOut(&finalIRect); | |
| 864 if (clip_bounds_quick_reject(clipBounds, finalIRect)) { | |
| 865 // clipped out | |
| 866 return; | |
| 867 } | |
| 868 | |
| 869 if (paint.getMaskFilter()->directFilterMaskGPU(fContext, | |
| 870 fRenderTarget, | |
| 871 &grPaint, | |
| 872 fClip, | |
| 873 viewMatrix, | |
| 874 strokeInfo, | |
| 875 *devPathPtr)) { | |
| 876 // the mask filter was able to draw itself directly, so there's
nothing | |
| 877 // left to do. | |
| 878 return; | |
| 879 } | |
| 880 | |
| 881 | |
| 882 SkAutoTUnref<GrTexture> mask(create_mask_GPU(fContext, | |
| 883 maskRect, | |
| 884 *devPathPtr, | |
| 885 strokeInfo, | |
| 886 grPaint.isAntiAlias(), | |
| 887 fRenderTarget->numSampl
es())); | |
| 888 if (mask) { | |
| 889 GrTexture* filtered; | |
| 890 | |
| 891 if (paint.getMaskFilter()->filterMaskGPU(mask, viewMatrix, maskR
ect, &filtered, true)) { | |
| 892 // filterMaskGPU gives us ownership of a ref to the result | |
| 893 SkAutoTUnref<GrTexture> atu(filtered); | |
| 894 if (draw_mask(fDrawContext, | |
| 895 fRenderTarget, | |
| 896 fClip, | |
| 897 viewMatrix, | |
| 898 maskRect, | |
| 899 &grPaint, | |
| 900 filtered)) { | |
| 901 // This path is completely drawn | |
| 902 return; | |
| 903 } | |
| 904 } | |
| 905 } | |
| 906 } | |
| 907 | |
| 908 // draw the mask on the CPU - this is a fallthrough path in case the | |
| 909 // GPU path fails | |
| 910 SkPaint::Style style = strokeInfo.isHairlineStyle() ? SkPaint::kStroke_S
tyle : | |
| 911 SkPaint::kFill_Sty
le; | |
| 912 draw_with_mask_filter(fDrawContext, fContext->textureProvider(), fRender
Target, | |
| 913 fClip, viewMatrix, *devPathPtr, | |
| 914 paint.getMaskFilter(), clipBounds, &grPaint, style
); | |
| 915 return; | |
| 916 } | |
| 917 | |
| 918 fDrawContext->drawPath(fRenderTarget, fClip, grPaint, viewMatrix, *pathPtr,
strokeInfo); | |
| 919 } | 647 } |
| 920 | 648 |
| 921 static const int kBmpSmallTileSize = 1 << 10; | 649 static const int kBmpSmallTileSize = 1 << 10; |
| 922 | 650 |
| 923 static inline int get_tile_count(const SkIRect& srcRect, int tileSize) { | 651 static inline int get_tile_count(const SkIRect& srcRect, int tileSize) { |
| 924 int tilesX = (srcRect.fRight / tileSize) - (srcRect.fLeft / tileSize) + 1; | 652 int tilesX = (srcRect.fRight / tileSize) - (srcRect.fLeft / tileSize) + 1; |
| 925 int tilesY = (srcRect.fBottom / tileSize) - (srcRect.fTop / tileSize) + 1; | 653 int tilesY = (srcRect.fBottom / tileSize) - (srcRect.fTop / tileSize) + 1; |
| 926 return tilesX * tilesY; | 654 return tilesX * tilesY; |
| 927 } | 655 } |
| 928 | 656 |
| (...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1924 draw.fClip->getBounds()); | 1652 draw.fClip->getBounds()); |
| 1925 } | 1653 } |
| 1926 | 1654 |
| 1927 void SkGpuDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkSca
lar x, SkScalar y, | 1655 void SkGpuDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkSca
lar x, SkScalar y, |
| 1928 const SkPaint& paint, SkDrawFilter* drawFilter) { | 1656 const SkPaint& paint, SkDrawFilter* drawFilter) { |
| 1929 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawTextBlob", fContext); | 1657 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawTextBlob", fContext); |
| 1930 CHECK_SHOULD_DRAW(draw); | 1658 CHECK_SHOULD_DRAW(draw); |
| 1931 | 1659 |
| 1932 SkDEBUGCODE(this->validate();) | 1660 SkDEBUGCODE(this->validate();) |
| 1933 | 1661 |
| 1934 fTextContext->drawTextBlob(fRenderTarget, fClip, paint, *draw.fMatrix, blob,
x, y, drawFilter, | 1662 fTextContext->drawTextBlob(this, fRenderTarget, fClip, paint, *draw.fMatrix, |
| 1935 draw.fClip->getBounds()); | 1663 blob, x, y, drawFilter, draw.fClip->getBounds()); |
| 1936 } | 1664 } |
| 1937 | 1665 |
| 1938 /////////////////////////////////////////////////////////////////////////////// | 1666 /////////////////////////////////////////////////////////////////////////////// |
| 1939 | 1667 |
| 1940 bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const { | 1668 bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const { |
| 1941 if (paint.getShader() || | 1669 if (paint.getShader() || |
| 1942 !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode) || | 1670 !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode) || |
| 1943 paint.getMaskFilter() || | 1671 paint.getMaskFilter() || |
| 1944 paint.getRasterizer() || | 1672 paint.getRasterizer() || |
| 1945 paint.getColorFilter() || | 1673 paint.getColorFilter() || |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2064 #endif | 1792 #endif |
| 2065 } | 1793 } |
| 2066 | 1794 |
| 2067 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() { | 1795 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() { |
| 2068 // We always return a transient cache, so it is freed after each | 1796 // We always return a transient cache, so it is freed after each |
| 2069 // filter traversal. | 1797 // filter traversal. |
| 2070 return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize); | 1798 return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize); |
| 2071 } | 1799 } |
| 2072 | 1800 |
| 2073 #endif | 1801 #endif |
| OLD | NEW |