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 |