Commit 31d2c105 authored by junov@chromium.org's avatar junov@chromium.org

Add rendering fast path for when playing a display list canvas at 1:1 scale

This patch modifies GraphicsContext::drawPicture to make it
avoid the use of image filters for presenting canvas
contents, and just use a plain save layer when drawing
contents at 1:1 pixel scale.

BUG=386601

Review URL: https://codereview.chromium.org/662673002

git-svn-id: svn://svn.chromium.org/blink/trunk@183836 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 30b5e791
...@@ -59,6 +59,16 @@ ...@@ -59,6 +59,16 @@
#include "wtf/Assertions.h" #include "wtf/Assertions.h"
#include "wtf/MathExtras.h" #include "wtf/MathExtras.h"
namespace {
// Tolerance value use for comparing scale factor to 1..
// Numerical error should not reach 6th decimal except for highly degenerate cases,
// and effect of 6th decimal on scale is negligible over max span of a skia canvas
// which is 32k pixels.
const float cPictureScaleEpsilon = 0.000001;
}
namespace blink { namespace blink {
struct GraphicsContext::RecordingState { struct GraphicsContext::RecordingState {
...@@ -1125,6 +1135,11 @@ void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest, ...@@ -1125,6 +1135,11 @@ void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest,
image->draw(this, dest, src, op, blendMode); image->draw(this, dest, src, op, blendMode);
} }
static inline bool pictureScaleIsApproximatelyOne(float x)
{
return fabsf(x - 1.0f) < cPictureScaleEpsilon;
}
void GraphicsContext::drawPicture(PassRefPtr<SkPicture> picture, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode) void GraphicsContext::drawPicture(PassRefPtr<SkPicture> picture, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode)
{ {
ASSERT(m_canvas); ASSERT(m_canvas);
...@@ -1134,22 +1149,35 @@ void GraphicsContext::drawPicture(PassRefPtr<SkPicture> picture, const FloatRect ...@@ -1134,22 +1149,35 @@ void GraphicsContext::drawPicture(PassRefPtr<SkPicture> picture, const FloatRect
SkMatrix ctm = m_canvas->getTotalMatrix(); SkMatrix ctm = m_canvas->getTotalMatrix();
SkRect deviceDest; SkRect deviceDest;
ctm.mapRect(&deviceDest, dest); ctm.mapRect(&deviceDest, dest);
SkRect sourceBounds = WebCoreFloatRectToSKRect(src); float scaleX = deviceDest.width() / src.width();
float scaleY = deviceDest.height() / src.height();
RefPtr<SkPictureImageFilter> pictureFilter = adoptRef(SkPictureImageFilter::Create(picture.get(), sourceBounds));
SkMatrix layerScale;
layerScale.setScale(deviceDest.width() / src.width(), deviceDest.height() / src.height());
RefPtr<SkMatrixImageFilter> matrixFilter = adoptRef(SkMatrixImageFilter::Create(layerScale, SkPaint::kLow_FilterLevel, pictureFilter.get()));
SkPaint picturePaint; SkPaint picturePaint;
picturePaint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op, blendMode)); picturePaint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op, blendMode));
picturePaint.setImageFilter(matrixFilter.get()); SkRect sourceBounds = WebCoreFloatRectToSKRect(src);
SkRect layerBounds = SkRect::MakeWH(std::max(deviceDest.width(), sourceBounds.width()), std::max(deviceDest.height(), sourceBounds.height())); if (pictureScaleIsApproximatelyOne(scaleX * m_deviceScaleFactor) && pictureScaleIsApproximatelyOne(scaleY * m_deviceScaleFactor)) {
m_canvas->save(); // Fast path for canvases that are rasterized at screen resolution
m_canvas->resetMatrix(); SkRect skBounds = WebCoreFloatRectToSKRect(dest);
m_canvas->translate(deviceDest.x(), deviceDest.y()); m_canvas->saveLayer(&skBounds, &picturePaint);
m_canvas->saveLayer(&layerBounds, &picturePaint); SkMatrix pictureTransform;
m_canvas->restore(); pictureTransform.setRectToRect(sourceBounds, skBounds, SkMatrix::kFill_ScaleToFit);
m_canvas->restore(); m_canvas->concat(pictureTransform);
m_canvas->drawPicture(picture.get());
m_canvas->restore();
} else {
RefPtr<SkPictureImageFilter> pictureFilter = adoptRef(SkPictureImageFilter::Create(picture.get(), sourceBounds));
SkMatrix layerScale;
layerScale.setScale(scaleX, scaleY);
RefPtr<SkMatrixImageFilter> matrixFilter = adoptRef(SkMatrixImageFilter::Create(layerScale, SkPaint::kLow_FilterLevel, pictureFilter.get()));
picturePaint.setImageFilter(matrixFilter.get());
SkRect layerBounds = SkRect::MakeWH(std::max(deviceDest.width(), sourceBounds.width()), std::max(deviceDest.height(), sourceBounds.height()));
m_canvas->save();
m_canvas->resetMatrix();
m_canvas->translate(deviceDest.x(), deviceDest.y());
m_canvas->saveLayer(&layerBounds, &picturePaint);
m_canvas->restore();
m_canvas->restore();
}
} }
void GraphicsContext::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y) void GraphicsContext::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment