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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 extern bool (*gShouldDrawProc)(); | 56 extern bool (*gShouldDrawProc)(); |
57 #define CHECK_SHOULD_DRAW(draw) \ | 57 #define CHECK_SHOULD_DRAW(draw) \ |
58 do { \ | 58 do { \ |
59 if (gShouldDrawProc && !gShouldDrawProc()) return; \ | 59 if (gShouldDrawProc && !gShouldDrawProc()) return; \ |
60 this->prepareDraw(draw); \ | 60 this->prepareDraw(draw); \ |
61 } while (0) | 61 } while (0) |
62 #else | 62 #else |
63 #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw) | 63 #define CHECK_SHOULD_DRAW(draw) this->prepareDraw(draw) |
64 #endif | 64 #endif |
65 | 65 |
66 // This constant represents the screen alignment criterion in texels for | |
67 // requiring texture domain clamping to prevent color bleeding when drawing | |
68 // a sub region of a larger source image. | |
69 #define COLOR_BLEED_TOLERANCE 0.001f | |
70 | |
71 #define DO_DEFERRED_CLEAR() \ | 66 #define DO_DEFERRED_CLEAR() \ |
72 do { \ | 67 do { \ |
73 if (fNeedClear) { \ | 68 if (fNeedClear) { \ |
74 this->clearAll(); \ | 69 this->clearAll(); \ |
75 } \ | 70 } \ |
76 } while (false) \ | 71 } while (false) \ |
77 | 72 |
78 /////////////////////////////////////////////////////////////////////////////// | 73 /////////////////////////////////////////////////////////////////////////////// |
79 | 74 |
80 #define CHECK_FOR_ANNOTATION(paint) \ | 75 #define CHECK_FOR_ANNOTATION(paint) \ |
(...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 SkIRect outClippedSrcRect; | 830 SkIRect outClippedSrcRect; |
836 | 831 |
837 return this->shouldTileImageID(image->unique(), image->bounds(), viewMatrix,
params, srcRectPtr, | 832 return this->shouldTileImageID(image->unique(), image->bounds(), viewMatrix,
params, srcRectPtr, |
838 maxTileSize, &outTileSize, &outClippedSrcRect
); | 833 maxTileSize, &outTileSize, &outClippedSrcRect
); |
839 } | 834 } |
840 | 835 |
841 void SkGpuDevice::drawBitmap(const SkDraw& origDraw, | 836 void SkGpuDevice::drawBitmap(const SkDraw& origDraw, |
842 const SkBitmap& bitmap, | 837 const SkBitmap& bitmap, |
843 const SkMatrix& m, | 838 const SkMatrix& m, |
844 const SkPaint& paint) { | 839 const SkPaint& paint) { |
845 | 840 CHECK_SHOULD_DRAW(origDraw); |
846 GrTexture* texture = bitmap.getTexture(); | 841 bool alphaOnly = kAlpha_8_SkColorType == bitmap.colorType(); |
847 if (texture) { | 842 SkMatrix viewMatrix; |
848 CHECK_SHOULD_DRAW(origDraw); | 843 viewMatrix.setConcat(*origDraw.fMatrix, m); |
849 bool alphaOnly = kAlpha_8_SkColorType == bitmap.colorType(); | 844 if (bitmap.getTexture()) { |
850 GrBitmapTextureAdjuster adjuster(&bitmap); | 845 GrBitmapTextureAdjuster adjuster(&bitmap); |
851 SkMatrix viewMatrix; | 846 // We can use kFast here because we know texture-backed bitmaps don't su
pport extractSubset. |
852 viewMatrix.setConcat(*origDraw.fMatrix, m); | 847 this->drawTextureProducer(&adjuster, alphaOnly, nullptr, nullptr, |
853 this->drawTextureAdjuster(&adjuster, alphaOnly, nullptr, nullptr, | |
854 SkCanvas::kFast_SrcRectConstraint, viewMatrix,
fClip, paint); | 848 SkCanvas::kFast_SrcRectConstraint, viewMatrix,
fClip, paint); |
855 return; | 849 return; |
856 } | 850 } |
857 SkMatrix concat; | 851 int maxTileSize = fContext->caps()->maxTileSize(); |
858 SkTCopyOnFirstWrite<SkDraw> draw(origDraw); | 852 |
859 if (!m.isIdentity()) { | 853 // The tile code path doesn't currently support AA, so if the paint asked fo
r aa and we could |
860 concat.setConcat(*draw->fMatrix, m); | 854 // draw untiled, then we bypass checking for tiling purely for optimization
reasons. |
861 draw.writable()->fMatrix = &concat; | 855 bool drawAA = !fRenderTarget->isUnifiedMultisampled() && |
| 856 paint.isAntiAlias() && |
| 857 bitmap.width() <= maxTileSize && |
| 858 bitmap.height() <= maxTileSize; |
| 859 |
| 860 bool skipTileCheck = drawAA || paint.getMaskFilter(); |
| 861 |
| 862 if (!skipTileCheck) { |
| 863 SkRect srcRect = SkRect::MakeIWH(bitmap.width(), bitmap.height()); |
| 864 int tileSize; |
| 865 SkIRect clippedSrcRect; |
| 866 |
| 867 GrTextureParams params; |
| 868 bool doBicubic; |
| 869 GrTextureParams::FilterMode textureFilterMode = |
| 870 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewMatrix
, SkMatrix::I(), |
| 871 &doBicubic); |
| 872 |
| 873 int tileFilterPad; |
| 874 |
| 875 if (doBicubic) { |
| 876 tileFilterPad = GrBicubicEffect::kFilterTexelPad; |
| 877 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { |
| 878 tileFilterPad = 0; |
| 879 } else { |
| 880 tileFilterPad = 1; |
| 881 } |
| 882 params.setFilterMode(textureFilterMode); |
| 883 |
| 884 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFil
terPad; |
| 885 if (this->shouldTileBitmap(bitmap, viewMatrix, params, &srcRect, |
| 886 maxTileSizeForFilter, &tileSize, &clippedSrcR
ect)) { |
| 887 this->drawTiledBitmap(bitmap, viewMatrix, srcRect, clippedSrcRect, p
arams, paint, |
| 888 SkCanvas::kStrict_SrcRectConstraint, tileSize,
doBicubic); |
| 889 return; |
| 890 } |
862 } | 891 } |
863 this->drawBitmapCommon(*draw, bitmap, nullptr, nullptr, paint, | 892 GrBitmapTextureMaker maker(fContext, bitmap); |
864 SkCanvas::kStrict_SrcRectConstraint); | 893 this->drawTextureProducer(&maker, alphaOnly, nullptr, nullptr, |
| 894 SkCanvas::kStrict_SrcRectConstraint, viewMatrix, f
Clip, paint); |
865 } | 895 } |
866 | 896 |
867 // This method outsets 'iRect' by 'outset' all around and then clamps its extent
s to | 897 // This method outsets 'iRect' by 'outset' all around and then clamps its extent
s to |
868 // 'clamp'. 'offset' is adjusted to remain positioned over the top-left corner | 898 // 'clamp'. 'offset' is adjusted to remain positioned over the top-left corner |
869 // of 'iRect' for all possible outsets/clamps. | 899 // of 'iRect' for all possible outsets/clamps. |
870 static inline void clamped_outset_with_offset(SkIRect* iRect, | 900 static inline void clamped_outset_with_offset(SkIRect* iRect, |
871 int outset, | 901 int outset, |
872 SkPoint* offset, | 902 SkPoint* offset, |
873 const SkIRect& clamp) { | 903 const SkIRect& clamp) { |
874 iRect->outset(outset, outset); | 904 iRect->outset(outset, outset); |
(...skipping 15 matching lines...) Expand all Loading... |
890 } | 920 } |
891 | 921 |
892 if (iRect->fRight > clamp.fRight) { | 922 if (iRect->fRight > clamp.fRight) { |
893 iRect->fRight = clamp.fRight; | 923 iRect->fRight = clamp.fRight; |
894 } | 924 } |
895 if (iRect->fBottom > clamp.fBottom) { | 925 if (iRect->fBottom > clamp.fBottom) { |
896 iRect->fBottom = clamp.fBottom; | 926 iRect->fBottom = clamp.fBottom; |
897 } | 927 } |
898 } | 928 } |
899 | 929 |
900 static bool has_aligned_samples(const SkRect& srcRect, | |
901 const SkRect& transformedRect) { | |
902 // detect pixel disalignment | |
903 if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) - | |
904 transformedRect.left()) < COLOR_BLEED_TOLERANCE && | |
905 SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) - | |
906 transformedRect.top()) < COLOR_BLEED_TOLERANCE && | |
907 SkScalarAbs(transformedRect.width() - srcRect.width()) < | |
908 COLOR_BLEED_TOLERANCE && | |
909 SkScalarAbs(transformedRect.height() - srcRect.height()) < | |
910 COLOR_BLEED_TOLERANCE) { | |
911 return true; | |
912 } | |
913 return false; | |
914 } | |
915 | |
916 static bool may_color_bleed(const SkRect& srcRect, | |
917 const SkRect& transformedRect, | |
918 const SkMatrix& m, | |
919 bool isMSAA) { | |
920 // Only gets called if has_aligned_samples returned false. | |
921 // So we can assume that sampling is axis aligned but not texel aligned. | |
922 SkASSERT(!has_aligned_samples(srcRect, transformedRect)); | |
923 SkRect innerSrcRect(srcRect), innerTransformedRect, | |
924 outerTransformedRect(transformedRect); | |
925 if (isMSAA) { | |
926 innerSrcRect.inset(SK_Scalar1, SK_Scalar1); | |
927 } else { | |
928 innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf); | |
929 } | |
930 m.mapRect(&innerTransformedRect, innerSrcRect); | |
931 | |
932 // The gap between outerTransformedRect and innerTransformedRect | |
933 // represents the projection of the source border area, which is | |
934 // problematic for color bleeding. We must check whether any | |
935 // destination pixels sample the border area. | |
936 outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); | |
937 innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); | |
938 SkIRect outer, inner; | |
939 outerTransformedRect.round(&outer); | |
940 innerTransformedRect.round(&inner); | |
941 // If the inner and outer rects round to the same result, it means the | |
942 // border does not overlap any pixel centers. Yay! | |
943 return inner != outer; | |
944 } | |
945 | |
946 static bool needs_texture_domain(const SkBitmap& bitmap, | |
947 const SkRect& srcRect, | |
948 GrTextureParams ¶ms, | |
949 const SkMatrix& contextMatrix, | |
950 bool bicubic, | |
951 bool isMSAA) { | |
952 bool needsTextureDomain = false; | |
953 GrTexture* tex = bitmap.getTexture(); | |
954 int width = tex ? tex->width() : bitmap.width(); | |
955 int height = tex ? tex->height() : bitmap.height(); | |
956 | |
957 if (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode) { | |
958 // Need texture domain if drawing a sub rect | |
959 needsTextureDomain = srcRect.width() < width || | |
960 srcRect.height() < height; | |
961 if (!bicubic && needsTextureDomain && contextMatrix.rectStaysRect()) { | |
962 // sampling is axis-aligned | |
963 SkRect transformedRect; | |
964 contextMatrix.mapRect(&transformedRect, srcRect); | |
965 | |
966 if (has_aligned_samples(srcRect, transformedRect)) { | |
967 params.setFilterMode(GrTextureParams::kNone_FilterMode); | |
968 needsTextureDomain = false; | |
969 } else { | |
970 needsTextureDomain = may_color_bleed(srcRect, transformedRect, | |
971 contextMatrix, isMSAA); | |
972 } | |
973 } | |
974 } | |
975 return needsTextureDomain; | |
976 } | |
977 | |
978 static void draw_aa_bitmap(GrDrawContext* drawContext, GrContext* context, | |
979 GrRenderTarget* renderTarget, const GrClip& clip, | |
980 const SkMatrix& viewMatrix, const SkMatrix& srcRectTo
DstRect, | |
981 const SkPaint& paint, const SkBitmap* bitmapPtr, cons
t SkSize& dstSize) { | |
982 SkShader::TileMode tm[] = { | |
983 SkShader::kClamp_TileMode, | |
984 SkShader::kClamp_TileMode, | |
985 }; | |
986 | |
987 bool doBicubic; | |
988 GrTextureParams::FilterMode textureFilterMode = | |
989 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewMatrix
, | |
990 srcRectToDstRect, | |
991 &doBicubic); | |
992 | |
993 // Setup texture to wrap bitmap | |
994 GrTextureParams params(tm, textureFilterMode); | |
995 SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(context, *bitmapPtr
, params)); | |
996 | |
997 if (!texture) { | |
998 SkErrorInternals::SetError(kInternalError_SkError, | |
999 "Couldn't convert bitmap to texture."); | |
1000 return; | |
1001 } | |
1002 | |
1003 | |
1004 GrPaint grPaint; | |
1005 | |
1006 // Create and insert texture effect | |
1007 SkAutoTUnref<const GrFragmentProcessor> fp; | |
1008 if (doBicubic) { | |
1009 fp.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), tm)); | |
1010 } else { | |
1011 fp.reset(GrSimpleTextureEffect::Create(texture, SkMatrix::I(), params)); | |
1012 } | |
1013 | |
1014 if (kAlpha_8_SkColorType == bitmapPtr->colorType()) { | |
1015 fp.reset(GrFragmentProcessor::MulOutputByInputUnpremulColor(fp)); | |
1016 } else { | |
1017 fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp)); | |
1018 } | |
1019 | |
1020 if (!SkPaintToGrPaintReplaceShader(context, paint, fp, &grPaint)) { | |
1021 return; | |
1022 } | |
1023 | |
1024 // Setup dst rect and final matrix | |
1025 SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight}; | |
1026 | |
1027 SkRect devRect; | |
1028 viewMatrix.mapRect(&devRect, dstRect); | |
1029 | |
1030 SkMatrix matrix; | |
1031 matrix.setIDiv(bitmapPtr->width(), bitmapPtr->height()); | |
1032 | |
1033 SkMatrix dstRectToSrcRect; | |
1034 if (!srcRectToDstRect.invert(&dstRectToSrcRect)) { | |
1035 return; | |
1036 } | |
1037 matrix.preConcat(dstRectToSrcRect); | |
1038 | |
1039 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFill(grPaint.get
Color(), | |
1040 viewMatrix, | |
1041 matrix, | |
1042 dstRect, | |
1043 devRect)); | |
1044 | |
1045 drawContext->drawBatch(clip, grPaint, batch); | |
1046 } | |
1047 | |
1048 static bool can_ignore_strict_subset_constraint(const SkBitmap& bitmap, const Sk
Rect& subset) { | |
1049 GrTexture* tex = bitmap.getTexture(); | |
1050 int width = tex ? tex->width() : bitmap.width(); | |
1051 int height = tex ? tex->height() : bitmap.height(); | |
1052 return subset.contains(SkRect::MakeIWH(width, height)); | |
1053 } | |
1054 | |
1055 void SkGpuDevice::drawBitmapCommon(const SkDraw& draw, | |
1056 const SkBitmap& bitmap, | |
1057 const SkRect* srcRectPtr, | |
1058 const SkSize* dstSizePtr, | |
1059 const SkPaint& paint, | |
1060 SkCanvas::SrcRectConstraint constraint) { | |
1061 CHECK_SHOULD_DRAW(draw); | |
1062 | |
1063 SkRect srcRect; | |
1064 SkSize dstSize; | |
1065 // If there is no src rect, or the src rect contains the entire bitmap then
we're effectively | |
1066 // in the (easier) bleed case, so update flags. | |
1067 if (nullptr == srcRectPtr) { | |
1068 SkScalar w = SkIntToScalar(bitmap.width()); | |
1069 SkScalar h = SkIntToScalar(bitmap.height()); | |
1070 dstSize.fWidth = w; | |
1071 dstSize.fHeight = h; | |
1072 srcRect.set(0, 0, w, h); | |
1073 } else { | |
1074 SkASSERT(dstSizePtr); | |
1075 srcRect = *srcRectPtr; | |
1076 dstSize = *dstSizePtr; | |
1077 } | |
1078 | |
1079 if (can_ignore_strict_subset_constraint(bitmap, srcRect)) { | |
1080 constraint = SkCanvas::kFast_SrcRectConstraint; | |
1081 } | |
1082 | |
1083 // If the render target is not msaa and draw is antialiased, we call | |
1084 // drawRect instead of drawing on the render target directly. | |
1085 // FIXME: the tiled bitmap code path doesn't currently support | |
1086 // anti-aliased edges, we work around that for now by drawing directly | |
1087 // if the image size exceeds maximum texture size. | |
1088 int maxTileSize = fContext->caps()->maxTileSize(); | |
1089 bool drawAA = !fRenderTarget->isUnifiedMultisampled() && | |
1090 paint.isAntiAlias() && | |
1091 bitmap.width() <= maxTileSize && | |
1092 bitmap.height() <= maxTileSize; | |
1093 | |
1094 if (paint.getMaskFilter() || drawAA) { | |
1095 // Convert the bitmap to a shader so that the rect can be drawn | |
1096 // through drawRect, which supports mask filters. | |
1097 SkBitmap tmp; // subset of bitmap, if necessary | |
1098 const SkBitmap* bitmapPtr = &bitmap; | |
1099 SkMatrix srcRectToDstRect; | |
1100 if (srcRectPtr) { | |
1101 srcRectToDstRect.setTranslate(-srcRectPtr->fLeft, -srcRectPtr->fTop)
; | |
1102 srcRectToDstRect.postScale(dstSize.fWidth / srcRectPtr->width(), | |
1103 dstSize.fHeight / srcRectPtr->height()); | |
1104 // In bleed mode we position and trim the bitmap based on the src re
ct which is | |
1105 // already accounted for in 'm' and 'srcRect'. In clamp mode we need
to chop out | |
1106 // the desired portion of the bitmap and then update 'm' and 'srcRec
t' to | |
1107 // compensate. | |
1108 if (SkCanvas::kStrict_SrcRectConstraint == constraint) { | |
1109 SkIRect iSrc; | |
1110 srcRect.roundOut(&iSrc); | |
1111 | |
1112 SkPoint offset = SkPoint::Make(SkIntToScalar(iSrc.fLeft), | |
1113 SkIntToScalar(iSrc.fTop)); | |
1114 | |
1115 if (!bitmap.extractSubset(&tmp, iSrc)) { | |
1116 return; // extraction failed | |
1117 } | |
1118 bitmapPtr = &tmp; | |
1119 srcRect.offset(-offset.fX, -offset.fY); | |
1120 | |
1121 // The source rect has changed so update the matrix | |
1122 srcRectToDstRect.preTranslate(offset.fX, offset.fY); | |
1123 } | |
1124 } else { | |
1125 srcRectToDstRect.reset(); | |
1126 } | |
1127 | |
1128 // If we have a maskfilter then we can't batch, so we take a slow path.
However, we fast | |
1129 // path the case where we are drawing an AA rect so we can batch many dr
awImageRect calls | |
1130 if (paint.getMaskFilter()) { | |
1131 SkPaint paintWithShader(paint); | |
1132 paintWithShader.setShader(SkShader::CreateBitmapShader(*bitmapPtr, | |
1133 SkShader::kClamp_TileMode, SkShader::kClam
p_TileMode, | |
1134 &srcRectToDstRect))->unref(); | |
1135 SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight}; | |
1136 this->drawRect(draw, dstRect, paintWithShader); | |
1137 } else { | |
1138 draw_aa_bitmap(fDrawContext, fContext, fRenderTarget, fClip, *draw.f
Matrix, | |
1139 srcRectToDstRect, paint, bitmapPtr, dstSize); | |
1140 } | |
1141 | |
1142 return; | |
1143 } | |
1144 | |
1145 // If there is no mask filter than it is OK to handle the src rect -> dst re
ct scaling using | |
1146 // the view matrix rather than a local matrix. | |
1147 SkMatrix viewM = *draw.fMatrix; | |
1148 viewM.preScale(dstSize.fWidth / srcRect.width(), | |
1149 dstSize.fHeight / srcRect.height()); | |
1150 | |
1151 GrTextureParams params; | |
1152 bool doBicubic; | |
1153 GrTextureParams::FilterMode textureFilterMode = | |
1154 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewM, SkM
atrix::I(), | |
1155 &doBicubic); | |
1156 | |
1157 int tileFilterPad; | |
1158 if (doBicubic) { | |
1159 tileFilterPad = GrBicubicEffect::kFilterTexelPad; | |
1160 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { | |
1161 tileFilterPad = 0; | |
1162 } else { | |
1163 tileFilterPad = 1; | |
1164 } | |
1165 params.setFilterMode(textureFilterMode); | |
1166 | |
1167 maxTileSize = fContext->caps()->maxTileSize() - 2 * tileFilterPad; | |
1168 int tileSize; | |
1169 | |
1170 SkIRect clippedSrcRect; | |
1171 if (this->shouldTileBitmap(bitmap, viewM, params, srcRectPtr, maxTileSize, &
tileSize, | |
1172 &clippedSrcRect)) { | |
1173 this->drawTiledBitmap(bitmap, viewM, srcRect, clippedSrcRect, params, pa
int, constraint, | |
1174 tileSize, doBicubic); | |
1175 } else { | |
1176 // take the simple case | |
1177 bool needsTextureDomain = needs_texture_domain(bitmap, | |
1178 srcRect, | |
1179 params, | |
1180 viewM, | |
1181 doBicubic, | |
1182 fRenderTarget->isUnifiedM
ultisampled()); | |
1183 this->internalDrawBitmap(bitmap, | |
1184 viewM, | |
1185 srcRect, | |
1186 params, | |
1187 paint, | |
1188 constraint, | |
1189 doBicubic, | |
1190 needsTextureDomain); | |
1191 } | |
1192 } | |
1193 | |
1194 // Break 'bitmap' into several tiles to draw it since it has already | 930 // Break 'bitmap' into several tiles to draw it since it has already |
1195 // been determined to be too large to fit in VRAM | 931 // been determined to be too large to fit in VRAM |
1196 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, | 932 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, |
1197 const SkMatrix& viewMatrix, | 933 const SkMatrix& viewMatrix, |
1198 const SkRect& srcRect, | 934 const SkRect& srcRect, |
1199 const SkIRect& clippedSrcIRect, | 935 const SkIRect& clippedSrcIRect, |
1200 const GrTextureParams& params, | 936 const GrTextureParams& params, |
1201 const SkPaint& origPaint, | 937 const SkPaint& origPaint, |
1202 SkCanvas::SrcRectConstraint constraint, | 938 SkCanvas::SrcRectConstraint constraint, |
1203 int tileSize, | 939 int tileSize, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1262 srcRect.roundOut(&iClampRect); | 998 srcRect.roundOut(&iClampRect); |
1263 } | 999 } |
1264 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1; | 1000 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1; |
1265 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect)
; | 1001 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect)
; |
1266 } | 1002 } |
1267 | 1003 |
1268 if (bitmap.extractSubset(&tmpB, iTileR)) { | 1004 if (bitmap.extractSubset(&tmpB, iTileR)) { |
1269 // now offset it to make it "local" to our tmp bitmap | 1005 // now offset it to make it "local" to our tmp bitmap |
1270 tileR.offset(-offset.fX, -offset.fY); | 1006 tileR.offset(-offset.fX, -offset.fY); |
1271 GrTextureParams paramsTemp = params; | 1007 GrTextureParams paramsTemp = params; |
1272 bool needsTextureDomain = needs_texture_domain( | 1008 // de-optimized this determination |
1273 bitmap, srcRect, params
Temp, | 1009 bool needsTextureDomain = true; |
1274 viewM, bicubic, | |
1275 fRenderTarget->isUnifie
dMultisampled()); | |
1276 this->internalDrawBitmap(tmpB, | 1010 this->internalDrawBitmap(tmpB, |
1277 viewM, | 1011 viewM, |
1278 tileR, | 1012 tileR, |
1279 paramsTemp, | 1013 paramsTemp, |
1280 *paint, | 1014 *paint, |
1281 constraint, | 1015 constraint, |
1282 bicubic, | 1016 bicubic, |
1283 needsTextureDomain); | 1017 needsTextureDomain); |
1284 } | 1018 } |
1285 } | 1019 } |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1495 SkRect::MakeXYWH(SkIntToScalar(left), | 1229 SkRect::MakeXYWH(SkIntToScalar(left), |
1496 SkIntToScalar(top), | 1230 SkIntToScalar(top), |
1497 SkIntToScalar(w), | 1231 SkIntToScalar(w), |
1498 SkIntToScalar(h)), | 1232 SkIntToScalar(h)), |
1499 SkRect::MakeXYWH(0, | 1233 SkRect::MakeXYWH(0, |
1500 0, | 1234 0, |
1501 SK_Scalar1 * w / texture->widt
h(), | 1235 SK_Scalar1 * w / texture->widt
h(), |
1502 SK_Scalar1 * h / texture->heig
ht())); | 1236 SK_Scalar1 * h / texture->heig
ht())); |
1503 } | 1237 } |
1504 | 1238 |
1505 void SkGpuDevice::drawBitmapRect(const SkDraw& origDraw, const SkBitmap& bitmap, | 1239 void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, |
1506 const SkRect* src, const SkRect& dst, | 1240 const SkRect* src, const SkRect& origDst, |
1507 const SkPaint& paint, SkCanvas::SrcRectConstrai
nt constraint) { | 1241 const SkPaint& paint, SkCanvas::SrcRectConstrai
nt constraint) { |
1508 if (GrTexture* tex = bitmap.getTexture()) { | 1242 bool alphaOnly = kAlpha_8_SkColorType == bitmap.colorType(); |
1509 CHECK_SHOULD_DRAW(origDraw); | 1243 if (bitmap.getTexture()) { |
1510 bool alphaOnly = GrPixelConfigIsAlphaOnly(tex->config()); | 1244 CHECK_SHOULD_DRAW(draw); |
1511 GrBitmapTextureAdjuster adjuster(&bitmap); | 1245 GrBitmapTextureAdjuster adjuster(&bitmap); |
1512 this->drawTextureAdjuster(&adjuster, alphaOnly, src, &dst, constraint, *
origDraw.fMatrix, | 1246 this->drawTextureProducer(&adjuster, alphaOnly, src, &origDst, constrain
t, *draw.fMatrix, |
1513 fClip, paint); | 1247 fClip, paint); |
1514 return; | 1248 return; |
1515 } | 1249 } |
1516 | 1250 // The src rect is inferred to be the bmp bounds if not provided. Otherwise,
the src rect must |
1517 SkMatrix matrix; | 1251 // be clipped to the bmp bounds. To determine tiling parameters we need the
filter mode which |
1518 SkRect bitmapBounds, tmpSrc; | 1252 // in turn requires knowing the src-to-dst mapping. If the src was clipped t
o the bmp bounds |
1519 | 1253 // then we use the src-to-dst mapping to compute a new clipped dst rect. |
1520 bitmapBounds.set(0, 0, | 1254 const SkRect* dst = &origDst; |
1521 SkIntToScalar(bitmap.width()), | 1255 const SkRect bmpBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height()); |
1522 SkIntToScalar(bitmap.height())); | |
1523 | |
1524 // Compute matrix from the two rectangles | 1256 // Compute matrix from the two rectangles |
1525 if (src) { | 1257 if (!src) { |
1526 tmpSrc = *src; | 1258 src = &bmpBounds; |
1527 } else { | |
1528 tmpSrc = bitmapBounds; | |
1529 } | 1259 } |
1530 | 1260 |
1531 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); | 1261 SkMatrix srcToDstMatrix; |
1532 | 1262 if (!srcToDstMatrix.setRectToRect(*src, *dst, SkMatrix::kFill_ScaleToFit)) { |
1533 // clip the tmpSrc to the bounds of the bitmap. No check needed if src==null
. | 1263 return; |
1534 if (src) { | 1264 } |
1535 if (!bitmapBounds.contains(tmpSrc)) { | 1265 SkRect tmpSrc, tmpDst; |
1536 if (!tmpSrc.intersect(bitmapBounds)) { | 1266 if (src != &bmpBounds) { |
| 1267 if (!bmpBounds.contains(*src)) { |
| 1268 tmpSrc = *src; |
| 1269 if (!tmpSrc.intersect(bmpBounds)) { |
1537 return; // nothing to draw | 1270 return; // nothing to draw |
1538 } | 1271 } |
| 1272 src = &tmpSrc; |
| 1273 srcToDstMatrix.mapRect(&tmpDst, *src); |
| 1274 dst = &tmpDst; |
1539 } | 1275 } |
1540 } | 1276 } |
1541 | 1277 |
1542 SkRect tmpDst; | 1278 int maxTileSize = fContext->caps()->maxTileSize(); |
1543 matrix.mapRect(&tmpDst, tmpSrc); | |
1544 | 1279 |
1545 SkTCopyOnFirstWrite<SkDraw> draw(origDraw); | 1280 // The tile code path doesn't currently support AA, so if the paint asked fo
r aa and we could |
1546 if (0 != tmpDst.fLeft || 0 != tmpDst.fTop) { | 1281 // draw untiled, then we bypass checking for tiling purely for optimization
reasons. |
1547 // Translate so that tempDst's top left is at the origin. | 1282 bool drawAA = !fRenderTarget->isUnifiedMultisampled() && |
1548 matrix = *origDraw.fMatrix; | 1283 paint.isAntiAlias() && |
1549 matrix.preTranslate(tmpDst.fLeft, tmpDst.fTop); | 1284 bitmap.width() <= maxTileSize && |
1550 draw.writable()->fMatrix = &matrix; | 1285 bitmap.height() <= maxTileSize; |
| 1286 |
| 1287 bool skipTileCheck = drawAA || paint.getMaskFilter(); |
| 1288 |
| 1289 if (!skipTileCheck) { |
| 1290 int tileSize; |
| 1291 SkIRect clippedSrcRect; |
| 1292 |
| 1293 GrTextureParams params; |
| 1294 bool doBicubic; |
| 1295 GrTextureParams::FilterMode textureFilterMode = |
| 1296 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), *draw.fMat
rix, srcToDstMatrix, |
| 1297 &doBicubic); |
| 1298 |
| 1299 int tileFilterPad; |
| 1300 |
| 1301 if (doBicubic) { |
| 1302 tileFilterPad = GrBicubicEffect::kFilterTexelPad; |
| 1303 } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { |
| 1304 tileFilterPad = 0; |
| 1305 } else { |
| 1306 tileFilterPad = 1; |
| 1307 } |
| 1308 params.setFilterMode(textureFilterMode); |
| 1309 |
| 1310 int maxTileSizeForFilter = fContext->caps()->maxTileSize() - 2 * tileFil
terPad; |
| 1311 // Fold the dst rect into the view matrix. This is only OK because we do
n't get here if |
| 1312 // we have a mask filter. |
| 1313 SkMatrix viewMatrix = *draw.fMatrix; |
| 1314 viewMatrix.preTranslate(dst->fLeft, dst->fTop); |
| 1315 viewMatrix.preScale(dst->width()/src->width(), dst->height()/src->height
()); |
| 1316 if (this->shouldTileBitmap(bitmap, viewMatrix, params, src, |
| 1317 maxTileSizeForFilter, &tileSize, &clippedSrcR
ect)) { |
| 1318 this->drawTiledBitmap(bitmap, viewMatrix, *src, clippedSrcRect, para
ms, paint, |
| 1319 constraint, tileSize, doBicubic); |
| 1320 return; |
| 1321 } |
1551 } | 1322 } |
1552 SkSize dstSize; | 1323 GrBitmapTextureMaker maker(fContext, bitmap); |
1553 dstSize.fWidth = tmpDst.width(); | 1324 this->drawTextureProducer(&maker, alphaOnly, src, dst, constraint, *draw.fMa
trix, fClip, paint); |
1554 dstSize.fHeight = tmpDst.height(); | |
1555 | |
1556 this->drawBitmapCommon(*draw, bitmap, &tmpSrc, &dstSize, paint, constraint); | |
1557 } | 1325 } |
1558 | 1326 |
1559 void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, | 1327 void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, |
1560 int x, int y, const SkPaint& paint) { | 1328 int x, int y, const SkPaint& paint) { |
1561 // clear of the source device must occur before CHECK_SHOULD_DRAW | 1329 // clear of the source device must occur before CHECK_SHOULD_DRAW |
1562 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext); | 1330 GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext); |
1563 SkGpuDevice* dev = static_cast<SkGpuDevice*>(device); | 1331 SkGpuDevice* dev = static_cast<SkGpuDevice*>(device); |
1564 | 1332 |
1565 // TODO: If the source device covers the whole of this device, we could | 1333 // TODO: If the source device covers the whole of this device, we could |
1566 // omit fNeedsClear -related flushing. | 1334 // omit fNeedsClear -related flushing. |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1673 | 1441 |
1674 void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x
, SkScalar y, | 1442 void SkGpuDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x
, SkScalar y, |
1675 const SkPaint& paint) { | 1443 const SkPaint& paint) { |
1676 SkBitmap bm; | 1444 SkBitmap bm; |
1677 if (GrTexture* tex = as_IB(image)->peekTexture()) { | 1445 if (GrTexture* tex = as_IB(image)->peekTexture()) { |
1678 CHECK_SHOULD_DRAW(draw); | 1446 CHECK_SHOULD_DRAW(draw); |
1679 SkMatrix viewMatrix = *draw.fMatrix; | 1447 SkMatrix viewMatrix = *draw.fMatrix; |
1680 viewMatrix.preTranslate(x, y); | 1448 viewMatrix.preTranslate(x, y); |
1681 bool alphaOnly = GrPixelConfigIsAlphaOnly(tex->config()); | 1449 bool alphaOnly = GrPixelConfigIsAlphaOnly(tex->config()); |
1682 GrImageTextureAdjuster adjuster(as_IB(image)); | 1450 GrImageTextureAdjuster adjuster(as_IB(image)); |
1683 this->drawTextureAdjuster(&adjuster, alphaOnly, nullptr, nullptr, | 1451 this->drawTextureProducer(&adjuster, alphaOnly, nullptr, nullptr, |
1684 SkCanvas::kFast_SrcRectConstraint, viewMatrix,
fClip, paint); | 1452 SkCanvas::kFast_SrcRectConstraint, viewMatrix,
fClip, paint); |
1685 return; | 1453 return; |
1686 } else { | 1454 } else { |
1687 if (this->shouldTileImage(image, nullptr, SkCanvas::kFast_SrcRectConstra
int, | 1455 if (this->shouldTileImage(image, nullptr, SkCanvas::kFast_SrcRectConstra
int, |
1688 paint.getFilterQuality(), *draw.fMatrix)) { | 1456 paint.getFilterQuality(), *draw.fMatrix)) { |
1689 // only support tiling as bitmap at the moment, so force raster-vers
ion | 1457 // only support tiling as bitmap at the moment, so force raster-vers
ion |
1690 if (!as_IB(image)->getROPixels(&bm)) { | 1458 if (!as_IB(image)->getROPixels(&bm)) { |
1691 return; | 1459 return; |
1692 } | 1460 } |
1693 } else { | 1461 } else { |
1694 if (!wrap_as_bm(this->context(), image, &bm)) { | 1462 if (!wrap_as_bm(this->context(), image, &bm)) { |
1695 return; | 1463 return; |
1696 } | 1464 } |
1697 } | 1465 } |
1698 } | 1466 } |
1699 this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint); | 1467 this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint); |
1700 } | 1468 } |
1701 | 1469 |
1702 void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const
SkRect* src, | 1470 void SkGpuDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const
SkRect* src, |
1703 const SkRect& dst, const SkPaint& paint, | 1471 const SkRect& dst, const SkPaint& paint, |
1704 SkCanvas::SrcRectConstraint constraint) { | 1472 SkCanvas::SrcRectConstraint constraint) { |
1705 if (GrTexture* tex = as_IB(image)->peekTexture()) { | 1473 if (GrTexture* tex = as_IB(image)->peekTexture()) { |
1706 CHECK_SHOULD_DRAW(draw); | 1474 CHECK_SHOULD_DRAW(draw); |
1707 GrImageTextureAdjuster adjuster(as_IB(image)); | 1475 GrImageTextureAdjuster adjuster(as_IB(image)); |
1708 bool alphaOnly = GrPixelConfigIsAlphaOnly(tex->config()); | 1476 bool alphaOnly = GrPixelConfigIsAlphaOnly(tex->config()); |
1709 this->drawTextureAdjuster(&adjuster, alphaOnly, src, &dst, constraint, *
draw.fMatrix, | 1477 this->drawTextureProducer(&adjuster, alphaOnly, src, &dst, constraint, *
draw.fMatrix, |
1710 fClip, paint); | 1478 fClip, paint); |
1711 return; | 1479 return; |
1712 } | 1480 } |
1713 SkBitmap bm; | 1481 SkBitmap bm; |
1714 SkMatrix viewMatrix = *draw.fMatrix; | 1482 SkMatrix viewMatrix = *draw.fMatrix; |
1715 viewMatrix.preScale(dst.width() / (src ? src->width() : image->width()), | 1483 viewMatrix.preScale(dst.width() / (src ? src->width() : image->width()), |
1716 dst.height() / (src ? src->height() : image->height())); | 1484 dst.height() / (src ? src->height() : image->height())); |
1717 if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(),
viewMatrix)) { | 1485 if (this->shouldTileImage(image, src, constraint, paint.getFilterQuality(),
viewMatrix)) { |
1718 // only support tiling as bitmap at the moment, so force raster-version | 1486 // only support tiling as bitmap at the moment, so force raster-version |
1719 if (!as_IB(image)->getROPixels(&bm)) { | 1487 if (!as_IB(image)->getROPixels(&bm)) { |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2070 return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize); | 1838 return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize); |
2071 } | 1839 } |
2072 | 1840 |
2073 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() { | 1841 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() { |
2074 // We always return a transient cache, so it is freed after each | 1842 // We always return a transient cache, so it is freed after each |
2075 // filter traversal. | 1843 // filter traversal. |
2076 return SkGpuDevice::NewImageFilterCache(); | 1844 return SkGpuDevice::NewImageFilterCache(); |
2077 } | 1845 } |
2078 | 1846 |
2079 #endif | 1847 #endif |
OLD | NEW |