| 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 "GrBlurUtils.h" |
| (...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 } else { | 666 } else { |
| 667 return maxTileSize; | 667 return maxTileSize; |
| 668 } | 668 } |
| 669 } | 669 } |
| 670 | 670 |
| 671 // Given a bitmap, an optional src rect, and a context with a clip and matrix de
termine what | 671 // Given a bitmap, an optional src rect, and a context with a clip and matrix de
termine what |
| 672 // pixels from the bitmap are necessary. | 672 // pixels from the bitmap are necessary. |
| 673 static void determine_clipped_src_rect(int width, int height, | 673 static void determine_clipped_src_rect(int width, int height, |
| 674 const GrClip& clip, | 674 const GrClip& clip, |
| 675 const SkMatrix& viewMatrix, | 675 const SkMatrix& viewMatrix, |
| 676 const SkMatrix& srcToDstRect, |
| 676 const SkISize& imageSize, | 677 const SkISize& imageSize, |
| 677 const SkRect* srcRectPtr, | 678 const SkRect* srcRectPtr, |
| 678 SkIRect* clippedSrcIRect) { | 679 SkIRect* clippedSrcIRect) { |
| 679 clip.getConservativeBounds(width, height, clippedSrcIRect, nullptr); | 680 clip.getConservativeBounds(width, height, clippedSrcIRect, nullptr); |
| 680 SkMatrix inv; | 681 SkMatrix inv = SkMatrix::Concat(viewMatrix, srcToDstRect); |
| 681 if (!viewMatrix.invert(&inv)) { | 682 if (!inv.invert(&inv)) { |
| 682 clippedSrcIRect->setEmpty(); | 683 clippedSrcIRect->setEmpty(); |
| 683 return; | 684 return; |
| 684 } | 685 } |
| 685 SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect); | 686 SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect); |
| 686 inv.mapRect(&clippedSrcRect); | 687 inv.mapRect(&clippedSrcRect); |
| 687 if (srcRectPtr) { | 688 if (srcRectPtr) { |
| 688 // we've setup src space 0,0 to map to the top left of the src rect. | 689 // we've setup src space 0,0 to map to the top left of the src rect. |
| 689 clippedSrcRect.offset(srcRectPtr->fLeft, srcRectPtr->fTop); | 690 clippedSrcRect.offset(srcRectPtr->fLeft, srcRectPtr->fTop); |
| 690 if (!clippedSrcRect.intersect(*srcRectPtr)) { | 691 if (!clippedSrcRect.intersect(*srcRectPtr)) { |
| 691 clippedSrcIRect->setEmpty(); | 692 clippedSrcIRect->setEmpty(); |
| 692 return; | 693 return; |
| 693 } | 694 } |
| 694 } | 695 } |
| 695 clippedSrcRect.roundOut(clippedSrcIRect); | 696 clippedSrcRect.roundOut(clippedSrcIRect); |
| 696 SkIRect bmpBounds = SkIRect::MakeSize(imageSize); | 697 SkIRect bmpBounds = SkIRect::MakeSize(imageSize); |
| 697 if (!clippedSrcIRect->intersect(bmpBounds)) { | 698 if (!clippedSrcIRect->intersect(bmpBounds)) { |
| 698 clippedSrcIRect->setEmpty(); | 699 clippedSrcIRect->setEmpty(); |
| 699 } | 700 } |
| 700 } | 701 } |
| 701 | 702 |
| 702 bool SkGpuDevice::shouldTileImageID(uint32_t imageID, const SkIRect& imageRect, | 703 bool SkGpuDevice::shouldTileImageID(uint32_t imageID, const SkIRect& imageRect, |
| 703 const SkMatrix& viewMatrix, | 704 const SkMatrix& viewMatrix, |
| 705 const SkMatrix& srcToDstRect, |
| 704 const GrTextureParams& params, | 706 const GrTextureParams& params, |
| 705 const SkRect* srcRectPtr, | 707 const SkRect* srcRectPtr, |
| 706 int maxTileSize, | 708 int maxTileSize, |
| 707 int* tileSize, | 709 int* tileSize, |
| 708 SkIRect* clippedSubset) const { | 710 SkIRect* clippedSubset) const { |
| 709 ASSERT_SINGLE_OWNER | 711 ASSERT_SINGLE_OWNER |
| 710 // if it's larger than the max tile size, then we have no choice but tiling. | 712 // if it's larger than the max tile size, then we have no choice but tiling. |
| 711 if (imageRect.width() > maxTileSize || imageRect.height() > maxTileSize) { | 713 if (imageRect.width() > maxTileSize || imageRect.height() > maxTileSize) { |
| 712 determine_clipped_src_rect(fDrawContext->width(), fDrawContext->height()
, | 714 determine_clipped_src_rect(fDrawContext->width(), fDrawContext->height()
, fClip, viewMatrix, |
| 713 fClip, viewMatrix, imageRect.size(), | 715 srcToDstRect, imageRect.size(), srcRectPtr, c
lippedSubset); |
| 714 srcRectPtr, clippedSubset); | |
| 715 *tileSize = determine_tile_size(*clippedSubset, maxTileSize); | 716 *tileSize = determine_tile_size(*clippedSubset, maxTileSize); |
| 716 return true; | 717 return true; |
| 717 } | 718 } |
| 718 | 719 |
| 719 // If the image would only produce 4 tiles of the smaller size, don't bother
tiling it. | 720 // If the image would only produce 4 tiles of the smaller size, don't bother
tiling it. |
| 720 const size_t area = imageRect.width() * imageRect.height(); | 721 const size_t area = imageRect.width() * imageRect.height(); |
| 721 if (area < 4 * kBmpSmallTileSize * kBmpSmallTileSize) { | 722 if (area < 4 * kBmpSmallTileSize * kBmpSmallTileSize) { |
| 722 return false; | 723 return false; |
| 723 } | 724 } |
| 724 | 725 |
| 725 // At this point we know we could do the draw by uploading the entire bitmap | 726 // At this point we know we could do the draw by uploading the entire bitmap |
| 726 // as a texture. However, if the texture would be large compared to the | 727 // as a texture. However, if the texture would be large compared to the |
| 727 // cache size and we don't require most of it for this draw then tile to | 728 // cache size and we don't require most of it for this draw then tile to |
| 728 // reduce the amount of upload and cache spill. | 729 // reduce the amount of upload and cache spill. |
| 729 | 730 |
| 730 // assumption here is that sw bitmap size is a good proxy for its size as | 731 // assumption here is that sw bitmap size is a good proxy for its size as |
| 731 // a texture | 732 // a texture |
| 732 size_t bmpSize = area * sizeof(SkPMColor); // assume 32bit pixels | 733 size_t bmpSize = area * sizeof(SkPMColor); // assume 32bit pixels |
| 733 size_t cacheSize; | 734 size_t cacheSize; |
| 734 fContext->getResourceCacheLimits(nullptr, &cacheSize); | 735 fContext->getResourceCacheLimits(nullptr, &cacheSize); |
| 735 if (bmpSize < cacheSize / 2) { | 736 if (bmpSize < cacheSize / 2) { |
| 736 return false; | 737 return false; |
| 737 } | 738 } |
| 738 | 739 |
| 739 // Figure out how much of the src we will need based on the src rect and cli
pping. Reject if | 740 // Figure out how much of the src we will need based on the src rect and cli
pping. Reject if |
| 740 // tiling memory savings would be < 50%. | 741 // tiling memory savings would be < 50%. |
| 741 determine_clipped_src_rect(fDrawContext->width(), fDrawContext->height(), | 742 determine_clipped_src_rect(fDrawContext->width(), fDrawContext->height(), fC
lip, viewMatrix, |
| 742 fClip, viewMatrix, imageRect.size(), srcRectPtr, | 743 srcToDstRect, imageRect.size(), srcRectPtr, clipp
edSubset); |
| 743 clippedSubset); | |
| 744 *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max
sized tile. | 744 *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max
sized tile. |
| 745 size_t usedTileBytes = get_tile_count(*clippedSubset, kBmpSmallTileSize) * | 745 size_t usedTileBytes = get_tile_count(*clippedSubset, kBmpSmallTileSize) * |
| 746 kBmpSmallTileSize * kBmpSmallTileSize; | 746 kBmpSmallTileSize * kBmpSmallTileSize; |
| 747 | 747 |
| 748 return usedTileBytes < 2 * bmpSize; | 748 return usedTileBytes < 2 * bmpSize; |
| 749 } | 749 } |
| 750 | 750 |
| 751 bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap, | |
| 752 const SkMatrix& viewMatrix, | |
| 753 const GrTextureParams& params, | |
| 754 const SkRect* srcRectPtr, | |
| 755 int maxTileSize, | |
| 756 int* tileSize, | |
| 757 SkIRect* clippedSrcRect) const { | |
| 758 ASSERT_SINGLE_OWNER | |
| 759 return this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset(),
viewMatrix, params, | |
| 760 srcRectPtr, maxTileSize, tileSize, clippedSrc
Rect); | |
| 761 } | |
| 762 | |
| 763 bool SkGpuDevice::shouldTileImage(const SkImage* image, const SkRect* srcRectPtr
, | 751 bool SkGpuDevice::shouldTileImage(const SkImage* image, const SkRect* srcRectPtr
, |
| 764 SkCanvas::SrcRectConstraint constraint, SkFilt
erQuality quality, | 752 SkCanvas::SrcRectConstraint constraint, SkFilt
erQuality quality, |
| 765 const SkMatrix& viewMatrix) const { | 753 const SkMatrix& viewMatrix, |
| 754 const SkMatrix& srcToDstRect) const { |
| 766 ASSERT_SINGLE_OWNER | 755 ASSERT_SINGLE_OWNER |
| 767 // if image is explictly texture backed then just use the texture | 756 // if image is explictly texture backed then just use the texture |
| 768 if (as_IB(image)->peekTexture()) { | 757 if (as_IB(image)->peekTexture()) { |
| 769 return false; | 758 return false; |
| 770 } | 759 } |
| 771 | 760 |
| 772 GrTextureParams params; | 761 GrTextureParams params; |
| 773 bool doBicubic; | 762 bool doBicubic; |
| 774 GrTextureParams::FilterMode textureFilterMode = | 763 GrTextureParams::FilterMode textureFilterMode = |
| 775 GrSkFilterQualityToGrFilterMode(quality, viewMatrix, SkMatri
x::I(), &doBicubic); | 764 GrSkFilterQualityToGrFilterMode(quality, viewMatrix, srcToDs
tRect, &doBicubic); |
| 776 | 765 |
| 777 int tileFilterPad; | 766 int tileFilterPad; |
| 778 if (doBicubic) { | 767 if (doBicubic) { |
| 779 tileFilterPad = GrBicubicEffect::kFilterTexelPad; | 768 tileFilterPad = GrBicubicEffect::kFilterTexelPad; |
| 780 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { | 769 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { |
| 781 tileFilterPad = 0; | 770 tileFilterPad = 0; |
| 782 } else { | 771 } else { |
| 783 tileFilterPad = 1; | 772 tileFilterPad = 1; |
| 784 } | 773 } |
| 785 params.setFilterMode(textureFilterMode); | 774 params.setFilterMode(textureFilterMode); |
| 786 | 775 |
| 787 int maxTileSize = fContext->caps()->maxTileSize() - 2 * tileFilterPad; | 776 int maxTileSize = fContext->caps()->maxTileSize() - 2 * tileFilterPad; |
| 788 | 777 |
| 789 // these are output, which we safely ignore, as we just want to know the pre
dicate | 778 // these are output, which we safely ignore, as we just want to know the pre
dicate |
| 790 int outTileSize; | 779 int outTileSize; |
| 791 SkIRect outClippedSrcRect; | 780 SkIRect outClippedSrcRect; |
| 792 | 781 |
| 793 return this->shouldTileImageID(image->unique(), image->bounds(), viewMatrix,
params, srcRectPtr, | 782 return this->shouldTileImageID(image->unique(), image->bounds(), viewMatrix,
srcToDstRect, |
| 794 maxTileSize, &outTileSize, &outClippedSrcRect
); | 783 params, srcRectPtr, maxTileSize, &outTileSize
, |
| 784 &outClippedSrcRect); |
| 795 } | 785 } |
| 796 | 786 |
| 797 void SkGpuDevice::drawBitmap(const SkDraw& origDraw, | 787 void SkGpuDevice::drawBitmap(const SkDraw& origDraw, |
| 798 const SkBitmap& bitmap, | 788 const SkBitmap& bitmap, |
| 799 const SkMatrix& m, | 789 const SkMatrix& m, |
| 800 const SkPaint& paint) { | 790 const SkPaint& paint) { |
| 801 ASSERT_SINGLE_OWNER | 791 ASSERT_SINGLE_OWNER |
| 802 CHECK_SHOULD_DRAW(origDraw); | 792 CHECK_SHOULD_DRAW(origDraw); |
| 803 SkMatrix viewMatrix; | 793 SkMatrix viewMatrix; |
| 804 viewMatrix.setConcat(*origDraw.fMatrix, m); | 794 viewMatrix.setConcat(*origDraw.fMatrix, m); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 830 if (doBicubic) { | 820 if (doBicubic) { |
| 831 tileFilterPad = GrBicubicEffect::kFilterTexelPad; | 821 tileFilterPad = GrBicubicEffect::kFilterTexelPad; |
| 832 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { | 822 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { |
| 833 tileFilterPad = 0; | 823 tileFilterPad = 0; |
| 834 } else { | 824 } else { |
| 835 tileFilterPad = 1; | 825 tileFilterPad = 1; |
| 836 } | 826 } |
| 837 params.setFilterMode(textureFilterMode); | 827 params.setFilterMode(textureFilterMode); |
| 838 | 828 |
| 839 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFil
terPad; | 829 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFil
terPad; |
| 840 if (this->shouldTileBitmap(bitmap, viewMatrix, params, &srcRect, | 830 if (this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset()
, viewMatrix, |
| 841 maxTileSizeForFilter, &tileSize, &clippedSrcR
ect)) { | 831 SkMatrix::I(), params, &srcRect, maxTileSize
ForFilter, |
| 842 this->drawTiledBitmap(bitmap, viewMatrix, srcRect, clippedSrcRect, p
arams, paint, | 832 &tileSize, &clippedSrcRect)) { |
| 843 SkCanvas::kStrict_SrcRectConstraint, tileSize,
doBicubic); | 833 this->drawTiledBitmap(bitmap, viewMatrix, SkMatrix::I(), srcRect, cl
ippedSrcRect, |
| 834 params, paint, SkCanvas::kStrict_SrcRectConstr
aint, tileSize, |
| 835 doBicubic); |
| 844 return; | 836 return; |
| 845 } | 837 } |
| 846 } | 838 } |
| 847 GrBitmapTextureMaker maker(fContext, bitmap); | 839 GrBitmapTextureMaker maker(fContext, bitmap); |
| 848 this->drawTextureProducer(&maker, nullptr, nullptr, SkCanvas::kStrict_SrcRec
tConstraint, | 840 this->drawTextureProducer(&maker, nullptr, nullptr, SkCanvas::kStrict_SrcRec
tConstraint, |
| 849 viewMatrix, fClip, paint); | 841 viewMatrix, fClip, paint); |
| 850 } | 842 } |
| 851 | 843 |
| 852 // This method outsets 'iRect' by 'outset' all around and then clamps its extent
s to | 844 // This method outsets 'iRect' by 'outset' all around and then clamps its extent
s to |
| 853 // 'clamp'. 'offset' is adjusted to remain positioned over the top-left corner | 845 // 'clamp'. 'offset' is adjusted to remain positioned over the top-left corner |
| (...skipping 25 matching lines...) Expand all Loading... |
| 879 } | 871 } |
| 880 if (iRect->fBottom > clamp.fBottom) { | 872 if (iRect->fBottom > clamp.fBottom) { |
| 881 iRect->fBottom = clamp.fBottom; | 873 iRect->fBottom = clamp.fBottom; |
| 882 } | 874 } |
| 883 } | 875 } |
| 884 | 876 |
| 885 // Break 'bitmap' into several tiles to draw it since it has already | 877 // Break 'bitmap' into several tiles to draw it since it has already |
| 886 // been determined to be too large to fit in VRAM | 878 // been determined to be too large to fit in VRAM |
| 887 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, | 879 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, |
| 888 const SkMatrix& viewMatrix, | 880 const SkMatrix& viewMatrix, |
| 881 const SkMatrix& dstMatrix, |
| 889 const SkRect& srcRect, | 882 const SkRect& srcRect, |
| 890 const SkIRect& clippedSrcIRect, | 883 const SkIRect& clippedSrcIRect, |
| 891 const GrTextureParams& params, | 884 const GrTextureParams& params, |
| 892 const SkPaint& origPaint, | 885 const SkPaint& origPaint, |
| 893 SkCanvas::SrcRectConstraint constraint, | 886 SkCanvas::SrcRectConstraint constraint, |
| 894 int tileSize, | 887 int tileSize, |
| 895 bool bicubic) { | 888 bool bicubic) { |
| 896 ASSERT_SINGLE_OWNER | 889 ASSERT_SINGLE_OWNER |
| 897 | 890 |
| 898 // This is the funnel for all paths that draw tiled bitmaps/images. Log hist
ogram entries. | 891 // This is the funnel for all paths that draw tiled bitmaps/images. Log hist
ogram entries. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 926 SkIntToScalar((y + 1) * tileSize)); | 919 SkIntToScalar((y + 1) * tileSize)); |
| 927 | 920 |
| 928 if (!SkRect::Intersects(tileR, clippedSrcRect)) { | 921 if (!SkRect::Intersects(tileR, clippedSrcRect)) { |
| 929 continue; | 922 continue; |
| 930 } | 923 } |
| 931 | 924 |
| 932 if (!tileR.intersect(srcRect)) { | 925 if (!tileR.intersect(srcRect)) { |
| 933 continue; | 926 continue; |
| 934 } | 927 } |
| 935 | 928 |
| 936 SkBitmap tmpB; | |
| 937 SkIRect iTileR; | 929 SkIRect iTileR; |
| 938 tileR.roundOut(&iTileR); | 930 tileR.roundOut(&iTileR); |
| 939 SkPoint offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft), | 931 SkVector offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft), |
| 940 SkIntToScalar(iTileR.fTop)); | 932 SkIntToScalar(iTileR.fTop)); |
| 941 | 933 SkRect rectToDraw = SkRect::MakeXYWH(offset.fX, offset.fY, |
| 942 // Adjust the context matrix to draw at the right x,y in device spac
e | 934 tileR.width(), tileR.height()); |
| 943 SkMatrix viewM = viewMatrix; | 935 dstMatrix.mapRect(&rectToDraw); |
| 944 SkMatrix tmpM; | |
| 945 tmpM.setTranslate(offset.fX - srcRect.fLeft, offset.fY - srcRect.fTo
p); | |
| 946 viewM.preConcat(tmpM); | |
| 947 | |
| 948 if (GrTextureParams::kNone_FilterMode != params.filterMode() || bicu
bic) { | 936 if (GrTextureParams::kNone_FilterMode != params.filterMode() || bicu
bic) { |
| 949 SkIRect iClampRect; | 937 SkIRect iClampRect; |
| 950 | 938 |
| 951 if (SkCanvas::kFast_SrcRectConstraint == constraint) { | 939 if (SkCanvas::kFast_SrcRectConstraint == constraint) { |
| 952 // In bleed mode we want to always expand the tile on all ed
ges | 940 // In bleed mode we want to always expand the tile on all ed
ges |
| 953 // but stay within the bitmap bounds | 941 // but stay within the bitmap bounds |
| 954 iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height()
); | 942 iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height()
); |
| 955 } else { | 943 } else { |
| 956 // In texture-domain/clamp mode we only want to expand the | 944 // In texture-domain/clamp mode we only want to expand the |
| 957 // tile on edges interior to "srcRect" (i.e., we want to | 945 // tile on edges interior to "srcRect" (i.e., we want to |
| 958 // not bleed across the original clamped edges) | 946 // not bleed across the original clamped edges) |
| 959 srcRect.roundOut(&iClampRect); | 947 srcRect.roundOut(&iClampRect); |
| 960 } | 948 } |
| 961 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1; | 949 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1; |
| 962 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect)
; | 950 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect)
; |
| 963 } | 951 } |
| 964 | 952 |
| 953 SkBitmap tmpB; |
| 965 if (bitmap.extractSubset(&tmpB, iTileR)) { | 954 if (bitmap.extractSubset(&tmpB, iTileR)) { |
| 966 // now offset it to make it "local" to our tmp bitmap | 955 // now offset it to make it "local" to our tmp bitmap |
| 967 tileR.offset(-offset.fX, -offset.fY); | 956 tileR.offset(-offset.fX, -offset.fY); |
| 968 GrTextureParams paramsTemp = params; | 957 GrTextureParams paramsTemp = params; |
| 969 // de-optimized this determination | 958 // de-optimized this determination |
| 970 bool needsTextureDomain = true; | 959 bool needsTextureDomain = true; |
| 971 this->internalDrawBitmap(tmpB, | 960 this->drawBitmapTile(tmpB, |
| 972 viewM, | 961 viewMatrix, |
| 973 tileR, | 962 rectToDraw, |
| 974 paramsTemp, | 963 tileR, |
| 975 *paint, | 964 paramsTemp, |
| 976 constraint, | 965 *paint, |
| 977 bicubic, | 966 constraint, |
| 978 needsTextureDomain); | 967 bicubic, |
| 968 needsTextureDomain); |
| 979 } | 969 } |
| 980 } | 970 } |
| 981 } | 971 } |
| 982 } | 972 } |
| 983 | 973 |
| 984 /* | 974 void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap, |
| 985 * This is called by drawBitmap(), which has to handle images that may be too | 975 const SkMatrix& viewMatrix, |
| 986 * large to be represented by a single texture. | 976 const SkRect& dstRect, |
| 987 * | 977 const SkRect& srcRect, |
| 988 * internalDrawBitmap assumes that the specified bitmap will fit in a texture | 978 const GrTextureParams& params, |
| 989 * and that non-texture portion of the GrPaint has already been setup. | 979 const SkPaint& paint, |
| 990 */ | 980 SkCanvas::SrcRectConstraint constraint, |
| 991 void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, | 981 bool bicubic, |
| 992 const SkMatrix& viewMatrix, | 982 bool needsTextureDomain) { |
| 993 const SkRect& srcRect, | |
| 994 const GrTextureParams& params, | |
| 995 const SkPaint& paint, | |
| 996 SkCanvas::SrcRectConstraint constraint, | |
| 997 bool bicubic, | |
| 998 bool needsTextureDomain) { | |
| 999 // We should have already handled bitmaps larger than the max texture size. | 983 // We should have already handled bitmaps larger than the max texture size. |
| 1000 SkASSERT(bitmap.width() <= fContext->caps()->maxTextureSize() && | 984 SkASSERT(bitmap.width() <= fContext->caps()->maxTextureSize() && |
| 1001 bitmap.height() <= fContext->caps()->maxTextureSize()); | 985 bitmap.height() <= fContext->caps()->maxTextureSize()); |
| 1002 // We should be respecting the max tile size by the time we get here. | 986 // We should be respecting the max tile size by the time we get here. |
| 1003 SkASSERT(bitmap.width() <= fContext->caps()->maxTileSize() && | 987 SkASSERT(bitmap.width() <= fContext->caps()->maxTileSize() && |
| 1004 bitmap.height() <= fContext->caps()->maxTileSize()); | 988 bitmap.height() <= fContext->caps()->maxTileSize()); |
| 1005 | 989 |
| 1006 sk_sp<GrTexture> texture = GrMakeCachedBitmapTexture(fContext, bitmap, param
s, | 990 sk_sp<GrTexture> texture = GrMakeCachedBitmapTexture(fContext, bitmap, param
s, |
| 1007 fDrawContext->sourceGam
maTreatment()); | 991 fDrawContext->sourceGam
maTreatment()); |
| 1008 if (nullptr == texture) { | 992 if (nullptr == texture) { |
| 1009 return; | 993 return; |
| 1010 } | 994 } |
| 1011 | 995 |
| 1012 sk_sp<GrColorSpaceXform> colorSpaceXform = | 996 sk_sp<GrColorSpaceXform> colorSpaceXform = |
| 1013 GrColorSpaceXform::Make(bitmap.colorSpace(), fDrawContext->getColorSpace
()); | 997 GrColorSpaceXform::Make(bitmap.colorSpace(), fDrawContext->getColorSpace
()); |
| 1014 SkRect dstRect = {0, 0, srcRect.width(), srcRect.height() }; | 998 |
| 1015 SkRect paintRect; | 999 SkScalar iw = 1.f / texture->width(); |
| 1016 SkScalar wInv = SkScalarInvert(SkIntToScalar(texture->width())); | 1000 SkScalar ih = 1.f / texture->height(); |
| 1017 SkScalar hInv = SkScalarInvert(SkIntToScalar(texture->height())); | |
| 1018 paintRect.setLTRB(SkScalarMul(srcRect.fLeft, wInv), | |
| 1019 SkScalarMul(srcRect.fTop, hInv), | |
| 1020 SkScalarMul(srcRect.fRight, wInv), | |
| 1021 SkScalarMul(srcRect.fBottom, hInv)); | |
| 1022 | 1001 |
| 1023 SkMatrix texMatrix; | 1002 SkMatrix texMatrix; |
| 1024 texMatrix.reset(); | 1003 // Compute a matrix that maps the rect we will draw to the src rect. |
| 1025 if (kAlpha_8_SkColorType == bitmap.colorType() && paint.getShader()) { | 1004 texMatrix.setRectToRect(dstRect, srcRect, SkMatrix::kStart_ScaleToFit); |
| 1026 // In cases where we are doing an A8 bitmap draw with a shader installed
, we cannot use | 1005 texMatrix.postScale(iw, ih); |
| 1027 // local coords with the bitmap draw since it may mess up texture look u
ps for the shader. | |
| 1028 // Thus we need to pass in the transform matrix directly to the texture
processor used for | |
| 1029 // the bitmap draw. | |
| 1030 texMatrix.setScale(wInv, hInv); | |
| 1031 } | |
| 1032 | |
| 1033 SkRect textureDomain = SkRect::MakeEmpty(); | |
| 1034 | 1006 |
| 1035 // Construct a GrPaint by setting the bitmap texture as the first effect and
then configuring | 1007 // Construct a GrPaint by setting the bitmap texture as the first effect and
then configuring |
| 1036 // the rest from the SkPaint. | 1008 // the rest from the SkPaint. |
| 1037 sk_sp<GrFragmentProcessor> fp; | 1009 sk_sp<GrFragmentProcessor> fp; |
| 1038 | 1010 |
| 1039 if (needsTextureDomain && (SkCanvas::kStrict_SrcRectConstraint == constraint
)) { | 1011 if (needsTextureDomain && (SkCanvas::kStrict_SrcRectConstraint == constraint
)) { |
| 1040 // Use a constrained texture domain to avoid color bleeding | 1012 // Use a constrained texture domain to avoid color bleeding |
| 1041 SkScalar left, top, right, bottom; | 1013 SkRect domain; |
| 1042 if (srcRect.width() > SK_Scalar1) { | 1014 if (srcRect.width() > SK_Scalar1) { |
| 1043 SkScalar border = SK_ScalarHalf / texture->width(); | 1015 domain.fLeft = (srcRect.fLeft + 0.5f) * iw; |
| 1044 left = paintRect.left() + border; | 1016 domain.fRight = (srcRect.fRight - 0.5f) * iw; |
| 1045 right = paintRect.right() - border; | |
| 1046 } else { | 1017 } else { |
| 1047 left = right = SkScalarHalf(paintRect.left() + paintRect.right()); | 1018 domain.fLeft = domain.fRight = srcRect.centerX() * iw; |
| 1048 } | 1019 } |
| 1049 if (srcRect.height() > SK_Scalar1) { | 1020 if (srcRect.height() > SK_Scalar1) { |
| 1050 SkScalar border = SK_ScalarHalf / texture->height(); | 1021 domain.fTop = (srcRect.fTop + 0.5f) * ih; |
| 1051 top = paintRect.top() + border; | 1022 domain.fBottom = (srcRect.fBottom - 0.5f) * ih; |
| 1052 bottom = paintRect.bottom() - border; | |
| 1053 } else { | 1023 } else { |
| 1054 top = bottom = SkScalarHalf(paintRect.top() + paintRect.bottom()); | 1024 domain.fTop = domain.fBottom = srcRect.centerY() * ih; |
| 1055 } | 1025 } |
| 1056 textureDomain.setLTRB(left, top, right, bottom); | |
| 1057 if (bicubic) { | 1026 if (bicubic) { |
| 1058 fp = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform)
, texMatrix, | 1027 fp = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform)
, texMatrix, |
| 1059 textureDomain); | 1028 domain); |
| 1060 } else { | 1029 } else { |
| 1061 fp = GrTextureDomainEffect::Make(texture.get(), std::move(colorSpace
Xform), texMatrix, | 1030 fp = GrTextureDomainEffect::Make(texture.get(), std::move(colorSpace
Xform), texMatrix, |
| 1062 textureDomain, GrTextureDomain::kCl
amp_Mode, | 1031 domain, GrTextureDomain::kClamp_Mod
e, |
| 1063 params.filterMode()); | 1032 params.filterMode()); |
| 1064 } | 1033 } |
| 1065 } else if (bicubic) { | 1034 } else if (bicubic) { |
| 1066 SkASSERT(GrTextureParams::kNone_FilterMode == params.filterMode()); | 1035 SkASSERT(GrTextureParams::kNone_FilterMode == params.filterMode()); |
| 1067 SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTil
eModeY() }; | 1036 SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTil
eModeY() }; |
| 1068 fp = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform), te
xMatrix, tileModes); | 1037 fp = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform), te
xMatrix, tileModes); |
| 1069 } else { | 1038 } else { |
| 1070 fp = GrSimpleTextureEffect::Make(texture.get(), std::move(colorSpaceXfor
m), texMatrix, params); | 1039 fp = GrSimpleTextureEffect::Make(texture.get(), std::move(colorSpaceXfor
m), texMatrix, params); |
| 1071 } | 1040 } |
| 1072 | 1041 |
| 1073 GrPaint grPaint; | 1042 GrPaint grPaint; |
| 1074 if (!SkPaintToGrPaintWithTexture(this->context(), fDrawContext.get(), paint,
viewMatrix, | 1043 if (!SkPaintToGrPaintWithTexture(this->context(), fDrawContext.get(), paint,
viewMatrix, |
| 1075 std::move(fp), kAlpha_8_SkColorType == bitm
ap.colorType(), | 1044 std::move(fp), kAlpha_8_SkColorType == bitm
ap.colorType(), |
| 1076 &grPaint)) { | 1045 &grPaint)) { |
| 1077 return; | 1046 return; |
| 1078 } | 1047 } |
| 1079 | 1048 |
| 1080 if (kAlpha_8_SkColorType == bitmap.colorType() && paint.getShader()) { | 1049 fDrawContext->drawRect(fClip, grPaint, viewMatrix, dstRect); |
| 1081 // We don't have local coords in this case and have previously set the t
ransform | |
| 1082 // matrices directly on the texture processor. | |
| 1083 fDrawContext->drawRect(fClip, grPaint, viewMatrix, dstRect); | |
| 1084 } else { | |
| 1085 fDrawContext->fillRectToRect(fClip, grPaint, viewMatrix, dstRect, paintR
ect); | |
| 1086 } | |
| 1087 } | 1050 } |
| 1088 | 1051 |
| 1089 void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, | 1052 void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, |
| 1090 int left, int top, const SkPaint& paint) { | 1053 int left, int top, const SkPaint& paint) { |
| 1091 ASSERT_SINGLE_OWNER | 1054 ASSERT_SINGLE_OWNER |
| 1092 CHECK_SHOULD_DRAW(draw); | 1055 CHECK_SHOULD_DRAW(draw); |
| 1093 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSprite", fContext); | 1056 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSprite", fContext); |
| 1094 | 1057 |
| 1095 if (fContext->abandoned()) { | 1058 if (fContext->abandoned()) { |
| 1096 return; | 1059 return; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1241 if (doBicubic) { | 1204 if (doBicubic) { |
| 1242 tileFilterPad = GrBicubicEffect::kFilterTexelPad; | 1205 tileFilterPad = GrBicubicEffect::kFilterTexelPad; |
| 1243 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { | 1206 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { |
| 1244 tileFilterPad = 0; | 1207 tileFilterPad = 0; |
| 1245 } else { | 1208 } else { |
| 1246 tileFilterPad = 1; | 1209 tileFilterPad = 1; |
| 1247 } | 1210 } |
| 1248 params.setFilterMode(textureFilterMode); | 1211 params.setFilterMode(textureFilterMode); |
| 1249 | 1212 |
| 1250 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFil
terPad; | 1213 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFil
terPad; |
| 1251 // Fold the dst rect into the view matrix. This is only OK because we do
n't get here if | 1214 if (this->shouldTileImageID(bitmap.getGenerationID(), bitmap.getSubset()
, *draw.fMatrix, |
| 1252 // we have a mask filter. | 1215 srcToDstMatrix, params, src, maxTileSizeForF
ilter, &tileSize, |
| 1253 SkMatrix viewMatrix = *draw.fMatrix; | 1216 &clippedSrcRect)) { |
| 1254 viewMatrix.preTranslate(dst->fLeft, dst->fTop); | 1217 this->drawTiledBitmap(bitmap, *draw.fMatrix, srcToDstMatrix, *src, c
lippedSrcRect, |
| 1255 viewMatrix.preScale(dst->width()/src->width(), dst->height()/src->height
()); | 1218 params, paint, constraint, tileSize, doBicubic
); |
| 1256 if (this->shouldTileBitmap(bitmap, viewMatrix, params, src, | |
| 1257 maxTileSizeForFilter, &tileSize, &clippedSrcR
ect)) { | |
| 1258 this->drawTiledBitmap(bitmap, viewMatrix, *src, clippedSrcRect, para
ms, paint, | |
| 1259 constraint, tileSize, doBicubic); | |
| 1260 return; | 1219 return; |
| 1261 } | 1220 } |
| 1262 } | 1221 } |
| 1263 GrBitmapTextureMaker maker(fContext, bitmap); | 1222 GrBitmapTextureMaker maker(fContext, bitmap); |
| 1264 this->drawTextureProducer(&maker, src, dst, constraint, *draw.fMatrix, fClip
, paint); | 1223 this->drawTextureProducer(&maker, src, dst, constraint, *draw.fMatrix, fClip
, paint); |
| 1265 } | 1224 } |
| 1266 | 1225 |
| 1267 sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkBitmap& bitmap) { | 1226 sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkBitmap& bitmap) { |
| 1268 SkAutoLockPixels alp(bitmap, true); | 1227 SkAutoLockPixels alp(bitmap, true); |
| 1269 if (!bitmap.readyToDraw()) { | 1228 if (!bitmap.readyToDraw()) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 viewMatrix.preTranslate(x, y); | 1317 viewMatrix.preTranslate(x, y); |
| 1359 if (as_IB(image)->peekTexture()) { | 1318 if (as_IB(image)->peekTexture()) { |
| 1360 CHECK_SHOULD_DRAW(draw); | 1319 CHECK_SHOULD_DRAW(draw); |
| 1361 GrImageTextureAdjuster adjuster(as_IB(image)); | 1320 GrImageTextureAdjuster adjuster(as_IB(image)); |
| 1362 this->drawTextureProducer(&adjuster, nullptr, nullptr, SkCanvas::kFast_S
rcRectConstraint, | 1321 this->drawTextureProducer(&adjuster, nullptr, nullptr, SkCanvas::kFast_S
rcRectConstraint, |
| 1363 viewMatrix, fClip, paint); | 1322 viewMatrix, fClip, paint); |
| 1364 return; | 1323 return; |
| 1365 } else { | 1324 } else { |
| 1366 SkBitmap bm; | 1325 SkBitmap bm; |
| 1367 if (this->shouldTileImage(image, nullptr, SkCanvas::kFast_SrcRectConstra
int, | 1326 if (this->shouldTileImage(image, nullptr, SkCanvas::kFast_SrcRectConstra
int, |
| 1368 paint.getFilterQuality(), *draw.fMatrix)) { | 1327 paint.getFilterQuality(), *draw.fMatrix, SkMat
rix::I())) { |
| 1369 // only support tiling as bitmap at the moment, so force raster-vers
ion | 1328 // only support tiling as bitmap at the moment, so force raster-vers
ion |
| 1370 if (!as_IB(image)->getROPixels(&bm)) { | 1329 if (!as_IB(image)->getROPixels(&bm)) { |
| 1371 return; | 1330 return; |
| 1372 } | 1331 } |
| 1373 this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint); | 1332 this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint); |
| 1374 } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) { | 1333 } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) { |
| 1375 CHECK_SHOULD_DRAW(draw); | 1334 CHECK_SHOULD_DRAW(draw); |
| 1376 GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_C
achingHint); | 1335 GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_C
achingHint); |
| 1377 this->drawTextureProducer(&maker, nullptr, nullptr, SkCanvas::kFast_
SrcRectConstraint, | 1336 this->drawTextureProducer(&maker, nullptr, nullptr, SkCanvas::kFast_
SrcRectConstraint, |
| 1378 viewMatrix, fClip, paint); | 1337 viewMatrix, fClip, paint); |
| 1379 } else if (as_IB(image)->getROPixels(&bm)) { | 1338 } else if (as_IB(image)->getROPixels(&bm)) { |
| 1380 this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint); | 1339 this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint); |
| 1381 } | 1340 } |
| 1382 } | 1341 } |
| 1383 } | 1342 } |
| 1384 | 1343 |
| 1385 void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const
SkRect* src, | 1344 void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const
SkRect* src, |
| 1386 const SkRect& dst, const SkPaint& paint, | 1345 const SkRect& dst, const SkPaint& paint, |
| 1387 SkCanvas::SrcRectConstraint constraint) { | 1346 SkCanvas::SrcRectConstraint constraint) { |
| 1388 ASSERT_SINGLE_OWNER | 1347 ASSERT_SINGLE_OWNER |
| 1389 if (as_IB(image)->peekTexture()) { | 1348 if (as_IB(image)->peekTexture()) { |
| 1390 CHECK_SHOULD_DRAW(draw); | 1349 CHECK_SHOULD_DRAW(draw); |
| 1391 GrImageTextureAdjuster adjuster(as_IB(image)); | 1350 GrImageTextureAdjuster adjuster(as_IB(image)); |
| 1392 this->drawTextureProducer(&adjuster, src, &dst, constraint, *draw.fMatri
x, fClip, paint); | 1351 this->drawTextureProducer(&adjuster, src, &dst, constraint, *draw.fMatri
x, fClip, paint); |
| 1393 return; | 1352 return; |
| 1394 } | 1353 } |
| 1395 SkBitmap bm; | 1354 SkBitmap bm; |
| 1396 SkMatrix totalMatrix = *draw.fMatrix; | 1355 SkMatrix srcToDstRect; |
| 1397 totalMatrix.preScale(dst.width() / (src ? src->width() : image->width()), | 1356 srcToDstRect.setRectToRect((src ? *src : SkRect::MakeIWH(image->width(), ima
ge->height())), |
| 1398 dst.height() / (src ? src->height() : image->height()))
; | 1357 dst, SkMatrix::kFill_ScaleToFit); |
| 1399 if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(),
totalMatrix)) { | 1358 if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(),
*draw.fMatrix, |
| 1359 srcToDstRect)) { |
| 1400 // only support tiling as bitmap at the moment, so force raster-version | 1360 // only support tiling as bitmap at the moment, so force raster-version |
| 1401 if (!as_IB(image)->getROPixels(&bm)) { | 1361 if (!as_IB(image)->getROPixels(&bm)) { |
| 1402 return; | 1362 return; |
| 1403 } | 1363 } |
| 1404 this->drawBitmapRect(draw, bm, src, dst, paint, constraint); | 1364 this->drawBitmapRect(draw, bm, src, dst, paint, constraint); |
| 1405 } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) { | 1365 } else if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) { |
| 1406 CHECK_SHOULD_DRAW(draw); | 1366 CHECK_SHOULD_DRAW(draw); |
| 1407 GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_Cachi
ngHint); | 1367 GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_Cachi
ngHint); |
| 1408 this->drawTextureProducer(&maker, src, &dst, constraint, *draw.fMatrix,
fClip, paint); | 1368 this->drawTextureProducer(&maker, src, &dst, constraint, *draw.fMatrix,
fClip, paint); |
| 1409 } else if (as_IB(image)->getROPixels(&bm)) { | 1369 } else if (as_IB(image)->getROPixels(&bm)) { |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1754 } | 1714 } |
| 1755 | 1715 |
| 1756 SkImageFilterCache* SkGpuDevice::getImageFilterCache() { | 1716 SkImageFilterCache* SkGpuDevice::getImageFilterCache() { |
| 1757 ASSERT_SINGLE_OWNER | 1717 ASSERT_SINGLE_OWNER |
| 1758 // We always return a transient cache, so it is freed after each | 1718 // We always return a transient cache, so it is freed after each |
| 1759 // filter traversal. | 1719 // filter traversal. |
| 1760 return SkImageFilterCache::Create(kDefaultImageFilterCacheSize); | 1720 return SkImageFilterCache::Create(kDefaultImageFilterCacheSize); |
| 1761 } | 1721 } |
| 1762 | 1722 |
| 1763 #endif | 1723 #endif |
| OLD | NEW |