bool SkImageFilterUtils::GetInputResultGPU(const SkImageFilter* filter, SkImageFilter::Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result, SkIPoint* offset) { // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity // matrix with no clip and that the matrix, clip, and render target set before this function was // called are restored before we return to the caller. GrContext* context = src.getTexture()->getContext(); GrContext::AutoWideOpenIdentityDraw awoid(context, NULL); if (!filter) { offset->fX = offset->fY = 0; *result = src; return true; } else if (filter->canFilterImageGPU()) { return filter->filterImageGPU(proxy, src, ctm, result, offset); } else { if (filter->filterImage(proxy, src, ctm, result, offset)) { if (!result->getTexture()) { SkImageInfo info; if (!result->asImageInfo(&info)) { return false; } GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL); result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref(); GrUnlockAndUnrefCachedBitmapTexture(resultTex); } return true; } else { return false; } } }
GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const { SkMatrix matrix; matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height()); if (this->hasLocalMatrix()) { SkMatrix inverse; if (!this->getLocalMatrix().invert(&inverse)) { return NULL; } matrix.preConcat(inverse); } SkShader::TileMode tm[] = { (TileMode)fState.fTileModeX, (TileMode)fState.fTileModeY, }; // Must set wrap and filter on the sampler before requesting a texture. SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel(); GrTextureParams::FilterMode textureFilterMode; switch(paintFilterLevel) { case SkPaint::kNone_FilterLevel: textureFilterMode = GrTextureParams::kNone_FilterMode; break; case SkPaint::kLow_FilterLevel: textureFilterMode = GrTextureParams::kBilerp_FilterMode; break; case SkPaint::kMedium_FilterLevel: textureFilterMode = GrTextureParams::kMipMap_FilterMode; break; case SkPaint::kHigh_FilterLevel: // fall back to no filtering here; we will install another // shader that will do the HQ filtering. textureFilterMode = GrTextureParams::kNone_FilterMode; break; default: SkErrorInternals::SetError( kInvalidPaint_SkError, "Sorry, I don't understand the filtering " "mode you asked for. Falling back to " "MIPMaps."); textureFilterMode = GrTextureParams::kMipMap_FilterMode; break; } GrTextureParams params(tm, textureFilterMode); GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, ¶ms); if (NULL == texture) { SkErrorInternals::SetError( kInternalError_SkError, "Couldn't convert bitmap to texture."); return NULL; } GrEffectRef* effect = NULL; if (paintFilterLevel == SkPaint::kHigh_FilterLevel) { effect = GrBicubicEffect::Create(texture, matrix, params); } else { effect = GrSimpleTextureEffect::Create(texture, matrix, params); } GrUnlockAndUnrefCachedBitmapTexture(texture); return effect; }
GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const { SkMatrix matrix; matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height()); SkMatrix inverse; if (!this->getLocalMatrix().invert(&inverse)) { return NULL; } matrix.preConcat(inverse); SkShader::TileMode tm[] = { (TileMode)fState.fTileModeX, (TileMode)fState.fTileModeY, }; // Must set wrap and filter on the sampler before requesting a texture. SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel(); GrTextureParams::FilterMode textureFilterMode; switch(paintFilterLevel) { case SkPaint::kNone_FilterLevel: textureFilterMode = GrTextureParams::kNone_FilterMode; break; case SkPaint::kLow_FilterLevel: textureFilterMode = GrTextureParams::kBilerp_FilterMode; break; case SkPaint::kMedium_FilterLevel: textureFilterMode = GrTextureParams::kMipMap_FilterMode; break; case SkPaint::kHigh_FilterLevel: // Minification can look bad with the bicubic effect. This is an overly aggressive // check for MIP fallbacks. It doesn't consider the fact that minification in the local // matrix could be offset by the view matrix and vice versa. We also don't know whether // the draw has explicit local coords (e.g. drawVertices) where the scale factor is // unknown and varies. if (context->getMatrix().getMinStretch() >= SK_Scalar1 && this->getLocalMatrix().getMaxStretch() <= SK_Scalar1) { // fall back to no filtering here; we will install another // shader that will do the HQ filtering. textureFilterMode = GrTextureParams::kNone_FilterMode; } else { // Fall back to mip-mapping. paintFilterLevel = SkPaint::kMedium_FilterLevel; textureFilterMode = GrTextureParams::kMipMap_FilterMode; } break; default: SkErrorInternals::SetError( kInvalidPaint_SkError, "Sorry, I don't understand the filtering " "mode you asked for. Falling back to " "MIPMaps."); textureFilterMode = GrTextureParams::kMipMap_FilterMode; break; } GrTextureParams params(tm, textureFilterMode); GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, ¶ms); if (NULL == texture) { SkErrorInternals::SetError( kInternalError_SkError, "Couldn't convert bitmap to texture."); return NULL; } GrEffectRef* effect = NULL; if (paintFilterLevel == SkPaint::kHigh_FilterLevel) { effect = GrBicubicEffect::Create(texture, matrix, tm); } else { effect = GrSimpleTextureEffect::Create(texture, matrix, params); } GrUnlockAndUnrefCachedBitmapTexture(texture); return effect; }
bool SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint, const SkMatrix* localMatrix, GrColor* grColor, GrEffectRef** grEffect) const { SkMatrix matrix; matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height()); SkMatrix lmInverse; if (!this->getLocalMatrix().invert(&lmInverse)) { return false; } if (localMatrix) { SkMatrix inv; if (!localMatrix->invert(&inv)) { return false; } lmInverse.postConcat(inv); } matrix.preConcat(lmInverse); SkShader::TileMode tm[] = { (TileMode)fTileModeX, (TileMode)fTileModeY, }; // Must set wrap and filter on the sampler before requesting a texture. In two places below // we check the matrix scale factors to determine how to interpret the filter quality setting. // This completely ignores the complexity of the drawVertices case where explicit local coords // are provided by the caller. bool useBicubic = false; GrTextureParams::FilterMode textureFilterMode; switch(paint.getFilterLevel()) { case SkPaint::kNone_FilterLevel: textureFilterMode = GrTextureParams::kNone_FilterMode; break; case SkPaint::kLow_FilterLevel: textureFilterMode = GrTextureParams::kBilerp_FilterMode; break; case SkPaint::kMedium_FilterLevel: { SkMatrix matrix; matrix.setConcat(context->getMatrix(), this->getLocalMatrix()); if (matrix.getMinScale() < SK_Scalar1) { textureFilterMode = GrTextureParams::kMipMap_FilterMode; } else { // Don't trigger MIP level generation unnecessarily. textureFilterMode = GrTextureParams::kBilerp_FilterMode; } break; } case SkPaint::kHigh_FilterLevel: { SkMatrix matrix; matrix.setConcat(context->getMatrix(), this->getLocalMatrix()); useBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode); break; } default: SkErrorInternals::SetError( kInvalidPaint_SkError, "Sorry, I don't understand the filtering " "mode you asked for. Falling back to " "MIPMaps."); textureFilterMode = GrTextureParams::kMipMap_FilterMode; break; } GrTextureParams params(tm, textureFilterMode); GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, ¶ms); if (NULL == texture) { SkErrorInternals::SetError( kInternalError_SkError, "Couldn't convert bitmap to texture."); return false; } *grColor = (kAlpha_8_SkColorType == fRawBitmap.colorType()) ? SkColor2GrColor(paint.getColor()) : SkColor2GrColorJustAlpha(paint.getColor()); if (useBicubic) { *grEffect = GrBicubicEffect::Create(texture, matrix, tm); } else { *grEffect = GrSimpleTextureEffect::Create(texture, matrix, params); } GrUnlockAndUnrefCachedBitmapTexture(texture); return true; }