Apply matrix early in draw bitmap
R=robertphillips@google.com, senorblanco@chromium.org Author: bsalomon@google.com Review URL: https://codereview.chromium.org/30593003 git-svn-id: http://skia.googlecode.com/svn/trunk@11930 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
e66d376067
commit
25e5a20e65
@ -31,3 +31,5 @@
|
||||
# ('Poppler random failures'): ignore any Poppler failures, for now
|
||||
pdf-poppler
|
||||
|
||||
# Added by bsalomon, test case added in https://codereview.chromium.org/30593003
|
||||
imagefiltersgraph
|
@ -7,11 +7,13 @@
|
||||
|
||||
#include "gm.h"
|
||||
|
||||
#include "SkArithmeticMode.h"
|
||||
#include "SkBitmapSource.h"
|
||||
#include "SkBlurImageFilter.h"
|
||||
#include "SkColorFilter.h"
|
||||
#include "SkColorMatrixFilter.h"
|
||||
#include "SkColorFilterImageFilter.h"
|
||||
#include "SkFlattenableBuffers.h"
|
||||
#include "SkMergeImageFilter.h"
|
||||
#include "SkMorphologyImageFilter.h"
|
||||
#include "SkXfermodeImageFilter.h"
|
||||
@ -20,6 +22,59 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't
|
||||
// perform a draw and this one does.
|
||||
class SimpleOffsetFilter : public SkImageFilter {
|
||||
public:
|
||||
SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
|
||||
: SkImageFilter(input), fDX(dx), fDY(dy) {}
|
||||
|
||||
virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
|
||||
SkBitmap* dst, SkIPoint* offset) SK_OVERRIDE {
|
||||
SkBitmap source = src;
|
||||
SkImageFilter* input = getInput(0);
|
||||
SkIPoint srcOffset = SkIPoint::Make(0, 0);
|
||||
if (NULL != input && !input->filterImage(proxy, src, ctm, &source, &srcOffset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkIRect bounds;
|
||||
source.getBounds(&bounds);
|
||||
|
||||
if (!this->applyCropRect(&bounds, ctm)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
|
||||
SkCanvas canvas(device);
|
||||
SkPaint paint;
|
||||
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||
canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
|
||||
*dst = device->accessBitmap(false);
|
||||
offset->fX += bounds.left();
|
||||
offset->fY += bounds.top();
|
||||
return true;
|
||||
}
|
||||
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
|
||||
|
||||
protected:
|
||||
explicit SimpleOffsetFilter(SkFlattenableReadBuffer& buffer)
|
||||
: SkImageFilter(buffer) {
|
||||
fDX = buffer.readScalar();
|
||||
fDY = buffer.readScalar();
|
||||
}
|
||||
|
||||
virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
|
||||
this->SkImageFilter::flatten(buffer);
|
||||
buffer.writeScalar(fDX);
|
||||
buffer.writeScalar(fDY);
|
||||
}
|
||||
|
||||
private:
|
||||
SkScalar fDX, fDY;
|
||||
};
|
||||
|
||||
class ImageFiltersGraphGM : public skiagm::GM {
|
||||
public:
|
||||
ImageFiltersGraphGM() : fInitialized(false) {}
|
||||
@ -43,7 +98,7 @@ protected:
|
||||
canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
|
||||
}
|
||||
|
||||
virtual SkISize onISize() { return SkISize::Make(200, 100); }
|
||||
virtual SkISize onISize() { return SkISize::Make(500, 150); }
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) {
|
||||
if (!fInitialized) {
|
||||
@ -81,6 +136,22 @@ protected:
|
||||
paint.setImageFilter(blendColor);
|
||||
canvas->drawBitmap(fBitmap, 100, 0, &paint);
|
||||
}
|
||||
{
|
||||
SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
|
||||
0, SK_Scalar1, 0, 0, 0,
|
||||
0, 0, SK_Scalar1, 0, 0,
|
||||
0, 0, 0, SkFloatToScalar(0.5f), 0 };
|
||||
SkColorMatrixFilter matrixCF(matrix);
|
||||
SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(&matrixCF));
|
||||
SimpleOffsetFilter offsetFilter(SkIntToScalar(10), SkIntToScalar(10), matrixFilter);
|
||||
|
||||
SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
|
||||
SkXfermodeImageFilter arithFilter(arith, matrixFilter, &offsetFilter);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setImageFilter(&arithFilter);
|
||||
canvas->drawSprite(fBitmap, 200, 0, &paint);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -191,13 +191,11 @@ private:
|
||||
const SkRect* srcRectPtr) const;
|
||||
void internalDrawBitmap(const SkBitmap&,
|
||||
const SkRect&,
|
||||
const SkMatrix&,
|
||||
const GrTextureParams& params,
|
||||
const SkPaint& paint,
|
||||
SkCanvas::DrawBitmapRectFlags flags);
|
||||
void drawTiledBitmap(const SkBitmap& bitmap,
|
||||
const SkRect& srcRect,
|
||||
const SkMatrix& m,
|
||||
const GrTextureParams& params,
|
||||
const SkPaint& paint,
|
||||
SkCanvas::DrawBitmapRectFlags flags);
|
||||
|
@ -23,6 +23,11 @@ bool SkImageFilterUtils::WrapTexture(GrTexture* texture, int width, int height,
|
||||
bool SkImageFilterUtils::GetInputResultGPU(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) {
|
||||
*result = src;
|
||||
return true;
|
||||
@ -31,9 +36,7 @@ bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter:
|
||||
} else {
|
||||
if (filter->filterImage(proxy, src, ctm, result, offset)) {
|
||||
if (!result->getTexture()) {
|
||||
GrContext* context = ((GrTexture *) src.getTexture())->getContext();
|
||||
GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context,
|
||||
*result, NULL);
|
||||
GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
|
||||
result->setPixelRef(new SkGrPixelRef(resultTex))->unref();
|
||||
GrUnlockAndUnrefCachedBitmapTexture(resultTex);
|
||||
}
|
||||
|
@ -1164,6 +1164,8 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
|
||||
return;
|
||||
}
|
||||
|
||||
fContext->concatMatrix(m);
|
||||
|
||||
GrTextureParams params;
|
||||
SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel();
|
||||
GrTextureParams::FilterMode textureFilterMode;
|
||||
@ -1195,9 +1197,9 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
|
||||
|
||||
if (!this->shouldTileBitmap(bitmap, params, srcRectPtr)) {
|
||||
// take the simple case
|
||||
this->internalDrawBitmap(bitmap, srcRect, m, params, paint, flags);
|
||||
this->internalDrawBitmap(bitmap, srcRect, params, paint, flags);
|
||||
} else {
|
||||
this->drawTiledBitmap(bitmap, srcRect, m, params, paint, flags);
|
||||
this->drawTiledBitmap(bitmap, srcRect, params, paint, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1205,7 +1207,6 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
|
||||
// been determined to be too large to fit in VRAM
|
||||
void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
|
||||
const SkRect& srcRect,
|
||||
const SkMatrix& m,
|
||||
const GrTextureParams& params,
|
||||
const SkPaint& paint,
|
||||
SkCanvas::DrawBitmapRectFlags flags) {
|
||||
@ -1226,9 +1227,8 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
|
||||
if (!fContext->getClip()->fClipStack->intersectRectWithClip(&clipRect)) {
|
||||
return;
|
||||
}
|
||||
SkMatrix matrix, inverse;
|
||||
matrix.setConcat(fContext->getMatrix(), m);
|
||||
if (!matrix.invert(&inverse)) {
|
||||
SkMatrix inverse;
|
||||
if (!fContext->getMatrix().invert(&inverse)) {
|
||||
return;
|
||||
}
|
||||
inverse.mapRect(&clipRect);
|
||||
@ -1278,10 +1278,11 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
|
||||
if (bitmap.extractSubset(&tmpB, iTileR)) {
|
||||
// now offset it to make it "local" to our tmp bitmap
|
||||
tileR.offset(-offset.fX, -offset.fY);
|
||||
SkMatrix tmpM(m);
|
||||
tmpM.preTranslate(offset.fX, offset.fY);
|
||||
|
||||
this->internalDrawBitmap(tmpB, tileR, tmpM, params, paint, flags);
|
||||
SkMatrix tmpM;
|
||||
tmpM.setTranslate(offset.fX, offset.fY);
|
||||
GrContext::AutoMatrix am;
|
||||
am.setPreConcat(fContext, tmpM);
|
||||
this->internalDrawBitmap(tmpB, tileR, params, paint, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1338,7 +1339,6 @@ static bool may_color_bleed(const SkRect& srcRect,
|
||||
*/
|
||||
void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
|
||||
const SkRect& srcRect,
|
||||
const SkMatrix& m,
|
||||
const GrTextureParams& params,
|
||||
const SkPaint& paint,
|
||||
SkCanvas::DrawBitmapRectFlags flags) {
|
||||
@ -1366,19 +1366,18 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
|
||||
// Need texture domain if drawing a sub rect.
|
||||
needsTextureDomain = srcRect.width() < bitmap.width() ||
|
||||
srcRect.height() < bitmap.height();
|
||||
if (needsTextureDomain && m.rectStaysRect() && fContext->getMatrix().rectStaysRect()) {
|
||||
if (needsTextureDomain && fContext->getMatrix().rectStaysRect()) {
|
||||
const SkMatrix& matrix = fContext->getMatrix();
|
||||
// sampling is axis-aligned
|
||||
SkRect transformedRect;
|
||||
SkMatrix srcToDeviceMatrix(m);
|
||||
srcToDeviceMatrix.postConcat(fContext->getMatrix());
|
||||
srcToDeviceMatrix.mapRect(&transformedRect, srcRect);
|
||||
|
||||
matrix.mapRect(&transformedRect, srcRect);
|
||||
|
||||
if (has_aligned_samples(srcRect, transformedRect)) {
|
||||
// We could also turn off filtering here (but we already did a cache lookup with
|
||||
// params).
|
||||
needsTextureDomain = false;
|
||||
} else {
|
||||
needsTextureDomain = may_color_bleed(srcRect, transformedRect, m);
|
||||
needsTextureDomain = may_color_bleed(srcRect, transformedRect, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1421,7 +1420,7 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
|
||||
return;
|
||||
}
|
||||
|
||||
fContext->drawRectToRect(grPaint, dstRect, paintRect, &m);
|
||||
fContext->drawRectToRect(grPaint, dstRect, paintRect, NULL);
|
||||
}
|
||||
|
||||
static bool filter_texture(SkBaseDevice* device, GrContext* context,
|
||||
|
Loading…
Reference in New Issue
Block a user