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 |