summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsenorblanco@chromium.org <senorblanco@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538>2011-03-18 21:03:43 +0000
committersenorblanco@chromium.org <senorblanco@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538>2011-03-18 21:03:43 +0000
commit9d9fcff2dec88a3269c2227cc6eda11d9ab02bc3 (patch)
tree25f59f0bc0a44a2bc4b09196411a3ab4f8c7f617
parent204147c8efa2aa17a4afaad705915feb843068b7 (diff)
downloadchromium_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
-rw-r--r--third_party/WebKit/LayoutTests/ChangeLog16
-rw-r--r--third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-transforms-fillRect-shadow.js2
-rwxr-xr-xthird_party/WebKit/LayoutTests/platform/chromium/test_expectations.txt7
-rw-r--r--third_party/WebKit/Source/WebCore/ChangeLog106
-rw-r--r--third_party/WebKit/Source/WebCore/WebCore.gypi4
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp322
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h17
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp137
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/gpu/BicubicShader.h58
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp125
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/gpu/ConvolutionShader.h58
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h1
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp44
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h16
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp8
-rw-r--r--third_party/WebKit/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp3
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