Chromium Code Reviews| 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 "effects/GrTextureDomainEffect.h" | 10 #include "effects/GrTextureDomainEffect.h" |
| (...skipping 1149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1160 // also affect the behavior of the mask filter. | 1160 // also affect the behavior of the mask filter. |
| 1161 SkMatrix drawMatrix; | 1161 SkMatrix drawMatrix; |
| 1162 drawMatrix.setConcat(fContext->getMatrix(), newM); | 1162 drawMatrix.setConcat(fContext->getMatrix(), newM); |
| 1163 SkDraw transformedDraw(draw); | 1163 SkDraw transformedDraw(draw); |
| 1164 transformedDraw.fMatrix = &drawMatrix; | 1164 transformedDraw.fMatrix = &drawMatrix; |
| 1165 | 1165 |
| 1166 this->drawRect(transformedDraw, srcRect, paintWithTexture); | 1166 this->drawRect(transformedDraw, srcRect, paintWithTexture); |
| 1167 | 1167 |
| 1168 return; | 1168 return; |
| 1169 } | 1169 } |
| 1170 | |
|
robertphillips
2013/10/20 21:21:39
How does this get undone?
bsalomon
2013/10/21 13:19:10
It doesn't :) But SkGpuDevice sets the canvas matr
| |
| 1171 fContext->concatMatrix(m); | |
| 1170 | 1172 |
| 1171 GrTextureParams params; | 1173 GrTextureParams params; |
| 1172 SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel(); | 1174 SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel(); |
| 1173 GrTextureParams::FilterMode textureFilterMode; | 1175 GrTextureParams::FilterMode textureFilterMode; |
| 1174 switch(paintFilterLevel) { | 1176 switch(paintFilterLevel) { |
| 1175 case SkPaint::kNone_FilterLevel: | 1177 case SkPaint::kNone_FilterLevel: |
| 1176 textureFilterMode = GrTextureParams::kNone_FilterMode; | 1178 textureFilterMode = GrTextureParams::kNone_FilterMode; |
| 1177 break; | 1179 break; |
| 1178 case SkPaint::kLow_FilterLevel: | 1180 case SkPaint::kLow_FilterLevel: |
| 1179 textureFilterMode = GrTextureParams::kBilerp_FilterMode; | 1181 textureFilterMode = GrTextureParams::kBilerp_FilterMode; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1192 "MIPMaps."); | 1194 "MIPMaps."); |
| 1193 textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 1195 textureFilterMode = GrTextureParams::kMipMap_FilterMode; |
| 1194 break; | 1196 break; |
| 1195 | 1197 |
| 1196 } | 1198 } |
| 1197 | 1199 |
| 1198 params.setFilterMode(textureFilterMode); | 1200 params.setFilterMode(textureFilterMode); |
| 1199 | 1201 |
| 1200 if (!this->shouldTileBitmap(bitmap, params, srcRectPtr)) { | 1202 if (!this->shouldTileBitmap(bitmap, params, srcRectPtr)) { |
| 1201 // take the simple case | 1203 // take the simple case |
| 1202 this->internalDrawBitmap(bitmap, srcRect, m, params, paint, flags); | 1204 this->internalDrawBitmap(bitmap, srcRect, params, paint, flags); |
| 1203 } else { | 1205 } else { |
| 1204 this->drawTiledBitmap(bitmap, srcRect, m, params, paint, flags); | 1206 this->drawTiledBitmap(bitmap, srcRect, params, paint, flags); |
| 1205 } | 1207 } |
| 1206 } | 1208 } |
| 1207 | 1209 |
| 1208 // Break 'bitmap' into several tiles to draw it since it has already | 1210 // Break 'bitmap' into several tiles to draw it since it has already |
| 1209 // been determined to be too large to fit in VRAM | 1211 // been determined to be too large to fit in VRAM |
| 1210 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, | 1212 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, |
| 1211 const SkRect& srcRect, | 1213 const SkRect& srcRect, |
| 1212 const SkMatrix& m, | |
| 1213 const GrTextureParams& params, | 1214 const GrTextureParams& params, |
| 1214 const SkPaint& paint, | 1215 const SkPaint& paint, |
| 1215 SkCanvas::DrawBitmapRectFlags flags) { | 1216 SkCanvas::DrawBitmapRectFlags flags) { |
| 1216 int maxTextureSize = fContext->getMaxTextureSize(); | 1217 int maxTextureSize = fContext->getMaxTextureSize(); |
| 1217 if (SkPaint::kNone_FilterLevel != paint.getFilterLevel()) { | 1218 if (SkPaint::kNone_FilterLevel != paint.getFilterLevel()) { |
| 1218 // We may need a skosh more room if we have to bump out the tile | 1219 // We may need a skosh more room if we have to bump out the tile |
| 1219 // by 1 pixel all around | 1220 // by 1 pixel all around |
| 1220 maxTextureSize -= 2; | 1221 maxTextureSize -= 2; |
| 1221 } | 1222 } |
| 1222 | 1223 |
| 1223 int tileSize = determine_tile_size(bitmap, srcRect, maxTextureSize); | 1224 int tileSize = determine_tile_size(bitmap, srcRect, maxTextureSize); |
| 1224 | 1225 |
| 1225 // compute clip bounds in local coordinates | 1226 // compute clip bounds in local coordinates |
| 1226 SkRect clipRect; | 1227 SkRect clipRect; |
| 1227 { | 1228 { |
| 1228 const GrRenderTarget* rt = fContext->getRenderTarget(); | 1229 const GrRenderTarget* rt = fContext->getRenderTarget(); |
| 1229 clipRect.setWH(SkIntToScalar(rt->width()), SkIntToScalar(rt->height())); | 1230 clipRect.setWH(SkIntToScalar(rt->width()), SkIntToScalar(rt->height())); |
| 1230 if (!fContext->getClip()->fClipStack->intersectRectWithClip(&clipRect)) { | 1231 if (!fContext->getClip()->fClipStack->intersectRectWithClip(&clipRect)) { |
| 1231 return; | 1232 return; |
| 1232 } | 1233 } |
| 1233 SkMatrix matrix, inverse; | 1234 SkMatrix inverse; |
| 1234 matrix.setConcat(fContext->getMatrix(), m); | 1235 if (!fContext->getMatrix().invert(&inverse)) { |
| 1235 if (!matrix.invert(&inverse)) { | |
| 1236 return; | 1236 return; |
| 1237 } | 1237 } |
| 1238 inverse.mapRect(&clipRect); | 1238 inverse.mapRect(&clipRect); |
| 1239 } | 1239 } |
| 1240 | 1240 |
| 1241 int nx = bitmap.width() / tileSize; | 1241 int nx = bitmap.width() / tileSize; |
| 1242 int ny = bitmap.height() / tileSize; | 1242 int ny = bitmap.height() / tileSize; |
| 1243 for (int x = 0; x <= nx; x++) { | 1243 for (int x = 0; x <= nx; x++) { |
| 1244 for (int y = 0; y <= ny; y++) { | 1244 for (int y = 0; y <= ny; y++) { |
| 1245 SkRect tileR; | 1245 SkRect tileR; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1275 // not bleed across the original clamped edges) | 1275 // not bleed across the original clamped edges) |
| 1276 srcRect.roundOut(&iClampRect); | 1276 srcRect.roundOut(&iClampRect); |
| 1277 } | 1277 } |
| 1278 | 1278 |
| 1279 clamped_unit_outset_with_offset(&iTileR, &offset, iClampRect); | 1279 clamped_unit_outset_with_offset(&iTileR, &offset, iClampRect); |
| 1280 } | 1280 } |
| 1281 | 1281 |
| 1282 if (bitmap.extractSubset(&tmpB, iTileR)) { | 1282 if (bitmap.extractSubset(&tmpB, iTileR)) { |
| 1283 // now offset it to make it "local" to our tmp bitmap | 1283 // now offset it to make it "local" to our tmp bitmap |
| 1284 tileR.offset(-offset.fX, -offset.fY); | 1284 tileR.offset(-offset.fX, -offset.fY); |
| 1285 SkMatrix tmpM(m); | 1285 SkMatrix tmpM; |
| 1286 tmpM.preTranslate(offset.fX, offset.fY); | 1286 tmpM.setTranslate(offset.fX, offset.fY); |
| 1287 | 1287 GrContext::AutoMatrix am; |
| 1288 this->internalDrawBitmap(tmpB, tileR, tmpM, params, paint, flags ); | 1288 am.setPreConcat(fContext, tmpM); |
| 1289 this->internalDrawBitmap(tmpB, tileR, params, paint, flags); | |
| 1289 } | 1290 } |
| 1290 } | 1291 } |
| 1291 } | 1292 } |
| 1292 } | 1293 } |
| 1293 | 1294 |
| 1294 static bool has_aligned_samples(const SkRect& srcRect, | 1295 static bool has_aligned_samples(const SkRect& srcRect, |
| 1295 const SkRect& transformedRect) { | 1296 const SkRect& transformedRect) { |
| 1296 // detect pixel disalignment | 1297 // detect pixel disalignment |
| 1297 if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) - | 1298 if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) - |
| 1298 transformedRect.left()) < COLOR_BLEED_TOLERANCE && | 1299 transformedRect.left()) < COLOR_BLEED_TOLERANCE && |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1335 | 1336 |
| 1336 /* | 1337 /* |
| 1337 * This is called by drawBitmap(), which has to handle images that may be too | 1338 * This is called by drawBitmap(), which has to handle images that may be too |
| 1338 * large to be represented by a single texture. | 1339 * large to be represented by a single texture. |
| 1339 * | 1340 * |
| 1340 * internalDrawBitmap assumes that the specified bitmap will fit in a texture | 1341 * internalDrawBitmap assumes that the specified bitmap will fit in a texture |
| 1341 * and that non-texture portion of the GrPaint has already been setup. | 1342 * and that non-texture portion of the GrPaint has already been setup. |
| 1342 */ | 1343 */ |
| 1343 void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, | 1344 void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, |
| 1344 const SkRect& srcRect, | 1345 const SkRect& srcRect, |
| 1345 const SkMatrix& m, | |
| 1346 const GrTextureParams& params, | 1346 const GrTextureParams& params, |
| 1347 const SkPaint& paint, | 1347 const SkPaint& paint, |
| 1348 SkCanvas::DrawBitmapRectFlags flags) { | 1348 SkCanvas::DrawBitmapRectFlags flags) { |
| 1349 SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() && | 1349 SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() && |
| 1350 bitmap.height() <= fContext->getMaxTextureSize()); | 1350 bitmap.height() <= fContext->getMaxTextureSize()); |
| 1351 | 1351 |
| 1352 GrTexture* texture; | 1352 GrTexture* texture; |
| 1353 SkAutoCachedTexture act(this, bitmap, ¶ms, &texture); | 1353 SkAutoCachedTexture act(this, bitmap, ¶ms, &texture); |
| 1354 if (NULL == texture) { | 1354 if (NULL == texture) { |
| 1355 return; | 1355 return; |
| 1356 } | 1356 } |
| 1357 | 1357 |
| 1358 SkRect dstRect(srcRect); | 1358 SkRect dstRect(srcRect); |
| 1359 SkRect paintRect; | 1359 SkRect paintRect; |
| 1360 SkScalar wInv = SkScalarInvert(SkIntToScalar(bitmap.width())); | 1360 SkScalar wInv = SkScalarInvert(SkIntToScalar(bitmap.width())); |
| 1361 SkScalar hInv = SkScalarInvert(SkIntToScalar(bitmap.height())); | 1361 SkScalar hInv = SkScalarInvert(SkIntToScalar(bitmap.height())); |
| 1362 paintRect.setLTRB(SkScalarMul(srcRect.fLeft, wInv), | 1362 paintRect.setLTRB(SkScalarMul(srcRect.fLeft, wInv), |
| 1363 SkScalarMul(srcRect.fTop, hInv), | 1363 SkScalarMul(srcRect.fTop, hInv), |
| 1364 SkScalarMul(srcRect.fRight, wInv), | 1364 SkScalarMul(srcRect.fRight, wInv), |
| 1365 SkScalarMul(srcRect.fBottom, hInv)); | 1365 SkScalarMul(srcRect.fBottom, hInv)); |
| 1366 | 1366 |
| 1367 bool needsTextureDomain = false; | 1367 bool needsTextureDomain = false; |
| 1368 if (!(flags & SkCanvas::kBleed_DrawBitmapRectFlag) && | 1368 if (!(flags & SkCanvas::kBleed_DrawBitmapRectFlag) && |
| 1369 params.filterMode() != GrTextureParams::kNone_FilterMode) { | 1369 params.filterMode() != GrTextureParams::kNone_FilterMode) { |
| 1370 // Need texture domain if drawing a sub rect. | 1370 // Need texture domain if drawing a sub rect. |
| 1371 needsTextureDomain = srcRect.width() < bitmap.width() || | 1371 needsTextureDomain = srcRect.width() < bitmap.width() || |
| 1372 srcRect.height() < bitmap.height(); | 1372 srcRect.height() < bitmap.height(); |
| 1373 if (needsTextureDomain && m.rectStaysRect() && fContext->getMatrix().rec tStaysRect()) { | 1373 if (needsTextureDomain && fContext->getMatrix().rectStaysRect()) { |
| 1374 const SkMatrix& matrix = fContext->getMatrix(); | |
| 1374 // sampling is axis-aligned | 1375 // sampling is axis-aligned |
| 1375 SkRect transformedRect; | 1376 SkRect transformedRect; |
| 1376 SkMatrix srcToDeviceMatrix(m); | 1377 matrix.mapRect(&transformedRect, srcRect); |
| 1377 srcToDeviceMatrix.postConcat(fContext->getMatrix()); | 1378 |
| 1378 srcToDeviceMatrix.mapRect(&transformedRect, srcRect); | |
| 1379 | |
| 1380 if (has_aligned_samples(srcRect, transformedRect)) { | 1379 if (has_aligned_samples(srcRect, transformedRect)) { |
| 1381 // We could also turn off filtering here (but we already did a c ache lookup with | 1380 // We could also turn off filtering here (but we already did a c ache lookup with |
| 1382 // params). | 1381 // params). |
| 1383 needsTextureDomain = false; | 1382 needsTextureDomain = false; |
| 1384 } else { | 1383 } else { |
| 1385 needsTextureDomain = may_color_bleed(srcRect, transformedRect, m ); | 1384 needsTextureDomain = may_color_bleed(srcRect, transformedRect, m atrix); |
|
bsalomon
2013/10/20 14:14:18
I think this was supposed take the full matrix and
robertphillips
2013/10/20 21:21:39
I agree
| |
| 1386 } | 1385 } |
| 1387 } | 1386 } |
| 1388 } | 1387 } |
| 1389 | 1388 |
| 1390 SkRect textureDomain = SkRect::MakeEmpty(); | 1389 SkRect textureDomain = SkRect::MakeEmpty(); |
| 1391 SkAutoTUnref<GrEffectRef> effect; | 1390 SkAutoTUnref<GrEffectRef> effect; |
| 1392 if (needsTextureDomain) { | 1391 if (needsTextureDomain) { |
| 1393 // Use a constrained texture domain to avoid color bleeding | 1392 // Use a constrained texture domain to avoid color bleeding |
| 1394 SkScalar left, top, right, bottom; | 1393 SkScalar left, top, right, bottom; |
| 1395 if (srcRect.width() > SK_Scalar1) { | 1394 if (srcRect.width() > SK_Scalar1) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1418 | 1417 |
| 1419 // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring | 1418 // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring |
| 1420 // the rest from the SkPaint. | 1419 // the rest from the SkPaint. |
| 1421 GrPaint grPaint; | 1420 GrPaint grPaint; |
| 1422 grPaint.addColorEffect(effect); | 1421 grPaint.addColorEffect(effect); |
| 1423 bool alphaOnly = !(SkBitmap::kA8_Config == bitmap.config()); | 1422 bool alphaOnly = !(SkBitmap::kA8_Config == bitmap.config()); |
| 1424 if (!skPaint2GrPaintNoShader(this, paint, alphaOnly, false, &grPaint)) { | 1423 if (!skPaint2GrPaintNoShader(this, paint, alphaOnly, false, &grPaint)) { |
| 1425 return; | 1424 return; |
| 1426 } | 1425 } |
| 1427 | 1426 |
| 1428 fContext->drawRectToRect(grPaint, dstRect, paintRect, &m); | 1427 fContext->drawRectToRect(grPaint, dstRect, paintRect, NULL); |
| 1429 } | 1428 } |
| 1430 | 1429 |
| 1431 static bool filter_texture(SkBaseDevice* device, GrContext* context, | 1430 static bool filter_texture(SkBaseDevice* device, GrContext* context, |
| 1432 GrTexture* texture, SkImageFilter* filter, | 1431 GrTexture* texture, SkImageFilter* filter, |
| 1433 int w, int h, const SkMatrix& ctm, SkBitmap* result, | 1432 int w, int h, const SkMatrix& ctm, SkBitmap* result, |
| 1434 SkIPoint* offset) { | 1433 SkIPoint* offset) { |
| 1435 SkASSERT(filter); | 1434 SkASSERT(filter); |
| 1436 SkDeviceImageFilterProxy proxy(device); | 1435 SkDeviceImageFilterProxy proxy(device); |
| 1437 | 1436 |
| 1438 if (filter->canFilterImageGPU()) { | 1437 if (filter->canFilterImageGPU()) { |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1851 GrTexture* texture, | 1850 GrTexture* texture, |
| 1852 bool needClear) | 1851 bool needClear) |
| 1853 : SkBitmapDevice(make_bitmap(context, texture->asRenderTarget())) { | 1852 : SkBitmapDevice(make_bitmap(context, texture->asRenderTarget())) { |
| 1854 | 1853 |
| 1855 SkASSERT(texture && texture->asRenderTarget()); | 1854 SkASSERT(texture && texture->asRenderTarget()); |
| 1856 // This constructor is called from onCreateCompatibleDevice. It has locked t he RT in the texture | 1855 // This constructor is called from onCreateCompatibleDevice. It has locked t he RT in the texture |
| 1857 // cache. We pass true for the third argument so that it will get unlocked. | 1856 // cache. We pass true for the third argument so that it will get unlocked. |
| 1858 this->initFromRenderTarget(context, texture->asRenderTarget(), true); | 1857 this->initFromRenderTarget(context, texture->asRenderTarget(), true); |
| 1859 fNeedClear = needClear; | 1858 fNeedClear = needClear; |
| 1860 } | 1859 } |
| OLD | NEW |