diff options
author | senorblanco@chromium.org <senorblanco@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538> | 2011-03-18 21:03:43 +0000 |
---|---|---|
committer | senorblanco@chromium.org <senorblanco@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538> | 2011-03-18 21:03:43 +0000 |
commit | 9d9fcff2dec88a3269c2227cc6eda11d9ab02bc3 (patch) | |
tree | 25f59f0bc0a44a2bc4b09196411a3ab4f8c7f617 | |
parent | 204147c8efa2aa17a4afaad705915feb843068b7 (diff) | |
download | chromium_src-9d9fcff2dec88a3269c2227cc6eda11d9ab02bc3.zip chromium_src-9d9fcff2dec88a3269c2227cc6eda11d9ab02bc3.tar.gz chromium_src-9d9fcff2dec88a3269c2227cc6eda11d9ab02bc3.tar.bz2 |
2011-03-16 Stephen White <senorblanco@chromium.org>
Reviewed by Kenneth Russell.
Implement GPU-accelerated shadows.
https://bugs.webkit.org/show_bug.cgi?id=56476
For hard shadows, we simply offset the CTM and draw in the shadow
color. For soft shadows, we use a separable Gaussian convolution,
with a bilinear downsample and Mitchell-Netravali upsample in order to
preserve quality.
* WebCore.gypi:
Add BicubicShader and ConvolutionShader to the build.
* platform/graphics/chromium/GLES2Canvas.cpp:
(WebCore::GLES2Canvas::State::State):
Add shadow-related members to the GLES2Canvas::State
(WebCore::GLES2Canvas::State::shadowActive):
Add a helper function to know if shadows are active.
(WebCore::GLES2Canvas::clearRect):
(WebCore::GLES2Canvas::scissorClear):
Refactor the scissor clearing function out of clearRect().
(WebCore::GLES2Canvas::fillPath):
Add hook for shadow rendering in paths. Bind framebuffer at this level.
(WebCore::GLES2Canvas::fillRect):
Add hook for shadow rendering in rects. Bind framebuffer at this level.
(WebCore::GLES2Canvas::fillRectInternal):
Rename fillRect() -> fillRectInternal(), which does bind its vertex
buffer, but does not bind the framebuffer.
(WebCore::GLES2Canvas::setShadowColor):
(WebCore::GLES2Canvas::setShadowOffset):
(WebCore::GLES2Canvas::setShadowBlur):
(WebCore::GLES2Canvas::setShadowsIgnoreTransforms):
Implement graphicsContext-style setters for shadow parameters.
(WebCore::GLES2Canvas::clipPath):
Call fillPathInternal(), not fillPath().
(WebCore::GLES2Canvas::restore):
(WebCore::GLES2Canvas::drawTexturedRect):
Bind the framebuffer at this level. Do not bind vertices here (will
be done in drawTexturedQuad).
(WebCore::GLES2Canvas::drawTexturedRectTile):
drawQuad() -> drawTexturedQuad().
(WebCore::GLES2Canvas::convolveRect):
Implement one pass of a convolution filter (X or Y).
(WebCore::gauss):
(WebCore::buildKernel):
Some helper functions to build a Gaussian convolution kernel.
(WebCore::GLES2Canvas::drawTexturedQuad):
Rename drawQuad() -> drawTexturedQuad(), to be more clear. Do not
bind the framebuffer at this level (it will be done higher).
(WebCore::GLES2Canvas::drawTexturedQuadMitchell):
Implement Mitchell-Netravali bicubic sampling, using BicubicShader.
(WebCore::GLES2Canvas::fillPathInternal):
Rename fillPath() -> fillPathInternal(), which does use quad vertices,
but does not bind the framebuffer or set the compositing mode.
(WebCore::GLES2Canvas::flipRect):
Implement a helper function to flip a rectangle in Y within the canvas.
(WebCore::GLES2Canvas::clearBorders):
Implement a helper function to clear an n-pixel border around a rect.
(WebCore::GLES2Canvas::beginShadowDraw):
Setup before drawing a primitive's shadow: for hard shadows, just
offset the CTM by the shadow offset. For soft shadows, bind to an
offscreen DrawingBuffer.
(WebCore::GLES2Canvas::endShadowDraw):
Tear-down after drawing a primitive's shadow: for hard shadows, just
restore the CTM. For soft shadows, downsample (if necessary), then
blur in X, blur in Y, upsample if necessary).
* platform/graphics/chromium/GLES2Canvas.h:
* platform/graphics/gpu/BicubicShader.cpp: Added.
(WebCore::BicubicShader::BicubicShader):
(WebCore::BicubicShader::create):
(WebCore::BicubicShader::use):
* platform/graphics/gpu/BicubicShader.h: Added.
Implement a bicubic image filtering shader.
* platform/graphics/gpu/ConvolutionShader.cpp: Added.
(WebCore::ConvolutionShader::ConvolutionShader):
(WebCore::ConvolutionShader::create):
(WebCore::ConvolutionShader::use):
* platform/graphics/gpu/ConvolutionShader.h: Added.
Implement a 1-dimensional convolution shader. In order to minimize
texture samples, this shader is parameterized at compile time by the
width of the convolution kernel.
* platform/graphics/gpu/DrawingBuffer.h:
(WebCore::DrawingBuffer::colorBuffer):
Add an accessor to retrieve a DrawingBuffer's texture ID.
* platform/graphics/gpu/SharedGraphicsContext3D.cpp:
(WebCore::SharedGraphicsContext3D::create):
(WebCore::SharedGraphicsContext3D::SharedGraphicsContext3D):
(WebCore::SharedGraphicsContext3D::useBicubicProgram):
(WebCore::SharedGraphicsContext3D::useConvolutionProgram):
Create BicubicShader and cMaxKernelWidth ConvolutionShader's (one for
each possible kernel width).
(WebCore::SharedGraphicsContext3D::getOffscreenBuffer):
Implement a simple cache of offscreen DrawingBuffers, integer-indexed.
This is done to minimize the VRAM usage: only 2 buffers are used for
all canvases.
* platform/graphics/gpu/SharedGraphicsContext3D.h:
Add bicubic and convolution shader members, and useXXX() functions.
* platform/graphics/skia/GraphicsContextSkia.cpp:
(WebCore::GraphicsContext::setPlatformShadow):
Hook into GraphicsContextSkia's platform shadow setters to set
parameters on GLES2Canvas.
* platform/graphics/skia/PlatformContextSkia.cpp:
(WebCore::PlatformContextSkia::canAccelerate):
Remove shadows (loopers) from the list of things we can't accelerate.
2011-03-16 Stephen White <senorblanco@chromium.org>
Reviewed by Kenneth Russell.
Canvas2D GPU acceleration should support shadows
https://bugs.webkit.org/show_bug.cgi?id=56476
* fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js:
(shouldBeAround):
Widen the threshold for this test, which doesn't seem to allow for
a true Gaussian blur implementation.
* platform/chromium/test_expectations.txt:
Update some tests which are now passing on GPU, and some which time out
due to Mesa slowness.
git-svn-id: svn://svn.chromium.org/blink/trunk@81509 bbb929c8-8fbe-4397-9dbb-9b2b20218538
16 files changed, 882 insertions, 42 deletions
diff --git a/third_party/WebKit/LayoutTests/ChangeLog b/third_party/WebKit/LayoutTests/ChangeLog index b7131cd..36e4a90 100644 --- a/third_party/WebKit/LayoutTests/ChangeLog +++ b/third_party/WebKit/LayoutTests/ChangeLog @@ -1,3 +1,18 @@ +2011-03-16 Stephen White <senorblanco@chromium.org> + + Reviewed by Kenneth Russell. + + Canvas2D GPU acceleration should support shadows + https://bugs.webkit.org/show_bug.cgi?id=56476 + + * fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js: + (shouldBeAround): + Widen the threshold for this test, which doesn't seem to allow for + a true Gaussian blur implementation. + * platform/chromium/test_expectations.txt: + Update some tests which are now passing on GPU, and some which time out + due to Mesa slowness. + 2011-03-18 James Simonsen <simonjam@chromium.org> [Chromium] Unreviewed, re-enable some stable tests and add a flaky one. @@ -318,6 +333,7 @@ * platform/win-wk2/inspector/console: Added. * platform/win-wk2/inspector/console/command-line-api-inspect-expected.txt: Added. +>>>>>>> .r81488 2011-03-18 Alexander Pavlov <apavlov@chromium.org> [Chromium] Unreviewed, suppress editing/deleting/5206311-1.html crashes on Mac Debug diff --git a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js index a090b47..5c5c55a 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js +++ b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js @@ -19,7 +19,7 @@ function shouldBeAround(a, b) evalA = e; } - if (Math.abs(evalA - b) < 10) + if (Math.abs(evalA - b) < 20) print("PASS " + a + " is around " + b , "green") else print("FAIL " + a + " is not around " + b + " (actual: " + evalA + ")", "red"); diff --git a/third_party/WebKit/LayoutTests/platform/chromium/test_expectations.txt b/third_party/WebKit/LayoutTests/platform/chromium/test_expectations.txt index 53ac7b5..15b9d51 100755 --- a/third_party/WebKit/LayoutTests/platform/chromium/test_expectations.txt +++ b/third_party/WebKit/LayoutTests/platform/chromium/test_expectations.txt @@ -1679,7 +1679,7 @@ BUGCR27551 WIN : fast/css/shadow-multiple.html = IMAGE // WebKit merge 50756:50820, possibly due to WebKit r50808/r50786 and Chromium r31715 BUGCR27553 WIN : fast/text/atsui-partial-selection.html = IMAGE -BUGCR22700 WIN LINUX : fast/canvas/canvas-shadow.html = TEXT +BUGCR22700 CPU WIN LINUX : fast/canvas/canvas-shadow.html = TEXT // Failures from merge 50972:51042 // The test requires DRT/Test Shell to support error page handling. @@ -2557,7 +2557,7 @@ BUGCR61739 WIN LINUX DEBUG : animations/suspend-resume-animation-events.html = C // New tests added with http://trac.webkit.org/changeset/72472 and further. // See https://bugs.webkit.org/show_bug.cgi?id=51982 for more info. BUGWK52509 : svg/css/rect-gradient-stroke-shadow.svg = IMAGE -BUGCR63921 LINUX WIN : fast/canvas/canvas-fillPath-shadow.html = TEXT +BUGCR63921 CPU LINUX WIN : fast/canvas/canvas-fillPath-shadow.html = TEXT BUGCR63921 CPU LINUX WIN : fast/canvas/canvas-fillPath-gradient-shadow.html = TEXT BUGCR63921 CPU LINUX WIN : fast/canvas/canvas-fillPath-pattern-shadow.html = TEXT BUGCR63921 CPU LINUX WIN : fast/canvas/canvas-fillPath-alpha-shadow.html = TEXT @@ -3279,3 +3279,6 @@ BUGCR76716 DEBUG : fast/css/first-child-pseudo-class.html = PASS TEXT BUGCR76616 WIN LINUX : fast/text/emphasis-combined-text.html = IMAGE+TEXT // Needs leopard baseline. Snow leopard is horribly broken. BUGCR76616 MAC : fast/text/emphasis-combined-text.html = IMAGE+TEXT + +BUGWK56677 GPU WIN LINUX : fast/canvas/canvas-drawImage-shadow.html = TEXT +BUGWK56677 GPU WIN LINUX : fast/canvas/canvas-scale-drawImage-shadow.html = TEXT diff --git a/third_party/WebKit/Source/WebCore/ChangeLog b/third_party/WebKit/Source/WebCore/ChangeLog index 3f229c2..5bbd5fd 100644 --- a/third_party/WebKit/Source/WebCore/ChangeLog +++ b/third_party/WebKit/Source/WebCore/ChangeLog @@ -1,3 +1,109 @@ +2011-03-16 Stephen White <senorblanco@chromium.org> + + Reviewed by Kenneth Russell. + + Implement GPU-accelerated shadows. + https://bugs.webkit.org/show_bug.cgi?id=56476 + + For hard shadows, we simply offset the CTM and draw in the shadow + color. For soft shadows, we use a separable Gaussian convolution, + with a bilinear downsample and Mitchell-Netravali upsample in order to + preserve quality. + + * WebCore.gypi: + Add BicubicShader and ConvolutionShader to the build. + * platform/graphics/chromium/GLES2Canvas.cpp: + (WebCore::GLES2Canvas::State::State): + Add shadow-related members to the GLES2Canvas::State + (WebCore::GLES2Canvas::State::shadowActive): + Add a helper function to know if shadows are active. + (WebCore::GLES2Canvas::clearRect): + (WebCore::GLES2Canvas::scissorClear): + Refactor the scissor clearing function out of clearRect(). + (WebCore::GLES2Canvas::fillPath): + Add hook for shadow rendering in paths. Bind framebuffer at this level. + (WebCore::GLES2Canvas::fillRect): + Add hook for shadow rendering in rects. Bind framebuffer at this level. + (WebCore::GLES2Canvas::fillRectInternal): + Rename fillRect() -> fillRectInternal(), which does bind its vertex + buffer, but does not bind the framebuffer. + (WebCore::GLES2Canvas::setShadowColor): + (WebCore::GLES2Canvas::setShadowOffset): + (WebCore::GLES2Canvas::setShadowBlur): + (WebCore::GLES2Canvas::setShadowsIgnoreTransforms): + Implement graphicsContext-style setters for shadow parameters. + (WebCore::GLES2Canvas::clipPath): + Call fillPathInternal(), not fillPath(). + (WebCore::GLES2Canvas::restore): + (WebCore::GLES2Canvas::drawTexturedRect): + Bind the framebuffer at this level. Do not bind vertices here (will + be done in drawTexturedQuad). + (WebCore::GLES2Canvas::drawTexturedRectTile): + drawQuad() -> drawTexturedQuad(). + (WebCore::GLES2Canvas::convolveRect): + Implement one pass of a convolution filter (X or Y). + (WebCore::gauss): + (WebCore::buildKernel): + Some helper functions to build a Gaussian convolution kernel. + (WebCore::GLES2Canvas::drawTexturedQuad): + Rename drawQuad() -> drawTexturedQuad(), to be more clear. Do not + bind the framebuffer at this level (it will be done higher). + (WebCore::GLES2Canvas::drawTexturedQuadMitchell): + Implement Mitchell-Netravali bicubic sampling, using BicubicShader. + (WebCore::GLES2Canvas::fillPathInternal): + Rename fillPath() -> fillPathInternal(), which does use quad vertices, + but does not bind the framebuffer or set the compositing mode. + (WebCore::GLES2Canvas::flipRect): + Implement a helper function to flip a rectangle in Y within the canvas. + (WebCore::GLES2Canvas::clearBorders): + Implement a helper function to clear an n-pixel border around a rect. + (WebCore::GLES2Canvas::beginShadowDraw): + Setup before drawing a primitive's shadow: for hard shadows, just + offset the CTM by the shadow offset. For soft shadows, bind to an + offscreen DrawingBuffer. + (WebCore::GLES2Canvas::endShadowDraw): + Tear-down after drawing a primitive's shadow: for hard shadows, just + restore the CTM. For soft shadows, downsample (if necessary), then + blur in X, blur in Y, upsample if necessary). + * platform/graphics/chromium/GLES2Canvas.h: + * platform/graphics/gpu/BicubicShader.cpp: Added. + (WebCore::BicubicShader::BicubicShader): + (WebCore::BicubicShader::create): + (WebCore::BicubicShader::use): + * platform/graphics/gpu/BicubicShader.h: Added. + Implement a bicubic image filtering shader. + * platform/graphics/gpu/ConvolutionShader.cpp: Added. + (WebCore::ConvolutionShader::ConvolutionShader): + (WebCore::ConvolutionShader::create): + (WebCore::ConvolutionShader::use): + * platform/graphics/gpu/ConvolutionShader.h: Added. + Implement a 1-dimensional convolution shader. In order to minimize + texture samples, this shader is parameterized at compile time by the + width of the convolution kernel. + * platform/graphics/gpu/DrawingBuffer.h: + (WebCore::DrawingBuffer::colorBuffer): + Add an accessor to retrieve a DrawingBuffer's texture ID. + * platform/graphics/gpu/SharedGraphicsContext3D.cpp: + (WebCore::SharedGraphicsContext3D::create): + (WebCore::SharedGraphicsContext3D::SharedGraphicsContext3D): + (WebCore::SharedGraphicsContext3D::useBicubicProgram): + (WebCore::SharedGraphicsContext3D::useConvolutionProgram): + Create BicubicShader and cMaxKernelWidth ConvolutionShader's (one for + each possible kernel width). + (WebCore::SharedGraphicsContext3D::getOffscreenBuffer): + Implement a simple cache of offscreen DrawingBuffers, integer-indexed. + This is done to minimize the VRAM usage: only 2 buffers are used for + all canvases. + * platform/graphics/gpu/SharedGraphicsContext3D.h: + Add bicubic and convolution shader members, and useXXX() functions. + * platform/graphics/skia/GraphicsContextSkia.cpp: + (WebCore::GraphicsContext::setPlatformShadow): + Hook into GraphicsContextSkia's platform shadow setters to set + parameters on GLES2Canvas. + * platform/graphics/skia/PlatformContextSkia.cpp: + (WebCore::PlatformContextSkia::canAccelerate): + Remove shadows (loopers) from the list of things we can't accelerate. + 2011-03-18 Andreas Kling <kling@webkit.org> Reviewed by Darin Adler. diff --git a/third_party/WebKit/Source/WebCore/WebCore.gypi b/third_party/WebKit/Source/WebCore/WebCore.gypi index 2e618f9..be8f0df 100644 --- a/third_party/WebKit/Source/WebCore/WebCore.gypi +++ b/third_party/WebKit/Source/WebCore/WebCore.gypi @@ -4244,6 +4244,10 @@ 'platform/graphics/freetype/FontPlatformDataFreeType.cpp', 'platform/graphics/freetype/GlyphPageTreeNodeFreeType.cpp', 'platform/graphics/freetype/SimpleFontDataFreeType.cpp', + 'platform/graphics/gpu/BicubicShader.cpp', + 'platform/graphics/gpu/BicubicShader.h', + 'platform/graphics/gpu/ConvolutionShader.cpp', + 'platform/graphics/gpu/ConvolutionShader.h', 'platform/graphics/gpu/DrawingBuffer.cpp', 'platform/graphics/gpu/DrawingBuffer.h', 'platform/graphics/gpu/LoopBlinnClassifier.cpp', diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp index 2ff6b8b..9e1255d 100644 --- a/third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp +++ b/third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp @@ -65,26 +65,38 @@ typedef WTF::Vector<double> DoubleVector; struct GLES2Canvas::State { State() : m_fillColor(0, 0, 0, 255) + , m_shadowColor(0, 0, 0, 0) , m_alpha(1.0f) , m_compositeOp(CompositeSourceOver) , m_clippingEnabled(false) + , m_shadowOffset(0, 0) + , m_shadowBlur(0) + , m_shadowsIgnoreTransforms(false) { } State(const State& other) : m_fillColor(other.m_fillColor) + , m_shadowColor(other.m_shadowColor) , m_alpha(other.m_alpha) , m_compositeOp(other.m_compositeOp) , m_ctm(other.m_ctm) , m_clippingPaths() // Don't copy; clipping paths are tracked per-state. , m_clippingEnabled(other.m_clippingEnabled) + , m_shadowOffset(other.m_shadowOffset) + , m_shadowBlur(other.m_shadowBlur) + , m_shadowsIgnoreTransforms(other.m_shadowsIgnoreTransforms) { } Color m_fillColor; + Color m_shadowColor; float m_alpha; CompositeOperator m_compositeOp; AffineTransform m_ctm; WTF::Vector<Path> m_clippingPaths; bool m_clippingEnabled; + FloatSize m_shadowOffset; + float m_shadowBlur; + bool m_shadowsIgnoreTransforms; // Helper function for applying the state's alpha value to the given input // color to produce a new output color. The logic is the same as @@ -100,7 +112,10 @@ struct GLES2Canvas::State { int a = (c.alpha() * s) >> 8; return Color(c.red(), c.green(), c.blue(), a); } - + bool shadowActive() const + { + return m_shadowColor.alpha() > 0 && (m_shadowBlur || m_shadowOffset.width() || m_shadowOffset.height()); + } }; static inline FloatPoint operator*(const FloatPoint& f, float scale) @@ -194,11 +209,7 @@ void GLES2Canvas::clearRect(const FloatRect& rect) { bindFramebuffer(); if (m_state->m_ctm.isIdentity() && !m_state->m_clippingEnabled) { - m_context->scissor(rect.x(), m_size.height() - rect.height() - rect.y(), rect.width(), rect.height()); - m_context->enable(GraphicsContext3D::SCISSOR_TEST); - m_context->clearColor(Color(RGBA32(0))); - m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); - m_context->disable(GraphicsContext3D::SCISSOR_TEST); + scissorClear(rect.x(), rect.y(), rect.width(), rect.height()); } else { save(); setCompositeOperation(CompositeClear); @@ -207,35 +218,64 @@ void GLES2Canvas::clearRect(const FloatRect& rect) } } +void GLES2Canvas::scissorClear(float x, float y, float width, float height) +{ + int intX = static_cast<int>(x + 0.5f); + int intY = static_cast<int>(y + 0.5f); + int intWidth = static_cast<int>(x + width + 0.5f) - intX; + int intHeight = static_cast<int>(y + height + 0.5f) - intY; + m_context->scissor(intX, m_size.height() - intHeight - intY, intWidth, intHeight); + m_context->enable(GraphicsContext3D::SCISSOR_TEST); + m_context->clearColor(Color(RGBA32(0))); + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); + m_context->disable(GraphicsContext3D::SCISSOR_TEST); +} + void GLES2Canvas::fillPath(const Path& path) { + bindFramebuffer(); m_context->applyCompositeOperator(m_state->m_compositeOp); applyClipping(m_state->m_clippingEnabled); - fillPath(path, m_state->applyAlpha(m_state->m_fillColor)); + + if (m_state->shadowActive()) { + beginShadowDraw(); + fillPathInternal(path, m_state->m_shadowColor); + endShadowDraw(path.boundingRect()); + } + fillPathInternal(path, m_state->applyAlpha(m_state->m_fillColor)); } void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { + bindFramebuffer(); m_context->applyCompositeOperator(m_state->m_compositeOp); applyClipping(m_state->m_clippingEnabled); - m_context->useQuadVertices(); + if (m_state->shadowActive()) { + beginShadowDraw(); + fillRectInternal(rect, m_state->m_shadowColor); + endShadowDraw(rect); + } + fillRectInternal(rect, color); +} + +void GLES2Canvas::fillRect(const FloatRect& rect) +{ + fillRect(rect, m_state->applyAlpha(m_state->m_fillColor), ColorSpaceDeviceRGB); +} + +void GLES2Canvas::fillRectInternal(const FloatRect& rect, const Color& color) +{ AffineTransform matrix(m_flipMatrix); matrix *= m_state->m_ctm; matrix.translate(rect.x(), rect.y()); matrix.scale(rect.width(), rect.height()); + m_context->useQuadVertices(); m_context->useFillSolidProgram(matrix, color); - - bindFramebuffer(); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); } -void GLES2Canvas::fillRect(const FloatRect& rect) -{ - fillRect(rect, m_state->applyAlpha(m_state->m_fillColor), ColorSpaceDeviceRGB); -} - void GLES2Canvas::setFillColor(const Color& color, ColorSpace colorSpace) { m_state->m_fillColor = color; @@ -246,6 +286,26 @@ void GLES2Canvas::setAlpha(float alpha) m_state->m_alpha = alpha; } +void GLES2Canvas::setShadowColor(const Color& color, ColorSpace) +{ + m_state->m_shadowColor = color; +} + +void GLES2Canvas::setShadowOffset(const FloatSize& offset) +{ + m_state->m_shadowOffset = offset; +} + +void GLES2Canvas::setShadowBlur(float shadowBlur) +{ + m_state->m_shadowBlur = shadowBlur; +} + +void GLES2Canvas::setShadowsIgnoreTransforms(bool shadowsIgnoreTransforms) +{ + m_state->m_shadowsIgnoreTransforms = shadowsIgnoreTransforms; +} + void GLES2Canvas::translate(float x, float y) { m_state->m_ctm.translate(x, y); @@ -278,7 +338,7 @@ void GLES2Canvas::clipPath(const Path& path) beginStencilDraw(); // Red is used so we can see it if it ends up in the color buffer. Color red(255, 0, 0, 255); - fillPath(path, red); + fillPathInternal(path, red); m_state->m_clippingPaths.append(path); m_state->m_clippingEnabled = true; } @@ -311,7 +371,7 @@ void GLES2Canvas::restore() for (pathIter = clippingPaths.begin(); pathIter < clippingPaths.end(); ++pathIter) { // Red is used so we can see it if it ends up in the color buffer. Color red(255, 0, 0, 255); - fillPath(*pathIter, red); + fillPathInternal(*pathIter, red); } } } @@ -319,15 +379,15 @@ void GLES2Canvas::restore() void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) { + bindFramebuffer(); m_context->applyCompositeOperator(compositeOp); applyClipping(false); - m_context->useQuadVertices(); m_context->setActiveTexture(GraphicsContext3D::TEXTURE0); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture); - drawQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha); + drawTexturedQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha); } void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) @@ -338,12 +398,12 @@ void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, c void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp, bool clip) { + bindFramebuffer(); m_context->applyCompositeOperator(compositeOp); applyClipping(clip); const TilingData& tiles = texture->tiles(); IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect); - m_context->useQuadVertices(); m_context->setActiveTexture(GraphicsContext3D::TEXTURE0); for (int y = tileIdxRect.y(); y <= tileIdxRect.maxY(); y++) { @@ -367,13 +427,18 @@ void GLES2Canvas::drawTexturedRectTile(Texture* texture, int tile, const FloatRe IntRect tileBoundsWithBorder = tiles.tileBoundsWithBorder(tile); - drawQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha); + drawTexturedQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha); } -void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) +void GLES2Canvas::convolveRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, float imageIncrement[2], const float* kernel, int kernelWidth) { + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST); + AffineTransform matrix(m_flipMatrix); - matrix *= transform; matrix.translate(dstRect.x(), dstRect.y()); matrix.scale(dstRect.width(), dstRect.height()); @@ -382,13 +447,79 @@ void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, texMatrix.translate(srcRect.x(), srcRect.y()); texMatrix.scale(srcRect.width(), srcRect.height()); - bindFramebuffer(); + m_context->useQuadVertices(); + m_context->useConvolutionProgram(matrix, texMatrix, kernel, kernelWidth, imageIncrement); + m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); + checkGLError("glDrawArrays"); +} + +static float gauss(float x, float sigma) +{ + return exp(- (x * x) / (2.0f * sigma * sigma)); +} + +static void buildKernel(float sigma, float* kernel, int kernelWidth) +{ + float halfWidth = (kernelWidth - 1.0f) / 2.0f; + float sum = 0.0f; + for (int i = 0; i < kernelWidth; ++i) { + kernel[i] = gauss(i - halfWidth, sigma); + sum += kernel[i]; + } + // Normalize the kernel + float scale = 1.0f / sum; + for (int i = 0; i < kernelWidth; ++i) + kernel[i] *= scale; +} +void GLES2Canvas::drawTexturedQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) +{ + AffineTransform matrix(m_flipMatrix); + matrix *= transform; + matrix.translate(dstRect.x(), dstRect.y()); + matrix.scale(dstRect.width(), dstRect.height()); + + AffineTransform texMatrix; + texMatrix.scale(1.0f / textureSize.width(), 1.0f / textureSize.height()); + texMatrix.translate(srcRect.x(), srcRect.y()); + texMatrix.scale(srcRect.width(), srcRect.height()); + + m_context->useQuadVertices(); m_context->useTextureProgram(matrix, texMatrix, alpha); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); checkGLError("glDrawArrays"); } +void GLES2Canvas::drawTexturedQuadMitchell(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) +{ + static const float mitchellCoefficients[16] = { + 0.0f / 18.0f, 1.0f / 18.0f, 16.0f / 18.0f, 1.0f / 18.0f, + 0.0f / 18.0f, 9.0f / 18.0f, 0.0f / 18.0f, -9.0f / 18.0f, + -6.0f / 18.0f, 27.0f / 18.0f, -36.0f / 18.0f, 15.0f / 18.0f, + 7.0f / 18.0f, -21.0f / 18.0f, 21.0f / 18.0f, -7.0f / 18.0f, + }; + + AffineTransform matrix(m_flipMatrix); + matrix *= transform; + matrix.translate(dstRect.x(), dstRect.y()); + matrix.scale(dstRect.width(), dstRect.height()); + + float imageIncrement[2] = { 1.0f / textureSize.width(), 1.0f / textureSize.height() }; + + AffineTransform texMatrix; + texMatrix.scale(imageIncrement[0], imageIncrement[1]); + texMatrix.translate(srcRect.x(), srcRect.y()); + texMatrix.scale(srcRect.width(), srcRect.height()); + + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST); + + m_context->useQuadVertices(); + m_context->useBicubicProgram(matrix, texMatrix, mitchellCoefficients, imageIncrement, alpha); + m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); + checkGLError("glDrawArrays"); +} + void GLES2Canvas::setCompositeOperation(CompositeOperator op) { m_state->m_compositeOp = op; @@ -554,12 +685,9 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig *count = indices.size(); } -void GLES2Canvas::fillPath(const Path& path, const Color& color) +void GLES2Canvas::fillPathInternal(const Path& path, const Color& color) { if (SharedGraphicsContext3D::useLoopBlinnForPathRendering()) { - bindFramebuffer(); - m_context->applyCompositeOperator(m_state->m_compositeOp); - m_pathCache.clear(); LoopBlinnPathProcessor processor; processor.process(path, m_pathCache); @@ -590,18 +718,18 @@ void GLES2Canvas::fillPath(const Path& path, const Color& color) int count; unsigned vertexBuffer, indexBuffer; createVertexBufferFromPath(path, &count, &vertexBuffer, &indexBuffer); + + AffineTransform matrix(m_flipMatrix); + matrix *= m_state->m_ctm; + m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vertexBuffer); checkGLError("bindBuffer"); m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indexBuffer); checkGLError("bindBuffer"); - AffineTransform matrix(m_flipMatrix); - matrix *= m_state->m_ctm; - m_context->useFillSolidProgram(matrix, color); checkGLError("useFillSolidProgram"); - bindFramebuffer(); m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, count, GraphicsContext3D::UNSIGNED_SHORT, 0); checkGLError("drawArrays"); @@ -613,6 +741,136 @@ void GLES2Canvas::fillPath(const Path& path, const Color& color) } } +FloatRect GLES2Canvas::flipRect(const FloatRect& rect) +{ + FloatRect flippedRect(rect); + flippedRect.setY(m_size.height() - rect.y()); + flippedRect.setHeight(-rect.height()); + return flippedRect; +} + +void GLES2Canvas::clearBorders(const FloatRect& rect, int width) +{ + scissorClear(rect.x(), rect.y() - width, rect.width() + width, width); + scissorClear(rect.maxX(), rect.y(), width, rect.height() + width); + scissorClear(rect.x() - width, rect.maxY(), rect.width() + width, width); + scissorClear(rect.x() - width, rect.y() - width, width, rect.height() + width); +} + +void GLES2Canvas::beginShadowDraw() +{ + float offsetX = m_state->m_shadowOffset.width(); + float offsetY = m_state->m_shadowOffset.height(); + save(); + if (m_state->m_shadowsIgnoreTransforms) { + AffineTransform newCTM; + newCTM.translate(offsetX, -offsetY); + newCTM *= m_state->m_ctm; + m_state->m_ctm = newCTM; + } else + m_state->m_ctm.translate(offsetX, offsetY); + + if (m_state->m_shadowBlur > 0) { + // Draw hard shadow to offscreen buffer 0. + DrawingBuffer* dstBuffer = m_context->getOffscreenBuffer(0, m_size); + dstBuffer->bind(); + m_context->applyCompositeOperator(CompositeCopy); + applyClipping(false); + m_context->clearColor(Color(RGBA32(0))); + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); + } +} + +void GLES2Canvas::endShadowDraw(const FloatRect& boundingBox) +{ + if (m_state->m_shadowBlur > 0) { + // Buffer 0 contains the primitive drawn with a hard shadow. + DrawingBuffer* srcBuffer = m_context->getOffscreenBuffer(0, m_size); + DrawingBuffer* dstBuffer = m_context->getOffscreenBuffer(1, m_size); + + float sigma = m_state->m_shadowBlur * 0.333333f; + FloatRect shadowBoundingBox(m_state->m_ctm.mapRect(boundingBox)); + FloatRect rect(FloatPoint(0, 0), m_size); + FloatRect srcRect(shadowBoundingBox); + + int scaleFactor = 1; + while (sigma > cMaxSigma) { + srcRect.scale(0.5f); + scaleFactor *= 2; + sigma *= 0.5f; + } + srcRect = enclosingIntRect(srcRect); + srcRect.scale(scaleFactor); + for (int i = 1; i < scaleFactor; i *= 2) { + dstBuffer->bind(); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, srcBuffer->colorBuffer()); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + FloatRect dstRect(srcRect); + dstRect.scale(0.5f); + // Clear out 1 pixel border for linear filtering. + clearBorders(dstRect, 1); + drawTexturedQuad(srcBuffer->size(), flipRect(srcRect), dstRect, AffineTransform(), 1.0); + srcRect = dstRect; + std::swap(srcBuffer, dstBuffer); + } + + int halfWidth = static_cast<int>(sigma * 3.0f); + int kernelWidth = halfWidth * 2 + 1; + OwnArrayPtr<float> kernel = adoptArrayPtr(new float[kernelWidth]); + buildKernel(sigma, kernel.get(), kernelWidth); + + if (scaleFactor > 1) { + scissorClear(srcRect.maxX(), srcRect.y(), kernelWidth, srcRect.height()); + scissorClear(srcRect.x() - kernelWidth, srcRect.y(), kernelWidth, srcRect.height()); + } + + // Blur in X offscreen. + dstBuffer->bind(); + srcRect.inflateX(halfWidth); + srcRect.intersect(rect); + float imageIncrementX[2] = {1.0f / srcBuffer->size().width(), 0.0f}; + convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementX, kernel.get(), kernelWidth); + + if (scaleFactor > 1) { + scissorClear(srcRect.x(), srcRect.maxY(), srcRect.width(), kernelWidth); + scissorClear(srcRect.x(), srcRect.y() - kernelWidth, srcRect.width(), kernelWidth); + } + srcRect.inflateY(halfWidth); + srcRect.intersect(rect); + std::swap(srcBuffer, dstBuffer); + + float imageIncrementY[2] = {0.0f, 1.0f / srcBuffer->size().height()}; + if (scaleFactor > 1) { + // Blur in Y offscreen. + dstBuffer->bind(); + convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementY, kernel.get(), kernelWidth); + // Clear out 2 pixel border for bicubic filtering. + clearBorders(srcRect, 2); + std::swap(srcBuffer, dstBuffer); + + // Upsample srcBuffer -> main framebuffer using bicubic filtering. + bindFramebuffer(); + m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->m_clippingEnabled); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, srcBuffer->colorBuffer()); + FloatRect dstRect = srcRect; + dstRect.scale(scaleFactor); + drawTexturedQuadMitchell(srcBuffer->size(), flipRect(srcRect), dstRect, AffineTransform(), 1.0); + } else { + // Blur in Y directly to framebuffer. + bindFramebuffer(); + m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->m_clippingEnabled); + + convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementY, kernel.get(), kernelWidth); + } + } + restore(); +} + void GLES2Canvas::beginStencilDraw() { // Turn on stencil test. diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h b/third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h index 8887a16..0782df1 100644 --- a/third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h +++ b/third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h @@ -64,6 +64,10 @@ public: void clearRect(const FloatRect&); void setFillColor(const Color&, ColorSpace); void setAlpha(float alpha); + void setShadowColor(const Color&, ColorSpace); + void setShadowOffset(const FloatSize&); + void setShadowBlur(float); + void setShadowsIgnoreTransforms(bool); void setCompositeOperation(CompositeOperator); void translate(float x, float y); void rotate(float angleInRadians); @@ -96,11 +100,20 @@ public: DrawingBuffer* drawingBuffer() const { return m_drawingBuffer; } private: + void scissorClear(float x, float y, float width, float height); void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); - void drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); + void drawTexturedQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); + void drawTexturedQuadMitchell(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); + void convolveRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, float imageIncrement[2], const float* kernel, int kernelWidth); + void applyCompositeOperator(CompositeOperator); void createVertexBufferFromPath(const Path&, int* count, unsigned* vertexBuffer, unsigned* indexBuffer); - void fillPath(const Path&, const Color&); + void fillPathInternal(const Path&, const Color&); + void fillRectInternal(const FloatRect&, const Color&); + FloatRect flipRect(const FloatRect&); + void clearBorders(const FloatRect&, int width); + void beginShadowDraw(); + void endShadowDraw(const FloatRect& boundingBox); void beginStencilDraw(); void applyClipping(bool enable); void checkGLError(const char* header); diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp new file mode 100644 index 0000000..40c9843 --- /dev/null +++ b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(ACCELERATED_2D_CANVAS) + +#include "BicubicShader.h" + +#include "GraphicsContext3D.h" + +namespace WebCore { + +BicubicShader::BicubicShader(GraphicsContext3D* context, unsigned program) + : Shader(context, program) + , m_matrixLocation(context->getUniformLocation(program, "matrix")) + , m_texMatrixLocation(context->getUniformLocation(program, "texMatrix")) + , m_coefficientsLocation(context->getUniformLocation(program, "coefficients")) + , m_imageIncrementLocation(context->getUniformLocation(program, "imageIncrement")) + , m_imageLocation(context->getUniformLocation(program, "image")) + , m_alphaLocation(context->getUniformLocation(program, "alpha")) + , m_positionLocation(context->getAttribLocation(program, "position")) +{ +} + +PassOwnPtr<BicubicShader> BicubicShader::create(GraphicsContext3D* context) +{ + static const char* vertexShaderSource = + "uniform mat3 matrix;\n" + "uniform mat3 texMatrix;\n" + "attribute vec3 position;\n" + "varying vec2 texCoord;\n" + "void main() {\n" + " texCoord = (texMatrix * position).xy;\n" + " gl_Position = vec4(matrix * position, 1.0);\n" + "}\n"; + static const char* fragmentShaderSource = + "#ifdef GL_ES\n" + "precision mediump float;\n" + "#endif\n" + "uniform sampler2D image;\n" + "uniform vec2 imageIncrement;\n" + "uniform mat4 coefficients;\n" + "uniform float alpha;\n" + "varying vec2 texCoord;\n" + "vec4 cubicBlend(float t, vec4 c0, vec4 c1, vec4 c2, vec4 c3) {\n" + " vec4 ts = vec4(1.0, t, t * t, t * t * t);\n" + " vec4 result = coefficients * ts;\n" + " return result.w * c0 + result.z * c1 + result.y * c2 + result.x * c3;\n" + "}\n" + "void main() {\n" + " vec2 imageCoord = texCoord;\n" + " vec2 f = fract(imageCoord / imageIncrement) - vec2(0.5, 0.5);\n" + " vec4 t00 = texture2D(image, imageCoord + imageIncrement * vec2(-1, -1));\n" + " vec4 t10 = texture2D(image, imageCoord + imageIncrement * vec2( 0, -1));\n" + " vec4 t20 = texture2D(image, imageCoord + imageIncrement * vec2( 1, -1));\n" + " vec4 t30 = texture2D(image, imageCoord + imageIncrement * vec2( 2, -1));\n" + " vec4 t0 = cubicBlend(f.x, t00, t10, t20, t30);\n" + " vec4 t01 = texture2D(image, imageCoord + imageIncrement * vec2(-1, 0));\n" + " vec4 t11 = texture2D(image, imageCoord + imageIncrement * vec2( 0, 0));\n" + " vec4 t21 = texture2D(image, imageCoord + imageIncrement * vec2( 1, 0));\n" + " vec4 t31 = texture2D(image, imageCoord + imageIncrement * vec2( 2, 0));\n" + " vec4 t1 = cubicBlend(f.x, t01, t11, t21, t31);\n" + " vec4 t02 = texture2D(image, imageCoord + imageIncrement * vec2(-1, 1));\n" + " vec4 t12 = texture2D(image, imageCoord + imageIncrement * vec2( 0, 1));\n" + " vec4 t22 = texture2D(image, imageCoord + imageIncrement * vec2( 1, 1));\n" + " vec4 t32 = texture2D(image, imageCoord + imageIncrement * vec2( 2, 1));\n" + " vec4 t2 = cubicBlend(f.x, t02, t12, t22, t32);\n" + " vec4 t03 = texture2D(image, imageCoord + imageIncrement * vec2(-1, 2));\n" + " vec4 t13 = texture2D(image, imageCoord + imageIncrement * vec2( 0, 2));\n" + " vec4 t23 = texture2D(image, imageCoord + imageIncrement * vec2( 1, 2));\n" + " vec4 t33 = texture2D(image, imageCoord + imageIncrement * vec2( 2, 2));\n" + " vec4 t3 = cubicBlend(f.x, t03, t13, t23, t33);\n" + " gl_FragColor = cubicBlend(f.y, t0, t1, t2, t3);\n" + "}\n"; + + unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource); + if (!program) + return 0; + + return new BicubicShader(context, program); +} + +void BicubicShader::use(const AffineTransform& transform, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha) +{ + m_context->useProgram(m_program); + float matrix[9]; + affineTo3x3(transform, matrix); + m_context->uniformMatrix3fv(m_matrixLocation, false /*transpose*/, matrix, 1 /*count*/); + + float texMatrix[9]; + affineTo3x3(texTransform, texMatrix); + m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, texMatrix, 1 /*count*/); + m_context->uniformMatrix4fv(m_coefficientsLocation, false /*transpose*/, const_cast<float *>(coefficients), 1 /*count*/); + + m_context->uniform2f(m_imageIncrementLocation, imageIncrement[0], imageIncrement[1]); + + // For now, we always use texture unit 0. If that ever changes, we should + // expose this parameter to the caller. + m_context->uniform1i(m_imageLocation, 0); + m_context->uniform1f(m_alphaLocation, alpha); + + m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); + + m_context->enableVertexAttribArray(m_positionLocation); +} + +} + +#endif diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/BicubicShader.h b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/BicubicShader.h new file mode 100644 index 0000000..f7522f4 --- /dev/null +++ b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/BicubicShader.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BicubicShader_h +#define BicubicShader_h + +#include "Shader.h" + +namespace WebCore { + +class BicubicShader : public Shader { +public: + static PassOwnPtr<BicubicShader> create(GraphicsContext3D*); + + void use(const AffineTransform&, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha); + +private: + BicubicShader(GraphicsContext3D*, unsigned program); + + int m_matrixLocation; + int m_texMatrixLocation; + int m_coefficientsLocation; + int m_imageIncrementLocation; + int m_imageLocation; + int m_alphaLocation; + int m_positionLocation; +}; + +} + +#endif // BicubicShader_h diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp new file mode 100644 index 0000000..f0b6bd9 --- /dev/null +++ b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(ACCELERATED_2D_CANVAS) + +#include "ConvolutionShader.h" + +#include "GraphicsContext3D.h" +#include "StringExtras.h" + +namespace WebCore { + +ConvolutionShader::ConvolutionShader(GraphicsContext3D* context, unsigned program, int kernelWidth) + : Shader(context, program) + , m_kernelWidth(kernelWidth) + , m_matrixLocation(context->getUniformLocation(program, "matrix")) + , m_texMatrixLocation(context->getUniformLocation(program, "texMatrix")) + , m_kernelLocation(context->getUniformLocation(program, "kernel")) + , m_imageLocation(context->getUniformLocation(program, "image")) + , m_imageIncrementLocation(context->getUniformLocation(program, "imageIncrement")) + , m_positionLocation(context->getAttribLocation(program, "position")) +{ +} + +PassOwnPtr<ConvolutionShader> ConvolutionShader::create(GraphicsContext3D* context, int kernelWidth) +{ + static const char* vertexShaderRaw = + "#define KERNEL_WIDTH %d\n" + "uniform mat3 matrix;\n" + "uniform mat3 texMatrix;\n" + "uniform vec2 imageIncrement;\n" + "attribute vec3 position;\n" + "varying vec2 imageCoord;\n" + "void main() {\n" + " // Offset image coords by half of kernel width, in image texels\n" + " gl_Position = vec4(matrix * position, 1.0);\n" + " float scale = (float(KERNEL_WIDTH) - 1.0) / 2.0;\n" + " imageCoord = (texMatrix * position).xy - vec2(scale, scale) * imageIncrement;\n" + "}\n"; + char vertexShaderSource[1024]; + snprintf(vertexShaderSource, sizeof(vertexShaderSource), vertexShaderRaw, kernelWidth); + static const char* fragmentShaderRaw = + "#ifdef GL_ES\n" + "precision mediump float;\n" + "#endif\n" + "#define KERNEL_WIDTH %d\n" + "uniform sampler2D image;\n" + "uniform float kernel[KERNEL_WIDTH];\n" + "uniform vec2 imageIncrement;\n" + "varying vec2 imageCoord;\n" + "void main() {\n" + " vec2 coord = imageCoord;\n" + " vec4 sum = vec4(0, 0, 0, 0);\n" + " for (int i = 0; i < KERNEL_WIDTH; i++) {\n" + " sum += texture2D(image, coord) * kernel[i];\n" + " coord += imageIncrement;\n" + " }\n" + " gl_FragColor = sum;\n" + "}\n"; + char fragmentShaderSource[1024]; + snprintf(fragmentShaderSource, sizeof(fragmentShaderSource), fragmentShaderRaw, kernelWidth); + + unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource); + if (!program) + return 0; + return new ConvolutionShader(context, program, kernelWidth); +} + +void ConvolutionShader::use(const AffineTransform& transform, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]) +{ + m_context->useProgram(m_program); + float matrix[9]; + affineTo3x3(transform, matrix); + m_context->uniformMatrix3fv(m_matrixLocation, false /*transpose*/, matrix, 1 /*count*/); + + float texMatrix[9]; + affineTo3x3(texTransform, texMatrix); + m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, texMatrix, 1 /*count*/); + + m_context->uniform2f(m_imageIncrementLocation, imageIncrement[0], imageIncrement[1]); + + // For now, we always use texture unit 0. If that ever changes, we should + // expose this parameter to the caller. + m_context->uniform1i(m_imageLocation, 0); + if (kernelWidth > m_kernelWidth) + kernelWidth = m_kernelWidth; + m_context->uniform1fv(m_kernelLocation, const_cast<float*>(kernel), kernelWidth); + + m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); + + m_context->enableVertexAttribArray(m_positionLocation); +} + +} + +#endif diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h new file mode 100644 index 0000000..533e0f5 --- /dev/null +++ b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ConvolutionShader_h +#define ConvolutionShader_h + +#include "Shader.h" + +namespace WebCore { + +class ConvolutionShader : public Shader { +public: + static PassOwnPtr<ConvolutionShader> create(GraphicsContext3D*, int kernelWidth); + + void use(const AffineTransform&, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]); + +private: + ConvolutionShader(GraphicsContext3D*, unsigned program, int kernelWidth); + + int m_kernelWidth; + int m_matrixLocation; + int m_texMatrixLocation; + int m_kernelLocation; + int m_imageLocation; + int m_imageIncrementLocation; + int m_positionLocation; +}; + +} + +#endif // ConvolutionShader_h diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h index 49ae114..26b04c9 100644 --- a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h +++ b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h @@ -59,6 +59,7 @@ public: void reset(const IntSize&); void bind(); IntSize size() const { return m_size; } + Platform3DObject colorBuffer() const { return m_colorBuffer; } // Clear all resources from this object, as well as context. Called when context is destroyed // to prevent invalid accesses to the resources. diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp index ea8bc71..c223e29 100644 --- a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp +++ b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp @@ -35,7 +35,10 @@ #include "SharedGraphicsContext3D.h" #include "AffineTransform.h" +#include "BicubicShader.h" #include "Color.h" +#include "ConvolutionShader.h" +#include "DrawingBuffer.h" #include "Extensions3D.h" #include "FloatRect.h" #include "IntSize.h" @@ -43,6 +46,7 @@ #include "SolidFillShader.h" #include "TexShader.h" +#include <wtf/OwnArrayPtr.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> @@ -65,15 +69,26 @@ PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(HostWindow* OwnPtr<TexShader> texShader = TexShader::create(context.get()); if (!texShader) return 0; - return adoptRef(new SharedGraphicsContext3D(context.release(), solidFillShader.release(), texShader.release())); + OwnPtr<BicubicShader> bicubicShader = BicubicShader::create(context.get()); + if (!bicubicShader) + return 0; + OwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders = adoptArrayPtr(new OwnPtr<ConvolutionShader>[cMaxKernelWidth]); + for (int i = 0; i < cMaxKernelWidth; ++i) { + convolutionShaders[i] = ConvolutionShader::create(context.get(), i + 1); + if (!convolutionShaders[i]) + return 0; + } + return adoptRef(new SharedGraphicsContext3D(context.release(), solidFillShader.release(), texShader.release(), bicubicShader.release(), convolutionShaders.release())); } -SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader) +SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader, PassOwnPtr<BicubicShader> bicubicShader, PassOwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders) : m_context(context) , m_bgraSupported(false) , m_quadVertices(0) , m_solidFillShader(solidFillShader) , m_texShader(texShader) + , m_bicubicShader(bicubicShader) + , m_convolutionShaders(convolutionShaders) , m_oesStandardDerivativesSupported(false) { allContexts()->add(this); @@ -369,6 +384,17 @@ void SharedGraphicsContext3D::useTextureProgram(const AffineTransform& transform m_texShader->use(transform, texTransform, 0, alpha); } +void SharedGraphicsContext3D::useBicubicProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha) +{ + m_bicubicShader->use(transform, texTransform, coefficients, imageIncrement, alpha); +} + +void SharedGraphicsContext3D::useConvolutionProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]) +{ + ASSERT(kernelWidth >= 1 && kernelWidth <= cMaxKernelWidth); + m_convolutionShaders[kernelWidth - 1]->use(transform, texTransform, kernel, kernelWidth, imageIncrement); +} + void SharedGraphicsContext3D::bindFramebuffer(Platform3DObject framebuffer) { m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer); @@ -411,6 +437,20 @@ void SharedGraphicsContext3D::useLoopBlinnExteriorProgram(unsigned vertexOffset, m_loopBlinnExteriorShader->use(vertexOffset, klmOffset, transform, color); } +DrawingBuffer* SharedGraphicsContext3D::getOffscreenBuffer(unsigned index, const IntSize& size) +{ + if (index >= m_offscreenBuffers.size()) + m_offscreenBuffers.resize(index + 1); + + if (!m_offscreenBuffers[index]) + m_offscreenBuffers[index] = m_context->createDrawingBuffer(size); + + if (size.width() != m_offscreenBuffers[index]->size().width() + || size.height() != m_offscreenBuffers[index]->size().height()) + m_offscreenBuffers[index]->reset(size); + return m_offscreenBuffers[index].get(); +} + } // namespace WebCore #endif diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h index 707fd24..2697add 100644 --- a/third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h +++ b/third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h @@ -38,6 +38,7 @@ #include <wtf/HashMap.h> #include <wtf/HashSet.h> +#include <wtf/OwnArrayPtr.h> #include <wtf/OwnPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -45,7 +46,10 @@ namespace WebCore { class AffineTransform; +class BicubicShader; class Color; +class ConvolutionShader; +class DrawingBuffer; class FloatRect; class HostWindow; class IntSize; @@ -101,6 +105,8 @@ public: void useFillSolidProgram(const AffineTransform&, const Color&); void useTextureProgram(const AffineTransform&, const AffineTransform&, float alpha); + void useBicubicProgram(const AffineTransform&, const AffineTransform&, const float coefficients[16], const float imageIncrement[2], float alpha); + void useConvolutionProgram(const AffineTransform&, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2]); void setActiveTexture(GC3Denum textureUnit); void bindTexture(GC3Denum target, Platform3DObject texture); @@ -127,9 +133,10 @@ public: static bool useLoopBlinnForPathRendering(); void useLoopBlinnInteriorProgram(unsigned vertexOffset, const AffineTransform&, const Color&); void useLoopBlinnExteriorProgram(unsigned vertexOffset, unsigned klmOffset, const AffineTransform&, const Color&); + DrawingBuffer* getOffscreenBuffer(unsigned index, const IntSize&); private: - SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D>, PassOwnPtr<SolidFillShader>, PassOwnPtr<TexShader>); + SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D>, PassOwnPtr<SolidFillShader>, PassOwnPtr<TexShader>, PassOwnPtr<BicubicShader>, PassOwnArrayPtr<OwnPtr<ConvolutionShader> >); // Used to implement removeTexturesFor(), see the comment above. static HashSet<SharedGraphicsContext3D*>* allContexts(); @@ -142,6 +149,8 @@ private: OwnPtr<SolidFillShader> m_solidFillShader; OwnPtr<TexShader> m_texShader; + OwnPtr<BicubicShader> m_bicubicShader; + OwnArrayPtr<OwnPtr<ConvolutionShader> > m_convolutionShaders; TextureHashMap m_textures; @@ -150,8 +159,13 @@ private: OwnPtr<LoopBlinnSolidFillShader> m_loopBlinnInteriorShader; OwnPtr<LoopBlinnSolidFillShader> m_loopBlinnExteriorShader; bool m_oesStandardDerivativesSupported; + + WTF::Vector<RefPtr<DrawingBuffer> > m_offscreenBuffers; }; +const float cMaxSigma = 4.0f; +const int cMaxKernelWidth = 25; + } // namespace WebCore #endif // SharedGraphicsContext3D_h diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/third_party/WebKit/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index dadff8b..df680eb 100644 --- a/third_party/WebKit/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/third_party/WebKit/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -1025,6 +1025,14 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, if (paintingDisabled()) return; + if (platformContext()->useGPU()) { + GLES2Canvas* canvas = platformContext()->gpuCanvas(); + canvas->setShadowOffset(size); + canvas->setShadowBlur(blurFloat); + canvas->setShadowColor(color, colorSpace); + canvas->setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms); + } + // Detect when there's no effective shadow and clear the looper. if (!size.width() && !size.height() && !blurFloat) { platformContext()->setDrawLooper(0); diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/third_party/WebKit/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index 324d45c..5177e1d 100644 --- a/third_party/WebKit/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/third_party/WebKit/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -703,8 +703,7 @@ void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths) bool PlatformContextSkia::canAccelerate() const { - return !m_state->m_fillShader // Can't accelerate with a fill gradient or pattern. - && !m_state->m_looper; // Can't accelerate with a shadow. + return !m_state->m_fillShader; // Can't accelerate with a fill gradient or pattern. } bool PlatformContextSkia::canvasClipApplied() const |