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 |