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