Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/gpu/SkGpuDevice.cpp

Issue 264303008: Disable filtering in draw Bitmap operation when pixels are aligned (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix merge error on expectations/gm/ignored-tests.txt Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/gpu/SkGpuDevice.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "effects/GrBicubicEffect.h" 10 #include "effects/GrBicubicEffect.h"
(...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 } 1133 }
1134 1134
1135 if (iRect->fRight > clamp.fRight) { 1135 if (iRect->fRight > clamp.fRight) {
1136 iRect->fRight = clamp.fRight; 1136 iRect->fRight = clamp.fRight;
1137 } 1137 }
1138 if (iRect->fBottom > clamp.fBottom) { 1138 if (iRect->fBottom > clamp.fBottom) {
1139 iRect->fBottom = clamp.fBottom; 1139 iRect->fBottom = clamp.fBottom;
1140 } 1140 }
1141 } 1141 }
1142 1142
1143 static bool has_aligned_samples(const SkRect& srcRect,
1144 const SkRect& transformedRect) {
1145 // detect pixel disalignment
1146 if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) -
1147 transformedRect.left()) < COLOR_BLEED_TOLERANCE &&
1148 SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) -
1149 transformedRect.top()) < COLOR_BLEED_TOLERANCE &&
1150 SkScalarAbs(transformedRect.width() - srcRect.width()) <
1151 COLOR_BLEED_TOLERANCE &&
1152 SkScalarAbs(transformedRect.height() - srcRect.height()) <
1153 COLOR_BLEED_TOLERANCE) {
1154 return true;
1155 }
1156 return false;
1157 }
1158
1159 static bool may_color_bleed(const SkRect& srcRect,
1160 const SkRect& transformedRect,
1161 const SkMatrix& m) {
1162 // Only gets called if has_aligned_samples returned false.
1163 // So we can assume that sampling is axis aligned but not texel aligned.
1164 SkASSERT(!has_aligned_samples(srcRect, transformedRect));
1165 SkRect innerSrcRect(srcRect), innerTransformedRect,
1166 outerTransformedRect(transformedRect);
1167 innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf);
1168 m.mapRect(&innerTransformedRect, innerSrcRect);
1169
1170 // The gap between outerTransformedRect and innerTransformedRect
1171 // represents the projection of the source border area, which is
1172 // problematic for color bleeding. We must check whether any
1173 // destination pixels sample the border area.
1174 outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
1175 innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
1176 SkIRect outer, inner;
1177 outerTransformedRect.round(&outer);
1178 innerTransformedRect.round(&inner);
1179 // If the inner and outer rects round to the same result, it means the
1180 // border does not overlap any pixel centers. Yay!
1181 return inner != outer;
1182 }
1183
1184 static bool needs_texture_domain(const SkBitmap& bitmap,
1185 const SkRect& srcRect,
1186 GrTextureParams &params,
1187 const SkMatrix& contextMatrix,
1188 bool bicubic) {
1189 bool needsTextureDomain = false;
1190
1191 if (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode) {
1192 // Need texture domain if drawing a sub rect
1193 needsTextureDomain = srcRect.width() < bitmap.width() ||
1194 srcRect.height() < bitmap.height();
1195 if (!bicubic && needsTextureDomain && contextMatrix.rectStaysRect()) {
1196 // sampling is axis-aligned
1197 SkRect transformedRect;
1198 contextMatrix.mapRect(&transformedRect, srcRect);
1199
1200 if (has_aligned_samples(srcRect, transformedRect)) {
1201 params.setFilterMode(GrTextureParams::kNone_FilterMode);
1202 needsTextureDomain = false;
1203 } else {
1204 needsTextureDomain = may_color_bleed(srcRect, transformedRect, c ontextMatrix);
1205 }
1206 }
1207 }
1208 return needsTextureDomain;
1209 }
1210
1143 void SkGpuDevice::drawBitmapCommon(const SkDraw& draw, 1211 void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
1144 const SkBitmap& bitmap, 1212 const SkBitmap& bitmap,
1145 const SkRect* srcRectPtr, 1213 const SkRect* srcRectPtr,
1146 const SkSize* dstSizePtr, 1214 const SkSize* dstSizePtr,
1147 const SkPaint& paint, 1215 const SkPaint& paint,
1148 SkCanvas::DrawBitmapRectFlags flags) { 1216 SkCanvas::DrawBitmapRectFlags flags) {
1149 CHECK_SHOULD_DRAW(draw, false); 1217 CHECK_SHOULD_DRAW(draw, false);
1150 1218
1151 SkRect srcRect; 1219 SkRect srcRect;
1152 SkSize dstSize; 1220 SkSize dstSize;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1271 int maxTileSize = fContext->getMaxTextureSize() - 2 * tileFilterPad; 1339 int maxTileSize = fContext->getMaxTextureSize() - 2 * tileFilterPad;
1272 int tileSize; 1340 int tileSize;
1273 1341
1274 SkIRect clippedSrcRect; 1342 SkIRect clippedSrcRect;
1275 if (this->shouldTileBitmap(bitmap, params, srcRectPtr, maxTileSize, &tileSiz e, 1343 if (this->shouldTileBitmap(bitmap, params, srcRectPtr, maxTileSize, &tileSiz e,
1276 &clippedSrcRect)) { 1344 &clippedSrcRect)) {
1277 this->drawTiledBitmap(bitmap, srcRect, clippedSrcRect, params, paint, fl ags, tileSize, 1345 this->drawTiledBitmap(bitmap, srcRect, clippedSrcRect, params, paint, fl ags, tileSize,
1278 doBicubic); 1346 doBicubic);
1279 } else { 1347 } else {
1280 // take the simple case 1348 // take the simple case
1281 this->internalDrawBitmap(bitmap, srcRect, params, paint, flags, doBicubi c); 1349 bool needsTextureDomain = needs_texture_domain(bitmap,
1350 srcRect,
1351 params,
1352 fContext->getMatrix(),
1353 doBicubic);
1354 this->internalDrawBitmap(bitmap,
1355 srcRect,
1356 params,
1357 paint,
1358 flags,
1359 doBicubic,
1360 needsTextureDomain);
1282 } 1361 }
1283 } 1362 }
1284 1363
1285 // Break 'bitmap' into several tiles to draw it since it has already 1364 // Break 'bitmap' into several tiles to draw it since it has already
1286 // been determined to be too large to fit in VRAM 1365 // been determined to be too large to fit in VRAM
1287 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, 1366 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
1288 const SkRect& srcRect, 1367 const SkRect& srcRect,
1289 const SkIRect& clippedSrcIRect, 1368 const SkIRect& clippedSrcIRect,
1290 const GrTextureParams& params, 1369 const GrTextureParams& params,
1291 const SkPaint& paint, 1370 const SkPaint& paint,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1342 // not bleed across the original clamped edges) 1421 // not bleed across the original clamped edges)
1343 srcRect.roundOut(&iClampRect); 1422 srcRect.roundOut(&iClampRect);
1344 } 1423 }
1345 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1; 1424 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1;
1346 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect) ; 1425 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect) ;
1347 } 1426 }
1348 1427
1349 if (bitmap.extractSubset(&tmpB, iTileR)) { 1428 if (bitmap.extractSubset(&tmpB, iTileR)) {
1350 // now offset it to make it "local" to our tmp bitmap 1429 // now offset it to make it "local" to our tmp bitmap
1351 tileR.offset(-offset.fX, -offset.fY); 1430 tileR.offset(-offset.fX, -offset.fY);
1352 1431 GrTextureParams paramsTemp = params;
1353 this->internalDrawBitmap(tmpB, tileR, params, paint, flags, bicu bic); 1432 bool needsTextureDomain = needs_texture_domain(bitmap,
1433 srcRect,
1434 paramsTemp,
1435 fContext->getMatr ix(),
1436 bicubic);
1437 this->internalDrawBitmap(tmpB,
1438 tileR,
1439 paramsTemp,
1440 paint,
1441 flags,
1442 bicubic,
1443 needsTextureDomain);
1354 } 1444 }
1355 } 1445 }
1356 } 1446 }
1357 } 1447 }
1358 1448
1359 static bool has_aligned_samples(const SkRect& srcRect,
1360 const SkRect& transformedRect) {
1361 // detect pixel disalignment
1362 if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) -
1363 transformedRect.left()) < COLOR_BLEED_TOLERANCE &&
1364 SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) -
1365 transformedRect.top()) < COLOR_BLEED_TOLERANCE &&
1366 SkScalarAbs(transformedRect.width() - srcRect.width()) <
1367 COLOR_BLEED_TOLERANCE &&
1368 SkScalarAbs(transformedRect.height() - srcRect.height()) <
1369 COLOR_BLEED_TOLERANCE) {
1370 return true;
1371 }
1372 return false;
1373 }
1374
1375 static bool may_color_bleed(const SkRect& srcRect,
1376 const SkRect& transformedRect,
1377 const SkMatrix& m) {
1378 // Only gets called if has_aligned_samples returned false.
1379 // So we can assume that sampling is axis aligned but not texel aligned.
1380 SkASSERT(!has_aligned_samples(srcRect, transformedRect));
1381 SkRect innerSrcRect(srcRect), innerTransformedRect,
1382 outerTransformedRect(transformedRect);
1383 innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf);
1384 m.mapRect(&innerTransformedRect, innerSrcRect);
1385
1386 // The gap between outerTransformedRect and innerTransformedRect
1387 // represents the projection of the source border area, which is
1388 // problematic for color bleeding. We must check whether any
1389 // destination pixels sample the border area.
1390 outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
1391 innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
1392 SkIRect outer, inner;
1393 outerTransformedRect.round(&outer);
1394 innerTransformedRect.round(&inner);
1395 // If the inner and outer rects round to the same result, it means the
1396 // border does not overlap any pixel centers. Yay!
1397 return inner != outer;
1398 }
1399
1400 1449
1401 /* 1450 /*
1402 * This is called by drawBitmap(), which has to handle images that may be too 1451 * This is called by drawBitmap(), which has to handle images that may be too
1403 * large to be represented by a single texture. 1452 * large to be represented by a single texture.
1404 * 1453 *
1405 * internalDrawBitmap assumes that the specified bitmap will fit in a texture 1454 * internalDrawBitmap assumes that the specified bitmap will fit in a texture
1406 * and that non-texture portion of the GrPaint has already been setup. 1455 * and that non-texture portion of the GrPaint has already been setup.
1407 */ 1456 */
1408 void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, 1457 void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
1409 const SkRect& srcRect, 1458 const SkRect& srcRect,
1410 const GrTextureParams& params, 1459 const GrTextureParams& params,
1411 const SkPaint& paint, 1460 const SkPaint& paint,
1412 SkCanvas::DrawBitmapRectFlags flags, 1461 SkCanvas::DrawBitmapRectFlags flags,
1413 bool bicubic) { 1462 bool bicubic,
1463 bool needsTextureDomain) {
1414 SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() && 1464 SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() &&
1415 bitmap.height() <= fContext->getMaxTextureSize()); 1465 bitmap.height() <= fContext->getMaxTextureSize());
1416 1466
1417 GrTexture* texture; 1467 GrTexture* texture;
1418 SkAutoCachedTexture act(this, bitmap, &params, &texture); 1468 SkAutoCachedTexture act(this, bitmap, &params, &texture);
1419 if (NULL == texture) { 1469 if (NULL == texture) {
1420 return; 1470 return;
1421 } 1471 }
1422 1472
1423 SkRect dstRect = {0, 0, srcRect.width(), srcRect.height() }; 1473 SkRect dstRect = {0, 0, srcRect.width(), srcRect.height() };
1424 SkRect paintRect; 1474 SkRect paintRect;
1425 SkScalar wInv = SkScalarInvert(SkIntToScalar(texture->width())); 1475 SkScalar wInv = SkScalarInvert(SkIntToScalar(texture->width()));
1426 SkScalar hInv = SkScalarInvert(SkIntToScalar(texture->height())); 1476 SkScalar hInv = SkScalarInvert(SkIntToScalar(texture->height()));
1427 paintRect.setLTRB(SkScalarMul(srcRect.fLeft, wInv), 1477 paintRect.setLTRB(SkScalarMul(srcRect.fLeft, wInv),
1428 SkScalarMul(srcRect.fTop, hInv), 1478 SkScalarMul(srcRect.fTop, hInv),
1429 SkScalarMul(srcRect.fRight, wInv), 1479 SkScalarMul(srcRect.fRight, wInv),
1430 SkScalarMul(srcRect.fBottom, hInv)); 1480 SkScalarMul(srcRect.fBottom, hInv));
1431 1481
1432 bool needsTextureDomain = false;
1433 if (!(flags & SkCanvas::kBleed_DrawBitmapRectFlag) &&
1434 (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode)) {
1435 // Need texture domain if drawing a sub rect
1436 needsTextureDomain = srcRect.width() < bitmap.width() ||
1437 srcRect.height() < bitmap.height();
1438 if (!bicubic && needsTextureDomain && fContext->getMatrix().rectStaysRec t()) {
1439 const SkMatrix& matrix = fContext->getMatrix();
1440 // sampling is axis-aligned
1441 SkRect transformedRect;
1442 matrix.mapRect(&transformedRect, srcRect);
1443
1444 if (has_aligned_samples(srcRect, transformedRect)) {
1445 // We could also turn off filtering here (but we already did a c ache lookup with
1446 // params).
1447 needsTextureDomain = false;
1448 } else {
1449 needsTextureDomain = may_color_bleed(srcRect, transformedRect, m atrix);
1450 }
1451 }
1452 }
1453
1454 SkRect textureDomain = SkRect::MakeEmpty(); 1482 SkRect textureDomain = SkRect::MakeEmpty();
1455 SkAutoTUnref<GrEffectRef> effect; 1483 SkAutoTUnref<GrEffectRef> effect;
1456 if (needsTextureDomain) { 1484 if (needsTextureDomain && !(flags & SkCanvas::kBleed_DrawBitmapRectFlag)) {
1457 // Use a constrained texture domain to avoid color bleeding 1485 // Use a constrained texture domain to avoid color bleeding
1458 SkScalar left, top, right, bottom; 1486 SkScalar left, top, right, bottom;
1459 if (srcRect.width() > SK_Scalar1) { 1487 if (srcRect.width() > SK_Scalar1) {
1460 SkScalar border = SK_ScalarHalf / texture->width(); 1488 SkScalar border = SK_ScalarHalf / texture->width();
1461 left = paintRect.left() + border; 1489 left = paintRect.left() + border;
1462 right = paintRect.right() - border; 1490 right = paintRect.right() - border;
1463 } else { 1491 } else {
1464 left = right = SkScalarHalf(paintRect.left() + paintRect.right()); 1492 left = right = SkScalarHalf(paintRect.left() + paintRect.right());
1465 } 1493 }
1466 if (srcRect.height() > SK_Scalar1) { 1494 if (srcRect.height() > SK_Scalar1) {
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after
2092 GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(pict ure, i); 2120 GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(pict ure, i);
2093 2121
2094 if (NULL != layer->getTexture()) { 2122 if (NULL != layer->getTexture()) {
2095 fContext->unlockScratchTexture(layer->getTexture()); 2123 fContext->unlockScratchTexture(layer->getTexture());
2096 layer->setTexture(NULL); 2124 layer->setTexture(NULL);
2097 } 2125 }
2098 } 2126 }
2099 2127
2100 return true; 2128 return true;
2101 } 2129 }
OLDNEW
« no previous file with comments | « include/gpu/SkGpuDevice.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698