summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/platform/graphics
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/platform/graphics
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/platform/graphics')
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp35
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.h11
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/BitmapImageTest.cpp207
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Canvas2DImageBufferSurface.h9
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp328
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h34
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp166
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.cpp75
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.h7
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManagerTest.cpp339
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Color.cpp66
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Color.h38
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ColorSpace.cpp107
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ColorSpace.h15
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/CompositingReasons.h328
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.cpp14
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.h10
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp13
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.h12
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp103
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.h11
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp117
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.cpp33
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.h11
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DisplayList.cpp20
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DisplayList.h14
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp (renamed from chromium/third_party/WebKit/Source/platform/graphics/DrawLooper.cpp)44
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.h (renamed from chromium/third_party/WebKit/Source/platform/graphics/DrawLooper.h)31
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Extensions3D.cpp237
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Extensions3D.h327
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/FrameData.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/FrameData.h16
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp108
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Gradient.h25
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GradientGeneratedImage.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp1001
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.h321
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3D.cpp944
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3D.h551
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextCullSaver.h46
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.cpp855
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.h6
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextState.cpp256
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextState.h169
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp1123
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp291
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h107
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerClient.h8
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.cpp99
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.h (renamed from chromium/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp)63
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp168
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h14
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes3D.h52
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Image.h10
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp227
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.h26
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageBufferClient.h (renamed from chromium/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h)28
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp13
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h16
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.cpp23
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.h18
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp24
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp166
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h11
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp161
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageLayerChromiumTest.cpp130
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageSource.cpp15
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ImageSource.h10
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.cpp15
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.h16
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.cpp7
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.h3
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegateTest.cpp197
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Path.cpp73
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Path.h24
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp48
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.h2
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Pattern.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/StrokeData.cpp21
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/StrokeData.h26
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/ThreadSafeDataTransport.cpp3
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp12
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.h4
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/angle/ANGLEPlatformBridge.cpp229
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/angle/ANGLEPlatformBridge.h96
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/cg/GraphicsContextCG.h41
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/WebGLImageConversionNEON.h (renamed from chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/GraphicsContext3DNEON.h)6
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/filters/FELightingNEON.h203
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.h11
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.cpp39
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.h3
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.cpp130
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.h34
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.cpp59
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.h5
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.cpp100
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.h8
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.cpp10
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.h4
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.cpp1
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.h2
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.cpp52
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.h7
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.cpp33
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.h5
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.cpp6
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.h8
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.cpp257
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.h45
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.cpp93
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.h15
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.h2
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.cpp150
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.h8
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.cpp18
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.h3
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.h2
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.cpp40
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.h6
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.cpp44
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.h7
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/Filter.h74
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.cpp173
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.h45
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperation.h44
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.cpp24
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.h1
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperationsTest.cpp (renamed from chromium/third_party/WebKit/Source/platform/graphics/gpu/SharedGraphicsContext3D.h)48
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/ImageFilterBuilderTest.cpp125
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/LightSource.h7
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/ParallelJobs.h5
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.h12
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.cpp2
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.h4
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.cpp91
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.h23
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.cpp32
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.h7
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.cpp16
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.h6
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.cpp23
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.h15
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterArrayParameter.cpp54
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterArrayParameter.h74
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterCompiledProgram.cpp149
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterCompiledProgram.h95
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterConstants.h60
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterGlobalContext.cpp112
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterGlobalContext.h83
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMesh.cpp68
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMesh.h76
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMeshGenerator.cpp171
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMeshGenerator.h121
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterNumberParameter.cpp50
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterNumberParameter.h73
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterOperation.cpp74
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterOperation.h97
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameter.h78
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameterList.cpp116
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameterList.h63
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgram.cpp85
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgram.h92
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramClient.cpp39
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramClient.h49
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramInfo.cpp106
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramInfo.h110
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterRenderer.cpp292
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterRenderer.h98
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterTransformParameter.cpp70
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterTransformParameter.h72
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterValidatedProgram.cpp617
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterValidatedProgram.h123
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/FECustomFilter.cpp367
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/FECustomFilter.h101
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/ValidatedCustomFilterOperation.cpp60
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/filters/custom/ValidatedCustomFilterOperation.h93
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp772
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h156
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp623
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp101
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h44
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/SharedGraphicsContext3D.cpp85
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.cpp26
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.h15
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.cpp (renamed from chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3DImagePacking.cpp)809
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.h168
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/media/MediaPlayer.h71
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/skia/GaneshUtils.cpp4
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.cpp208
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.h23
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/skia/OpaqueRegionSkia.cpp20
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp6
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h15
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/win/TransparencyWin.cpp512
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/win/TransparencyWin.h256
199 files changed, 9369 insertions, 11440 deletions
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp b/chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
index 80dfafe42b5..a62674ff7b0 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
@@ -28,6 +28,7 @@
#include "platform/graphics/BitmapImage.h"
#include "platform/Timer.h"
+#include "platform/TraceEvent.h"
#include "platform/geometry/FloatRect.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "platform/graphics/ImageObserver.h"
@@ -235,13 +236,24 @@ bool BitmapImage::dataChanged(bool allDataReceived)
// Feed all the data we've seen so far to the image decoder.
m_allDataReceived = allDataReceived;
- m_source.setData(data(), allDataReceived);
+ ASSERT(data());
+ m_source.setData(*data(), allDataReceived);
m_haveFrameCount = false;
m_hasUniformFrameSize = true;
return isSizeAvailable();
}
+bool BitmapImage::isAllDataReceived() const
+{
+ return m_allDataReceived;
+}
+
+bool BitmapImage::hasColorProfile() const
+{
+ return m_source.hasColorProfile();
+}
+
String BitmapImage::filenameExtension() const
{
return m_source.filenameExtension();
@@ -332,7 +344,7 @@ bool BitmapImage::ensureFrameIsCached(size_t index)
PassRefPtr<NativeImageSkia> BitmapImage::frameAtIndex(size_t index)
{
if (!ensureFrameIsCached(index))
- return 0;
+ return nullptr;
return m_frames[index].m_frame;
}
@@ -387,7 +399,7 @@ ImageOrientation BitmapImage::frameOrientationAtIndex(size_t index)
return m_source.orientationAtIndex(index);
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
bool BitmapImage::notSolidColor()
{
return size().width() != 1 || size().height() != 1 || frameCount() > 1;
@@ -414,7 +426,7 @@ bool BitmapImage::shouldAnimate()
return (repetitionCount(false) != cAnimationNone && !m_animationFinished && imageObserver());
}
-void BitmapImage::startAnimation(bool catchUpIfNecessary)
+void BitmapImage::startAnimation(CatchUpAnimation catchUpIfNecessary)
{
if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)
return;
@@ -462,10 +474,10 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary)
if (nextFrame == 0 && m_repetitionsComplete == 0 && m_desiredFrameStartTime < time)
m_desiredFrameStartTime = time;
- if (!catchUpIfNecessary || time < m_desiredFrameStartTime) {
+ if (catchUpIfNecessary == DoNotCatchUp || time < m_desiredFrameStartTime) {
// Haven't yet reached time for next frame to start; delay until then.
m_frameTimer = new Timer<BitmapImage>(this, &BitmapImage::advanceAnimation);
- m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.));
+ m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.), FROM_HERE);
} else {
// We've already reached or passed the time for the next frame to start.
// See if we've also passed the time for frames after that to start, in
@@ -505,7 +517,7 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary)
// situation the best we can do is to simply change frames as fast
// as possible, so force startAnimation() to set a zero-delay timer
// and bail out if we're not caught up.
- startAnimation(false);
+ startAnimation(DoNotCatchUp);
}
}
}
@@ -530,6 +542,15 @@ void BitmapImage::resetAnimation()
destroyDecodedDataIfNecessary();
}
+bool BitmapImage::maybeAnimated()
+{
+ if (m_animationFinished)
+ return false;
+ if (frameCount() > 1)
+ return true;
+ return m_source.repetitionCount() != cAnimationNone;
+}
+
void BitmapImage::advanceAnimation(Timer<BitmapImage>*)
{
internalAdvanceAnimation(false);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.h b/chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.h
index 59941a4abc6..9b2c9f851ea 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/BitmapImage.h
@@ -67,6 +67,8 @@ public:
virtual bool getHotSpot(IntPoint&) const OVERRIDE;
virtual bool dataChanged(bool allDataReceived) OVERRIDE;
+ bool isAllDataReceived() const;
+ bool hasColorProfile() const;
virtual String filenameExtension() const OVERRIDE;
// It may look unusual that there is no start animation call as public API. This is because
@@ -74,13 +76,14 @@ public:
// automatically pause once all observers no longer want to render the image anywhere.
virtual void stopAnimation() OVERRIDE;
virtual void resetAnimation() OVERRIDE;
+ virtual bool maybeAnimated() OVERRIDE;
virtual PassRefPtr<NativeImageSkia> nativeImageForCurrentFrame() OVERRIDE;
virtual bool currentFrameKnownToBeOpaque() OVERRIDE;
ImageOrientation currentFrameOrientation();
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
virtual bool notSolidColor() OVERRIDE;
#endif
@@ -138,7 +141,7 @@ protected:
// Animation.
int repetitionCount(bool imageKnownToBeComplete); // |imageKnownToBeComplete| should be set if the caller knows the entire image has been decoded.
bool shouldAnimate();
- virtual void startAnimation(bool catchUpIfNecessary = true) OVERRIDE;
+ virtual void startAnimation(CatchUpAnimation = CatchUp) OVERRIDE;
void advanceAnimation(Timer<BitmapImage>*);
// Function that does the real work of advancing the animation. When
@@ -153,8 +156,8 @@ protected:
// changed.
void checkForSolidColor();
- virtual bool mayFillWithSolidColor();
- virtual Color solidColor() const;
+ virtual bool mayFillWithSolidColor() OVERRIDE;
+ virtual Color solidColor() const OVERRIDE;
ImageSource m_source;
mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image).
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/BitmapImageTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/BitmapImageTest.cpp
new file mode 100644
index 00000000000..1fa2ea249cd
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/BitmapImageTest.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2013, 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"
+#include "platform/graphics/BitmapImage.h"
+
+#include "platform/SharedBuffer.h"
+#include "platform/graphics/DeferredImageDecoder.h"
+#include "platform/graphics/ImageObserver.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebUnitTestSupport.h"
+
+#include <gtest/gtest.h>
+
+namespace WebCore {
+
+class BitmapImageTest : public ::testing::Test {
+public:
+ class FakeImageObserver : public ImageObserver {
+ public:
+ FakeImageObserver() : m_lastDecodedSizeChangedDelta(0) { }
+
+ virtual void decodedSizeChanged(const Image*, int delta)
+ {
+ m_lastDecodedSizeChangedDelta = delta;
+ }
+ virtual void didDraw(const Image*) OVERRIDE { }
+ virtual bool shouldPauseAnimation(const Image*) OVERRIDE { return false; }
+ virtual void animationAdvanced(const Image*) OVERRIDE { }
+ virtual void changedInRect(const Image*, const IntRect&) { }
+
+ int m_lastDecodedSizeChangedDelta;
+ };
+
+ static PassRefPtr<SharedBuffer> readFile(const char* fileName)
+ {
+ String filePath = blink::Platform::current()->unitTestSupport()->webKitRootDir();
+ filePath.append(fileName);
+ return blink::Platform::current()->unitTestSupport()->readFromFile(filePath);
+ }
+
+ // Accessors to BitmapImage's protected methods.
+ void destroyDecodedData(bool destroyAll) { m_image->destroyDecodedData(destroyAll); }
+ size_t frameCount() { return m_image->frameCount(); }
+ void setCurrentFrame(size_t frame) { m_image->m_currentFrame = frame; }
+ size_t frameDecodedSize(size_t frame) { return m_image->m_frames[frame].m_frameBytes; }
+ size_t decodedFramesCount() const { return m_image->m_frames.size(); }
+
+ void loadImage(const char* fileName)
+ {
+ RefPtr<SharedBuffer> imageData = readFile(fileName);
+ ASSERT_TRUE(imageData.get());
+
+ m_image->setData(imageData, true);
+ EXPECT_EQ(0u, decodedSize());
+
+ size_t frameCount = m_image->frameCount();
+ for (size_t i = 0; i < frameCount; ++i)
+ m_image->frameAtIndex(i);
+ }
+
+ size_t decodedSize()
+ {
+ // In the context of this test, the following loop will give the correct result, but only because the test
+ // forces all frames to be decoded in loadImage() above. There is no general guarantee that frameDecodedSize()
+ // is up-to-date. Because of how multi frame images (like GIF) work, requesting one frame to be decoded may
+ // require other previous frames to be decoded as well. In those cases frameDecodedSize() wouldn't return the
+ // correct thing for the previous frame because the decoded size wouldn't have propagated upwards to the
+ // BitmapImage frame cache.
+ size_t size = 0;
+ for (size_t i = 0; i < decodedFramesCount(); ++i)
+ size += frameDecodedSize(i);
+ return size;
+ }
+
+ void advanceAnimation()
+ {
+ m_image->advanceAnimation(0);
+ }
+
+protected:
+ virtual void SetUp() OVERRIDE
+ {
+ DeferredImageDecoder::setEnabled(false);
+ m_image = BitmapImage::create(&m_imageObserver);
+ }
+
+ FakeImageObserver m_imageObserver;
+ RefPtr<BitmapImage> m_image;
+};
+
+// Fails on the WebKit XP (deps) bot, see http://crbug.com/327104
+#if OS(WIN)
+TEST_F(BitmapImageTest, DISABLED_destroyDecodedDataExceptCurrentFrame)
+#else
+TEST_F(BitmapImageTest, destroyDecodedDataExceptCurrentFrame)
+#endif
+{
+ loadImage("/LayoutTests/fast/images/resources/animated-10color.gif");
+ size_t totalSize = decodedSize();
+ size_t frame = frameCount() / 2;
+ setCurrentFrame(frame);
+ size_t size = frameDecodedSize(frame);
+ destroyDecodedData(false);
+ EXPECT_LT(m_imageObserver.m_lastDecodedSizeChangedDelta, 0);
+ EXPECT_GE(m_imageObserver.m_lastDecodedSizeChangedDelta, -static_cast<int>(totalSize - size));
+}
+
+// Fails on the WebKit XP (deps) bot, see http://crbug.com/327104
+#if OS(WIN)
+TEST_F(BitmapImageTest, DISABLED_destroyAllDecodedData)
+#else
+TEST_F(BitmapImageTest, destroyAllDecodedData)
+#endif
+{
+ loadImage("/LayoutTests/fast/images/resources/animated-10color.gif");
+ size_t totalSize = decodedSize();
+ EXPECT_GT(totalSize, 0u);
+ destroyDecodedData(true);
+ EXPECT_EQ(-static_cast<int>(totalSize), m_imageObserver.m_lastDecodedSizeChangedDelta);
+ EXPECT_EQ(0u, decodedSize());
+}
+
+TEST_F(BitmapImageTest, maybeAnimated)
+{
+ loadImage("/LayoutTests/fast/images/resources/gif-loop-count.gif");
+ for (size_t i = 0; i < frameCount(); ++i) {
+ EXPECT_TRUE(m_image->maybeAnimated());
+ advanceAnimation();
+ }
+ EXPECT_FALSE(m_image->maybeAnimated());
+}
+
+TEST_F(BitmapImageTest, isAllDataReceived)
+{
+ RefPtr<SharedBuffer> imageData = readFile("/LayoutTests/fast/images/resources/green.jpg");
+ ASSERT_TRUE(imageData.get());
+
+ RefPtr<BitmapImage> image = BitmapImage::create();
+ EXPECT_FALSE(image->isAllDataReceived());
+
+ image->setData(imageData, false);
+ EXPECT_FALSE(image->isAllDataReceived());
+
+ image->setData(imageData, true);
+ EXPECT_TRUE(image->isAllDataReceived());
+
+ image->setData(SharedBuffer::create("data", sizeof("data")), false);
+ EXPECT_FALSE(image->isAllDataReceived());
+
+ image->setData(imageData, true);
+ EXPECT_TRUE(image->isAllDataReceived());
+}
+
+#if USE(QCMSLIB)
+
+TEST_F(BitmapImageTest, jpegHasColorProfile)
+{
+ loadImage("/LayoutTests/fast/images/resources/icc-v2-gbr.jpg");
+ EXPECT_EQ(1u, decodedFramesCount());
+ EXPECT_TRUE(m_image->hasColorProfile());
+}
+
+TEST_F(BitmapImageTest, pngHasColorProfile)
+{
+ loadImage("/LayoutTests/fast/images/resources/palatted-color-png-gamma-one-color-profile.png");
+ EXPECT_EQ(1u, decodedFramesCount());
+ EXPECT_TRUE(m_image->hasColorProfile());
+}
+
+TEST_F(BitmapImageTest, webpHasColorProfile)
+{
+ loadImage("/LayoutTests/fast/images/resources/webp-color-profile-lossy.webp");
+ EXPECT_EQ(1u, decodedFramesCount());
+ EXPECT_TRUE(m_image->hasColorProfile());
+}
+
+#endif // USE(QCMSLIB)
+
+} // namespace
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DImageBufferSurface.h b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DImageBufferSurface.h
index e14bb5d9424..b56f1ec89b9 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DImageBufferSurface.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DImageBufferSurface.h
@@ -37,7 +37,7 @@
namespace WebCore {
// This shim necessary because ImageBufferSurfaces are not allowed to be RefCounted
-class Canvas2DImageBufferSurface : public ImageBufferSurface {
+class Canvas2DImageBufferSurface FINAL : public ImageBufferSurface {
public:
Canvas2DImageBufferSurface(const IntSize& size, OpacityMode opacityMode = NonOpaque, int msaaSampleCount = 1)
: ImageBufferSurface(size, opacityMode)
@@ -55,10 +55,13 @@ public:
// ImageBufferSurface implementation
virtual void willUse() OVERRIDE { m_layerBridge->willUse(); }
virtual SkCanvas* canvas() const OVERRIDE { return m_layerBridge->canvas(); }
- virtual bool isValid() const OVERRIDE { return m_layerBridge && m_layerBridge->isValid(); }
+ virtual bool isValid() const OVERRIDE { return m_layerBridge && m_layerBridge->checkSurfaceValid(); }
+ virtual bool restore() OVERRIDE { return m_layerBridge->restoreSurface(); }
virtual blink::WebLayer* layer() const OVERRIDE { return m_layerBridge->layer(); }
virtual Platform3DObject getBackingTexture() const OVERRIDE { return m_layerBridge->getBackingTexture(); }
- virtual bool isAccelerated() const { return m_layerBridge->isAccelerated(); }
+ virtual bool isAccelerated() const OVERRIDE { return m_layerBridge->isAccelerated(); }
+ virtual void setIsHidden(bool hidden) OVERRIDE { m_layerBridge->setIsHidden(hidden); }
+ virtual void setImageBuffer(ImageBuffer* imageBuffer) OVERRIDE { m_layerBridge->setImageBuffer(imageBuffer); }
private:
RefPtr<Canvas2DLayerBridge> m_layerBridge;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index 492dc2b439a..d31443542cd 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -33,22 +33,29 @@
#include "platform/TraceEvent.h"
#include "platform/graphics/Canvas2DLayerManager.h"
#include "platform/graphics/GraphicsLayer.h"
-#include "platform/graphics/gpu/SharedGraphicsContext3D.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCompositorSupport.h"
#include "public/platform/WebGraphicsContext3D.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
+#include "wtf/RefCountedLeakCounter.h"
using blink::WebExternalTextureLayer;
using blink::WebGraphicsContext3D;
+namespace {
+enum {
+ InvalidMailboxIndex = -1,
+};
+
+DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, canvas2DLayerBridgeInstanceCounter, ("Canvas2DLayerBridge"));
+}
+
namespace WebCore {
-static PassRefPtr<SkSurface> createSkSurface(GraphicsContext3D* context3D, const IntSize& size, int msaaSampleCount)
+static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size, int msaaSampleCount = 0)
{
- ASSERT(!context3D->webContext()->isContextLost());
- GrContext* gr = context3D->grContext();
if (!gr)
- return 0;
+ return nullptr;
gr->resetContext();
SkImageInfo info;
info.fWidth = size.width();
@@ -61,31 +68,38 @@ static PassRefPtr<SkSurface> createSkSurface(GraphicsContext3D* context3D, const
PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(const IntSize& size, OpacityMode opacityMode, int msaaSampleCount)
{
TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
- RefPtr<GraphicsContext3D> context = SharedGraphicsContext3D::get();
- RefPtr<SkSurface> surface(createSkSurface(context.get(), size, msaaSampleCount));
+ OwnPtr<blink::WebGraphicsContext3DProvider> contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+ if (!contextProvider)
+ return nullptr;
+ RefPtr<SkSurface> surface(createSkSurface(contextProvider->grContext(), size, msaaSampleCount));
if (!surface)
- return 0;
+ return nullptr;
RefPtr<Canvas2DLayerBridge> layerBridge;
OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface.get()));
- layerBridge = adoptRef(new Canvas2DLayerBridge(context, canvas.release(), msaaSampleCount, opacityMode));
+ layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), canvas.release(), msaaSampleCount, opacityMode));
return layerBridge.release();
}
-Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SkDeferredCanvas> canvas, int msaaSampleCount, OpacityMode opacityMode)
+Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<blink::WebGraphicsContext3DProvider> contextProvider, PassOwnPtr<SkDeferredCanvas> canvas, int msaaSampleCount, OpacityMode opacityMode)
: m_canvas(canvas)
- , m_context(context)
+ , m_contextProvider(contextProvider)
+ , m_imageBuffer(0)
, m_msaaSampleCount(msaaSampleCount)
, m_bytesAllocated(0)
, m_didRecordDrawCommand(false)
- , m_surfaceIsValid(true)
+ , m_isSurfaceValid(true)
, m_framesPending(0)
+ , m_framesSinceMailboxRelease(0)
, m_destructionInProgress(false)
, m_rateLimitingEnabled(false)
+ , m_isHidden(false)
, m_next(0)
, m_prev(0)
, m_lastImageId(0)
+ , m_releasedMailboxInfoIndex(InvalidMailboxIndex)
{
ASSERT(m_canvas);
+ ASSERT(m_contextProvider);
// Used by browser tests to detect the use of a Canvas2DLayerBridge.
TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->createExternalTextureLayer(this));
@@ -94,44 +108,86 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context,
GraphicsLayer::registerContentsLayer(m_layer->layer());
m_layer->setRateLimitContext(m_rateLimitingEnabled);
m_canvas->setNotificationClient(this);
+#ifndef NDEBUG
+ canvas2DLayerBridgeInstanceCounter.increment();
+#endif
}
Canvas2DLayerBridge::~Canvas2DLayerBridge()
{
ASSERT(m_destructionInProgress);
+ ASSERT(!Canvas2DLayerManager::get().isInList(this));
m_layer.clear();
+ freeReleasedMailbox();
+#if ASSERT_ENABLED
Vector<MailboxInfo>::iterator mailboxInfo;
- for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
+ for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++mailboxInfo) {
ASSERT(mailboxInfo->m_status != MailboxInUse);
- if (mailboxInfo->m_status == MailboxReleased) {
- if (mailboxInfo->m_mailbox.syncPoint) {
- context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
- mailboxInfo->m_mailbox.syncPoint = 0;
- }
- // Invalidate texture state in case the compositor altered it since the copy-on-write.
- mailboxInfo->m_image->getTexture()->invalidateCachedState();
- }
+ ASSERT(mailboxInfo->m_status != MailboxReleased || m_contextProvider->context3d()->isContextLost() || !m_isSurfaceValid);
}
+#endif
m_mailboxes.clear();
+#ifndef NDEBUG
+ canvas2DLayerBridgeInstanceCounter.decrement();
+#endif
}
void Canvas2DLayerBridge::beginDestruction()
{
ASSERT(!m_destructionInProgress);
+ setRateLimitingEnabled(false);
+ m_canvas->silentFlush();
+ m_imageBuffer = 0;
+ freeTransientResources();
+ setIsHidden(true);
m_destructionInProgress = true;
GraphicsLayer::unregisterContentsLayer(m_layer->layer());
m_canvas->setNotificationClient(0);
+ m_canvas.clear();
m_layer->clearTexture();
- Canvas2DLayerManager::get().layerToBeDestroyed(this);
// Orphaning the layer is required to trigger the recration of a new layer
// in the case where destruction is caused by a canvas resize. Test:
// virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
m_layer->layer()->removeFromParent();
+ // To anyone who ever hits this assert: Please update crbug.com/344666
+ // with repro steps.
+ ASSERT(!m_bytesAllocated);
+}
+
+void Canvas2DLayerBridge::setIsHidden(bool hidden)
+{
+ ASSERT(!m_destructionInProgress);
+ bool newHiddenValue = hidden || m_destructionInProgress;
+ if (m_isHidden == newHiddenValue)
+ return;
+
+ m_isHidden = newHiddenValue;
+ if (isHidden()) {
+ freeTransientResources();
+ }
+}
+
+void Canvas2DLayerBridge::freeTransientResources()
+{
+ ASSERT(!m_destructionInProgress);
+ freeReleasedMailbox();
+ flush();
+ freeMemoryIfPossible(bytesAllocated());
+ ASSERT(!hasTransientResources());
+}
+
+bool Canvas2DLayerBridge::hasTransientResources() const
+{
+ return !m_destructionInProgress && (hasReleasedMailbox() || bytesAllocated());
}
void Canvas2DLayerBridge::limitPendingFrames()
{
ASSERT(!m_destructionInProgress);
+ if (isHidden()) {
+ freeTransientResources();
+ return;
+ }
if (m_didRecordDrawCommand) {
m_framesPending++;
m_didRecordDrawCommand = false;
@@ -144,20 +200,24 @@ void Canvas2DLayerBridge::limitPendingFrames()
flush();
}
}
+ ++m_framesSinceMailboxRelease;
+ if (releasedMailboxHasExpired()) {
+ freeReleasedMailbox();
+ }
}
void Canvas2DLayerBridge::prepareForDraw()
{
ASSERT(!m_destructionInProgress);
ASSERT(m_layer);
- if (!isValid()) {
+ if (!checkSurfaceValid()) {
if (m_canvas) {
// drop pending commands because there is no surface to draw to
m_canvas->silentFlush();
}
return;
}
- m_context->makeContextCurrent();
+ context()->makeContextCurrent();
}
void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAllocated)
@@ -165,12 +225,11 @@ void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca
ASSERT(!m_destructionInProgress);
intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated;
m_bytesAllocated = bytesAllocated;
- Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, delta);
+ Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this, delta);
}
size_t Canvas2DLayerBridge::storageAllocatedForRecording()
{
- ASSERT(!m_destructionInProgress);
return m_canvas->storageAllocatedForRecording();
}
@@ -192,7 +251,7 @@ void Canvas2DLayerBridge::skippedPendingDrawCommands()
void Canvas2DLayerBridge::setRateLimitingEnabled(bool enabled)
{
- ASSERT(!m_destructionInProgress || !enabled);
+ ASSERT(!m_destructionInProgress);
if (m_rateLimitingEnabled != enabled) {
m_rateLimitingEnabled = enabled;
m_layer->setRateLimitContext(m_rateLimitingEnabled);
@@ -203,9 +262,9 @@ size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree)
{
ASSERT(!m_destructionInProgress);
size_t bytesFreed = m_canvas->freeMemoryIfPossible(bytesToFree);
- if (bytesFreed)
- Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, -((intptr_t)bytesFreed));
m_bytesAllocated -= bytesFreed;
+ if (bytesFreed)
+ Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this, -((intptr_t)bytesFreed));
return bytesFreed;
}
@@ -214,112 +273,175 @@ void Canvas2DLayerBridge::flush()
ASSERT(!m_destructionInProgress);
if (m_canvas->hasPendingCommands()) {
TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
+ freeReleasedMailbox(); // To avoid unnecessary triple-buffering
m_canvas->flush();
}
}
+bool Canvas2DLayerBridge::releasedMailboxHasExpired()
+{
+ // This heuristic indicates that the canvas is not being
+ // actively presented by the compositor (3 frames rendered since
+ // last mailbox release), suggesting that double buffering is not required.
+ return hasReleasedMailbox() && m_framesSinceMailboxRelease > 2;
+}
+
+Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::releasedMailboxInfo()
+{
+ return hasReleasedMailbox() ? &m_mailboxes[m_releasedMailboxInfoIndex] : 0;
+}
+
+bool Canvas2DLayerBridge::hasReleasedMailbox() const
+{
+ return m_releasedMailboxInfoIndex != InvalidMailboxIndex;
+}
+
+void Canvas2DLayerBridge::freeReleasedMailbox()
+{
+ if (m_contextProvider->context3d()->isContextLost() || !m_isSurfaceValid)
+ return;
+ MailboxInfo* mailboxInfo = releasedMailboxInfo();
+ if (!mailboxInfo)
+ return;
+
+ ASSERT(mailboxInfo->m_status == MailboxReleased);
+ if (mailboxInfo->m_mailbox.syncPoint) {
+ context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
+ mailboxInfo->m_mailbox.syncPoint = 0;
+ }
+ // Invalidate texture state in case the compositor altered it since the copy-on-write.
+ if (mailboxInfo->m_image) {
+ if (isHidden() || releasedMailboxHasExpired())
+ mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureFlags>(GrTexture::kReturnToCache_FlagBit));
+ mailboxInfo->m_image->getTexture()->textureParamsModified();
+ mailboxInfo->m_image.clear();
+ }
+ mailboxInfo->m_status = MailboxAvailable;
+ m_releasedMailboxInfoIndex = InvalidMailboxIndex;
+ Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
+}
+
blink::WebGraphicsContext3D* Canvas2DLayerBridge::context()
{
// Check on m_layer is necessary because context() may be called during
// the destruction of m_layer
- if (m_layer) {
- isValid(); // To ensure rate limiter is disabled if context is lost.
+ if (m_layer && !m_destructionInProgress)
+ checkSurfaceValid(); // To ensure rate limiter is disabled if context is lost.
+ return m_contextProvider->context3d();
+}
+
+bool Canvas2DLayerBridge::checkSurfaceValid()
+{
+ ASSERT(!m_destructionInProgress);
+ if (m_destructionInProgress || !m_isSurfaceValid)
+ return false;
+ if (m_contextProvider->context3d()->isContextLost()) {
+ m_isSurfaceValid = false;
+ if (m_imageBuffer)
+ m_imageBuffer->notifySurfaceInvalid();
+ setRateLimitingEnabled(false);
}
- return m_context->webContext();
+ return m_isSurfaceValid;
}
-bool Canvas2DLayerBridge::isValid()
+bool Canvas2DLayerBridge::restoreSurface()
{
- ASSERT(m_layer);
+ ASSERT(!m_destructionInProgress);
if (m_destructionInProgress)
return false;
- if (m_context->webContext()->isContextLost() || !m_surfaceIsValid) {
- // Attempt to recover.
- m_layer->clearTexture();
- m_mailboxes.clear();
- RefPtr<GraphicsContext3D> sharedContext = SharedGraphicsContext3D::get();
- if (!sharedContext || sharedContext->webContext()->isContextLost()) {
- m_surfaceIsValid = false;
- } else {
- m_context = sharedContext;
- IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()->height());
- RefPtr<SkSurface> surface(createSkSurface(m_context.get(), size, m_msaaSampleCount));
- if (surface.get()) {
- m_canvas->setSurface(surface.get());
- m_surfaceIsValid = true;
- // FIXME: draw sad canvas picture into new buffer crbug.com/243842
- } else {
- // Surface allocation failed. Set m_surfaceIsValid to false to
- // trigger subsequent retry.
- m_surfaceIsValid = false;
- }
+ ASSERT(m_layer && !m_isSurfaceValid);
+
+ blink::WebGraphicsContext3D* sharedContext = 0;
+ // We must clear the mailboxes before calling m_layer->clearTexture() to prevent
+ // re-entry via mailboxReleased from operating on defunct GrContext objects.
+ m_mailboxes.clear();
+ m_releasedMailboxInfoIndex = InvalidMailboxIndex;
+ m_layer->clearTexture();
+ m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+ if (m_contextProvider)
+ sharedContext = m_contextProvider->context3d();
+
+ if (sharedContext && !sharedContext->isContextLost()) {
+ IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()->height());
+ RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext(), size, m_msaaSampleCount));
+ if (surface.get()) {
+ m_canvas->setSurface(surface.get());
+ m_isSurfaceValid = true;
+ // FIXME: draw sad canvas picture into new buffer crbug.com/243842
}
}
- if (!m_surfaceIsValid)
- setRateLimitingEnabled(false);
- return m_surfaceIsValid;
+
+ return m_isSurfaceValid;
}
bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox, blink::WebExternalBitmap* bitmap)
{
+ if (m_destructionInProgress) {
+ // It can be hit in the following sequence.
+ // 1. Canvas draws something.
+ // 2. The compositor begins the frame.
+ // 3. Javascript makes a context be lost.
+ // 4. Here.
+ return false;
+ }
if (bitmap) {
// Using accelerated 2d canvas with software renderer, which
- // should only happen in tests that use fake graphics contexts.
- // In this case, we do not care about producing any results for
- // compositing.
+ // should only happen in tests that use fake graphics contexts
+ // or in Android WebView in software mode. In this case, we do
+ // not care about producing any results for this canvas.
m_canvas->silentFlush();
+ m_lastImageId = 0;
return false;
}
- if (!isValid())
+ if (!checkSurfaceValid())
return false;
+
+ blink::WebGraphicsContext3D* webContext = context();
+
// Release to skia textures that were previouosly released by the
// compositor. We do this before acquiring the next snapshot in
// order to cap maximum gpu memory consumption.
- m_context->makeContextCurrent();
+ webContext->makeContextCurrent();
flush();
- Vector<MailboxInfo>::iterator mailboxInfo;
- for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
- if (mailboxInfo->m_status == MailboxReleased) {
- if (mailboxInfo->m_mailbox.syncPoint) {
- context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
- mailboxInfo->m_mailbox.syncPoint = 0;
- }
- // Invalidate texture state in case the compositor altered it since the copy-on-write.
- mailboxInfo->m_image->getTexture()->invalidateCachedState();
- mailboxInfo->m_image.reset(0);
- mailboxInfo->m_status = MailboxAvailable;
- }
- }
- SkAutoTUnref<SkImage> image(m_canvas->newImageSnapshot());
+
+ RefPtr<SkImage> image = adoptRef(m_canvas->newImageSnapshot());
+
// Early exit if canvas was not drawn to since last prepareMailbox
if (image->uniqueID() == m_lastImageId)
return false;
m_lastImageId = image->uniqueID();
- mailboxInfo = createMailboxInfo();
+ MailboxInfo* mailboxInfo = createMailboxInfo();
mailboxInfo->m_status = MailboxInUse;
- mailboxInfo->m_image.swap(&image);
- // Because of texture sharing with the compositor, we must invalidate
- // the state cached in skia so that the deferred copy on write
- // in SkSurface_Gpu does not make any false assumptions.
- mailboxInfo->m_image->getTexture()->invalidateCachedState();
+ mailboxInfo->m_image = image;
ASSERT(mailboxInfo->m_mailbox.syncPoint == 0);
ASSERT(mailboxInfo->m_image.get());
ASSERT(mailboxInfo->m_image->getTexture());
- m_context->bindTexture(GL_TEXTURE_2D, mailboxInfo->m_image->getTexture()->getTextureHandle());
- m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo->m_mailbox.name);
- context()->flush();
- mailboxInfo->m_mailbox.syncPoint = context()->insertSyncPoint();
- m_context->bindTexture(GL_TEXTURE_2D, 0);
+ // Because of texture sharing with the compositor, we must invalidate
+ // the state cached in skia so that the deferred copy on write
+ // in SkSurface_Gpu does not make any false assumptions.
+ mailboxInfo->m_image->getTexture()->textureParamsModified();
+
+ webContext->bindTexture(GL_TEXTURE_2D, mailboxInfo->m_image->getTexture()->getTextureHandle());
+ webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo->m_mailbox.name);
+ if (isHidden()) {
+ // With hidden canvases, we release the SkImage immediately because
+ // there is no need for animations to be double buffered.
+ mailboxInfo->m_image.clear();
+ } else {
+ webContext->flush();
+ mailboxInfo->m_mailbox.syncPoint = webContext->insertSyncPoint();
+ }
+ webContext->bindTexture(GL_TEXTURE_2D, 0);
// Because we are changing the texture binding without going through skia,
// we must dirty the context.
- m_context->grContext()->resetContext(kTextureBinding_GrGLBackendState);
+ m_contextProvider->grContext()->resetContext(kTextureBinding_GrGLBackendState);
// set m_parentLayerBridge to make sure 'this' stays alive as long as it has
// live mailboxes
@@ -355,15 +477,24 @@ Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::createMailboxInfo() {
void Canvas2DLayerBridge::mailboxReleased(const blink::WebExternalTextureMailbox& mailbox)
{
+ freeReleasedMailbox(); // Never have more than one mailbox in the released state.
Vector<MailboxInfo>::iterator mailboxInfo;
- for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
- if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.name))) {
+ for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++mailboxInfo) {
+ if (nameEquals(mailboxInfo->m_mailbox, mailbox)) {
mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint;
ASSERT(mailboxInfo->m_status == MailboxInUse);
mailboxInfo->m_status = MailboxReleased;
// Trigger Canvas2DLayerBridge self-destruction if this is the
// last live mailbox and the layer bridge is not externally
// referenced.
+ m_releasedMailboxInfoIndex = mailboxInfo - m_mailboxes.begin();
+ m_framesSinceMailboxRelease = 0;
+ if (isHidden()) {
+ freeReleasedMailbox();
+ } else {
+ ASSERT(!m_destructionInProgress);
+ Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
+ }
ASSERT(mailboxInfo->m_parentLayerBridge.get() == this);
mailboxInfo->m_parentLayerBridge.clear();
return;
@@ -373,6 +504,7 @@ void Canvas2DLayerBridge::mailboxReleased(const blink::WebExternalTextureMailbox
blink::WebLayer* Canvas2DLayerBridge::layer() const
{
+ ASSERT(!m_destructionInProgress);
ASSERT(m_layer);
return m_layer->layer();
}
@@ -387,11 +519,11 @@ void Canvas2DLayerBridge::willUse()
Platform3DObject Canvas2DLayerBridge::getBackingTexture()
{
ASSERT(!m_destructionInProgress);
- if (!isValid())
+ if (!checkSurfaceValid())
return 0;
willUse();
m_canvas->flush();
- m_context->flush();
+ context()->flush();
GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget();
if (renderTarget) {
return renderTarget->asTexture()->getTextureHandle();
@@ -401,10 +533,10 @@ Platform3DObject Canvas2DLayerBridge::getBackingTexture()
Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
// This copy constructor should only be used for Vector reallocation
- // Assuming 'other' is to be destroyed, we swap m_image ownership
+ // Assuming 'other' is to be destroyed, we transfer m_image ownership
// rather than do a refcount dance.
memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
- m_image.swap(const_cast<SkAutoTUnref<SkImage>*>(&other.m_image));
+ m_image = const_cast<MailboxInfo*>(&other)->m_image.release();
m_status = other.m_status;
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
index d259c5fcd9d..f2fd4aaaf6f 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
@@ -30,11 +30,11 @@
#include "SkImage.h"
#include "platform/PlatformExport.h"
#include "platform/geometry/IntSize.h"
-#include "platform/graphics/GraphicsContext3D.h"
#include "platform/graphics/ImageBufferSurface.h"
#include "public/platform/WebExternalTextureLayer.h"
#include "public/platform/WebExternalTextureLayerClient.h"
#include "public/platform/WebExternalTextureMailbox.h"
+#include "third_party/khronos/GLES2/gl2.h"
#include "wtf/DoublyLinkedList.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/RefCounted.h"
@@ -42,20 +42,23 @@
namespace blink {
class WebGraphicsContext3D;
+class WebGraphicsContext3DProvider;
}
class Canvas2DLayerBridgeTest;
namespace WebCore {
+class ImageBuffer;
+
class PLATFORM_EXPORT Canvas2DLayerBridge : public blink::WebExternalTextureLayerClient, public SkDeferredCanvas::NotificationClient, public DoublyLinkedListNode<Canvas2DLayerBridge>, public RefCounted<Canvas2DLayerBridge> {
WTF_MAKE_NONCOPYABLE(Canvas2DLayerBridge);
public:
static PassRefPtr<Canvas2DLayerBridge> create(const IntSize&, OpacityMode, int msaaSampleCount);
+
virtual ~Canvas2DLayerBridge();
// blink::WebExternalTextureLayerClient implementation.
- virtual blink::WebGraphicsContext3D* context() OVERRIDE;
virtual bool prepareMailbox(blink::WebExternalTextureMailbox*, blink::WebExternalBitmap*) OVERRIDE;
virtual void mailboxReleased(const blink::WebExternalTextureMailbox&) OVERRIDE;
@@ -68,34 +71,47 @@ public:
// ImageBufferSurface implementation
void willUse();
SkCanvas* canvas() const { return m_canvas.get(); }
- bool isValid();
+ bool checkSurfaceValid();
+ bool restoreSurface();
blink::WebLayer* layer() const;
Platform3DObject getBackingTexture();
bool isAccelerated() const { return true; }
+ void setIsHidden(bool);
+ void setImageBuffer(ImageBuffer* imageBuffer) { m_imageBuffer = imageBuffer; }
// Methods used by Canvas2DLayerManager
virtual size_t freeMemoryIfPossible(size_t); // virtual for mocking
virtual void flush(); // virtual for mocking
virtual size_t storageAllocatedForRecording(); // virtual for faking
- size_t bytesAllocated() const {return m_bytesAllocated;}
+ size_t bytesAllocated() const { return m_bytesAllocated; }
void limitPendingFrames();
+ void freeReleasedMailbox();
+ bool hasReleasedMailbox() const;
+ void freeTransientResources();
+ bool hasTransientResources() const;
+ bool isHidden() { return m_isHidden; }
void beginDestruction();
protected:
- Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D>, PassOwnPtr<SkDeferredCanvas>, int, OpacityMode);
+ Canvas2DLayerBridge(PassOwnPtr<blink::WebGraphicsContext3DProvider>, PassOwnPtr<SkDeferredCanvas>, int, OpacityMode);
void setRateLimitingEnabled(bool);
+ bool releasedMailboxHasExpired();
+ blink::WebGraphicsContext3D* context();
OwnPtr<SkDeferredCanvas> m_canvas;
OwnPtr<blink::WebExternalTextureLayer> m_layer;
- RefPtr<GraphicsContext3D> m_context;
+ OwnPtr<blink::WebGraphicsContext3DProvider> m_contextProvider;
+ ImageBuffer* m_imageBuffer;
int m_msaaSampleCount;
size_t m_bytesAllocated;
bool m_didRecordDrawCommand;
- bool m_surfaceIsValid;
+ bool m_isSurfaceValid;
int m_framesPending;
+ int m_framesSinceMailboxRelease;
bool m_destructionInProgress;
bool m_rateLimitingEnabled;
+ bool m_isHidden;
friend class WTF::DoublyLinkedListNode<Canvas2DLayerBridge>;
friend class ::Canvas2DLayerBridgeTest;
@@ -110,7 +126,7 @@ protected:
struct MailboxInfo {
blink::WebExternalTextureMailbox m_mailbox;
- SkAutoTUnref<SkImage> m_image;
+ RefPtr<SkImage> m_image;
MailboxStatus m_status;
RefPtr<Canvas2DLayerBridge> m_parentLayerBridge;
@@ -118,9 +134,11 @@ protected:
MailboxInfo() {}
};
MailboxInfo* createMailboxInfo();
+ MailboxInfo* releasedMailboxInfo();
uint32_t m_lastImageId;
Vector<MailboxInfo> m_mailboxes;
+ int m_releasedMailboxInfoIndex;
};
}
#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
new file mode 100644
index 00000000000..29d4aa17b63
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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"
+
+#include "platform/graphics/Canvas2DLayerBridge.h"
+
+#include "SkDeferredCanvas.h"
+#include "SkSurface.h"
+#include "platform/graphics/ImageBuffer.h"
+#include "platform/graphics/test/MockWebGraphicsContext3D.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebExternalBitmap.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
+#include "public/platform/WebThread.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "wtf/RefPtr.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+using namespace blink;
+using testing::InSequence;
+using testing::Return;
+using testing::Test;
+
+namespace {
+
+class MockCanvasContext : public MockWebGraphicsContext3D {
+public:
+ MOCK_METHOD0(flush, void(void));
+ MOCK_METHOD0(createTexture, unsigned(void));
+ MOCK_METHOD1(deleteTexture, void(unsigned));
+};
+
+class MockWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider {
+public:
+ MockWebGraphicsContext3DProvider(WebGraphicsContext3D* context3d)
+ : m_context3d(context3d) { }
+
+ WebGraphicsContext3D* context3d()
+ {
+ return m_context3d;
+ }
+
+ GrContext* grContext()
+ {
+ return 0;
+ }
+
+private:
+ WebGraphicsContext3D* m_context3d;
+};
+
+class Canvas2DLayerBridgePtr {
+public:
+ Canvas2DLayerBridgePtr(PassRefPtr<Canvas2DLayerBridge> layerBridge)
+ : m_layerBridge(layerBridge) { }
+
+ ~Canvas2DLayerBridgePtr()
+ {
+ m_layerBridge->beginDestruction();
+ }
+
+ Canvas2DLayerBridge* operator->() { return m_layerBridge.get(); }
+ Canvas2DLayerBridge* get() { return m_layerBridge.get(); }
+
+private:
+ RefPtr<Canvas2DLayerBridge> m_layerBridge;
+};
+
+class NullWebExternalBitmap : public WebExternalBitmap {
+public:
+ virtual WebSize size()
+ {
+ return WebSize();
+ }
+
+ virtual void setSize(WebSize)
+ {
+ }
+
+ virtual uint8* pixels()
+ {
+ return 0;
+ }
+};
+
+} // namespace
+
+class Canvas2DLayerBridgeTest : public Test {
+protected:
+ void fullLifecycleTest()
+ {
+ MockCanvasContext mainMock;
+ OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock));
+ RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterPMColor(300, 150));
+ OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface.get()));
+
+ ::testing::Mock::VerifyAndClearExpectations(&mainMock);
+
+ {
+ Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainMockProvider.release(), canvas.release(), 0, NonOpaque)));
+
+ ::testing::Mock::VerifyAndClearExpectations(&mainMock);
+
+ EXPECT_CALL(mainMock, flush());
+ unsigned textureId = bridge->getBackingTexture();
+ EXPECT_EQ(textureId, 0u);
+
+ ::testing::Mock::VerifyAndClearExpectations(&mainMock);
+ } // bridge goes out of scope here
+
+ ::testing::Mock::VerifyAndClearExpectations(&mainMock);
+ }
+
+ void prepareMailboxWithBitmapTest()
+ {
+ MockCanvasContext mainMock;
+ RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterPMColor(300, 150));
+ OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface.get()));
+ OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock));
+ Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainMockProvider.release(), canvas.release(), 0, NonOpaque)));
+ bridge->m_lastImageId = 1;
+
+ NullWebExternalBitmap bitmap;
+ bridge->prepareMailbox(0, &bitmap);
+ EXPECT_EQ(0u, bridge->m_lastImageId);
+ }
+};
+
+namespace {
+
+TEST_F(Canvas2DLayerBridgeTest, testFullLifecycleSingleThreaded)
+{
+ fullLifecycleTest();
+}
+
+TEST_F(Canvas2DLayerBridgeTest, prepareMailboxWithBitmapTest)
+{
+ prepareMailboxWithBitmapTest();
+}
+
+} // namespace
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.cpp
index 5d21312a0fe..3e56351950b 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.cpp
@@ -31,11 +31,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using blink::WebThread;
namespace {
+
enum {
DefaultMaxBytesAllocated = 64*1024*1024,
DefaultTargetBytesAllocated = 16*1024*1024,
};
-}
+
+} // unnamed namespace
namespace WebCore {
@@ -81,8 +83,14 @@ void Canvas2DLayerManager::didProcessTask()
ASSERT(m_taskObserverActive);
blink::Platform::current()->currentThread()->removeTaskObserver(this);
m_taskObserverActive = false;
- for (Canvas2DLayerBridge* layer = m_layerList.head(); layer; layer = layer->next())
- layer->limitPendingFrames();
+ Canvas2DLayerBridge* layer = m_layerList.head();
+ while (layer) {
+ Canvas2DLayerBridge* currentLayer = layer;
+ // must increment iterator before calling limitPendingFrames, which
+ // may result in the layer being removed from the list.
+ layer = layer->next();
+ currentLayer->limitPendingFrames();
+ }
}
void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer)
@@ -92,8 +100,7 @@ void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer)
m_layerList.remove(layer);
m_layerList.push(layer); // Set as MRU
}
- } else
- addLayerToList(layer);
+ }
if (!m_taskObserverActive) {
m_taskObserverActive = true;
@@ -102,48 +109,42 @@ void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer)
}
}
-void Canvas2DLayerManager::addLayerToList(Canvas2DLayerBridge* layer)
-{
- ASSERT(!isInList(layer));
- m_bytesAllocated += layer->bytesAllocated();
- m_layerList.push(layer); // Set as MRU
-}
-
-void Canvas2DLayerManager::layerAllocatedStorageChanged(Canvas2DLayerBridge* layer, intptr_t deltaBytes)
+void Canvas2DLayerManager::layerTransientResourceAllocationChanged(Canvas2DLayerBridge* layer, intptr_t deltaBytes)
{
- if (!isInList(layer))
- addLayerToList(layer);
- else {
- ASSERT((intptr_t)m_bytesAllocated + deltaBytes >= 0);
- m_bytesAllocated = (intptr_t)m_bytesAllocated + deltaBytes;
+ ASSERT((intptr_t)m_bytesAllocated + deltaBytes >= 0);
+ m_bytesAllocated = (intptr_t)m_bytesAllocated + deltaBytes;
+ if (!isInList(layer) && layer->hasTransientResources()) {
+ m_layerList.push(layer);
+ } else if (isInList(layer) && !layer->hasTransientResources()) {
+ m_layerList.remove(layer);
+ layer->setNext(0);
+ layer->setPrev(0);
}
+
if (deltaBytes > 0)
freeMemoryIfNecessary();
}
-void Canvas2DLayerManager::layerToBeDestroyed(Canvas2DLayerBridge* layer)
-{
- if (isInList(layer))
- removeLayerFromList(layer);
-}
-
void Canvas2DLayerManager::freeMemoryIfNecessary()
{
- if (m_bytesAllocated > m_maxBytesAllocated) {
+ if (m_bytesAllocated >= m_maxBytesAllocated) {
// Pass 1: Free memory from caches
Canvas2DLayerBridge* layer = m_layerList.tail(); // LRU
- while (m_bytesAllocated > m_targetBytesAllocated && layer) {
- layer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocated);
+ while (layer && m_bytesAllocated > m_targetBytesAllocated) {
+ Canvas2DLayerBridge* currentLayer = layer;
layer = layer->prev();
+ currentLayer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocated);
+ ASSERT(isInList(currentLayer) == currentLayer->hasTransientResources());
}
// Pass 2: Flush canvases
- Canvas2DLayerBridge* leastRecentlyUsedLayer = m_layerList.tail();
- while (m_bytesAllocated > m_targetBytesAllocated && leastRecentlyUsedLayer) {
- leastRecentlyUsedLayer->flush();
- leastRecentlyUsedLayer->freeMemoryIfPossible(~0);
- removeLayerFromList(leastRecentlyUsedLayer);
- leastRecentlyUsedLayer = m_layerList.tail();
+ layer = m_layerList.tail();
+ while (m_bytesAllocated > m_targetBytesAllocated && layer) {
+ Canvas2DLayerBridge* currentLayer = layer;
+ layer = layer->prev();
+ currentLayer->flush();
+ currentLayer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocated);
+ ASSERT(isInList(currentLayer) == currentLayer->hasTransientResources());
}
}
}
@@ -151,13 +152,11 @@ void Canvas2DLayerManager::freeMemoryIfNecessary()
void Canvas2DLayerManager::removeLayerFromList(Canvas2DLayerBridge* layer)
{
ASSERT(isInList(layer));
- m_bytesAllocated -= layer->bytesAllocated();
- m_layerList.remove(layer);
- layer->setNext(0);
- layer->setPrev(0);
+ ASSERT(!layer->hasTransientResources());
+
}
-bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer)
+bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer) const
{
return layer->prev() || m_layerList.head() == layer;
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.h b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.h
index e2c4e042e65..231fc85b72b 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManager.h
@@ -35,18 +35,19 @@ namespace WebCore {
class PLATFORM_EXPORT Canvas2DLayerManager : public blink::WebThread::TaskObserver {
public:
static Canvas2DLayerManager& get();
+
void init(size_t maxBytesAllocated, size_t targetBytesAllocated);
virtual ~Canvas2DLayerManager();
- void layerAllocatedStorageChanged(Canvas2DLayerBridge*, intptr_t deltaBytes);
+ void layerTransientResourceAllocationChanged(Canvas2DLayerBridge*, intptr_t deltaBytes = 0);
void layerDidDraw(Canvas2DLayerBridge*);
- void layerToBeDestroyed(Canvas2DLayerBridge*);
+
+ bool isInList(Canvas2DLayerBridge*) const;
private:
Canvas2DLayerManager();
// internal methods
void freeMemoryIfNecessary();
- bool isInList(Canvas2DLayerBridge*);
void addLayerToList(Canvas2DLayerBridge*);
void removeLayerFromList(Canvas2DLayerBridge*);
virtual void willProcessTask() OVERRIDE;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManagerTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManagerTest.cpp
new file mode 100644
index 00000000000..a2f6b0c5da0
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Canvas2DLayerManagerTest.cpp
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2012 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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"
+
+#include "platform/graphics/Canvas2DLayerManager.h"
+
+#include "SkDevice.h"
+#include "SkSurface.h"
+#include "platform/graphics/test/MockWebGraphicsContext3D.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
+#include "public/platform/WebThread.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+using testing::InSequence;
+using testing::Return;
+using testing::Test;
+
+namespace {
+
+class MockWebGraphicsContext3DProvider : public blink::WebGraphicsContext3DProvider {
+public:
+ MockWebGraphicsContext3DProvider(blink::WebGraphicsContext3D* context3d)
+ : m_context3d(context3d) { }
+
+ blink::WebGraphicsContext3D* context3d()
+ {
+ return m_context3d;
+ }
+
+ GrContext* grContext()
+ {
+ return 0;
+ }
+
+private:
+ blink::WebGraphicsContext3D* m_context3d;
+};
+
+class FakeCanvas2DLayerBridge : public Canvas2DLayerBridge {
+public:
+ FakeCanvas2DLayerBridge(blink::WebGraphicsContext3D* context, PassOwnPtr<SkDeferredCanvas> canvas)
+ : Canvas2DLayerBridge(adoptPtr(new MockWebGraphicsContext3DProvider(context)), canvas, 0, NonOpaque)
+ , m_freeableBytes(0)
+ , m_freeMemoryIfPossibleCount(0)
+ , m_flushCount(0)
+ {
+ }
+
+ virtual size_t storageAllocatedForRecording() OVERRIDE
+ {
+ // Because the fake layer has no canvas to query, just
+ // return status quo. Allocation changes that would normally be
+ // initiated by the canvas can be faked by invoking
+ // storageAllocatedForRecordingChanged directly from the test code.
+ return m_bytesAllocated;
+ }
+
+ void fakeFreeableBytes(size_t size)
+ {
+ m_freeableBytes = size;
+ }
+
+ virtual size_t freeMemoryIfPossible(size_t size) OVERRIDE
+ {
+ m_freeMemoryIfPossibleCount++;
+ size_t bytesFreed = size < m_freeableBytes ? size : m_freeableBytes;
+ m_freeableBytes -= bytesFreed;
+ if (bytesFreed)
+ storageAllocatedForRecordingChanged(m_bytesAllocated - bytesFreed);
+ return bytesFreed;
+ }
+
+ virtual void flush() OVERRIDE
+ {
+ flushedDrawCommands();
+ m_freeableBytes = bytesAllocated();
+ m_flushCount++;
+ }
+
+public:
+ size_t m_freeableBytes;
+ int m_freeMemoryIfPossibleCount;
+ int m_flushCount;
+};
+
+class FakeCanvas2DLayerBridgePtr {
+public:
+ FakeCanvas2DLayerBridgePtr(PassRefPtr<FakeCanvas2DLayerBridge> layerBridge)
+ : m_layerBridge(layerBridge) { }
+
+ ~FakeCanvas2DLayerBridgePtr()
+ {
+ m_layerBridge->beginDestruction();
+ }
+
+ FakeCanvas2DLayerBridge* operator->() { return m_layerBridge.get(); }
+ FakeCanvas2DLayerBridge* get() { return m_layerBridge.get(); }
+
+private:
+ RefPtr<FakeCanvas2DLayerBridge> m_layerBridge;
+};
+
+static PassOwnPtr<SkDeferredCanvas> createCanvas()
+{
+ RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterPMColor(1, 1));
+ return adoptPtr(SkDeferredCanvas::Create(surface.get()));
+}
+
+} // unnamed namespace
+
+class Canvas2DLayerManagerTest : public Test {
+protected:
+ void storageAllocationTrackingTest()
+ {
+ Canvas2DLayerManager& manager = Canvas2DLayerManager::get();
+ manager.init(10, 10);
+ {
+ OwnPtr<blink::MockWebGraphicsContext3D> webContext = adoptPtr(new blink::MockWebGraphicsContext3D);
+ OwnPtr<SkDeferredCanvas> canvas1 = createCanvas();
+ FakeCanvas2DLayerBridgePtr layer1(adoptRef(new FakeCanvas2DLayerBridge(webContext.get(), canvas1.release())));
+ EXPECT_EQ((size_t)0, manager.m_bytesAllocated);
+ layer1->storageAllocatedForRecordingChanged(1);
+ EXPECT_EQ((size_t)1, manager.m_bytesAllocated);
+ // Test allocation increase
+ layer1->storageAllocatedForRecordingChanged(2);
+ EXPECT_EQ((size_t)2, manager.m_bytesAllocated);
+ // Test allocation decrease
+ layer1->storageAllocatedForRecordingChanged(1);
+ EXPECT_EQ((size_t)1, manager.m_bytesAllocated);
+ {
+ OwnPtr<SkDeferredCanvas> canvas2 = createCanvas();
+ FakeCanvas2DLayerBridgePtr layer2(adoptRef(new FakeCanvas2DLayerBridge(webContext.get(), canvas2.release())));
+ EXPECT_EQ((size_t)1, manager.m_bytesAllocated);
+ // verify multi-layer allocation tracking
+ layer2->storageAllocatedForRecordingChanged(2);
+ EXPECT_EQ((size_t)3, manager.m_bytesAllocated);
+ }
+ // Verify tracking after destruction
+ EXPECT_EQ((size_t)1, manager.m_bytesAllocated);
+ }
+ }
+
+ void evictionTest()
+ {
+ OwnPtr<blink::MockWebGraphicsContext3D> webContext = adoptPtr(new blink::MockWebGraphicsContext3D);
+ Canvas2DLayerManager& manager = Canvas2DLayerManager::get();
+ manager.init(10, 5);
+ OwnPtr<SkDeferredCanvas> canvas = createCanvas();
+ FakeCanvas2DLayerBridgePtr layer(adoptRef(new FakeCanvas2DLayerBridge(webContext.get(), canvas.release())));
+ layer->fakeFreeableBytes(10);
+ layer->storageAllocatedForRecordingChanged(8); // under the max
+ EXPECT_EQ(0, layer->m_freeMemoryIfPossibleCount);
+ layer->storageAllocatedForRecordingChanged(12); // over the max
+ EXPECT_EQ(1, layer->m_freeMemoryIfPossibleCount);
+ EXPECT_EQ((size_t)3, layer->m_freeableBytes);
+ EXPECT_EQ(0, layer->m_flushCount); // eviction succeeded without triggering a flush
+ EXPECT_EQ((size_t)5, layer->bytesAllocated());
+ }
+
+ void hiddenCanvasTest()
+ {
+ OwnPtr<blink::MockWebGraphicsContext3D> webContext = adoptPtr(new blink::MockWebGraphicsContext3D);
+ Canvas2DLayerManager& manager = Canvas2DLayerManager::get();
+ manager.init(20, 5);
+ OwnPtr<SkDeferredCanvas> canvas = createCanvas();
+ FakeCanvas2DLayerBridgePtr layer(adoptRef(new FakeCanvas2DLayerBridge(webContext.get(), canvas.release())));
+ layer->fakeFreeableBytes(5);
+ layer->storageAllocatedForRecordingChanged(10);
+ EXPECT_EQ(0, layer->m_freeMemoryIfPossibleCount);
+ EXPECT_EQ(0, layer->m_flushCount);
+ EXPECT_EQ((size_t)10, layer->bytesAllocated());
+ layer->setIsHidden(true);
+ EXPECT_EQ(1, layer->m_freeMemoryIfPossibleCount);
+ EXPECT_EQ((size_t)0, layer->m_freeableBytes);
+ EXPECT_EQ((size_t)0, layer->bytesAllocated());
+ EXPECT_EQ(1, layer->m_flushCount);
+ }
+
+ void addRemoveLayerTest()
+ {
+ OwnPtr<blink::MockWebGraphicsContext3D> webContext = adoptPtr(new blink::MockWebGraphicsContext3D);
+ Canvas2DLayerManager& manager = Canvas2DLayerManager::get();
+ manager.init(10, 5);
+ OwnPtr<SkDeferredCanvas> canvas = createCanvas();
+ FakeCanvas2DLayerBridgePtr layer(adoptRef(new FakeCanvas2DLayerBridge(webContext.get(), canvas.release())));
+ EXPECT_FALSE(manager.isInList(layer.get()));
+ layer->storageAllocatedForRecordingChanged(5);
+ EXPECT_TRUE(manager.isInList(layer.get()));
+ layer->storageAllocatedForRecordingChanged(0);
+ EXPECT_FALSE(manager.isInList(layer.get()));
+ }
+
+ void flushEvictionTest()
+ {
+ OwnPtr<blink::MockWebGraphicsContext3D> webContext = adoptPtr(new blink::MockWebGraphicsContext3D);
+ Canvas2DLayerManager& manager = Canvas2DLayerManager::get();
+ manager.init(10, 5);
+ OwnPtr<SkDeferredCanvas> canvas = createCanvas();
+ FakeCanvas2DLayerBridgePtr layer(adoptRef(new FakeCanvas2DLayerBridge(webContext.get(), canvas.release())));
+ layer->fakeFreeableBytes(1); // Not enough freeable bytes, will cause aggressive eviction by flushing
+ layer->storageAllocatedForRecordingChanged(8); // under the max
+ EXPECT_EQ(0, layer->m_freeMemoryIfPossibleCount);
+ layer->storageAllocatedForRecordingChanged(12); // over the max
+ EXPECT_EQ(2, layer->m_freeMemoryIfPossibleCount); // Two tries, one before flush, one after flush
+ EXPECT_EQ((size_t)5, layer->m_freeableBytes);
+ EXPECT_EQ(1, layer->m_flushCount); // flush was attempted
+ EXPECT_EQ((size_t)5, layer->bytesAllocated());
+ EXPECT_TRUE(manager.isInList(layer.get()));
+ }
+
+ void doDeferredFrameTestTask(FakeCanvas2DLayerBridge* layer, bool skipCommands)
+ {
+ EXPECT_FALSE(Canvas2DLayerManager::get().m_taskObserverActive);
+ layer->willUse();
+ layer->storageAllocatedForRecordingChanged(1);
+ EXPECT_TRUE(Canvas2DLayerManager::get().m_taskObserverActive);
+ if (skipCommands) {
+ layer->willUse();
+ layer->skippedPendingDrawCommands();
+ }
+ blink::Platform::current()->currentThread()->exitRunLoop();
+ }
+
+ class DeferredFrameTestTask : public blink::WebThread::Task {
+ public:
+ DeferredFrameTestTask(Canvas2DLayerManagerTest* test, FakeCanvas2DLayerBridge* layer, bool skipCommands)
+ {
+ m_test = test;
+ m_layer = layer;
+ m_skipCommands = skipCommands;
+ }
+
+ virtual void run() OVERRIDE
+ {
+ m_test->doDeferredFrameTestTask(m_layer, m_skipCommands);
+ }
+ private:
+ Canvas2DLayerManagerTest* m_test;
+ FakeCanvas2DLayerBridge* m_layer;
+ bool m_skipCommands;
+ };
+
+ void deferredFrameTest()
+ {
+ OwnPtr<blink::MockWebGraphicsContext3D> webContext = adoptPtr(new blink::MockWebGraphicsContext3D);
+ Canvas2DLayerManager::get().init(10, 10);
+ OwnPtr<SkDeferredCanvas> canvas = createCanvas();
+ FakeCanvas2DLayerBridgePtr layer(adoptRef(new FakeCanvas2DLayerBridge(webContext.get(), canvas.release())));
+ blink::Platform::current()->currentThread()->postTask(new DeferredFrameTestTask(this, layer.get(), true));
+ blink::Platform::current()->currentThread()->enterRunLoop();
+ // Verify that didProcessTask was called upon completion
+ EXPECT_FALSE(Canvas2DLayerManager::get().m_taskObserverActive);
+ // Verify that no flush was performed because frame is fresh
+ EXPECT_EQ(0, layer->m_flushCount);
+
+ // Verify that no flushes are triggered as long as frame are fresh
+ blink::Platform::current()->currentThread()->postTask(new DeferredFrameTestTask(this, layer.get(), true));
+ blink::Platform::current()->currentThread()->enterRunLoop();
+ EXPECT_FALSE(Canvas2DLayerManager::get().m_taskObserverActive);
+ EXPECT_EQ(0, layer->m_flushCount);
+
+ blink::Platform::current()->currentThread()->postTask(new DeferredFrameTestTask(this, layer.get(), true));
+ blink::Platform::current()->currentThread()->enterRunLoop();
+ EXPECT_FALSE(Canvas2DLayerManager::get().m_taskObserverActive);
+ EXPECT_EQ(0, layer->m_flushCount);
+
+ // Verify that a flush is triggered when queue is accumulating a multi-frame backlog.
+ blink::Platform::current()->currentThread()->postTask(new DeferredFrameTestTask(this, layer.get(), false));
+ blink::Platform::current()->currentThread()->enterRunLoop();
+ EXPECT_FALSE(Canvas2DLayerManager::get().m_taskObserverActive);
+ EXPECT_EQ(1, layer->m_flushCount);
+
+ blink::Platform::current()->currentThread()->postTask(new DeferredFrameTestTask(this, layer.get(), false));
+ blink::Platform::current()->currentThread()->enterRunLoop();
+ EXPECT_FALSE(Canvas2DLayerManager::get().m_taskObserverActive);
+ EXPECT_EQ(2, layer->m_flushCount);
+ }
+};
+
+namespace {
+
+TEST_F(Canvas2DLayerManagerTest, testStorageAllocationTracking)
+{
+ storageAllocationTrackingTest();
+}
+
+TEST_F(Canvas2DLayerManagerTest, testEviction)
+{
+ evictionTest();
+}
+
+TEST_F(Canvas2DLayerManagerTest, testFlushEviction)
+{
+ flushEvictionTest();
+}
+
+TEST_F(Canvas2DLayerManagerTest, testDeferredFrame)
+{
+ deferredFrameTest();
+}
+
+TEST_F(Canvas2DLayerManagerTest, testHiddenCanvas)
+{
+ hiddenCanvasTest();
+}
+
+TEST_F(Canvas2DLayerManagerTest, testAddRemoveLayer)
+{
+ addRemoveLayerTest();
+}
+
+} // unnamed namespace
+
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Color.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Color.cpp
index 97b568a1a9e..db081a70a37 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Color.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Color.cpp
@@ -26,17 +26,19 @@
#include "config.h"
#include "platform/graphics/Color.h"
+#include "platform/Decimal.h"
#include "wtf/Assertions.h"
-#include "wtf/DecimalNumber.h"
#include "wtf/HexNumber.h"
#include "wtf/MathExtras.h"
+#include "wtf/dtoa.h"
#include "wtf/text/StringBuilder.h"
using namespace std;
namespace WebCore {
-#if !COMPILER(MSVC)
+#if !COMPILER(MSVC) || COMPILER(CLANG)
+// FIXME: Use C++11 strong enums to avoid static data member with initializer definition problems.
const RGBA32 Color::black;
const RGBA32 Color::white;
const RGBA32 Color::darkGray;
@@ -177,27 +179,42 @@ int differenceSquared(const Color& c1, const Color& c2)
return dR * dR + dG * dG + dB * dB;
}
-Color::Color(const String& name)
+bool Color::setFromString(const String& name)
{
- if (name[0] == '#') {
- if (name.is8Bit())
- m_valid = parseHexColor(name.characters8() + 1, name.length() - 1, m_color);
- else
- m_valid = parseHexColor(name.characters16() + 1, name.length() - 1, m_color);
- } else {
- setNamedColor(name);
- }
+ if (name[0] != '#')
+ return setNamedColor(name);
+ if (name.is8Bit())
+ return parseHexColor(name.characters8() + 1, name.length() - 1, m_color);
+ return parseHexColor(name.characters16() + 1, name.length() - 1, m_color);
}
-Color::Color(const char* name)
+String Color::serializedAsCSSComponentValue() const
{
- if (name[0] == '#') {
- m_valid = parseHexColor(&name[1], m_color);
- } else {
- const NamedColor* foundColor = findColor(name, strlen(name));
- m_color = foundColor ? foundColor->ARGBValue : 0;
- m_valid = foundColor;
+ StringBuilder result;
+ result.reserveCapacity(32);
+ bool colorHasAlpha = hasAlpha();
+ if (colorHasAlpha)
+ result.append("rgba(", 5);
+ else
+ result.append("rgb(", 4);
+
+ result.appendNumber(static_cast<unsigned char>(red()));
+ result.append(", ", 2);
+
+ result.appendNumber(static_cast<unsigned char>(green()));
+ result.append(", ", 2);
+
+ result.appendNumber(static_cast<unsigned char>(blue()));
+ if (colorHasAlpha) {
+ result.append(", ", 2);
+
+ NumberToStringBuffer buffer;
+ const char* alphaString = numberToFixedPrecisionString(alpha() / 255.0f, 6, buffer, true);
+ result.append(alphaString, strlen(alphaString));
}
+
+ result.append(')');
+ return result.toString();
}
String Color::serialized() const
@@ -228,9 +245,7 @@ String Color::serialized() const
if (!alpha())
result.append('0');
else {
- NumberToLStringBuffer buffer;
- unsigned length = DecimalNumber(alpha() / 255.0).toStringDecimal(buffer, WTF::NumberToStringBufferLength);
- result.append(buffer, length);
+ result.append(Decimal::fromDouble(alpha() / 255.0).toString());
}
result.append(')');
@@ -260,11 +275,11 @@ static inline const NamedColor* findNamedColor(const String& name)
return findColor(buffer, length);
}
-void Color::setNamedColor(const String& name)
+bool Color::setNamedColor(const String& name)
{
const NamedColor* foundColor = findNamedColor(name);
m_color = foundColor ? foundColor->ARGBValue : 0;
- m_valid = foundColor;
+ return foundColor;
}
Color Color::light() const
@@ -312,6 +327,11 @@ Color Color::dark() const
alpha());
}
+Color Color::combineWithAlpha(float otherAlpha) const
+{
+ return colorWithOverrideAlpha(rgb(), (alpha() / 255.f) * otherAlpha);
+}
+
static int blendComponent(int c, int a)
{
// We use white.
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Color.h b/chromium/third_party/WebKit/Source/platform/graphics/Color.h
index 9664906a8f7..ce371ab23f8 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Color.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Color.h
@@ -62,16 +62,14 @@ const NamedColor* findColor(register const char* str, register unsigned len);
class PLATFORM_EXPORT Color {
WTF_MAKE_FAST_ALLOCATED;
public:
- Color() : m_color(0), m_valid(false) { }
- Color(RGBA32 color, bool valid = true) : m_color(color), m_valid(valid) { ASSERT(!m_color || m_valid); }
- Color(int r, int g, int b) : m_color(makeRGB(r, g, b)), m_valid(true) { }
- Color(int r, int g, int b, int a) : m_color(makeRGBA(r, g, b, a)), m_valid(true) { }
+ Color() : m_color(Color::transparent) { }
+ Color(RGBA32 color) : m_color(color) { }
+ Color(int r, int g, int b) : m_color(makeRGB(r, g, b)) { }
+ Color(int r, int g, int b, int a) : m_color(makeRGBA(r, g, b, a)) { }
// Color is currently limited to 32bit RGBA, perhaps some day we'll support better colors
- Color(float r, float g, float b, float a) : m_color(makeRGBA32FromFloats(r, g, b, a)), m_valid(true) { }
+ Color(float r, float g, float b, float a) : m_color(makeRGBA32FromFloats(r, g, b, a)) { }
// Creates a new color from the specific CMYK and alpha values.
- Color(float c, float m, float y, float k, float a) : m_color(makeRGBAFromCMYKA(c, m, y, k, a)), m_valid(true) { }
- explicit Color(const String&);
- explicit Color(const char*);
+ Color(float c, float m, float y, float k, float a) : m_color(makeRGBAFromCMYKA(c, m, y, k, a)) { }
static Color createUnchecked(int r, int g, int b)
{
@@ -88,13 +86,18 @@ public:
// - http://www.whatwg.org/specs/web-apps/current-work/#serialization-of-a-color
String serialized() const;
+ // Returns the color serialized according to CSSOM
+ // - http://dev.w3.org/csswg/cssom/#serialize-a-css-component-value
+ String serializedAsCSSComponentValue() const;
+
// Returns the color serialized as either #RRGGBB or #RRGGBBAA
// The latter format is not a valid CSS color, and should only be seen in DRT dumps.
String nameForRenderTreeAsText() const;
- void setNamedColor(const String&);
-
- bool isValid() const { return m_valid; }
+ // Returns whether parsing succeeded. The resulting Color is arbitrary
+ // if parsing fails.
+ bool setFromString(const String&);
+ bool setNamedColor(const String&);
bool hasAlpha() const { return alpha() < 255; }
@@ -104,8 +107,8 @@ public:
int alpha() const { return alphaChannel(m_color); }
RGBA32 rgb() const { return m_color; } // Preserve the alpha.
- void setRGB(int r, int g, int b) { m_color = makeRGB(r, g, b); m_valid = true; }
- void setRGB(RGBA32 rgb) { m_color = rgb; m_valid = true; }
+ void setRGB(int r, int g, int b) { m_color = makeRGB(r, g, b); }
+ void setRGB(RGBA32 rgb) { m_color = rgb; }
void getRGBA(float& r, float& g, float& b, float& a) const;
void getRGBA(double& r, double& g, double& b, double& a) const;
void getHSL(double& h, double& s, double& l) const;
@@ -113,6 +116,8 @@ public:
Color light() const;
Color dark() const;
+ Color combineWithAlpha(float otherAlpha) const;
+
// This is an implementation of Porter-Duff's "source-over" equation
Color blend(const Color&) const;
Color blendWithWhite() const;
@@ -130,12 +135,11 @@ public:
private:
RGBA32 m_color;
- bool m_valid;
};
inline bool operator==(const Color& a, const Color& b)
{
- return a.rgb() == b.rgb() && a.isValid() == b.isValid();
+ return a.rgb() == b.rgb();
}
inline bool operator!=(const Color& a, const Color& b)
@@ -148,10 +152,6 @@ PLATFORM_EXPORT RGBA32 premultipliedARGBFromColor(const Color&);
inline Color blend(const Color& from, const Color& to, double progress, bool blendPremultiplied = true)
{
- // We need to preserve the state of the valid flag at the end of the animation
- if (progress == 1 && !to.isValid())
- return Color();
-
if (blendPremultiplied) {
// Contrary to the name, RGBA32 actually stores ARGB, so we can initialize Color directly from premultipliedARGBFromColor().
// Also, premultipliedARGBFromColor() bails on zero alpha, so special-case that.
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ColorSpace.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ColorSpace.cpp
new file mode 100644
index 00000000000..b33b64db0e2
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ColorSpace.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. 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"
+#include "platform/graphics/ColorSpace.h"
+
+#include "wtf/MathExtras.h"
+
+namespace WebCore {
+
+namespace ColorSpaceUtilities {
+
+static const uint8_t* getLinearRgbLUT()
+{
+ static uint8_t linearRgbLUT[256];
+ static bool initialized;
+ if (!initialized) {
+ for (unsigned i = 0; i < 256; i++) {
+ float color = i / 255.0f;
+ color = (color <= 0.04045f ? color / 12.92f : pow((color + 0.055f) / 1.055f, 2.4f));
+ color = std::max(0.0f, color);
+ color = std::min(1.0f, color);
+ linearRgbLUT[i] = static_cast<uint8_t>(round(color * 255));
+ }
+ initialized = true;
+ }
+ return linearRgbLUT;
+}
+
+static const uint8_t* getDeviceRgbLUT()
+{
+ static uint8_t deviceRgbLUT[256];
+ static bool initialized;
+ if (!initialized) {
+ for (unsigned i = 0; i < 256; i++) {
+ float color = i / 255.0f;
+ color = (powf(color, 1.0f / 2.4f) * 1.055f) - 0.055f;
+ color = std::max(0.0f, color);
+ color = std::min(1.0f, color);
+ deviceRgbLUT[i] = static_cast<uint8_t>(round(color * 255));
+ }
+ initialized = true;
+ }
+ return deviceRgbLUT;
+}
+
+const uint8_t* getConversionLUT(ColorSpace dstColorSpace, ColorSpace srcColorSpace)
+{
+ // Identity.
+ if (srcColorSpace == dstColorSpace)
+ return 0;
+
+ // Only sRGB/DeviceRGB <-> linearRGB are supported at the moment.
+ if ((srcColorSpace != ColorSpaceLinearRGB && srcColorSpace != ColorSpaceDeviceRGB)
+ || (dstColorSpace != ColorSpaceLinearRGB && dstColorSpace != ColorSpaceDeviceRGB))
+ return 0;
+
+ if (dstColorSpace == ColorSpaceLinearRGB)
+ return getLinearRgbLUT();
+ if (dstColorSpace == ColorSpaceDeviceRGB)
+ return getDeviceRgbLUT();
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+Color convertColor(const Color& srcColor, ColorSpace dstColorSpace, ColorSpace srcColorSpace)
+{
+ const uint8_t* lookupTable = getConversionLUT(dstColorSpace, srcColorSpace);
+ if (!lookupTable)
+ return srcColor;
+
+ return Color(lookupTable[srcColor.red()], lookupTable[srcColor.green()], lookupTable[srcColor.blue()], srcColor.alpha());
+}
+
+} // namespace ColorSpaceUtilities
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ColorSpace.h b/chromium/third_party/WebKit/Source/platform/graphics/ColorSpace.h
index 06918f7ff1f..9b1735a2463 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ColorSpace.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ColorSpace.h
@@ -27,6 +27,7 @@
#define ColorSpace_h
#include "platform/PlatformExport.h"
+#include "platform/graphics/Color.h"
namespace WebCore {
@@ -36,6 +37,20 @@ enum ColorSpace {
ColorSpaceLinearRGB
};
+namespace ColorSpaceUtilities {
+
+// Get a pointer to a 8-bit lookup table that will convert color components
+// in the |srcColorSpace| to the |dstColorSpace|.
+// If the conversion cannot be performed, or is a no-op (identity transform),
+// then 0 is returned.
+// (Note that a round-trip - f(B,A)[f(A,B)[x]] - is not lossless in general.)
+const uint8_t* getConversionLUT(ColorSpace dstColorSpace, ColorSpace srcColorSpace = ColorSpaceDeviceRGB);
+
+// Convert a Color assumed to be in the |srcColorSpace| into the |dstColorSpace|.
+Color convertColor(const Color& srcColor, ColorSpace dstColorSpace, ColorSpace srcColorSpace = ColorSpaceDeviceRGB);
+
+} // namespace ColorSpaceUtilities
+
} // namespace WebCore
#endif // ColorSpace_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/CompositingReasons.h b/chromium/third_party/WebKit/Source/platform/graphics/CompositingReasons.h
new file mode 100644
index 00000000000..b4aa6f895c2
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/CompositingReasons.h
@@ -0,0 +1,328 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CompositingReasons_h
+#define CompositingReasons_h
+
+#include "wtf/MathExtras.h"
+#include <stdint.h>
+
+namespace WebCore {
+
+const uint64_t CompositingReasonNone = 0;
+const uint64_t CompositingReasonAll = ~static_cast<uint64_t>(0);
+
+// Intrinsic reasons that can be known right away by the layer
+const uint64_t CompositingReason3DTransform = UINT64_C(1) << 0;
+const uint64_t CompositingReasonVideo = UINT64_C(1) << 1;
+const uint64_t CompositingReasonCanvas = UINT64_C(1) << 2;
+const uint64_t CompositingReasonPlugin = UINT64_C(1) << 3;
+const uint64_t CompositingReasonIFrame = UINT64_C(1) << 4;
+const uint64_t CompositingReasonBackfaceVisibilityHidden = UINT64_C(1) << 5;
+const uint64_t CompositingReasonActiveAnimation = UINT64_C(1) << 6;
+const uint64_t CompositingReasonTransitionProperty = UINT64_C(1) << 7;
+const uint64_t CompositingReasonFilters = UINT64_C(1) << 8;
+const uint64_t CompositingReasonPositionFixed = UINT64_C(1) << 9;
+const uint64_t CompositingReasonOverflowScrollingTouch = UINT64_C(1) << 10;
+const uint64_t CompositingReasonOverflowScrollingParent = UINT64_C(1) << 11;
+const uint64_t CompositingReasonOutOfFlowClipping = UINT64_C(1) << 12;
+const uint64_t CompositingReasonVideoOverlay = UINT64_C(1) << 13;
+const uint64_t CompositingReasonWillChangeCompositingHint = UINT64_C(1) << 14;
+
+// Overlap reasons that require knowing what's behind you in paint-order before knowing the answer
+const uint64_t CompositingReasonAssumedOverlap = UINT64_C(1) << 15;
+const uint64_t CompositingReasonOverlap = UINT64_C(1) << 16;
+const uint64_t CompositingReasonNegativeZIndexChildren = UINT64_C(1) << 17;
+const uint64_t CompositingReasonScrollsWithRespectToSquashingLayer = UINT64_C(1) << 18;
+const uint64_t CompositingReasonSquashingSparsityExceeded = UINT64_C(1) << 19;
+const uint64_t CompositingReasonSquashingClippingContainerMismatch = UINT64_C(1) << 20;
+const uint64_t CompositingReasonSquashingOpacityAncestorMismatch = UINT64_C(1) << 21;
+const uint64_t CompositingReasonSquashingTransformAncestorMismatch = UINT64_C(1) << 22;
+const uint64_t CompositingReasonSquashingFilterAncestorMismatch = UINT64_C(1) << 23;
+const uint64_t CompositingReasonSquashingWouldBreakPaintOrder = UINT64_C(1) << 24;
+const uint64_t CompositingReasonSquashingVideoIsDisallowed = UINT64_C(1) << 25;
+const uint64_t CompositingReasonSquashedLayerClipsCompositingDescendants = UINT64_C(1) << 26;
+
+// Subtree reasons that require knowing what the status of your subtree is before knowing the answer
+const uint64_t CompositingReasonTransformWithCompositedDescendants = UINT64_C(1) << 27;
+const uint64_t CompositingReasonOpacityWithCompositedDescendants = UINT64_C(1) << 28;
+const uint64_t CompositingReasonMaskWithCompositedDescendants = UINT64_C(1) << 29;
+const uint64_t CompositingReasonReflectionWithCompositedDescendants = UINT64_C(1) << 30;
+const uint64_t CompositingReasonFilterWithCompositedDescendants = UINT64_C(1) << 31;
+const uint64_t CompositingReasonBlendingWithCompositedDescendants = UINT64_C(1) << 32;
+const uint64_t CompositingReasonClipsCompositingDescendants = UINT64_C(1) << 33;
+const uint64_t CompositingReasonPerspectiveWith3DDescendants = UINT64_C(1) << 34;
+const uint64_t CompositingReasonPreserve3DWith3DDescendants = UINT64_C(1) << 35;
+const uint64_t CompositingReasonReflectionOfCompositedParent = UINT64_C(1) << 36;
+const uint64_t CompositingReasonIsolateCompositedDescendants = UINT64_C(1) << 37;
+
+// The root layer is a special case that may be forced to be a layer, but also it needs to be
+// a layer if anything else in the subtree is composited.
+const uint64_t CompositingReasonRoot = UINT64_C(1) << 38;
+
+// CompositedLayerMapping internal hierarchy reasons
+const uint64_t CompositingReasonLayerForAncestorClip = UINT64_C(1) << 39;
+const uint64_t CompositingReasonLayerForDescendantClip = UINT64_C(1) << 40;
+const uint64_t CompositingReasonLayerForPerspective = UINT64_C(1) << 41;
+const uint64_t CompositingReasonLayerForHorizontalScrollbar = UINT64_C(1) << 42;
+const uint64_t CompositingReasonLayerForVerticalScrollbar = UINT64_C(1) << 43;
+const uint64_t CompositingReasonLayerForScrollCorner = UINT64_C(1) << 44;
+const uint64_t CompositingReasonLayerForScrollingContents = UINT64_C(1) << 45;
+const uint64_t CompositingReasonLayerForScrollingContainer = UINT64_C(1) << 46;
+const uint64_t CompositingReasonLayerForSquashingContents = UINT64_C(1) << 47;
+const uint64_t CompositingReasonLayerForSquashingContainer = UINT64_C(1) << 48;
+const uint64_t CompositingReasonLayerForForeground = UINT64_C(1) << 49;
+const uint64_t CompositingReasonLayerForBackground = UINT64_C(1) << 50;
+const uint64_t CompositingReasonLayerForMask = UINT64_C(1) << 51;
+const uint64_t CompositingReasonLayerForClippingMask = UINT64_C(1) << 52;
+const uint64_t CompositingReasonLayerForScrollingBlockSelection = UINT64_C(1) << 53;
+
+// Various combinations of compositing reasons are defined here also, for more intutive and faster bitwise logic.
+const uint64_t CompositingReasonComboAllDirectReasons =
+ CompositingReason3DTransform
+ | CompositingReasonVideo
+ | CompositingReasonCanvas
+ | CompositingReasonPlugin
+ | CompositingReasonIFrame
+ | CompositingReasonBackfaceVisibilityHidden
+ | CompositingReasonActiveAnimation
+ | CompositingReasonTransitionProperty
+ | CompositingReasonFilters
+ | CompositingReasonPositionFixed
+ | CompositingReasonOverflowScrollingTouch
+ | CompositingReasonOverflowScrollingParent
+ | CompositingReasonOutOfFlowClipping
+ | CompositingReasonVideoOverlay
+ | CompositingReasonWillChangeCompositingHint;
+
+const uint64_t CompositingReasonComboAllStyleDeterminedReasons =
+ CompositingReason3DTransform
+ | CompositingReasonBackfaceVisibilityHidden
+ | CompositingReasonActiveAnimation
+ | CompositingReasonTransitionProperty
+ | CompositingReasonFilters
+ | CompositingReasonWillChangeCompositingHint;
+
+const uint64_t CompositingReasonComboReasonsThatRequireOwnBacking =
+ CompositingReasonComboAllDirectReasons
+ | CompositingReasonOverlap
+ | CompositingReasonAssumedOverlap
+ | CompositingReasonNegativeZIndexChildren
+ | CompositingReasonScrollsWithRespectToSquashingLayer
+ | CompositingReasonSquashingSparsityExceeded
+ | CompositingReasonSquashingClippingContainerMismatch
+ | CompositingReasonSquashingOpacityAncestorMismatch
+ | CompositingReasonSquashingTransformAncestorMismatch
+ | CompositingReasonSquashingFilterAncestorMismatch
+ | CompositingReasonSquashingWouldBreakPaintOrder
+ | CompositingReasonSquashingVideoIsDisallowed
+ | CompositingReasonSquashedLayerClipsCompositingDescendants
+ | CompositingReasonTransformWithCompositedDescendants
+ | CompositingReasonOpacityWithCompositedDescendants
+ | CompositingReasonMaskWithCompositedDescendants
+ | CompositingReasonFilterWithCompositedDescendants
+ | CompositingReasonBlendingWithCompositedDescendants
+ | CompositingReasonIsolateCompositedDescendants
+ | CompositingReasonPreserve3DWith3DDescendants; // preserve-3d has to create backing store to ensure that 3d-transformed elements intersect.
+
+const uint64_t CompositingReasonComboSquashableReasons =
+ CompositingReasonOverlap
+ | CompositingReasonAssumedOverlap
+ | CompositingReasonOverflowScrollingParent;
+
+typedef uint64_t CompositingReasons;
+
+// Any reasons other than overlap or assumed overlap will require the layer to be separately compositing.
+inline bool requiresCompositing(CompositingReasons reasons)
+{
+ return reasons & ~CompositingReasonComboSquashableReasons;
+}
+
+// If the layer has overlap or assumed overlap, but no other reasons, then it should be squashed.
+inline bool requiresSquashing(CompositingReasons reasons)
+{
+ return !requiresCompositing(reasons) && (reasons & CompositingReasonComboSquashableReasons);
+}
+
+struct CompositingReasonStringMap {
+ CompositingReasons reason;
+ const char* shortName;
+ const char* description;
+};
+
+// FIXME: This static data shouldn't be in a header. When it's in the header
+// it's copied into every compilation unit that includes the header.
+static const CompositingReasonStringMap compositingReasonStringMap[] = {
+ { CompositingReasonNone,
+ "Unknown",
+ "No reason given" },
+ { CompositingReason3DTransform,
+ "transform3D",
+ "Has a 3d transform" },
+ { CompositingReasonVideo,
+ "video",
+ "Is an accelerated video" },
+ { CompositingReasonCanvas,
+ "canvas",
+ "Is an accelerated canvas" },
+ { CompositingReasonPlugin,
+ "plugin",
+ "Is an accelerated plugin" },
+ { CompositingReasonIFrame,
+ "iFrame",
+ "Is an accelerated iFrame" },
+ { CompositingReasonBackfaceVisibilityHidden,
+ "backfaceVisibilityHidden",
+ "Has backface-visibility: hidden" },
+ { CompositingReasonActiveAnimation,
+ "activeAnimation",
+ "Has an active accelerated animation or transition" },
+ { CompositingReasonTransitionProperty,
+ "transitionProperty",
+ "Has an acceleratable transition property (active or inactive)" },
+ { CompositingReasonFilters,
+ "filters",
+ "Has an accelerated filter" },
+ { CompositingReasonPositionFixed,
+ "positionFixed",
+ "Is fixed position" },
+ { 0, 0, 0 }, // Available.
+ { CompositingReasonOverflowScrollingTouch,
+ "overflowScrollingTouch",
+ "Is a scrollable overflow element" },
+ { CompositingReasonOverflowScrollingParent,
+ "overflowScrollingParent",
+ "Scroll parent is not an ancestor" },
+ { CompositingReasonOutOfFlowClipping,
+ "outOfFlowClipping",
+ "Has clipping ancestor" },
+ { CompositingReasonVideoOverlay,
+ "videoOverlay",
+ "Is overlay controls for video" },
+ { CompositingReasonWillChangeCompositingHint,
+ "willChange",
+ "Has a will-change compositing hint" },
+ { 0, 0, 0 }, // Available.
+ { CompositingReasonAssumedOverlap,
+ "assumedOverlap",
+ "Might overlap other composited content" },
+ { CompositingReasonOverlap,
+ "overlap",
+ "Overlaps other composited content" },
+ { CompositingReasonNegativeZIndexChildren,
+ "negativeZIndexChildren",
+ "Parent with composited negative z-index content" },
+ { CompositingReasonScrollsWithRespectToSquashingLayer,
+ "scrollsWithRespectToSquashingLayer",
+ "Cannot be squashed since this layer scrolls with respect to the squashing layer" },
+ { CompositingReasonSquashingSparsityExceeded,
+ "squashingSparsityExceeded",
+ "Cannot be squashed as the squashing layer would become too sparse" },
+ { CompositingReasonSquashingClippingContainerMismatch,
+ "squashingClippingContainerMismatch",
+ "Cannot be squashed because this layer has a different clipping container than the squashing layer" },
+ { CompositingReasonSquashingOpacityAncestorMismatch,
+ "squashingOpacityAncestorMismatch",
+ "Cannot be squashed because this layer has a different opacity ancestor than the squashing layer" },
+ { CompositingReasonSquashingTransformAncestorMismatch,
+ "squashingTransformAncestorMismatch",
+ "Cannot be squashed because this layer has a different transform ancestor than the squashing layer" },
+ { CompositingReasonSquashingFilterAncestorMismatch,
+ "squashingFilterAncestorMismatch",
+ "Cannot be squashed because this layer has a different filter ancestor than the squashing layer" },
+ { CompositingReasonSquashingWouldBreakPaintOrder,
+ "squashingWouldBreakPaintOrder",
+ "Cannot be squashed without breaking paint order" },
+ { CompositingReasonSquashingVideoIsDisallowed,
+ "squashingVideoIsDisallowed",
+ "Squashing video is not supported" },
+ { CompositingReasonSquashedLayerClipsCompositingDescendants,
+ "squashedLayerClipsCompositingDescendants",
+ "Squashing a layer that clips composited descendants is not supported." },
+ { CompositingReasonTransformWithCompositedDescendants,
+ "transformWithCompositedDescendants",
+ "Has a transform that needs to be known by compositor because of composited descendants" },
+ { CompositingReasonOpacityWithCompositedDescendants,
+ "opacityWithCompositedDescendants",
+ "Has opacity that needs to be applied by compositor because of composited descendants" },
+ { CompositingReasonMaskWithCompositedDescendants,
+ "maskWithCompositedDescendants",
+ "Has a mask that needs to be known by compositor because of composited descendants" },
+ { CompositingReasonReflectionWithCompositedDescendants,
+ "reflectionWithCompositedDescendants",
+ "Has a reflection that needs to be known by compositor because of composited descendants" },
+ { CompositingReasonFilterWithCompositedDescendants,
+ "filterWithCompositedDescendants",
+ "Has a filter effect that needs to be known by compositor because of composited descendants" },
+ { CompositingReasonBlendingWithCompositedDescendants,
+ "blendingWithCompositedDescendants",
+ "Has a blenidng effect that needs to be known by compositor because of composited descendants" },
+ { CompositingReasonClipsCompositingDescendants,
+ "clipsCompositingDescendants",
+ "Has a clip that needs to be known by compositor because of composited descendants" },
+ { CompositingReasonPerspectiveWith3DDescendants,
+ "perspectiveWith3DDescendants",
+ "Has a perspective transform that needs to be known by compositor because of 3d descendants" },
+ { CompositingReasonPreserve3DWith3DDescendants,
+ "preserve3DWith3DDescendants",
+ "Has a preserves-3d property that needs to be known by compositor because of 3d descendants" },
+ { CompositingReasonReflectionOfCompositedParent,
+ "reflectionOfCompositedParent",
+ "Is a reflection of a composited layer" },
+ { CompositingReasonIsolateCompositedDescendants,
+ "isolateCompositedDescendants",
+ "Should isolate descendants to apply a blend effect" },
+ { CompositingReasonRoot,
+ "root",
+ "Is the root layer" },
+ { CompositingReasonLayerForAncestorClip,
+ "layerForAncestorClip",
+ "Secondary layer, applies a clip due to a sibling in the compositing tree" },
+ { CompositingReasonLayerForDescendantClip,
+ "layerForDescendantClip",
+ "Secondary layer, to clip descendants of the owning layer" },
+ { CompositingReasonLayerForPerspective,
+ "layerForPerspective",
+ "Secondary layer, to house the perspective transform for all descendants" },
+ { CompositingReasonLayerForHorizontalScrollbar,
+ "layerForHorizontalScrollbar",
+ "Secondary layer, the horizontal scrollbar layer" },
+ { CompositingReasonLayerForVerticalScrollbar,
+ "layerForVerticalScrollbar",
+ "Secondary layer, the vertical scrollbar layer" },
+ { CompositingReasonLayerForScrollCorner,
+ "layerForScrollCorner",
+ "Secondary layer, the scroll corner layer" },
+ { CompositingReasonLayerForScrollingContents,
+ "layerForScrollingContents",
+ "Secondary layer, to house contents that can be scrolled" },
+ { CompositingReasonLayerForScrollingContainer,
+ "layerForScrollingContainer",
+ "Secondary layer, used to position the scolling contents while scrolling" },
+ { CompositingReasonLayerForSquashingContents,
+ "layerForSquashingContents",
+ "Secondary layer, home for a group of squashable content" },
+ { CompositingReasonLayerForSquashingContainer,
+ "layerForSquashingContainer",
+ "Secondary layer, no-op layer to place the squashing layer correctly in the composited layer tree" },
+ { CompositingReasonLayerForForeground,
+ "layerForForeground",
+ "Secondary layer, to contain any normal flow and positive z-index contents on top of a negative z-index layer" },
+ { CompositingReasonLayerForBackground,
+ "layerForBackground",
+ "Secondary layer, to contain acceleratable background content" },
+ { CompositingReasonLayerForMask,
+ "layerForMask",
+ "Secondary layer, to contain the mask contents" },
+ { CompositingReasonLayerForClippingMask,
+ "layerForClippingMask",
+ "Secondary layer, for clipping mask" },
+ { CompositingReasonLayerForScrollingBlockSelection,
+ "layerForScrollingBlockSelection",
+ "Secondary layer, to house block selection gaps for composited scrolling with no scrolling contents" },
+};
+
+} // namespace WebCore
+
+#endif // CompositingReasons_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.cpp b/chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.cpp
index dcbcabf3777..667e2553ecc 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.cpp
@@ -62,22 +62,22 @@ void CrossfadeGeneratedImage::drawCrossfade(GraphicsContext* context)
// Draw the image we're fading away from.
context->save();
if (m_crossfadeSize != fromImageSize) {
- context->scale(FloatSize(
+ context->scale(
static_cast<float>(m_crossfadeSize.width()) / fromImageSize.width(),
- static_cast<float>(m_crossfadeSize.height()) / fromImageSize.height()));
+ static_cast<float>(m_crossfadeSize.height()) / fromImageSize.height());
}
- context->setAlpha(inversePercentage);
+ context->setAlphaAsFloat(inversePercentage);
context->drawImage(m_fromImage, IntPoint());
context->restore();
// Draw the image we're fading towards.
context->save();
if (m_crossfadeSize != toImageSize) {
- context->scale(FloatSize(
+ context->scale(
static_cast<float>(m_crossfadeSize.width()) / toImageSize.width(),
- static_cast<float>(m_crossfadeSize.height()) / toImageSize.height()));
+ static_cast<float>(m_crossfadeSize.height()) / toImageSize.height());
}
- context->setAlpha(m_percentage);
+ context->setAlphaAsFloat(m_percentage);
context->drawImage(m_toImage, IntPoint(), CompositePlusLighter);
context->restore();
@@ -91,7 +91,7 @@ void CrossfadeGeneratedImage::draw(GraphicsContext* context, const FloatRect& ds
context->clip(dstRect);
context->translate(dstRect.x(), dstRect.y());
if (dstRect.size() != srcRect.size())
- context->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()));
+ context->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height());
context->translate(-srcRect.x(), -srcRect.y());
drawCrossfade(context);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.h b/chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.h
index 8d96298f126..5be008518e3 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/CrossfadeGeneratedImage.h
@@ -43,12 +43,12 @@ public:
return adoptRef(new CrossfadeGeneratedImage(fromImage, toImage, percentage, crossfadeSize, size));
}
- virtual void setContainerSize(const IntSize&) { }
- virtual bool usesContainerSize() const { return false; }
- virtual bool hasRelativeWidth() const { return false; }
- virtual bool hasRelativeHeight() const { return false; }
+ virtual void setContainerSize(const IntSize&) OVERRIDE { }
+ virtual bool usesContainerSize() const OVERRIDE { return false; }
+ virtual bool hasRelativeWidth() const OVERRIDE { return false; }
+ virtual bool hasRelativeHeight() const OVERRIDE { return false; }
- virtual IntSize size() const { return m_crossfadeSize; }
+ virtual IntSize size() const OVERRIDE { return m_crossfadeSize; }
protected:
virtual void draw(GraphicsContext*, const FloatRect&, const FloatRect&,
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp b/chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp
index 55ff319432f..a32fc04b4c9 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp
@@ -47,27 +47,26 @@ DecodingImageGenerator::~DecodingImageGenerator()
{
}
-SkData* DecodingImageGenerator::refEncodedData()
+SkData* DecodingImageGenerator::onRefEncodedData()
{
// FIXME: If the image has been clipped or scaled, do not return the original
// encoded data, since on playback it will not be known how the clipping/scaling
// was done.
- RefPtr<SharedBuffer> buffer = 0;
+ RefPtr<SharedBuffer> buffer = nullptr;
bool allDataReceived = false;
m_frameGenerator->copyData(&buffer, &allDataReceived);
- if (buffer && allDataReceived) {
+ if (buffer && allDataReceived)
return SkData::NewWithCopy(buffer->data(), buffer->size());
- }
return 0;
}
-bool DecodingImageGenerator::getInfo(SkImageInfo* info)
+bool DecodingImageGenerator::onGetInfo(SkImageInfo* info)
{
*info = m_imageInfo;
return true;
}
-bool DecodingImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes)
+bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount)
{
TRACE_EVENT1("webkit", "DecodingImageGenerator::getPixels", "index", static_cast<int>(m_frameIndex));
@@ -79,7 +78,7 @@ bool DecodingImageGenerator::getPixels(const SkImageInfo& info, void* pixels, si
ASSERT(info.fAlphaType == m_imageInfo.fAlphaType);
PlatformInstrumentation::willDecodeLazyPixelRef(m_generationId);
bool decoded = m_frameGenerator->decodeAndScale(m_imageInfo, m_frameIndex, pixels, rowBytes);
- PlatformInstrumentation::didDecodeLazyPixelRef(m_generationId);
+ PlatformInstrumentation::didDecodeLazyPixelRef();
return decoded;
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.h b/chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.h
index edea6418259..fe5cb00b60d 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.h
@@ -42,18 +42,18 @@ class ImageFrameGenerator;
//
// This class does not own an ImageDecode. It does not own encoded data. It serves
// as and adapter to ImageFrameGenerator which actually performs decoding.
-class DecodingImageGenerator : public SkImageGenerator {
+class DecodingImageGenerator FINAL : public SkImageGenerator {
public:
DecodingImageGenerator(PassRefPtr<ImageFrameGenerator>, const SkImageInfo&, size_t index);
virtual ~DecodingImageGenerator();
- // SkImageGenerator implementation.
- virtual SkData* refEncodedData();
- virtual bool getInfo(SkImageInfo*);
- virtual bool getPixels(const SkImageInfo&, void* pixels, size_t rowBytes);
-
void setGenerationId(size_t id) { m_generationId = id; }
+protected:
+ virtual SkData* onRefEncodedData() OVERRIDE;
+ virtual bool onGetInfo(SkImageInfo*) OVERRIDE;
+ virtual bool onGetPixels(const SkImageInfo&, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount) OVERRIDE;
+
private:
RefPtr<ImageFrameGenerator> m_frameGenerator;
SkImageInfo m_imageInfo;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp b/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp
index 557ce37339c..4f3822ee4e4 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp
@@ -36,22 +36,21 @@ namespace WebCore {
namespace {
-// URI label for a lazily decoded SkPixelRef.
-const char labelLazyDecoded[] = "lazy";
-
// URI label for SkDiscardablePixelRef.
const char labelDiscardable[] = "discardable";
} // namespace
bool DeferredImageDecoder::s_enabled = false;
-bool DeferredImageDecoder::s_skiaDiscardableMemoryEnabled = false;
DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)
: m_allDataReceived(false)
+ , m_lastDataSize(0)
+ , m_dataChanged(false)
, m_actualDecoder(actualDecoder)
, m_orientation(DefaultImageOrientation)
, m_repetitionCount(cAnimationNone)
+ , m_hasColorProfile(false)
{
}
@@ -74,21 +73,19 @@ bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap)
{
return bitmap.pixelRef()
&& bitmap.pixelRef()->getURI()
- && (!memcmp(bitmap.pixelRef()->getURI(), labelLazyDecoded, sizeof(labelLazyDecoded))
- || !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable)));
+ && !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable));
}
void DeferredImageDecoder::setEnabled(bool enabled)
{
s_enabled = enabled;
-#if !OS(ANDROID)
- // FIXME: This code is temporary to enable discardable memory for
- // non-Android platforms. In the future all platforms will be
- // the same and we can remove this code.
- s_skiaDiscardableMemoryEnabled = enabled;
if (enabled)
ImageDecodingStore::setImageCachingEnabled(false);
-#endif
+}
+
+bool DeferredImageDecoder::enabled()
+{
+ return s_enabled;
}
String DeferredImageDecoder::filenameExtension() const
@@ -110,17 +107,21 @@ ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
return 0;
}
-void DeferredImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
+void DeferredImageDecoder::setData(SharedBuffer& data, bool allDataReceived)
{
if (m_actualDecoder) {
- m_data = data;
+ const bool firstData = !m_data;
+ const bool moreData = data.size() > m_lastDataSize;
+ m_dataChanged = firstData || moreData;
+ m_data = RefPtr<SharedBuffer>(data);
+ m_lastDataSize = data.size();
m_allDataReceived = allDataReceived;
- m_actualDecoder->setData(data, allDataReceived);
+ m_actualDecoder->setData(&data, allDataReceived);
prepareLazyDecodedFrames();
}
if (m_frameGenerator)
- m_frameGenerator->setData(data, allDataReceived);
+ m_frameGenerator->setData(&data, allDataReceived);
}
bool DeferredImageDecoder::isSizeAvailable()
@@ -130,6 +131,11 @@ bool DeferredImageDecoder::isSizeAvailable()
return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true;
}
+bool DeferredImageDecoder::hasColorProfile() const
+{
+ return m_actualDecoder ? m_actualDecoder->hasColorProfile() : m_hasColorProfile;
+}
+
IntSize DeferredImageDecoder::size() const
{
return m_actualDecoder ? m_actualDecoder->size() : m_size;
@@ -137,7 +143,7 @@ IntSize DeferredImageDecoder::size() const
IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
{
- // FIXME: Frame size is assumed to be uniform. This might not be true for
+ // FIXME: LocalFrame size is assumed to be uniform. This might not be true for
// future supported codecs.
return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size;
}
@@ -205,6 +211,7 @@ void DeferredImageDecoder::activateLazyDecoding()
m_size = m_actualDecoder->size();
m_orientation = m_actualDecoder->orientation();
m_filenameExtension = m_actualDecoder->filenameExtension();
+ m_hasColorProfile = m_actualDecoder->hasColorProfile();
const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationNone || (m_allDataReceived && m_actualDecoder->frameCount() == 1u);
m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_actualDecoder->decodedSize().width(), m_actualDecoder->decodedSize().height()), m_data, m_allDataReceived, !isSingleFrame);
}
@@ -221,6 +228,11 @@ void DeferredImageDecoder::prepareLazyDecodedFrames()
const size_t previousSize = m_lazyDecodedFrames.size();
m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
+
+ // We have encountered a broken image file. Simply bail.
+ if (m_lazyDecodedFrames.size() < previousSize)
+ return;
+
for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) {
OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame()));
frame->setSkBitmap(createBitmap(i));
@@ -231,8 +243,17 @@ void DeferredImageDecoder::prepareLazyDecodedFrames()
// The last lazy decoded frame created from previous call might be
// incomplete so update its state.
- if (previousSize)
- m_lazyDecodedFrames[previousSize - 1]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(previousSize - 1) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
+ if (previousSize) {
+ const size_t lastFrame = previousSize - 1;
+ m_lazyDecodedFrames[lastFrame]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(lastFrame) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
+
+ // If data has changed then create a new bitmap. This forces
+ // Skia to decode again.
+ if (m_dataChanged) {
+ m_dataChanged = false;
+ m_lazyDecodedFrames[lastFrame]->setSkBitmap(createBitmap(lastFrame));
+ }
+ }
if (m_allDataReceived) {
m_repetitionCount = m_actualDecoder->repetitionCount();
@@ -241,18 +262,8 @@ void DeferredImageDecoder::prepareLazyDecodedFrames()
}
}
-// Creates either a SkBitmap backed by SkDiscardablePixelRef or a SkBitmap using the
-// legacy LazyDecodingPixelRef.
-SkBitmap DeferredImageDecoder::createBitmap(size_t index)
-{
- // This code is temporary until the transition to SkDiscardablePixelRef is complete.
- if (s_skiaDiscardableMemoryEnabled)
- return createSkiaDiscardableBitmap(index);
- return createLazyDecodingBitmap(index);
-}
-
// Creates a SkBitmap that is backed by SkDiscardablePixelRef.
-SkBitmap DeferredImageDecoder::createSkiaDiscardableBitmap(size_t index)
+SkBitmap DeferredImageDecoder::createBitmap(size_t index)
{
IntSize decodedSize = m_actualDecoder->decodedSize();
ASSERT(decodedSize.width() > 0);
@@ -261,7 +272,11 @@ SkBitmap DeferredImageDecoder::createSkiaDiscardableBitmap(size_t index)
SkImageInfo info;
info.fWidth = decodedSize.width();
info.fHeight = decodedSize.height();
+#if SK_B32_SHIFT // Little-endian RGBA pixels. (Android)
+ info.fColorType = kRGBA_8888_SkColorType;
+#else
info.fColorType = kBGRA_8888_SkColorType;
+#endif
info.fAlphaType = kPremul_SkAlphaType;
SkBitmap bitmap;
@@ -273,34 +288,6 @@ SkBitmap DeferredImageDecoder::createSkiaDiscardableBitmap(size_t index)
return bitmap;
}
-SkBitmap DeferredImageDecoder::createLazyDecodingBitmap(size_t index)
-{
- IntSize decodedSize = m_actualDecoder->decodedSize();
- ASSERT(decodedSize.width() > 0);
- ASSERT(decodedSize.height() > 0);
-
- SkImageInfo info;
- info.fWidth = decodedSize.width();
- info.fHeight = decodedSize.height();
- info.fColorType = kPMColor_SkColorType;
- info.fAlphaType = kPremul_SkAlphaType;
-
- // Creates a lazily decoded SkPixelRef that references the entire image without scaling.
- SkBitmap bitmap;
- bitmap.setConfig(info);
- bitmap.setPixelRef(new LazyDecodingPixelRef(info, m_frameGenerator, index))->unref();
-
- // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyDecodingPixelRef.
- // FIXME: It would be more useful to give the actual image URI.
- bitmap.pixelRef()->setURI(labelLazyDecoded);
-
- // Inform the bitmap that we will never change the pixels. This is a performance hint
- // subsystems that may try to cache this bitmap (e.g. pictures, pipes, gpu, pdf, etc.)
- bitmap.setImmutable();
-
- return bitmap;
-}
-
bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
{
// TODO: Implement.
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.h b/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.h
index 91710475f38..2aa48c6a090 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.h
@@ -52,14 +52,16 @@ public:
static bool isLazyDecoded(const SkBitmap&);
static void setEnabled(bool);
+ static bool enabled();
String filenameExtension() const;
ImageFrame* frameBufferAtIndex(size_t index);
- void setData(SharedBuffer* data, bool allDataReceived);
+ void setData(SharedBuffer& data, bool allDataReceived);
bool isSizeAvailable();
+ bool hasColorProfile() const;
IntSize size() const;
IntSize frameSizeAtIndex(size_t index) const;
size_t frameCount();
@@ -79,25 +81,24 @@ private:
explicit DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder);
void prepareLazyDecodedFrames();
SkBitmap createBitmap(size_t index);
- SkBitmap createSkiaDiscardableBitmap(size_t index);
- SkBitmap createLazyDecodingBitmap(size_t index);
void activateLazyDecoding();
- void setData(PassRefPtr<SharedBuffer>, bool allDataReceived);
RefPtr<SharedBuffer> m_data;
bool m_allDataReceived;
+ unsigned m_lastDataSize;
+ bool m_dataChanged;
OwnPtr<ImageDecoder> m_actualDecoder;
String m_filenameExtension;
IntSize m_size;
ImageOrientation m_orientation;
int m_repetitionCount;
+ bool m_hasColorProfile;
Vector<OwnPtr<ImageFrame> > m_lazyDecodedFrames;
RefPtr<ImageFrameGenerator> m_frameGenerator;
static bool s_enabled;
- static bool s_skiaDiscardableMemoryEnabled;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
index 4048eb72c23..c4a953efa42 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
@@ -29,6 +29,7 @@
#include "SkBitmapDevice.h"
#include "SkCanvas.h"
#include "SkPicture.h"
+#include "SkPictureRecorder.h"
#include "platform/SharedBuffer.h"
#include "platform/Task.h"
#include "platform/graphics/ImageDecodingStore.h"
@@ -59,12 +60,6 @@ const unsigned char whitePNG[] = {
0x42, 0x60, 0x82,
};
-static SkCanvas* createRasterCanvas(int width, int height)
-{
- SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(SkBitmap::kARGB_8888_Config, width, height));
- return new SkCanvas(device);
-}
-
struct Rasterizer {
SkCanvas* canvas;
SkPicture* picture;
@@ -76,14 +71,15 @@ class DeferredImageDecoderTest : public ::testing::Test, public MockImageDecoder
public:
virtual void SetUp() OVERRIDE
{
- ImageDecodingStore::initializeOnce();
+ ImageDecodingStore::instance()->setCacheLimitInBytes(1024 * 1024);
DeferredImageDecoder::setEnabled(true);
m_data = SharedBuffer::create(whitePNG, sizeof(whitePNG));
OwnPtr<MockImageDecoder> decoder = MockImageDecoder::create(this);
m_actualDecoder = decoder.get();
m_actualDecoder->setSize(1, 1);
m_lazyDecoder = DeferredImageDecoder::createForTesting(decoder.release());
- m_canvas.reset(createRasterCanvas(100, 100));
+ m_canvas.reset(SkCanvas::NewRasterN32(100, 100));
+ ASSERT_TRUE(m_canvas);
m_frameBufferRequestCount = 0;
m_frameCount = 1;
m_repetitionCount = cAnimationNone;
@@ -94,7 +90,7 @@ public:
virtual void TearDown() OVERRIDE
{
- ImageDecodingStore::shutdown();
+ ImageDecodingStore::instance()->clear();
}
virtual void decoderBeingDestroyed() OVERRIDE
@@ -141,7 +137,6 @@ protected:
// Don't own this but saves the pointer to query states.
MockImageDecoder* m_actualDecoder;
OwnPtr<DeferredImageDecoder> m_lazyDecoder;
- SkPicture m_picture;
SkAutoTUnref<SkCanvas> m_canvas;
int m_frameBufferRequestCount;
RefPtr<SharedBuffer> m_data;
@@ -154,82 +149,85 @@ protected:
TEST_F(DeferredImageDecoderTest, drawIntoSkPicture)
{
- m_lazyDecoder->setData(m_data.get(), true);
+ m_lazyDecoder->setData(*m_data, true);
RefPtr<NativeImageSkia> image = m_lazyDecoder->frameBufferAtIndex(0)->asNewNativeImage();
EXPECT_EQ(1, image->bitmap().width());
EXPECT_EQ(1, image->bitmap().height());
EXPECT_FALSE(image->bitmap().isNull());
EXPECT_TRUE(image->bitmap().isImmutable());
- SkCanvas* tempCanvas = m_picture.beginRecording(100, 100);
+ SkPictureRecorder recorder;
+ SkCanvas* tempCanvas = recorder.beginRecording(100, 100, 0, 0);
tempCanvas->drawBitmap(image->bitmap(), 0, 0);
- m_picture.endRecording();
+ RefPtr<SkPicture> picture = adoptRef(recorder.endRecording());
EXPECT_EQ(0, m_frameBufferRequestCount);
- m_canvas->drawPicture(m_picture);
+ m_canvas->drawPicture(picture.get());
EXPECT_EQ(0, m_frameBufferRequestCount);
SkBitmap canvasBitmap;
- canvasBitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
+ ASSERT_TRUE(canvasBitmap.allocN32Pixels(100, 100));
ASSERT_TRUE(m_canvas->readPixels(&canvasBitmap, 0, 0));
SkAutoLockPixels autoLock(canvasBitmap);
EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), canvasBitmap.getColor(0, 0));
}
-TEST_F(DeferredImageDecoderTest, DISABLED_drawScaledIntoSkPicture)
+TEST_F(DeferredImageDecoderTest, drawIntoSkPictureProgressive)
{
- m_lazyDecoder->setData(m_data.get(), true);
- RefPtr<NativeImageSkia> image = m_lazyDecoder->frameBufferAtIndex(0)->asNewNativeImage();
- SkBitmap scaledBitmap = image->resizedBitmap(SkISize::Make(50, 51), SkIRect::MakeWH(50, 51));
- EXPECT_FALSE(scaledBitmap.isNull());
- EXPECT_TRUE(scaledBitmap.isImmutable());
- EXPECT_EQ(50, scaledBitmap.width());
- EXPECT_EQ(51, scaledBitmap.height());
- EXPECT_EQ(0, m_frameBufferRequestCount);
+ RefPtr<SharedBuffer> partialData = SharedBuffer::create(m_data->data(), m_data->size() - 10);
- SkCanvas* tempCanvas = m_picture.beginRecording(100, 100);
- tempCanvas->drawBitmap(scaledBitmap, 0, 0);
- m_picture.endRecording();
- EXPECT_EQ(0, m_frameBufferRequestCount);
+ // Received only half the file.
+ m_lazyDecoder->setData(*partialData, false);
+ RefPtr<NativeImageSkia> image = m_lazyDecoder->frameBufferAtIndex(0)->asNewNativeImage();
+ SkPictureRecorder recorder;
+ SkCanvas* tempCanvas = recorder.beginRecording(100, 100, 0, 0);
+ tempCanvas->drawBitmap(image->bitmap(), 0, 0);
+ RefPtr<SkPicture> picture = adoptRef(recorder.endRecording());
+ m_canvas->drawPicture(picture.get());
- m_canvas->drawPicture(m_picture);
- EXPECT_EQ(0, m_frameBufferRequestCount);
+ // Fully received the file and draw the SkPicture again.
+ m_lazyDecoder->setData(*m_data, true);
+ image = m_lazyDecoder->frameBufferAtIndex(0)->asNewNativeImage();
+ tempCanvas = recorder.beginRecording(100, 100, 0, 0);
+ tempCanvas->drawBitmap(image->bitmap(), 0, 0);
+ picture = adoptRef(recorder.endRecording());
+ m_canvas->drawPicture(picture.get());
SkBitmap canvasBitmap;
- canvasBitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
+ ASSERT_TRUE(canvasBitmap.allocN32Pixels(100, 100));
ASSERT_TRUE(m_canvas->readPixels(&canvasBitmap, 0, 0));
SkAutoLockPixels autoLock(canvasBitmap);
EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), canvasBitmap.getColor(0, 0));
- EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), canvasBitmap.getColor(49, 50));
}
static void rasterizeMain(SkCanvas* canvas, SkPicture* picture)
{
- canvas->drawPicture(*picture);
+ canvas->drawPicture(picture);
}
TEST_F(DeferredImageDecoderTest, decodeOnOtherThread)
{
- m_lazyDecoder->setData(m_data.get(), true);
+ m_lazyDecoder->setData(*m_data, true);
RefPtr<NativeImageSkia> image = m_lazyDecoder->frameBufferAtIndex(0)->asNewNativeImage();
EXPECT_EQ(1, image->bitmap().width());
EXPECT_EQ(1, image->bitmap().height());
EXPECT_FALSE(image->bitmap().isNull());
EXPECT_TRUE(image->bitmap().isImmutable());
- SkCanvas* tempCanvas = m_picture.beginRecording(100, 100);
+ SkPictureRecorder recorder;
+ SkCanvas* tempCanvas = recorder.beginRecording(100, 100, 0, 0);
tempCanvas->drawBitmap(image->bitmap(), 0, 0);
- m_picture.endRecording();
+ RefPtr<SkPicture> picture = adoptRef(recorder.endRecording());
EXPECT_EQ(0, m_frameBufferRequestCount);
// Create a thread to rasterize SkPicture.
OwnPtr<blink::WebThread> thread = adoptPtr(blink::Platform::current()->createThread("RasterThread"));
- thread->postTask(new Task(WTF::bind(&rasterizeMain, m_canvas.get(), &m_picture)));
+ thread->postTask(new Task(WTF::bind(&rasterizeMain, m_canvas.get(), picture.get())));
thread.clear();
EXPECT_EQ(0, m_frameBufferRequestCount);
SkBitmap canvasBitmap;
- canvasBitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
+ ASSERT_TRUE(canvasBitmap.allocN32Pixels(100, 100));
ASSERT_TRUE(m_canvas->readPixels(&canvasBitmap, 0, 0));
SkAutoLockPixels autoLock(canvasBitmap);
EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), canvasBitmap.getColor(0, 0));
@@ -238,19 +236,25 @@ TEST_F(DeferredImageDecoderTest, decodeOnOtherThread)
TEST_F(DeferredImageDecoderTest, singleFrameImageLoading)
{
m_status = ImageFrame::FramePartial;
- m_lazyDecoder->setData(m_data.get(), false);
+ m_lazyDecoder->setData(*m_data, false);
EXPECT_FALSE(m_lazyDecoder->frameIsCompleteAtIndex(0));
ImageFrame* frame = m_lazyDecoder->frameBufferAtIndex(0);
+ unsigned firstId = frame->getSkBitmap().getGenerationID();
EXPECT_EQ(ImageFrame::FramePartial, frame->status());
EXPECT_TRUE(m_actualDecoder);
m_status = ImageFrame::FrameComplete;
- m_lazyDecoder->setData(m_data.get(), true);
+ m_data->append(" ", 1);
+ m_lazyDecoder->setData(*m_data, true);
EXPECT_FALSE(m_actualDecoder);
EXPECT_TRUE(m_lazyDecoder->frameIsCompleteAtIndex(0));
frame = m_lazyDecoder->frameBufferAtIndex(0);
+ unsigned secondId = frame->getSkBitmap().getGenerationID();
EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
EXPECT_FALSE(m_frameBufferRequestCount);
+ EXPECT_NE(firstId, secondId);
+
+ EXPECT_EQ(secondId, m_lazyDecoder->frameBufferAtIndex(0)->getSkBitmap().getGenerationID());
}
TEST_F(DeferredImageDecoderTest, multiFrameImageLoading)
@@ -259,8 +263,9 @@ TEST_F(DeferredImageDecoderTest, multiFrameImageLoading)
m_frameCount = 1;
m_frameDuration = 10;
m_status = ImageFrame::FramePartial;
- m_lazyDecoder->setData(m_data.get(), false);
+ m_lazyDecoder->setData(*m_data, false);
EXPECT_EQ(ImageFrame::FramePartial, m_lazyDecoder->frameBufferAtIndex(0)->status());
+ unsigned firstId = m_lazyDecoder->frameBufferAtIndex(0)->getSkBitmap().getGenerationID();
EXPECT_FALSE(m_lazyDecoder->frameIsCompleteAtIndex(0));
EXPECT_EQ(10.0f, m_lazyDecoder->frameBufferAtIndex(0)->duration());
EXPECT_EQ(10.0f, m_lazyDecoder->frameDurationAtIndex(0));
@@ -268,9 +273,12 @@ TEST_F(DeferredImageDecoderTest, multiFrameImageLoading)
m_frameCount = 2;
m_frameDuration = 20;
m_status = ImageFrame::FrameComplete;
- m_lazyDecoder->setData(m_data.get(), false);
+ m_data->append(" ", 1);
+ m_lazyDecoder->setData(*m_data, false);
EXPECT_EQ(ImageFrame::FrameComplete, m_lazyDecoder->frameBufferAtIndex(0)->status());
EXPECT_EQ(ImageFrame::FrameComplete, m_lazyDecoder->frameBufferAtIndex(1)->status());
+ unsigned secondId = m_lazyDecoder->frameBufferAtIndex(0)->getSkBitmap().getGenerationID();
+ EXPECT_NE(firstId, secondId);
EXPECT_TRUE(m_lazyDecoder->frameIsCompleteAtIndex(0));
EXPECT_TRUE(m_lazyDecoder->frameIsCompleteAtIndex(1));
EXPECT_EQ(20.0f, m_lazyDecoder->frameDurationAtIndex(1));
@@ -281,11 +289,12 @@ TEST_F(DeferredImageDecoderTest, multiFrameImageLoading)
m_frameCount = 3;
m_frameDuration = 30;
m_status = ImageFrame::FrameComplete;
- m_lazyDecoder->setData(m_data.get(), true);
+ m_lazyDecoder->setData(*m_data, true);
EXPECT_FALSE(m_actualDecoder);
EXPECT_EQ(ImageFrame::FrameComplete, m_lazyDecoder->frameBufferAtIndex(0)->status());
EXPECT_EQ(ImageFrame::FrameComplete, m_lazyDecoder->frameBufferAtIndex(1)->status());
EXPECT_EQ(ImageFrame::FrameComplete, m_lazyDecoder->frameBufferAtIndex(2)->status());
+ EXPECT_EQ(secondId, m_lazyDecoder->frameBufferAtIndex(0)->getSkBitmap().getGenerationID());
EXPECT_TRUE(m_lazyDecoder->frameIsCompleteAtIndex(0));
EXPECT_TRUE(m_lazyDecoder->frameIsCompleteAtIndex(1));
EXPECT_TRUE(m_lazyDecoder->frameIsCompleteAtIndex(2));
@@ -301,7 +310,7 @@ TEST_F(DeferredImageDecoderTest, multiFrameImageLoading)
TEST_F(DeferredImageDecoderTest, decodedSize)
{
m_decodedSize = IntSize(22, 33);
- m_lazyDecoder->setData(m_data.get(), true);
+ m_lazyDecoder->setData(*m_data, true);
RefPtr<NativeImageSkia> image = m_lazyDecoder->frameBufferAtIndex(0)->asNewNativeImage();
EXPECT_EQ(m_decodedSize.width(), image->bitmap().width());
EXPECT_EQ(m_decodedSize.height(), image->bitmap().height());
@@ -311,12 +320,26 @@ TEST_F(DeferredImageDecoderTest, decodedSize)
useMockImageDecoderFactory();
// The following code should not fail any assert.
- SkCanvas* tempCanvas = m_picture.beginRecording(100, 100);
+ SkPictureRecorder recorder;
+ SkCanvas* tempCanvas = recorder.beginRecording(100, 100, 0, 0);
tempCanvas->drawBitmap(image->bitmap(), 0, 0);
- m_picture.endRecording();
+ RefPtr<SkPicture> picture = adoptRef(recorder.endRecording());
EXPECT_EQ(0, m_frameBufferRequestCount);
- m_canvas->drawPicture(m_picture);
+ m_canvas->drawPicture(picture.get());
EXPECT_EQ(1, m_frameBufferRequestCount);
}
+TEST_F(DeferredImageDecoderTest, smallerFrameCount)
+{
+ m_frameCount = 1;
+ m_lazyDecoder->setData(*m_data, false);
+ EXPECT_EQ(m_frameCount, m_lazyDecoder->frameCount());
+ m_frameCount = 2;
+ m_lazyDecoder->setData(*m_data, false);
+ EXPECT_EQ(m_frameCount, m_lazyDecoder->frameCount());
+ m_frameCount = 0;
+ m_lazyDecoder->setData(*m_data, true);
+ EXPECT_EQ(m_frameCount, m_lazyDecoder->frameCount());
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.cpp b/chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.cpp
index 1671e701278..2029a32897a 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.cpp
@@ -27,7 +27,7 @@
#include "platform/graphics/DiscardablePixelRef.h"
#include "public/platform/Platform.h"
-#include "wtf/StdLibExtras.h"
+#include <string.h>
namespace WebCore {
@@ -44,16 +44,16 @@ bool DiscardablePixelRefAllocator::allocPixelRef(SkBitmap* dst, SkColorTable* ct
// It should not be possible to have a non-null color table in Blink.
ASSERT(!ctable);
- Sk64 size = dst->getSize64();
- if (size.isNeg() || !size.is32())
+ int64_t size = dst->computeSize64();
+ if (size < 0 || !sk_64_isS32(size))
return false;
- SkImageInfo info;
- if (!dst->asImageInfo(&info))
+ const SkImageInfo& info = dst->info();
+ if (kUnknown_SkColorType == info.colorType())
return false;
- SkAutoTUnref<DiscardablePixelRef> pixelRef(new DiscardablePixelRef(info, adoptPtr(new SkMutex())));
- if (pixelRef->allocAndLockDiscardableMemory(size.get32())) {
+ SkAutoTUnref<DiscardablePixelRef> pixelRef(new DiscardablePixelRef(info, dst->rowBytes(), adoptPtr(new SkMutex())));
+ if (pixelRef->allocAndLockDiscardableMemory(sk_64_asS32(size))) {
pixelRef->setURI(labelDiscardable);
dst->setPixelRef(pixelRef.get());
// This method is only called when a DiscardablePixelRef is created to back a SkBitmap.
@@ -68,10 +68,11 @@ bool DiscardablePixelRefAllocator::allocPixelRef(SkBitmap* dst, SkColorTable* ct
return dst->allocPixels();
}
-DiscardablePixelRef::DiscardablePixelRef(const SkImageInfo& info, PassOwnPtr<SkMutex> mutex)
+DiscardablePixelRef::DiscardablePixelRef(const SkImageInfo& info, size_t rowBytes, PassOwnPtr<SkMutex> mutex)
: SkPixelRef(info, mutex.get())
, m_lockedMemory(0)
, m_mutex(mutex)
+ , m_rowBytes(rowBytes)
{
}
@@ -89,13 +90,18 @@ bool DiscardablePixelRef::allocAndLockDiscardableMemory(size_t bytes)
return false;
}
-void* DiscardablePixelRef::onLockPixels(SkColorTable** ctable)
+bool DiscardablePixelRef::onNewLockPixels(LockRec* rec)
{
if (!m_lockedMemory && m_discardable->lock())
m_lockedMemory = m_discardable->data();
- *ctable = 0;
- return m_lockedMemory;
+ if (m_lockedMemory) {
+ rec->fPixels = m_lockedMemory;
+ rec->fColorTable = 0;
+ rec->fRowBytes = m_rowBytes;
+ return true;
+ }
+ return false;
}
void DiscardablePixelRef::onUnlockPixels()
@@ -107,10 +113,7 @@ void DiscardablePixelRef::onUnlockPixels()
bool DiscardablePixelRef::isDiscardable(SkPixelRef* pixelRef)
{
- // FIXME: DEFINE_STATIC_LOCAL is not thread safe.
- // ImageDecodingStore provides the synchronization for this.
- DEFINE_STATIC_LOCAL(const SkString, discardable, (labelDiscardable));
- return pixelRef && pixelRef->getURI() && discardable.equals(pixelRef->getURI());
+ return pixelRef && pixelRef->getURI() && !strcmp(pixelRef->getURI(), labelDiscardable);
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.h b/chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.h
index 5e535576d13..bfed77f1c90 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DiscardablePixelRef.h
@@ -41,14 +41,14 @@ class PLATFORM_EXPORT DiscardablePixelRefAllocator : public SkBitmap::Allocator
// SkBitmap::Allocator implementation. The discardable memory allocated
// after this call is locked and will not be purged until next
// onUnlockPixels().
- virtual bool allocPixelRef(SkBitmap*, SkColorTable*);
+ virtual bool allocPixelRef(SkBitmap*, SkColorTable*) OVERRIDE;
};
// PixelRef object whose memory can be discarded when pixels are unlocked.
class PLATFORM_EXPORT DiscardablePixelRef : public SkPixelRef {
public:
- DiscardablePixelRef(const SkImageInfo&, PassOwnPtr<SkMutex>);
- ~DiscardablePixelRef();
+ DiscardablePixelRef(const SkImageInfo&, size_t rowBytes, PassOwnPtr<SkMutex>);
+ virtual ~DiscardablePixelRef();
static bool isDiscardable(SkPixelRef*);
bool allocAndLockDiscardableMemory(size_t);
@@ -57,13 +57,14 @@ public:
protected:
// SkPixelRef implementation.
- virtual void* onLockPixels(SkColorTable**);
- virtual void onUnlockPixels();
+ virtual bool onNewLockPixels(LockRec*) OVERRIDE;
+ virtual void onUnlockPixels() OVERRIDE;
private:
void* m_lockedMemory;
OwnPtr<blink::WebDiscardableMemory> m_discardable;
OwnPtr<SkMutex> m_mutex;
+ size_t m_rowBytes;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DisplayList.cpp b/chromium/third_party/WebKit/Source/platform/graphics/DisplayList.cpp
index c16d3517cdc..f8fa9ff4eda 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DisplayList.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DisplayList.cpp
@@ -31,13 +31,15 @@
#include "config.h"
#include "platform/graphics/DisplayList.h"
+#include "platform/geometry/IntSize.h"
#include "third_party/skia/include/core/SkPicture.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "wtf/PassOwnPtr.h"
namespace WebCore {
DisplayList::DisplayList(const FloatRect& bounds)
: m_bounds(bounds)
- , m_picture(adoptRef(new SkPicture()))
{
}
@@ -55,4 +57,20 @@ SkPicture* DisplayList::picture() const
return m_picture.get();
}
+SkCanvas* DisplayList::beginRecording(const IntSize& size, uint32_t recordFlags)
+{
+ m_picture.clear();
+ if (!m_recorder)
+ m_recorder = adoptPtr(new SkPictureRecorder);
+ return m_recorder->beginRecording(size.width(), size.height(), 0, recordFlags);
+}
+
+void DisplayList::endRecording()
+{
+ if (m_recorder) {
+ m_picture = adoptRef(m_recorder->endRecording());
+ m_recorder.clear();
+ }
+}
+
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DisplayList.h b/chromium/third_party/WebKit/Source/platform/graphics/DisplayList.h
index ca745e5b5ff..e1d050b2b12 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DisplayList.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DisplayList.h
@@ -37,10 +37,14 @@
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
+class SkCanvas;
class SkPicture;
+class SkPictureRecorder;
namespace WebCore {
+class IntSize;
+
class PLATFORM_EXPORT DisplayList FINAL : public WTF::RefCounted<DisplayList> {
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(DisplayList);
@@ -49,11 +53,21 @@ public:
~DisplayList();
const FloatRect& bounds() const;
+
+ // This entry point will return 0 when the DisplayList is in the
+ // midst of recording (i.e., between a beginRecording/endRecording pair)
+ // and if no recording has ever been completed. Otherwise it will return
+ // the picture created by the last endRecording call.
SkPicture* picture() const;
+ SkCanvas* beginRecording(const IntSize&, uint32_t recordFlags = 0);
+ bool isRecording() const { return m_recorder; }
+ void endRecording();
+
private:
FloatRect m_bounds;
RefPtr<SkPicture> m_picture;
+ OwnPtr<SkPictureRecorder> m_recorder;
};
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DrawLooper.cpp b/chromium/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp
index 814f5d672c5..fef526e07ca 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DrawLooper.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp
@@ -29,7 +29,7 @@
*/
#include "config.h"
-#include "platform/graphics/DrawLooper.h"
+#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/geometry/FloatSize.h"
#include "platform/graphics/Color.h"
@@ -39,37 +39,45 @@
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkXfermode.h"
#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
-#include "third_party/skia/include/effects/SkLayerDrawLooper.h"
+#include "wtf/RefPtr.h"
namespace WebCore {
-DrawLooper::DrawLooper() : m_skDrawLooper(adoptRef(new SkLayerDrawLooper)) { }
+DrawLooperBuilder::DrawLooperBuilder() { }
-DrawLooper::~DrawLooper() { }
+DrawLooperBuilder::~DrawLooperBuilder() { }
-SkDrawLooper* DrawLooper::skDrawLooper() const
+PassOwnPtr<DrawLooperBuilder> DrawLooperBuilder::create()
{
- return m_skDrawLooper.get();
+ return adoptPtr(new DrawLooperBuilder);
}
-void DrawLooper::addUnmodifiedContent()
+PassRefPtr<SkDrawLooper> DrawLooperBuilder::detachDrawLooper()
+{
+ return adoptRef(m_skDrawLooperBuilder.detachLooper());
+}
+
+void DrawLooperBuilder::addUnmodifiedContent()
{
SkLayerDrawLooper::LayerInfo info;
- m_skDrawLooper->addLayerOnTop(info);
+ m_skDrawLooperBuilder.addLayerOnTop(info);
+}
+
+// This replicates the old skia behavior when it used to take radius for blur. Now it takes sigma.
+static SkScalar RadiusToSigma(SkScalar radius)
+{
+ SkASSERT(radius > 0);
+ return 0.57735f * radius + 0.5f;
}
-void DrawLooper::addShadow(const FloatSize& offset, float blur, const Color& color,
+void DrawLooperBuilder::addShadow(const FloatSize& offset, float blur, const Color& color,
ShadowTransformMode shadowTransformMode, ShadowAlphaMode shadowAlphaMode)
{
// Detect when there's no effective shadow.
- if (!color.isValid() || !color.alpha())
+ if (!color.alpha())
return;
- SkColor skColor;
- if (color.isValid())
- skColor = color.rgb();
- else
- skColor = SkColorSetARGB(0xFF / 3, 0, 0, 0); // "std" apple shadow color.
+ SkColor skColor = color.rgb();
SkLayerDrawLooper::LayerInfo info;
@@ -90,14 +98,14 @@ void DrawLooper::addShadow(const FloatSize& offset, float blur, const Color& col
info.fOffset.set(offset.width(), offset.height());
info.fPostTranslate = (shadowTransformMode == ShadowIgnoresTransforms);
- SkPaint* paint = m_skDrawLooper->addLayerOnTop(info);
+ SkPaint* paint = m_skDrawLooperBuilder.addLayerOnTop(info);
if (blur) {
+ const SkScalar sigma = RadiusToSigma(blur / 2);
uint32_t mfFlags = SkBlurMaskFilter::kHighQuality_BlurFlag;
if (shadowTransformMode == ShadowIgnoresTransforms)
mfFlags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
- RefPtr<SkMaskFilter> mf = adoptRef(SkBlurMaskFilter::Create(
- (double)blur / 2.0, SkBlurMaskFilter::kNormal_BlurStyle, mfFlags));
+ RefPtr<SkMaskFilter> mf = adoptRef(SkBlurMaskFilter::Create(kNormal_SkBlurStyle, sigma, mfFlags));
paint->setMaskFilter(mf.get());
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/DrawLooper.h b/chromium/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.h
index 4a66910c300..79cce8da67f 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/DrawLooper.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.h
@@ -28,25 +28,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef DrawLooper_h
-#define DrawLooper_h
+#ifndef DrawLooperBuilder_h
+#define DrawLooperBuilder_h
#include "platform/PlatformExport.h"
+#include "third_party/skia/include/effects/SkLayerDrawLooper.h"
#include "wtf/Noncopyable.h"
-#include "wtf/RefPtr.h"
+#include "wtf/PassOwnPtr.h"
+#include "wtf/PassRefPtr.h"
class SkDrawLooper;
-class SkLayerDrawLooper;
namespace WebCore {
class Color;
class FloatSize;
-class PLATFORM_EXPORT DrawLooper {
+class PLATFORM_EXPORT DrawLooperBuilder FINAL {
// Implementing the copy constructor properly would require writing code to
- // copy the underlying SkDrawLooper.
- WTF_MAKE_NONCOPYABLE(DrawLooper);
+ // copy the underlying SkLayerDrawLooper::Builder.
+ WTF_MAKE_NONCOPYABLE(DrawLooperBuilder);
public:
enum ShadowTransformMode {
@@ -58,12 +59,14 @@ public:
ShadowIgnoresAlpha
};
- DrawLooper();
- ~DrawLooper();
+ DrawLooperBuilder();
+ ~DrawLooperBuilder();
- // Callees should not modify this looper other than to iterate over it.
- // A downcast to SkLayerDrawLooper* is tantamount to a const_cast.
- SkDrawLooper* skDrawLooper() const;
+ static PassOwnPtr<DrawLooperBuilder> create();
+
+ // Creates the SkDrawLooper and passes ownership to the caller. The builder
+ // should not be used any more after calling this method.
+ PassRefPtr<SkDrawLooper> detachDrawLooper();
void addUnmodifiedContent();
void addShadow(const FloatSize& offset, float blur, const Color&,
@@ -71,9 +74,9 @@ public:
ShadowAlphaMode = ShadowRespectsAlpha);
private:
- RefPtr<SkLayerDrawLooper> m_skDrawLooper;
+ SkLayerDrawLooper::Builder m_skDrawLooperBuilder;
};
} // namespace WebCore
-#endif // DrawLooper_h
+#endif // DrawLooperBuilder_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Extensions3D.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Extensions3D.cpp
deleted file mode 100644
index 6d0a61e6864..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/Extensions3D.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2010 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:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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"
-
-#include "platform/graphics/Extensions3D.h"
-
-#include "platform/graphics/GraphicsContext3D.h"
-#include "public/platform/WebGraphicsContext3D.h"
-#include "wtf/text/CString.h"
-
-namespace WebCore {
-
-Extensions3D::Extensions3D(GraphicsContext3D* context)
- : m_context(context)
-{
-}
-
-Extensions3D::~Extensions3D()
-{
-}
-
-bool Extensions3D::supports(const String& name)
-{
- return m_context->supportsExtension(name);
-}
-
-void Extensions3D::ensureEnabled(const String& name)
-{
- bool result = m_context->ensureExtensionEnabled(name);
- ASSERT_UNUSED(result, result);
-}
-
-bool Extensions3D::isEnabled(const String& name)
-{
- return m_context->isExtensionEnabled(name);
-}
-
-int Extensions3D::getGraphicsResetStatusARB()
-{
- return static_cast<int>(m_context->webContext()->getGraphicsResetStatusARB());
-}
-
-void Extensions3D::blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter)
-{
- m_context->webContext()->blitFramebufferCHROMIUM(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-}
-
-void Extensions3D::renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height)
-{
- m_context->webContext()->renderbufferStorageMultisampleCHROMIUM(target, samples, internalformat, width, height);
-}
-
-void* Extensions3D::mapBufferSubDataCHROMIUM(unsigned target, int offset, int size, unsigned access)
-{
- return m_context->webContext()->mapBufferSubDataCHROMIUM(target, offset, size, access);
-}
-
-void Extensions3D::unmapBufferSubDataCHROMIUM(const void* data)
-{
- m_context->webContext()->unmapBufferSubDataCHROMIUM(data);
-}
-
-void* Extensions3D::mapTexSubImage2DCHROMIUM(unsigned target, int level, int xoffset, int yoffset, int width, int height, unsigned format, unsigned type, unsigned access)
-{
- return m_context->webContext()->mapTexSubImage2DCHROMIUM(target, level, xoffset, yoffset, width, height, format, type, access);
-}
-
-void Extensions3D::unmapTexSubImage2DCHROMIUM(const void* data)
-{
- m_context->webContext()->unmapTexSubImage2DCHROMIUM(data);
-}
-
-Platform3DObject Extensions3D::createVertexArrayOES()
-{
- return m_context->webContext()->createVertexArrayOES();
-}
-
-void Extensions3D::deleteVertexArrayOES(Platform3DObject array)
-{
- m_context->webContext()->deleteVertexArrayOES(array);
-}
-
-GC3Dboolean Extensions3D::isVertexArrayOES(Platform3DObject array)
-{
- return m_context->webContext()->isVertexArrayOES(array);
-}
-
-void Extensions3D::bindVertexArrayOES(Platform3DObject array)
-{
- m_context->webContext()->bindVertexArrayOES(array);
-}
-
-String Extensions3D::getTranslatedShaderSourceANGLE(Platform3DObject shader)
-{
- return m_context->webContext()->getTranslatedShaderSourceANGLE(shader);
-}
-
-void Extensions3D::rateLimitOffscreenContextCHROMIUM()
-{
- m_context->webContext()->rateLimitOffscreenContextCHROMIUM();
-}
-
-void Extensions3D::paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer* imageBuffer)
-{
- m_context->paintFramebufferToCanvas(framebuffer, width, height, premultiplyAlpha, imageBuffer);
-}
-
-void Extensions3D::texImageIOSurface2DCHROMIUM(unsigned target, int width, int height, uint32_t ioSurfaceId, unsigned plane)
-{
- m_context->webContext()->texImageIOSurface2DCHROMIUM(target, width, height, ioSurfaceId, plane);
-}
-
-void Extensions3D::texStorage2DEXT(unsigned int target, int levels, unsigned int internalFormat, int width, int height)
-{
- m_context->webContext()->texStorage2DEXT(target, levels, internalFormat, width, height);
-}
-
-Platform3DObject Extensions3D::createQueryEXT()
-{
- return m_context->webContext()->createQueryEXT();
-}
-
-void Extensions3D::deleteQueryEXT(Platform3DObject query)
-{
- m_context->webContext()->deleteQueryEXT(query);
-}
-
-GC3Dboolean Extensions3D::isQueryEXT(Platform3DObject query)
-{
- return m_context->webContext()->isQueryEXT(query);
-}
-
-void Extensions3D::beginQueryEXT(GC3Denum target, Platform3DObject query)
-{
- m_context->webContext()->beginQueryEXT(target, query);
-}
-
-void Extensions3D::endQueryEXT(GC3Denum target)
-{
- m_context->webContext()->endQueryEXT(target);
-}
-
-void Extensions3D::getQueryivEXT(GC3Denum target, GC3Denum pname, GC3Dint* params)
-{
- m_context->webContext()->getQueryivEXT(target, pname, params);
-}
-
-void Extensions3D::getQueryObjectuivEXT(Platform3DObject query, GC3Denum pname, GC3Duint* params)
-{
- m_context->webContext()->getQueryObjectuivEXT(query, pname, params);
-}
-
-bool Extensions3D::canUseCopyTextureCHROMIUM(GC3Denum destFormat, GC3Denum destType, GC3Dint level)
-{
- // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE/(Level 0) should be lifted when
- // WebGraphicsContext3D::copyTextureCHROMIUM(...) are fully functional.
- if ((destFormat == GL_RGB || destFormat == GL_RGBA)
- && destType == GL_UNSIGNED_BYTE
- && !level)
- return true;
- return false;
-}
-
-void Extensions3D::copyTextureCHROMIUM(GC3Denum target, Platform3DObject sourceId, Platform3DObject destId, GC3Dint level, GC3Denum internalFormat, GC3Denum destType)
-{
- m_context->webContext()->copyTextureCHROMIUM(target, sourceId, destId, level, internalFormat, destType);
-}
-
-void Extensions3D::shallowFlushCHROMIUM()
-{
- return m_context->webContext()->shallowFlushCHROMIUM();
-}
-
-void Extensions3D::insertEventMarkerEXT(const String& marker)
-{
- m_context->webContext()->insertEventMarkerEXT(marker.utf8().data());
-}
-
-void Extensions3D::pushGroupMarkerEXT(const String& marker)
-{
- m_context->webContext()->pushGroupMarkerEXT(marker.utf8().data());
-}
-
-void Extensions3D::popGroupMarkerEXT(void)
-{
- m_context->webContext()->popGroupMarkerEXT();
-}
-
-void Extensions3D::drawBuffersEXT(GC3Dsizei n, const GC3Denum* bufs)
-{
- m_context->webContext()->drawBuffersEXT(n, bufs);
-}
-
-void Extensions3D::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount)
-{
- m_context->webContext()->drawArraysInstancedANGLE(mode, first, count, primcount);
-}
-
-void Extensions3D::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount)
-{
- m_context->webContext()->drawElementsInstancedANGLE(mode, count, type, offset, primcount);
-}
-
-void Extensions3D::vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor)
-{
- m_context->webContext()->vertexAttribDivisorANGLE(index, divisor);
-}
-
-void Extensions3D::loseContextCHROMIUM(GC3Denum current, GC3Denum other)
-{
- m_context->webContext()->loseContextCHROMIUM(current, other);
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Extensions3D.h b/chromium/third_party/WebKit/Source/platform/graphics/Extensions3D.h
deleted file mode 100644
index 4fd8bae351c..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/Extensions3D.h
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * 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:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 Extensions3D_h
-#define Extensions3D_h
-
-#include "platform/PlatformExport.h"
-#include "platform/graphics/GraphicsTypes3D.h"
-
-#include "wtf/text/WTFString.h"
-
-namespace WebCore {
-
-class GraphicsContext3D;
-class ImageBuffer;
-
-// The supported extensions are defined below.
-//
-// Calling any extension function not supported by the current context
-// must be a no-op; in particular, it may not have side effects. In
-// this situation, if the function has a return value, 0 is returned.
-class PLATFORM_EXPORT Extensions3D {
-public:
- ~Extensions3D();
-
- // Supported extensions:
- // GL_EXT_texture_format_BGRA8888
- // GL_EXT_read_format_bgra
- // GL_ARB_robustness
- // GL_ARB_texture_non_power_of_two / GL_OES_texture_npot
- // GL_EXT_packed_depth_stencil / GL_OES_packed_depth_stencil
- // GL_ANGLE_framebuffer_blit / GL_ANGLE_framebuffer_multisample
- // GL_OES_texture_float
- // GL_OES_texture_float_linear
- // GL_OES_texture_half_float
- // GL_OES_texture_half_float_linear
- // GL_OES_standard_derivatives
- // GL_OES_rgb8_rgba8
- // GL_OES_vertex_array_object
- // GL_OES_element_index_uint
- // GL_ANGLE_translated_shader_source
- // GL_ARB_texture_rectangle (only the subset required to
- // implement IOSurface binding; it's recommended to support
- // this only on Mac OS X to limit the amount of code dependent
- // on this extension)
- // GL_EXT_texture_compression_dxt1
- // GL_EXT_texture_compression_s3tc
- // GL_OES_compressed_ETC1_RGB8_texture
- // GL_IMG_texture_compression_pvrtc
- // EXT_texture_filter_anisotropic
- // GL_EXT_debug_marker
- // GL_CHROMIUM_copy_texture
- // GL_CHROMIUM_flipy
- // GL_ARB_draw_buffers / GL_EXT_draw_buffers
- // GL_ANGLE_instanced_arrays
-
- // GL_CHROMIUM_shallow_flush : only supported if an ipc command buffer is used.
- // GL_CHROMIUM_resource_safe : indicating that textures/renderbuffers are always initialized before read/write.
- // GL_CHROMIUM_strict_attribs : indicating a GL error is generated for out-of-bounds buffer accesses.
- // GL_CHROMIUM_post_sub_buffer
- // GL_CHROMIUM_map_sub
- // GL_CHROMIUM_swapbuffers_complete_callback
- // GL_CHROMIUM_rate_limit_offscreen_context
- // GL_CHROMIUM_paint_framebuffer_canvas
- // GL_CHROMIUM_iosurface (Mac OS X specific)
- // GL_CHROMIUM_command_buffer_query
- // GL_ANGLE_texture_usage
- // GL_EXT_debug_marker
- // GL_EXT_texture_storage
- // GL_EXT_occlusion_query_boolean
-
- // Takes full name of extension; for example,
- // "GL_EXT_texture_format_BGRA8888".
- bool supports(const String&);
-
- // Certain OpenGL and WebGL implementations may support enabling
- // extensions lazily. This method may only be called with
- // extension names for which supports returns true.
- void ensureEnabled(const String&);
-
- // Takes full name of extension: for example, "GL_EXT_texture_format_BGRA8888".
- // Checks to see whether the given extension is actually enabled (see ensureEnabled).
- // Has no other side-effects.
- bool isEnabled(const String&);
-
- enum ExtensionsEnumType {
- // GL_EXT_texture_format_BGRA8888 enums
- BGRA_EXT = 0x80E1,
-
- // GL_ARB_robustness/GL_CHROMIUM_lose_context enums
- GUILTY_CONTEXT_RESET_ARB = 0x8253,
- INNOCENT_CONTEXT_RESET_ARB = 0x8254,
- UNKNOWN_CONTEXT_RESET_ARB = 0x8255,
-
- // GL_EXT/OES_packed_depth_stencil enums
- DEPTH24_STENCIL8 = 0x88F0,
-
- // GL_ANGLE_framebuffer_blit names
- READ_FRAMEBUFFER = 0x8CA8,
- DRAW_FRAMEBUFFER = 0x8CA9,
- DRAW_FRAMEBUFFER_BINDING = 0x8CA6,
- READ_FRAMEBUFFER_BINDING = 0x8CAA,
-
- // GL_ANGLE_framebuffer_multisample names
- RENDERBUFFER_SAMPLES = 0x8CAB,
- FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = 0x8D56,
- MAX_SAMPLES = 0x8D57,
-
- // GL_OES_standard_derivatives names
- FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B,
-
- // GL_OES_rgb8_rgba8 names
- RGB8_OES = 0x8051,
- RGBA8_OES = 0x8058,
-
- // GL_OES_vertex_array_object names
- VERTEX_ARRAY_BINDING_OES = 0x85B5,
-
- // GL_ANGLE_translated_shader_source
- TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE = 0x93A0,
-
- // GL_ARB_texture_rectangle
- TEXTURE_RECTANGLE_ARB = 0x84F5,
- TEXTURE_BINDING_RECTANGLE_ARB = 0x84F6,
-
- // GL_EXT_texture_compression_dxt1
- // GL_EXT_texture_compression_s3tc
- COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0,
- COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1,
- COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2,
- COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3,
-
- // GL_OES_compressed_ETC1_RGB8_texture
- ETC1_RGB8_OES = 0x8D64,
-
- // GL_IMG_texture_compression_pvrtc
- COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00,
- COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01,
- COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02,
- COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03,
-
- // GL_AMD_compressed_ATC_texture
- COMPRESSED_ATC_RGB_AMD = 0x8C92,
- COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD = 0x8C93,
- COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD = 0x87EE,
-
- // GL_EXT_texture_filter_anisotropic
- TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE,
- MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF,
-
- // GL_CHROMIUM_flipy
- UNPACK_FLIP_Y_CHROMIUM = 0x9240,
-
- // GL_CHROMIUM_copy_texture
- UNPACK_PREMULTIPLY_ALPHA_CHROMIUM = 0x9241,
- UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM = 0x9242,
-
- // GL_ARB_draw_buffers / GL_EXT_draw_buffers
- MAX_DRAW_BUFFERS_EXT = 0x8824,
- DRAW_BUFFER0_EXT = 0x8825,
- DRAW_BUFFER1_EXT = 0x8826,
- DRAW_BUFFER2_EXT = 0x8827,
- DRAW_BUFFER3_EXT = 0x8828,
- DRAW_BUFFER4_EXT = 0x8829,
- DRAW_BUFFER5_EXT = 0x882A,
- DRAW_BUFFER6_EXT = 0x882B,
- DRAW_BUFFER7_EXT = 0x882C,
- DRAW_BUFFER8_EXT = 0x882D,
- DRAW_BUFFER9_EXT = 0x882E,
- DRAW_BUFFER10_EXT = 0x882F,
- DRAW_BUFFER11_EXT = 0x8830,
- DRAW_BUFFER12_EXT = 0x8831,
- DRAW_BUFFER13_EXT = 0x8832,
- DRAW_BUFFER14_EXT = 0x8833,
- DRAW_BUFFER15_EXT = 0x8834,
- MAX_COLOR_ATTACHMENTS_EXT = 0x8CDF,
- COLOR_ATTACHMENT0_EXT = 0x8CE0,
- COLOR_ATTACHMENT1_EXT = 0x8CE1,
- COLOR_ATTACHMENT2_EXT = 0x8CE2,
- COLOR_ATTACHMENT3_EXT = 0x8CE3,
- COLOR_ATTACHMENT4_EXT = 0x8CE4,
- COLOR_ATTACHMENT5_EXT = 0x8CE5,
- COLOR_ATTACHMENT6_EXT = 0x8CE6,
- COLOR_ATTACHMENT7_EXT = 0x8CE7,
- COLOR_ATTACHMENT8_EXT = 0x8CE8,
- COLOR_ATTACHMENT9_EXT = 0x8CE9,
- COLOR_ATTACHMENT10_EXT = 0x8CEA,
- COLOR_ATTACHMENT11_EXT = 0x8CEB,
- COLOR_ATTACHMENT12_EXT = 0x8CEC,
- COLOR_ATTACHMENT13_EXT = 0x8CED,
- COLOR_ATTACHMENT14_EXT = 0x8CEE,
- COLOR_ATTACHMENT15_EXT = 0x8CEF,
-
- // GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object)
- READ_ONLY = 0x88B8,
- WRITE_ONLY = 0x88B9,
-
- // GL_EXT_texture_storage
- BGRA8_EXT = 0x93A1,
-
- // GL_EXT_occlusion_query_boolean
- ANY_SAMPLES_PASSED_EXT = 0x8C2F,
- ANY_SAMPLES_PASSED_CONSERVATIVE_EXT = 0x8D6A,
- CURRENT_QUERY_EXT = 0x8865,
- QUERY_RESULT_EXT = 0x8866,
- QUERY_RESULT_AVAILABLE_EXT = 0x8867,
-
- // GL_CHROMIUM_command_buffer_query
- COMMANDS_ISSUED_CHROMIUM = 0x84F2,
-
- // GL_ANGLE_instanced_arrays
- VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE
- };
-
- // GL_ARB_robustness
- // Note: This method's behavior differs from the GL_ARB_robustness
- // specification in the following way:
- // The implementation must not reset the error state during this call.
- // If getGraphicsResetStatusARB returns an error, it should continue
- // returning the same error. Restoring the GraphicsContext3D is handled
- // externally.
- int getGraphicsResetStatusARB();
-
- // GL_ANGLE_framebuffer_blit
- void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter);
-
- // GL_ANGLE_framebuffer_multisample
- void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height);
-
- // GL_OES_vertex_array_object
- Platform3DObject createVertexArrayOES();
- void deleteVertexArrayOES(Platform3DObject);
- GC3Dboolean isVertexArrayOES(Platform3DObject);
- void bindVertexArrayOES(Platform3DObject);
-
- // GL_ANGLE_translated_shader_source
- String getTranslatedShaderSourceANGLE(Platform3DObject);
-
- // GL_CHROMIUM_copy_texture
- // canUseCopyTextureCHROMIUM(...) is used to check if copyTextureCHROMIUM(...) can work for the specified
- // format, type and level for the destination texture.
- bool canUseCopyTextureCHROMIUM(GC3Denum destFormat, GC3Denum destType, GC3Dint level);
- void copyTextureCHROMIUM(GC3Denum, Platform3DObject, Platform3DObject, GC3Dint, GC3Denum, GC3Denum);
-
- // GL_EXT_debug_marker
- void insertEventMarkerEXT(const String&);
- void pushGroupMarkerEXT(const String&);
- void popGroupMarkerEXT(void);
-
- // GL_ARB_draw_buffers / GL_EXT_draw_buffers
- void drawBuffersEXT(GC3Dsizei n, const GC3Denum* bufs);
-
- // GL_CHROMIUM_map_sub
- void* mapBufferSubDataCHROMIUM(unsigned target, int offset, int size, unsigned access);
- void unmapBufferSubDataCHROMIUM(const void*);
- void* mapTexSubImage2DCHROMIUM(unsigned target, int level, int xoffset, int yoffset, int width, int height, unsigned format, unsigned type, unsigned access);
- void unmapTexSubImage2DCHROMIUM(const void*);
-
- // GL_CHROMIUM_rate_limit_offscreen_context
- void rateLimitOffscreenContextCHROMIUM();
-
- // GL_CHROMIUM_paint_framebuffer_canvas
- void paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer*);
-
- // GL_CHROMIUM_iosurface
- // To avoid needing to expose extraneous enums, assumes internal format
- // RGBA, format BGRA, and type UNSIGNED_INT_8_8_8_8_REV.
- void texImageIOSurface2DCHROMIUM(unsigned target, int width, int height, uint32_t ioSurfaceId, unsigned plane);
-
- // GL_EXT_texture_storage
- void texStorage2DEXT(unsigned target, int levels, unsigned internalformat, int width, int height);
-
- // GL_EXT_occlusion_query
- Platform3DObject createQueryEXT();
- void deleteQueryEXT(Platform3DObject);
- GC3Dboolean isQueryEXT(Platform3DObject);
- void beginQueryEXT(GC3Denum, Platform3DObject);
- void endQueryEXT(GC3Denum);
- void getQueryivEXT(GC3Denum, GC3Denum, GC3Dint*);
- void getQueryObjectuivEXT(Platform3DObject, GC3Denum, GC3Duint*);
-
- // GL_CHROMIUM_shallow_flush
- void shallowFlushCHROMIUM();
-
- // GL_ANGLE_instanced_arrays
- void drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
- void drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount);
- void vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor);
-
- // GL_CHROMIUM_lose_context
- void loseContextCHROMIUM(GC3Denum, GC3Denum);
-
-private:
- // Instances of this class are strictly owned by the GraphicsContext3D implementation and do not
- // need to be instantiated by any other code.
- friend class GraphicsContext3D;
- explicit Extensions3D(GraphicsContext3D*);
-
- // Weak pointer back to GraphicsContext3D.
- GraphicsContext3D* m_context;
-};
-
-} // namespace WebCore
-
-#endif // Extensions3D_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/FrameData.cpp b/chromium/third_party/WebKit/Source/platform/graphics/FrameData.cpp
index cdbae1ff0cf..3e1c9d26449 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/FrameData.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/FrameData.cpp
@@ -32,7 +32,7 @@
namespace WebCore {
FrameData::FrameData()
- : m_frame(0)
+ : m_frame(nullptr)
, m_orientation(DefaultImageOrientation)
, m_duration(0)
, m_haveMetadata(false)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/FrameData.h b/chromium/third_party/WebKit/Source/platform/graphics/FrameData.h
index f27857f468c..740eec3ea72 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/FrameData.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/FrameData.h
@@ -34,16 +34,6 @@
#include "wtf/VectorTraits.h"
namespace WebCore {
-struct FrameData;
-}
-
-namespace WTF {
-template<> struct VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits {
- static const bool canInitializeWithMemset = false; // Not all FrameData members initialize to 0.
-};
-}
-
-namespace WebCore {
class NativeImageSkia;
@@ -68,4 +58,10 @@ public:
} // namespace WebCore
+namespace WTF {
+template<> struct VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits<WebCore::FrameData> {
+ static const bool canInitializeWithMemset = false; // Not all FrameData members initialize to 0.
+};
+}
+
#endif // FrameData_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp
index f81ad11061a..91c4f47f4cb 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp
@@ -29,38 +29,41 @@
#include "platform/graphics/Gradient.h"
#include "platform/geometry/FloatRect.h"
-#include "platform/graphics/Color.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/skia/SkiaUtils.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorShader.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
+typedef Vector<SkScalar, 8> ColorStopOffsetVector;
+typedef Vector<SkColor, 8> ColorStopColorVector;
+
namespace WebCore {
Gradient::Gradient(const FloatPoint& p0, const FloatPoint& p1)
- : m_radial(false)
- , m_p0(p0)
+ : m_p0(p0)
, m_p1(p1)
, m_r0(0)
, m_r1(0)
, m_aspectRatio(1)
+ , m_radial(false)
, m_stopsSorted(false)
- , m_spreadMethod(SpreadMethodPad)
, m_drawInPMColorSpace(false)
+ , m_spreadMethod(SpreadMethodPad)
{
}
Gradient::Gradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1, float aspectRatio)
- : m_radial(true)
- , m_p0(p0)
+ : m_p0(p0)
, m_p1(p1)
, m_r0(r0)
, m_r1(r1)
, m_aspectRatio(aspectRatio)
+ , m_radial(true)
, m_stopsSorted(false)
- , m_spreadMethod(SpreadMethodPad)
, m_drawInPMColorSpace(false)
+ , m_spreadMethod(SpreadMethodPad)
{
}
@@ -68,32 +71,23 @@ Gradient::~Gradient()
{
}
-void Gradient::addColorStop(float value, const Color& color)
+static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b)
{
- float r;
- float g;
- float b;
- float a;
- color.getRGBA(r, g, b, a);
- m_stops.append(ColorStop(value, r, g, b, a));
-
- m_stopsSorted = false;
- m_gradient.clear();
+ return a.stop < b.stop;
}
void Gradient::addColorStop(const Gradient::ColorStop& stop)
{
- m_stops.append(stop);
+ if (m_stops.isEmpty()) {
+ m_stopsSorted = true;
+ } else {
+ m_stopsSorted = m_stopsSorted && compareStops(m_stops.last(), stop);
+ }
- m_stopsSorted = false;
+ m_stops.append(stop);
m_gradient.clear();
}
-static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b)
-{
- return a.stop < b.stop;
-}
-
void Gradient::sortStopsIfNecessary()
{
if (m_stopsSorted)
@@ -110,7 +104,7 @@ void Gradient::sortStopsIfNecessary()
bool Gradient::hasAlpha() const
{
for (size_t i = 0; i < m_stops.size(); i++) {
- if (m_stops[i].alpha < 1)
+ if (m_stops[i].color.hasAlpha())
return true;
}
@@ -143,18 +137,7 @@ void Gradient::setGradientSpaceTransform(const AffineTransform& gradientSpaceTra
return;
m_gradientSpaceTransformation = gradientSpaceTransformation;
- if (m_gradient)
- m_gradient->setLocalMatrix(affineTransformToSkMatrix(m_gradientSpaceTransformation));
-}
-
-static inline U8CPU F2B(float x)
-{
- return static_cast<int>(x * 255);
-}
-
-static SkColor makeSkColor(float a, float r, float g, float b)
-{
- return SkColorSetARGB(F2B(a), F2B(r), F2B(g), F2B(b));
+ m_gradient.clear();
}
// Determine the total number of stops needed, including pseudo-stops at the
@@ -173,19 +156,25 @@ static size_t totalStopsNeeded(const Gradient::ColorStop* stopData, size_t count
return countUsed;
}
+// FIXME: This would be more at home as Color::operator SkColor.
+static inline SkColor makeSkColor(const Color& c)
+{
+ return SkColorSetARGB(c.alpha(), c.red(), c.green(), c.blue());
+}
+
// Collect sorted stop position and color information into the pos and colors
// buffers, ensuring stops at both 0.0 and 1.0. The buffers must be large
// enough to hold information for all stops, including the new endpoints if
// stops at 0.0 and 1.0 aren't already included.
static void fillStops(const Gradient::ColorStop* stopData,
- size_t count, SkScalar* pos, SkColor* colors)
+ size_t count, ColorStopOffsetVector& pos, ColorStopColorVector& colors)
{
const Gradient::ColorStop* stop = stopData;
size_t start = 0;
if (count < 1) {
// A gradient with no stops must be transparent black.
pos[0] = WebCoreFloatToSkScalar(0.0);
- colors[0] = makeSkColor(0.0, 0.0, 0.0, 0.0);
+ colors[0] = SK_ColorTRANSPARENT;
start = 1;
} else if (stop->stop > 0.0) {
// Copy the first stop to 0.0. The first stop position may have a slight
@@ -193,13 +182,13 @@ static void fillStops(const Gradient::ColorStop* stopData,
// 0.0 comes through cleanly and people aren't likely to want a gradient
// with a stop at (0 + epsilon).
pos[0] = WebCoreFloatToSkScalar(0.0);
- colors[0] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
+ colors[0] = makeSkColor(stop->color);
start = 1;
}
for (size_t i = start; i < start + count; i++) {
pos[i] = WebCoreFloatToSkScalar(stop->stop);
- colors[i] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
+ colors[i] = makeSkColor(stop->color);
++stop;
}
@@ -223,11 +212,8 @@ SkShader* Gradient::shader()
ASSERT(countUsed >= 2);
ASSERT(countUsed >= m_stops.size());
- // FIXME: Why is all this manual pointer math needed?!
- SkAutoMalloc storage(countUsed * (sizeof(SkColor) + sizeof(SkScalar)));
- SkColor* colors = (SkColor*)storage.get();
- SkScalar* pos = (SkScalar*)(colors + countUsed);
-
+ ColorStopOffsetVector pos(countUsed);
+ ColorStopColorVector colors(countUsed);
fillStops(m_stops.data(), m_stops.size(), pos, colors);
SkShader::TileMode tile = SkShader::kClamp_TileMode;
@@ -245,36 +231,36 @@ SkShader* Gradient::shader()
uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader::kInterpolateColorsInPremul_Flag : 0;
if (m_radial) {
+ if (aspectRatio() != 1) {
+ // CSS3 elliptical gradients: apply the elliptical scaling at the
+ // gradient center point.
+ m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y());
+ m_gradientSpaceTransformation.scale(1, 1 / aspectRatio());
+ m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y());
+ ASSERT(m_p0 == m_p1);
+ }
+ SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransformation);
+
// Since the two-point radial gradient is slower than the plain radial,
// only use it if we have to.
if (m_p0 == m_p1 && m_r0 <= 0.0f) {
- m_gradient = adoptRef(SkGradientShader::CreateRadial(m_p1, m_r1, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace));
+ m_gradient = adoptRef(SkGradientShader::CreateRadial(m_p1.data(), m_r1, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix));
} else {
// The radii we give to Skia must be positive. If we're given a
// negative radius, ask for zero instead.
SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0;
SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0;
- m_gradient = adoptRef(SkGradientShader::CreateTwoPointConical(m_p0, radius0, m_p1, radius1, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace));
- }
-
- if (aspectRatio() != 1) {
- // CSS3 elliptical gradients: apply the elliptical scaling at the
- // gradient center point.
- m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y());
- m_gradientSpaceTransformation.scale(1, 1 / aspectRatio());
- m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y());
- ASSERT(m_p0 == m_p1);
+ m_gradient = adoptRef(SkGradientShader::CreateTwoPointConical(m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix));
}
} else {
- SkPoint pts[2] = { m_p0, m_p1 };
- m_gradient = adoptRef(SkGradientShader::CreateLinear(pts, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace));
+ SkPoint pts[2] = { m_p0.data(), m_p1.data() };
+ SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransformation);
+ m_gradient = adoptRef(SkGradientShader::CreateLinear(pts, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix));
}
if (!m_gradient) {
// use last color, since our "geometry" was degenerate (e.g. radius==0)
m_gradient = adoptRef(new SkColorShader(colors[countUsed - 1]));
- } else {
- m_gradient->setLocalMatrix(affineTransformToSkMatrix(m_gradientSpaceTransformation));
}
return m_gradient.get();
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Gradient.h b/chromium/third_party/WebKit/Source/platform/graphics/Gradient.h
index 0fa5814555f..ff48b9f9a2e 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Gradient.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Gradient.h
@@ -31,6 +31,7 @@
#include "platform/PlatformExport.h"
#include "platform/geometry/FloatPoint.h"
+#include "platform/graphics/Color.h"
#include "platform/graphics/GraphicsTypes.h"
#include "platform/transforms/AffineTransform.h"
#include "wtf/PassRefPtr.h"
@@ -42,7 +43,6 @@ class SkShader;
namespace WebCore {
-class Color;
class FloatRect;
class IntSize;
@@ -60,18 +60,15 @@ public:
struct ColorStop {
float stop;
- float red;
- float green;
- float blue;
- float alpha;
+ Color color;
- ColorStop() : stop(0), red(0), green(0), blue(0), alpha(0) { }
- ColorStop(float s, float r, float g, float b, float a) : stop(s), red(r), green(g), blue(b), alpha(a) { }
+ ColorStop(float s, const Color& c) : stop(s), color(c) { }
};
void addColorStop(const ColorStop&);
- void addColorStop(float, const Color&);
+ void addColorStop(float value, const Color& color) { addColorStop(ColorStop(value, color)); }
bool hasAlpha() const;
+ bool shaderChanged() const { return !m_gradient; }
bool isRadial() const { return m_radial; }
bool isZeroSize() const { return m_p0.x() == m_p1.x() && m_p0.y() == m_p1.y() && (!m_radial || m_r0 == m_r1); }
@@ -118,8 +115,6 @@ public:
SkShader* shader();
- void setStopsSorted(bool s) { m_stopsSorted = s; }
-
void setDrawsInPMColorSpace(bool drawInPMColorSpace);
void setSpreadMethod(GradientSpreadMethod);
@@ -135,20 +130,18 @@ private:
void sortStopsIfNecessary();
- // Keep any parameters relevant to rendering in sync with the structure in Gradient::hash().
- bool m_radial;
FloatPoint m_p0;
FloatPoint m_p1;
float m_r0;
float m_r1;
float m_aspectRatio; // For elliptical gradient, width / height.
- mutable Vector<ColorStop, 2> m_stops;
- mutable bool m_stopsSorted;
+ Vector<ColorStop, 2> m_stops;
+ bool m_radial;
+ bool m_stopsSorted;
+ bool m_drawInPMColorSpace;
GradientSpreadMethod m_spreadMethod;
AffineTransform m_gradientSpaceTransformation;
- bool m_drawInPMColorSpace;
-
RefPtr<SkShader> m_gradient;
};
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GradientGeneratedImage.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GradientGeneratedImage.cpp
index 90eabf6658f..772612b029e 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GradientGeneratedImage.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GradientGeneratedImage.cpp
@@ -38,7 +38,7 @@ void GradientGeneratedImage::draw(GraphicsContext* destContext, const FloatRect&
destContext->clip(destRect);
destContext->translate(destRect.x(), destRect.y());
if (destRect.size() != srcRect.size())
- destContext->scale(FloatSize(destRect.width() / srcRect.width(), destRect.height() / srcRect.height()));
+ destContext->scale(destRect.width() / srcRect.width(), destRect.height() / srcRect.height());
destContext->translate(-srcRect.x(), -srcRect.y());
destContext->setFillGradient(m_gradient);
destContext->fillRect(FloatRect(FloatPoint(), m_size));
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
index 251011bc443..9b479b7a2ba 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
@@ -27,6 +27,7 @@
#include "config.h"
#include "platform/graphics/GraphicsContext.h"
+#include "platform/TraceEvent.h"
#include "platform/geometry/IntRect.h"
#include "platform/geometry/RoundedRect.h"
#include "platform/graphics/BitmapImage.h"
@@ -39,9 +40,11 @@
#include "third_party/skia/include/core/SkAnnotation.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkDevice.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRefCnt.h"
+#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
#include "third_party/skia/include/effects/SkCornerPathEffect.h"
#include "third_party/skia/include/effects/SkLumaColorFilter.h"
@@ -50,10 +53,6 @@
#include "wtf/Assertions.h"
#include "wtf/MathExtras.h"
-#if OS(MACOSX)
-#include <ApplicationServices/ApplicationServices.h>
-#endif
-
using namespace std;
using blink::WebBlendMode;
@@ -64,20 +63,20 @@ namespace {
class CompatibleImageBufferSurface : public ImageBufferSurface {
WTF_MAKE_NONCOPYABLE(CompatibleImageBufferSurface); WTF_MAKE_FAST_ALLOCATED;
public:
- CompatibleImageBufferSurface(PassRefPtr<SkBaseDevice> device, const IntSize& size, OpacityMode opacityMode)
+ CompatibleImageBufferSurface(PassRefPtr<SkSurface> surface, const IntSize& size, OpacityMode opacityMode)
: ImageBufferSurface(size, opacityMode)
+ , m_surface(surface)
{
- m_canvas = adoptPtr(new SkCanvas(device.get())); // Takes a ref on device
}
virtual ~CompatibleImageBufferSurface() { }
- virtual SkCanvas* canvas() const OVERRIDE { return m_canvas.get(); }
- virtual bool isValid() const OVERRIDE { return m_canvas; }
- virtual bool isAccelerated() const OVERRIDE { return isValid() && m_canvas->getTopDevice()->accessRenderTarget(); }
+ virtual SkCanvas* canvas() const OVERRIDE { return m_surface ? m_surface->getCanvas() : 0; }
+ virtual bool isValid() const OVERRIDE { return m_surface; }
+ virtual bool isAccelerated() const OVERRIDE { return isValid() && m_surface->getCanvas()->getTopDevice()->accessRenderTarget(); }
virtual Platform3DObject getBackingTexture() const OVERRIDE
{
ASSERT(isAccelerated());
- GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget();
+ GrRenderTarget* renderTarget = m_surface->getCanvas()->getTopDevice()->accessRenderTarget();
if (renderTarget) {
return renderTarget->asTexture()->getTextureHandle();
}
@@ -85,15 +84,16 @@ public:
};
private:
- OwnPtr<SkCanvas> m_canvas;
+ RefPtr<SkSurface> m_surface;
};
} // unnamed namespace
-struct GraphicsContext::DeferredSaveState {
- DeferredSaveState(unsigned mask, int count) : m_flags(mask), m_restoreCount(count) { }
+struct GraphicsContext::CanvasSaveState {
+ CanvasSaveState(bool pendingSave, int count)
+ : m_pendingSave(pendingSave), m_restoreCount(count) { }
- unsigned m_flags;
+ bool m_pendingSave;
int m_restoreCount;
};
@@ -110,14 +110,18 @@ struct GraphicsContext::RecordingState {
const SkMatrix m_savedMatrix;
};
-GraphicsContext::GraphicsContext(SkCanvas* canvas)
+GraphicsContext::GraphicsContext(SkCanvas* canvas, DisabledMode disableContextOrPainting)
: m_canvas(canvas)
- , m_deferredSaveFlags(0)
+ , m_paintStateStack()
+ , m_paintStateIndex(0)
+ , m_pendingCanvasSave(false)
, m_annotationMode(0)
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
, m_annotationCount(0)
, m_layerCount(0)
+ , m_disableDestructionChecks(false)
#endif
+ , m_disabledState(disableContextOrPainting)
, m_trackOpaqueRegion(false)
, m_trackTextRegion(false)
, m_useHighResMarker(false)
@@ -125,78 +129,80 @@ GraphicsContext::GraphicsContext(SkCanvas* canvas)
, m_accelerated(false)
, m_isCertainlyOpaque(true)
, m_printing(false)
+ , m_antialiasHairlineImages(false)
{
- m_stateStack.append(adoptPtr(new GraphicsContextState()));
- m_state = m_stateStack.last().get();
-}
+ if (!canvas)
+ m_disabledState |= PaintingDisabled;
-GraphicsContext::~GraphicsContext()
-{
- ASSERT(m_stateStack.size() == 1);
- ASSERT(!m_annotationCount);
- ASSERT(!m_layerCount);
- ASSERT(m_recordingStateStack.isEmpty());
+ // FIXME: Do some tests to determine how many states are typically used, and allocate
+ // several here.
+ m_paintStateStack.append(GraphicsContextState::create());
+ m_paintState = m_paintStateStack.last().get();
}
-const SkBitmap* GraphicsContext::bitmap() const
-{
- TRACE_EVENT0("skia", "GraphicsContext::bitmap");
- return &m_canvas->getDevice()->accessBitmap(false);
-}
-
-const SkBitmap& GraphicsContext::layerBitmap(AccessMode access) const
+GraphicsContext::~GraphicsContext()
{
- return m_canvas->getTopDevice()->accessBitmap(access == ReadWrite);
+#if ASSERT_ENABLED
+ if (!m_disableDestructionChecks) {
+ ASSERT(!m_paintStateIndex);
+ ASSERT(!m_paintState->saveCount());
+ ASSERT(!m_annotationCount);
+ ASSERT(!m_layerCount);
+ ASSERT(m_recordingStateStack.isEmpty());
+ ASSERT(m_canvasStateStack.isEmpty());
+ }
+#endif
}
void GraphicsContext::save()
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- m_stateStack.append(m_state->clone());
- m_state = m_stateStack.last().get();
+ m_paintState->incrementSaveCount();
- m_saveStateStack.append(DeferredSaveState(m_deferredSaveFlags, m_canvas->getSaveCount()));
- m_deferredSaveFlags |= SkCanvas::kMatrixClip_SaveFlag;
+ m_canvasStateStack.append(CanvasSaveState(m_pendingCanvasSave, m_canvas->getSaveCount()));
+ m_pendingCanvasSave = true;
}
void GraphicsContext::restore()
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- if (m_stateStack.size() == 1) {
+ if (!m_paintStateIndex && !m_paintState->saveCount()) {
WTF_LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty");
return;
}
- m_stateStack.removeLast();
- m_state = m_stateStack.last().get();
+ if (m_paintState->saveCount()) {
+ m_paintState->decrementSaveCount();
+ } else {
+ m_paintStateIndex--;
+ m_paintState = m_paintStateStack[m_paintStateIndex].get();
+ }
- DeferredSaveState savedState = m_saveStateStack.last();
- m_saveStateStack.removeLast();
- m_deferredSaveFlags = savedState.m_flags;
+ CanvasSaveState savedState = m_canvasStateStack.last();
+ m_canvasStateStack.removeLast();
+ m_pendingCanvasSave = savedState.m_pendingSave;
m_canvas->restoreToCount(savedState.m_restoreCount);
}
-void GraphicsContext::saveLayer(const SkRect* bounds, const SkPaint* paint, SkCanvas::SaveFlags saveFlags)
+void GraphicsContext::saveLayer(const SkRect* bounds, const SkPaint* paint)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- realizeSave(SkCanvas::kMatrixClip_SaveFlag);
+ realizeCanvasSave();
- m_canvas->saveLayer(bounds, paint, saveFlags);
- if (bounds)
- m_canvas->clipRect(*bounds);
+ m_canvas->saveLayer(bounds, paint);
if (m_trackOpaqueRegion)
m_opaqueRegion.pushCanvasLayer(paint);
}
void GraphicsContext::restoreLayer()
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
m_canvas->restore();
@@ -207,7 +213,7 @@ void GraphicsContext::restoreLayer()
void GraphicsContext::beginAnnotation(const char* rendererName, const char* paintPhase,
const String& elementId, const String& elementClass, const String& elementTag)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
canvas()->beginCommentGroup("GraphicsContextAnnotation");
@@ -220,34 +226,27 @@ void GraphicsContext::beginAnnotation(const char* rendererName, const char* pain
for (AnnotationList::const_iterator it = annotations.begin(); it != end; ++it)
canvas()->addComment(it->first, it->second.ascii().data());
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
++m_annotationCount;
#endif
}
void GraphicsContext::endAnnotation()
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
canvas()->endCommentGroup();
ASSERT(m_annotationCount > 0);
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
--m_annotationCount;
#endif
}
-void GraphicsContext::setStrokeColor(const Color& color)
-{
- m_state->m_strokeData.setColor(color);
- m_state->m_strokeData.clearGradient();
- m_state->m_strokeData.clearPattern();
-}
-
void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
ASSERT(pattern);
@@ -255,13 +254,12 @@ void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
setStrokeColor(Color::black);
return;
}
- m_state->m_strokeData.clearGradient();
- m_state->m_strokeData.setPattern(pattern);
+ mutableState()->setStrokePattern(pattern);
}
void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
ASSERT(gradient);
@@ -269,20 +267,12 @@ void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
setStrokeColor(Color::black);
return;
}
- m_state->m_strokeData.setGradient(gradient);
- m_state->m_strokeData.clearPattern();
-}
-
-void GraphicsContext::setFillColor(const Color& color)
-{
- m_state->m_fillColor = color;
- m_state->m_fillGradient.clear();
- m_state->m_fillPattern.clear();
+ mutableState()->setStrokeGradient(gradient);
}
void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
ASSERT(pattern);
@@ -290,13 +280,13 @@ void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
setFillColor(Color::black);
return;
}
- m_state->m_fillGradient.clear();
- m_state->m_fillPattern = pattern;
+
+ mutableState()->setFillPattern(pattern);
}
void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
ASSERT(gradient);
@@ -304,81 +294,64 @@ void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
setFillColor(Color::black);
return;
}
- m_state->m_fillGradient = gradient;
- m_state->m_fillPattern.clear();
+
+ mutableState()->setFillGradient(gradient);
}
void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color& color,
- DrawLooper::ShadowTransformMode shadowTransformMode,
- DrawLooper::ShadowAlphaMode shadowAlphaMode)
+ DrawLooperBuilder::ShadowTransformMode shadowTransformMode,
+ DrawLooperBuilder::ShadowAlphaMode shadowAlphaMode)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- if (!color.isValid() || !color.alpha() || (!offset.width() && !offset.height() && !blur)) {
+ if (!color.alpha() || (!offset.width() && !offset.height() && !blur)) {
clearShadow();
return;
}
- DrawLooper drawLooper;
- drawLooper.addShadow(offset, blur, color, shadowTransformMode, shadowAlphaMode);
- drawLooper.addUnmodifiedContent();
- setDrawLooper(drawLooper);
+ OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create();
+ drawLooperBuilder->addShadow(offset, blur, color, shadowTransformMode, shadowAlphaMode);
+ drawLooperBuilder->addUnmodifiedContent();
+ setDrawLooper(drawLooperBuilder.release());
}
-void GraphicsContext::setDrawLooper(const DrawLooper& drawLooper)
+void GraphicsContext::setDrawLooper(PassOwnPtr<DrawLooperBuilder> drawLooperBuilder)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- m_state->m_looper = drawLooper.skDrawLooper();
+ mutableState()->setDrawLooper(drawLooperBuilder->detachDrawLooper());
}
void GraphicsContext::clearDrawLooper()
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- m_state->m_looper.clear();
+ mutableState()->clearDrawLooper();
}
bool GraphicsContext::hasShadow() const
{
- return !!m_state->m_looper;
-}
-
-int GraphicsContext::getNormalizedAlpha() const
-{
- int alpha = roundf(m_state->m_alpha * 256);
- if (alpha > 255)
- alpha = 255;
- else if (alpha < 0)
- alpha = 0;
- return alpha;
-}
-
-bool GraphicsContext::getClipBounds(SkRect* bounds) const
-{
- if (paintingDisabled())
- return false;
- return m_canvas->getClipBounds(bounds);
+ return !!immutableState()->drawLooper();
}
bool GraphicsContext::getTransformedClipBounds(FloatRect* bounds) const
{
- if (paintingDisabled())
+ if (contextDisabled())
return false;
SkIRect skIBounds;
if (!m_canvas->getClipDeviceBounds(&skIBounds))
return false;
- SkRect skBounds = SkRect::MakeFromIRect(skIBounds);
+ SkRect skBounds = SkRect::Make(skIBounds);
*bounds = FloatRect(skBounds);
return true;
}
SkMatrix GraphicsContext::getTotalMatrix() const
{
- if (paintingDisabled())
+ if (contextDisabled())
return SkMatrix::I();
if (!isRecording())
@@ -391,16 +364,9 @@ SkMatrix GraphicsContext::getTotalMatrix() const
return totalMatrix;
}
-bool GraphicsContext::isPrintingDevice() const
-{
- if (paintingDisabled())
- return false;
- return m_canvas->getTopDevice()->getDeviceCapabilities() & SkBaseDevice::kVector_Capability;
-}
-
void GraphicsContext::adjustTextRenderMode(SkPaint* paint)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
if (!paint->isLCDRenderText())
@@ -413,9 +379,9 @@ bool GraphicsContext::couldUseLCDRenderedText()
{
// Our layers only have a single alpha channel. This means that subpixel
// rendered text cannot be composited correctly when the layer is
- // collapsed. Therefore, subpixel text is disabled when we are drawing
+ // collapsed. Therefore, subpixel text is contextDisabled when we are drawing
// onto a layer.
- if (paintingDisabled() || isDrawingToLayer() || !isCertainlyOpaque())
+ if (contextDisabled() || m_canvas->isDrawingToLayer() || !isCertainlyOpaque())
return false;
return shouldSmoothFonts();
@@ -423,94 +389,94 @@ bool GraphicsContext::couldUseLCDRenderedText()
void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation, WebBlendMode blendMode)
{
- m_state->m_compositeOperator = compositeOperation;
- m_state->m_blendMode = blendMode;
- m_state->m_xferMode = WebCoreCompositeToSkiaComposite(compositeOperation, blendMode);
+ if (contextDisabled())
+ return;
+ mutableState()->setCompositeOperation(compositeOperation, blendMode);
}
SkColorFilter* GraphicsContext::colorFilter()
{
- return m_state->m_colorFilter.get();
+ return immutableState()->colorFilter();
}
void GraphicsContext::setColorFilter(ColorFilter colorFilter)
{
+ GraphicsContextState* stateToSet = mutableState();
+
// We only support one active color filter at the moment. If (when) this becomes a problem,
// we should switch to using color filter chains (Skia work in progress).
- ASSERT(!m_state->m_colorFilter);
- m_state->m_colorFilter = WebCoreColorFilterToSkiaColorFilter(colorFilter);
+ ASSERT(!stateToSet->colorFilter());
+ stateToSet->setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter));
}
-bool GraphicsContext::readPixels(SkBitmap* bitmap, int x, int y, SkCanvas::Config8888 config8888)
+bool GraphicsContext::readPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, int x, int y)
{
- if (paintingDisabled())
+ if (contextDisabled())
return false;
- return m_canvas->readPixels(bitmap, x, y, config8888);
+ return m_canvas->readPixels(info, pixels, rowBytes, x, y);
}
void GraphicsContext::setMatrix(const SkMatrix& matrix)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- realizeSave(SkCanvas::kMatrix_SaveFlag);
+ realizeCanvasSave();
m_canvas->setMatrix(matrix);
}
-bool GraphicsContext::concat(const SkMatrix& matrix)
+void GraphicsContext::concat(const SkMatrix& matrix)
{
- if (paintingDisabled())
- return false;
+ if (contextDisabled())
+ return;
- realizeSave(SkCanvas::kMatrix_SaveFlag);
+ if (matrix.isIdentity())
+ return;
- return m_canvas->concat(matrix);
+ realizeCanvasSave();
+
+ m_canvas->concat(matrix);
}
void GraphicsContext::beginTransparencyLayer(float opacity, const FloatRect* bounds)
{
- beginLayer(opacity, m_state->m_compositeOperator, bounds);
+ beginLayer(opacity, immutableState()->compositeOperator(), bounds);
}
-void GraphicsContext::beginLayer(float opacity, CompositeOperator op, const FloatRect* bounds, ColorFilter colorFilter)
+void GraphicsContext::beginLayer(float opacity, CompositeOperator op, const FloatRect* bounds, ColorFilter colorFilter, ImageFilter* imageFilter)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- // We need the "alpha" layer flag here because the base layer is opaque
- // (the surface of the page) but layers on top may have transparent parts.
- // Without explicitly setting the alpha flag, the layer will inherit the
- // opaque setting of the base and some things won't work properly.
- SkCanvas::SaveFlags saveFlags = static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag);
-
SkPaint layerPaint;
layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255));
- layerPaint.setXfermode(WebCoreCompositeToSkiaComposite(op, m_state->m_blendMode).get());
+ layerPaint.setXfermode(WebCoreCompositeToSkiaComposite(op, m_paintState->blendMode()).get());
layerPaint.setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter).get());
+ layerPaint.setImageFilter(imageFilter);
if (bounds) {
SkRect skBounds = WebCoreFloatRectToSKRect(*bounds);
- saveLayer(&skBounds, &layerPaint, saveFlags);
+ saveLayer(&skBounds, &layerPaint);
} else {
- saveLayer(0, &layerPaint, saveFlags);
+ saveLayer(0, &layerPaint);
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
++m_layerCount;
#endif
}
void GraphicsContext::endLayer()
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
restoreLayer();
ASSERT(m_layerCount > 0);
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
--m_layerCount;
#endif
}
@@ -522,16 +488,17 @@ void GraphicsContext::beginRecording(const FloatRect& bounds)
SkCanvas* savedCanvas = m_canvas;
SkMatrix savedMatrix = getTotalMatrix();
- IntRect recordingRect = enclosingIntRect(bounds);
- m_canvas = displayList->picture()->beginRecording(recordingRect.width(), recordingRect.height(),
- SkPicture::kUsePathBoundsForClip_RecordingFlag);
+ if (!contextDisabled()) {
+ IntRect recordingRect = enclosingIntRect(bounds);
+ m_canvas = displayList->beginRecording(recordingRect.size());
- // We want the bounds offset mapped to (0, 0), such that the display list content
- // is fully contained within the SkPictureRecord's bounds.
- if (!toFloatSize(bounds.location()).isZero()) {
- m_canvas->translate(-bounds.x(), -bounds.y());
- // To avoid applying the offset repeatedly in getTotalMatrix(), we pre-apply it here.
- savedMatrix.preTranslate(bounds.x(), bounds.y());
+ // We want the bounds offset mapped to (0, 0), such that the display list content
+ // is fully contained within the SkPictureRecord's bounds.
+ if (!toFloatSize(bounds.location()).isZero()) {
+ m_canvas->translate(-bounds.x(), -bounds.y());
+ // To avoid applying the offset repeatedly in getTotalMatrix(), we pre-apply it here.
+ savedMatrix.preTranslate(bounds.x(), bounds.y());
+ }
}
m_recordingStateStack.append(RecordingState(savedCanvas, savedMatrix, displayList));
@@ -542,8 +509,10 @@ PassRefPtr<DisplayList> GraphicsContext::endRecording()
ASSERT(!m_recordingStateStack.isEmpty());
RecordingState recording = m_recordingStateStack.last();
- ASSERT(recording.m_displayList->picture()->getRecordingCanvas());
- recording.m_displayList->picture()->endRecording();
+ if (!contextDisabled()) {
+ ASSERT(recording.m_displayList->isRecording());
+ recording.m_displayList->endRecording();
+ }
m_recordingStateStack.removeLast();
m_canvas = recording.m_savedCanvas;
@@ -558,49 +527,27 @@ bool GraphicsContext::isRecording() const
void GraphicsContext::drawDisplayList(DisplayList* displayList)
{
- ASSERT(!displayList->picture()->getRecordingCanvas());
+ ASSERT(displayList);
+ ASSERT(!displayList->isRecording());
- if (paintingDisabled() || !displayList)
+ if (contextDisabled() || displayList->bounds().isEmpty())
return;
- realizeSave(SkCanvas::kMatrixClip_SaveFlag);
+ realizeCanvasSave();
const FloatRect& bounds = displayList->bounds();
if (bounds.x() || bounds.y())
m_canvas->translate(bounds.x(), bounds.y());
- m_canvas->drawPicture(*displayList->picture());
+ m_canvas->drawPicture(displayList->picture());
if (bounds.x() || bounds.y())
m_canvas->translate(-bounds.x(), -bounds.y());
}
-void GraphicsContext::setupPaintForFilling(SkPaint* paint) const
-{
- if (paintingDisabled())
- return;
-
- setupPaintCommon(paint);
-
- setupShader(paint, m_state->m_fillGradient.get(), m_state->m_fillPattern.get(), m_state->m_fillColor.rgb());
-}
-
-float GraphicsContext::setupPaintForStroking(SkPaint* paint, int length) const
-{
- if (paintingDisabled())
- return 0.0f;
-
- setupPaintCommon(paint);
-
- setupShader(paint, m_state->m_strokeData.gradient(), m_state->m_strokeData.pattern(),
- m_state->m_strokeData.color().rgb());
-
- return m_state->m_strokeData.setupPaint(paint, length);
-}
-
void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
if (numPoints <= 1)
@@ -609,40 +556,18 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* poin
SkPath path;
setPathFromConvexPoints(&path, numPoints, points);
- SkPaint paint;
- setupPaintForFilling(&paint);
+ SkPaint paint(immutableState()->fillPaint());
paint.setAntiAlias(shouldAntialias);
drawPath(path, paint);
- if (strokeStyle() != NoStroke) {
- paint.reset();
- setupPaintForStroking(&paint);
- drawPath(path, paint);
- }
-}
-
-// This method is only used to draw the little circles used in lists.
-void GraphicsContext::drawEllipse(const IntRect& elipseRect)
-{
- if (paintingDisabled())
- return;
-
- SkRect rect = elipseRect;
- SkPaint paint;
- setupPaintForFilling(&paint);
- drawOval(rect, paint);
-
- if (strokeStyle() != NoStroke) {
- paint.reset();
- setupPaintForStroking(&paint);
- drawOval(rect, paint);
- }
+ if (strokeStyle() != NoStroke)
+ drawPath(path, immutableState()->strokePaint());
}
void GraphicsContext::drawFocusRing(const Path& focusRingPath, int width, int offset, const Color& color)
{
// FIXME: Implement support for offset.
- if (paintingDisabled())
+ if (contextDisabled())
return;
SkPaint paint;
@@ -656,7 +581,7 @@ void GraphicsContext::drawFocusRing(const Path& focusRingPath, int width, int of
void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
unsigned rectCount = rects.size();
@@ -698,6 +623,9 @@ static inline IntRect areaCastingShadowInHole(const IntRect& holeRect, int shado
void GraphicsContext::drawInnerShadow(const RoundedRect& rect, const Color& shadowColor, const IntSize shadowOffset, int shadowBlur, int shadowSpread, Edges clippedEdges)
{
+ if (contextDisabled())
+ return;
+
IntRect holeRect(rect.rect());
holeRect.inflate(-shadowSpread);
@@ -737,26 +665,24 @@ void GraphicsContext::drawInnerShadow(const RoundedRect& rect, const Color& shad
clip(rect.rect());
}
- DrawLooper drawLooper;
- drawLooper.addShadow(shadowOffset, shadowBlur, shadowColor,
- DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha);
- setDrawLooper(drawLooper);
+ OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create();
+ drawLooperBuilder->addShadow(shadowOffset, shadowBlur, shadowColor,
+ DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowIgnoresAlpha);
+ setDrawLooper(drawLooperBuilder.release());
fillRectWithRoundedHole(outerRect, roundedHole, fillColor);
restore();
clearDrawLooper();
}
-// This is only used to draw borders.
void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
StrokeStyle penStyle = strokeStyle();
if (penStyle == NoStroke)
return;
- SkPaint paint;
FloatPoint p1 = point1;
FloatPoint p2 = point2;
bool isVerticalLine = (p1.x() == p2.x());
@@ -766,13 +692,12 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
// be the sum of the displacement component vectors give or take 1 -
// probably worth the speed up of no square root, which also won't be exact.
FloatSize disp = p2 - p1;
- int length = SkScalarRound(disp.width() + disp.height());
- setupPaintForStroking(&paint, length);
+ int length = SkScalarRoundToInt(disp.width() + disp.height());
+ SkPaint paint(immutableState()->strokePaint(length));
if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) {
// Do a rect fill of our endpoints. This ensures we always have the
// appearance of being a border. We then draw the actual dotted/dashed line.
-
SkRect r1, r2;
r1.set(p1.x(), p1.y(), p1.x() + width, p1.y() + width);
r2.set(p2.x(), p2.y(), p2.x() + width, p2.y() + width);
@@ -791,7 +716,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
}
adjustLineToPixelBoundaries(p1, p2, width, penStyle);
- SkPoint pts[2] = { (SkPoint)p1, (SkPoint)p2 };
+ SkPoint pts[2] = { p1.data(), p2.data() };
m_canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);
@@ -801,7 +726,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float width, DocumentMarkerLineStyle style)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
int deviceScaleFactor = m_useHighResMarker ? 2 : 1;
@@ -816,12 +741,11 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt
// Match the artwork used by the Mac.
const int rowPixels = 4 * deviceScaleFactor;
const int colPixels = 3 * deviceScaleFactor;
- misspellBitmap[index] = new SkBitmap;
- misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config,
- rowPixels, colPixels);
- misspellBitmap[index]->allocPixels();
+ SkBitmap bitmap;
+ if (!bitmap.allocN32Pixels(rowPixels, colPixels))
+ return;
- misspellBitmap[index]->eraseARGB(0, 0, 0, 0);
+ bitmap.eraseARGB(0, 0, 0, 0);
const uint32_t transparentColor = 0x00000000;
if (deviceScaleFactor == 1) {
@@ -834,7 +758,7 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt
// c d c c d c
// e f e e f e
for (int x = 0; x < colPixels; ++x) {
- uint32_t* row = misspellBitmap[index]->getAddr32(0, x);
+ uint32_t* row = bitmap.getAddr32(0, x);
row[0] = colors[index][x * 2];
row[1] = colors[index][x * 2 + 1];
row[2] = colors[index][x * 2];
@@ -855,7 +779,7 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt
// n o p p o n
// q r s s r q
for (int x = 0; x < colPixels; ++x) {
- uint32_t* row = misspellBitmap[index]->getAddr32(0, x);
+ uint32_t* row = bitmap.getAddr32(0, x);
row[0] = colors[index][x * 3];
row[1] = colors[index][x * 3 + 1];
row[2] = colors[index][x * 3 + 2];
@@ -867,23 +791,27 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt
}
} else
ASSERT_NOT_REACHED();
+
+ misspellBitmap[index] = new SkBitmap(bitmap);
#else
// We use a 2-pixel-high misspelling indicator because that seems to be
// what WebKit is designed for, and how much room there is in a typical
// page for it.
const int rowPixels = 32 * deviceScaleFactor; // Must be multiple of 4 for pattern below.
const int colPixels = 2 * deviceScaleFactor;
- misspellBitmap[index] = new SkBitmap;
- misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config, rowPixels, colPixels);
- misspellBitmap[index]->allocPixels();
+ SkBitmap bitmap;
+ if (!bitmap.allocN32Pixels(rowPixels, colPixels))
+ return;
- misspellBitmap[index]->eraseARGB(0, 0, 0, 0);
+ bitmap.eraseARGB(0, 0, 0, 0);
if (deviceScaleFactor == 1)
- draw1xMarker(misspellBitmap[index], index);
+ draw1xMarker(&bitmap, index);
else if (deviceScaleFactor == 2)
- draw2xMarker(misspellBitmap[index], index);
+ draw2xMarker(&bitmap, index);
else
ASSERT_NOT_REACHED();
+
+ misspellBitmap[index] = new SkBitmap(bitmap);
#endif
}
@@ -905,11 +833,10 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt
originY *= deviceScaleFactor;
#endif
+ SkMatrix localMatrix;
+ localMatrix.setTranslate(originX, originY);
RefPtr<SkShader> shader = adoptRef(SkShader::CreateBitmapShader(
- *misspellBitmap[index], SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
- SkMatrix matrix;
- matrix.setTranslate(originX, originY);
- shader->setLocalMatrix(matrix);
+ *misspellBitmap[index], SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix));
SkPaint paint;
paint.setShader(shader.get());
@@ -919,7 +846,7 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt
if (deviceScaleFactor == 2) {
save();
- scale(FloatSize(0.5, 0.5));
+ scale(0.5, 0.5);
}
drawRect(rect, paint);
if (deviceScaleFactor == 2)
@@ -928,44 +855,47 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt
void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool printing)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
if (width <= 0)
return;
- int thickness = SkMax32(static_cast<int>(strokeThickness()), 1);
- SkRect r;
- r.fLeft = WebCoreFloatToSkScalar(pt.x());
- // Avoid anti-aliasing lines. Currently, these are always horizontal.
- // Round to nearest pixel to match text and other content.
- r.fTop = WebCoreFloatToSkScalar(floorf(pt.y() + 0.5f));
- r.fRight = r.fLeft + WebCoreFloatToSkScalar(width);
- r.fBottom = r.fTop + SkIntToScalar(thickness);
-
SkPaint paint;
switch (strokeStyle()) {
case NoStroke:
case SolidStroke:
case DoubleStroke:
- case WavyStroke:
- setupPaintForFilling(&paint);
- break;
+ case WavyStroke: {
+ int thickness = SkMax32(static_cast<int>(strokeThickness()), 1);
+ SkRect r;
+ r.fLeft = WebCoreFloatToSkScalar(pt.x());
+ // Avoid anti-aliasing lines. Currently, these are always horizontal.
+ // Round to nearest pixel to match text and other content.
+ r.fTop = WebCoreFloatToSkScalar(floorf(pt.y() + 0.5f));
+ r.fRight = r.fLeft + WebCoreFloatToSkScalar(width);
+ r.fBottom = r.fTop + SkIntToScalar(thickness);
+ paint = immutableState()->fillPaint();
+ // Text lines are drawn using the stroke color.
+ paint.setColor(effectiveStrokeColor());
+ drawRect(r, paint);
+ return;
+ }
case DottedStroke:
- case DashedStroke:
- setupPaintForStroking(&paint);
- break;
+ case DashedStroke: {
+ int y = floorf(pt.y() + std::max<float>(strokeThickness() / 2.0f, 0.5f));
+ drawLine(IntPoint(pt.x(), y), IntPoint(pt.x() + width, y));
+ return;
+ }
}
- // Text lines are drawn using the stroke color.
- paint.setColor(effectiveStrokeColor());
- drawRect(r, paint);
+ ASSERT_NOT_REACHED();
}
// Draws a filled rectangle with a stroked border.
void GraphicsContext::drawRect(const IntRect& rect)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
ASSERT(!rect.isEmpty());
@@ -973,34 +903,26 @@ void GraphicsContext::drawRect(const IntRect& rect)
return;
SkRect skRect = rect;
- SkPaint paint;
- int fillcolorNotTransparent = m_state->m_fillColor.rgb() & 0xFF000000;
- if (fillcolorNotTransparent) {
- setupPaintForFilling(&paint);
+ int fillcolorNotTransparent = immutableState()->fillColor().rgb() & 0xFF000000;
+ if (fillcolorNotTransparent)
+ drawRect(skRect, immutableState()->fillPaint());
+
+ if (immutableState()->strokeData().style() != NoStroke
+ && immutableState()->strokeData().color().alpha()) {
+ // Stroke a width: 1 inset border
+ SkPaint paint(immutableState()->fillPaint());
+ paint.setColor(effectiveStrokeColor());
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(1);
+
+ skRect.inset(0.5f, 0.5f);
drawRect(skRect, paint);
}
-
- if (m_state->m_strokeData.style() != NoStroke && (m_state->m_strokeData.color().rgb() & 0xFF000000)) {
- // We do a fill of four rects to simulate the stroke of a border.
- paint.reset();
- setupPaintForFilling(&paint);
- // need to jam in the strokeColor
- paint.setColor(this->effectiveStrokeColor());
-
- SkRect topBorder = { skRect.fLeft, skRect.fTop, skRect.fRight, skRect.fTop + 1 };
- drawRect(topBorder, paint);
- SkRect bottomBorder = { skRect.fLeft, skRect.fBottom - 1, skRect.fRight, skRect.fBottom };
- drawRect(bottomBorder, paint);
- SkRect leftBorder = { skRect.fLeft, skRect.fTop + 1, skRect.fLeft + 1, skRect.fBottom - 1 };
- drawRect(leftBorder, paint);
- SkRect rightBorder = { skRect.fRight - 1, skRect.fTop + 1, skRect.fRight, skRect.fBottom - 1 };
- drawRect(rightBorder, paint);
- }
}
void GraphicsContext::drawText(const Font& font, const TextRunPaintInfo& runInfo, const FloatPoint& point)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
font.drawText(this, runInfo, point);
@@ -1008,7 +930,7 @@ void GraphicsContext::drawText(const Font& font, const TextRunPaintInfo& runInfo
void GraphicsContext::drawEmphasisMarks(const Font& font, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
font.drawEmphasisMarks(this, runInfo, mark, point);
@@ -1016,7 +938,7 @@ void GraphicsContext::drawEmphasisMarks(const Font& font, const TextRunPaintInfo
void GraphicsContext::drawBidiText(const Font& font, const TextRunPaintInfo& runInfo, const FloatPoint& point, Font::CustomFontNotReadyAction customFontNotReadyAction)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
// sub-run painting is not supported for Bidi text.
@@ -1056,7 +978,7 @@ void GraphicsContext::drawBidiText(const Font& font, const TextRunPaintInfo& run
void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, int from, int to)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor);
@@ -1069,21 +991,16 @@ void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperat
drawImage(image, FloatRect(IntRect(p, image->size())), FloatRect(FloatPoint(), FloatSize(image->size())), op, shouldRespectImageOrientation);
}
-void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
{
if (!image)
return;
- drawImage(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->size())), op, shouldRespectImageOrientation, useLowQualityScale);
-}
-
-void GraphicsContext::drawImage(Image* image, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
-{
- drawImage(image, FloatRect(IntRect(dest, srcRect.size())), FloatRect(srcRect), op, shouldRespectImageOrientation);
+ drawImage(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->size())), op, shouldRespectImageOrientation);
}
-void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
{
- drawImage(image, dest, src, op, blink::WebBlendModeNormal, shouldRespectImageOrientation, useLowQualityScale);
+ drawImage(image, dest, src, op, blink::WebBlendModeNormal, shouldRespectImageOrientation);
}
void GraphicsContext::drawImage(Image* image, const FloatRect& dest)
@@ -1093,42 +1010,24 @@ void GraphicsContext::drawImage(Image* image, const FloatRect& dest)
drawImage(image, dest, FloatRect(IntRect(IntPoint(), image->size())));
}
-void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
-{ if (paintingDisabled() || !image)
+void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode, RespectImageOrientationEnum shouldRespectImageOrientation)
+{
+ if (contextDisabled() || !image)
return;
-
- InterpolationQuality previousInterpolationQuality = InterpolationDefault;
-
- if (useLowQualityScale) {
- previousInterpolationQuality = imageInterpolationQuality();
- setImageInterpolationQuality(InterpolationLow);
- }
-
image->draw(this, dest, src, op, blendMode, shouldRespectImageOrientation);
-
- if (useLowQualityScale)
- setImageInterpolationQuality(previousInterpolationQuality);
}
-void GraphicsContext::drawTiledImage(Image* image, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLowQualityScale, WebBlendMode blendMode, const IntSize& repeatSpacing)
+void GraphicsContext::drawTiledImage(Image* image, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, WebBlendMode blendMode, const IntSize& repeatSpacing)
{
- if (paintingDisabled() || !image)
+ if (contextDisabled() || !image)
return;
-
- if (useLowQualityScale) {
- InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
- setImageInterpolationQuality(InterpolationLow);
- image->drawTiled(this, destRect, srcPoint, tileSize, op, blendMode, repeatSpacing);
- setImageInterpolationQuality(previousInterpolationQuality);
- } else {
- image->drawTiled(this, destRect, srcPoint, tileSize, op, blendMode, repeatSpacing);
- }
+ image->drawTiled(this, destRect, srcPoint, tileSize, op, blendMode, repeatSpacing);
}
void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const IntRect& srcRect,
- const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op, bool useLowQualityScale)
+ const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op)
{
- if (paintingDisabled() || !image)
+ if (contextDisabled() || !image)
return;
if (hRule == Image::StretchTile && vRule == Image::StretchTile) {
@@ -1137,81 +1036,54 @@ void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const In
return;
}
- if (useLowQualityScale) {
- InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
- setImageInterpolationQuality(InterpolationLow);
- image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, op);
- setImageInterpolationQuality(previousInterpolationQuality);
- } else {
- image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, op);
- }
+ image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, op);
}
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntPoint& p, CompositeOperator op, WebBlendMode blendMode)
+void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest,
+ const FloatRect* src, CompositeOperator op)
{
- if (!image)
+ if (contextDisabled() || !image)
return;
- drawImageBuffer(image, FloatRect(IntRect(p, image->size())), FloatRect(FloatPoint(), FloatSize(image->size())), op, blendMode);
-}
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntRect& r, CompositeOperator op, WebBlendMode blendMode, bool useLowQualityScale)
-{
- if (!image)
- return;
- drawImageBuffer(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->size())), op, blendMode, useLowQualityScale);
+ image->draw(this, dest, src, op);
}
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op, WebBlendMode blendMode)
+void GraphicsContext::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
{
- drawImageBuffer(image, FloatRect(IntRect(dest, srcRect.size())), FloatRect(srcRect), op, blendMode);
-}
+ if (contextDisabled())
+ return;
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, WebBlendMode blendMode, bool useLowQualityScale)
-{
- drawImageBuffer(image, FloatRect(dest), FloatRect(srcRect), op, blendMode, useLowQualityScale);
-}
+ m_canvas->writePixels(info, pixels, rowBytes, x, y);
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest)
-{
- if (!image)
- return;
- drawImageBuffer(image, dest, FloatRect(IntRect(IntPoint(), image->size())));
-}
+ if (m_trackOpaqueRegion) {
+ SkRect rect = SkRect::MakeXYWH(x, y, info.width(), info.height());
+ SkPaint paint;
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode, bool useLowQualityScale)
-{
- if (paintingDisabled() || !image)
- return;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ if (kOpaque_SkAlphaType != info.alphaType())
+ paint.setAlpha(0x80); // signal to m_opaqueRegion that we are not fully opaque
- if (useLowQualityScale) {
- InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
- setImageInterpolationQuality(InterpolationLow);
- image->draw(this, dest, src, op, blendMode, useLowQualityScale);
- setImageInterpolationQuality(previousInterpolationQuality);
- } else {
- image->draw(this, dest, src, op, blendMode, useLowQualityScale);
+ m_opaqueRegion.didDrawRect(this, rect, paint, 0);
+ // more efficient would be to call markRectAsOpaque or MarkRectAsNonOpaque directly,
+ // rather than cons-ing up a paint with an xfermode and alpha
}
}
-void GraphicsContext::writePixels(const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888)
+void GraphicsContext::writePixels(const SkBitmap& bitmap, int x, int y)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- m_canvas->writePixels(bitmap, x, y, config8888);
-
- if (m_trackOpaqueRegion) {
- SkRect rect = SkRect::MakeXYWH(x, y, bitmap.width(), bitmap.height());
- SkPaint paint;
-
- paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- m_opaqueRegion.didDrawRect(this, rect, paint, &bitmap);
+ if (!bitmap.getTexture()) {
+ SkAutoLockPixels alp(bitmap);
+ if (bitmap.getPixels())
+ writePixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(), x, y);
}
}
void GraphicsContext::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
m_canvas->drawBitmap(bitmap, left, top, paint);
@@ -1225,10 +1097,11 @@ void GraphicsContext::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar
void GraphicsContext::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
const SkRect& dst, const SkPaint* paint)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- SkCanvas::DrawBitmapRectFlags flags = m_state->m_shouldClampToSourceRect ? SkCanvas::kNone_DrawBitmapRectFlag : SkCanvas::kBleed_DrawBitmapRectFlag;
+ SkCanvas::DrawBitmapRectFlags flags =
+ immutableState()->shouldClampToSourceRect() ? SkCanvas::kNone_DrawBitmapRectFlag : SkCanvas::kBleed_DrawBitmapRectFlag;
m_canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags);
@@ -1238,7 +1111,7 @@ void GraphicsContext::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
void GraphicsContext::drawOval(const SkRect& oval, const SkPaint& paint)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
m_canvas->drawOval(oval, paint);
@@ -1249,7 +1122,7 @@ void GraphicsContext::drawOval(const SkRect& oval, const SkPaint& paint)
void GraphicsContext::drawPath(const SkPath& path, const SkPaint& paint)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
m_canvas->drawPath(path, paint);
@@ -1260,7 +1133,7 @@ void GraphicsContext::drawPath(const SkPath& path, const SkPaint& paint)
void GraphicsContext::drawRect(const SkRect& rect, const SkPaint& paint)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
m_canvas->drawRect(rect, paint);
@@ -1271,6 +1144,9 @@ void GraphicsContext::drawRect(const SkRect& rect, const SkPaint& paint)
void GraphicsContext::didDrawRect(const SkRect& rect, const SkPaint& paint, const SkBitmap* bitmap)
{
+ if (contextDisabled())
+ return;
+
if (m_trackOpaqueRegion)
m_opaqueRegion.didDrawRect(this, rect, paint, bitmap);
}
@@ -1278,7 +1154,7 @@ void GraphicsContext::didDrawRect(const SkRect& rect, const SkPaint& paint, cons
void GraphicsContext::drawPosText(const void* text, size_t byteLength,
const SkPoint pos[], const SkRect& textRect, const SkPaint& paint)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
m_canvas->drawPosText(text, byteLength, pos, paint);
@@ -1289,81 +1165,79 @@ void GraphicsContext::drawPosText(const void* text, size_t byteLength,
m_opaqueRegion.didDrawUnbounded(this, paint, OpaqueRegionSkia::FillOrStroke);
}
-void GraphicsContext::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY, const SkRect& textRect, const SkPaint& paint)
-{
- if (paintingDisabled())
- return;
-
- m_canvas->drawPosTextH(text, byteLength, xpos, constY, paint);
- didDrawTextInRect(textRect);
-
- // FIXME: compute bounds for positioned text.
- if (m_trackOpaqueRegion)
- m_opaqueRegion.didDrawUnbounded(this, paint, OpaqueRegionSkia::FillOrStroke);
-}
-
-void GraphicsContext::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkRect& textRect, const SkMatrix* matrix, const SkPaint& paint)
-{
- if (paintingDisabled())
- return;
-
- m_canvas->drawTextOnPath(text, byteLength, path, matrix, paint);
- didDrawTextInRect(textRect);
-
- // FIXME: compute bounds for positioned text.
- if (m_trackOpaqueRegion)
- m_opaqueRegion.didDrawUnbounded(this, paint, OpaqueRegionSkia::FillOrStroke);
-}
-
void GraphicsContext::fillPath(const Path& pathToFill)
{
- if (paintingDisabled() || pathToFill.isEmpty())
+ if (contextDisabled() || pathToFill.isEmpty())
return;
// Use const_cast and temporarily modify the fill type instead of copying the path.
SkPath& path = const_cast<SkPath&>(pathToFill.skPath());
SkPath::FillType previousFillType = path.getFillType();
- SkPath::FillType temporaryFillType = m_state->m_fillRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
+ SkPath::FillType temporaryFillType =
+ immutableState()->fillRule() == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
path.setFillType(temporaryFillType);
- SkPaint paint;
- setupPaintForFilling(&paint);
- drawPath(path, paint);
+ drawPath(path, immutableState()->fillPaint());
path.setFillType(previousFillType);
}
void GraphicsContext::fillRect(const FloatRect& rect)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
SkRect r = rect;
- SkPaint paint;
- setupPaintForFilling(&paint);
- drawRect(r, paint);
+ drawRect(r, immutableState()->fillPaint());
}
void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
SkRect r = rect;
- SkPaint paint;
- setupPaintCommon(&paint);
+ SkPaint paint = immutableState()->fillPaint();
paint.setColor(color.rgb());
drawRect(r, paint);
}
+void GraphicsContext::fillBetweenRoundedRects(const IntRect& outer, const IntSize& outerTopLeft, const IntSize& outerTopRight, const IntSize& outerBottomLeft, const IntSize& outerBottomRight,
+ const IntRect& inner, const IntSize& innerTopLeft, const IntSize& innerTopRight, const IntSize& innerBottomLeft, const IntSize& innerBottomRight, const Color& color) {
+ if (contextDisabled())
+ return;
+
+ SkVector outerRadii[4];
+ SkVector innerRadii[4];
+ setRadii(outerRadii, outerTopLeft, outerTopRight, outerBottomRight, outerBottomLeft);
+ setRadii(innerRadii, innerTopLeft, innerTopRight, innerBottomRight, innerBottomLeft);
+
+ SkRRect rrOuter;
+ SkRRect rrInner;
+ rrOuter.setRectRadii(outer, outerRadii);
+ rrInner.setRectRadii(inner, innerRadii);
+
+ SkPaint paint(immutableState()->fillPaint());
+ paint.setColor(color.rgb());
+
+ m_canvas->drawDRRect(rrOuter, rrInner, paint);
+
+ if (m_trackOpaqueRegion)
+ m_opaqueRegion.didDrawBounded(this, rrOuter.getBounds(), paint);
+}
+
+void GraphicsContext::fillBetweenRoundedRects(const RoundedRect& outer, const RoundedRect& inner, const Color& color)
+{
+ fillBetweenRoundedRects(outer.rect(), outer.radii().topLeft(), outer.radii().topRight(), outer.radii().bottomLeft(), outer.radii().bottomRight(),
+ inner.rect(), inner.radii().topLeft(), inner.radii().topRight(), inner.radii().bottomLeft(), inner.radii().bottomRight(), color);
+}
+
void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
if (topLeft.width() + topRight.width() > rect.width()
@@ -1383,8 +1257,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
SkRRect rr;
rr.setRectRadii(rect, radii);
- SkPaint paint;
- setupPaintForFilling(&paint);
+ SkPaint paint(immutableState()->fillPaint());
paint.setColor(color.rgb());
m_canvas->drawRRect(rr, paint);
@@ -1395,34 +1268,36 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
void GraphicsContext::fillEllipse(const FloatRect& ellipse)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
SkRect rect = ellipse;
- SkPaint paint;
- setupPaintForFilling(&paint);
- drawOval(rect, paint);
+ drawOval(rect, immutableState()->fillPaint());
}
void GraphicsContext::strokePath(const Path& pathToStroke)
{
- if (paintingDisabled() || pathToStroke.isEmpty())
+ if (contextDisabled() || pathToStroke.isEmpty())
return;
const SkPath& path = pathToStroke.skPath();
- SkPaint paint;
- setupPaintForStroking(&paint);
- drawPath(path, paint);
+ drawPath(path, immutableState()->strokePaint());
+}
+
+void GraphicsContext::strokeRect(const FloatRect& rect)
+{
+ strokeRect(rect, strokeThickness());
}
void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- SkPaint paint;
- setupPaintForStroking(&paint);
+ SkPaint paint(immutableState()->strokePaint());
paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth));
+ // Reset the dash effect to account for the width
+ immutableState()->strokeData().setupPaintDashPathEffect(&paint, 0);
// strokerect has special rules for CSS when the rect is degenerate:
// if width==0 && height==0, do nothing
// if width==0 || height==0, then just draw line for the other dimension
@@ -1444,20 +1319,22 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
void GraphicsContext::strokeEllipse(const FloatRect& ellipse)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- SkRect rect(ellipse);
- SkPaint paint;
- setupPaintForStroking(&paint);
- drawOval(rect, paint);
+ drawOval(ellipse, immutableState()->strokePaint());
}
-void GraphicsContext::clipRoundedRect(const RoundedRect& rect)
+void GraphicsContext::clipRoundedRect(const RoundedRect& rect, SkRegion::Op regionOp)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
+ if (!rect.isRounded()) {
+ clipRect(rect.rect(), NotAntiAliased, regionOp);
+ return;
+ }
+
SkVector radii[4];
RoundedRect::Radii wkRadii = rect.radii();
setRadii(radii, wkRadii.topLeft(), wkRadii.topRight(), wkRadii.bottomRight(), wkRadii.bottomLeft());
@@ -1465,12 +1342,12 @@ void GraphicsContext::clipRoundedRect(const RoundedRect& rect)
SkRRect r;
r.setRectRadii(rect.rect(), radii);
- clipRRect(r, AntiAliased);
+ clipRRect(r, AntiAliased, regionOp);
}
void GraphicsContext::clipOut(const Path& pathToClip)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
// Use const_cast and temporarily toggle the inverse fill type instead of copying the path.
@@ -1482,7 +1359,7 @@ void GraphicsContext::clipOut(const Path& pathToClip)
void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
{
- if (paintingDisabled() || pathToClip.isEmpty())
+ if (contextDisabled() || pathToClip.isEmpty())
return;
// Use const_cast and temporarily modify the fill type instead of copying the path.
@@ -1498,7 +1375,7 @@ void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
if (numPoints <= 1)
@@ -1511,22 +1388,15 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
void GraphicsContext::clipOutRoundedRect(const RoundedRect& rect)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- if (!rect.isRounded()) {
- clipOut(rect.rect());
- return;
- }
-
- Path path;
- path.addRoundedRect(rect);
- clipOut(path);
+ clipRoundedRect(rect, SkRegion::kDifference_Op);
}
void GraphicsContext::canvasClip(const Path& pathToClip, WindRule clipRule)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
// Use const_cast and temporarily modify the fill type instead of copying the path.
@@ -1540,69 +1410,94 @@ void GraphicsContext::canvasClip(const Path& pathToClip, WindRule clipRule)
path.setFillType(previousFillType);
}
-bool GraphicsContext::clipRect(const SkRect& rect, AntiAliasingMode aa, SkRegion::Op op)
+void GraphicsContext::clipRect(const SkRect& rect, AntiAliasingMode aa, SkRegion::Op op)
{
- if (paintingDisabled())
- return false;
+ if (contextDisabled())
+ return;
- realizeSave(SkCanvas::kClip_SaveFlag);
+ realizeCanvasSave();
- return m_canvas->clipRect(rect, op, aa == AntiAliased);
+ m_canvas->clipRect(rect, op, aa == AntiAliased);
}
-bool GraphicsContext::clipPath(const SkPath& path, AntiAliasingMode aa, SkRegion::Op op)
+void GraphicsContext::clipPath(const SkPath& path, AntiAliasingMode aa, SkRegion::Op op)
{
- if (paintingDisabled())
- return false;
+ if (contextDisabled())
+ return;
- realizeSave(SkCanvas::kClip_SaveFlag);
+ realizeCanvasSave();
- return m_canvas->clipPath(path, op, aa == AntiAliased);
+ m_canvas->clipPath(path, op, aa == AntiAliased);
}
-bool GraphicsContext::clipRRect(const SkRRect& rect, AntiAliasingMode aa, SkRegion::Op op)
+void GraphicsContext::clipRRect(const SkRRect& rect, AntiAliasingMode aa, SkRegion::Op op)
{
- if (paintingDisabled())
- return false;
+ if (contextDisabled())
+ return;
+
+ realizeCanvasSave();
+
+ m_canvas->clipRRect(rect, op, aa == AntiAliased);
+}
+
+void GraphicsContext::beginCull(const FloatRect& rect)
+{
+ if (contextDisabled())
+ return;
+
+ realizeCanvasSave();
+ m_canvas->pushCull(rect);
+}
- realizeSave(SkCanvas::kClip_SaveFlag);
+void GraphicsContext::endCull()
+{
+ if (contextDisabled())
+ return;
- return m_canvas->clipRRect(rect, op, aa == AntiAliased);
+ realizeCanvasSave();
+
+ m_canvas->popCull();
}
void GraphicsContext::rotate(float angleInRadians)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
- realizeSave(SkCanvas::kMatrix_SaveFlag);
+ realizeCanvasSave();
m_canvas->rotate(WebCoreFloatToSkScalar(angleInRadians * (180.0f / 3.14159265f)));
}
-void GraphicsContext::translate(float w, float h)
+void GraphicsContext::translate(float x, float y)
{
- if (paintingDisabled())
+ if (contextDisabled())
+ return;
+
+ if (!x && !y)
return;
- realizeSave(SkCanvas::kMatrix_SaveFlag);
+ realizeCanvasSave();
- m_canvas->translate(WebCoreFloatToSkScalar(w), WebCoreFloatToSkScalar(h));
+ m_canvas->translate(WebCoreFloatToSkScalar(x), WebCoreFloatToSkScalar(y));
}
-void GraphicsContext::scale(const FloatSize& size)
+void GraphicsContext::scale(float x, float y)
{
- if (paintingDisabled())
+ if (contextDisabled())
+ return;
+
+ if (x == 1.0f && y == 1.0f)
return;
- realizeSave(SkCanvas::kMatrix_SaveFlag);
+ realizeCanvasSave();
- m_canvas->scale(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height()));
+ m_canvas->scale(WebCoreFloatToSkScalar(x), WebCoreFloatToSkScalar(y));
}
void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
SkAutoDataUnref url(SkData::NewWithCString(link.string().utf8().data()));
@@ -1611,7 +1506,7 @@ void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
void GraphicsContext::setURLFragmentForRect(const String& destName, const IntRect& rect)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
SkAutoDataUnref skDestName(SkData::NewWithCString(destName.utf8().data()));
@@ -1620,16 +1515,16 @@ void GraphicsContext::setURLFragmentForRect(const String& destName, const IntRec
void GraphicsContext::addURLTargetAtPoint(const String& name, const IntPoint& pos)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
SkAutoDataUnref nameData(SkData::NewWithCString(name.utf8().data()));
SkAnnotateNamedDestination(m_canvas, SkPoint::Make(pos.x(), pos.y()), nameData);
}
-AffineTransform GraphicsContext::getCTM(IncludeDeviceScale) const
+AffineTransform GraphicsContext::getCTM() const
{
- if (paintingDisabled())
+ if (contextDisabled())
return AffineTransform();
SkMatrix m = getTotalMatrix();
@@ -1643,7 +1538,7 @@ AffineTransform GraphicsContext::getCTM(IncludeDeviceScale) const
void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, CompositeOperator op)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
CompositeOperator previousOperator = compositeOperation();
@@ -1654,6 +1549,9 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, Compos
void GraphicsContext::fillRoundedRect(const RoundedRect& rect, const Color& color)
{
+ if (contextDisabled())
+ return;
+
if (rect.isRounded())
fillRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight(), color);
else
@@ -1662,7 +1560,7 @@ void GraphicsContext::fillRoundedRect(const RoundedRect& rect, const Color& colo
void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedRect& roundedHoleRect, const Color& color)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
Path path;
@@ -1687,12 +1585,11 @@ void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const Rounded
void GraphicsContext::clearRect(const FloatRect& rect)
{
- if (paintingDisabled())
+ if (contextDisabled())
return;
SkRect r = rect;
- SkPaint paint;
- setupPaintForFilling(&paint);
+ SkPaint paint(immutableState()->fillPaint());
paint.setXfermodeMode(SkXfermode::kClear_Mode);
drawRect(r, paint);
}
@@ -1732,51 +1629,24 @@ PassOwnPtr<ImageBuffer> GraphicsContext::createCompatibleBuffer(const IntSize& s
// resolution than one pixel per unit. Also set up a corresponding scale factor on the
// graphics context.
- AffineTransform transform = getCTM(DefinitelyIncludeDeviceScale);
+ AffineTransform transform = getCTM();
IntSize scaledSize(static_cast<int>(ceil(size.width() * transform.xScale())), static_cast<int>(ceil(size.height() * transform.yScale())));
- RefPtr<SkBaseDevice> device = adoptRef(m_canvas->getTopDevice()->createCompatibleDevice(SkBitmap::kARGB_8888_Config, size.width(), size.height(), opacityMode == Opaque));
- if (!device)
+ SkAlphaType alphaType = (opacityMode == Opaque) ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+ SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), alphaType);
+ RefPtr<SkSurface> skSurface = adoptRef(m_canvas->newSurface(info));
+ if (!skSurface)
return nullptr;
- OwnPtr<ImageBufferSurface> surface = adoptPtr(new CompatibleImageBufferSurface(device.release(), scaledSize, opacityMode));
+ OwnPtr<ImageBufferSurface> surface = adoptPtr(new CompatibleImageBufferSurface(skSurface.release(), scaledSize, opacityMode));
ASSERT(surface->isValid());
OwnPtr<ImageBuffer> buffer = adoptPtr(new ImageBuffer(surface.release()));
- buffer->context()->scale(FloatSize(static_cast<float>(scaledSize.width()) / size.width(),
- static_cast<float>(scaledSize.height()) / size.height()));
+ buffer->context()->scale(static_cast<float>(scaledSize.width()) / size.width(),
+ static_cast<float>(scaledSize.height()) / size.height());
return buffer.release();
}
-void GraphicsContext::addCornerArc(SkPath* path, const SkRect& rect, const IntSize& size, int startAngle)
-{
- SkIRect ir;
- int rx = SkMin32(SkScalarRound(rect.width()), size.width());
- int ry = SkMin32(SkScalarRound(rect.height()), size.height());
-
- ir.set(-rx, -ry, rx, ry);
- switch (startAngle) {
- case 0:
- ir.offset(rect.fRight - ir.fRight, rect.fBottom - ir.fBottom);
- break;
- case 90:
- ir.offset(rect.fLeft - ir.fLeft, rect.fBottom - ir.fBottom);
- break;
- case 180:
- ir.offset(rect.fLeft - ir.fLeft, rect.fTop - ir.fTop);
- break;
- case 270:
- ir.offset(rect.fRight - ir.fRight, rect.fTop - ir.fTop);
- break;
- default:
- ASSERT(0);
- }
-
- SkRect r;
- r.set(ir);
- path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false);
-}
-
void GraphicsContext::setPathFromConvexPoints(SkPath* path, size_t numPoints, const FloatPoint* points)
{
path->incReserve(numPoints);
@@ -1799,35 +1669,15 @@ void GraphicsContext::setPathFromConvexPoints(SkPath* path, size_t numPoints, co
path->setConvexity(convexity);
}
-void GraphicsContext::setupPaintCommon(SkPaint* paint) const
-{
-#if defined(SK_DEBUG)
- {
- SkPaint defaultPaint;
- SkASSERT(*paint == defaultPaint);
- }
-#endif
-
- paint->setAntiAlias(m_state->m_shouldAntialias);
-
- if (!SkXfermode::IsMode(m_state->m_xferMode.get(), SkXfermode::kSrcOver_Mode))
- paint->setXfermode(m_state->m_xferMode.get());
-
- if (m_state->m_looper)
- paint->setLooper(m_state->m_looper.get());
-
- paint->setColorFilter(m_state->m_colorFilter.get());
-}
-
void GraphicsContext::drawOuterPath(const SkPath& path, SkPaint& paint, int width)
{
#if OS(MACOSX)
paint.setAlpha(64);
paint.setStrokeWidth(width);
- paint.setPathEffect(new SkCornerPathEffect((width - 1) * 0.5f))->unref();
+ paint.setPathEffect(SkCornerPathEffect::Create((width - 1) * 0.5f))->unref();
#else
paint.setStrokeWidth(1);
- paint.setPathEffect(new SkCornerPathEffect(1))->unref();
+ paint.setPathEffect(SkCornerPathEffect::Create(1))->unref();
#endif
drawPath(path, paint);
}
@@ -1869,16 +1719,10 @@ PassRefPtr<SkColorFilter> GraphicsContext::WebCoreColorFilterToSkiaColorFilter(C
break;
}
- return 0;
+ return nullptr;
}
-#if OS(MACOSX)
-CGColorSpaceRef PLATFORM_EXPORT deviceRGBColorSpaceRef()
-{
- static CGColorSpaceRef deviceSpace = CGColorSpaceCreateDeviceRGB();
- return deviceSpace;
-}
-#else
+#if !OS(MACOSX)
void GraphicsContext::draw2xMarker(SkBitmap* bitmap, int index)
{
const SkPMColor lineColor = lineColors(index);
@@ -1970,31 +1814,10 @@ const SkPMColor GraphicsContext::antiColors2(int index)
}
#endif
-void GraphicsContext::setupShader(SkPaint* paint, Gradient* grad, Pattern* pat, SkColor color) const
-{
- RefPtr<SkShader> shader;
-
- if (grad) {
- shader = grad->shader();
- color = SK_ColorBLACK;
- } else if (pat) {
- shader = pat->shader();
- color = SK_ColorBLACK;
- paint->setFilterBitmap(imageInterpolationQuality() != InterpolationNone);
- }
-
- paint->setColor(m_state->applyAlpha(color));
-
- if (!shader)
- return;
-
- paint->setShader(shader.get());
-}
-
void GraphicsContext::didDrawTextInRect(const SkRect& textRect)
{
if (m_trackTextRegion) {
- TRACE_EVENT0("skia", "PlatformContextSkia::trackTextRegion");
+ TRACE_EVENT0("skia", "GraphicsContext::didDrawTextInRect");
m_textRegion.join(textRect);
}
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.h b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.h
index d756c011043..ab1eeccedc9 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext.h
@@ -29,19 +29,15 @@
#define GraphicsContext_h
#include "platform/PlatformExport.h"
-#include "platform/TraceEvent.h"
#include "platform/fonts/Font.h"
#include "platform/geometry/FloatRect.h"
#include "platform/graphics/DashArray.h"
-#include "platform/graphics/DrawLooper.h"
+#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/ImageBufferSurface.h"
#include "platform/graphics/ImageOrientation.h"
#include "platform/graphics/GraphicsContextAnnotation.h"
#include "platform/graphics/GraphicsContextState.h"
#include "platform/graphics/skia/OpaqueRegionSkia.h"
-#include "platform/graphics/skia/SkiaUtils.h"
-// TODO(robertphillips): replace this include with "class SkBaseDevice;"
-#include "third_party/skia/include/core/SkDevice.h"
#include "wtf/FastAllocBase.h"
#include "wtf/Forward.h"
#include "wtf/Noncopyable.h"
@@ -59,6 +55,8 @@ class DisplayList;
class ImageBuffer;
class KURL;
+typedef SkImageFilter ImageFilter;
+
class PLATFORM_EXPORT GraphicsContext {
WTF_MAKE_NONCOPYABLE(GraphicsContext); WTF_MAKE_FAST_ALLOCATED;
public:
@@ -71,99 +69,131 @@ public:
ReadWrite
};
- explicit GraphicsContext(SkCanvas*);
+ enum DisabledMode {
+ NothingDisabled = 0, // Run as normal.
+ PaintingDisabled = 1, // Do not issue painting calls to the canvas but maintain state correctly.
+ FullyDisabled = 2 // Do absolutely minimal work to remove the cost of the context from performance tests.
+ };
+
+ explicit GraphicsContext(SkCanvas*, DisabledMode = NothingDisabled);
~GraphicsContext();
- // Returns the canvas used for painting, NOT guaranteed to be non-null.
+ // Returns the canvas used for painting. Must not be called if painting is disabled.
// Accessing the backing canvas this way flushes all queued save ops,
// so it should be avoided. Use the corresponding draw/matrix/clip methods instead.
SkCanvas* canvas()
{
+ ASSERT(!paintingDisabled());
+
// Flush any pending saves.
- realizeSave(SkCanvas::kMatrixClip_SaveFlag);
+ realizeCanvasSave();
return m_canvas;
}
- const SkCanvas* canvas() const { return m_canvas; }
- bool paintingDisabled() const { return !m_canvas; }
-
- const SkBitmap* bitmap() const;
- const SkBitmap& layerBitmap(AccessMode = ReadOnly) const;
+ const SkCanvas* canvas() const
+ {
+ ASSERT(!paintingDisabled());
+ return m_canvas;
+ }
+ bool paintingDisabled() const { return m_disabledState & PaintingDisabled; }
+ bool contextDisabled() const { return m_disabledState; }
+
+ // This is just a heuristic that currently happens to work. We need either
+ // a more reliable way to know that we are recording, or (better) we need
+ // to obviate the need for this query, and address whatever the caller
+ // needed in some other way.
+ // See bug# 372110
+ bool isRecordingCanvas() const
+ {
+ return m_canvas->imageInfo().colorType() == kUnknown_SkColorType;
+ }
// ---------- State management methods -----------------
void save();
void restore();
+ unsigned saveCount() { return m_canvasStateStack.size(); }
+#if ASSERT_ENABLED
+ void disableDestructionChecks() { m_disableDestructionChecks = true; }
+#endif
- void saveLayer(const SkRect* bounds, const SkPaint*, SkCanvas::SaveFlags = SkCanvas::kARGB_ClipLayer_SaveFlag);
+ void saveLayer(const SkRect* bounds, const SkPaint*);
void restoreLayer();
- float strokeThickness() const { return m_state->m_strokeData.thickness(); }
- void setStrokeThickness(float thickness) { m_state->m_strokeData.setThickness(thickness); }
+ float strokeThickness() const { return immutableState()->strokeData().thickness(); }
+ void setStrokeThickness(float thickness) { mutableState()->setStrokeThickness(thickness); }
- StrokeStyle strokeStyle() const { return m_state->m_strokeData.style(); }
- void setStrokeStyle(StrokeStyle style) { m_state->m_strokeData.setStyle(style); }
+ StrokeStyle strokeStyle() const { return immutableState()->strokeData().style(); }
+ void setStrokeStyle(StrokeStyle style) { mutableState()->setStrokeStyle(style); }
- Color strokeColor() const { return m_state->m_strokeData.color(); }
- void setStrokeColor(const Color&);
+ Color strokeColor() const { return immutableState()->strokeData().color(); }
+ void setStrokeColor(const Color& color) { mutableState()->setStrokeColor(color); }
+ SkColor effectiveStrokeColor() const { return immutableState()->effectiveStrokeColor(); }
- Pattern* strokePattern() const { return m_state->m_strokeData.pattern(); }
+ Pattern* strokePattern() const { return immutableState()->strokeData().pattern(); }
void setStrokePattern(PassRefPtr<Pattern>);
- Gradient* strokeGradient() const { return m_state->m_strokeData.gradient(); }
+ Gradient* strokeGradient() const { return immutableState()->strokeData().gradient(); }
void setStrokeGradient(PassRefPtr<Gradient>);
- void setLineCap(LineCap cap) { m_state->m_strokeData.setLineCap(cap); }
- void setLineDash(const DashArray& dashes, float dashOffset) { m_state->m_strokeData.setLineDash(dashes, dashOffset); }
- void setLineJoin(LineJoin join) { m_state->m_strokeData.setLineJoin(join); }
- void setMiterLimit(float limit) { m_state->m_strokeData.setMiterLimit(limit); }
+ void setLineCap(LineCap cap) { mutableState()->setLineCap(cap); }
+ void setLineDash(const DashArray& dashes, float dashOffset) { mutableState()->setLineDash(dashes, dashOffset); }
+ void setLineJoin(LineJoin join) { mutableState()->setLineJoin(join); }
+ void setMiterLimit(float limit) { mutableState()->setMiterLimit(limit); }
- WindRule fillRule() const { return m_state->m_fillRule; }
- void setFillRule(WindRule fillRule) { m_state->m_fillRule = fillRule; }
+ WindRule fillRule() const { return immutableState()->fillRule(); }
+ void setFillRule(WindRule fillRule) { mutableState()->setFillRule(fillRule); }
- Color fillColor() const { return m_state->m_fillColor; }
- void setFillColor(const Color&);
- SkColor effectiveFillColor() const { return m_state->applyAlpha(m_state->m_fillColor.rgb()); }
+ Color fillColor() const { return immutableState()->fillColor(); }
+ void setFillColor(const Color& color) { mutableState()->setFillColor(color); }
+ SkColor effectiveFillColor() const { return immutableState()->effectiveFillColor(); }
void setFillPattern(PassRefPtr<Pattern>);
- Pattern* fillPattern() const { return m_state->m_fillPattern.get(); }
+ Pattern* fillPattern() const { return immutableState()->fillPattern(); }
void setFillGradient(PassRefPtr<Gradient>);
- Gradient* fillGradient() const { return m_state->m_fillGradient.get(); }
-
- SkDrawLooper* drawLooper() const { return m_state->m_looper.get(); }
- SkColor effectiveStrokeColor() const { return m_state->applyAlpha(m_state->m_strokeData.color().rgb()); }
+ Gradient* fillGradient() const { return immutableState()->fillGradient(); }
- int getNormalizedAlpha() const;
+ SkDrawLooper* drawLooper() const { return immutableState()->drawLooper(); }
- bool getClipBounds(SkRect* bounds) const;
bool getTransformedClipBounds(FloatRect* bounds) const;
SkMatrix getTotalMatrix() const;
- bool isPrintingDevice() const;
- void setShouldAntialias(bool antialias) { m_state->m_shouldAntialias = antialias; }
- bool shouldAntialias() const { return m_state->m_shouldAntialias; }
+ void setShouldAntialias(bool antialias) { mutableState()->setShouldAntialias(antialias); }
+ bool shouldAntialias() const { return immutableState()->shouldAntialias(); }
+
+ // Disable the anti-aliasing optimization for scales/multiple-of-90-degrees
+ // rotations of thin ("hairline") images.
+ // Note: This will only be reliable when the device pixel scale/ratio is
+ // fixed (e.g. when drawing to context backed by an ImageBuffer).
+ void disableAntialiasingOptimizationForHairlineImages() { ASSERT(!isRecording()); m_antialiasHairlineImages = true; }
+ bool shouldAntialiasHairlineImages() const { return m_antialiasHairlineImages; }
- void setShouldClampToSourceRect(bool clampToSourceRect) { m_state->m_shouldClampToSourceRect = clampToSourceRect; }
- bool shouldClampToSourceRect() const { return m_state->m_shouldClampToSourceRect; }
+ void setShouldClampToSourceRect(bool clampToSourceRect) { mutableState()->setShouldClampToSourceRect(clampToSourceRect); }
+ bool shouldClampToSourceRect() const { return immutableState()->shouldClampToSourceRect(); }
- void setShouldSmoothFonts(bool smoothFonts) { m_state->m_shouldSmoothFonts = smoothFonts; }
- bool shouldSmoothFonts() const { return m_state->m_shouldSmoothFonts; }
+ void setShouldSmoothFonts(bool smoothFonts) { mutableState()->setShouldSmoothFonts(smoothFonts); }
+ bool shouldSmoothFonts() const { return immutableState()->shouldSmoothFonts(); }
// Turn off LCD text for the paint if not supported on this context.
void adjustTextRenderMode(SkPaint*);
bool couldUseLCDRenderedText();
- TextDrawingModeFlags textDrawingMode() const { return m_state->m_textDrawingMode; }
- void setTextDrawingMode(TextDrawingModeFlags mode) { m_state->m_textDrawingMode = mode; }
+ void setTextDrawingMode(TextDrawingModeFlags mode) { mutableState()->setTextDrawingMode(mode); }
+ TextDrawingModeFlags textDrawingMode() const { return immutableState()->textDrawingMode(); }
- void setAlpha(float alpha) { m_state->m_alpha = alpha; }
+ void setAlphaAsFloat(float alpha) { mutableState()->setAlphaAsFloat(alpha);}
+ int getNormalizedAlpha() const
+ {
+ int alpha = immutableState()->alpha();
+ return alpha > 255 ? 255 : alpha;
+ }
- void setImageInterpolationQuality(InterpolationQuality quality) { m_state->m_interpolationQuality = quality; }
- InterpolationQuality imageInterpolationQuality() const { return m_state->m_interpolationQuality; }
+ void setImageInterpolationQuality(InterpolationQuality quality) { mutableState()->setInterpolationQuality(quality); }
+ InterpolationQuality imageInterpolationQuality() const { return immutableState()->interpolationQuality(); }
void setCompositeOperation(CompositeOperator, blink::WebBlendMode = blink::WebBlendModeNormal);
- CompositeOperator compositeOperation() const { return m_state->m_compositeOperator; }
- blink::WebBlendMode blendModeOperation() const { return m_state->m_blendMode; }
+ CompositeOperator compositeOperation() const { return immutableState()->compositeOperator(); }
+ blink::WebBlendMode blendModeOperation() const { return immutableState()->blendMode(); }
// Change the way document markers are rendered.
// Any deviceScaleFactor higher than 1.5 is enough to justify setting this flag.
@@ -171,7 +201,7 @@ public:
// If true we are (most likely) rendering to a web page and the
// canvas has been prepared with an opaque background. If false,
- // the canvas may havbe transparency (as is the case when rendering
+ // the canvas may have transparency (as is the case when rendering
// to a canvas object).
void setCertainlyOpaque(bool isOpaque) { m_isCertainlyOpaque = isOpaque; }
bool isCertainlyOpaque() const { return m_isCertainlyOpaque; }
@@ -206,16 +236,13 @@ public:
// ---------- End state management methods -----------------
// Get the contents of the image buffer
- bool readPixels(SkBitmap*, int, int, SkCanvas::Config8888 = SkCanvas::kNative_Premul_Config8888);
+ bool readPixels(const SkImageInfo&, void* pixels, size_t rowBytes, int x, int y);
- // Sets up the paint for the current fill style.
- void setupPaintForFilling(SkPaint*) const;
+ // Get the current fill style.
+ const SkPaint& fillPaint() const { return immutableState()->fillPaint(); }
- // Sets up the paint for stroking. Returns a float representing the
- // effective width of the pen. If a non-zero length is provided, the
- // number of dashes/dots on a dashed/dotted line will be adjusted to
- // start and end that length with a dash/dot.
- float setupPaintForStroking(SkPaint*, int length = 0) const;
+ // Get the current stroke style.
+ const SkPaint& strokePaint() const { return immutableState()->strokePaint(); }
// These draw methods will do both stroking and filling.
// FIXME: ...except drawRect(), which fills properly but always strokes
@@ -223,7 +250,6 @@ public:
// stroke color).
void drawRect(const IntRect&);
void drawLine(const IntPoint&, const IntPoint&);
- void drawEllipse(const IntRect&);
void drawConvexPolygon(size_t numPoints, const FloatPoint*, bool shouldAntialias = false);
void fillPath(const Path&);
@@ -240,33 +266,33 @@ public:
void clearRect(const FloatRect&);
+ void strokeRect(const FloatRect&);
void strokeRect(const FloatRect&, float lineWidth);
+ void fillBetweenRoundedRects(const IntRect&, const IntSize& outerTopLeft, const IntSize& outerTopRight, const IntSize& outerBottomLeft, const IntSize& outerBottomRight,
+ const IntRect&, const IntSize& innerTopLeft, const IntSize& innerTopRight, const IntSize& innerBottomLeft, const IntSize& innerBottomRight, const Color&);
+ void fillBetweenRoundedRects(const RoundedRect&, const RoundedRect&, const Color&);
+
void drawDisplayList(DisplayList*);
void drawImage(Image*, const IntPoint&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
- void drawImage(Image*, const IntRect&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation, bool useLowQualityScale = false);
- void drawImage(Image*, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
+ void drawImage(Image*, const IntRect&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
void drawImage(Image*, const FloatRect& destRect);
- void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation, bool useLowQualityScale = false);
- void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator, blink::WebBlendMode, RespectImageOrientationEnum = DoNotRespectImageOrientation, bool useLowQualityScale = false);
+ void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
+ void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator, blink::WebBlendMode, RespectImageOrientationEnum = DoNotRespectImageOrientation);
void drawTiledImage(Image*, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
- CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false, blink::WebBlendMode = blink::WebBlendModeNormal, const IntSize& repeatSpacing = IntSize());
+ CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal, const IntSize& repeatSpacing = IntSize());
void drawTiledImage(Image*, const IntRect& destRect, const IntRect& srcRect,
const FloatSize& tileScaleFactor, Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
- CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ CompositeOperator = CompositeSourceOver);
- void drawImageBuffer(ImageBuffer*, const IntPoint&, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal);
- void drawImageBuffer(ImageBuffer*, const IntRect&, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal, bool useLowQualityScale = false);
- void drawImageBuffer(ImageBuffer*, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal);
- void drawImageBuffer(ImageBuffer*, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal, bool useLowQualityScale = false);
- void drawImageBuffer(ImageBuffer*, const FloatRect& destRect);
- void drawImageBuffer(ImageBuffer*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal, bool useLowQualityScale = false);
+ void drawImageBuffer(ImageBuffer*, const FloatRect& destRect, const FloatRect* srcRect = 0, CompositeOperator = CompositeSourceOver);
// These methods write to the canvas and modify the opaque region, if tracked.
// Also drawLine(const IntPoint& point1, const IntPoint& point2) and fillRoundedRect
- void writePixels(const SkBitmap&, int x, int y, SkCanvas::Config8888 = SkCanvas::kNative_Premul_Config8888);
+ void writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
+ void writePixels(const SkBitmap&, int x, int y);
void drawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint* = 0);
void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint* = 0);
void drawOval(const SkRect&, const SkPaint&);
@@ -278,17 +304,15 @@ public:
void didDrawRect(const SkRect&, const SkPaint&, const SkBitmap* = 0);
void drawRect(const SkRect&, const SkPaint&);
void drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkRect& textRect, const SkPaint&);
- void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkRect& textRect, const SkPaint&);
- void drawTextOnPath(const void* text, size_t byteLength, const SkPath&, const SkRect& textRect, const SkMatrix*, const SkPaint&);
- void clip(const IntRect& rect) { clip(FloatRect(rect)); }
+ void clip(const IntRect& rect) { clipRect(rect); }
void clip(const FloatRect& rect) { clipRect(rect); }
- void clipRoundedRect(const RoundedRect&);
+ void clipRoundedRect(const RoundedRect&, SkRegion::Op = SkRegion::kIntersect_Op);
void clipOut(const IntRect& rect) { clipRect(rect, NotAntiAliased, SkRegion::kDifference_Op); }
void clipOutRoundedRect(const RoundedRect&);
void clipPath(const Path&, WindRule = RULE_EVENODD);
void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true);
- bool clipRect(const SkRect&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
+ void clipRect(const SkRect&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
void drawText(const Font&, const TextRunPaintInfo&, const FloatPoint&);
void drawEmphasisMarks(const Font&, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&);
@@ -303,9 +327,12 @@ public:
void drawLineForDocumentMarker(const FloatPoint&, float width, DocumentMarkerLineStyle);
void beginTransparencyLayer(float opacity, const FloatRect* = 0);
- void beginLayer(float opacity, CompositeOperator, const FloatRect* = 0, ColorFilter = ColorFilterNone);
+ void beginLayer(float opacity, CompositeOperator, const FloatRect* = 0, ColorFilter = ColorFilterNone, ImageFilter* = 0);
void endLayer();
+ void beginCull(const FloatRect&);
+ void endCull();
+
// Instead of being dispatched to the active canvas, draw commands following beginRecording()
// are stored in a display list that can be replayed at a later time.
void beginRecording(const FloatRect& bounds);
@@ -313,13 +340,14 @@ public:
bool hasShadow() const;
void setShadow(const FloatSize& offset, float blur, const Color&,
- DrawLooper::ShadowTransformMode = DrawLooper::ShadowRespectsTransforms,
- DrawLooper::ShadowAlphaMode = DrawLooper::ShadowRespectsAlpha);
+ DrawLooperBuilder::ShadowTransformMode = DrawLooperBuilder::ShadowRespectsTransforms,
+ DrawLooperBuilder::ShadowAlphaMode = DrawLooperBuilder::ShadowRespectsAlpha);
void clearShadow() { clearDrawLooper(); }
// It is assumed that this draw looper is used only for shadows
// (i.e. a draw looper is set if and only if there is a shadow).
- void setDrawLooper(const DrawLooper&);
+ // The builder passed into this method will be destroyed.
+ void setDrawLooper(PassOwnPtr<DrawLooperBuilder>);
void clearDrawLooper();
void drawFocusRing(const Vector<IntRect>&, int width, int offset, const Color&);
@@ -342,20 +370,21 @@ public:
void clipOut(const Path&);
// ---------- Transformation methods -----------------
- enum IncludeDeviceScale { DefinitelyIncludeDeviceScale, PossiblyIncludeDeviceScale };
- AffineTransform getCTM(IncludeDeviceScale includeScale = PossiblyIncludeDeviceScale) const;
+ // Note that the getCTM method returns only the current transform from Blink's perspective,
+ // which is not the final transform used to place content on screen. It cannot be relied upon
+ // for testing where a point will appear on screen or how large it will be.
+ AffineTransform getCTM() const;
void concatCTM(const AffineTransform& affine) { concat(affineTransformToSkMatrix(affine)); }
void setCTM(const AffineTransform& affine) { setMatrix(affineTransformToSkMatrix(affine)); }
void setMatrix(const SkMatrix&);
- void scale(const FloatSize&);
+ void scale(float x, float y);
void rotate(float angleInRadians);
- void translate(const FloatSize& size) { translate(size.width(), size.height()); }
void translate(float x, float y);
// This function applies the device scale factor to the context, making the context capable of
// acting as a base-level context for a HiDPI environment.
- void applyDeviceScaleFactor(float deviceScaleFactor) { scale(FloatSize(deviceScaleFactor, deviceScaleFactor)); }
+ void applyDeviceScaleFactor(float deviceScaleFactor) { scale(deviceScaleFactor, deviceScaleFactor); }
// ---------- End transformation methods -----------------
// URL drawing
@@ -374,7 +403,14 @@ public:
void endAnnotation();
private:
- static void addCornerArc(SkPath*, const SkRect&, const IntSize&, int);
+ const GraphicsContextState* immutableState() const { return m_paintState; }
+
+ GraphicsContextState* mutableState()
+ {
+ realizePaintSave();
+ return m_paintState;
+ }
+
static void setPathFromConvexPoints(SkPath*, size_t, const FloatPoint*);
static void setRadii(SkVector*, IntSize, IntSize, IntSize, IntSize);
@@ -391,91 +427,93 @@ private:
static void draw2xMarker(SkBitmap*, int);
#endif
- // Return value % max, but account for value possibly being negative.
- static int fastMod(int value, int max)
- {
- bool isNeg = false;
- if (value < 0) {
- value = -value;
- isNeg = true;
- }
- if (value >= max)
- value %= max;
- if (isNeg)
- value = -value;
- return value;
- }
-
- // Sets up the common flags on a paint for antialiasing, effects, etc.
- // This is implicitly called by setupPaintFill and setupPaintStroke, but
- // you may wish to call it directly sometimes if you don't want that other
- // behavior.
- void setupPaintCommon(SkPaint*) const;
-
// Helpers for drawing a focus ring (drawFocusRing)
void drawOuterPath(const SkPath&, SkPaint&, int);
void drawInnerPath(const SkPath&, SkPaint&, int);
// SkCanvas wrappers.
- bool isDrawingToLayer() const { return m_canvas->isDrawingToLayer(); }
-
- bool clipPath(const SkPath&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
- bool clipRRect(const SkRRect&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
-
- bool concat(const SkMatrix&);
+ void clipPath(const SkPath&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
+ void clipRRect(const SkRRect&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
- // common code between setupPaintFor[Filling,Stroking]
- void setupShader(SkPaint*, Gradient*, Pattern*, SkColor) const;
+ void concat(const SkMatrix&);
- // Apply deferred saves
- void realizeSave(SkCanvas::SaveFlags flags)
+ // Apply deferred paint state saves
+ void realizePaintSave()
{
- if (m_deferredSaveFlags & flags) {
- m_canvas->save((SkCanvas::SaveFlags)m_deferredSaveFlags);
- m_deferredSaveFlags = 0;
+ if (contextDisabled())
+ return;
+
+ if (m_paintState->saveCount()) {
+ m_paintState->decrementSaveCount();
+ ++m_paintStateIndex;
+ if (m_paintStateStack.size() == m_paintStateIndex) {
+ m_paintStateStack.append(GraphicsContextState::createAndCopy(*m_paintState));
+ m_paintState = m_paintStateStack[m_paintStateIndex].get();
+ } else {
+ GraphicsContextState* priorPaintState = m_paintState;
+ m_paintState = m_paintStateStack[m_paintStateIndex].get();
+ m_paintState->copy(*priorPaintState);
+ }
}
}
+ // Apply deferred canvas state saves
+ void realizeCanvasSave()
+ {
+ if (!m_pendingCanvasSave || contextDisabled())
+ return;
+
+ m_canvas->save();
+ m_pendingCanvasSave = false;
+ }
+
void didDrawTextInRect(const SkRect& textRect);
void fillRectWithRoundedHole(const IntRect&, const RoundedRect& roundedHoleRect, const Color&);
bool isRecording() const;
- // null indicates painting is disabled. Never delete this object.
+ // null indicates painting is contextDisabled. Never delete this object.
SkCanvas* m_canvas;
- // Pointer to the current drawing state. This is a cached value of m_stateStack.last().
- GraphicsContextState* m_state;
- // States stack. Enables local drawing state change with save()/restore() calls.
- // Use OwnPtr to avoid copying the large state structure.
- Vector<OwnPtr<GraphicsContextState> > m_stateStack;
-
- // Currently pending save flags.
- // FIXME: While defined as a bitmask of SkCanvas::SaveFlags, this is mostly used as a bool.
- // It will come in handy when adding granular save() support (clip vs. matrix vs. paint).
- // crbug.com/233713
- struct DeferredSaveState;
- unsigned m_deferredSaveFlags;
- Vector<DeferredSaveState> m_saveStateStack;
+ // Paint states stack. Enables local drawing state change with save()/restore() calls.
+ // This state controls the appearance of drawn content.
+ // We do not delete from this stack to avoid memory churn.
+ Vector<OwnPtr<GraphicsContextState> > m_paintStateStack;
+ // Current index on the stack. May not be the last thing on the stack.
+ unsigned m_paintStateIndex;
+ // Raw pointer to the current state.
+ GraphicsContextState* m_paintState;
+
+ // Currently pending save flags for Skia Canvas state.
+ // Canvas state includes the canavs, it's matrix and clips. Think of it as _where_
+ // the draw operations will happen.
+ struct CanvasSaveState;
+ Vector<CanvasSaveState> m_canvasStateStack;
+ bool m_pendingCanvasSave;
AnnotationModeFlags m_annotationMode;
struct RecordingState;
Vector<RecordingState> m_recordingStateStack;
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
unsigned m_annotationCount;
unsigned m_layerCount;
+ bool m_disableDestructionChecks;
#endif
// Tracks the region painted opaque via the GraphicsContext.
OpaqueRegionSkia m_opaqueRegion;
- bool m_trackOpaqueRegion : 1;
// Tracks the region where text is painted via the GraphicsContext.
- bool m_trackTextRegion : 1;
SkRect m_textRegion;
+ unsigned m_disabledState;
+
+ // Activation for the above region tracking features
+ bool m_trackOpaqueRegion : 1;
+ bool m_trackTextRegion : 1;
+
// Are we on a high DPI display? If so, spelling and grammar markers are larger.
bool m_useHighResMarker : 1;
// FIXME: Make this go away: crbug.com/236892
@@ -483,6 +521,7 @@ private:
bool m_accelerated : 1;
bool m_isCertainlyOpaque : 1;
bool m_printing : 1;
+ bool m_antialiasHairlineImages : 1;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3D.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3D.cpp
deleted file mode 100644
index 7981c3a640b..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3D.cpp
+++ /dev/null
@@ -1,944 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2010 Mozilla Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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"
-
-#include "platform/graphics/GraphicsContext3D.h"
-#include "platform/CheckedInt.h"
-#include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/ImageBuffer.h"
-#include "platform/graphics/ImageObserver.h"
-#include "platform/graphics/gpu/DrawingBuffer.h"
-#include "platform/image-decoders/ImageDecoder.h"
-#include "third_party/skia/include/gpu/GrContext.h"
-#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
-#include "wtf/CPU.h"
-#include "wtf/text/CString.h"
-#include "wtf/text/StringHash.h"
-
-#include "public/platform/Platform.h"
-#include "public/platform/WebGraphicsContext3D.h"
-#include "public/platform/WebGraphicsContext3DProvider.h"
-
-namespace WebCore {
-
-namespace {
-
-void getDrawingParameters(DrawingBuffer* drawingBuffer, blink::WebGraphicsContext3D* graphicsContext3D,
- Platform3DObject* frameBufferId, int* width, int* height)
-{
- ASSERT(drawingBuffer);
- *frameBufferId = drawingBuffer->framebuffer();
- *width = drawingBuffer->size().width();
- *height = drawingBuffer->size().height();
-}
-
-} // anonymous namespace
-
-GraphicsContext3D::GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3D> webContext, bool preserveDrawingBuffer)
- : m_impl(webContext.get())
- , m_ownedWebContext(webContext)
- , m_initializedAvailableExtensions(false)
- , m_layerComposited(false)
- , m_preserveDrawingBuffer(preserveDrawingBuffer)
- , m_packAlignment(4)
- , m_resourceSafety(ResourceSafetyUnknown)
- , m_grContext(0)
-{
-}
-
-GraphicsContext3D::GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3DProvider> provider, bool preserveDrawingBuffer)
- : m_provider(provider)
- , m_impl(m_provider->context3d())
- , m_initializedAvailableExtensions(false)
- , m_layerComposited(false)
- , m_preserveDrawingBuffer(preserveDrawingBuffer)
- , m_packAlignment(4)
- , m_resourceSafety(ResourceSafetyUnknown)
- , m_grContext(m_provider->grContext())
-{
-}
-
-GraphicsContext3D::~GraphicsContext3D()
-{
- setContextLostCallback(nullptr);
- setErrorMessageCallback(nullptr);
-}
-
-// Macros to assist in delegating from GraphicsContext3D to
-// WebGraphicsContext3D.
-
-#define DELEGATE_TO_WEBCONTEXT(name) \
-void GraphicsContext3D::name() \
-{ \
- m_impl->name(); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_R(name, rt) \
-rt GraphicsContext3D::name() \
-{ \
- return m_impl->name(); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_1(name, t1) \
-void GraphicsContext3D::name(t1 a1) \
-{ \
- m_impl->name(a1); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_1R(name, t1, rt) \
-rt GraphicsContext3D::name(t1 a1) \
-{ \
- return m_impl->name(a1); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_2(name, t1, t2) \
-void GraphicsContext3D::name(t1 a1, t2 a2) \
-{ \
- m_impl->name(a1, a2); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_2R(name, t1, t2, rt) \
-rt GraphicsContext3D::name(t1 a1, t2 a2) \
-{ \
- return m_impl->name(a1, a2); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_3(name, t1, t2, t3) \
-void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
-{ \
- m_impl->name(a1, a2, a3); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_3R(name, t1, t2, t3, rt) \
-rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
-{ \
- return m_impl->name(a1, a2, a3); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_4(name, t1, t2, t3, t4) \
-void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
-{ \
- m_impl->name(a1, a2, a3, a4); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_4R(name, t1, t2, t3, t4, rt) \
-rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
-{ \
- return m_impl->name(a1, a2, a3, a4); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_5(name, t1, t2, t3, t4, t5) \
-void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
-{ \
- m_impl->name(a1, a2, a3, a4, a5); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_6(name, t1, t2, t3, t4, t5, t6) \
-void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
-{ \
- m_impl->name(a1, a2, a3, a4, a5, a6); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_6R(name, t1, t2, t3, t4, t5, t6, rt) \
-rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
-{ \
- return m_impl->name(a1, a2, a3, a4, a5, a6); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_7(name, t1, t2, t3, t4, t5, t6, t7) \
-void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) \
-{ \
- m_impl->name(a1, a2, a3, a4, a5, a6, a7); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_7R(name, t1, t2, t3, t4, t5, t6, t7, rt) \
-rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) \
-{ \
- return m_impl->name(a1, a2, a3, a4, a5, a6, a7); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_8(name, t1, t2, t3, t4, t5, t6, t7, t8) \
-void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) \
-{ \
- m_impl->name(a1, a2, a3, a4, a5, a6, a7, a8); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_9(name, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
-void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8, t9 a9) \
-{ \
- m_impl->name(a1, a2, a3, a4, a5, a6, a7, a8, a9); \
-}
-
-#define DELEGATE_TO_WEBCONTEXT_9R(name, t1, t2, t3, t4, t5, t6, t7, t8, t9, rt) \
-rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8, t9 a9) \
-{ \
- return m_impl->name(a1, a2, a3, a4, a5, a6, a7, a8, a9); \
-}
-
-class GraphicsContext3DContextLostCallbackAdapter : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
-public:
- GraphicsContext3DContextLostCallbackAdapter(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callback)
- : m_contextLostCallback(callback) { }
- virtual ~GraphicsContext3DContextLostCallbackAdapter() { }
-
- virtual void onContextLost()
- {
- if (m_contextLostCallback)
- m_contextLostCallback->onContextLost();
- }
-private:
- OwnPtr<GraphicsContext3D::ContextLostCallback> m_contextLostCallback;
-};
-
-class GraphicsContext3DErrorMessageCallbackAdapter : public blink::WebGraphicsContext3D::WebGraphicsErrorMessageCallback {
-public:
- GraphicsContext3DErrorMessageCallbackAdapter(PassOwnPtr<GraphicsContext3D::ErrorMessageCallback> callback)
- : m_errorMessageCallback(callback) { }
- virtual ~GraphicsContext3DErrorMessageCallbackAdapter() { }
-
- virtual void onErrorMessage(const blink::WebString& message, blink::WGC3Dint id)
- {
- if (m_errorMessageCallback)
- m_errorMessageCallback->onErrorMessage(message, id);
- }
-private:
- OwnPtr<GraphicsContext3D::ErrorMessageCallback> m_errorMessageCallback;
-};
-
-void GraphicsContext3D::setContextLostCallback(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callback)
-{
- if (m_ownedWebContext) {
- m_contextLostCallbackAdapter = adoptPtr(new GraphicsContext3DContextLostCallbackAdapter(callback));
- m_ownedWebContext->setContextLostCallback(m_contextLostCallbackAdapter.get());
- }
-}
-
-void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<GraphicsContext3D::ErrorMessageCallback> callback)
-{
- if (m_ownedWebContext) {
- m_errorMessageCallbackAdapter = adoptPtr(new GraphicsContext3DErrorMessageCallbackAdapter(callback));
- m_ownedWebContext->setErrorMessageCallback(m_errorMessageCallbackAdapter.get());
- }
-}
-
-PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs)
-{
- blink::WebGraphicsContext3D::Attributes webAttributes;
- webAttributes.alpha = attrs.alpha;
- webAttributes.depth = attrs.depth;
- webAttributes.stencil = attrs.stencil;
- webAttributes.antialias = attrs.antialias;
- webAttributes.premultipliedAlpha = attrs.premultipliedAlpha;
- webAttributes.noExtensions = attrs.noExtensions;
- webAttributes.shareResources = attrs.shareResources;
- webAttributes.preferDiscreteGPU = attrs.preferDiscreteGPU;
- webAttributes.failIfMajorPerformanceCaveat = attrs.failIfMajorPerformanceCaveat;
- webAttributes.topDocumentURL = attrs.topDocumentURL.string();
-
- OwnPtr<blink::WebGraphicsContext3D> webContext = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(webAttributes));
- if (!webContext)
- return 0;
-
- return GraphicsContext3D::createGraphicsContextFromWebContext(webContext.release(), attrs.preserveDrawingBuffer);
-}
-
-PassRefPtr<GraphicsContext3D> GraphicsContext3D::createGraphicsContextFromProvider(PassOwnPtr<blink::WebGraphicsContext3DProvider> provider, bool preserveDrawingBuffer)
-{
- RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(provider, preserveDrawingBuffer));
- return context.release();
-}
-
-PassRefPtr<GraphicsContext3D> GraphicsContext3D::createGraphicsContextFromWebContext(PassOwnPtr<blink::WebGraphicsContext3D> webContext, bool preserveDrawingBuffer)
-{
- RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(webContext, preserveDrawingBuffer));
- return context.release();
-}
-
-GrContext* GraphicsContext3D::grContext()
-{
- return m_grContext;
-}
-
-DELEGATE_TO_WEBCONTEXT_R(makeContextCurrent, bool)
-DELEGATE_TO_WEBCONTEXT_R(lastFlushID, uint32_t)
-
-DELEGATE_TO_WEBCONTEXT_1(activeTexture, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_2(attachShader, Platform3DObject, Platform3DObject)
-
-void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name)
-{
- m_impl->bindAttribLocation(program, index, name.utf8().data());
-}
-
-DELEGATE_TO_WEBCONTEXT_2(bindBuffer, GC3Denum, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_2(bindFramebuffer, GC3Denum, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_2(bindRenderbuffer, GC3Denum, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_2(bindTexture, GC3Denum, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_4(blendColor, GC3Dclampf, GC3Dclampf, GC3Dclampf, GC3Dclampf)
-DELEGATE_TO_WEBCONTEXT_1(blendEquation, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_2(blendEquationSeparate, GC3Denum, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_2(blendFunc, GC3Denum, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_4(blendFuncSeparate, GC3Denum, GC3Denum, GC3Denum, GC3Denum)
-
-void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
-{
- bufferData(target, size, 0, usage);
-}
-
-DELEGATE_TO_WEBCONTEXT_4(bufferData, GC3Denum, GC3Dsizeiptr, const void*, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_4(bufferSubData, GC3Denum, GC3Dintptr, GC3Dsizeiptr, const void*)
-
-DELEGATE_TO_WEBCONTEXT_1R(checkFramebufferStatus, GC3Denum, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_1(clear, GC3Dbitfield)
-DELEGATE_TO_WEBCONTEXT_4(clearColor, GC3Dclampf, GC3Dclampf, GC3Dclampf, GC3Dclampf)
-DELEGATE_TO_WEBCONTEXT_1(clearDepth, GC3Dclampf)
-DELEGATE_TO_WEBCONTEXT_1(clearStencil, GC3Dint)
-DELEGATE_TO_WEBCONTEXT_4(colorMask, GC3Dboolean, GC3Dboolean, GC3Dboolean, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_1(compileShader, Platform3DObject)
-
-DELEGATE_TO_WEBCONTEXT_8(compressedTexImage2D, GC3Denum, GC3Dint, GC3Denum, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, const void*)
-DELEGATE_TO_WEBCONTEXT_9(compressedTexSubImage2D, GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Denum, GC3Dsizei, const void*)
-DELEGATE_TO_WEBCONTEXT_8(copyTexImage2D, GC3Denum, GC3Dint, GC3Denum, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Dint)
-DELEGATE_TO_WEBCONTEXT_8(copyTexSubImage2D, GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
-DELEGATE_TO_WEBCONTEXT_1(cullFace, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_1(depthFunc, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_1(depthMask, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_2(depthRange, GC3Dclampf, GC3Dclampf)
-DELEGATE_TO_WEBCONTEXT_2(detachShader, Platform3DObject, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_1(disable, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_1(disableVertexAttribArray, GC3Duint)
-DELEGATE_TO_WEBCONTEXT_3(drawArrays, GC3Denum, GC3Dint, GC3Dsizei)
-DELEGATE_TO_WEBCONTEXT_4(drawElements, GC3Denum, GC3Dsizei, GC3Denum, GC3Dintptr)
-
-DELEGATE_TO_WEBCONTEXT_1(enable, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_1(enableVertexAttribArray, GC3Duint)
-DELEGATE_TO_WEBCONTEXT(finish)
-DELEGATE_TO_WEBCONTEXT(flush)
-DELEGATE_TO_WEBCONTEXT_4(framebufferRenderbuffer, GC3Denum, GC3Denum, GC3Denum, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_5(framebufferTexture2D, GC3Denum, GC3Denum, GC3Denum, Platform3DObject, GC3Dint)
-DELEGATE_TO_WEBCONTEXT_1(frontFace, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_1(generateMipmap, GC3Denum)
-
-bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
-{
- blink::WebGraphicsContext3D::ActiveInfo webInfo;
- if (!m_impl->getActiveAttrib(program, index, webInfo))
- return false;
- info.name = webInfo.name;
- info.type = webInfo.type;
- info.size = webInfo.size;
- return true;
-}
-
-bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
-{
- blink::WebGraphicsContext3D::ActiveInfo webInfo;
- if (!m_impl->getActiveUniform(program, index, webInfo))
- return false;
- info.name = webInfo.name;
- info.type = webInfo.type;
- info.size = webInfo.size;
- return true;
-}
-
-DELEGATE_TO_WEBCONTEXT_4(getAttachedShaders, Platform3DObject, GC3Dsizei, GC3Dsizei*, Platform3DObject*)
-
-GC3Dint GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
-{
- return m_impl->getAttribLocation(program, name.utf8().data());
-}
-
-DELEGATE_TO_WEBCONTEXT_2(getBooleanv, GC3Denum, GC3Dboolean*)
-DELEGATE_TO_WEBCONTEXT_3(getBufferParameteriv, GC3Denum, GC3Denum, GC3Dint*)
-
-GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
-{
- blink::WebGraphicsContext3D::Attributes webAttributes = m_impl->getContextAttributes();
- GraphicsContext3D::Attributes attributes;
- attributes.alpha = webAttributes.alpha;
- attributes.depth = webAttributes.depth;
- attributes.stencil = webAttributes.stencil;
- attributes.antialias = webAttributes.antialias;
- attributes.premultipliedAlpha = webAttributes.premultipliedAlpha;
- attributes.preserveDrawingBuffer = m_preserveDrawingBuffer;
- attributes.preferDiscreteGPU = webAttributes.preferDiscreteGPU;
- return attributes;
-}
-
-DELEGATE_TO_WEBCONTEXT_R(getError, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_2(getFloatv, GC3Denum, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_4(getFramebufferAttachmentParameteriv, GC3Denum, GC3Denum, GC3Denum, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_2(getIntegerv, GC3Denum, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_3(getProgramiv, Platform3DObject, GC3Denum, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_1R(getProgramInfoLog, Platform3DObject, String)
-DELEGATE_TO_WEBCONTEXT_3(getRenderbufferParameteriv, GC3Denum, GC3Denum, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_3(getShaderiv, Platform3DObject, GC3Denum, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_1R(getShaderInfoLog, Platform3DObject, String)
-DELEGATE_TO_WEBCONTEXT_4(getShaderPrecisionFormat, GC3Denum, GC3Denum, GC3Dint*, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_1R(getShaderSource, Platform3DObject, String)
-DELEGATE_TO_WEBCONTEXT_1R(getString, GC3Denum, String)
-DELEGATE_TO_WEBCONTEXT_3(getTexParameterfv, GC3Denum, GC3Denum, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_3(getTexParameteriv, GC3Denum, GC3Denum, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_3(getUniformfv, Platform3DObject, GC3Dint, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_3(getUniformiv, Platform3DObject, GC3Dint, GC3Dint*)
-
-GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
-{
- return m_impl->getUniformLocation(program, name.utf8().data());
-}
-
-DELEGATE_TO_WEBCONTEXT_3(getVertexAttribfv, GC3Duint, GC3Denum, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_3(getVertexAttribiv, GC3Duint, GC3Denum, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_2R(getVertexAttribOffset, GC3Duint, GC3Denum, GC3Dsizeiptr)
-
-DELEGATE_TO_WEBCONTEXT_2(hint, GC3Denum, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_1R(isBuffer, Platform3DObject, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_1R(isEnabled, GC3Denum, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_1R(isFramebuffer, Platform3DObject, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_1R(isProgram, Platform3DObject, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_1R(isRenderbuffer, Platform3DObject, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_1R(isShader, Platform3DObject, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_1R(isTexture, Platform3DObject, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_1(lineWidth, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_1(linkProgram, Platform3DObject)
-
-void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
-{
- if (pname == GL_PACK_ALIGNMENT)
- m_packAlignment = param;
- m_impl->pixelStorei(pname, param);
-}
-
-DELEGATE_TO_WEBCONTEXT_2(polygonOffset, GC3Dfloat, GC3Dfloat)
-
-DELEGATE_TO_WEBCONTEXT_7(readPixels, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, void*)
-
-DELEGATE_TO_WEBCONTEXT(releaseShaderCompiler)
-DELEGATE_TO_WEBCONTEXT_4(renderbufferStorage, GC3Denum, GC3Denum, GC3Dsizei, GC3Dsizei)
-DELEGATE_TO_WEBCONTEXT_2(sampleCoverage, GC3Dclampf, GC3Dboolean)
-DELEGATE_TO_WEBCONTEXT_4(scissor, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
-
-void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string)
-{
- m_impl->shaderSource(shader, string.utf8().data());
-}
-
-DELEGATE_TO_WEBCONTEXT_3(stencilFunc, GC3Denum, GC3Dint, GC3Duint)
-DELEGATE_TO_WEBCONTEXT_4(stencilFuncSeparate, GC3Denum, GC3Denum, GC3Dint, GC3Duint)
-DELEGATE_TO_WEBCONTEXT_1(stencilMask, GC3Duint)
-DELEGATE_TO_WEBCONTEXT_2(stencilMaskSeparate, GC3Denum, GC3Duint)
-DELEGATE_TO_WEBCONTEXT_3(stencilOp, GC3Denum, GC3Denum, GC3Denum)
-DELEGATE_TO_WEBCONTEXT_4(stencilOpSeparate, GC3Denum, GC3Denum, GC3Denum, GC3Denum)
-
-DELEGATE_TO_WEBCONTEXT_9(texImage2D, GC3Denum, GC3Dint, GC3Denum, GC3Dsizei, GC3Dsizei, GC3Dint, GC3Denum, GC3Denum, const void*)
-DELEGATE_TO_WEBCONTEXT_3(texParameterf, GC3Denum, GC3Denum, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_3(texParameteri, GC3Denum, GC3Denum, GC3Dint)
-DELEGATE_TO_WEBCONTEXT_9(texSubImage2D, GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, const void*)
-
-DELEGATE_TO_WEBCONTEXT_2(uniform1f, GC3Dint, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_3(uniform1fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_2(uniform1i, GC3Dint, GC3Dint)
-DELEGATE_TO_WEBCONTEXT_3(uniform1iv, GC3Dint, GC3Dsizei, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_3(uniform2f, GC3Dint, GC3Dfloat, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_3(uniform2fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_3(uniform2i, GC3Dint, GC3Dint, GC3Dint)
-DELEGATE_TO_WEBCONTEXT_3(uniform2iv, GC3Dint, GC3Dsizei, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_4(uniform3f, GC3Dint, GC3Dfloat, GC3Dfloat, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_3(uniform3fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_4(uniform3i, GC3Dint, GC3Dint, GC3Dint, GC3Dint)
-DELEGATE_TO_WEBCONTEXT_3(uniform3iv, GC3Dint, GC3Dsizei, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_5(uniform4f, GC3Dint, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_3(uniform4fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_5(uniform4i, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint)
-DELEGATE_TO_WEBCONTEXT_3(uniform4iv, GC3Dint, GC3Dsizei, GC3Dint*)
-DELEGATE_TO_WEBCONTEXT_4(uniformMatrix2fv, GC3Dint, GC3Dsizei, GC3Dboolean, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_4(uniformMatrix3fv, GC3Dint, GC3Dsizei, GC3Dboolean, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_4(uniformMatrix4fv, GC3Dint, GC3Dsizei, GC3Dboolean, GC3Dfloat*)
-
-DELEGATE_TO_WEBCONTEXT_1(useProgram, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_1(validateProgram, Platform3DObject)
-
-DELEGATE_TO_WEBCONTEXT_2(vertexAttrib1f, GC3Duint, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_2(vertexAttrib1fv, GC3Duint, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_3(vertexAttrib2f, GC3Duint, GC3Dfloat, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_2(vertexAttrib2fv, GC3Duint, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_4(vertexAttrib3f, GC3Duint, GC3Dfloat, GC3Dfloat, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_2(vertexAttrib3fv, GC3Duint, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_5(vertexAttrib4f, GC3Duint, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat)
-DELEGATE_TO_WEBCONTEXT_2(vertexAttrib4fv, GC3Duint, GC3Dfloat*)
-DELEGATE_TO_WEBCONTEXT_6(vertexAttribPointer, GC3Duint, GC3Dint, GC3Denum, GC3Dboolean, GC3Dsizei, GC3Dintptr)
-
-DELEGATE_TO_WEBCONTEXT_4(viewport, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
-
-void GraphicsContext3D::markContextChanged()
-{
- m_layerComposited = false;
-}
-
-bool GraphicsContext3D::layerComposited() const
-{
- return m_layerComposited;
-}
-
-void GraphicsContext3D::markLayerComposited()
-{
- m_layerComposited = true;
-}
-
-void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer, DrawingBuffer* drawingBuffer)
-{
- Platform3DObject framebufferId;
- int width, height;
- getDrawingParameters(drawingBuffer, m_impl, &framebufferId, &width, &height);
- paintFramebufferToCanvas(framebufferId, width, height, !getContextAttributes().premultipliedAlpha, imageBuffer);
-}
-
-PassRefPtr<Uint8ClampedArray> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer* drawingBuffer, int& width, int& height)
-{
- if (getContextAttributes().premultipliedAlpha)
- return 0;
-
- Platform3DObject framebufferId;
- getDrawingParameters(drawingBuffer, m_impl, &framebufferId, &width, &height);
-
- Checked<int, RecordOverflow> dataSize = 4;
- dataSize *= width;
- dataSize *= height;
- if (dataSize.hasOverflowed())
- return 0;
-
- RefPtr<Uint8ClampedArray> pixels = Uint8ClampedArray::createUninitialized(width * height * 4);
-
- m_impl->bindFramebuffer(GL_FRAMEBUFFER, framebufferId);
- readBackFramebuffer(pixels->data(), width, height, ReadbackRGBA, AlphaDoNothing);
- flipVertically(pixels->data(), width, height);
-
- return pixels.release();
-}
-
-void GraphicsContext3D::readBackFramebuffer(unsigned char* pixels, int width, int height, ReadbackOrder readbackOrder, AlphaOp op)
-{
- if (m_packAlignment > 4)
- m_impl->pixelStorei(GL_PACK_ALIGNMENT, 1);
- m_impl->readPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
- if (m_packAlignment > 4)
- m_impl->pixelStorei(GL_PACK_ALIGNMENT, m_packAlignment);
-
- size_t bufferSize = 4 * width * height;
-
- if (readbackOrder == ReadbackSkia) {
-#if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
- // Swizzle red and blue channels to match SkBitmap's byte ordering.
- // TODO(kbr): expose GL_BGRA as extension.
- for (size_t i = 0; i < bufferSize; i += 4) {
- std::swap(pixels[i], pixels[i + 2]);
- }
-#endif
- }
-
- if (op == AlphaDoPremultiply) {
- for (size_t i = 0; i < bufferSize; i += 4) {
- pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
- pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
- pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
- }
- } else if (op != AlphaDoNothing) {
- ASSERT_NOT_REACHED();
- }
-}
-
-DELEGATE_TO_WEBCONTEXT_R(createBuffer, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_R(createFramebuffer, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_R(createProgram, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_R(createRenderbuffer, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_1R(createShader, GC3Denum, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_R(createTexture, Platform3DObject)
-
-DELEGATE_TO_WEBCONTEXT_1(deleteBuffer, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_1(deleteFramebuffer, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_1(deleteProgram, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_1(deleteRenderbuffer, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_1(deleteShader, Platform3DObject)
-DELEGATE_TO_WEBCONTEXT_1(deleteTexture, Platform3DObject)
-
-DELEGATE_TO_WEBCONTEXT_1(synthesizeGLError, GC3Denum)
-
-Extensions3D* GraphicsContext3D::extensions()
-{
- if (!m_extensions)
- m_extensions = adoptPtr(new Extensions3D(this));
- return m_extensions.get();
-}
-
-bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment)
-{
- ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8);
- texImage2D(target, level, internalformat, width, height, border, format, type, 0);
- return true;
-}
-
-bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format,
- GC3Denum type,
- unsigned int* componentsPerPixel,
- unsigned int* bytesPerComponent)
-{
- switch (format) {
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_OES:
- *componentsPerPixel = 1;
- break;
- case GL_LUMINANCE_ALPHA:
- *componentsPerPixel = 2;
- break;
- case GL_RGB:
- *componentsPerPixel = 3;
- break;
- case GL_RGBA:
- case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888
- *componentsPerPixel = 4;
- break;
- default:
- return false;
- }
- switch (type) {
- case GL_UNSIGNED_BYTE:
- *bytesPerComponent = sizeof(GC3Dubyte);
- break;
- case GL_UNSIGNED_SHORT:
- *bytesPerComponent = sizeof(GC3Dushort);
- break;
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- *componentsPerPixel = 1;
- *bytesPerComponent = sizeof(GC3Dushort);
- break;
- case GL_UNSIGNED_INT_24_8_OES:
- case GL_UNSIGNED_INT:
- *bytesPerComponent = sizeof(GC3Duint);
- break;
- case GL_FLOAT: // OES_texture_float
- *bytesPerComponent = sizeof(GC3Dfloat);
- break;
- case GL_HALF_FLOAT_OES: // OES_texture_half_float
- *bytesPerComponent = sizeof(GC3Dhalffloat);
- break;
- default:
- return false;
- }
- return true;
-}
-
-GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment,
- unsigned int* imageSizeInBytes, unsigned int* paddingInBytes)
-{
- ASSERT(imageSizeInBytes);
- ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8);
- if (width < 0 || height < 0)
- return GL_INVALID_VALUE;
- unsigned int bytesPerComponent, componentsPerPixel;
- if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel))
- return GL_INVALID_ENUM;
- if (!width || !height) {
- *imageSizeInBytes = 0;
- if (paddingInBytes)
- *paddingInBytes = 0;
- return GL_NO_ERROR;
- }
- CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel);
- checkedValue *= width;
- if (!checkedValue.isValid())
- return GL_INVALID_VALUE;
- unsigned int validRowSize = checkedValue.value();
- unsigned int padding = 0;
- unsigned int residual = validRowSize % alignment;
- if (residual) {
- padding = alignment - residual;
- checkedValue += padding;
- }
- // Last row needs no padding.
- checkedValue *= (height - 1);
- checkedValue += validRowSize;
- if (!checkedValue.isValid())
- return GL_INVALID_VALUE;
- *imageSizeInBytes = checkedValue.value();
- if (paddingInBytes)
- *paddingInBytes = padding;
- return GL_NO_ERROR;
-}
-
-GraphicsContext3D::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomSource imageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
-{
- m_image = image;
- m_imageHtmlDomSource = imageHtmlDomSource;
- m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile);
-}
-
-GraphicsContext3D::ImageExtractor::~ImageExtractor()
-{
- if (m_skiaImage)
- m_skiaImage->bitmap().unlockPixels();
-}
-
-bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
-{
- if (!m_image)
- return false;
- m_skiaImage = m_image->nativeImageForCurrentFrame();
- m_alphaOp = AlphaDoNothing;
- bool hasAlpha = m_skiaImage ? !m_skiaImage->bitmap().isOpaque() : true;
- if ((!m_skiaImage || ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && m_image->data()) {
- // Attempt to get raw unpremultiplied image data.
- OwnPtr<ImageDecoder> decoder(ImageDecoder::create(
- *(m_image->data()), ImageSource::AlphaNotPremultiplied,
- ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied));
- if (!decoder)
- return false;
- decoder->setData(m_image->data(), true);
- if (!decoder->frameCount())
- return false;
- ImageFrame* frame = decoder->frameBufferAtIndex(0);
- if (!frame || frame->status() != ImageFrame::FrameComplete)
- return false;
- hasAlpha = frame->hasAlpha();
- m_nativeImage = frame->asNewNativeImage();
- if (!m_nativeImage.get() || !m_nativeImage->isDataComplete() || !m_nativeImage->bitmap().width() || !m_nativeImage->bitmap().height())
- return false;
- SkBitmap::Config skiaConfig = m_nativeImage->bitmap().config();
- if (skiaConfig != SkBitmap::kARGB_8888_Config)
- return false;
- m_skiaImage = m_nativeImage.get();
- if (hasAlpha && premultiplyAlpha)
- m_alphaOp = AlphaDoPremultiply;
- } else if (!premultiplyAlpha && hasAlpha) {
- // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value for each pixel is 0xFF
- // which is true at present and may be changed in the future and needs adjustment accordingly.
- // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port,
- // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false.
- if (m_imageHtmlDomSource != HtmlDomVideo)
- m_alphaOp = AlphaDoUnmultiply;
- }
- if (!m_skiaImage)
- return false;
-
- m_imageSourceFormat = SK_B32_SHIFT ? DataFormatRGBA8 : DataFormatBGRA8;
- m_imageWidth = m_skiaImage->bitmap().width();
- m_imageHeight = m_skiaImage->bitmap().height();
- if (!m_imageWidth || !m_imageHeight)
- return false;
- m_imageSourceUnpackAlignment = 0;
- m_skiaImage->bitmap().lockPixels();
- m_imagePixelData = m_skiaImage->bitmap().getPixels();
- return true;
-}
-
-unsigned GraphicsContext3D::getClearBitsByFormat(GC3Denum format)
-{
- switch (format) {
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_RGB:
- case GL_RGB565:
- case GL_RGBA:
- case GL_RGBA4:
- case GL_RGB5_A1:
- return GL_COLOR_BUFFER_BIT;
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT:
- return GL_DEPTH_BUFFER_BIT;
- case GL_STENCIL_INDEX8:
- return GL_STENCIL_BUFFER_BIT;
- case GL_DEPTH_STENCIL_OES:
- return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
- default:
- return 0;
- }
-}
-
-unsigned GraphicsContext3D::getChannelBitsByFormat(GC3Denum format)
-{
- switch (format) {
- case GL_ALPHA:
- return ChannelAlpha;
- case GL_LUMINANCE:
- return ChannelRGB;
- case GL_LUMINANCE_ALPHA:
- return ChannelRGBA;
- case GL_RGB:
- case GL_RGB565:
- return ChannelRGB;
- case GL_RGBA:
- case GL_RGBA4:
- case GL_RGB5_A1:
- return ChannelRGBA;
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT:
- return ChannelDepth;
- case GL_STENCIL_INDEX8:
- return ChannelStencil;
- case GL_DEPTH_STENCIL_OES:
- return ChannelDepth | ChannelStencil;
- default:
- return 0;
- }
-}
-
-void GraphicsContext3D::paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer* imageBuffer)
-{
- unsigned char* pixels = 0;
-
- const SkBitmap& canvasBitmap = imageBuffer->bitmap();
- const SkBitmap* readbackBitmap = 0;
- ASSERT(canvasBitmap.config() == SkBitmap::kARGB_8888_Config);
- if (canvasBitmap.width() == width && canvasBitmap.height() == height) {
- // This is the fastest and most common case. We read back
- // directly into the canvas's backing store.
- readbackBitmap = &canvasBitmap;
- m_resizingBitmap.reset();
- } else {
- // We need to allocate a temporary bitmap for reading back the
- // pixel data. We will then use Skia to rescale this bitmap to
- // the size of the canvas's backing store.
- if (m_resizingBitmap.width() != width || m_resizingBitmap.height() != height) {
- m_resizingBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- if (!m_resizingBitmap.allocPixels())
- return;
- }
- readbackBitmap = &m_resizingBitmap;
- }
-
- // Read back the frame buffer.
- SkAutoLockPixels bitmapLock(*readbackBitmap);
- pixels = static_cast<unsigned char*>(readbackBitmap->getPixels());
-
- m_impl->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- readBackFramebuffer(pixels, width, height, ReadbackSkia, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing);
- flipVertically(pixels, width, height);
-
- readbackBitmap->notifyPixelsChanged();
- if (m_resizingBitmap.readyToDraw()) {
- // We need to draw the resizing bitmap into the canvas's backing store.
- SkCanvas canvas(canvasBitmap);
- SkRect dst;
- dst.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(canvasBitmap.width()), SkIntToScalar(canvasBitmap.height()));
- canvas.drawBitmapRect(m_resizingBitmap, 0, dst);
- }
-}
-
-namespace {
-
-void splitStringHelper(const String& str, HashSet<String>& set)
-{
- Vector<String> substrings;
- str.split(" ", substrings);
- for (size_t i = 0; i < substrings.size(); ++i)
- set.add(substrings[i]);
-}
-
-String mapExtensionName(const String& name)
-{
- if (name == "GL_ANGLE_framebuffer_blit"
- || name == "GL_ANGLE_framebuffer_multisample")
- return "GL_CHROMIUM_framebuffer_multisample";
- return name;
-}
-
-} // anonymous namespace
-
-void GraphicsContext3D::initializeExtensions()
-{
- if (m_initializedAvailableExtensions)
- return;
-
- m_initializedAvailableExtensions = true;
- bool success = m_impl->makeContextCurrent();
- ASSERT(success);
- if (!success)
- return;
-
- String extensionsString = m_impl->getString(GL_EXTENSIONS);
- splitStringHelper(extensionsString, m_enabledExtensions);
-
- String requestableExtensionsString = m_impl->getRequestableExtensionsCHROMIUM();
- splitStringHelper(requestableExtensionsString, m_requestableExtensions);
-}
-
-
-bool GraphicsContext3D::supportsExtension(const String& name)
-{
- initializeExtensions();
- String mappedName = mapExtensionName(name);
- return m_enabledExtensions.contains(mappedName) || m_requestableExtensions.contains(mappedName);
-}
-
-bool GraphicsContext3D::ensureExtensionEnabled(const String& name)
-{
- initializeExtensions();
-
- String mappedName = mapExtensionName(name);
- if (m_enabledExtensions.contains(mappedName))
- return true;
-
- if (m_requestableExtensions.contains(mappedName)) {
- m_impl->requestExtensionCHROMIUM(mappedName.ascii().data());
- m_enabledExtensions.clear();
- m_requestableExtensions.clear();
- m_initializedAvailableExtensions = false;
- }
-
- initializeExtensions();
- fprintf(stderr, "m_enabledExtensions.contains(%s) == %d\n", mappedName.ascii().data(), m_enabledExtensions.contains(mappedName));
- return m_enabledExtensions.contains(mappedName);
-}
-
-bool GraphicsContext3D::isExtensionEnabled(const String& name)
-{
- initializeExtensions();
- String mappedName = mapExtensionName(name);
- return m_enabledExtensions.contains(mappedName);
-}
-
-void GraphicsContext3D::flipVertically(uint8_t* framebuffer, int width, int height)
-{
- m_scanline.resize(width * 4);
- uint8* scanline = &m_scanline[0];
- unsigned rowBytes = width * 4;
- unsigned count = height / 2;
- for (unsigned i = 0; i < count; i++) {
- uint8* rowA = framebuffer + i * rowBytes;
- uint8* rowB = framebuffer + (height - i - 1) * rowBytes;
- memcpy(scanline, rowB, rowBytes);
- memcpy(rowB, rowA, rowBytes);
- memcpy(rowA, scanline, rowBytes);
- }
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3D.h b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3D.h
deleted file mode 100644
index a4466548f51..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3D.h
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Copyright (C) 2009 Apple 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 GraphicsContext3D_h
-#define GraphicsContext3D_h
-
-#include "platform/PlatformExport.h"
-#include "platform/geometry/IntRect.h"
-#include "platform/graphics/Extensions3D.h"
-#include "platform/graphics/GraphicsTypes3D.h"
-#include "platform/graphics/Image.h"
-#include "platform/weborigin/KURL.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/khronos/GLES2/gl2ext.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "wtf/HashMap.h"
-#include "wtf/HashSet.h"
-#include "wtf/ListHashSet.h"
-#include "wtf/Noncopyable.h"
-#include "wtf/OwnPtr.h"
-#include "wtf/PassOwnPtr.h"
-#include "wtf/RefCounted.h"
-#include "wtf/text/WTFString.h"
-
-// FIXME: Find a better way to avoid the name confliction for NO_ERROR.
-#if OS(WIN)
-#undef NO_ERROR
-#endif
-
-class GrContext;
-
-namespace blink {
-class WebGraphicsContext3D;
-class WebGraphicsContext3DProvider;
-}
-
-namespace WebCore {
-class DrawingBuffer;
-class Extensions3D;
-class GraphicsContext3DContextLostCallbackAdapter;
-class GraphicsContext3DErrorMessageCallbackAdapter;
-class Image;
-class ImageBuffer;
-class IntRect;
-class IntSize;
-
-struct ActiveInfo {
- String name;
- GC3Denum type;
- GC3Dint size;
-};
-
-class PLATFORM_EXPORT GraphicsContext3D : public RefCounted<GraphicsContext3D> {
-public:
- // Context creation attributes.
- struct Attributes {
- Attributes()
- : alpha(true)
- , depth(true)
- , stencil(false)
- , antialias(true)
- , premultipliedAlpha(true)
- , preserveDrawingBuffer(false)
- , noExtensions(false)
- , shareResources(true)
- , preferDiscreteGPU(false)
- , failIfMajorPerformanceCaveat(false)
- {
- }
-
- bool alpha;
- bool depth;
- bool stencil;
- bool antialias;
- bool premultipliedAlpha;
- bool preserveDrawingBuffer;
- bool noExtensions;
- bool shareResources;
- bool preferDiscreteGPU;
- bool failIfMajorPerformanceCaveat;
- KURL topDocumentURL;
- };
-
- class ContextLostCallback {
- public:
- virtual void onContextLost() = 0;
- virtual ~ContextLostCallback() {}
- };
-
- class ErrorMessageCallback {
- public:
- virtual void onErrorMessage(const String& message, GC3Dint id) = 0;
- virtual ~ErrorMessageCallback() { }
- };
-
- void setContextLostCallback(PassOwnPtr<ContextLostCallback>);
- void setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>);
-
- static PassRefPtr<GraphicsContext3D> create(Attributes);
-
- // Callers must make the context current before using it AND check that the context was created successfully
- // via ContextLost before using the context in any way. Once made current on a thread, the context cannot
- // be used on any other thread.
- static PassRefPtr<GraphicsContext3D> createGraphicsContextFromWebContext(PassOwnPtr<blink::WebGraphicsContext3D>, bool preserveDrawingBuffer = false);
- static PassRefPtr<GraphicsContext3D> createGraphicsContextFromProvider(PassOwnPtr<blink::WebGraphicsContext3DProvider>, bool preserveDrawingBuffer = false);
-
- ~GraphicsContext3D();
-
- GrContext* grContext();
- blink::WebGraphicsContext3D* webContext() const { return m_impl; }
-
- bool makeContextCurrent();
-
- uint32_t lastFlushID();
-
- // Helper to texImage2D with pixel==0 case: pixels are initialized to 0.
- // Return true if no GL error is synthesized.
- // By default, alignment is 4, the OpenGL default setting.
- bool texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint alignment = 4);
-
- //----------------------------------------------------------------------
- // Helpers for texture uploading and pixel readback.
- //
-
- // Computes the components per pixel and bytes per component
- // for the given format and type combination. Returns false if
- // either was an invalid enum.
- static bool computeFormatAndTypeParameters(GC3Denum format,
- GC3Denum type,
- unsigned int* componentsPerPixel,
- unsigned int* bytesPerComponent);
-
- // Computes the image size in bytes. If paddingInBytes is not null, padding
- // is also calculated in return. Returns NO_ERROR if succeed, otherwise
- // return the suggested GL error indicating the cause of the failure:
- // INVALID_VALUE if width/height is negative or overflow happens.
- // INVALID_ENUM if format/type is illegal.
- static GC3Denum computeImageSizeInBytes(GC3Denum format,
- GC3Denum type,
- GC3Dsizei width,
- GC3Dsizei height,
- GC3Dint alignment,
- unsigned int* imageSizeInBytes,
- unsigned int* paddingInBytes);
-
- // Attempt to enumerate all possible native image formats to
- // reduce the amount of temporary allocations during texture
- // uploading. This enum must be public because it is accessed
- // by non-member functions.
- enum DataFormat {
- DataFormatRGBA8 = 0,
- DataFormatRGBA16F,
- DataFormatRGBA32F,
- DataFormatRGB8,
- DataFormatRGB16F,
- DataFormatRGB32F,
- DataFormatBGR8,
- DataFormatBGRA8,
- DataFormatARGB8,
- DataFormatABGR8,
- DataFormatRGBA5551,
- DataFormatRGBA4444,
- DataFormatRGB565,
- DataFormatR8,
- DataFormatR16F,
- DataFormatR32F,
- DataFormatRA8,
- DataFormatRA16F,
- DataFormatRA32F,
- DataFormatAR8,
- DataFormatA8,
- DataFormatA16F,
- DataFormatA32F,
- DataFormatNumFormats
- };
-
- // Check if the format is one of the formats from the ImageData or DOM elements.
- // The formats from ImageData is always RGBA8.
- // The formats from DOM elements vary with Graphics ports. It can only be RGBA8 or BGRA8.
- static ALWAYS_INLINE bool srcFormatComeFromDOMElementOrImageData(DataFormat SrcFormat)
- {
- return SrcFormat == DataFormatBGRA8 || SrcFormat == DataFormatRGBA8;
- }
-
- //----------------------------------------------------------------------
- // Entry points for WebGL.
- //
-
- void activeTexture(GC3Denum texture);
- void attachShader(Platform3DObject program, Platform3DObject shader);
- void bindAttribLocation(Platform3DObject, GC3Duint index, const String& name);
- void bindBuffer(GC3Denum target, Platform3DObject);
- void bindFramebuffer(GC3Denum target, Platform3DObject);
- void bindRenderbuffer(GC3Denum target, Platform3DObject);
- void bindTexture(GC3Denum target, Platform3DObject);
- void blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha);
- void blendEquation(GC3Denum mode);
- void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha);
- void blendFunc(GC3Denum sfactor, GC3Denum dfactor);
- void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha);
-
- void bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage);
- void bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage);
- void bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data);
-
- GC3Denum checkFramebufferStatus(GC3Denum target);
- void clear(GC3Dbitfield mask);
- void clearColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha);
- void clearDepth(GC3Dclampf depth);
- void clearStencil(GC3Dint s);
- void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha);
- void compileShader(Platform3DObject);
-
- void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Dsizei imageSize, const void* data);
- void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Dsizei imageSize, const void* data);
- void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
- void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
- void cullFace(GC3Denum mode);
- void depthFunc(GC3Denum func);
- void depthMask(GC3Dboolean flag);
- void depthRange(GC3Dclampf zNear, GC3Dclampf zFar);
- void detachShader(Platform3DObject, Platform3DObject);
- void disable(GC3Denum cap);
- void disableVertexAttribArray(GC3Duint index);
- void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count);
- void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset);
-
- void enable(GC3Denum cap);
- void enableVertexAttribArray(GC3Duint index);
- void finish();
- void flush();
- void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject);
- void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject, GC3Dint level);
- void frontFace(GC3Denum mode);
- void generateMipmap(GC3Denum target);
-
- bool getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo&);
- bool getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo&);
- void getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders);
- GC3Dint getAttribLocation(Platform3DObject, const String& name);
- void getBooleanv(GC3Denum pname, GC3Dboolean* value);
- void getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value);
- Attributes getContextAttributes();
- GC3Denum getError();
- void getFloatv(GC3Denum pname, GC3Dfloat* value);
- void getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum pname, GC3Dint* value);
- void getIntegerv(GC3Denum pname, GC3Dint* value);
- void getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value);
- String getProgramInfoLog(Platform3DObject);
- void getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value);
- void getShaderiv(Platform3DObject, GC3Denum pname, GC3Dint* value);
- String getShaderInfoLog(Platform3DObject);
- void getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, GC3Dint* range, GC3Dint* precision);
- String getShaderSource(Platform3DObject);
- String getString(GC3Denum name);
- void getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value);
- void getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value);
- void getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value);
- void getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value);
- GC3Dint getUniformLocation(Platform3DObject, const String& name);
- void getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value);
- void getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value);
- GC3Dsizeiptr getVertexAttribOffset(GC3Duint index, GC3Denum pname);
-
- void hint(GC3Denum target, GC3Denum mode);
- GC3Dboolean isBuffer(Platform3DObject);
- GC3Dboolean isEnabled(GC3Denum cap);
- GC3Dboolean isFramebuffer(Platform3DObject);
- GC3Dboolean isProgram(Platform3DObject);
- GC3Dboolean isRenderbuffer(Platform3DObject);
- GC3Dboolean isShader(Platform3DObject);
- GC3Dboolean isTexture(Platform3DObject);
- void lineWidth(GC3Dfloat);
- void linkProgram(Platform3DObject);
- void pixelStorei(GC3Denum pname, GC3Dint param);
- void polygonOffset(GC3Dfloat factor, GC3Dfloat units);
-
- void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data);
-
- void releaseShaderCompiler();
-
- void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height);
- void sampleCoverage(GC3Dclampf value, GC3Dboolean invert);
- void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
- void shaderSource(Platform3DObject, const String& string);
- void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask);
- void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask);
- void stencilMask(GC3Duint mask);
- void stencilMaskSeparate(GC3Denum face, GC3Duint mask);
- void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
- void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
-
- void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels);
- void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
- void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
- void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels);
-
- void uniform1f(GC3Dint location, GC3Dfloat x);
- void uniform1fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v);
- void uniform1i(GC3Dint location, GC3Dint x);
- void uniform1iv(GC3Dint location, GC3Dsizei, GC3Dint* v);
- void uniform2f(GC3Dint location, GC3Dfloat x, GC3Dfloat y);
- void uniform2fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v);
- void uniform2i(GC3Dint location, GC3Dint x, GC3Dint y);
- void uniform2iv(GC3Dint location, GC3Dsizei, GC3Dint* v);
- void uniform3f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
- void uniform3fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v);
- void uniform3i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z);
- void uniform3iv(GC3Dint location, GC3Dsizei, GC3Dint* v);
- void uniform4f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
- void uniform4fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v);
- void uniform4i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w);
- void uniform4iv(GC3Dint location, GC3Dsizei, GC3Dint* v);
- void uniformMatrix2fv(GC3Dint location, GC3Dsizei, GC3Dboolean transpose, GC3Dfloat* value);
- void uniformMatrix3fv(GC3Dint location, GC3Dsizei, GC3Dboolean transpose, GC3Dfloat* value);
- void uniformMatrix4fv(GC3Dint location, GC3Dsizei, GC3Dboolean transpose, GC3Dfloat* value);
-
- void useProgram(Platform3DObject);
- void validateProgram(Platform3DObject);
-
- void vertexAttrib1f(GC3Duint index, GC3Dfloat x);
- void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values);
- void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y);
- void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values);
- void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
- void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values);
- void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
- void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values);
- void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized,
- GC3Dsizei stride, GC3Dintptr offset);
-
- void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
-
- void markContextChanged();
- void markLayerComposited();
- bool layerComposited() const;
-
- void paintRenderingResultsToCanvas(ImageBuffer*, DrawingBuffer*);
- PassRefPtr<Uint8ClampedArray> paintRenderingResultsToImageData(DrawingBuffer*, int&, int&);
-
- // Support for buffer creation and deletion
- Platform3DObject createBuffer();
- Platform3DObject createFramebuffer();
- Platform3DObject createProgram();
- Platform3DObject createRenderbuffer();
- Platform3DObject createShader(GC3Denum);
- Platform3DObject createTexture();
-
- void deleteBuffer(Platform3DObject);
- void deleteFramebuffer(Platform3DObject);
- void deleteProgram(Platform3DObject);
- void deleteRenderbuffer(Platform3DObject);
- void deleteShader(Platform3DObject);
- void deleteTexture(Platform3DObject);
-
- // Synthesizes an OpenGL error which will be returned from a
- // later call to getError. This is used to emulate OpenGL ES
- // 2.0 behavior on the desktop and to enforce additional error
- // checking mandated by WebGL.
- //
- // Per the behavior of glGetError, this stores at most one
- // instance of any given error, and returns them from calls to
- // getError in the order they were added.
- void synthesizeGLError(GC3Denum error);
-
- // Support for extensions. Returns a non-null object, though not
- // all methods it contains may necessarily be supported on the
- // current hardware. Must call Extensions3D::supports() to
- // determine this.
- Extensions3D* extensions();
-
- static unsigned getClearBitsByFormat(GC3Denum);
-
- enum ChannelBits {
- ChannelRed = 1,
- ChannelGreen = 2,
- ChannelBlue = 4,
- ChannelAlpha = 8,
- ChannelDepth = 16,
- ChannelStencil = 32,
- ChannelRGB = ChannelRed | ChannelGreen | ChannelBlue,
- ChannelRGBA = ChannelRGB | ChannelAlpha,
- };
-
- static unsigned getChannelBitsByFormat(GC3Denum);
-
- // Possible alpha operations that may need to occur during
- // pixel packing. FIXME: kAlphaDoUnmultiply is lossy and must
- // be removed.
- enum AlphaOp {
- AlphaDoNothing = 0,
- AlphaDoPremultiply = 1,
- AlphaDoUnmultiply = 2
- };
-
- enum ImageHtmlDomSource {
- HtmlDomImage = 0,
- HtmlDomCanvas = 1,
- HtmlDomVideo = 2,
- HtmlDomNone = 3
- };
-
- class PLATFORM_EXPORT ImageExtractor {
- public:
- ImageExtractor(Image*, ImageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
-
- ~ImageExtractor();
-
- bool extractSucceeded() { return m_extractSucceeded; }
- const void* imagePixelData() { return m_imagePixelData; }
- unsigned imageWidth() { return m_imageWidth; }
- unsigned imageHeight() { return m_imageHeight; }
- DataFormat imageSourceFormat() { return m_imageSourceFormat; }
- AlphaOp imageAlphaOp() { return m_alphaOp; }
- unsigned imageSourceUnpackAlignment() { return m_imageSourceUnpackAlignment; }
- ImageHtmlDomSource imageHtmlDomSource() { return m_imageHtmlDomSource; }
- private:
- // Extract the image and keeps track of its status, such as width, height, Source Alignment, format and AlphaOp etc.
- // This needs to lock the resources or relevant data if needed and return true upon success
- bool extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
-
- RefPtr<NativeImageSkia> m_nativeImage;
- RefPtr<NativeImageSkia> m_skiaImage;
- Image* m_image;
- ImageHtmlDomSource m_imageHtmlDomSource;
- bool m_extractSucceeded;
- const void* m_imagePixelData;
- unsigned m_imageWidth;
- unsigned m_imageHeight;
- DataFormat m_imageSourceFormat;
- AlphaOp m_alphaOp;
- unsigned m_imageSourceUnpackAlignment;
- };
-
- // The Following functions are implemented in GraphicsContext3DImagePacking.cpp
-
- // Packs the contents of the given Image which is passed in |pixels| into the passed Vector
- // according to the given format and type, and obeying the flipY and AlphaOp flags.
- // Returns true upon success.
- static bool packImageData(Image*, const void* pixels, GC3Denum format, GC3Denum type, bool flipY, AlphaOp, DataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector<uint8_t>& data);
-
- // Extracts the contents of the given ImageData into the passed Vector,
- // packing the pixel data according to the given format and type,
- // and obeying the flipY and premultiplyAlpha flags. Returns true
- // upon success.
- static bool extractImageData(const uint8_t*, const IntSize&, GC3Denum format, GC3Denum type, bool flipY, bool premultiplyAlpha, Vector<uint8_t>& data);
-
- // Helper function which extracts the user-supplied texture
- // data, applying the flipY and premultiplyAlpha parameters.
- // If the data is not tightly packed according to the passed
- // unpackAlignment, the output data will be tightly packed.
- // Returns true if successful, false if any error occurred.
- static bool extractTextureData(unsigned width, unsigned height, GC3Denum format, GC3Denum type, unsigned unpackAlignment, bool flipY, bool premultiplyAlpha, const void* pixels, Vector<uint8_t>& data);
-
- // End GraphicsContext3DImagePacking.cpp functions
-
- // This is the order of bytes to use when doing a readback.
- enum ReadbackOrder {
- ReadbackRGBA,
- ReadbackSkia
- };
-
- // Helper function which does a readback from the currently-bound
- // framebuffer into a buffer of a certain size with 4-byte pixels.
- void readBackFramebuffer(unsigned char* pixels, int width, int height, ReadbackOrder, AlphaOp);
-
-private:
- friend class Extensions3D;
-
- GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3D>, bool preserveDrawingBuffer);
- GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3DProvider>, bool preserveDrawingBuffer);
-
- // Helper for packImageData/extractImageData/extractTextureData which implement packing of pixel
- // data into the specified OpenGL destination format and type.
- // A sourceUnpackAlignment of zero indicates that the source
- // data is tightly packed. Non-zero values may take a slow path.
- // Destination data will have no gaps between rows.
- // Implemented in GraphicsContext3DImagePacking.cpp
- static bool packPixels(const uint8_t* sourceData, DataFormat sourceDataFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, unsigned destinationFormat, unsigned destinationType, AlphaOp, void* destinationData, bool flipY);
-
- void paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer*);
- // Helper function to flip a bitmap vertically.
- void flipVertically(uint8_t* data, int width, int height);
-
- // Extensions3D support.
- bool supportsExtension(const String& name);
- bool ensureExtensionEnabled(const String& name);
- bool isExtensionEnabled(const String& name);
-
- void initializeExtensions();
-
- bool preserveDrawingBuffer() const { return m_preserveDrawingBuffer; }
-
- OwnPtr<blink::WebGraphicsContext3DProvider> m_provider;
- blink::WebGraphicsContext3D* m_impl;
- OwnPtr<GraphicsContext3DContextLostCallbackAdapter> m_contextLostCallbackAdapter;
- OwnPtr<GraphicsContext3DErrorMessageCallbackAdapter> m_errorMessageCallbackAdapter;
- OwnPtr<blink::WebGraphicsContext3D> m_ownedWebContext;
- OwnPtr<Extensions3D> m_extensions;
- bool m_initializedAvailableExtensions;
- HashSet<String> m_enabledExtensions;
- HashSet<String> m_requestableExtensions;
- bool m_layerComposited;
- bool m_preserveDrawingBuffer;
- int m_packAlignment;
-
- enum ResourceSafety {
- ResourceSafetyUnknown,
- ResourceSafe,
- ResourceUnsafe
- };
- ResourceSafety m_resourceSafety;
-
- // If the width and height of the Canvas's backing store don't
- // match those that we were given in the most recent call to
- // reshape(), then we need an intermediate bitmap to read back the
- // frame buffer into. This seems to happen when CSS styles are
- // used to resize the Canvas.
- SkBitmap m_resizingBitmap;
-
- GrContext* m_grContext;
-
- // Used to flip a bitmap vertically.
- Vector<uint8_t> m_scanline;
-};
-
-} // namespace WebCore
-
-#endif // GraphicsContext3D_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextCullSaver.h b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextCullSaver.h
new file mode 100644
index 00000000000..1b1023ddea8
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextCullSaver.h
@@ -0,0 +1,46 @@
+#ifndef GraphicsContextCullSaver_h
+#define GraphicsContextCullSaver_h
+
+#include "platform/graphics/GraphicsContext.h"
+
+namespace WebCore {
+
+class FloatRect;
+
+class GraphicsContextCullSaver {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ GraphicsContextCullSaver(GraphicsContext& context)
+ : m_context(context)
+ , m_cullApplied(false)
+ {
+ }
+
+ GraphicsContextCullSaver(GraphicsContext& context, const FloatRect& rect)
+ : m_context(context)
+ , m_cullApplied(true)
+ {
+ context.beginCull(rect);
+ }
+
+ ~GraphicsContextCullSaver()
+ {
+ if (m_cullApplied)
+ m_context.endCull();
+ }
+
+ void cull(const FloatRect& rect)
+ {
+ ASSERT(!m_cullApplied);
+ m_context.beginCull(rect);
+ m_cullApplied = true;
+ }
+
+private:
+ GraphicsContext& m_context;
+ bool m_cullApplied;
+};
+
+} // namespace WebCore
+
+#endif // GraphicsContextCullSaver_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.cpp
index ef7fb7e7268..4b7d9781afa 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.cpp
@@ -32,17 +32,27 @@
#include "platform/graphics/GraphicsContextRecorder.h"
#include "platform/graphics/ImageBuffer.h"
+#include "platform/graphics/ImageSource.h"
+#include "platform/image-decoders/ImageDecoder.h"
+#include "platform/image-decoders/ImageFrame.h"
+#include "platform/image-encoders/skia/PNGImageEncoder.h"
#include "third_party/skia/include/core/SkBitmapDevice.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "wtf/HexNumber.h"
+#include "wtf/text/Base64.h"
+#include "wtf/text/TextEncoding.h"
namespace WebCore {
GraphicsContext* GraphicsContextRecorder::record(const IntSize& size, bool isCertainlyOpaque)
{
ASSERT(!m_picture);
+ ASSERT(!m_recorder);
ASSERT(!m_context);
- m_picture = adoptRef(new SkPicture());
m_isCertainlyOpaque = isCertainlyOpaque;
- SkCanvas* canvas = m_picture->beginRecording(size.width(), size.height());
+ m_recorder = adoptPtr(new SkPictureRecorder);
+ SkCanvas* canvas = m_recorder->beginRecording(size.width(), size.height(), 0, 0);
m_context = adoptPtr(new GraphicsContext(canvas));
m_context->setTrackOpaqueRegion(isCertainlyOpaque);
m_context->setCertainlyOpaque(isCertainlyOpaque);
@@ -51,8 +61,9 @@ GraphicsContext* GraphicsContextRecorder::record(const IntSize& size, bool isCer
PassRefPtr<GraphicsContextSnapshot> GraphicsContextRecorder::stop()
{
- m_picture->endRecording();
m_context.clear();
+ m_picture = adoptRef(m_recorder->endRecording());
+ m_recorder.clear();
return adoptRef(new GraphicsContextSnapshot(m_picture.release(), m_isCertainlyOpaque));
}
@@ -153,10 +164,838 @@ private:
Vector<double>* m_currentTimings;
};
+class LoggingCanvas : public SkCanvas {
+public:
+ LoggingCanvas(int width, int height) : SkCanvas(width, height)
+ {
+ m_log = JSONArray::create();
+ }
-PassOwnPtr<ImageBuffer> GraphicsContextSnapshot::replay(unsigned fromStep, unsigned toStep) const
+ void clear(SkColor color) OVERRIDE
+ {
+ addItemWithParams("clear")->setString("color", stringForSkColor(color));
+ }
+
+ void drawPaint(const SkPaint& paint) OVERRIDE
+ {
+ addItemWithParams("drawPaint")->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawPoints");
+ params->setString("pointMode", pointModeName(mode));
+ params->setArray("points", arrayForSkPoints(count, pts));
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void drawRect(const SkRect& rect, const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawRect");
+ params->setObject("rect", objectForSkRect(rect));
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void drawOval(const SkRect& oval, const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawOval");
+ params->setObject("oval", objectForSkRect(oval));
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void drawRRect(const SkRRect& rrect, const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawRRect");
+ params->setObject("rrect", objectForSkRRect(rrect));
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void drawPath(const SkPath& path, const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawPath");
+ params->setObject("path", objectForSkPath(path));
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawBitmap");
+ params->setNumber("left", left);
+ params->setNumber("top", top);
+ params->setObject("bitmap", objectForSkBitmap(bitmap));
+ params->setObject("paint", objectForSkPaint(*paint));
+ }
+
+ void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, const SkPaint* paint, DrawBitmapRectFlags flags) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawBitmapRectToRect");
+ params->setObject("bitmap", objectForSkBitmap(bitmap));
+ params->setObject("src", objectForSkRect(*src));
+ params->setObject("dst", objectForSkRect(dst));
+ params->setObject("paint", objectForSkPaint(*paint));
+ params->setNumber("flags", flags);
+ }
+
+ void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint* paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawBitmapMatrix");
+ params->setObject("bitmap", objectForSkBitmap(bitmap));
+ params->setArray("matrix", arrayForSkMatrix(m));
+ params->setObject("paint", objectForSkPaint(*paint));
+ }
+
+ void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawBitmapNine");
+ params->setObject("bitmap", objectForSkBitmap(bitmap));
+ params->setObject("center", objectForSkIRect(center));
+ params->setObject("dst", objectForSkRect(dst));
+ params->setObject("paint", objectForSkPaint(*paint));
+ }
+
+ void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawSprite");
+ params->setObject("bitmap", objectForSkBitmap(bitmap));
+ params->setNumber("left", left);
+ params->setNumber("top", top);
+ params->setObject("paint", objectForSkPaint(*paint));
+ }
+
+ void drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount, const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawVertices");
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void drawData(const void* data, size_t length) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawData");
+ params->setNumber("length", length);
+ }
+
+ void beginCommentGroup(const char* description) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("beginCommentGroup");
+ params->setString("description", description);
+ }
+
+ void addComment(const char* keyword, const char* value) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("addComment");
+ params->setString("key", keyword);
+ params->setString("value", value);
+ }
+
+ void endCommentGroup() OVERRIDE
+ {
+ addItem("endCommentGroup");
+ }
+
+ void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawDRRect");
+ params->setObject("outer", objectForSkRRect(outer));
+ params->setObject("inner", objectForSkRRect(inner));
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawText");
+ params->setString("text", stringForText(text, byteLength, paint));
+ params->setNumber("x", x);
+ params->setNumber("y", y);
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawPosText");
+ params->setString("text", stringForText(text, byteLength, paint));
+ size_t pointsCount = paint.countText(text, byteLength);
+ params->setArray("pos", arrayForSkPoints(pointsCount, pos));
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawPosTextH");
+ params->setString("text", stringForText(text, byteLength, paint));
+ size_t pointsCount = paint.countText(text, byteLength);
+ params->setArray("xpos", arrayForSkScalars(pointsCount, xpos));
+ params->setNumber("constY", constY);
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("drawTextOnPath");
+ params->setString("text", stringForText(text, byteLength, paint));
+ params->setObject("path", objectForSkPath(path));
+ params->setArray("matrix", arrayForSkMatrix(*matrix));
+ params->setObject("paint", objectForSkPaint(paint));
+ }
+
+ void onPushCull(const SkRect& cullRect) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("pushCull");
+ params->setObject("cullRect", objectForSkRect(cullRect));
+ }
+
+ void onPopCull() OVERRIDE
+ {
+ addItem("popCull");
+ }
+
+ void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle style) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("clipRect");
+ params->setObject("rect", objectForSkRect(rect));
+ params->setString("SkRegion::Op", regionOpName(op));
+ params->setBoolean("softClipEdgeStyle", kSoft_ClipEdgeStyle == style);
+ }
+
+ void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle style) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("clipRRect");
+ params->setObject("rrect", objectForSkRRect(rrect));
+ params->setString("SkRegion::Op", regionOpName(op));
+ params->setBoolean("softClipEdgeStyle", kSoft_ClipEdgeStyle == style);
+ }
+
+ void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle style) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("clipPath");
+ params->setObject("path", objectForSkPath(path));
+ params->setString("SkRegion::Op", regionOpName(op));
+ params->setBoolean("softClipEdgeStyle", kSoft_ClipEdgeStyle == style);
+ }
+
+ void onClipRegion(const SkRegion& region, SkRegion::Op op) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("clipRegion");
+ params->setString("op", regionOpName(op));
+ }
+
+ void onDrawPicture(const SkPicture* picture) OVERRIDE
+ {
+ addItemWithParams("drawPicture")->setObject("picture", objectForSkPicture(*picture));
+ }
+
+ void didSetMatrix(const SkMatrix& matrix) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("setMatrix");
+ params->setArray("matrix", arrayForSkMatrix(matrix));
+ this->SkCanvas::didSetMatrix(matrix);
+ }
+
+ void didConcat(const SkMatrix& matrix) OVERRIDE
+ {
+ switch (matrix.getType()) {
+ case SkMatrix::kTranslate_Mask:
+ translate(matrix.getTranslateX(), matrix.getTranslateY());
+ break;
+ case SkMatrix::kScale_Mask:
+ scale(matrix.getScaleX(), matrix.getScaleY());
+ break;
+ default:
+ concat(matrix);
+ }
+ this->SkCanvas::didConcat(matrix);
+ }
+
+ void willRestore() OVERRIDE
+ {
+ addItem("restore");
+ this->SkCanvas::willRestore();
+ }
+
+ SaveLayerStrategy willSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("saveLayer");
+ if (bounds)
+ params->setObject("bounds", objectForSkRect(*bounds));
+ params->setObject("paint", objectForSkPaint(*paint));
+ params->setString("saveFlags", saveFlagsToString(flags));
+ this->SkCanvas::willSaveLayer(bounds, paint, flags);
+ return kNoLayer_SaveLayerStrategy;
+ }
+
+ void willSave() OVERRIDE
+ {
+ RefPtr<JSONObject> params = addItemWithParams("save");
+ this->SkCanvas::willSave();
+ }
+
+ bool isClipEmpty() const OVERRIDE
+ {
+ return false;
+ }
+
+ bool isClipRect() const OVERRIDE
+ {
+ return true;
+ }
+
+#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
+ ClipType getClipType() const OVERRIDE
+ {
+ return kRect_ClipType;
+ }
+#endif
+
+ bool getClipBounds(SkRect* bounds) const OVERRIDE
+ {
+ if (bounds)
+ bounds->setXYWH(0, 0, SkIntToScalar(this->imageInfo().fWidth), SkIntToScalar(this->imageInfo().fHeight));
+ return true;
+ }
+
+ bool getClipDeviceBounds(SkIRect* bounds) const OVERRIDE
+ {
+ if (bounds)
+ bounds->setLargest();
+ return true;
+ }
+
+ PassRefPtr<JSONArray> log()
+ {
+ return m_log;
+ }
+
+private:
+ RefPtr<JSONArray> m_log;
+
+ PassRefPtr<JSONObject> addItem(const String& name)
+ {
+ RefPtr<JSONObject> item = JSONObject::create();
+ item->setString("method", name);
+ m_log->pushObject(item);
+ return item.release();
+ }
+
+ PassRefPtr<JSONObject> addItemWithParams(const String& name)
+ {
+ RefPtr<JSONObject> item = addItem(name);
+ RefPtr<JSONObject> params = JSONObject::create();
+ item->setObject("params", params);
+ return params.release();
+ }
+
+ PassRefPtr<JSONObject> objectForSkRect(const SkRect& rect)
+ {
+ RefPtr<JSONObject> rectItem = JSONObject::create();
+ rectItem->setNumber("left", rect.left());
+ rectItem->setNumber("top", rect.top());
+ rectItem->setNumber("right", rect.right());
+ rectItem->setNumber("bottom", rect.bottom());
+ return rectItem.release();
+ }
+
+ PassRefPtr<JSONObject> objectForSkIRect(const SkIRect& rect)
+ {
+ RefPtr<JSONObject> rectItem = JSONObject::create();
+ rectItem->setNumber("left", rect.left());
+ rectItem->setNumber("top", rect.top());
+ rectItem->setNumber("right", rect.right());
+ rectItem->setNumber("bottom", rect.bottom());
+ return rectItem.release();
+ }
+
+ String pointModeName(PointMode mode)
+ {
+ switch (mode) {
+ case SkCanvas::kPoints_PointMode: return "Points";
+ case SkCanvas::kLines_PointMode: return "Lines";
+ case SkCanvas::kPolygon_PointMode: return "Polygon";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ PassRefPtr<JSONObject> objectForSkPoint(const SkPoint& point)
+ {
+ RefPtr<JSONObject> pointItem = JSONObject::create();
+ pointItem->setNumber("x", point.x());
+ pointItem->setNumber("y", point.y());
+ return pointItem.release();
+ }
+
+ PassRefPtr<JSONArray> arrayForSkPoints(size_t count, const SkPoint points[])
+ {
+ RefPtr<JSONArray> pointsArrayItem = JSONArray::create();
+ for (size_t i = 0; i < count; ++i)
+ pointsArrayItem->pushObject(objectForSkPoint(points[i]));
+ return pointsArrayItem.release();
+ }
+
+ PassRefPtr<JSONObject> objectForSkPicture(const SkPicture& picture)
+ {
+ RefPtr<JSONObject> pictureItem = JSONObject::create();
+ pictureItem->setNumber("width", picture.width());
+ pictureItem->setNumber("height", picture.height());
+ return pictureItem.release();
+ }
+
+ PassRefPtr<JSONObject> objectForRadius(const SkRRect& rrect, SkRRect::Corner corner)
+ {
+ RefPtr<JSONObject> radiusItem = JSONObject::create();
+ SkVector radius = rrect.radii(corner);
+ radiusItem->setNumber("xRadius", radius.x());
+ radiusItem->setNumber("yRadius", radius.y());
+ return radiusItem.release();
+ }
+
+ String rrectTypeName(SkRRect::Type type)
+ {
+ switch (type) {
+ case SkRRect::kEmpty_Type: return "Empty";
+ case SkRRect::kRect_Type: return "Rect";
+ case SkRRect::kOval_Type: return "Oval";
+ case SkRRect::kSimple_Type: return "Simple";
+ case SkRRect::kNinePatch_Type: return "Nine-patch";
+ case SkRRect::kComplex_Type: return "Complex";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ String radiusName(SkRRect::Corner corner)
+ {
+ switch (corner) {
+ case SkRRect::kUpperLeft_Corner: return "upperLeftRadius";
+ case SkRRect::kUpperRight_Corner: return "upperRightRadius";
+ case SkRRect::kLowerRight_Corner: return "lowerRightRadius";
+ case SkRRect::kLowerLeft_Corner: return "lowerLeftRadius";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ }
+ }
+
+ PassRefPtr<JSONObject> objectForSkRRect(const SkRRect& rrect)
+ {
+ RefPtr<JSONObject> rrectItem = JSONObject::create();
+ rrectItem->setString("type", rrectTypeName(rrect.type()));
+ rrectItem->setNumber("left", rrect.rect().left());
+ rrectItem->setNumber("top", rrect.rect().top());
+ rrectItem->setNumber("right", rrect.rect().right());
+ rrectItem->setNumber("bottom", rrect.rect().bottom());
+ for (int i = 0; i < 4; ++i)
+ rrectItem->setObject(radiusName((SkRRect::Corner) i), objectForRadius(rrect, (SkRRect::Corner) i));
+ return rrectItem.release();
+ }
+
+ String fillTypeName(SkPath::FillType type)
+ {
+ switch (type) {
+ case SkPath::kWinding_FillType: return "Winding";
+ case SkPath::kEvenOdd_FillType: return "EvenOdd";
+ case SkPath::kInverseWinding_FillType: return "InverseWinding";
+ case SkPath::kInverseEvenOdd_FillType: return "InverseEvenOdd";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ String convexityName(SkPath::Convexity convexity)
+ {
+ switch (convexity) {
+ case SkPath::kUnknown_Convexity: return "Unknown";
+ case SkPath::kConvex_Convexity: return "Convex";
+ case SkPath::kConcave_Convexity: return "Concave";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ String verbName(SkPath::Verb verb)
+ {
+ switch (verb) {
+ case SkPath::kMove_Verb: return "Move";
+ case SkPath::kLine_Verb: return "Line";
+ case SkPath::kQuad_Verb: return "Quad";
+ case SkPath::kConic_Verb: return "Conic";
+ case SkPath::kCubic_Verb: return "Cubic";
+ case SkPath::kClose_Verb: return "Close";
+ case SkPath::kDone_Verb: return "Done";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ struct VerbParams {
+ String name;
+ unsigned pointCount;
+ unsigned pointOffset;
+
+ VerbParams(const String& name, unsigned pointCount, unsigned pointOffset)
+ : name(name)
+ , pointCount(pointCount)
+ , pointOffset(pointOffset) { }
+ };
+
+ VerbParams segmentParams(SkPath::Verb verb)
+ {
+ switch (verb) {
+ case SkPath::kMove_Verb: return VerbParams("Move", 1, 0);
+ case SkPath::kLine_Verb: return VerbParams("Line", 1, 1);
+ case SkPath::kQuad_Verb: return VerbParams("Quad", 2, 1);
+ case SkPath::kConic_Verb: return VerbParams("Conic", 2, 1);
+ case SkPath::kCubic_Verb: return VerbParams("Cubic", 3, 1);
+ case SkPath::kClose_Verb: return VerbParams("Close", 0, 0);
+ case SkPath::kDone_Verb: return VerbParams("Done", 0, 0);
+ default:
+ ASSERT_NOT_REACHED();
+ return VerbParams("?", 0, 0);
+ };
+ }
+
+ PassRefPtr<JSONObject> objectForSkPath(const SkPath& path)
+ {
+ RefPtr<JSONObject> pathItem = JSONObject::create();
+ pathItem->setString("fillType", fillTypeName(path.getFillType()));
+ pathItem->setString("convexity", convexityName(path.getConvexity()));
+ pathItem->setBoolean("isRect", path.isRect(0));
+ SkPath::Iter iter(path, false);
+ SkPoint points[4];
+ RefPtr<JSONArray> pathPointsArray = JSONArray::create();
+ for (SkPath::Verb verb = iter.next(points, false); verb != SkPath::kDone_Verb; verb = iter.next(points, false)) {
+ VerbParams verbParams = segmentParams(verb);
+ RefPtr<JSONObject> pathPointItem = JSONObject::create();
+ pathPointItem->setString("verb", verbParams.name);
+ ASSERT(verbParams.pointCount + verbParams.pointOffset <= WTF_ARRAY_LENGTH(points));
+ pathPointItem->setArray("points", arrayForSkPoints(verbParams.pointCount, points + verbParams.pointOffset));
+ if (SkPath::kConic_Verb == verb)
+ pathPointItem->setNumber("conicWeight", iter.conicWeight());
+ pathPointsArray->pushObject(pathPointItem);
+ }
+ pathItem->setArray("pathPoints", pathPointsArray);
+ pathItem->setObject("bounds", objectForSkRect(path.getBounds()));
+ return pathItem.release();
+ }
+
+ String configName(SkBitmap::Config config)
+ {
+ switch (config) {
+ case SkBitmap::kNo_Config: return "None";
+ case SkBitmap::kA8_Config: return "A8";
+ case SkBitmap::kIndex8_Config: return "Index8";
+ case SkBitmap::kRGB_565_Config: return "RGB565";
+ case SkBitmap::kARGB_4444_Config: return "ARGB4444";
+ case SkBitmap::kARGB_8888_Config: return "ARGB8888";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ PassRefPtr<JSONObject> objectForBitmapData(const SkBitmap& bitmap)
+ {
+ RefPtr<JSONObject> dataItem = JSONObject::create();
+ Vector<unsigned char> output;
+ WebCore::PNGImageEncoder::encode(bitmap, &output);
+ dataItem->setString("base64", WTF::base64Encode(reinterpret_cast<char*>(output.data()), output.size()));
+ dataItem->setString("mimeType", "image/png");
+ return dataItem.release();
+ }
+
+ PassRefPtr<JSONObject> objectForSkBitmap(const SkBitmap& bitmap)
+ {
+ RefPtr<JSONObject> bitmapItem = JSONObject::create();
+ bitmapItem->setNumber("width", bitmap.width());
+ bitmapItem->setNumber("height", bitmap.height());
+ bitmapItem->setString("config", configName(bitmap.config()));
+ bitmapItem->setBoolean("opaque", bitmap.isOpaque());
+ bitmapItem->setBoolean("immutable", bitmap.isImmutable());
+ bitmapItem->setBoolean("volatile", bitmap.isVolatile());
+ bitmapItem->setNumber("genID", bitmap.getGenerationID());
+ bitmapItem->setObject("data", objectForBitmapData(bitmap));
+ return bitmapItem.release();
+ }
+
+ PassRefPtr<JSONObject> objectForSkShader(const SkShader& shader)
+ {
+ RefPtr<JSONObject> shaderItem = JSONObject::create();
+ const SkMatrix localMatrix = shader.getLocalMatrix();
+ if (!localMatrix.isIdentity())
+ shaderItem->setArray("localMatrix", arrayForSkMatrix(localMatrix));
+ return shaderItem.release();
+ }
+
+ String stringForSkColor(const SkColor& color)
+ {
+ String colorString = "#";
+ appendUnsignedAsHex(color, colorString);
+ return colorString;
+ }
+
+ void appendFlagToString(String* flagsString, bool isSet, const String& name)
+ {
+ if (!isSet)
+ return;
+ if (flagsString->length())
+ flagsString->append("|");
+ flagsString->append(name);
+ }
+
+ String stringForSkPaintFlags(const SkPaint& paint)
+ {
+ if (!paint.getFlags())
+ return "none";
+ String flagsString = "";
+ appendFlagToString(&flagsString, paint.isAntiAlias(), "AntiAlias");
+ appendFlagToString(&flagsString, paint.isDither(), "Dither");
+ appendFlagToString(&flagsString, paint.isUnderlineText(), "UnderlinText");
+ appendFlagToString(&flagsString, paint.isStrikeThruText(), "StrikeThruText");
+ appendFlagToString(&flagsString, paint.isFakeBoldText(), "FakeBoldText");
+ appendFlagToString(&flagsString, paint.isLinearText(), "LinearText");
+ appendFlagToString(&flagsString, paint.isSubpixelText(), "SubpixelText");
+ appendFlagToString(&flagsString, paint.isDevKernText(), "DevKernText");
+ appendFlagToString(&flagsString, paint.isLCDRenderText(), "LCDRenderText");
+ appendFlagToString(&flagsString, paint.isEmbeddedBitmapText(), "EmbeddedBitmapText");
+ appendFlagToString(&flagsString, paint.isAutohinted(), "Autohinted");
+ appendFlagToString(&flagsString, paint.isVerticalText(), "VerticalText");
+ appendFlagToString(&flagsString, paint.getFlags() & SkPaint::kGenA8FromLCD_Flag, "GenA8FromLCD");
+ return flagsString;
+ }
+
+ String filterLevelName(SkPaint::FilterLevel filterLevel)
+ {
+ switch (filterLevel) {
+ case SkPaint::kNone_FilterLevel: return "None";
+ case SkPaint::kLow_FilterLevel: return "Low";
+ case SkPaint::kMedium_FilterLevel: return "Medium";
+ case SkPaint::kHigh_FilterLevel: return "High";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ String textAlignName(SkPaint::Align align)
+ {
+ switch (align) {
+ case SkPaint::kLeft_Align: return "Left";
+ case SkPaint::kCenter_Align: return "Center";
+ case SkPaint::kRight_Align: return "Right";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ String strokeCapName(SkPaint::Cap cap)
+ {
+ switch (cap) {
+ case SkPaint::kButt_Cap: return "Butt";
+ case SkPaint::kRound_Cap: return "Round";
+ case SkPaint::kSquare_Cap: return "Square";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ String strokeJoinName(SkPaint::Join join)
+ {
+ switch (join) {
+ case SkPaint::kMiter_Join: return "Miter";
+ case SkPaint::kRound_Join: return "Round";
+ case SkPaint::kBevel_Join: return "Bevel";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ String styleName(SkPaint::Style style)
+ {
+ switch (style) {
+ case SkPaint::kFill_Style: return "Fill";
+ case SkPaint::kStroke_Style: return "Stroke";
+ case SkPaint::kStrokeAndFill_Style: return "StrokeAndFill";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ String textEncodingName(SkPaint::TextEncoding encoding)
+ {
+ switch (encoding) {
+ case SkPaint::kUTF8_TextEncoding: return "UTF-8";
+ case SkPaint::kUTF16_TextEncoding: return "UTF-16";
+ case SkPaint::kUTF32_TextEncoding: return "UTF-32";
+ case SkPaint::kGlyphID_TextEncoding: return "GlyphID";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ String hintingName(SkPaint::Hinting hinting)
+ {
+ switch (hinting) {
+ case SkPaint::kNo_Hinting: return "None";
+ case SkPaint::kSlight_Hinting: return "Slight";
+ case SkPaint::kNormal_Hinting: return "Normal";
+ case SkPaint::kFull_Hinting: return "Full";
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ };
+ }
+
+ PassRefPtr<JSONObject> objectForSkPaint(const SkPaint& paint)
+ {
+ RefPtr<JSONObject> paintItem = JSONObject::create();
+ paintItem->setNumber("textSize", paint.getTextSize());
+ paintItem->setNumber("textScaleX", paint.getTextScaleX());
+ paintItem->setNumber("textSkewX", paint.getTextSkewX());
+ if (SkShader* shader = paint.getShader())
+ paintItem->setObject("shader", objectForSkShader(*shader));
+ paintItem->setString("color", stringForSkColor(paint.getColor()));
+ paintItem->setNumber("strokeWidth", paint.getStrokeWidth());
+ paintItem->setNumber("strokeMiter", paint.getStrokeMiter());
+ paintItem->setString("flags", stringForSkPaintFlags(paint));
+ paintItem->setString("filterLevel", filterLevelName(paint.getFilterLevel()));
+ paintItem->setString("textAlign", textAlignName(paint.getTextAlign()));
+ paintItem->setString("strokeCap", strokeCapName(paint.getStrokeCap()));
+ paintItem->setString("strokeJoin", strokeJoinName(paint.getStrokeJoin()));
+ paintItem->setString("styleName", styleName(paint.getStyle()));
+ paintItem->setString("textEncoding", textEncodingName(paint.getTextEncoding()));
+ paintItem->setString("hinting", hintingName(paint.getHinting()));
+ return paintItem.release();
+ }
+
+ PassRefPtr<JSONArray> arrayForSkMatrix(const SkMatrix& matrix)
+ {
+ RefPtr<JSONArray> matrixArray = JSONArray::create();
+ for (int i = 0; i < 9; ++i)
+ matrixArray->pushNumber(matrix[i]);
+ return matrixArray.release();
+ }
+
+ PassRefPtr<JSONArray> arrayForSkScalars(size_t n, const SkScalar scalars[])
+ {
+ RefPtr<JSONArray> scalarsArray = JSONArray::create();
+ for (size_t i = 0; i < n; ++i)
+ scalarsArray->pushNumber(scalars[i]);
+ return scalarsArray.release();
+ }
+
+ String regionOpName(SkRegion::Op op)
+ {
+ switch (op) {
+ case SkRegion::kDifference_Op: return "kDifference_Op";
+ case SkRegion::kIntersect_Op: return "kIntersect_Op";
+ case SkRegion::kUnion_Op: return "kUnion_Op";
+ case SkRegion::kXOR_Op: return "kXOR_Op";
+ case SkRegion::kReverseDifference_Op: return "kReverseDifference_Op";
+ case SkRegion::kReplace_Op: return "kReplace_Op";
+ default: return "Unknown type";
+ };
+ }
+
+ void translate(SkScalar dx, SkScalar dy)
+ {
+ RefPtr<JSONObject> params = addItemWithParams("translate");
+ params->setNumber("dx", dx);
+ params->setNumber("dy", dy);
+ }
+
+ void scale(SkScalar scaleX, SkScalar scaleY)
+ {
+ RefPtr<JSONObject> params = addItemWithParams("scale");
+ params->setNumber("scaleX", scaleX);
+ params->setNumber("scaleY", scaleY);
+ }
+
+ void concat(const SkMatrix& matrix)
+ {
+ RefPtr<JSONObject> params = addItemWithParams("concat");
+ params->setArray("matrix", arrayForSkMatrix(matrix));
+ }
+
+ String saveFlagsToString(SkCanvas::SaveFlags flags)
+ {
+ String flagsString = "";
+ if (flags & SkCanvas::kHasAlphaLayer_SaveFlag)
+ flagsString.append("kHasAlphaLayer_SaveFlag ");
+ if (flags & SkCanvas::kFullColorLayer_SaveFlag)
+ flagsString.append("kFullColorLayer_SaveFlag ");
+ if (flags & SkCanvas::kClipToLayer_SaveFlag)
+ flagsString.append("kClipToLayer_SaveFlag ");
+ return flagsString;
+ }
+
+ String textEncodingCanonicalName(SkPaint::TextEncoding encoding)
+ {
+ String name = textEncodingName(encoding);
+ if (encoding == SkPaint::kUTF16_TextEncoding || encoding == SkPaint::kUTF32_TextEncoding)
+ name.append("LE");
+ return name;
+ }
+
+ String stringForUTFText(const void* text, size_t length, SkPaint::TextEncoding encoding)
+ {
+ return WTF::TextEncoding(textEncodingCanonicalName(encoding)).decode((const char*)text, length);
+ }
+
+ String stringForText(const void* text, size_t byteLength, const SkPaint& paint)
+ {
+ SkPaint::TextEncoding encoding = paint.getTextEncoding();
+ switch (encoding) {
+ case SkPaint::kUTF8_TextEncoding:
+ case SkPaint::kUTF16_TextEncoding:
+ case SkPaint::kUTF32_TextEncoding:
+ return stringForUTFText(text, byteLength, encoding);
+ case SkPaint::kGlyphID_TextEncoding: {
+ WTF::Vector<SkUnichar> dataVector(byteLength / 2);
+ SkUnichar* textData = dataVector.data();
+ paint.glyphsToUnichars(static_cast<const uint16_t*>(text), byteLength / 2, textData);
+ return WTF::UTF32LittleEndianEncoding().decode(reinterpret_cast<const char*>(textData), byteLength * 2);
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ return "?";
+ }
+ }
+};
+
+static bool decodeBitmap(const void* data, size_t length, SkBitmap* result)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::create(static_cast<const char*>(data), length);
+ OwnPtr<ImageDecoder> imageDecoder = ImageDecoder::create(*buffer, ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileIgnored);
+ if (!imageDecoder)
+ return false;
+ imageDecoder->setData(buffer.get(), true);
+ ImageFrame* frame = imageDecoder->frameBufferAtIndex(0);
+ if (!frame)
+ return true;
+ *result = frame->getSkBitmap();
+ return true;
+}
+
+PassRefPtr<GraphicsContextSnapshot> GraphicsContextSnapshot::load(const char* data, size_t size)
{
+ SkMemoryStream stream(data, size);
+ RefPtr<SkPicture> picture = adoptRef(SkPicture::CreateFromStream(&stream, decodeBitmap));
+ if (!picture)
+ return nullptr;
+ return adoptRef(new GraphicsContextSnapshot(picture, false));
+}
+PassOwnPtr<ImageBuffer> GraphicsContextSnapshot::replay(unsigned fromStep, unsigned toStep) const
+{
OwnPtr<ImageBuffer> imageBuffer = createImageBuffer();
FragmentSnapshotPlayer player(m_picture, imageBuffer->context()->canvas());
player.play(fromStep, toStep);
@@ -177,4 +1016,12 @@ PassOwnPtr<ImageBuffer> GraphicsContextSnapshot::createImageBuffer() const
return ImageBuffer::create(IntSize(m_picture->width(), m_picture->height()), m_isCertainlyOpaque ? Opaque : NonOpaque);
}
+PassRefPtr<JSONArray> GraphicsContextSnapshot::snapshotCommandLog() const
+{
+ LoggingCanvas canvas(m_picture->width(), m_picture->height());
+ FragmentSnapshotPlayer player(m_picture, &canvas);
+ player.play(0, 0);
+ return canvas.log();
+}
+
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.h b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.h
index 341fb70fe7f..a7e8b15568b 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextRecorder.h
@@ -31,9 +31,11 @@
#ifndef GraphicsContextRecorder_h
#define GraphicsContextRecorder_h
+#include "platform/JSONValues.h"
#include "platform/PlatformExport.h"
#include "platform/graphics/GraphicsContext.h"
#include "third_party/skia/include/core/SkPicture.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "wtf/RefCounted.h"
namespace WebCore {
@@ -43,8 +45,11 @@ WTF_MAKE_NONCOPYABLE(GraphicsContextSnapshot);
public:
typedef Vector<Vector<double> > Timings;
+ static PassRefPtr<GraphicsContextSnapshot> load(const char*, size_t);
+
PassOwnPtr<ImageBuffer> replay(unsigned fromStep = 0, unsigned toStep = 0) const;
PassOwnPtr<Timings> profile(unsigned minIterations, double minDuration) const;
+ PassRefPtr<JSONArray> snapshotCommandLog() const;
private:
friend class GraphicsContextRecorder;
@@ -66,6 +71,7 @@ public:
private:
RefPtr<SkPicture> m_picture;
OwnPtr<GraphicsContext> m_context;
+ OwnPtr<SkPictureRecorder> m_recorder;
bool m_isCertainlyOpaque;
};
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextState.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextState.cpp
new file mode 100644
index 00000000000..2084636f46e
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextState.cpp
@@ -0,0 +1,256 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "platform/graphics/GraphicsContextState.h"
+
+#include "platform/graphics/skia/SkiaUtils.h"
+
+namespace WebCore {
+
+GraphicsContextState::GraphicsContextState()
+ : m_fillColor(Color::black)
+ , m_fillRule(RULE_NONZERO)
+ , m_textDrawingMode(TextModeFill)
+ , m_alpha(256)
+ , m_xferMode(nullptr)
+ , m_compositeOperator(CompositeSourceOver)
+ , m_blendMode(blink::WebBlendModeNormal)
+ , m_interpolationQuality(InterpolationDefault)
+ , m_saveCount(0)
+ , m_shouldAntialias(true)
+ , m_shouldSmoothFonts(true)
+ , m_shouldClampToSourceRect(true)
+{
+ m_strokePaint.setStyle(SkPaint::kStroke_Style);
+ m_strokePaint.setStrokeWidth(SkFloatToScalar(m_strokeData.thickness()));
+ m_strokePaint.setColor(applyAlpha(m_strokeData.color().rgb()));
+ m_strokePaint.setStrokeCap(SkPaint::kDefault_Cap);
+ m_strokePaint.setStrokeJoin(SkPaint::kDefault_Join);
+ m_strokePaint.setStrokeMiter(SkFloatToScalar(m_strokeData.miterLimit()));
+ m_strokePaint.setFilterLevel(WebCoreInterpolationQualityToSkFilterLevel(m_interpolationQuality));
+ m_strokePaint.setAntiAlias(m_shouldAntialias);
+ m_fillPaint.setColor(applyAlpha(m_fillColor.rgb()));
+ m_fillPaint.setFilterLevel(WebCoreInterpolationQualityToSkFilterLevel(m_interpolationQuality));
+ m_fillPaint.setAntiAlias(m_shouldAntialias);
+}
+
+GraphicsContextState::GraphicsContextState(const GraphicsContextState& other)
+ : m_strokePaint(other.m_strokePaint)
+ , m_fillPaint(other.m_fillPaint)
+ , m_strokeData(other.m_strokeData)
+ , m_fillColor(other.m_fillColor)
+ , m_fillRule(other.m_fillRule)
+ , m_fillGradient(other.m_fillGradient)
+ , m_fillPattern(other.m_fillPattern)
+ , m_looper(other.m_looper)
+ , m_textDrawingMode(other.m_textDrawingMode)
+ , m_alpha(other.m_alpha)
+ , m_xferMode(other.m_xferMode)
+ , m_colorFilter(other.m_colorFilter)
+ , m_compositeOperator(other.m_compositeOperator)
+ , m_blendMode(other.m_blendMode)
+ , m_interpolationQuality(other.m_interpolationQuality)
+ , m_saveCount(0)
+ , m_shouldAntialias(other.m_shouldAntialias)
+ , m_shouldSmoothFonts(other.m_shouldSmoothFonts)
+ , m_shouldClampToSourceRect(other.m_shouldClampToSourceRect) { }
+
+void GraphicsContextState::copy(const GraphicsContextState& source)
+{
+ this->~GraphicsContextState();
+ new (this) GraphicsContextState(source);
+}
+
+const SkPaint& GraphicsContextState::strokePaint(int strokedPathLength) const
+{
+ if (m_strokeData.gradient() && m_strokeData.gradient()->shaderChanged())
+ m_strokePaint.setShader(m_strokeData.gradient()->shader());
+ m_strokeData.setupPaintDashPathEffect(&m_strokePaint, strokedPathLength);
+ return m_strokePaint;
+}
+
+const SkPaint& GraphicsContextState::fillPaint() const
+{
+ if (m_fillGradient && m_fillGradient->shaderChanged())
+ m_fillPaint.setShader(m_fillGradient->shader());
+ return m_fillPaint;
+}
+
+void GraphicsContextState::setStrokeStyle(StrokeStyle style)
+{
+ m_strokeData.setStyle(style);
+}
+
+void GraphicsContextState::setStrokeThickness(float thickness)
+{
+ m_strokeData.setThickness(thickness);
+ m_strokePaint.setStrokeWidth(SkFloatToScalar(thickness));
+}
+
+void GraphicsContextState::setStrokeColor(const Color& color)
+{
+ m_strokeData.clearGradient();
+ m_strokeData.clearPattern();
+ m_strokeData.setColor(color);
+ m_strokePaint.setColor(applyAlpha(color.rgb()));
+ m_strokePaint.setShader(0);
+}
+
+void GraphicsContextState::setStrokeGradient(const PassRefPtr<Gradient> gradient)
+{
+ m_strokeData.setColor(Color::black);
+ m_strokeData.clearPattern();
+ m_strokeData.setGradient(gradient);
+ m_strokePaint.setColor(applyAlpha(SK_ColorBLACK));
+ m_strokePaint.setShader(m_strokeData.gradient()->shader());
+}
+
+void GraphicsContextState::clearStrokeGradient()
+{
+ m_strokeData.clearGradient();
+ ASSERT(!m_strokeData.pattern());
+ m_strokePaint.setColor(applyAlpha(m_strokeData.color().rgb()));
+}
+
+void GraphicsContextState::setStrokePattern(const PassRefPtr<Pattern> pattern)
+{
+ m_strokeData.setColor(Color::black);
+ m_strokeData.clearGradient();
+ m_strokeData.setPattern(pattern);
+ m_strokePaint.setColor(applyAlpha(SK_ColorBLACK));
+ m_strokePaint.setShader(m_strokeData.pattern()->shader());
+}
+
+void GraphicsContextState::clearStrokePattern()
+{
+ m_strokeData.clearPattern();
+ ASSERT(!m_strokeData.gradient());
+ m_strokePaint.setColor(applyAlpha(m_strokeData.color().rgb()));
+}
+
+void GraphicsContextState::setLineCap(LineCap cap)
+{
+ m_strokeData.setLineCap(cap);
+ m_strokePaint.setStrokeCap((SkPaint::Cap)cap);
+}
+
+void GraphicsContextState::setLineJoin(LineJoin join)
+{
+ m_strokeData.setLineJoin(join);
+ m_strokePaint.setStrokeJoin((SkPaint::Join)join);
+}
+
+void GraphicsContextState::setMiterLimit(float miterLimit)
+{
+ m_strokeData.setMiterLimit(miterLimit);
+ m_strokePaint.setStrokeMiter(SkFloatToScalar(miterLimit));
+}
+
+void GraphicsContextState::setFillColor(const Color& color)
+{
+ m_fillColor = color;
+ m_fillGradient.clear();
+ m_fillPattern.clear();
+ m_fillPaint.setColor(applyAlpha(color.rgb()));
+ m_fillPaint.setShader(0);
+}
+
+void GraphicsContextState::setFillGradient(const PassRefPtr<Gradient> gradient)
+{
+ m_fillColor = Color::black;
+ m_fillPattern.clear();
+ m_fillGradient = gradient;
+ m_fillPaint.setColor(applyAlpha(SK_ColorBLACK));
+ m_fillPaint.setShader(m_fillGradient->shader());
+}
+
+void GraphicsContextState::clearFillGradient()
+{
+ m_fillGradient.clear();
+ ASSERT(!m_fillPattern);
+ m_fillPaint.setColor(applyAlpha(m_fillColor.rgb()));
+}
+
+void GraphicsContextState::setFillPattern(const PassRefPtr<Pattern> pattern)
+{
+ m_fillColor = Color::black;
+ m_fillGradient.clear();
+ m_fillPattern = pattern;
+ m_fillPaint.setColor(applyAlpha(SK_ColorBLACK));
+ m_fillPaint.setShader(m_fillPattern->shader());
+}
+
+void GraphicsContextState::clearFillPattern()
+{
+ m_fillPattern.clear();
+ ASSERT(!m_fillGradient);
+ m_fillPaint.setColor(applyAlpha(m_fillColor.rgb()));
+}
+
+// Shadow. (This will need tweaking if we use draw loopers for other things.)
+void GraphicsContextState::setDrawLooper(PassRefPtr<SkDrawLooper> drawLooper)
+{
+ m_looper = drawLooper;
+ m_strokePaint.setLooper(m_looper.get());
+ m_fillPaint.setLooper(m_looper.get());
+}
+
+void GraphicsContextState::clearDrawLooper()
+{
+ m_looper.clear();
+ m_strokePaint.setLooper(0);
+ m_fillPaint.setLooper(0);
+}
+
+void GraphicsContextState::setAlphaAsFloat(float alpha)
+{
+ if (alpha < 0) {
+ m_alpha = 0;
+ } else {
+ m_alpha = roundf(alpha * 256);
+ if (m_alpha > 256)
+ m_alpha = 256;
+ }
+ m_strokePaint.setColor(applyAlpha(m_strokeData.color().rgb()));
+ m_fillPaint.setColor(applyAlpha(m_fillColor.rgb()));
+}
+
+void GraphicsContextState::setLineDash(const DashArray& dashes, float dashOffset)
+{
+ m_strokeData.setLineDash(dashes, dashOffset);
+}
+
+void GraphicsContextState::setColorFilter(PassRefPtr<SkColorFilter> colorFilter)
+{
+ m_colorFilter = colorFilter;
+ m_strokePaint.setColorFilter(m_colorFilter.get());
+ m_fillPaint.setColorFilter(m_colorFilter.get());
+}
+
+void GraphicsContextState::setCompositeOperation(CompositeOperator compositeOperation, blink::WebBlendMode blendMode)
+{
+ m_compositeOperator = compositeOperation;
+ m_blendMode = blendMode;
+ m_xferMode = WebCoreCompositeToSkiaComposite(compositeOperation, blendMode);
+ m_strokePaint.setXfermode(m_xferMode.get());
+ m_fillPaint.setXfermode(m_xferMode.get());
+}
+
+void GraphicsContextState::setInterpolationQuality(InterpolationQuality quality)
+{
+ m_interpolationQuality = quality;
+ m_strokePaint.setFilterLevel(WebCoreInterpolationQualityToSkFilterLevel(quality));
+ m_fillPaint.setFilterLevel(WebCoreInterpolationQualityToSkFilterLevel(quality));
+}
+
+void GraphicsContextState::setShouldAntialias(bool shouldAntialias)
+{
+ m_shouldAntialias = shouldAntialias;
+ m_strokePaint.setAntiAlias(shouldAntialias);
+ m_fillPaint.setAntiAlias(shouldAntialias);
+}
+
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextState.h b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextState.h
index d7e20da33f1..a3adc04d479 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextState.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextState.h
@@ -29,15 +29,15 @@
#ifndef GraphicsContextState_h
#define GraphicsContextState_h
+#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/Gradient.h"
#include "platform/graphics/GraphicsTypes.h"
#include "platform/graphics/Path.h"
#include "platform/graphics/Pattern.h"
#include "platform/graphics/StrokeData.h"
+#include "platform/graphics/skia/SkiaUtils.h"
#include "third_party/skia/include/core/SkColorFilter.h"
-#include "third_party/skia/include/core/SkColorPriv.h"
-#include "third_party/skia/include/core/SkDrawLooper.h"
-#include "third_party/skia/include/effects/SkDashPathEffect.h"
+#include "third_party/skia/include/core/SkPaint.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/RefPtr.h"
@@ -45,96 +45,144 @@ namespace WebCore {
// Encapsulates the state information we store for each pushed graphics state.
// Only GraphicsContext can use this class.
-class GraphicsContextState {
-private:
- friend class GraphicsContext;
-
- GraphicsContextState()
- : m_fillColor(Color::black)
- , m_fillRule(RULE_NONZERO)
- , m_textDrawingMode(TextModeFill)
- , m_alpha(1)
- , m_xferMode(0)
- , m_compositeOperator(CompositeSourceOver)
- , m_blendMode(blink::WebBlendModeNormal)
-#if USE(LOW_QUALITY_IMAGE_INTERPOLATION)
- , m_interpolationQuality(InterpolationLow)
-#else
- , m_interpolationQuality(InterpolationHigh)
-#endif
- , m_shouldAntialias(true)
- , m_shouldSmoothFonts(true)
- , m_shouldClampToSourceRect(true)
+class PLATFORM_EXPORT GraphicsContextState FINAL {
+public:
+ static PassOwnPtr<GraphicsContextState> create()
{
+ return adoptPtr(new GraphicsContextState());
}
- GraphicsContextState(const GraphicsContextState& other)
- : m_strokeData(other.m_strokeData)
- , m_fillColor(other.m_fillColor)
- , m_fillRule(other.m_fillRule)
- , m_fillGradient(other.m_fillGradient)
- , m_fillPattern(other.m_fillPattern)
- , m_looper(other.m_looper)
- , m_textDrawingMode(other.m_textDrawingMode)
- , m_alpha(other.m_alpha)
- , m_xferMode(other.m_xferMode)
- , m_colorFilter(other.m_colorFilter)
- , m_compositeOperator(other.m_compositeOperator)
- , m_blendMode(other.m_blendMode)
- , m_interpolationQuality(other.m_interpolationQuality)
- , m_shouldAntialias(other.m_shouldAntialias)
- , m_shouldSmoothFonts(other.m_shouldSmoothFonts)
- , m_shouldClampToSourceRect(other.m_shouldClampToSourceRect)
+ static PassOwnPtr<GraphicsContextState> createAndCopy(const GraphicsContextState& other)
{
+ return adoptPtr(new GraphicsContextState(other));
}
+ void copy(const GraphicsContextState&);
+
+ // SkPaint objects that reflect the current state. If the length of the
+ // path to be stroked is known, pass it in for correct dash or dot placement.
+ const SkPaint& strokePaint(int strokedPathLength = 0) const;
+ const SkPaint& fillPaint() const;
+
+ uint16_t saveCount() const { return m_saveCount; }
+ void incrementSaveCount() { ++m_saveCount; }
+ void decrementSaveCount() { --m_saveCount; }
+
+ // Stroke data
+ const StrokeData& strokeData() const { return m_strokeData; }
+
+ void setStrokeStyle(StrokeStyle);
+
+ void setStrokeThickness(float);
+
+ SkColor effectiveStrokeColor() const { return applyAlpha(m_strokeData.color().rgb()); }
+ void setStrokeColor(const Color&);
+
+ void setStrokeGradient(const PassRefPtr<Gradient>);
+ void clearStrokeGradient();
+
+ void setStrokePattern(const PassRefPtr<Pattern>);
+ void clearStrokePattern();
+
+ void setLineCap(LineCap);
+
+ void setLineJoin(LineJoin);
+
+ void setMiterLimit(float);
+
+ void setLineDash(const DashArray&, float);
+
+ // Fill data
+ Color fillColor() const { return m_fillColor; }
+ SkColor effectiveFillColor() const { return applyAlpha(m_fillColor.rgb()); }
+ void setFillColor(const Color&);
+
+ Gradient* fillGradient() const { return m_fillGradient.get(); }
+ void setFillGradient(const PassRefPtr<Gradient>);
+ void clearFillGradient();
+
+ Pattern* fillPattern() const { return m_fillPattern.get(); }
+ void setFillPattern(const PassRefPtr<Pattern>);
+ void clearFillPattern();
+
+ // Path fill rule
+ WindRule fillRule() const { return m_fillRule; }
+ void setFillRule(WindRule rule) { m_fillRule = rule; }
+
+ // Shadow. (This will need tweaking if we use draw loopers for other things.)
+ SkDrawLooper* drawLooper() const { return m_looper.get(); }
+ void setDrawLooper(PassRefPtr<SkDrawLooper>);
+ void clearDrawLooper();
+
+ // Text. (See TextModeFill & friends.)
+ TextDrawingModeFlags textDrawingMode() const { return m_textDrawingMode; }
+ void setTextDrawingMode(TextDrawingModeFlags mode) { m_textDrawingMode = mode; }
+
+ // Common shader state.
+ int alpha() const { return m_alpha; }
+ void setAlphaAsFloat(float);
+
+ SkColorFilter* colorFilter() const { return m_colorFilter.get(); }
+ void setColorFilter(PassRefPtr<SkColorFilter>);
+
+ // Compositing control, for the CSS and Canvas compositing spec.
+ void setCompositeOperation(CompositeOperator, blink::WebBlendMode);
+ CompositeOperator compositeOperator() const { return m_compositeOperator; }
+ blink::WebBlendMode blendMode() const { return m_blendMode; }
+ SkXfermode* xferMode() const { return m_xferMode.get(); }
+
+ // Image interpolation control.
+ InterpolationQuality interpolationQuality() const { return m_interpolationQuality; }
+ void setInterpolationQuality(InterpolationQuality);
+
+ bool shouldAntialias() const { return m_shouldAntialias; }
+ void setShouldAntialias(bool);
+
+ bool shouldSmoothFonts() const { return m_shouldSmoothFonts; }
+ void setShouldSmoothFonts(bool shouldSmoothFonts) { m_shouldSmoothFonts = shouldSmoothFonts; }
+
+ bool shouldClampToSourceRect() const { return m_shouldClampToSourceRect; }
+ void setShouldClampToSourceRect(bool shouldClampToSourceRect) { m_shouldClampToSourceRect = shouldClampToSourceRect; }
+
+private:
+ GraphicsContextState();
+ explicit GraphicsContextState(const GraphicsContextState&);
+ GraphicsContextState& operator=(const GraphicsContextState&);
+
// Helper function for applying the state's alpha value to the given input
// color to produce a new output color.
SkColor applyAlpha(SkColor c) const
{
- int s = roundf(m_alpha * 256);
- if (s >= 256)
- return c;
- if (s < 0)
- return 0;
-
- int a = SkAlphaMul(SkColorGetA(c), s);
+ int a = SkAlphaMul(SkColorGetA(c), m_alpha);
return (c & 0x00FFFFFF) | (a << 24);
}
- // Returns a new State with all of this object's inherited properties copied.
- PassOwnPtr<GraphicsContextState> clone() { return adoptPtr(new GraphicsContextState(*this)); }
-
- // Not supported. No implementations.
- void operator=(const GraphicsContextState&);
+ // These are mutbale to enable gradient updates when the paints are fetched for use.
+ mutable SkPaint m_strokePaint;
+ mutable SkPaint m_fillPaint;
- // Stroke.
StrokeData m_strokeData;
- // Fill.
Color m_fillColor;
WindRule m_fillRule;
RefPtr<Gradient> m_fillGradient;
RefPtr<Pattern> m_fillPattern;
- // Shadow. (This will need tweaking if we use draw loopers for other things.)
RefPtr<SkDrawLooper> m_looper;
- // Text. (See TextModeFill & friends.)
TextDrawingModeFlags m_textDrawingMode;
- // Common shader state.
- float m_alpha;
+ int m_alpha;
RefPtr<SkXfermode> m_xferMode;
RefPtr<SkColorFilter> m_colorFilter;
- // Compositing control, for the CSS and Canvas compositing spec.
CompositeOperator m_compositeOperator;
blink::WebBlendMode m_blendMode;
- // Image interpolation control.
InterpolationQuality m_interpolationQuality;
+ uint16_t m_saveCount;
+
bool m_shouldAntialias : 1;
bool m_shouldSmoothFonts : 1;
bool m_shouldClampToSourceRect : 1;
@@ -143,4 +191,3 @@ private:
} // namespace WebCore
#endif // GraphicsContextState_h
-
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp
new file mode 100644
index 00000000000..dbf9861c786
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp
@@ -0,0 +1,1123 @@
+/*
+ * Copyright (C) 2012 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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"
+
+#include "platform/graphics/GraphicsContext.h"
+
+#include "platform/graphics/BitmapImage.h"
+#include "platform/graphics/DisplayList.h"
+#include "platform/graphics/ImageBuffer.h"
+#include "platform/graphics/skia/NativeImageSkia.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkPicture.h"
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+#define EXPECT_EQ_RECT(a, b) \
+ EXPECT_EQ(a.x(), b.x()); \
+ EXPECT_EQ(a.y(), b.y()); \
+ EXPECT_EQ(a.width(), b.width()); \
+ EXPECT_EQ(a.height(), b.height());
+
+#define EXPECT_PIXELS_MATCH(bitmap, opaqueRect) \
+{ \
+ SkAutoLockPixels locker(bitmap); \
+ for (int y = opaqueRect.y(); y < opaqueRect.maxY(); ++y) \
+ for (int x = opaqueRect.x(); x < opaqueRect.maxX(); ++x) { \
+ int alpha = *bitmap.getAddr32(x, y) >> 24; \
+ EXPECT_EQ(255, alpha); \
+ } \
+}
+
+#define EXPECT_PIXELS_MATCH_EXACT(bitmap, opaqueRect) \
+{ \
+ SkAutoLockPixels locker(bitmap); \
+ for (int y = 0; y < bitmap.height(); ++y) \
+ for (int x = 0; x < bitmap.width(); ++x) { \
+ int alpha = *bitmap.getAddr32(x, y) >> 24; \
+ bool opaque = opaqueRect.contains(x, y); \
+ EXPECT_EQ(opaque, alpha == 255); \
+ } \
+}
+
+TEST(GraphicsContextTest, trackOpaqueTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), alpha, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(99, 13, 10, 90), opaque, CompositePlusLighter);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(99, 13, 10, 90), opaque, CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(99, 13, 10, 90), alpha, CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(10, 10, 89, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(8, 8, 3, 90), opaque, CompositeSourceOut);
+ EXPECT_EQ_RECT(IntRect(11, 10, 88, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(30, 30, 290, 290), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(40, 20, 290, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 390, 50), opaque, CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 390, 50), alpha);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 390, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 10, 290, 310), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueClipTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.save();
+ context.clip(FloatRect(0, 0, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.save();
+ context.clip(FloatRect(20, 20, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ // The intersection of the two clips becomes empty.
+ context.clip(FloatRect(30, 20, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ // The transform and the clip need to interact correctly (transform first)
+ context.save();
+ context.translate(10, 10);
+ context.clip(FloatRect(20, 20, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 30, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ // The transform and the clip need to interact correctly (clip first)
+ context.save();
+ context.clip(FloatRect(20, 20, 10, 10));
+ context.translate(10, 10);
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ Path path;
+ path.moveTo(FloatPoint(0, 0));
+ path.addLineTo(FloatPoint(100, 0));
+
+ // Non-rectangular clips just cause the paint to be considered non-opaque.
+ context.save();
+ context.clipPath(path, RULE_EVENODD);
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ // Another non-rectangular clip.
+ context.save();
+ context.clip(IntRect(30, 30, 20, 20));
+ context.clipOut(IntRect(30, 30, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+}
+
+TEST(GraphicsContextTest, trackImageMask)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
+ // out a transparency layer below that is filled with the mask color. In the end this should
+ // not be marked opaque.
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.beginTransparencyLayer(1);
+ context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
+
+ context.setCompositeOperation(CompositeDestinationIn);
+ context.beginTransparencyLayer(1);
+
+ OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
+ alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
+
+ context.endLayer();
+ context.endLayer();
+
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackImageMaskWithOpaqueRect)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
+ // out a transparency layer below that is filled with the mask color. In the end this should
+ // not be marked opaque.
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.beginTransparencyLayer(1);
+ context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
+
+ context.setCompositeOperation(CompositeDestinationIn);
+ context.beginTransparencyLayer(1);
+
+ OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
+ alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
+
+ // We can't have an opaque mask actually, but we can pretend here like it would look if we did.
+ context.fillRect(FloatRect(12, 12, 3, 3), opaque, CompositeSourceOver);
+
+ context.endLayer();
+ context.endLayer();
+
+ EXPECT_EQ_RECT(IntRect(12, 12, 3, 3), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueJoinTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(31, 20, 10, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(30, 20, 10, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(20, 31, 20, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(20, 30, 20, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(9, 20, 10, 20), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(10, 20, 10, 20), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(10, 9, 30, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(10, 10, 30, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 30, 30), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueLineTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.setShouldAntialias(false);
+ context.setMiterLimit(0);
+ context.setStrokeThickness(4);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+ context.setCompositeOperation(CompositeSourceOver);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(opaque);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(true);
+ context.setCompositeOperation(CompositeSourceOver);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(false);
+ context.save();
+ context.setStrokeColor(opaque);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(true);
+ context.save();
+ context.setStrokeColor(opaque);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaquePathTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(false);
+ context.setMiterLimit(1);
+ context.setStrokeThickness(5);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+ context.setCompositeOperation(CompositeSourceIn);
+
+ Path path;
+
+ context.setFillColor(alpha);
+ path.moveTo(FloatPoint(0, 0));
+ path.addLineTo(FloatPoint(100, 0));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ path.clear();
+
+ context.setFillColor(opaque);
+ path.moveTo(FloatPoint(0, 10));
+ path.addLineTo(FloatPoint(100, 13));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ path.clear();
+
+ context.setFillColor(alpha);
+ path.moveTo(FloatPoint(0, 10));
+ path.addLineTo(FloatPoint(100, 13));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ path.clear();
+
+ context.setFillColor(alpha);
+ path.moveTo(FloatPoint(0, 14));
+ path.addLineTo(FloatPoint(100, 10));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ path.clear();
+}
+
+TEST(GraphicsContextTest, trackOpaqueImageTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ SkBitmap opaqueBitmap;
+ ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */));
+
+ for (int y = 0; y < opaqueBitmap.height(); ++y)
+ for (int x = 0; x < opaqueBitmap.width(); ++x)
+ *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
+ RefPtr<BitmapImage> opaqueImage = BitmapImage::create(NativeImageSkia::create(opaqueBitmap));
+ EXPECT_TRUE(opaqueImage->currentFrameKnownToBeOpaque());
+
+ SkBitmap alphaBitmap;
+ ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10));
+
+ for (int y = 0; y < alphaBitmap.height(); ++y)
+ for (int x = 0; x < alphaBitmap.width(); ++x)
+ *alphaBitmap.getAddr32(x, y) = 0x00000000;
+ RefPtr<BitmapImage> alphaImage = BitmapImage::create(NativeImageSkia::create(alphaBitmap));
+ EXPECT_FALSE(alphaImage->currentFrameKnownToBeOpaque());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(opaqueImage.get(), IntPoint(0, 0));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.drawImage(alphaImage.get(), IntPoint(0, 0));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(opaqueImage.get(), IntPoint(5, 5));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.drawImage(alphaImage.get(), IntPoint(5, 5));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(opaqueImage.get(), IntPoint(10, 10));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.drawImage(alphaImage.get(), IntPoint(10, 10));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(alphaImage.get(), IntPoint(20, 10), CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setAlphaAsFloat(0.5);
+ context.drawImage(opaqueImage.get(), IntPoint(25, 15), CompositeSourceIn);
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 25, 90, 75), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(alphaImage.get(), IntPoint(10, 20), CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(20, 10, 80, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setAlphaAsFloat(0.5);
+ context.drawImage(opaqueImage.get(), IntPoint(15, 25), CompositeSourceIn);
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(25, 10, 75, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueOvalTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillEllipse(FloatRect(10, 10, 90, 90));
+ context.strokeEllipse(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+
+ context.setShouldAntialias(false);
+
+ context.setFillColor(opaque);
+ context.fillEllipse(FloatRect(10, 10, 50, 30));
+ context.strokeEllipse(FloatRect(10, 10, 50, 30));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setFillColor(alpha);
+ context.fillEllipse(FloatRect(10, 10, 30, 50));
+ context.strokeEllipse(FloatRect(10, 10, 30, 50));
+ EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(true);
+
+ context.setFillColor(opaque);
+ context.fillEllipse(FloatRect(10, 10, 50, 30));
+ context.strokeEllipse(FloatRect(10, 10, 50, 30));
+ EXPECT_EQ_RECT(IntRect(40, 41, 60, 59), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setFillColor(alpha);
+ context.fillEllipse(FloatRect(20, 10, 30, 50));
+ context.strokeEllipse(FloatRect(20, 10, 30, 50));
+ EXPECT_EQ_RECT(IntRect(51, 41, 49, 59), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueRoundedRectTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+ IntSize radii(10, 10);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRoundedRect(IntRect(10, 10, 90, 90), radii, radii, radii, radii, opaque);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+ context.setShouldAntialias(false);
+
+ context.fillRoundedRect(IntRect(10, 10, 50, 30), radii, radii, radii, radii, opaque);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRoundedRect(IntRect(10, 10, 30, 50), radii, radii, radii, radii, alpha);
+ EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRoundedRect(IntRect(10, 0, 50, 30), radii, radii, radii, radii, alpha);
+ EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRoundedRect(IntRect(30, 0, 70, 50), radii, radii, radii, radii, opaque);
+ EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueTextTest)
+{
+ int width = 200, height = 200;
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(width, height));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+ SkRect textRect = SkRect::MakeWH(width, height);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ SkPaint opaquePaint;
+ opaquePaint.setColor(opaque.rgb());
+ opaquePaint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ SkPaint alphaPaint;
+ alphaPaint.setColor(alpha.rgb());
+ alphaPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ SkPoint point = SkPoint::Make(0, 0);
+
+ context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawPosText("A", 1, &point, textRect, opaquePaint);
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawPosText("A", 1, &point, textRect, alphaPaint);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueWritePixelsTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+
+ SkBitmap opaqueBitmap;
+ ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */));
+ for (int y = 0; y < opaqueBitmap.height(); ++y)
+ for (int x = 0; x < opaqueBitmap.width(); ++x)
+ *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
+
+ SkBitmap alphaBitmap;
+ ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10));
+ for (int y = 0; y < alphaBitmap.height(); ++y)
+ for (int x = 0; x < alphaBitmap.width(); ++x)
+ *alphaBitmap.getAddr32(x, y) = 0x00000000;
+
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ context.writePixels(opaqueBitmap, 50, 50);
+ EXPECT_EQ_RECT(IntRect(50, 50, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.writePixels(alphaBitmap, 10, 0);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.writePixels(alphaBitmap, 10, 1);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.writePixels(alphaBitmap, 0, 10);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.writePixels(alphaBitmap, 1, 10);
+ EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueDrawBitmapTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+
+ SkBitmap opaqueBitmap;
+ ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */));
+ for (int y = 0; y < opaqueBitmap.height(); ++y)
+ for (int x = 0; x < opaqueBitmap.width(); ++x)
+ *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
+
+ SkBitmap alphaBitmap;
+ ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10));
+ for (int y = 0; y < alphaBitmap.height(); ++y)
+ for (int x = 0; x < alphaBitmap.width(); ++x)
+ *alphaBitmap.getAddr32(x, y) = 0x00000000;
+
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ context.drawBitmap(opaqueBitmap, 10, 10, &paint);
+ EXPECT_EQ_RECT(IntRect(10, 10, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmap(alphaBitmap, 10, 0, &paint);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmap(alphaBitmap, 10, 1, &paint);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmap(alphaBitmap, 0, 10, &paint);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmap(alphaBitmap, 1, 10, &paint);
+ EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueDrawBitmapRectTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+
+ SkBitmap opaqueBitmap;
+ ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */));
+ for (int y = 0; y < opaqueBitmap.height(); ++y)
+ for (int x = 0; x < opaqueBitmap.width(); ++x)
+ *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
+
+ SkBitmap alphaBitmap;
+ ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10));
+ for (int y = 0; y < alphaBitmap.height(); ++y)
+ for (int x = 0; x < alphaBitmap.width(); ++x)
+ *alphaBitmap.getAddr32(x, y) = 0x00000000;
+
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ context.drawBitmapRect(opaqueBitmap, 0, SkRect::MakeXYWH(10, 10, 90, 90), &paint);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 10), &paint);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 11), &paint);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 10, 10), &paint);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 11, 10), &paint);
+ EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, contextTransparencyLayerTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.clearRect(FloatRect(20, 20, 10, 10));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.beginTransparencyLayer(0.5);
+ context.save();
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
+ context.restore();
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.clearRect(FloatRect(20, 20, 10, 10));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.beginTransparencyLayer(0.5);
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, UnboundedDrawsAreClipped)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ Path path;
+ context.setShouldAntialias(false);
+ context.setMiterLimit(1);
+ context.setStrokeThickness(5);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+
+ // Make skia unable to compute fast bounds for our paths.
+ DashArray dashArray;
+ dashArray.append(1);
+ dashArray.append(0);
+ context.setLineDash(dashArray, 0);
+
+ // Make the device opaque in 10,10 40x40.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+
+ // Clip to the left edge of the opaque area.
+ context.clip(IntRect(10, 10, 10, 40));
+
+ // Draw a path that gets clipped. This should destroy the opaque area but only inside the clip.
+ context.setCompositeOperation(CompositeSourceOut);
+ context.setFillColor(alpha);
+ path.moveTo(FloatPoint(10, 10));
+ path.addLineTo(FloatPoint(40, 40));
+ context.strokePath(path);
+
+ EXPECT_EQ_RECT(IntRect(20, 10, 30, 40), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, PreserveOpaqueOnlyMattersForFirstLayer)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ Path path;
+ context.setShouldAntialias(false);
+ context.setMiterLimit(1);
+ context.setStrokeThickness(5);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+
+ // Make skia unable to compute fast bounds for our paths.
+ DashArray dashArray;
+ dashArray.append(1);
+ dashArray.append(0);
+ context.setLineDash(dashArray, 0);
+
+ // Make the device opaque in 10,10 40x40.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+
+ // Begin a layer that preserves opaque.
+ context.setCompositeOperation(CompositeSourceOver);
+ context.beginTransparencyLayer(0.5);
+
+ // Begin a layer that does not preserve opaque.
+ context.setCompositeOperation(CompositeSourceOut);
+ context.beginTransparencyLayer(0.5);
+
+ // This should not destroy the device opaqueness.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
+
+ // This should not destroy the device opaqueness either.
+ context.setFillColor(opaque);
+ path.moveTo(FloatPoint(10, 10));
+ path.addLineTo(FloatPoint(40, 40));
+ context.strokePath(path);
+
+ context.endLayer();
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+
+ // Now begin a layer that does not preserve opaque and draw through it to the device.
+ context.setCompositeOperation(CompositeSourceOut);
+ context.beginTransparencyLayer(0.5);
+
+ // This should destroy the device opaqueness.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
+
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+
+ // Now we draw with a path for which it cannot compute fast bounds. This should destroy the entire opaque region.
+
+ context.setCompositeOperation(CompositeSourceOut);
+ context.beginTransparencyLayer(0.5);
+
+ // This should nuke the device opaqueness.
+ context.setFillColor(opaque);
+ path.moveTo(FloatPoint(10, 10));
+ path.addLineTo(FloatPoint(40, 40));
+ context.strokePath(path);
+
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+}
+
+#define DISPATCH1(c1, c2, op, param1) do { c1.op(param1); c2.op(param1); } while (0);
+#define DISPATCH2(c1, c2, op, param1, param2) do { c1.op(param1, param2); c2.op(param1, param2); } while (0);
+
+TEST(GraphicsContextTest, RecordingTotalMatrix)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+ GraphicsContext context(&canvas);
+
+ SkCanvas controlCanvas(400, 400);
+ GraphicsContext controlContext(&controlCanvas);
+
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+ DISPATCH2(context, controlContext, scale, 2, 2);
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+
+ controlContext.save();
+ context.beginRecording(FloatRect(0, 0, 200, 200));
+ DISPATCH2(context, controlContext, translate, 10, 10);
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+
+ controlContext.save();
+ context.beginRecording(FloatRect(10, 10, 100, 100));
+ DISPATCH1(context, controlContext, rotate, 45);
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+
+ controlContext.restore();
+ context.endRecording();
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+
+ controlContext.restore();
+ context.endRecording();
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+}
+
+TEST(GraphicsContextTest, DisplayList)
+{
+ FloatRect rect(0, 0, 1, 1);
+ RefPtr<DisplayList> dl = adoptRef(new DisplayList(rect));
+
+ // picture() returns 0 initially
+ SkPicture* pic = dl->picture();
+ EXPECT_FALSE(pic);
+
+ // endRecording without a beginRecording does nothing
+ dl->endRecording();
+ pic = dl->picture();
+ EXPECT_FALSE(pic);
+
+ // Two beginRecordings in a row generate two canvases.
+ // Unfortunately the new one could be allocated in the same
+ // spot as the old one so ref the first one to prolong its life.
+ IntSize size(1, 1);
+ SkCanvas* canvas1 = dl->beginRecording(size);
+ EXPECT_TRUE(canvas1);
+ canvas1->ref();
+ SkCanvas* canvas2 = dl->beginRecording(size);
+ EXPECT_TRUE(canvas2);
+
+ EXPECT_NE(canvas1, canvas2);
+ EXPECT_EQ(1, canvas1->getRefCnt());
+ canvas1->unref();
+
+ EXPECT_TRUE(dl->isRecording());
+
+ // picture() returns 0 during recording
+ pic = dl->picture();
+ EXPECT_FALSE(pic);
+
+ // endRecording finally makes the picture accessible
+ dl->endRecording();
+ pic = dl->picture();
+ EXPECT_TRUE(pic);
+ EXPECT_EQ(1, pic->getRefCnt());
+}
+
+} // namespace
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
index d256fc7a0c1..6129a2e721f 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -31,8 +31,8 @@
#include "SkMatrix44.h"
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/LayoutRect.h"
-#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/GraphicsLayerFactory.h"
+#include "platform/graphics/Image.h"
#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
#include "platform/graphics/skia/NativeImageSkia.h"
#include "platform/scroll/ScrollableArea.h"
@@ -52,6 +52,8 @@
#include "wtf/HashSet.h"
#include "wtf/text/WTFString.h"
+#include <algorithm>
+
#ifndef NDEBUG
#include <stdio.h>
#endif
@@ -78,12 +80,12 @@ PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, G
GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
: m_client(client)
- , m_anchorPoint(0.5f, 0.5f, 0)
+ , m_backgroundColor(Color::transparent)
, m_opacity(1)
- , m_zPosition(0)
, m_blendMode(blink::WebBlendModeNormal)
+ , m_hasTransformOrigin(false)
, m_contentsOpaque(false)
- , m_preserves3D(false)
+ , m_shouldFlattenTransform(true)
, m_backfaceVisibility(true)
, m_masksToBounds(false)
, m_drawsContent(false)
@@ -92,7 +94,6 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
, m_hasScrollParent(false)
, m_hasClipParent(false)
, m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip)
- , m_contentsOrientation(CompositingCoordinatesTopDown)
, m_parent(0)
, m_maskLayer(0)
, m_contentsClippingMaskLayer(0)
@@ -102,8 +103,7 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
, m_contentsLayer(0)
, m_contentsLayerId(0)
, m_scrollableArea(0)
- , m_compositingReasons(blink::CompositingReasonUnknown)
- , m_debugInfo(0)
+ , m_3dRenderingContext(0)
{
#ifndef NDEBUG
if (m_client)
@@ -147,6 +147,8 @@ void GraphicsLayer::setParent(GraphicsLayer* layer)
m_parent = layer;
}
+#if ASSERT_ENABLED
+
bool GraphicsLayer::hasAncestor(GraphicsLayer* ancestor) const
{
for (GraphicsLayer* curr = parent(); curr; curr = curr->parent()) {
@@ -157,7 +159,9 @@ bool GraphicsLayer::hasAncestor(GraphicsLayer* ancestor) const
return false;
}
-bool GraphicsLayer::setChildren(const Vector<GraphicsLayer*>& newChildren)
+#endif
+
+bool GraphicsLayer::setChildren(const GraphicsLayerVector& newChildren)
{
// If the contents of the arrays are the same, nothing to do.
if (newChildren == m_children)
@@ -278,8 +282,8 @@ bool GraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChil
void GraphicsLayer::removeAllChildren()
{
- while (m_children.size()) {
- GraphicsLayer* curLayer = m_children[0];
+ while (!m_children.isEmpty()) {
+ GraphicsLayer* curLayer = m_children.last();
ASSERT(curLayer->parent());
curLayer->removeFromParent();
}
@@ -288,14 +292,8 @@ void GraphicsLayer::removeAllChildren()
void GraphicsLayer::removeFromParent()
{
if (m_parent) {
- unsigned i;
- for (i = 0; i < m_parent->m_children.size(); i++) {
- if (this == m_parent->m_children[i]) {
- m_parent->m_children.remove(i);
- break;
- }
- }
-
+ // We use reverseFind so that removeAllChildren() isn't n^2.
+ m_parent->m_children.remove(m_parent->m_children.reverseFind(this));
setParent(0);
}
@@ -339,34 +337,6 @@ void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const I
m_client->paintContents(this, context, m_paintingPhase, clip);
}
-void GraphicsLayer::setZPosition(float position)
-{
- m_zPosition = position;
-}
-
-float GraphicsLayer::accumulatedOpacity() const
-{
- if (!preserves3D())
- return 1;
-
- return m_opacity * (parent() ? parent()->accumulatedOpacity() : 1);
-}
-
-void GraphicsLayer::distributeOpacity(float accumulatedOpacity)
-{
- // If this is a transform layer we need to distribute our opacity to all our children
-
- // Incoming accumulatedOpacity is the contribution from our parent(s). We mutiply this by our own
- // opacity to get the total contribution
- accumulatedOpacity *= m_opacity;
-
- if (preserves3D()) {
- size_t numChildren = children().size();
- for (size_t i = 0; i < numChildren; ++i)
- children()[i]->distributeOpacity(accumulatedOpacity);
- }
-}
-
void GraphicsLayer::updateChildList()
{
WebLayer* childHost = m_layer->layer();
@@ -381,13 +351,8 @@ void GraphicsLayer::updateChildList()
childHost->addChild(m_contentsLayer);
}
- const Vector<GraphicsLayer*>& childLayers = children();
- size_t numChildren = childLayers.size();
- for (size_t i = 0; i < numChildren; ++i) {
- GraphicsLayer* curChild = childLayers[i];
-
- childHost->addChild(curChild->platformLayer());
- }
+ for (size_t i = 0; i < m_children.size(); ++i)
+ childHost->addChild(m_children[i]->platformLayer());
for (size_t i = 0; i < m_linkHighlights.size(); ++i)
childHost->addChild(m_linkHighlights[i]->layer());
@@ -482,7 +447,7 @@ void GraphicsLayer::setupContentsLayer(WebLayer* contentsLayer)
m_contentsLayerId = m_contentsLayer->id();
m_contentsLayer->setWebLayerClient(this);
- m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
+ m_contentsLayer->setTransformOrigin(FloatPoint3D());
m_contentsLayer->setUseParentBackfaceVisibility(true);
// It is necessary to call setDrawsContent as soon as we receive the new contentsLayer, for
@@ -494,6 +459,8 @@ void GraphicsLayer::setupContentsLayer(WebLayer* contentsLayer)
m_layer->layer()->insertChild(m_contentsLayer, 0);
WebLayer* borderWebLayer = m_contentsClippingMaskLayer ? m_contentsClippingMaskLayer->platformLayer() : 0;
m_contentsLayer->setMaskLayer(borderWebLayer);
+
+ m_contentsLayer->setRenderingContext(m_3dRenderingContext);
}
void GraphicsLayer::clearContentsLayerIfUnregistered()
@@ -505,18 +472,16 @@ void GraphicsLayer::clearContentsLayerIfUnregistered()
m_contentsLayerId = 0;
}
-void GraphicsLayer::setDebugInfo(blink::WebGraphicsLayerDebugInfo* debugInfo)
+GraphicsLayerDebugInfo& GraphicsLayer::debugInfo()
{
- if (m_debugInfo)
- delete m_debugInfo;
- m_debugInfo = debugInfo;
+ return m_debugInfo;
}
-blink::WebGraphicsLayerDebugInfo* GraphicsLayer::takeDebugInfo()
+blink::WebGraphicsLayerDebugInfo* GraphicsLayer::takeDebugInfoFor(WebLayer* layer)
{
- blink::WebGraphicsLayerDebugInfo* tempDebugInfo = m_debugInfo;
- m_debugInfo = 0;
- return tempDebugInfo;
+ GraphicsLayerDebugInfo* clone = m_debugInfo.clone();
+ clone->setDebugName(debugName(layer));
+ return clone;
}
WebLayer* GraphicsLayer::contentsLayerIfRegistered()
@@ -525,15 +490,6 @@ WebLayer* GraphicsLayer::contentsLayerIfRegistered()
return m_contentsLayer;
}
-double GraphicsLayer::backingStoreMemoryEstimate() const
-{
- if (!drawsContent())
- return 0;
-
- // Effects of page and device scale are ignored; subclasses should override to take these into account.
- return static_cast<double>(4 * size().width()) * size().height();
-}
-
void GraphicsLayer::resetTrackedRepaints()
{
repaintRectMap().remove(this);
@@ -563,10 +519,10 @@ void GraphicsLayer::collectTrackedRepaintRects(Vector<FloatRect>& rects) const
RepaintMap::iterator repaintIt = repaintRectMap().find(this);
if (repaintIt != repaintRectMap().end())
- rects.append(repaintIt->value);
+ rects.appendVector(repaintIt->value);
}
-void GraphicsLayer::dumpLayer(TextStream& ts, int indent, LayerTreeFlags flags) const
+void GraphicsLayer::dumpLayer(TextStream& ts, int indent, LayerTreeFlags flags, RenderingContextMap& renderingContextMap) const
{
writeIndent(ts, indent);
ts << "(" << "GraphicsLayer";
@@ -577,12 +533,23 @@ void GraphicsLayer::dumpLayer(TextStream& ts, int indent, LayerTreeFlags flags)
}
ts << "\n";
- dumpProperties(ts, indent, flags);
+ dumpProperties(ts, indent, flags, renderingContextMap);
writeIndent(ts, indent);
ts << ")\n";
}
-void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeFlags flags) const
+static bool compareFloatRects(const FloatRect& a, const FloatRect& b)
+{
+ if (a.x() != b.x())
+ return a.x() > b.x();
+ if (a.y() != b.y())
+ return a.y() > b.y();
+ if (a.width() != b.width())
+ return a.width() > b.width();
+ return a.height() > b.height();
+}
+
+void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeFlags flags, RenderingContextMap& renderingContextMap) const
{
if (m_position != FloatPoint()) {
writeIndent(ts, indent + 1);
@@ -594,9 +561,9 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeFlags fl
ts << "(bounds origin " << m_boundsOrigin.x() << " " << m_boundsOrigin.y() << ")\n";
}
- if (m_anchorPoint != FloatPoint3D(0.5f, 0.5f, 0)) {
+ if (m_hasTransformOrigin && m_transformOrigin != FloatPoint3D(m_size.width() * 0.5f, m_size.height() * 0.5f, 0)) {
writeIndent(ts, indent + 1);
- ts << "(anchor " << m_anchorPoint.x() << " " << m_anchorPoint.y() << ")\n";
+ ts << "(transformOrigin " << m_transformOrigin.x() << " " << m_transformOrigin.y() << ")\n";
}
if (m_size != IntSize()) {
@@ -624,9 +591,21 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeFlags fl
ts << "(contentsOpaque " << m_contentsOpaque << ")\n";
}
- if (m_preserves3D) {
+ if (!m_shouldFlattenTransform) {
+ writeIndent(ts, indent + 1);
+ ts << "(shouldFlattenTransform " << m_shouldFlattenTransform << ")\n";
+ }
+
+ if (m_3dRenderingContext) {
+ RenderingContextMap::const_iterator it = renderingContextMap.find(m_3dRenderingContext);
+ int contextId = renderingContextMap.size() + 1;
+ if (it == renderingContextMap.end())
+ renderingContextMap.set(m_3dRenderingContext, contextId);
+ else
+ contextId = it->value;
+
writeIndent(ts, indent + 1);
- ts << "(preserves3D " << m_preserves3D << ")\n";
+ ts << "(3dRenderingContext " << contextId << ")\n";
}
if (m_drawsContent) {
@@ -654,7 +633,7 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeFlags fl
ts << ")\n";
}
- if (m_backgroundColor.isValid() && m_backgroundColor != Color::transparent) {
+ if (m_backgroundColor.alpha()) {
writeIndent(ts, indent + 1);
ts << "(backgroundColor " << m_backgroundColor.nameForRenderTreeAsText() << ")\n";
}
@@ -668,24 +647,13 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeFlags fl
ts << "[" << m_transform.m41() << " " << m_transform.m42() << " " << m_transform.m43() << " " << m_transform.m44() << "])\n";
}
- // Avoid dumping the sublayer transform on the root layer, because it's used for geometry flipping, whose behavior
- // differs between platforms.
- if (parent() && !m_childrenTransform.isIdentity()) {
- writeIndent(ts, indent + 1);
- ts << "(childrenTransform ";
- ts << "[" << m_childrenTransform.m11() << " " << m_childrenTransform.m12() << " " << m_childrenTransform.m13() << " " << m_childrenTransform.m14() << "] ";
- ts << "[" << m_childrenTransform.m21() << " " << m_childrenTransform.m22() << " " << m_childrenTransform.m23() << " " << m_childrenTransform.m24() << "] ";
- ts << "[" << m_childrenTransform.m31() << " " << m_childrenTransform.m32() << " " << m_childrenTransform.m33() << " " << m_childrenTransform.m34() << "] ";
- ts << "[" << m_childrenTransform.m41() << " " << m_childrenTransform.m42() << " " << m_childrenTransform.m43() << " " << m_childrenTransform.m44() << "])\n";
- }
-
if (m_replicaLayer) {
writeIndent(ts, indent + 1);
ts << "(replica layer";
if (flags & LayerTreeIncludesDebugInfo)
ts << " " << m_replicaLayer;
ts << ")\n";
- m_replicaLayer->dumpLayer(ts, indent + 2, flags);
+ m_replicaLayer->dumpLayer(ts, indent + 2, flags, renderingContextMap);
}
if (m_replicatedLayer) {
@@ -697,47 +665,49 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeFlags fl
}
if ((flags & LayerTreeIncludesRepaintRects) && repaintRectMap().contains(this) && !repaintRectMap().get(this).isEmpty()) {
+ Vector<FloatRect> repaintRectsCopy = repaintRectMap().get(this);
+ std::sort(repaintRectsCopy.begin(), repaintRectsCopy.end(), &compareFloatRects);
writeIndent(ts, indent + 1);
ts << "(repaint rects\n";
- for (size_t i = 0; i < repaintRectMap().get(this).size(); ++i) {
- if (repaintRectMap().get(this)[i].isEmpty())
+ for (size_t i = 0; i < repaintRectsCopy.size(); ++i) {
+ if (repaintRectsCopy[i].isEmpty())
continue;
writeIndent(ts, indent + 2);
ts << "(rect ";
- ts << repaintRectMap().get(this)[i].x() << " ";
- ts << repaintRectMap().get(this)[i].y() << " ";
- ts << repaintRectMap().get(this)[i].width() << " ";
- ts << repaintRectMap().get(this)[i].height();
+ ts << repaintRectsCopy[i].x() << " ";
+ ts << repaintRectsCopy[i].y() << " ";
+ ts << repaintRectsCopy[i].width() << " ";
+ ts << repaintRectsCopy[i].height();
ts << ")\n";
}
writeIndent(ts, indent + 1);
ts << ")\n";
}
- if ((flags & LayerTreeIncludesPaintingPhases) && paintingPhase()) {
+ if ((flags & LayerTreeIncludesPaintingPhases) && m_paintingPhase) {
writeIndent(ts, indent + 1);
ts << "(paintingPhases\n";
- if (paintingPhase() & GraphicsLayerPaintBackground) {
+ if (m_paintingPhase & GraphicsLayerPaintBackground) {
writeIndent(ts, indent + 2);
ts << "GraphicsLayerPaintBackground\n";
}
- if (paintingPhase() & GraphicsLayerPaintForeground) {
+ if (m_paintingPhase & GraphicsLayerPaintForeground) {
writeIndent(ts, indent + 2);
ts << "GraphicsLayerPaintForeground\n";
}
- if (paintingPhase() & GraphicsLayerPaintMask) {
+ if (m_paintingPhase & GraphicsLayerPaintMask) {
writeIndent(ts, indent + 2);
ts << "GraphicsLayerPaintMask\n";
}
- if (paintingPhase() & GraphicsLayerPaintChildClippingMask) {
+ if (m_paintingPhase & GraphicsLayerPaintChildClippingMask) {
writeIndent(ts, indent + 2);
ts << "GraphicsLayerPaintChildClippingMask\n";
}
- if (paintingPhase() & GraphicsLayerPaintOverflowContents) {
+ if (m_paintingPhase & GraphicsLayerPaintOverflowContents) {
writeIndent(ts, indent + 2);
ts << "GraphicsLayerPaintOverflowContents\n";
}
- if (paintingPhase() & GraphicsLayerPaintCompositedScroll) {
+ if (m_paintingPhase & GraphicsLayerPaintCompositedScroll) {
writeIndent(ts, indent + 2);
ts << "GraphicsLayerPaintCompositedScroll\n";
}
@@ -756,13 +726,26 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeFlags fl
}
}
+ if (flags & LayerTreeIncludesDebugInfo) {
+ writeIndent(ts, indent + 1);
+ ts << "(compositingReasons\n";
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(compositingReasonStringMap); ++i) {
+ if (m_debugInfo.compositingReasons() & compositingReasonStringMap[i].reason) {
+ writeIndent(ts, indent + 2);
+ ts << compositingReasonStringMap[i].description << "\n";
+ }
+ }
+ writeIndent(ts, indent + 1);
+ ts << ")\n";
+ }
+
if (m_children.size()) {
writeIndent(ts, indent + 1);
ts << "(children " << m_children.size() << "\n";
unsigned i;
for (i = 0; i < m_children.size(); i++)
- m_children[i]->dumpLayer(ts, indent + 2, flags);
+ m_children[i]->dumpLayer(ts, indent + 2, flags, renderingContextMap);
writeIndent(ts, indent + 1);
ts << ")\n";
}
@@ -772,11 +755,12 @@ String GraphicsLayer::layerTreeAsText(LayerTreeFlags flags) const
{
TextStream ts;
- dumpLayer(ts, 0, flags);
+ RenderingContextMap renderingContextMap;
+ dumpLayer(ts, 0, flags, renderingContextMap);
return ts.release();
}
-blink::WebString GraphicsLayer::debugName(blink::WebLayer* webLayer)
+String GraphicsLayer::debugName(blink::WebLayer* webLayer) const
{
String name;
if (!m_client)
@@ -802,23 +786,20 @@ blink::WebString GraphicsLayer::debugName(blink::WebLayer* webLayer)
return name;
}
-void GraphicsLayer::setCompositingReasons(blink::WebCompositingReasons reasons)
+void GraphicsLayer::setCompositingReasons(CompositingReasons reasons)
{
- m_compositingReasons = reasons;
- m_layer->layer()->setCompositingReasons(reasons);
+ m_debugInfo.setCompositingReasons(reasons);
}
-void GraphicsLayer::setPosition(const FloatPoint& point)
+void GraphicsLayer::setOwnerNodeId(int nodeId)
{
- m_position = point;
- platformLayer()->setPosition(m_position);
+ m_debugInfo.setOwnerNodeId(nodeId);
}
-void GraphicsLayer::setAnchorPoint(const FloatPoint3D& point)
+void GraphicsLayer::setPosition(const FloatPoint& point)
{
- m_anchorPoint = point;
- platformLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
- platformLayer()->setAnchorPointZ(m_anchorPoint.z());
+ m_position = point;
+ platformLayer()->setPosition(m_position);
}
void GraphicsLayer::setSize(const FloatSize& size)
@@ -845,19 +826,33 @@ void GraphicsLayer::setTransform(const TransformationMatrix& transform)
platformLayer()->setTransform(TransformationMatrix::toSkMatrix44(m_transform));
}
-void GraphicsLayer::setChildrenTransform(const TransformationMatrix& transform)
+void GraphicsLayer::setTransformOrigin(const FloatPoint3D& transformOrigin)
{
- m_childrenTransform = transform;
- platformLayer()->setSublayerTransform(TransformationMatrix::toSkMatrix44(m_childrenTransform));
+ m_hasTransformOrigin = true;
+ m_transformOrigin = transformOrigin;
+ platformLayer()->setTransformOrigin(transformOrigin);
}
-void GraphicsLayer::setPreserves3D(bool preserves3D)
+void GraphicsLayer::setShouldFlattenTransform(bool shouldFlatten)
{
- if (preserves3D == m_preserves3D)
+ if (shouldFlatten == m_shouldFlattenTransform)
return;
- m_preserves3D = preserves3D;
- m_layer->layer()->setPreserves3D(m_preserves3D);
+ m_shouldFlattenTransform = shouldFlatten;
+
+ m_layer->layer()->setShouldFlattenTransform(shouldFlatten);
+}
+
+void GraphicsLayer::setRenderingContext(int context)
+{
+ if (m_3dRenderingContext == context)
+ return;
+
+ m_3dRenderingContext = context;
+ m_layer->layer()->setRenderingContext(context);
+
+ if (m_contentsLayer)
+ m_contentsLayer->setRenderingContext(m_3dRenderingContext);
}
void GraphicsLayer::setMasksToBounds(bool masksToBounds)
@@ -973,7 +968,7 @@ void GraphicsLayer::setContentsNeedsDisplay()
{
if (WebLayer* contentsLayer = contentsLayerIfRegistered()) {
contentsLayer->invalidate();
- addRepaintRect(contentsRect());
+ addRepaintRect(m_contentsRect);
}
}
@@ -1008,7 +1003,7 @@ void GraphicsLayer::setContentsRect(const IntRect& rect)
void GraphicsLayer::setContentsToImage(Image* image)
{
- RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : 0;
+ RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : nullptr;
if (nativeImage) {
if (!m_imageLayer) {
m_imageLayer = adoptPtr(Platform::current()->compositorSupport()->createImageLayer());
@@ -1033,7 +1028,7 @@ void GraphicsLayer::setContentsToNinePatch(Image* image, const IntRect& aperture
unregisterContentsLayer(m_ninePatchLayer->layer());
m_ninePatchLayer.clear();
}
- RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : 0;
+ RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : nullptr;
if (nativeImage) {
m_ninePatchLayer = adoptPtr(Platform::current()->compositorSupport()->createNinePatchLayer());
m_ninePatchLayer->setBitmap(nativeImage->bitmap(), aperture);
@@ -1043,27 +1038,6 @@ void GraphicsLayer::setContentsToNinePatch(Image* image, const IntRect& aperture
setContentsTo(m_ninePatchLayer ? m_ninePatchLayer->layer() : 0);
}
-void GraphicsLayer::setContentsToSolidColor(const Color& color)
-{
- if (color == m_contentsSolidColor)
- return;
-
- m_contentsSolidColor = color;
- if (color.isValid() && color.alpha()) {
- if (!m_solidColorLayer) {
- m_solidColorLayer = adoptPtr(Platform::current()->compositorSupport()->createSolidColorLayer());
- registerContentsLayer(m_solidColorLayer->layer());
- }
- m_solidColorLayer->setBackgroundColor(color.rgb());
- } else {
- if (!m_solidColorLayer)
- return;
- unregisterContentsLayer(m_solidColorLayer->layer());
- m_solidColorLayer.clear();
- }
- setContentsTo(m_solidColorLayer ? m_solidColorLayer->layer() : 0);
-}
-
bool GraphicsLayer::addAnimation(PassOwnPtr<WebAnimation> popAnimation)
{
OwnPtr<WebAnimation> animation(popAnimation);
@@ -1153,9 +1127,6 @@ static bool copyWebCoreFilterOperationsToWebFilterOperations(const FilterOperati
webFilters.appendDropShadowFilter(WebPoint(dropShadowOp.x(), dropShadowOp.y()), dropShadowOp.stdDeviation(), dropShadowOp.color().rgb());
break;
}
- case FilterOperation::CUSTOM:
- case FilterOperation::VALIDATED_CUSTOM:
- return false; // Not supported.
case FilterOperation::NONE:
break;
}
@@ -1191,6 +1162,14 @@ void GraphicsLayer::setBackgroundFilters(const FilterOperations& filters)
m_layer->layer()->setBackgroundFilters(*webFilters);
}
+void GraphicsLayer::setPaintingPhase(GraphicsLayerPaintingPhase phase)
+{
+ if (m_paintingPhase == phase)
+ return;
+ m_paintingPhase = phase;
+ setNeedsDisplay();
+}
+
void GraphicsLayer::addLinkHighlight(LinkHighlightClient* linkHighlight)
{
ASSERT(linkHighlight && !m_linkHighlights.contains(linkHighlight));
@@ -1214,6 +1193,8 @@ void GraphicsLayer::setScrollableArea(ScrollableArea* scrollableArea, bool isMai
// Main frame scrolling may involve pinch zoom and gets routed through
// WebViewImpl explicitly rather than via GraphicsLayer::didScroll.
+ // TODO(bokan): With pinch virtual viewport the special case will no
+ // longer be needed, remove once old-style pinch is gone.
if (isMainFrame)
m_layer->layer()->setScrollClient(0);
else
@@ -1226,13 +1207,13 @@ void GraphicsLayer::paint(GraphicsContext& context, const IntRect& clip)
}
-void GraphicsLayer::notifyAnimationStarted(double wallClockTime, double monotonicTime, WebAnimation::TargetProperty)
+void GraphicsLayer::notifyAnimationStarted(double monotonicTime, WebAnimation::TargetProperty)
{
if (m_client)
- m_client->notifyAnimationStarted(this, wallClockTime, monotonicTime);
+ m_client->notifyAnimationStarted(this, monotonicTime);
}
-void GraphicsLayer::notifyAnimationFinished(double, double, WebAnimation::TargetProperty)
+void GraphicsLayer::notifyAnimationFinished(double, WebAnimation::TargetProperty)
{
// Do nothing.
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
index ca16a0a91bb..256f68e78fb 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -34,11 +34,11 @@
#include "platform/geometry/IntRect.h"
#include "platform/graphics/Color.h"
#include "platform/graphics/GraphicsLayerClient.h"
+#include "platform/graphics/GraphicsLayerDebugInfo.h"
#include "platform/graphics/OpaqueRectTrackingContentLayerDelegate.h"
#include "platform/graphics/filters/FilterOperations.h"
#include "platform/transforms/TransformationMatrix.h"
#include "public/platform/WebAnimationDelegate.h"
-#include "public/platform/WebCompositingReasons.h"
#include "public/platform/WebContentLayer.h"
#include "public/platform/WebImageLayer.h"
#include "public/platform/WebLayerClient.h"
@@ -52,7 +52,6 @@
namespace blink {
class GraphicsLayerFactoryChromium;
class WebAnimation;
-class WebGraphicsLayerDebugInfo;
class WebLayer;
}
@@ -60,6 +59,7 @@ namespace WebCore {
class FloatRect;
class GraphicsContext;
+class GraphicsLayer;
class GraphicsLayerFactory;
class Image;
class ScrollableArea;
@@ -76,6 +76,8 @@ protected:
virtual ~LinkHighlightClient() { }
};
+typedef Vector<GraphicsLayer*, 64> GraphicsLayerVector;
+
// GraphicsLayer is an abstraction for a rendering surface with backing store,
// which may have associated transformation and animations.
@@ -89,21 +91,20 @@ public:
GraphicsLayerClient* client() const { return m_client; }
// blink::WebLayerClient implementation.
- virtual blink::WebString debugName(blink::WebLayer*) OVERRIDE;
- virtual blink::WebGraphicsLayerDebugInfo* takeDebugInfo() OVERRIDE;
+ virtual blink::WebGraphicsLayerDebugInfo* takeDebugInfoFor(blink::WebLayer*) OVERRIDE;
+
+ GraphicsLayerDebugInfo& debugInfo();
- void setCompositingReasons(blink::WebCompositingReasons);
- blink::WebCompositingReasons compositingReasons() const { return m_compositingReasons; }
+ void setCompositingReasons(CompositingReasons);
+ CompositingReasons compositingReasons() const { return m_debugInfo.compositingReasons(); }
+ void setOwnerNodeId(int);
GraphicsLayer* parent() const { return m_parent; };
void setParent(GraphicsLayer*); // Internal use only.
- // Returns true if the layer has the given layer as an ancestor (excluding self).
- bool hasAncestor(GraphicsLayer*) const;
-
const Vector<GraphicsLayer*>& children() const { return m_children; }
// Returns true if the child list changed.
- bool setChildren(const Vector<GraphicsLayer*>&);
+ bool setChildren(const GraphicsLayerVector&);
// Add child layers. If the child is already parented, it will be removed from its old parent.
void addChild(GraphicsLayer*);
@@ -123,16 +124,11 @@ public:
// The given layer will replicate this layer and its children; the replica renders behind this layer.
void setReplicatedByLayer(GraphicsLayer*);
- // Whether this layer is being replicated by another layer.
- bool isReplicated() const { return m_replicaLayer; }
// The layer that replicates this layer (if any).
GraphicsLayer* replicaLayer() const { return m_replicaLayer; }
// The layer being replicated.
GraphicsLayer* replicatedLayer() const { return m_replicatedLayer; }
- const FloatPoint& replicatedLayerPosition() const { return m_replicatedLayerPosition; }
- void setReplicatedLayerPosition(const FloatPoint& p) { m_replicatedLayerPosition = p; }
-
enum ShouldSetNeedsDisplay {
DontSetNeedsDisplay,
SetNeedsDisplay
@@ -146,10 +142,8 @@ public:
const FloatPoint& position() const { return m_position; }
void setPosition(const FloatPoint&);
- // Anchor point: (0, 0) is top left, (1, 1) is bottom right. The anchor point
- // affects the origin of the transforms.
- const FloatPoint3D& anchorPoint() const { return m_anchorPoint; }
- void setAnchorPoint(const FloatPoint3D&);
+ const FloatPoint3D& transformOrigin() const { return m_transformOrigin; }
+ void setTransformOrigin(const FloatPoint3D&);
// The size of the layer.
const FloatSize& size() const { return m_size; }
@@ -161,14 +155,8 @@ public:
const TransformationMatrix& transform() const { return m_transform; }
void setTransform(const TransformationMatrix&);
-
- const TransformationMatrix& childrenTransform() const { return m_childrenTransform; }
- void setChildrenTransform(const TransformationMatrix&);
-
- bool preserves3D() const { return m_preserves3D; }
- void setPreserves3D(bool);
-
- bool masksToBounds() const { return m_masksToBounds; }
+ void setShouldFlattenTransform(bool);
+ void setRenderingContext(int id);
void setMasksToBounds(bool);
bool drawsContent() const { return m_drawsContent; }
@@ -180,12 +168,9 @@ public:
void setScrollParent(blink::WebLayer*);
void setClipParent(blink::WebLayer*);
- void setDebugInfo(blink::WebGraphicsLayerDebugInfo*);
-
// For special cases, e.g. drawing missing tiles on Android.
// The compositor should never paint this color in normal cases because the RenderLayer
// will paint background by itself.
- const Color& backgroundColor() const { return m_backgroundColor; }
void setBackgroundColor(const Color&);
// opaque means that we know the layer contents have no alpha
@@ -198,21 +183,15 @@ public:
float opacity() const { return m_opacity; }
void setOpacity(float);
- blink::WebBlendMode blendMode() const { return m_blendMode; }
void setBlendMode(blink::WebBlendMode);
-
- bool isRootForIsolatedGroup() const { return m_isRootForIsolatedGroup; }
void setIsRootForIsolatedGroup(bool);
- const FilterOperations& filters() const { return m_filters; }
-
// Returns true if filter can be rendered by the compositor
bool setFilters(const FilterOperations&);
void setBackgroundFilters(const FilterOperations&);
// Some GraphicsLayers paint only the foreground or the background content
- GraphicsLayerPaintingPhase paintingPhase() const { return m_paintingPhase; }
- void setPaintingPhase(GraphicsLayerPaintingPhase phase) { m_paintingPhase = phase; }
+ void setPaintingPhase(GraphicsLayerPaintingPhase);
void setNeedsDisplay();
// mark the given rect (in layer coords) as needing dispay. Never goes deep.
@@ -221,7 +200,6 @@ public:
void setContentsNeedsDisplay();
// Set that the position/size of the contents (image or video).
- IntRect contentsRect() const { return m_contentsRect; }
void setContentsRect(const IntRect&);
// Return true if the animation is handled by the compositing system. If this returns
@@ -234,8 +212,6 @@ public:
// Layer contents
void setContentsToImage(Image*);
void setContentsToNinePatch(Image*, const IntRect& aperture);
- // Pass an invalid color to remove the contents layer.
- void setContentsToSolidColor(const Color&);
void setContentsToPlatformLayer(blink::WebLayer* layer) { setContentsTo(layer); }
bool hasContentsLayer() const { return m_contentsLayer; }
@@ -245,33 +221,15 @@ public:
// For hosting this GraphicsLayer in a native layer hierarchy.
blink::WebLayer* platformLayer() const;
- enum CompositingCoordinatesOrientation { CompositingCoordinatesTopDown, CompositingCoordinatesBottomUp };
-
- // Flippedness of the contents of this layer. Does not affect sublayer geometry.
- void setContentsOrientation(CompositingCoordinatesOrientation orientation) { m_contentsOrientation = orientation; }
- CompositingCoordinatesOrientation contentsOrientation() const { return m_contentsOrientation; }
-
- void dumpLayer(TextStream&, int indent, LayerTreeFlags) const;
+ typedef HashMap<int, int> RenderingContextMap;
+ void dumpLayer(TextStream&, int indent, LayerTreeFlags, RenderingContextMap&) const;
int paintCount() const { return m_paintCount; }
- // z-position is the z-equivalent of position(). It's only used for debugging purposes.
- float zPosition() const { return m_zPosition; }
- void setZPosition(float);
-
- void distributeOpacity(float);
- float accumulatedOpacity() const;
-
- // If the exposed rect of this layer changes, returns true if this or descendant layers need a flush,
- // for example to allocate new tiles.
- bool visibleRectChangeRequiresFlush(const FloatRect& /* clipRect */) const { return false; }
-
// Return a string with a human readable form of the layer tree, If debug is true
// pointers for the layers and timing data will be included in the returned string.
String layerTreeAsText(LayerTreeFlags = LayerTreeNormal) const;
-
- // Return an estimate of the backing store memory cost (in bytes). May be incorrect for tiled layers.
- double backingStoreMemoryEstimate() const;
+ String debugName(blink::WebLayer*) const;
void resetTrackedRepaints();
void addRepaintRect(const FloatRect&);
@@ -296,8 +254,8 @@ public:
virtual void paint(GraphicsContext&, const IntRect& clip) OVERRIDE;
// WebAnimationDelegate implementation.
- virtual void notifyAnimationStarted(double wallClockTime, double monotonicTime, blink::WebAnimation::TargetProperty) OVERRIDE;
- virtual void notifyAnimationFinished(double wallClockTime, double monotonicTime, blink::WebAnimation::TargetProperty) OVERRIDE;
+ virtual void notifyAnimationStarted(double monotonicTime, blink::WebAnimation::TargetProperty) OVERRIDE;
+ virtual void notifyAnimationFinished(double monotonicTime, blink::WebAnimation::TargetProperty) OVERRIDE;
// WebLayerScrollClient implementation.
virtual void didScroll() OVERRIDE;
@@ -315,6 +273,10 @@ private:
// can be batched before updating.
void addChildInternal(GraphicsLayer*);
+#if ASSERT_ENABLED
+ bool hasAncestor(GraphicsLayer*) const;
+#endif
+
// This method is used by platform GraphicsLayer classes to clear the filters
// when compositing is not done in hardware. It is not virtual, so the caller
// needs to notifiy the change to the platform layer as needed.
@@ -324,7 +286,7 @@ private:
int incrementPaintCount() { return ++m_paintCount; }
- void dumpProperties(TextStream&, int indent, LayerTreeFlags) const;
+ void dumpProperties(TextStream&, int indent, LayerTreeFlags, RenderingContextMap&) const;
// Helper functions used by settors to keep layer's the state consistent.
void updateChildList();
@@ -343,23 +305,22 @@ private:
// Position is relative to the parent GraphicsLayer
FloatPoint m_position;
- FloatPoint3D m_anchorPoint;
FloatSize m_size;
FloatPoint m_boundsOrigin;
TransformationMatrix m_transform;
- TransformationMatrix m_childrenTransform;
+ FloatPoint3D m_transformOrigin;
Color m_backgroundColor;
float m_opacity;
- float m_zPosition;
blink::WebBlendMode m_blendMode;
FilterOperations m_filters;
+ bool m_hasTransformOrigin : 1;
bool m_contentsOpaque : 1;
- bool m_preserves3D: 1;
+ bool m_shouldFlattenTransform: 1;
bool m_backfaceVisibility : 1;
bool m_masksToBounds : 1;
bool m_drawsContent : 1;
@@ -370,7 +331,6 @@ private:
bool m_hasClipParent : 1;
GraphicsLayerPaintingPhase m_paintingPhase;
- CompositingCoordinatesOrientation m_contentsOrientation; // affects orientation of layer contents
Vector<GraphicsLayer*> m_children;
GraphicsLayer* m_parent;
@@ -390,8 +350,6 @@ private:
OwnPtr<blink::WebContentLayer> m_layer;
OwnPtr<blink::WebImageLayer> m_imageLayer;
OwnPtr<blink::WebNinePatchLayer> m_ninePatchLayer;
- Color m_contentsSolidColor;
- OwnPtr<blink::WebSolidColorLayer> m_solidColorLayer;
blink::WebLayer* m_contentsLayer;
// We don't have ownership of m_contentsLayer, but we do want to know if a given layer is the
// same as our current layer in setContentsTo(). Since m_contentsLayer may be deleted at this point,
@@ -404,16 +362,15 @@ private:
OwnPtr<OpaqueRectTrackingContentLayerDelegate> m_opaqueRectTrackingContentLayerDelegate;
ScrollableArea* m_scrollableArea;
- blink::WebCompositingReasons m_compositingReasons;
- blink::WebGraphicsLayerDebugInfo* m_debugInfo;
+ GraphicsLayerDebugInfo m_debugInfo;
+ int m_3dRenderingContext;
};
-
} // namespace WebCore
#ifndef NDEBUG
// Outside the WebCore namespace for ease of invocation from gdb.
-void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer);
+void PLATFORM_EXPORT showGraphicsLayerTree(const WebCore::GraphicsLayer*);
#endif
#endif // GraphicsLayer_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerClient.h b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerClient.h
index f46e3020c8b..aec703d0a7a 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerClient.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerClient.h
@@ -64,15 +64,9 @@ public:
virtual ~GraphicsLayerClient() {}
// Callback for when hardware-accelerated animation started.
- virtual void notifyAnimationStarted(const GraphicsLayer*, double wallClockTime, double monotonicTime) = 0;
+ virtual void notifyAnimationStarted(const GraphicsLayer*, double monotonicTime) = 0;
virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) = 0;
- virtual void didCommitChangesForLayer(const GraphicsLayer*) const { }
-
- // Provides current transform (taking transform-origin and animations into account). Input matrix has been
- // initialized to identity already. Returns false if the layer has no transform.
- virtual bool getCurrentTransform(const GraphicsLayer*, TransformationMatrix&) const { return false; }
-
virtual bool isTrackingRepaints() const { return false; }
virtual String debugName(const GraphicsLayer*) = 0;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.cpp
new file mode 100644
index 00000000000..93cd1d05d04
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "platform/graphics/GraphicsLayerDebugInfo.h"
+
+#include "wtf/text/CString.h"
+
+namespace WebCore {
+
+GraphicsLayerDebugInfo::GraphicsLayerDebugInfo()
+ : m_compositingReasons(CompositingReasonNone)
+{
+}
+
+GraphicsLayerDebugInfo::~GraphicsLayerDebugInfo() { }
+
+void GraphicsLayerDebugInfo::appendAsTraceFormat(blink::WebString* out) const
+{
+ RefPtr<JSONObject> jsonObject = JSONObject::create();
+ appendLayoutRects(jsonObject.get());
+ appendCompositingReasons(jsonObject.get());
+ appendDebugName(jsonObject.get());
+ appendOwnerNodeId(jsonObject.get());
+ *out = jsonObject->toJSONString();
+}
+
+GraphicsLayerDebugInfo* GraphicsLayerDebugInfo::clone() const
+{
+ GraphicsLayerDebugInfo* toReturn = new GraphicsLayerDebugInfo();
+ for (size_t i = 0; i < m_currentLayoutRects.size(); ++i)
+ toReturn->currentLayoutRects().append(m_currentLayoutRects[i]);
+ toReturn->setCompositingReasons(m_compositingReasons);
+ toReturn->setOwnerNodeId(m_ownerNodeId);
+ return toReturn;
+}
+
+void GraphicsLayerDebugInfo::appendLayoutRects(JSONObject* jsonObject) const
+{
+ RefPtr<JSONArray> jsonArray = JSONArray::create();
+ for (size_t i = 0; i < m_currentLayoutRects.size(); i++) {
+ const LayoutRect& rect = m_currentLayoutRects[i];
+ RefPtr<JSONObject> rectContainer = JSONObject::create();
+ RefPtr<JSONArray> rectArray = JSONArray::create();
+ rectArray->pushNumber(rect.x().toFloat());
+ rectArray->pushNumber(rect.y().toFloat());
+ rectArray->pushNumber(rect.maxX().toFloat());
+ rectArray->pushNumber(rect.maxY().toFloat());
+ rectContainer->setArray("geometry_rect", rectArray);
+ jsonArray->pushObject(rectContainer);
+ }
+ jsonObject->setArray("layout_rects", jsonArray);
+}
+
+void GraphicsLayerDebugInfo::appendCompositingReasons(JSONObject* jsonObject) const
+{
+ RefPtr<JSONArray> jsonArray = JSONArray::create();
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(compositingReasonStringMap); ++i) {
+ if (!(m_compositingReasons & compositingReasonStringMap[i].reason))
+ continue;
+ jsonArray->pushString(compositingReasonStringMap[i].description);
+ }
+ jsonObject->setArray("compositing_reasons", jsonArray);
+}
+
+void GraphicsLayerDebugInfo::appendDebugName(JSONObject* jsonObject) const
+{
+ if (m_debugName.isEmpty())
+ return;
+
+ jsonObject->setString("layer_name", m_debugName);
+}
+
+void GraphicsLayerDebugInfo::appendOwnerNodeId(JSONObject* jsonObject) const
+{
+ if (!m_ownerNodeId)
+ return;
+
+ jsonObject->setNumber("owner_node", m_ownerNodeId);
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.h
index d6c3159bafc..6953cf48ef8 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Google Inc. All rights reserved.
+ * Copyright (C) 2014 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
@@ -28,34 +28,45 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "platform/graphics/gpu/AcceleratedImageBufferSurface.h"
+#ifndef GraphicsLayerDebugInfo_h
+#define GraphicsLayerDebugInfo_h
-#include "platform/graphics/gpu/SharedGraphicsContext3D.h"
-#include "third_party/skia/include/gpu/SkGpuDevice.h"
+#include "platform/JSONValues.h"
+#include "platform/geometry/LayoutRect.h"
+#include "platform/graphics/CompositingReasons.h"
+#include "public/platform/WebGraphicsLayerDebugInfo.h"
+
+#include "wtf/Vector.h"
namespace WebCore {
-AcceleratedImageBufferSurface::AcceleratedImageBufferSurface(const IntSize& size, OpacityMode opacityMode, int msaaSampleCount)
- : ImageBufferSurface(size, opacityMode)
-{
- GrContext* grContext = SharedGraphicsContext3D::get()->grContext();
- if (!grContext)
- return;
- RefPtr<SkGpuDevice> device = adoptRef(new SkGpuDevice(grContext, SkBitmap::kARGB_8888_Config, size.width(), size.height(), msaaSampleCount));
- if (!device->accessRenderTarget())
- return;
- m_canvas = adoptPtr(new SkCanvas(device.get()));
- clear();
-}
-
-Platform3DObject AcceleratedImageBufferSurface::getBackingTexture() const
-{
- GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget();
- if (renderTarget) {
- return renderTarget->asTexture()->getTextureHandle();
- }
- return 0;
-}
+class GraphicsLayerDebugInfo FINAL : public blink::WebGraphicsLayerDebugInfo {
+public:
+ GraphicsLayerDebugInfo();
+ virtual ~GraphicsLayerDebugInfo();
+
+ virtual void appendAsTraceFormat(blink::WebString* out) const OVERRIDE;
+
+ GraphicsLayerDebugInfo* clone() const;
+
+ void setDebugName(const String& name) { m_debugName = name; }
+ CompositingReasons compositingReasons() const { return m_compositingReasons; }
+ void setCompositingReasons(CompositingReasons reasons) { m_compositingReasons = reasons; }
+ void setOwnerNodeId(int id) { m_ownerNodeId = id; }
+ Vector<LayoutRect>& currentLayoutRects() { return m_currentLayoutRects; }
+
+private:
+ void appendLayoutRects(JSONObject*) const;
+ void appendCompositingReasons(JSONObject*) const;
+ void appendDebugName(JSONObject*) const;
+ void appendOwnerNodeId(JSONObject*) const;
+
+ String m_debugName;
+ CompositingReasons m_compositingReasons;
+ int m_ownerNodeId;
+ Vector<LayoutRect> m_currentLayoutRects;
+};
} // namespace WebCore
+
+#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
new file mode 100644
index 00000000000..b6ed1b6741c
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2012 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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"
+
+#include "platform/graphics/GraphicsLayer.h"
+
+#include "platform/scroll/ScrollableArea.h"
+#include "platform/transforms/Matrix3DTransformOperation.h"
+#include "platform/transforms/RotateTransformOperation.h"
+#include "platform/transforms/TranslateTransformOperation.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebCompositorSupport.h"
+#include "public/platform/WebFloatAnimationCurve.h"
+#include "public/platform/WebGraphicsContext3D.h"
+#include "public/platform/WebLayer.h"
+#include "public/platform/WebLayerTreeView.h"
+#include "public/platform/WebUnitTestSupport.h"
+#include "wtf/PassOwnPtr.h"
+
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+using namespace blink;
+
+namespace {
+
+class MockGraphicsLayerClient : public GraphicsLayerClient {
+public:
+ virtual void notifyAnimationStarted(const GraphicsLayer*, double monotonicTime) OVERRIDE { }
+ virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) OVERRIDE { }
+ virtual String debugName(const GraphicsLayer*) OVERRIDE { return String(); }
+};
+
+class GraphicsLayerForTesting : public GraphicsLayer {
+public:
+ explicit GraphicsLayerForTesting(GraphicsLayerClient* client)
+ : GraphicsLayer(client) { };
+
+ virtual blink::WebLayer* contentsLayer() const { return GraphicsLayer::contentsLayer(); }
+};
+
+class GraphicsLayerTest : public testing::Test {
+public:
+ GraphicsLayerTest()
+ {
+ m_clipLayer = adoptPtr(new GraphicsLayerForTesting(&m_client));
+ m_graphicsLayer = adoptPtr(new GraphicsLayerForTesting(&m_client));
+ m_clipLayer->addChild(m_graphicsLayer.get());
+ m_graphicsLayer->platformLayer()->setScrollClipLayer(
+ m_clipLayer->platformLayer());
+ m_platformLayer = m_graphicsLayer->platformLayer();
+ m_layerTreeView = adoptPtr(Platform::current()->unitTestSupport()->createLayerTreeViewForTesting());
+ ASSERT(m_layerTreeView);
+ m_layerTreeView->setRootLayer(*m_clipLayer->platformLayer());
+ m_layerTreeView->registerViewportLayers(
+ m_clipLayer->platformLayer(), m_graphicsLayer->platformLayer(), 0);
+ m_layerTreeView->setViewportSize(WebSize(1, 1));
+ }
+
+ virtual ~GraphicsLayerTest()
+ {
+ m_graphicsLayer.clear();
+ m_layerTreeView.clear();
+ }
+
+protected:
+ WebLayer* m_platformLayer;
+ OwnPtr<GraphicsLayerForTesting> m_graphicsLayer;
+ OwnPtr<GraphicsLayerForTesting> m_clipLayer;
+
+private:
+ OwnPtr<WebLayerTreeView> m_layerTreeView;
+ MockGraphicsLayerClient m_client;
+};
+
+TEST_F(GraphicsLayerTest, updateLayerShouldFlattenTransformWithAnimations)
+{
+ ASSERT_FALSE(m_platformLayer->hasActiveAnimation());
+
+ OwnPtr<WebFloatAnimationCurve> curve = adoptPtr(Platform::current()->compositorSupport()->createFloatAnimationCurve());
+ curve->add(WebFloatKeyframe(0.0, 0.0));
+ OwnPtr<WebAnimation> floatAnimation(adoptPtr(Platform::current()->compositorSupport()->createAnimation(*curve, WebAnimation::TargetPropertyOpacity)));
+ int animationId = floatAnimation->id();
+ ASSERT_TRUE(m_platformLayer->addAnimation(floatAnimation.leakPtr()));
+
+ ASSERT_TRUE(m_platformLayer->hasActiveAnimation());
+
+ m_graphicsLayer->setShouldFlattenTransform(false);
+
+ m_platformLayer = m_graphicsLayer->platformLayer();
+ ASSERT_TRUE(m_platformLayer);
+
+ ASSERT_TRUE(m_platformLayer->hasActiveAnimation());
+ m_platformLayer->removeAnimation(animationId);
+ ASSERT_FALSE(m_platformLayer->hasActiveAnimation());
+
+ m_graphicsLayer->setShouldFlattenTransform(true);
+
+ m_platformLayer = m_graphicsLayer->platformLayer();
+ ASSERT_TRUE(m_platformLayer);
+
+ ASSERT_FALSE(m_platformLayer->hasActiveAnimation());
+}
+
+class FakeScrollableArea : public ScrollableArea {
+public:
+ virtual bool isActive() const OVERRIDE { return false; }
+ virtual int scrollSize(ScrollbarOrientation) const OVERRIDE { return 100; }
+ virtual bool isScrollCornerVisible() const OVERRIDE { return false; }
+ virtual IntRect scrollCornerRect() const OVERRIDE { return IntRect(); }
+ virtual int visibleWidth() const OVERRIDE { return 10; }
+ virtual int visibleHeight() const OVERRIDE { return 10; }
+ virtual IntSize contentsSize() const OVERRIDE { return IntSize(100, 100); }
+ virtual bool scrollbarsCanBeActive() const OVERRIDE { return false; }
+ virtual IntRect scrollableAreaBoundingBox() const OVERRIDE { return IntRect(); }
+ virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&) OVERRIDE { }
+ virtual void invalidateScrollCornerRect(const IntRect&) OVERRIDE { }
+ virtual bool userInputScrollable(ScrollbarOrientation) const OVERRIDE { return true; }
+ virtual bool shouldPlaceVerticalScrollbarOnLeft() const OVERRIDE { return false; }
+ virtual int pageStep(ScrollbarOrientation) const OVERRIDE { return 0; }
+ virtual IntPoint minimumScrollPosition() const OVERRIDE { return IntPoint(); }
+ virtual IntPoint maximumScrollPosition() const OVERRIDE
+ {
+ return IntPoint(contentsSize().width() - visibleWidth(), contentsSize().height() - visibleHeight());
+ }
+
+ virtual void setScrollOffset(const IntPoint& scrollOffset) OVERRIDE { m_scrollPosition = scrollOffset; }
+ virtual IntPoint scrollPosition() const OVERRIDE { return m_scrollPosition; }
+
+private:
+ IntPoint m_scrollPosition;
+};
+
+TEST_F(GraphicsLayerTest, applyScrollToScrollableArea)
+{
+ FakeScrollableArea scrollableArea;
+ m_graphicsLayer->setScrollableArea(&scrollableArea, false);
+
+ WebPoint scrollPosition(7, 9);
+ m_platformLayer->setScrollPosition(scrollPosition);
+ m_graphicsLayer->didScroll();
+
+ EXPECT_EQ(scrollPosition, WebPoint(scrollableArea.scrollPosition()));
+}
+
+} // namespace
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h
index 1482dfbefc9..b0938f3fe27 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h
@@ -43,11 +43,15 @@ enum StrokeStyle {
};
enum InterpolationQuality {
- InterpolationDefault,
- InterpolationNone,
- InterpolationLow,
- InterpolationMedium,
- InterpolationHigh
+ InterpolationNone = SkPaint::kNone_FilterLevel,
+ InterpolationLow = SkPaint::kLow_FilterLevel,
+ InterpolationMedium = SkPaint::kMedium_FilterLevel,
+ InterpolationHigh = SkPaint::kHigh_FilterLevel,
+#if USE(LOW_QUALITY_IMAGE_INTERPOLATION)
+ InterpolationDefault = InterpolationLow,
+#else
+ InterpolationDefault = InterpolationHigh,
+#endif
};
enum CompositeOperator {
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes3D.h b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes3D.h
index a4ed898127b..0bef5e1645c 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes3D.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsTypes3D.h
@@ -26,36 +26,36 @@
#ifndef GraphicsTypes3D_h
#define GraphicsTypes3D_h
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
#include "wtf/Forward.h"
#include <stdint.h>
-// GC3D types and enums match the corresponding GL types and enums as defined
-// in OpenGL ES 2.0 header file gl2.h from khronos.org.
-typedef unsigned GC3Denum;
-typedef unsigned char GC3Dboolean;
-typedef unsigned GC3Dbitfield;
-typedef signed char GC3Dbyte;
-typedef unsigned char GC3Dubyte;
-typedef short GC3Dshort;
-typedef unsigned short GC3Dushort;
-typedef int GC3Dint;
-typedef int GC3Dsizei;
-typedef unsigned GC3Duint;
-typedef float GC3Dfloat;
-typedef unsigned short GC3Dhalffloat;
-typedef float GC3Dclampf;
-typedef intptr_t GC3Dintptr;
-typedef intptr_t GC3Dsizeiptr;
-typedef char GC3Dchar;
-
-typedef GC3Duint Platform3DObject;
+typedef unsigned Platform3DObject;
// WebGL-specific enums
-const GC3Denum GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL = 0x821A;
-const GC3Denum GC3D_UNPACK_FLIP_Y_WEBGL = 0x9240;
-const GC3Denum GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
-const GC3Denum GC3D_CONTEXT_LOST_WEBGL = 0x9242;
-const GC3Denum GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
-const GC3Denum GC3D_BROWSER_DEFAULT_WEBGL = 0x9244;
+const unsigned GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL = 0x821A;
+const unsigned GC3D_UNPACK_FLIP_Y_WEBGL = 0x9240;
+const unsigned GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
+const unsigned GC3D_CONTEXT_LOST_WEBGL = 0x9242;
+const unsigned GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
+const unsigned GC3D_BROWSER_DEFAULT_WEBGL = 0x9244;
+
+// GL_CHROMIUM_flipy
+const unsigned GC3D_UNPACK_FLIP_Y_CHROMIUM = 0x9240;
+
+// GL_CHROMIUM_copy_texture
+const unsigned GC3D_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM = 0x9241;
+const unsigned GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM = 0x9242;
+
+// GL_AMD_compressed_ATC_texture
+const unsigned GC3D_COMPRESSED_ATC_RGB_AMD = 0x8C92;
+const unsigned GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD = 0x8C93;
+const unsigned GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD = 0x87EE;
+
+// GL_CHROMIUM_image
+const unsigned GC3D_IMAGE_ROWBYTES_CHROMIUM = 0x78F0;
+const unsigned GC3D_IMAGE_MAP_CHROMIUM = 0x78F1;
+const unsigned GC3D_IMAGE_SCANOUT_CHROMIUM = 0x78F2;
#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Image.h b/chromium/third_party/WebKit/Source/platform/graphics/Image.h
index cc3cc9604f1..706f15ca133 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Image.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Image.h
@@ -98,23 +98,27 @@ public:
// Animation begins whenever someone draws the image, so startAnimation() is not normally called.
// It will automatically pause once all observers no longer want to render the image anywhere.
- virtual void startAnimation(bool /*catchUpIfNecessary*/ = true) { }
+ enum CatchUpAnimation { DoNotCatchUp, CatchUp };
+ virtual void startAnimation(CatchUpAnimation = CatchUp) { }
virtual void stopAnimation() {}
virtual void resetAnimation() {}
+ // True if this image can potentially animate.
+ virtual bool maybeAnimated() { return false; }
+
// Typically the ImageResource that owns us.
ImageObserver* imageObserver() const { return m_imageObserver; }
void setImageObserver(ImageObserver* observer) { m_imageObserver = observer; }
enum TileRule { StretchTile, RoundTile, SpaceTile, RepeatTile };
- virtual PassRefPtr<NativeImageSkia> nativeImageForCurrentFrame() { return 0; }
+ virtual PassRefPtr<NativeImageSkia> nativeImageForCurrentFrame() { return nullptr; }
virtual void drawPattern(GraphicsContext*, const FloatRect&,
const FloatSize&, const FloatPoint& phase, CompositeOperator,
const FloatRect&, blink::WebBlendMode = blink::WebBlendModeNormal, const IntSize& repeatSpacing = IntSize());
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
virtual bool notSolidColor() { return true; }
#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
index 76de0de00a8..c4439d2c953 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -33,21 +33,25 @@
#include "config.h"
#include "platform/graphics/ImageBuffer.h"
+#include "GrContext.h"
#include "platform/MIMETypeRegistry.h"
#include "platform/geometry/IntRect.h"
#include "platform/graphics/BitmapImage.h"
-#include "platform/graphics/Extensions3D.h"
#include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/GraphicsContext3D.h"
+#include "platform/graphics/GraphicsTypes3D.h"
+#include "platform/graphics/ImageBufferClient.h"
#include "platform/graphics/UnacceleratedImageBufferSurface.h"
#include "platform/graphics/gpu/DrawingBuffer.h"
-#include "platform/graphics/gpu/SharedGraphicsContext3D.h"
+#include "platform/graphics/gpu/Extensions3DUtil.h"
#include "platform/graphics/skia/NativeImageSkia.h"
#include "platform/graphics/skia/SkiaUtils.h"
#include "platform/image-encoders/skia/JPEGImageEncoder.h"
#include "platform/image-encoders/skia/PNGImageEncoder.h"
#include "platform/image-encoders/skia/WEBPImageEncoder.h"
#include "public/platform/Platform.h"
+#include "public/platform/WebExternalTextureMailbox.h"
+#include "public/platform/WebGraphicsContext3D.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
#include "third_party/skia/include/effects/SkTableColorFilter.h"
#include "wtf/MathExtras.h"
#include "wtf/text/Base64.h"
@@ -74,7 +78,9 @@ PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opa
ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface)
: m_surface(surface)
+ , m_client(0)
{
+ m_surface->setImageBuffer(this);
if (m_surface->canvas()) {
m_context = adoptPtr(new GraphicsContext(m_surface->canvas()));
m_context->setCertainlyOpaque(m_surface->opacityMode() == Opaque);
@@ -88,6 +94,8 @@ ImageBuffer::~ImageBuffer()
GraphicsContext* ImageBuffer::context() const
{
+ if (!isSurfaceValid())
+ return 0;
m_surface->willUse();
ASSERT(m_context.get());
return m_context.get();
@@ -99,23 +107,34 @@ const SkBitmap& ImageBuffer::bitmap() const
return m_surface->bitmap();
}
-bool ImageBuffer::isValid() const
+bool ImageBuffer::isSurfaceValid() const
{
return m_surface->isValid();
}
+bool ImageBuffer::restoreSurface() const
+{
+ return m_surface->isValid() || m_surface->restore();
+}
+
+void ImageBuffer::notifySurfaceInvalid()
+{
+ if (m_client)
+ m_client->notifySurfaceInvalid();
+}
+
static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap)
{
SkBitmap tmp;
- if (!bitmap.deepCopyTo(&tmp, bitmap.config()))
- bitmap.copyTo(&tmp, bitmap.config());
+ if (!bitmap.deepCopyTo(&tmp))
+ bitmap.copyTo(&tmp, bitmap.colorType());
return tmp;
}
PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior) const
{
- if (!isValid())
+ if (!isSurfaceValid())
return BitmapImage::create(NativeImageSkia::create());
const SkBitmap& bitmap = m_surface->bitmap();
@@ -132,29 +151,54 @@ blink::WebLayer* ImageBuffer::platformLayer() const
return m_surface->layer();
}
-bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DObject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool premultiplyAlpha, bool flipY)
+bool ImageBuffer::copyToPlatformTexture(blink::WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY)
{
- if (!m_surface->isAccelerated() || !platformLayer() || !isValid())
+ if (!m_surface->isAccelerated() || !platformLayer() || !isSurfaceValid())
+ return false;
+
+ if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(internalFormat, destType, level))
return false;
- if (!context.makeContextCurrent())
+ OwnPtr<blink::WebGraphicsContext3DProvider> provider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+ if (!provider)
return false;
+ blink::WebGraphicsContext3D* sharedContext = provider->context3d();
+ if (!sharedContext || !sharedContext->makeContextCurrent())
+ return false;
+
+ OwnPtr<blink::WebExternalTextureMailbox> mailbox = adoptPtr(new blink::WebExternalTextureMailbox);
+
+ // Contexts may be in a different share group. We must transfer the texture through a mailbox first
+ sharedContext->genMailboxCHROMIUM(mailbox->name);
+ sharedContext->produceTextureDirectCHROMIUM(getBackingTexture(), GL_TEXTURE_2D, mailbox->name);
+ sharedContext->flush();
- Extensions3D* extensions = context.extensions();
- if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->supports("GL_CHROMIUM_flipy")
- || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, level))
+ mailbox->syncPoint = sharedContext->insertSyncPoint();
+
+ if (!context->makeContextCurrent())
return false;
+ context->waitSyncPoint(mailbox->syncPoint);
+ Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox->name);
+
// The canvas is stored in a premultiplied format, so unpremultiply if necessary.
- context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, !premultiplyAlpha);
+ context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, !premultiplyAlpha);
// The canvas is stored in an inverted position, so the flip semantics are reversed.
- context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, !flipY);
- extensions->copyTextureCHROMIUM(GL_TEXTURE_2D, getBackingTexture(), texture, level, internalFormat, destType);
+ context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, !flipY);
+ context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, texture, level, internalFormat, destType);
+
+ context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, false);
+ context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false);
+
+ context->deleteTexture(sourceTexture);
+
+ context->flush();
+ sharedContext->waitSyncPoint(context->insertSyncPoint());
+
+ // Undo grContext texture binding changes introduced in this function
+ provider->grContext()->resetContext(kTextureBinding_GrGLBackendState);
- context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, false);
- context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false);
- context.flush();
return true;
}
@@ -169,28 +213,40 @@ Platform3DObject ImageBuffer::getBackingTexture()
return m_surface->getBackingTexture();
}
-bool ImageBuffer::copyRenderingResultsFromDrawingBuffer(DrawingBuffer* drawingBuffer)
+bool ImageBuffer::copyRenderingResultsFromDrawingBuffer(DrawingBuffer* drawingBuffer, bool fromFrontBuffer)
{
if (!drawingBuffer)
return false;
- RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get();
+ OwnPtr<blink::WebGraphicsContext3DProvider> provider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+ if (!provider)
+ return false;
+ blink::WebGraphicsContext3D* context3D = provider->context3d();
Platform3DObject tex = m_surface->getBackingTexture();
if (!context3D || !tex)
return false;
- return drawingBuffer->copyToPlatformTexture(*(context3D.get()), tex, GL_RGBA,
- GL_UNSIGNED_BYTE, 0, true, false);
+ m_surface->invalidateCachedBitmap();
+ return drawingBuffer->copyToPlatformTexture(context3D, tex, GL_RGBA,
+ GL_UNSIGNED_BYTE, 0, true, false, fromFrontBuffer);
}
-void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, const FloatRect& srcRect,
- CompositeOperator op, blink::WebBlendMode blendMode, bool useLowQualityScale)
+void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, const FloatRect* srcPtr, CompositeOperator op)
{
- if (!isValid())
+ if (!isSurfaceValid())
return;
- const SkBitmap& bitmap = m_surface->bitmap();
+ FloatRect srcRect = srcPtr ? *srcPtr : FloatRect(FloatPoint(), size());
+ SkBitmap bitmap = m_surface->bitmap();
+ // For ImageBufferSurface that enables cachedBitmap, Use the cached Bitmap for CPU side usage
+ // if it is available, otherwise generate and use it.
+ if (!context->isAccelerated() && m_surface->isAccelerated() && m_surface->cachedBitmapEnabled() && isSurfaceValid()) {
+ m_surface->updateCachedBitmapIfNeeded();
+ bitmap = m_surface->cachedBitmap();
+ }
+
RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsCopy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap));
- context->drawImage(image.get(), destRect, srcRect, op, blendMode, DoNotRespectImageOrientation, useLowQualityScale);
+
+ context->drawImage(image.get(), destRect, srcRect, op, blink::WebBlendModeNormal, DoNotRespectImageOrientation);
}
void ImageBuffer::flush()
@@ -203,7 +259,7 @@ void ImageBuffer::flush()
void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const FloatSize& scale,
const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, blink::WebBlendMode blendMode, const IntSize& repeatSpacing)
{
- if (!isValid())
+ if (!isSurfaceValid())
return;
const SkBitmap& bitmap = m_surface->bitmap();
@@ -211,60 +267,21 @@ void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect
image->drawPattern(context, srcRect, scale, phase, op, destRect, blendMode, repeatSpacing);
}
-static const Vector<uint8_t>& getLinearRgbLUT()
-{
- DEFINE_STATIC_LOCAL(Vector<uint8_t>, linearRgbLUT, ());
- if (linearRgbLUT.isEmpty()) {
- linearRgbLUT.reserveCapacity(256);
- for (unsigned i = 0; i < 256; i++) {
- float color = i / 255.0f;
- color = (color <= 0.04045f ? color / 12.92f : pow((color + 0.055f) / 1.055f, 2.4f));
- color = std::max(0.0f, color);
- color = std::min(1.0f, color);
- linearRgbLUT.append(static_cast<uint8_t>(round(color * 255)));
- }
- }
- return linearRgbLUT;
-}
-
-static const Vector<uint8_t>& getDeviceRgbLUT()
-{
- DEFINE_STATIC_LOCAL(Vector<uint8_t>, deviceRgbLUT, ());
- if (deviceRgbLUT.isEmpty()) {
- deviceRgbLUT.reserveCapacity(256);
- for (unsigned i = 0; i < 256; i++) {
- float color = i / 255.0f;
- color = (powf(color, 1.0f / 2.4f) * 1.055f) - 0.055f;
- color = std::max(0.0f, color);
- color = std::min(1.0f, color);
- deviceRgbLUT.append(static_cast<uint8_t>(round(color * 255)));
- }
- }
- return deviceRgbLUT;
-}
-
void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace)
{
- if (srcColorSpace == dstColorSpace)
- return;
-
- // only sRGB <-> linearRGB are supported at the moment
- if ((srcColorSpace != ColorSpaceLinearRGB && srcColorSpace != ColorSpaceDeviceRGB)
- || (dstColorSpace != ColorSpaceLinearRGB && dstColorSpace != ColorSpaceDeviceRGB))
+ const uint8_t* lookUpTable = ColorSpaceUtilities::getConversionLUT(dstColorSpace, srcColorSpace);
+ if (!lookUpTable)
return;
// FIXME: Disable color space conversions on accelerated canvases (for now).
- if (context()->isAccelerated() || !isValid())
+ if (context()->isAccelerated() || !isSurfaceValid())
return;
const SkBitmap& bitmap = m_surface->bitmap();
if (bitmap.isNull())
return;
- const Vector<uint8_t>& lookUpTable = dstColorSpace == ColorSpaceLinearRGB ?
- getLinearRgbLUT() : getDeviceRgbLUT();
-
- ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
+ ASSERT(bitmap.colorType() == kPMColor_SkColorType);
IntSize size = m_surface->size();
SkAutoLockPixels bitmapLock(bitmap);
for (int y = 0; y < size.height(); ++y) {
@@ -283,18 +300,9 @@ void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
PassRefPtr<SkColorFilter> ImageBuffer::createColorSpaceFilter(ColorSpace srcColorSpace,
ColorSpace dstColorSpace)
{
- if ((srcColorSpace == dstColorSpace)
- || (srcColorSpace != ColorSpaceLinearRGB && srcColorSpace != ColorSpaceDeviceRGB)
- || (dstColorSpace != ColorSpaceLinearRGB && dstColorSpace != ColorSpaceDeviceRGB))
- return 0;
-
- const uint8_t* lut = 0;
- if (dstColorSpace == ColorSpaceLinearRGB)
- lut = &getLinearRgbLUT()[0];
- else if (dstColorSpace == ColorSpaceDeviceRGB)
- lut = &getDeviceRgbLUT()[0];
- else
- return 0;
+ const uint8_t* lut = ColorSpaceUtilities::getConversionLUT(dstColorSpace, srcColorSpace);
+ if (!lut)
+ return nullptr;
return adoptRef(SkTableColorFilter::CreateARGB(0, lut, lut, lut));
}
@@ -304,50 +312,40 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, GraphicsContext*
{
float area = 4.0f * rect.width() * rect.height();
if (area > static_cast<float>(std::numeric_limits<int>::max()))
- return 0;
+ return nullptr;
RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
- unsigned char* data = result->data();
-
if (rect.x() < 0
|| rect.y() < 0
|| rect.maxX() > size.width()
|| rect.maxY() > size.height())
result->zeroFill();
- unsigned destBytesPerRow = 4 * rect.width();
- SkBitmap destBitmap;
- destBitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height(), destBytesPerRow);
- destBitmap.setPixels(data);
-
- SkCanvas::Config8888 config8888;
- if (multiplied == Premultiplied)
- config8888 = SkCanvas::kRGBA_Premul_Config8888;
- else
- config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
+ SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
+ SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), kRGBA_8888_SkColorType, alphaType);
- context->readPixels(&destBitmap, rect.x(), rect.y(), config8888);
+ context->readPixels(info, result->data(), 4 * rect.width(), rect.x(), rect.y());
return result.release();
}
PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
- if (!isValid())
+ if (!isSurfaceValid())
return Uint8ClampedArray::create(rect.width() * rect.height() * 4);
return getImageData<Unmultiplied>(rect, context(), m_surface->size());
}
PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
{
- if (!isValid())
+ if (!isSurfaceValid())
return Uint8ClampedArray::create(rect.width() * rect.height() * 4);
return getImageData<Premultiplied>(rect, context(), m_surface->size());
}
void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
{
- if (!isValid())
+ if (!isSurfaceValid())
return;
ASSERT(sourceRect.width() > 0);
@@ -360,11 +358,6 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
ASSERT(originX >= 0);
ASSERT(originX < sourceRect.maxX());
- int endX = destPoint.x() + sourceRect.maxX();
- ASSERT(endX <= m_surface->size().width());
-
- int numColumns = endX - destX;
-
int originY = sourceRect.y();
int destY = destPoint.y() + sourceRect.y();
ASSERT(destY >= 0);
@@ -372,22 +365,12 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
ASSERT(originY >= 0);
ASSERT(originY < sourceRect.maxY());
- int endY = destPoint.y() + sourceRect.maxY();
- ASSERT(endY <= m_surface->size().height());
- int numRows = endY - destY;
-
- unsigned srcBytesPerRow = 4 * sourceSize.width();
- SkBitmap srcBitmap;
- srcBitmap.setConfig(SkBitmap::kARGB_8888_Config, numColumns, numRows, srcBytesPerRow);
- srcBitmap.setPixels(source->data() + originY * srcBytesPerRow + originX * 4);
-
- SkCanvas::Config8888 config8888;
- if (multiplied == Premultiplied)
- config8888 = SkCanvas::kRGBA_Premul_Config8888;
- else
- config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
+ const size_t srcBytesPerRow = 4 * sourceSize.width();
+ const void* srcAddr = source->data() + originY * srcBytesPerRow + originX * 4;
+ const SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
+ SkImageInfo info = SkImageInfo::Make(sourceRect.width(), sourceRect.height(), kRGBA_8888_SkColorType, alphaType);
- context()->writePixels(srcBitmap, destX, destY, config8888);
+ context()->writePixels(info, srcAddr, srcBytesPerRow, destX, destY);
}
template <typename T>
@@ -421,7 +404,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
Vector<char> encodedImage;
- if (!isValid() || !encodeImage(m_surface->bitmap(), mimeType, quality, &encodedImage))
+ if (!isSurfaceValid() || !encodeImage(m_surface->bitmap(), mimeType, quality, &encodedImage))
return "data:,";
Vector<char> base64Data;
base64Encode(encodedImage, base64Data);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.h b/chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
index bc8465fbfba..936979db27c 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
@@ -33,7 +33,6 @@
#include "platform/geometry/IntSize.h"
#include "platform/graphics/Canvas2DLayerBridge.h"
#include "platform/graphics/ColorSpace.h"
-#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/GraphicsTypes.h"
#include "platform/graphics/GraphicsTypes3D.h"
#include "platform/graphics/ImageBufferSurface.h"
@@ -47,11 +46,16 @@
class SkCanvas;
+namespace blink {
+class WebGraphicsContext3D;
+}
+
namespace WebCore {
class DrawingBuffer;
-class GraphicsContext3D;
+class GraphicsContext;
class Image;
+class ImageBufferClient;
class IntPoint;
class IntRect;
@@ -78,8 +82,14 @@ public:
~ImageBuffer();
+ void setClient(ImageBufferClient* client) { m_client = client; }
+
const IntSize& size() const { return m_surface->size(); }
bool isAccelerated() const { return m_surface->isAccelerated(); }
+ bool isSurfaceValid() const;
+ bool restoreSurface() const;
+
+ void setIsHidden(bool hidden) { m_surface->setIsHidden(hidden); }
GraphicsContext* context() const;
@@ -103,18 +113,21 @@ public:
// FIXME: current implementations of this method have the restriction that they only work
// with textures that are RGB or RGBA format, UNSIGNED_BYTE type and level 0, as specified in
// Extensions3D::canUseCopyTextureCHROMIUM().
- bool copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC3Denum, GC3Denum, GC3Dint, bool, bool);
+ // Destroys the TEXTURE_2D binding for the active texture unit of the passed context
+ bool copyToPlatformTexture(blink::WebGraphicsContext3D*, Platform3DObject, GLenum, GLenum, GLint, bool, bool);
Platform3DObject getBackingTexture();
- bool copyRenderingResultsFromDrawingBuffer(DrawingBuffer*);
+
+ bool copyRenderingResultsFromDrawingBuffer(DrawingBuffer*, bool fromFrontBuffer = false);
void flush();
+ void notifySurfaceInvalid();
+
private:
ImageBuffer(PassOwnPtr<ImageBufferSurface>);
- bool isValid() const;
- void draw(GraphicsContext*, const FloatRect&, const FloatRect& = FloatRect(0, 0, -1, -1), CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal, bool useLowQualityScale = false);
+ void draw(GraphicsContext*, const FloatRect&, const FloatRect* = 0, CompositeOperator = CompositeSourceOver);
void drawPattern(GraphicsContext*, const FloatRect&, const FloatSize&, const FloatPoint&, CompositeOperator, const FloatRect&, blink::WebBlendMode, const IntSize& repeatSpacing = IntSize());
static PassRefPtr<SkColorFilter> createColorSpaceFilter(ColorSpace srcColorSpace, ColorSpace dstColorSpace);
@@ -126,6 +139,7 @@ private:
OwnPtr<ImageBufferSurface> m_surface;
OwnPtr<GraphicsContext> m_context;
+ ImageBufferClient* m_client;
};
struct ImageDataBuffer {
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h b/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferClient.h
index 1293abc3ac1..4843f501033 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Google Inc. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -28,30 +28,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef AcceleratedImageBufferSurface_h
-#define AcceleratedImageBufferSurface_h
-
-#include "platform/graphics/ImageBufferSurface.h"
-#include "wtf/OwnPtr.h"
+#ifndef ImageBufferClient_h
+#define ImageBufferClient_h
namespace WebCore {
-class PLATFORM_EXPORT AcceleratedImageBufferSurface : public ImageBufferSurface {
- WTF_MAKE_NONCOPYABLE(AcceleratedImageBufferSurface); WTF_MAKE_FAST_ALLOCATED;
+class ImageBufferClient {
public:
- AcceleratedImageBufferSurface(const IntSize&, OpacityMode = NonOpaque, int msaaSampleCount = 0);
- virtual ~AcceleratedImageBufferSurface() { }
-
- virtual SkCanvas* canvas() const OVERRIDE { return m_canvas.get();}
- virtual bool isValid() const OVERRIDE { return m_canvas; }
- virtual bool isAccelerated() const OVERRIDE { return true; }
- virtual Platform3DObject getBackingTexture() const OVERRIDE;
-
-private:
- OwnPtr<SkCanvas> m_canvas;
+ virtual ~ImageBufferClient() { }
+ virtual void notifySurfaceInvalid() = 0;
};
-
-} // namespace WebCore
+}
#endif
+
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
index c5e22dbdd03..2869f4cc29a 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
@@ -32,11 +32,19 @@
#include "platform/graphics/ImageBufferSurface.h"
+#include "platform/graphics/ImageBuffer.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDevice.h"
namespace WebCore {
+ImageBufferSurface::ImageBufferSurface(const IntSize& size, OpacityMode opacityMode)
+ : m_opacityMode(opacityMode)
+ , m_size(size)
+{
+ setIsHidden(false);
+}
+
void ImageBufferSurface::clear()
{
// Clear the background transparent or opaque, as required. It would be nice if this wasn't
@@ -56,5 +64,10 @@ const SkBitmap& ImageBufferSurface::bitmap() const
return canvas()->getTopDevice()->accessBitmap(false);
}
+const SkBitmap& ImageBufferSurface::cachedBitmap() const
+{
+ DEFINE_STATIC_LOCAL(SkBitmap, nullBitmap, ());
+ return nullBitmap;
+}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h b/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h
index a415cfa9e18..a240f3776b4 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h
@@ -44,6 +44,8 @@ namespace blink { class WebLayer; }
namespace WebCore {
+class ImageBuffer;
+
enum OpacityMode {
NonOpaque,
Opaque,
@@ -58,21 +60,25 @@ public:
virtual const SkBitmap& bitmap() const;
virtual void willUse() { } // Called by ImageBuffer before reading or writing to the surface.
virtual bool isValid() const = 0;
+ virtual bool restore() { return false; };
virtual blink::WebLayer* layer() const { return 0; };
virtual bool isAccelerated() const { return false; }
virtual Platform3DObject getBackingTexture() const { return 0; }
+ virtual bool cachedBitmapEnabled() const { return false; }
+ virtual const SkBitmap& cachedBitmap() const;
+ virtual void invalidateCachedBitmap() { }
+ virtual void updateCachedBitmapIfNeeded() { }
+ virtual void setIsHidden(bool) { }
+ virtual void setImageBuffer(ImageBuffer*) { }
OpacityMode opacityMode() const { return m_opacityMode; }
const IntSize& size() const { return m_size; }
+ void notifyIsValidChanged(bool isValid) const;
protected:
+ ImageBufferSurface(const IntSize&, OpacityMode);
void clear();
- ImageBufferSurface(const IntSize& size, OpacityMode opacityMode)
- : m_opacityMode(opacityMode)
- , m_size(size)
- { }
-
private:
OpacityMode m_opacityMode;
IntSize m_size;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.cpp
index 5e7bb4d43af..3d5e9dd65e2 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.cpp
@@ -27,6 +27,7 @@
#include "platform/graphics/ImageDecodingStore.h"
#include "platform/TraceEvent.h"
+#include "wtf/Threading.h"
namespace WebCore {
@@ -37,15 +38,8 @@ namespace {
// with a lot of (very) large images.
static const size_t maxTotalSizeOfDiscardableEntries = 256 * 1024 * 1024;
static const size_t defaultMaxTotalSizeOfHeapEntries = 32 * 1024 * 1024;
-static ImageDecodingStore* s_instance = 0;
static bool s_imageCachingEnabled = true;
-static void setInstance(ImageDecodingStore* imageDecodingStore)
-{
- delete s_instance;
- s_instance = imageDecodingStore;
-}
-
} // namespace
ImageDecodingStore::ImageDecodingStore()
@@ -69,17 +63,8 @@ ImageDecodingStore::~ImageDecodingStore()
ImageDecodingStore* ImageDecodingStore::instance()
{
- return s_instance;
-}
-
-void ImageDecodingStore::initializeOnce()
-{
- setInstance(ImageDecodingStore::create().leakPtr());
-}
-
-void ImageDecodingStore::shutdown()
-{
- setInstance(0);
+ AtomicallyInitializedStatic(ImageDecodingStore*, store = ImageDecodingStore::create().leakPtr());
+ return store;
}
void ImageDecodingStore::setImageCachingEnabled(bool enabled)
@@ -367,7 +352,7 @@ void ImageDecodingStore::insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheM
typename U::KeyType key = cacheEntry->cacheKey();
typename V::AddResult result = identifierMap->add(cacheEntry->generator(), typename V::MappedType());
- result.iterator->value.add(key);
+ result.storedValue->value.add(key);
cacheMap->add(key, cacheEntry);
TRACE_COUNTER1("webkit", "ImageDecodingStoreDiscardableMemoryUsageBytes", m_discardableMemoryUsageInBytes);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.h b/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.h
index 6a7d9f8f621..bd740f9ad59 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStore.h
@@ -89,8 +89,6 @@ public:
~ImageDecodingStore();
static ImageDecodingStore* instance();
- static void initializeOnce();
- static void shutdown();
// Why do we need this?
// ImageDecodingStore is used in two code paths:
@@ -137,8 +135,8 @@ private:
// Image cache entry is identified by:
// 1. Pointer to ImageFrameGenerator.
// 2. Size of the image.
- // 3. Frame index.
- // 4. Frame generation. Increments on each progressive decode.
+ // 3. LocalFrame index.
+ // 4. LocalFrame generation. Increments on each progressive decode.
//
// The use of generation ID is to allow multiple versions of an image frame
// be stored in the cache. Each generation comes from a progressive decode.
@@ -192,7 +190,7 @@ private:
CacheEntry* m_next;
};
- class ImageCacheEntry : public CacheEntry {
+ class ImageCacheEntry FINAL : public CacheEntry {
public:
static PassOwnPtr<ImageCacheEntry> createAndUse(const ImageFrameGenerator* generator, PassOwnPtr<ScaledImageFragment> image)
{
@@ -207,8 +205,8 @@ private:
// FIXME: getSafeSize() returns size in bytes truncated to a 32-bits integer.
// Find a way to get the size in 64-bits.
- virtual size_t memoryUsageInBytes() const { return cachedImage()->bitmap().getSafeSize(); }
- virtual CacheType type() const { return TypeImage; }
+ virtual size_t memoryUsageInBytes() const OVERRIDE { return cachedImage()->bitmap().getSafeSize(); }
+ virtual CacheType type() const OVERRIDE { return TypeImage; }
static ImageCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size, size_t index, size_t generation)
{
@@ -222,7 +220,7 @@ private:
OwnPtr<ScaledImageFragment> m_cachedImage;
};
- class DecoderCacheEntry : public CacheEntry {
+ class DecoderCacheEntry FINAL : public CacheEntry {
public:
static PassOwnPtr<DecoderCacheEntry> create(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder, bool isDiscardable)
{
@@ -236,8 +234,8 @@ private:
{
}
- virtual size_t memoryUsageInBytes() const { return m_size.width() * m_size.height() * 4; }
- virtual CacheType type() const { return TypeDecoder; }
+ virtual size_t memoryUsageInBytes() const OVERRIDE { return m_size.width() * m_size.height() * 4; }
+ virtual CacheType type() const OVERRIDE { return TypeDecoder; }
static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size)
{
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
index 7ac6cb2c3c2..ef4cf128336 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
@@ -41,7 +41,7 @@ class ImageDecodingStoreTest : public ::testing::Test, public MockImageDecoderCl
public:
virtual void SetUp()
{
- ImageDecodingStore::initializeOnce();
+ ImageDecodingStore::instance()->setCacheLimitInBytes(1024 * 1024);
ImageDecodingStore::instance()->setImageCachingEnabled(true);
m_data = SharedBuffer::create();
m_generator = ImageFrameGenerator::create(SkISize::Make(100, 100), m_data, true);
@@ -50,7 +50,7 @@ public:
virtual void TearDown()
{
- ImageDecodingStore::shutdown();
+ ImageDecodingStore::instance()->clear();
}
virtual void decoderBeingDestroyed()
@@ -77,22 +77,26 @@ protected:
PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size, bool discardable = false, size_t index = 0)
{
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- if (!discardable)
+ bitmap.setInfo(SkImageInfo::MakeN32Premul(size));
+ if (!discardable) {
bitmap.allocPixels();
- else
- bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
+ } else {
+ MockDiscardablePixelRef::Allocator mockDiscardableAllocator;
+ bitmap.allocPixels(&mockDiscardableAllocator, 0);
+ }
return ScaledImageFragment::createComplete(size, index, bitmap);
}
PassOwnPtr<ScaledImageFragment> createIncompleteImage(const SkISize& size, bool discardable = false, size_t generation = 0)
{
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- if (!discardable)
+ bitmap.setInfo(SkImageInfo::MakeN32Premul(size));
+ if (!discardable) {
bitmap.allocPixels();
- else
- bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
+ } else {
+ MockDiscardablePixelRef::Allocator mockDiscardableAllocator;
+ bitmap.allocPixels(&mockDiscardableAllocator, 0);
+ }
return ScaledImageFragment::createPartial(size, 0, generation, bitmap);
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
index 1c04365f94f..a51db79f686 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
@@ -35,35 +35,55 @@
#include "platform/image-decoders/ImageDecoder.h"
#include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkMallocPixelRef.h"
namespace WebCore {
-namespace {
+// Creates a SkPixelRef such that the memory for pixels is given by an external body.
+// This is used to write directly to the memory given by Skia during decoding.
+class ImageFrameGenerator::ExternalMemoryAllocator : public SkBitmap::Allocator {
+public:
+ ExternalMemoryAllocator(const SkImageInfo& info, void* pixels, size_t rowBytes)
+ : m_info(info)
+ , m_pixels(pixels)
+ , m_rowBytes(rowBytes)
+ {
+ }
-skia::ImageOperations::ResizeMethod resizeMethod()
-{
- return skia::ImageOperations::RESIZE_LANCZOS3;
-}
+ virtual bool allocPixelRef(SkBitmap* dst, SkColorTable* ctable) OVERRIDE
+ {
+ const SkImageInfo& info = dst->info();
+ if (kUnknown_SkColorType == info.colorType())
+ return false;
-} // namespace
+ if (info != m_info || m_rowBytes != dst->rowBytes())
+ return false;
+
+ if (!dst->installPixels(m_info, m_pixels, m_rowBytes))
+ return false;
+ dst->lockPixels();
+ return true;
+ }
+
+private:
+ SkImageInfo m_info;
+ void* m_pixels;
+ size_t m_rowBytes;
+};
ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<SharedBuffer> data, bool allDataReceived, bool isMultiFrame)
: m_fullSize(fullSize)
, m_isMultiFrame(isMultiFrame)
, m_decodeFailedAndEmpty(false)
, m_decodeCount(ScaledImageFragment::FirstPartialImage)
- , m_allocator(adoptPtr(new DiscardablePixelRefAllocator()))
+ , m_discardableAllocator(adoptPtr(new DiscardablePixelRefAllocator()))
{
setData(data.get(), allDataReceived);
}
ImageFrameGenerator::~ImageFrameGenerator()
{
- // FIXME: This check is not really thread-safe. This should be changed to:
- // ImageDecodingStore::removeCacheFromInstance(this);
- // Which uses a lock internally.
- if (ImageDecodingStore::instance())
- ImageDecodingStore::instance()->removeCacheIndexedByGenerator(this);
+ ImageDecodingStore::instance()->removeCacheIndexedByGenerator(this);
}
void ImageFrameGenerator::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
@@ -95,11 +115,7 @@ const ScaledImageFragment* ImageFrameGenerator::decodeAndScale(const SkISize& sc
TRACE_EVENT2("webkit", "ImageFrameGenerator::decodeAndScale", "generator", this, "decodeCount", static_cast<int>(m_decodeCount));
- cachedImage = tryToScale(0, scaledSize, index);
- if (cachedImage)
- return cachedImage;
-
- cachedImage = tryToResumeDecodeAndScale(scaledSize, index);
+ cachedImage = tryToResumeDecode(scaledSize, index);
if (cachedImage)
return cachedImage;
return 0;
@@ -108,33 +124,49 @@ const ScaledImageFragment* ImageFrameGenerator::decodeAndScale(const SkISize& sc
bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes)
{
// This method is called to populate a discardable memory owned by Skia.
- // Ideally we want the decoder to write directly to |pixels| but this
- // simple implementation copies from a decoded bitmap.
+
+ // Prevents concurrent decode or scale operations on the same image data.
+ MutexLocker lock(m_decodeMutex);
// This implementation does not support scaling so check the requested size.
- ASSERT(m_fullSize.width() == info.fWidth);
- ASSERT(m_fullSize.height() == info.fHeight);
+ SkISize scaledSize = SkISize::Make(info.fWidth, info.fHeight);
+ ASSERT(m_fullSize == scaledSize);
+
+ if (m_decodeFailedAndEmpty)
+ return 0;
+
+ TRACE_EVENT2("webkit", "ImageFrameGenerator::decodeAndScale", "generator", this, "decodeCount", static_cast<int>(m_decodeCount));
// Don't use discardable memory for decoding if Skia is providing output
- // memory. By clearing the memory allocator decoding will use heap memory.
+ // memory. Instead use ExternalMemoryAllocator such that we can
+ // write directly to the memory given by Skia.
//
// TODO:
// This is not pretty because this class is used in two different code
// paths: discardable memory decoding on Android and discardable memory
// in Skia. Once the transition to caching in Skia is complete we can get
// rid of the logic that handles discardable memory.
- m_allocator.clear();
+ m_discardableAllocator.clear();
+ m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, rowBytes));
- const ScaledImageFragment* cachedImage = decodeAndScale(SkISize::Make(info.fWidth, info.fHeight), index);
+ const ScaledImageFragment* cachedImage = tryToResumeDecode(scaledSize, index);
if (!cachedImage)
return false;
- ASSERT(cachedImage->bitmap().width() == info.fWidth);
- ASSERT(cachedImage->bitmap().height() == info.fHeight);
+ // Don't keep the allocator because it contains a pointer to memory
+ // that we do not own.
+ m_externalAllocator.clear();
+
+ ASSERT(cachedImage->bitmap().width() == scaledSize.width());
+ ASSERT(cachedImage->bitmap().height() == scaledSize.height());
- bool copied = cachedImage->bitmap().copyPixelsTo(pixels, rowBytes * info.fHeight, rowBytes);
+ bool result = true;
+ // Check to see if decoder has written directly to the memory provided
+ // by Skia. If not make a copy.
+ if (cachedImage->bitmap().getPixels() != pixels)
+ result = cachedImage->bitmap().copyPixelsTo(pixels, rowBytes * info.fHeight, rowBytes);
ImageDecodingStore::instance()->unlockCache(this, cachedImage);
- return copied;
+ return result;
}
const ScaledImageFragment* ImageFrameGenerator::tryToLockCompleteCache(const SkISize& scaledSize, size_t index)
@@ -145,34 +177,7 @@ const ScaledImageFragment* ImageFrameGenerator::tryToLockCompleteCache(const SkI
return 0;
}
-const ScaledImageFragment* ImageFrameGenerator::tryToScale(const ScaledImageFragment* fullSizeImage, const SkISize& scaledSize, size_t index)
-{
- TRACE_EVENT0("webkit", "ImageFrameGenerator::tryToScale");
-
- // If the requested scaled size is the same as the full size then exit
- // early. This saves a cache lookup.
- if (scaledSize == m_fullSize)
- return 0;
-
- if (!fullSizeImage && !ImageDecodingStore::instance()->lockCache(this, m_fullSize, index, &fullSizeImage))
- return 0;
-
- // This call allocates the DiscardablePixelRef and lock/unlocks it
- // afterwards. So the memory allocated to the scaledBitmap can be
- // discarded after this call. Need to lock the scaledBitmap and
- // check the pixels before using it next time.
- SkBitmap scaledBitmap = skia::ImageOperations::Resize(fullSizeImage->bitmap(), resizeMethod(), scaledSize.width(), scaledSize.height(), m_allocator.get());
-
- OwnPtr<ScaledImageFragment> scaledImage;
- if (fullSizeImage->isComplete())
- scaledImage = ScaledImageFragment::createComplete(scaledSize, fullSizeImage->index(), scaledBitmap);
- else
- scaledImage = ScaledImageFragment::createPartial(scaledSize, fullSizeImage->index(), nextGenerationId(), scaledBitmap);
- ImageDecodingStore::instance()->unlockCache(this, fullSizeImage);
- return ImageDecodingStore::instance()->insertAndLockCache(this, scaledImage.release());
-}
-
-const ScaledImageFragment* ImageFrameGenerator::tryToResumeDecodeAndScale(const SkISize& scaledSize, size_t index)
+const ScaledImageFragment* ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_t index)
{
TRACE_EVENT1("webkit", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index));
@@ -218,9 +223,7 @@ const ScaledImageFragment* ImageFrameGenerator::tryToResumeDecodeAndScale(const
ImageDecodingStore::instance()->insertDecoder(this, decoderContainer.release(), DiscardablePixelRef::isDiscardable(cachedImage->bitmap().pixelRef()));
}
- if (m_fullSize == scaledSize)
- return cachedImage;
- return tryToScale(cachedImage, scaledSize, index);
+ return cachedImage;
}
PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder)
@@ -230,10 +233,12 @@ PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(size_t index, ImageD
ASSERT(decoder);
SharedBuffer* data = 0;
bool allDataReceived = false;
+ bool newDecoder = false;
m_data.data(&data, &allDataReceived);
// Try to create an ImageDecoder if we are not given one.
if (!*decoder) {
+ newDecoder = true;
if (m_imageDecoderFactory)
*decoder = m_imageDecoderFactory->create().leakPtr();
@@ -244,10 +249,18 @@ PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(size_t index, ImageD
return nullptr;
}
- // TODO: this is very ugly. We need to refactor the way how we can pass a
- // memory allocator to image decoders.
- if (!m_isMultiFrame)
- (*decoder)->setMemoryAllocator(m_allocator.get());
+ // This variable is set to true if we can skip a memcpy of the decoded bitmap.
+ bool canSkipBitmapCopy = false;
+
+ if (!m_isMultiFrame && newDecoder && allDataReceived) {
+ // If we're using an external memory allocator that means we're decoding
+ // directly into the output memory and we can save one memcpy.
+ canSkipBitmapCopy = true;
+ if (m_externalAllocator)
+ (*decoder)->setMemoryAllocator(m_externalAllocator.get());
+ else
+ (*decoder)->setMemoryAllocator(m_discardableAllocator.get());
+ }
(*decoder)->setData(data, allDataReceived);
// If this call returns a newly allocated DiscardablePixelRef, then
// ImageFrame::m_bitmap and the contained DiscardablePixelRef are locked.
@@ -257,11 +270,15 @@ PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(size_t index, ImageD
ImageFrame* frame = (*decoder)->frameBufferAtIndex(index);
(*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder.
(*decoder)->clearCacheExceptFrame(index);
+ (*decoder)->setMemoryAllocator(0);
if (!frame || frame->status() == ImageFrame::FrameEmpty)
return nullptr;
- const bool isComplete = frame->status() == ImageFrame::FrameComplete;
+ // A cache object is considered complete if we can decode a complete frame.
+ // Or we have received all data. The image might not be fully decoded in
+ // the latter case.
+ const bool isCacheComplete = frame->status() == ImageFrame::FrameComplete || allDataReceived;
SkBitmap fullSizeBitmap = frame->getSkBitmap();
if (fullSizeBitmap.isNull())
return nullptr;
@@ -278,14 +295,25 @@ PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(size_t index, ImageD
}
ASSERT(fullSizeBitmap.width() == m_fullSize.width() && fullSizeBitmap.height() == m_fullSize.height());
- if (isComplete)
+ // We early out and do not copy the memory if decoder writes directly to
+ // the memory provided by Skia and the decode was complete.
+ if (canSkipBitmapCopy && isCacheComplete)
return ScaledImageFragment::createComplete(m_fullSize, index, fullSizeBitmap);
- // If the image is partial we need to return a copy. This is to avoid future
- // decode operations writing to the same bitmap.
+ // If the image is progressively decoded we need to return a copy.
+ // This is to avoid future decode operations writing to the same bitmap.
+ // FIXME: Note that discardable allocator is used. This is because the code
+ // is still used in the Android discardable memory path. When this code is
+ // used in the Skia discardable memory path |m_discardableAllocator| is empty.
+ // This is confusing and should be cleaned up when we can deprecate the use
+ // case for Android discardable memory.
SkBitmap copyBitmap;
- return fullSizeBitmap.copyTo(&copyBitmap, fullSizeBitmap.config(), m_allocator.get()) ?
- ScaledImageFragment::createPartial(m_fullSize, index, nextGenerationId(), copyBitmap) : nullptr;
+ if (!fullSizeBitmap.copyTo(&copyBitmap, fullSizeBitmap.colorType(), m_discardableAllocator.get()))
+ return nullptr;
+
+ if (isCacheComplete)
+ return ScaledImageFragment::createComplete(m_fullSize, index, copyBitmap);
+ return ScaledImageFragment::createPartial(m_fullSize, index, nextGenerationId(), copyBitmap);
}
bool ImageFrameGenerator::hasAlpha(size_t index)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h b/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h
index 32817b48a67..2f7d49be02e 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.h
@@ -86,18 +86,18 @@ public:
bool hasAlpha(size_t);
private:
+ class ExternalMemoryAllocator;
friend class ImageFrameGeneratorTest;
friend class DeferredImageDecoderTest;
// For testing. |factory| will overwrite the default ImageDecoder creation logic if |factory->create()| returns non-zero.
void setImageDecoderFactory(PassOwnPtr<ImageDecoderFactory> factory) { m_imageDecoderFactory = factory; }
// For testing.
- SkBitmap::Allocator* allocator() const { return m_allocator.get(); }
- void setAllocator(PassOwnPtr<SkBitmap::Allocator> allocator) { m_allocator = allocator; }
+ SkBitmap::Allocator* allocator() const { return m_discardableAllocator.get(); }
+ void setAllocator(PassOwnPtr<SkBitmap::Allocator> allocator) { m_discardableAllocator = allocator; }
// These methods are called while m_decodeMutex is locked.
const ScaledImageFragment* tryToLockCompleteCache(const SkISize& scaledSize, size_t index);
- const ScaledImageFragment* tryToScale(const ScaledImageFragment* fullSizeImage, const SkISize& scaledSize, size_t index);
- const ScaledImageFragment* tryToResumeDecodeAndScale(const SkISize& scaledSize, size_t index);
+ const ScaledImageFragment* tryToResumeDecode(const SkISize& scaledSize, size_t index);
// Use the given decoder to decode. If a decoder is not given then try to create one.
PassOwnPtr<ScaledImageFragment> decode(size_t index, ImageDecoder**);
@@ -113,7 +113,8 @@ private:
bool m_decodeFailedAndEmpty;
Vector<bool> m_hasAlpha;
size_t m_decodeCount;
- OwnPtr<SkBitmap::Allocator> m_allocator;
+ OwnPtr<SkBitmap::Allocator> m_discardableAllocator;
+ OwnPtr<ExternalMemoryAllocator> m_externalAllocator;
OwnPtr<ImageDecoderFactory> m_imageDecoderFactory;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
index 1f74b5b34a7..81d860fb341 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
@@ -40,7 +40,6 @@ namespace {
// Helper methods to generate standard sizes.
SkISize fullSize() { return SkISize::Make(100, 100); }
-SkISize scaledSize() { return SkISize::Make(50, 50); }
} // namespace
@@ -48,10 +47,10 @@ class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderC
public:
virtual void SetUp() OVERRIDE
{
- ImageDecodingStore::initializeOnce();
+ ImageDecodingStore::instance()->setCacheLimitInBytes(1024 * 1024);
ImageDecodingStore::instance()->setImageCachingEnabled(true);
m_data = SharedBuffer::create();
- m_generator = ImageFrameGenerator::create(fullSize(), m_data, true);
+ m_generator = ImageFrameGenerator::create(fullSize(), m_data, false);
useMockImageDecoderFactory();
m_decodersDestroyed = 0;
m_frameBufferRequestCount = 0;
@@ -60,7 +59,7 @@ public:
virtual void TearDown() OVERRIDE
{
- ImageDecodingStore::shutdown();
+ ImageDecodingStore::instance()->clear();
}
virtual void decoderBeingDestroyed() OVERRIDE
@@ -93,8 +92,8 @@ protected:
PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size)
{
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- bitmap.allocPixels();
+ if (!bitmap.allocN32Pixels(size.width(), size.height()))
+ return nullptr;
return ScaledImageFragment::createComplete(size, 0, bitmap);
}
@@ -116,7 +115,9 @@ protected:
PassOwnPtr<ScaledImageFragment> decode(size_t index)
{
ImageDecoder* decoder = 0;
- return m_generator->decode(index, &decoder);
+ OwnPtr<ScaledImageFragment> fragment = m_generator->decode(index, &decoder);
+ delete decoder;
+ return fragment.release();
}
RefPtr<SharedBuffer> m_data;
@@ -129,8 +130,10 @@ protected:
TEST_F(ImageFrameGeneratorTest, cacheHit)
{
+ OwnPtr<ScaledImageFragment> completeImageTemp = createCompleteImage(fullSize());
+ ASSERT_TRUE(completeImageTemp);
const ScaledImageFragment* fullImage = ImageDecodingStore::instance()->insertAndLockCache(
- m_generator.get(), createCompleteImage(fullSize()));
+ m_generator.get(), completeImageTemp.release());
EXPECT_EQ(fullSize(), fullImage->scaledSize());
ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
@@ -142,62 +145,11 @@ TEST_F(ImageFrameGeneratorTest, cacheHit)
EXPECT_EQ(0, m_frameBufferRequestCount);
}
-TEST_F(ImageFrameGeneratorTest, cacheMissWithScale)
-{
- const ScaledImageFragment* fullImage = ImageDecodingStore::instance()->insertAndLockCache(
- m_generator.get(), createCompleteImage(fullSize()));
- EXPECT_EQ(fullSize(), fullImage->scaledSize());
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
-
- // Cache miss because of scaled size not found.
- const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_NE(fullImage, scaledImage);
- EXPECT_EQ(scaledSize(), scaledImage->scaledSize());
- EXPECT_TRUE(m_generator->hasAlpha(0));
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
-
- // Cache hit.
- const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_EQ(scaledImage, tempImage);
- EXPECT_EQ(scaledSize(), tempImage->scaledSize());
- EXPECT_TRUE(m_generator->hasAlpha(0));
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
- EXPECT_EQ(0, m_frameBufferRequestCount);
-}
-
-TEST_F(ImageFrameGeneratorTest, cacheMissWithDecodeAndScale)
-{
- setFrameStatus(ImageFrame::FrameComplete);
-
- // Cache miss.
- const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_EQ(1, m_frameBufferRequestCount);
- EXPECT_EQ(scaledSize(), scaledImage->scaledSize());
- EXPECT_FALSE(m_generator->hasAlpha(0));
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
- EXPECT_EQ(1, m_decodersDestroyed);
-
- // Cache hit.
- const ScaledImageFragment* fullImage = m_generator->decodeAndScale(fullSize());
- EXPECT_NE(scaledImage, fullImage);
- EXPECT_EQ(fullSize(), fullImage->scaledSize());
- EXPECT_FALSE(m_generator->hasAlpha(0));
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
-
- // Cache hit.
- const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_EQ(scaledImage, tempImage);
- EXPECT_EQ(scaledSize(), tempImage->scaledSize());
- EXPECT_FALSE(m_generator->hasAlpha(0));
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
- EXPECT_EQ(1, m_frameBufferRequestCount);
-}
-
TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecode)
{
setFrameStatus(ImageFrame::FramePartial);
- const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
+ const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(1, m_frameBufferRequestCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
@@ -216,29 +168,6 @@ TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecode)
EXPECT_EQ(0, m_decodersDestroyed);
}
-TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecodeAndScale)
-{
- setFrameStatus(ImageFrame::FramePartial);
-
- const ScaledImageFragment* tempImage= m_generator->decodeAndScale(scaledSize());
- EXPECT_FALSE(tempImage->isComplete());
- EXPECT_EQ(1, m_frameBufferRequestCount);
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
- EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
- EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
- EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
-
- addNewData();
- tempImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_FALSE(tempImage->isComplete());
- EXPECT_EQ(2, m_frameBufferRequestCount);
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
- EXPECT_EQ(5, ImageDecodingStore::instance()->cacheEntries());
- EXPECT_EQ(4, ImageDecodingStore::instance()->imageCacheEntries());
- EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
- EXPECT_EQ(0, m_decodersDestroyed);
-}
-
TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete)
{
setFrameStatus(ImageFrame::FramePartial);
@@ -270,42 +199,6 @@ TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete)
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
}
-TEST_F(ImageFrameGeneratorTest, incompleteDecodeAndScaleBecomesComplete)
-{
- setFrameStatus(ImageFrame::FramePartial);
-
- const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_FALSE(tempImage->isComplete());
- EXPECT_EQ(1, m_frameBufferRequestCount);
- EXPECT_EQ(0, m_decodersDestroyed);
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
- EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
- EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
- EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
-
- setFrameStatus(ImageFrame::FrameComplete);
- addNewData();
-
- tempImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_TRUE(tempImage->isComplete());
- EXPECT_EQ(2, m_frameBufferRequestCount);
- EXPECT_EQ(1, m_decodersDestroyed);
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
- EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries());
- EXPECT_EQ(4, ImageDecodingStore::instance()->imageCacheEntries());
- EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
-
- tempImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_TRUE(tempImage->isComplete());
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
-
- tempImage = m_generator->decodeAndScale(fullSize());
- EXPECT_TRUE(tempImage->isComplete());
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
-
- EXPECT_EQ(2, m_frameBufferRequestCount);
-}
-
static void decodeThreadMain(ImageFrameGenerator* generator)
{
const ScaledImageFragment* tempImage = generator->decodeAndScale(fullSize());
@@ -325,7 +218,7 @@ TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded)
EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
- // Frame can now be decoded completely.
+ // LocalFrame can now be decoded completely.
setFrameStatus(ImageFrame::FrameComplete);
addNewData();
OwnPtr<blink::WebThread> thread = adoptPtr(blink::Platform::current()->createThread("DecodeThread"));
@@ -344,34 +237,6 @@ TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded)
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
}
-TEST_F(ImageFrameGeneratorTest, concurrentIncompleteDecodeAndScale)
-{
- setFrameStatus(ImageFrame::FramePartial);
-
- const ScaledImageFragment* fullImage = m_generator->decodeAndScale(fullSize());
- const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_FALSE(fullImage->isComplete());
- EXPECT_FALSE(scaledImage->isComplete());
- EXPECT_EQ(2, m_frameBufferRequestCount);
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
- EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries());
- EXPECT_EQ(3, ImageDecodingStore::instance()->imageCacheEntries());
- EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
- EXPECT_EQ(0, m_decodersDestroyed);
-
- addNewData();
- setFrameStatus(ImageFrame::FrameComplete);
- scaledImage = m_generator->decodeAndScale(scaledSize());
- EXPECT_TRUE(scaledImage->isComplete());
- EXPECT_EQ(3, m_frameBufferRequestCount);
- ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
- EXPECT_EQ(5, ImageDecodingStore::instance()->cacheEntries());
- EXPECT_EQ(5, ImageDecodingStore::instance()->imageCacheEntries());
- EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
- EXPECT_EQ(1, m_decodersDestroyed);
-}
-
TEST_F(ImageFrameGeneratorTest, incompleteBitmapCopied)
{
setFrameStatus(ImageFrame::FramePartial);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageLayerChromiumTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ImageLayerChromiumTest.cpp
new file mode 100644
index 00000000000..0ae7d518523
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageLayerChromiumTest.cpp
@@ -0,0 +1,130 @@
+/*
+ * 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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"
+#include "platform/graphics/Image.h"
+
+#include "platform/graphics/GraphicsLayer.h"
+#include "platform/graphics/skia/NativeImageSkia.h"
+#include "public/platform/WebImageLayer.h"
+#include "wtf/PassOwnPtr.h"
+
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+class MockGraphicsLayerClient : public GraphicsLayerClient {
+public:
+ virtual void notifyAnimationStarted(const GraphicsLayer*, double monotonicTime) OVERRIDE { }
+ virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) OVERRIDE { }
+ virtual String debugName(const GraphicsLayer*) OVERRIDE { return String(); }
+};
+
+class TestImage : public Image {
+public:
+
+ static PassRefPtr<TestImage> create(const IntSize& size, bool isOpaque)
+ {
+ return adoptRef(new TestImage(size, isOpaque));
+ }
+
+ explicit TestImage(const IntSize& size, bool isOpaque)
+ : Image(0)
+ , m_size(size)
+ {
+ SkBitmap bitmap;
+ EXPECT_TRUE(bitmap.allocN32Pixels(size.width(), size.height(), isOpaque));
+ m_nativeImage = NativeImageSkia::create(bitmap);
+ }
+
+ virtual bool isBitmapImage() const OVERRIDE
+ {
+ return true;
+ }
+
+ virtual bool currentFrameKnownToBeOpaque() OVERRIDE
+ {
+ return m_nativeImage->bitmap().isOpaque();
+ }
+
+ virtual IntSize size() const OVERRIDE
+ {
+ return m_size;
+ }
+
+ virtual PassRefPtr<NativeImageSkia> nativeImageForCurrentFrame() OVERRIDE
+ {
+ if (m_size.isZero())
+ return nullptr;
+
+ return m_nativeImage;
+ }
+
+ // Stub implementations of pure virtual Image functions.
+ virtual void destroyDecodedData(bool) OVERRIDE
+ {
+ }
+
+ virtual void draw(GraphicsContext*, const FloatRect&, const FloatRect&, CompositeOperator, blink::WebBlendMode) OVERRIDE
+ {
+ }
+
+private:
+
+ IntSize m_size;
+
+ RefPtr<NativeImageSkia> m_nativeImage;
+};
+
+class GraphicsLayerForTesting : public GraphicsLayer {
+public:
+ explicit GraphicsLayerForTesting(GraphicsLayerClient* client)
+ : GraphicsLayer(client) { };
+
+ virtual blink::WebLayer* contentsLayer() const { return GraphicsLayer::contentsLayer(); }
+};
+
+TEST(ImageLayerChromiumTest, opaqueImages)
+{
+ MockGraphicsLayerClient client;
+ OwnPtr<GraphicsLayerForTesting> graphicsLayer = adoptPtr(new GraphicsLayerForTesting(&client));
+ ASSERT_TRUE(graphicsLayer.get());
+
+ RefPtr<Image> opaqueImage = TestImage::create(IntSize(100, 100), true /* opaque */);
+ ASSERT_TRUE(opaqueImage.get());
+ RefPtr<Image> nonOpaqueImage = TestImage::create(IntSize(100, 100), false /* opaque */);
+ ASSERT_TRUE(nonOpaqueImage.get());
+
+ ASSERT_FALSE(graphicsLayer->contentsLayer());
+
+ graphicsLayer->setContentsToImage(opaqueImage.get());
+ ASSERT_TRUE(graphicsLayer->contentsLayer()->opaque());
+
+ graphicsLayer->setContentsToImage(nonOpaqueImage.get());
+ ASSERT_FALSE(graphicsLayer->contentsLayer()->opaque());
+}
+
+} // namespace
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageSource.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ImageSource.cpp
index dee22c39154..68ce34edfc3 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageSource.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageSource.cpp
@@ -55,14 +55,14 @@ bool ImageSource::initialized() const
return m_decoder;
}
-void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
+void ImageSource::setData(SharedBuffer& data, bool allDataReceived)
{
// Make the decoder by sniffing the bytes.
// This method will examine the data and instantiate an instance of the appropriate decoder plugin.
// If insufficient bytes are available to determine the image type, no decoder plugin will be
// made.
if (!m_decoder)
- m_decoder = DeferredImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption);
+ m_decoder = DeferredImageDecoder::create(data, m_alphaOption, m_gammaAndColorProfileOption);
if (m_decoder)
m_decoder->setData(data, allDataReceived);
@@ -78,6 +78,11 @@ bool ImageSource::isSizeAvailable()
return m_decoder && m_decoder->isSizeAvailable();
}
+bool ImageSource::hasColorProfile() const
+{
+ return m_decoder && m_decoder->hasColorProfile();
+}
+
IntSize ImageSource::size(RespectImageOrientationEnum shouldRespectOrientation) const
{
return frameSizeAtIndex(0, shouldRespectOrientation);
@@ -113,16 +118,16 @@ size_t ImageSource::frameCount() const
PassRefPtr<NativeImageSkia> ImageSource::createFrameAtIndex(size_t index)
{
if (!m_decoder)
- return 0;
+ return nullptr;
ImageFrame* buffer = m_decoder->frameBufferAtIndex(index);
if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
- return 0;
+ return nullptr;
// Zero-height images can cause problems for some ports. If we have an
// empty image dimension, just bail.
if (size().isEmpty())
- return 0;
+ return nullptr;
// Return the buffer contents as a native image. For some ports, the data
// is already in a native container, and this just increments its refcount.
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ImageSource.h b/chromium/third_party/WebKit/Source/platform/graphics/ImageSource.h
index bf84e295c04..e599781c08b 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ImageSource.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ImageSource.h
@@ -42,8 +42,8 @@ class IntSize;
class NativeImageSkia;
class SharedBuffer;
-// Right now GIFs are the only recognized image format that supports animation.
-// The animation system and the constants below are designed with this in mind.
+// GIF and WebP support animation. The explanation below is in terms of GIF,
+// but the same constants are used for WebP, too.
// GIFs have an optional 16-bit unsigned loop count that describes how an
// animated GIF should be cycled. If the loop count is absent, the animation
// cycles once; if it is 0, the animation cycles infinitely; otherwise the
@@ -98,15 +98,19 @@ public:
bool initialized() const;
- void setData(SharedBuffer* data, bool allDataReceived);
+ void setData(SharedBuffer& data, bool allDataReceived);
String filenameExtension() const;
bool isSizeAvailable();
+ bool hasColorProfile() const;
IntSize size(RespectImageOrientationEnum = DoNotRespectImageOrientation) const;
IntSize frameSizeAtIndex(size_t, RespectImageOrientationEnum = DoNotRespectImageOrientation) const;
bool getHotSpot(IntPoint&) const;
+ // Returns one of the cAnimationXXX constants at the top of the file, or
+ // a loop count. In the latter case, the actual number of times the animation
+ // cycles is one more than the loop count. See comment atop the file.
int repetitionCount();
size_t frameCount() const;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.cpp b/chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.cpp
index 26115ee88df..af3f781f4e3 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.cpp
@@ -50,7 +50,7 @@ SkData* LazyDecodingPixelRef::onRefEncodedData()
{
// If the image has been clipped or scaled, do not return the original encoded data, since
// on playback it will not be known how the clipping/scaling was done.
- RefPtr<SharedBuffer> buffer = 0;
+ RefPtr<SharedBuffer> buffer = nullptr;
bool allDataReceived = false;
m_frameGenerator->copyData(&buffer, &allDataReceived);
if (buffer && allDataReceived) {
@@ -60,9 +60,9 @@ SkData* LazyDecodingPixelRef::onRefEncodedData()
return 0;
}
-void* LazyDecodingPixelRef::onLockPixels(SkColorTable**)
+bool LazyDecodingPixelRef::onNewLockPixels(LockRec* rec)
{
- TRACE_EVENT_ASYNC_BEGIN0("webkit", "LazyDecodingPixelRef::lockPixels", this);
+ TRACE_EVENT_ASYNC_BEGIN0("webkit", "LazyDecodingPixelRef::onNewLockPixels", this);
ASSERT(!m_lockedImageResource);
@@ -75,14 +75,17 @@ void* LazyDecodingPixelRef::onLockPixels(SkColorTable**)
if (!m_lockedImageResource) {
PlatformInstrumentation::willDecodeLazyPixelRef(getGenerationID());
m_lockedImageResource = m_frameGenerator->decodeAndScale(size, m_frameIndex);
- PlatformInstrumentation::didDecodeLazyPixelRef(getGenerationID());
+ PlatformInstrumentation::didDecodeLazyPixelRef();
}
if (!m_lockedImageResource)
- return 0;
+ return false;
ASSERT(!m_lockedImageResource->bitmap().isNull());
ASSERT(m_lockedImageResource->scaledSize() == size);
- return m_lockedImageResource->bitmap().getAddr(0, 0);
+ rec->fPixels = m_lockedImageResource->bitmap().getAddr(0, 0);
+ rec->fColorTable = 0;
+ rec->fRowBytes = m_lockedImageResource->bitmap().rowBytes();
+ return true;
}
void LazyDecodingPixelRef::onUnlockPixels()
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.h b/chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.h
index c1a137e9725..80ceeaf8153 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/LazyDecodingPixelRef.h
@@ -45,7 +45,7 @@ namespace WebCore {
class ImageFrameGenerator;
class ScaledImageFragment;
-class LazyDecodingPixelRef : public LazyPixelRef {
+class LazyDecodingPixelRef FINAL : public LazyPixelRef {
public:
LazyDecodingPixelRef(const SkImageInfo&, PassRefPtr<ImageFrameGenerator>, size_t index);
virtual ~LazyDecodingPixelRef();
@@ -57,17 +57,17 @@ public:
// Returns true if the image might already be decoded in the cache.
// Optimistic version of PrepareToDecode; requires less locking.
- virtual bool MaybeDecoded();
- virtual bool PrepareToDecode(const LazyPixelRef::PrepareParams&);
- virtual void Decode();
+ virtual bool MaybeDecoded() OVERRIDE;
+ virtual bool PrepareToDecode(const LazyPixelRef::PrepareParams&) OVERRIDE;
+ virtual void Decode() OVERRIDE;
protected:
// SkPixelRef implementation.
- virtual void* onLockPixels(SkColorTable**);
- virtual void onUnlockPixels();
- virtual bool onLockPixelsAreWritable() const;
+ virtual bool onNewLockPixels(LockRec*) OVERRIDE;
+ virtual void onUnlockPixels() OVERRIDE;
+ virtual bool onLockPixelsAreWritable() const OVERRIDE;
- virtual SkData* onRefEncodedData() SK_OVERRIDE;
+ virtual SkData* onRefEncodedData() OVERRIDE;
private:
RefPtr<ImageFrameGenerator> m_frameGenerator;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.cpp b/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.cpp
index 174970257a1..9b2266822ac 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.cpp
@@ -48,13 +48,16 @@ OpaqueRectTrackingContentLayerDelegate::~OpaqueRectTrackingContentLayerDelegate(
{
}
-void OpaqueRectTrackingContentLayerDelegate::paintContents(SkCanvas* canvas, const WebRect& clip, bool canPaintLCDText, WebFloatRect& opaque)
+void OpaqueRectTrackingContentLayerDelegate::paintContents(
+ SkCanvas* canvas, const WebRect& clip, bool canPaintLCDText, WebFloatRect& opaque,
+ blink::WebContentLayerClient::GraphicsContextStatus contextStatus)
{
static const unsigned char* annotationsEnabled = 0;
if (UNLIKELY(!annotationsEnabled))
annotationsEnabled = EventTracer::getTraceCategoryEnabledFlag(TRACE_DISABLED_BY_DEFAULT("blink.graphics_context_annotations"));
- GraphicsContext context(canvas);
+ GraphicsContext context(canvas,
+ contextStatus == blink::WebContentLayerClient::GraphicsContextEnabled ? GraphicsContext::NothingDisabled : GraphicsContext::FullyDisabled);
context.setTrackOpaqueRegion(!m_opaque);
context.setCertainlyOpaque(m_opaque);
context.setShouldSmoothFonts(canPaintLCDText);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.h b/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.h
index e870b9cf92d..02f1d60b73c 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegate.h
@@ -56,7 +56,8 @@ public:
void setOpaque(bool opaque) { m_opaque = opaque; }
// blink::WebContentLayerClient implementation.
- virtual void paintContents(SkCanvas*, const blink::WebRect& clip, bool canPaintLCDText, blink::WebFloatRect& opaque) OVERRIDE;
+ virtual void paintContents(SkCanvas*, const blink::WebRect& clip, bool canPaintLCDText, blink::WebFloatRect& opaque,
+ blink::WebContentLayerClient::GraphicsContextStatus = GraphicsContextEnabled) OVERRIDE;
private:
GraphicsContextPainter* m_painter;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegateTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegateTest.cpp
new file mode 100644
index 00000000000..40e7ced5cbb
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/OpaqueRectTrackingContentLayerDelegateTest.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2012 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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"
+
+#include "platform/graphics/OpaqueRectTrackingContentLayerDelegate.h"
+
+#include "platform/geometry/IntRect.h"
+#include "platform/graphics/Color.h"
+#include "platform/graphics/GraphicsContext.h"
+#include "public/platform/WebFloatRect.h"
+#include "public/platform/WebRect.h"
+#include "skia/ext/platform_canvas.h"
+
+#include <gtest/gtest.h>
+
+using blink::WebRect;
+using blink::WebFloatRect;
+using namespace WebCore;
+
+namespace {
+
+struct PaintCallback {
+ virtual void operator()(GraphicsContext&, const IntRect&) = 0;
+};
+
+class TestLayerPainterChromium : public GraphicsContextPainter {
+public:
+ TestLayerPainterChromium(PaintCallback& callback) : m_callback(callback) { }
+
+ virtual void paint(GraphicsContext& context, const IntRect& contentRect) OVERRIDE
+ {
+ m_callback(context, contentRect);
+ }
+
+private:
+ PaintCallback& m_callback;
+};
+
+// Paint callback functions
+
+struct PaintFillOpaque : public PaintCallback {
+ virtual void operator()(GraphicsContext& context, const IntRect& contentRect) OVERRIDE
+ {
+ Color opaque(255, 0, 0, 255);
+ IntRect top(contentRect.x(), contentRect.y(), contentRect.width(), contentRect.height() / 2);
+ IntRect bottom(contentRect.x(), contentRect.y() + contentRect.height() / 2, contentRect.width(), contentRect.height() / 2);
+ context.fillRect(top, opaque);
+ context.fillRect(bottom, opaque);
+ }
+};
+
+struct PaintFillAlpha : public PaintCallback {
+ virtual void operator()(GraphicsContext& context, const IntRect& contentRect)
+ {
+ Color alpha(0, 0, 0, 0);
+ context.fillRect(contentRect, alpha);
+ }
+};
+
+struct PaintFillPartialOpaque : public PaintCallback {
+ PaintFillPartialOpaque(IntRect opaqueRect)
+ : m_opaqueRect(opaqueRect)
+ {
+ }
+
+ virtual void operator()(GraphicsContext& context, const IntRect& contentRect)
+ {
+ Color alpha(0, 0, 0, 0);
+ context.fillRect(contentRect, alpha);
+
+ IntRect fillOpaque = m_opaqueRect;
+ fillOpaque.intersect(contentRect);
+
+ Color opaque(255, 255, 255, 255);
+ context.fillRect(fillOpaque, opaque);
+ }
+
+ IntRect m_opaqueRect;
+};
+
+#define EXPECT_EQ_RECT(a, b) \
+ EXPECT_EQ(a.x, b.x); \
+ EXPECT_EQ(a.width, b.width); \
+ EXPECT_EQ(a.y, b.y); \
+ EXPECT_EQ(a.height, b.height);
+
+class OpaqueRectTrackingContentLayerDelegateTest : public testing::Test {
+public:
+ OpaqueRectTrackingContentLayerDelegateTest()
+ : m_skCanvas(adoptPtr(skia::CreateBitmapCanvas(canvasRect().width, canvasRect().height, false)))
+ {
+ }
+
+ SkCanvas* skCanvas() { return m_skCanvas.get(); }
+ WebRect canvasRect() { return WebRect(0, 0, 400, 400); }
+
+private:
+ OwnPtr<SkCanvas> m_skCanvas;
+};
+
+TEST_F(OpaqueRectTrackingContentLayerDelegateTest, testOpaqueRectPresentAfterOpaquePaint)
+{
+ PaintFillOpaque fillOpaque;
+ TestLayerPainterChromium painter(fillOpaque);
+
+ OpaqueRectTrackingContentLayerDelegate delegate(&painter);
+
+ WebFloatRect opaqueRect;
+ delegate.paintContents(skCanvas(), canvasRect(), false, opaqueRect);
+ EXPECT_EQ_RECT(WebFloatRect(0, 0, 400, 400), opaqueRect);
+}
+
+TEST_F(OpaqueRectTrackingContentLayerDelegateTest, testOpaqueRectNotPresentAfterNonOpaquePaint)
+{
+ PaintFillAlpha fillAlpha;
+ TestLayerPainterChromium painter(fillAlpha);
+ OpaqueRectTrackingContentLayerDelegate delegate(&painter);
+
+ WebFloatRect opaqueRect;
+ delegate.paintContents(skCanvas(), canvasRect(), false, opaqueRect);
+ EXPECT_EQ_RECT(WebFloatRect(0, 0, 0, 0), opaqueRect);
+}
+
+TEST_F(OpaqueRectTrackingContentLayerDelegateTest, testOpaqueRectNotPresentForOpaqueLayerWithOpaquePaint)
+{
+ PaintFillOpaque fillOpaque;
+ TestLayerPainterChromium painter(fillOpaque);
+ OpaqueRectTrackingContentLayerDelegate delegate(&painter);
+
+ delegate.setOpaque(true);
+
+ WebFloatRect opaqueRect;
+ delegate.paintContents(skCanvas(), canvasRect(), false, opaqueRect);
+ EXPECT_EQ_RECT(WebFloatRect(0, 0, 0, 0), opaqueRect);
+}
+
+TEST_F(OpaqueRectTrackingContentLayerDelegateTest, testOpaqueRectNotPresentForOpaqueLayerWithNonOpaquePaint)
+{
+ PaintFillOpaque fillAlpha;
+ TestLayerPainterChromium painter(fillAlpha);
+ OpaqueRectTrackingContentLayerDelegate delegate(&painter);
+
+ delegate.setOpaque(true);
+
+ WebFloatRect opaqueRect;
+ delegate.paintContents(skCanvas(), canvasRect(), false, opaqueRect);
+ EXPECT_EQ_RECT(WebFloatRect(0, 0, 0, 0), opaqueRect);
+}
+
+TEST_F(OpaqueRectTrackingContentLayerDelegateTest, testPartialOpaqueRectNoTransform)
+{
+ IntRect partialRect(100, 200, 50, 75);
+ PaintFillPartialOpaque fillPartial(partialRect);
+ TestLayerPainterChromium painter(fillPartial);
+ OpaqueRectTrackingContentLayerDelegate delegate(&painter);
+
+ WebFloatRect opaqueRect;
+ delegate.paintContents(skCanvas(), canvasRect(), false, opaqueRect);
+ EXPECT_EQ_RECT(WebFloatRect(partialRect.x(), partialRect.y(), partialRect.width(), partialRect.height()), opaqueRect);
+}
+
+TEST_F(OpaqueRectTrackingContentLayerDelegateTest, testPartialOpaqueRectTranslation)
+{
+ IntRect partialRect(100, 200, 50, 75);
+ PaintFillPartialOpaque fillPartial(partialRect);
+ TestLayerPainterChromium painter(fillPartial);
+ OpaqueRectTrackingContentLayerDelegate delegate(&painter);
+
+ WebFloatRect opaqueRect;
+ WebRect contentRect(11, 12, 389, 388);
+ delegate.paintContents(skCanvas(), contentRect, false, opaqueRect);
+ EXPECT_EQ_RECT(WebFloatRect(partialRect.x(), partialRect.y(), partialRect.width(), partialRect.height()), opaqueRect);
+}
+
+} // namespace
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Path.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Path.cpp
index e04f4a8ea7b..44c455e4e2a 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Path.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Path.cpp
@@ -36,7 +36,6 @@
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/skia/SkiaUtils.h"
#include "platform/transforms/AffineTransform.h"
-#include "third_party/skia/include/core/SkPathMeasure.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
#include "wtf/MathExtras.h"
@@ -177,10 +176,8 @@ float Path::normalAngleAtLength(float length, bool& ok) const
return normal;
}
-bool Path::pointAndNormalAtLength(float length, FloatPoint& point, float& normal) const
+static bool calculatePointAndNormalOnPath(SkPathMeasure& measure, SkScalar length, FloatPoint& point, float& normalAngle, SkScalar* accumulatedLength = 0)
{
- SkPathMeasure measure(m_path, false);
-
do {
SkScalar contourLength = measure.getLength();
if (length <= contourLength) {
@@ -188,19 +185,58 @@ bool Path::pointAndNormalAtLength(float length, FloatPoint& point, float& normal
SkPoint position;
if (measure.getPosTan(length, &position, &tangent)) {
- normal = rad2deg(SkScalarToFloat(SkScalarATan2(tangent.fY, tangent.fX)));
+ normalAngle = rad2deg(SkScalarToFloat(SkScalarATan2(tangent.fY, tangent.fX)));
point = FloatPoint(SkScalarToFloat(position.fX), SkScalarToFloat(position.fY));
return true;
}
}
length -= contourLength;
+ if (accumulatedLength)
+ *accumulatedLength += contourLength;
} while (measure.nextContour());
+ return false;
+}
+
+bool Path::pointAndNormalAtLength(float length, FloatPoint& point, float& normal) const
+{
+ SkPathMeasure measure(m_path, false);
+
+ if (calculatePointAndNormalOnPath(measure, WebCoreFloatToSkScalar(length), point, normal))
+ return true;
normal = 0;
point = FloatPoint(0, 0);
return false;
}
+Path::PositionCalculator::PositionCalculator(const Path& path)
+ : m_path(path.skPath())
+ , m_pathMeasure(path.skPath(), false)
+ , m_accumulatedLength(0)
+{
+}
+
+bool Path::PositionCalculator::pointAndNormalAtLength(float length, FloatPoint& point, float& normalAngle)
+{
+ SkScalar skLength = WebCoreFloatToSkScalar(length);
+ if (skLength >= 0) {
+ if (skLength < m_accumulatedLength) {
+ // Reset path measurer to rewind (and restart from 0).
+ m_pathMeasure.setPath(&m_path, false);
+ m_accumulatedLength = 0;
+ } else {
+ skLength -= m_accumulatedLength;
+ }
+
+ if (calculatePointAndNormalOnPath(m_pathMeasure, skLength, point, normalAngle, &m_accumulatedLength))
+ return true;
+ }
+
+ normalAngle = 0;
+ point = FloatPoint(0, 0);
+ return false;
+}
+
void Path::clear()
{
m_path.reset();
@@ -248,27 +284,27 @@ void Path::setWindRule(const WindRule rule)
void Path::moveTo(const FloatPoint& point)
{
- m_path.moveTo(point);
+ m_path.moveTo(point.data());
}
void Path::addLineTo(const FloatPoint& point)
{
- m_path.lineTo(point);
+ m_path.lineTo(point.data());
}
void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& ep)
{
- m_path.quadTo(cp, ep);
+ m_path.quadTo(cp.data(), ep.data());
}
void Path::addBezierCurveTo(const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& ep)
{
- m_path.cubicTo(p1, p2, ep);
+ m_path.cubicTo(p1.data(), p2.data(), ep.data());
}
void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
{
- m_path.arcTo(p1, p2, WebCoreFloatToSkScalar(radius));
+ m_path.arcTo(p1.data(), p2.data(), WebCoreFloatToSkScalar(radius));
}
void Path::closeSubpath()
@@ -279,7 +315,7 @@ void Path::closeSubpath()
void Path::addEllipse(const FloatPoint& p, float radiusX, float radiusY, float startAngle, float endAngle, bool anticlockwise)
{
ASSERT(ellipseIsRenderable(startAngle, endAngle));
- ASSERT(startAngle >= 0 && startAngle < 2 * piFloat);
+ ASSERT(startAngle >= 0 && startAngle < twoPiFloat);
ASSERT((anticlockwise && (startAngle - endAngle) >= 0) || (!anticlockwise && (endAngle - startAngle) >= 0));
SkScalar cx = WebCoreFloatToSkScalar(p.x());
@@ -327,7 +363,7 @@ void Path::addRect(const FloatRect& rect)
void Path::addEllipse(const FloatPoint& p, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise)
{
ASSERT(ellipseIsRenderable(startAngle, endAngle));
- ASSERT(startAngle >= 0 && startAngle < 2 * piFloat);
+ ASSERT(startAngle >= 0 && startAngle < twoPiFloat);
ASSERT((anticlockwise && (startAngle - endAngle) >= 0) || (!anticlockwise && (endAngle - startAngle) >= 0));
if (!rotation) {
@@ -336,7 +372,7 @@ void Path::addEllipse(const FloatPoint& p, float radiusX, float radiusY, float r
}
// Add an arc after the relevant transform.
- AffineTransform ellipseTransform = AffineTransform::translation(p.x(), p.y()).rotate(rad2deg(rotation));
+ AffineTransform ellipseTransform = AffineTransform::translation(p.x(), p.y()).rotateRadians(rotation);
ASSERT(ellipseTransform.isInvertible());
AffineTransform inverseEllipseTransform = ellipseTransform.inverse();
transform(inverseEllipseTransform);
@@ -436,6 +472,11 @@ void Path::addBeziersForRoundedRect(const FloatRect& rect, const FloatSize& topL
closeSubpath();
}
+void Path::addPath(const Path& src, const AffineTransform& transform)
+{
+ m_path.addPath(src.skPath(), affineTransformToSkMatrix(transform));
+}
+
void Path::translate(const FloatSize& size)
{
m_path.offset(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height()));
@@ -446,11 +487,11 @@ bool Path::unionPath(const Path& other)
return Op(m_path, other.m_path, kUnion_PathOp, &m_path);
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
bool ellipseIsRenderable(float startAngle, float endAngle)
{
- return (std::abs(endAngle - startAngle) < 2 * piFloat)
- || WebCoreFloatNearlyEqual(std::abs(endAngle - startAngle), 2 * piFloat);
+ return (std::abs(endAngle - startAngle) < twoPiFloat)
+ || WebCoreFloatNearlyEqual(std::abs(endAngle - startAngle), twoPiFloat);
}
#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Path.h b/chromium/third_party/WebKit/Source/platform/graphics/Path.h
index 1970b97d500..f6bdd439bb5 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Path.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Path.h
@@ -33,6 +33,7 @@
#include "platform/geometry/RoundedRect.h"
#include "platform/graphics/WindRule.h"
#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkPathMeasure.h"
#include "wtf/FastAllocBase.h"
#include "wtf/Forward.h"
@@ -85,6 +86,25 @@ public:
float normalAngleAtLength(float length, bool& ok) const;
bool pointAndNormalAtLength(float length, FloatPoint&, float&) const;
+ // Helper for computing a sequence of positions and normals (normal angles) on a path.
+ // The best possible access pattern will be one where the |length| value is
+ // strictly increasing.
+ // For other access patterns, performance will vary depending on curvature
+ // and number of segments, but should never be worse than that of the
+ // state-less method on Path.
+ class PLATFORM_EXPORT PositionCalculator {
+ WTF_MAKE_NONCOPYABLE(PositionCalculator);
+ public:
+ explicit PositionCalculator(const Path&);
+
+ bool pointAndNormalAtLength(float length, FloatPoint&, float&);
+
+ private:
+ SkPath m_path;
+ SkPathMeasure m_pathMeasure;
+ SkScalar m_accumulatedLength;
+ };
+
void clear();
bool isEmpty() const;
// Gets the current point of the current path, which is conceptually the final point reached by the path so far.
@@ -111,6 +131,8 @@ public:
void addRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
void addRoundedRect(const RoundedRect&);
+ void addPath(const Path&, const AffineTransform&);
+
void translate(const FloatSize&);
const SkPath& skPath() const { return m_path; }
@@ -130,7 +152,7 @@ private:
SkPath m_path;
};
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
PLATFORM_EXPORT bool ellipseIsRenderable(float startAngle, float endAngle);
#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp b/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp
index 406c5b180cd..862ae8686e0 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp
@@ -25,8 +25,6 @@
namespace WebCore {
-static const float kPathSegmentLengthTolerance = 0.00001f;
-
static inline FloatPoint midPoint(const FloatPoint& first, const FloatPoint& second)
{
return FloatPoint((first.x() + second.x()) / 2.0f, (first.y() + second.y()) / 2.0f);
@@ -43,7 +41,13 @@ struct QuadraticBezier {
: start(s)
, control(c)
, end(e)
+ , splitDepth(0)
+ {
+ }
+
+ double magnitudeSquared() const
{
+ return ((double)(start.dot(start)) + (double)(control.dot(control)) + (double)(end.dot(end))) / 9.0;
}
float approximateDistance() const
@@ -62,11 +66,14 @@ struct QuadraticBezier {
left.start = start;
right.end = end;
+
+ left.splitDepth = right.splitDepth = splitDepth + 1;
}
FloatPoint start;
FloatPoint control;
FloatPoint end;
+ unsigned short splitDepth;
};
struct CubicBezier {
@@ -76,7 +83,13 @@ struct CubicBezier {
, control1(c1)
, control2(c2)
, end(e)
+ , splitDepth(0)
+ {
+ }
+
+ double magnitudeSquared() const
{
+ return ((double)(start.dot(start)) + (double)(control1.dot(control1)) + (double)(control2.dot(control2)) + (double)(end.dot(end))) / 16.0;
}
float approximateDistance() const
@@ -99,24 +112,26 @@ struct CubicBezier {
FloatPoint leftControl2ToRightControl1 = midPoint(left.control2, right.control1);
left.end = leftControl2ToRightControl1;
right.start = leftControl2ToRightControl1;
+
+ left.splitDepth = right.splitDepth = splitDepth + 1;
}
FloatPoint start;
FloatPoint control1;
FloatPoint control2;
FloatPoint end;
+ unsigned short splitDepth;
};
-// FIXME: This function is possibly very slow due to the ifs required for proper path measuring
-// A simple speed-up would be to use an additional boolean template parameter to control whether
-// to use the "fast" version of this function with no PathTraversalState updating, vs. the slow
-// version which does update the PathTraversalState. We'll have to shark it to see if that's necessary.
-// Another check which is possible up-front (to send us down the fast path) would be to check if
-// approximateDistance() + current total distance > desired distance
template<class CurveType>
static float curveLength(PathTraversalState& traversalState, CurveType curve)
{
- static const unsigned curveStackDepthLimit = 20;
+ static const unsigned short curveSplitDepthLimit = 20;
+ static const double pathSegmentLengthToleranceSquared = 1.e-16;
+
+ double curveScaleForToleranceSquared = curve.magnitudeSquared();
+ if (curveScaleForToleranceSquared < pathSegmentLengthToleranceSquared)
+ return 0;
Vector<CurveType> curveStack;
curveStack.append(curve);
@@ -124,7 +139,8 @@ static float curveLength(PathTraversalState& traversalState, CurveType curve)
float totalLength = 0;
do {
float length = curve.approximateDistance();
- if ((length - distanceLine(curve.start, curve.end)) > kPathSegmentLengthTolerance && curveStack.size() <= curveStackDepthLimit) {
+ double lengthDiscrepancy = length - distanceLine(curve.start, curve.end);
+ if ((lengthDiscrepancy * lengthDiscrepancy) / curveScaleForToleranceSquared > pathSegmentLengthToleranceSquared && curve.splitDepth < curveSplitDepthLimit) {
CurveType leftCurve;
CurveType rightCurve;
curve.split(leftCurve, rightCurve);
@@ -159,20 +175,20 @@ PathTraversalState::PathTraversalState(PathTraversalAction action)
float PathTraversalState::closeSubpath()
{
float distance = distanceLine(m_current, m_start);
- m_current = m_control1 = m_control2 = m_start;
+ m_current = m_start;
return distance;
}
float PathTraversalState::moveTo(const FloatPoint& point)
{
- m_current = m_start = m_control1 = m_control2 = point;
+ m_current = m_start = point;
return 0;
}
float PathTraversalState::lineTo(const FloatPoint& point)
{
float distance = distanceLine(m_current, point);
- m_current = m_control1 = m_control2 = point;
+ m_current = point;
return distance;
}
@@ -180,9 +196,6 @@ float PathTraversalState::quadraticBezierTo(const FloatPoint& newControl, const
{
float distance = curveLength<QuadraticBezier>(*this, QuadraticBezier(m_current, newControl, newEnd));
- m_control1 = newControl;
- m_control2 = newEnd;
-
if (m_action != TraversalPointAtLength && m_action != TraversalNormalAngleAtLength)
m_current = newEnd;
@@ -193,9 +206,6 @@ float PathTraversalState::cubicBezierTo(const FloatPoint& newControl1, const Flo
{
float distance = curveLength<CubicBezier>(*this, CubicBezier(m_current, newControl1, newControl2, newEnd));
- m_control1 = newEnd;
- m_control2 = newControl2;
-
if (m_action != TraversalPointAtLength && m_action != TraversalNormalAngleAtLength)
m_current = newEnd;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.h b/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.h
index e2ecbe8d15b..f29dedc07c7 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.h
@@ -56,8 +56,6 @@ public:
FloatPoint m_current;
FloatPoint m_start;
- FloatPoint m_control1;
- FloatPoint m_control2;
float m_totalLength;
unsigned m_segmentIndex;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Pattern.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Pattern.cpp
index 6e21b821660..3d7c0acf957 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Pattern.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Pattern.cpp
@@ -57,11 +57,13 @@ SkShader* Pattern::shader()
if (m_pattern)
return m_pattern.get();
+ SkMatrix localMatrix = affineTransformToSkMatrix(m_patternSpaceTransformation);
+
// If we don't have a bitmap, return a transparent shader.
if (!m_tileImage)
m_pattern = adoptRef(new SkColorShader(SK_ColorTRANSPARENT));
else if (m_repeatX && m_repeatY)
- m_pattern = adoptRef(SkShader::CreateBitmapShader(m_tileImage->bitmap(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
+ m_pattern = adoptRef(SkShader::CreateBitmapShader(m_tileImage->bitmap(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix));
else {
// Skia does not have a "draw the tile only once" option. Clamp_TileMode
// repeats the last line of the image after drawing one tile. To avoid
@@ -76,20 +78,24 @@ SkShader* Pattern::shader()
// Create a transparent bitmap 1 pixel wider and/or taller than the
// original, then copy the orignal into it.
// FIXME: Is there a better way to pad (not scale) an image in skia?
+ SkImageInfo info = m_tileImage->bitmap().info();
+ info.fWidth += expandW;
+ info.fHeight += expandH;
+ // we explicitly require non-opaquness, since we are going to add a transparent strip.
+ info.fAlphaType = kPremul_SkAlphaType;
+
SkBitmap bm2;
- bm2.setConfig(m_tileImage->bitmap().config(), m_tileImage->bitmap().width() + expandW, m_tileImage->bitmap().height() + expandH);
- bm2.allocPixels();
+ bm2.allocPixels(info);
bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
SkCanvas canvas(bm2);
canvas.drawBitmap(m_tileImage->bitmap(), 0, 0);
bm2.setImmutable();
- m_pattern = adoptRef(SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY));
+ m_pattern = adoptRef(SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY, &localMatrix));
// Clamp to int, since that's what the adjust function takes.
m_externalMemoryAllocated = static_cast<int>(std::min(static_cast<size_t>(INT_MAX), bm2.getSafeSize()));
v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(m_externalMemoryAllocated);
}
- m_pattern->setLocalMatrix(affineTransformToSkMatrix(m_patternSpaceTransformation));
return m_pattern.get();
}
@@ -97,7 +103,7 @@ void Pattern::setPatternSpaceTransform(const AffineTransform& patternSpaceTransf
{
m_patternSpaceTransformation = patternSpaceTransformation;
if (m_pattern)
- m_pattern->setLocalMatrix(affineTransformToSkMatrix(m_patternSpaceTransformation));
+ m_pattern.clear();
}
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/StrokeData.cpp b/chromium/third_party/WebKit/Source/platform/graphics/StrokeData.cpp
index 75fb7ca6314..61b4f87826d 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/StrokeData.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/StrokeData.cpp
@@ -54,19 +54,23 @@ void StrokeData::setLineDash(const DashArray& dashes, float dashOffset)
for (unsigned i = 0; i < count; i++)
intervals[i] = dashes[i % dashLength];
- m_dash = adoptRef(new SkDashPathEffect(intervals.get(), count, dashOffset));
+ m_dash = adoptRef(SkDashPathEffect::Create(intervals.get(), count, dashOffset));
}
-float StrokeData::setupPaint(SkPaint* paint, int length) const
+void StrokeData::setupPaint(SkPaint* paint, int length) const
{
- float width = m_thickness;
-
paint->setStyle(SkPaint::kStroke_Style);
- paint->setStrokeWidth(SkFloatToScalar(width));
+ paint->setStrokeWidth(SkFloatToScalar(m_thickness));
paint->setStrokeCap(m_lineCap);
paint->setStrokeJoin(m_lineJoin);
paint->setStrokeMiter(SkFloatToScalar(m_miterLimit));
+ setupPaintDashPathEffect(paint, length);
+}
+
+void StrokeData::setupPaintDashPathEffect(SkPaint* paint, int length) const
+{
+ float width = m_thickness;
if (m_dash) {
paint->setPathEffect(m_dash.get());
} else {
@@ -75,7 +79,8 @@ float StrokeData::setupPaint(SkPaint* paint, int length) const
case SolidStroke:
case DoubleStroke:
case WavyStroke: // FIXME: https://code.google.com/p/chromium/issues/detail?id=229574
- break;
+ paint->setPathEffect(0);
+ return;
case DashedStroke:
width = dashRatio * width;
// Fall through.
@@ -100,12 +105,10 @@ float StrokeData::setupPaint(SkPaint* paint, int length) const
}
SkScalar dashLengthSk = SkIntToScalar(dashLength);
SkScalar intervals[2] = { dashLengthSk, dashLengthSk };
- RefPtr<SkDashPathEffect> pathEffect = adoptRef(new SkDashPathEffect(intervals, 2, SkIntToScalar(phase)));
+ RefPtr<SkDashPathEffect> pathEffect = adoptRef(SkDashPathEffect::Create(intervals, 2, SkIntToScalar(phase)));
paint->setPathEffect(pathEffect.get());
}
}
-
- return width;
}
} // namespace
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/StrokeData.h b/chromium/third_party/WebKit/Source/platform/graphics/StrokeData.h
index 177012d5999..2a075a995a3 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/StrokeData.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/StrokeData.h
@@ -56,10 +56,10 @@ public:
}
StrokeStyle style() const { return m_style; }
- void setStyle(const StrokeStyle style) { m_style = style; }
+ void setStyle(StrokeStyle style) { m_style = style; }
float thickness() const { return m_thickness; }
- void setThickness(const float thickness) { m_thickness = thickness; }
+ void setThickness(float thickness) { m_thickness = thickness; }
Color color() const { return m_color; }
void setColor(const Color& color) { m_color = color; }
@@ -73,22 +73,26 @@ public:
void clearPattern() { m_pattern.clear(); }
LineCap lineCap() const { return (LineCap)m_lineCap; }
- void setLineCap(const LineCap cap) { m_lineCap = (SkPaint::Cap)cap; }
+ void setLineCap(LineCap cap) { m_lineCap = (SkPaint::Cap)cap; }
LineJoin lineJoin() const { return (LineJoin)m_lineJoin; }
- void setLineJoin(const LineJoin join) { m_lineJoin = (SkPaint::Join)join; }
+ void setLineJoin(LineJoin join) { m_lineJoin = (SkPaint::Join)join; }
float miterLimit() const { return m_miterLimit; }
- void setMiterLimit(const float miterLimit) { m_miterLimit = miterLimit; }
+ void setMiterLimit(float miterLimit) { m_miterLimit = miterLimit; }
- void setLineDash(const DashArray&, const float);
+ void setLineDash(const DashArray&, float);
// Sets everything on the paint except the pattern, gradient and color.
- // GraphicsContext::setupShader does that. Returns a float representing the
- // effective width of the pen. If a non-zero length is provided, the
- // number of dashes/dots on a dashed/dotted line will be adjusted to
- // start and end that length with a dash/dot.
- float setupPaint(SkPaint*, int length = 0) const;
+ // If a non-zero length is provided, the number of dashes/dots on a
+ // dashed/dotted line will be adjusted to start and end that length with a
+ // dash/dot.
+ void setupPaint(SkPaint*, int length = 0) const;
+
+ // Setup any DashPathEffect on the paint. If a non-zero length is provided,
+ // and no line dash has been set, the number of dashes/dots on a dashed/dotted
+ // line will be adjusted to start and end that length with a dash/dot.
+ void setupPaintDashPathEffect(SkPaint*, int) const;
private:
StrokeStyle m_style;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/ThreadSafeDataTransport.cpp b/chromium/third_party/WebKit/Source/platform/graphics/ThreadSafeDataTransport.cpp
index 8b18648b364..a75eba87cd3 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/ThreadSafeDataTransport.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/ThreadSafeDataTransport.cpp
@@ -33,6 +33,7 @@ namespace WebCore {
ThreadSafeDataTransport::ThreadSafeDataTransport()
: m_readBuffer(SharedBuffer::create())
+ , m_allDataReceived(false)
, m_readPosition(0)
{
}
@@ -53,7 +54,7 @@ void ThreadSafeDataTransport::setData(SharedBuffer* buffer, bool allDataReceived
}
MutexLocker locker(m_mutex);
- m_newBufferQueue.append(newBufferQueue);
+ m_newBufferQueue.appendVector(newBufferQueue);
m_allDataReceived = allDataReceived;
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp b/chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp
index 40812df5e77..50b12726a23 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp
@@ -32,20 +32,16 @@
#include "platform/graphics/UnacceleratedImageBufferSurface.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "wtf/PassOwnPtr.h"
+#include "wtf/PassRefPtr.h"
namespace WebCore {
UnacceleratedImageBufferSurface::UnacceleratedImageBufferSurface(const IntSize& size, OpacityMode opacityMode)
: ImageBufferSurface(size, opacityMode)
+ , m_canvas(adoptRef(SkCanvas::NewRasterN32(size.width(), size.height())))
{
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- bitmap.allocPixels();
- if (bitmap.isNull())
- return;
- m_canvas = adoptPtr(new SkCanvas(bitmap));
- clear();
+ if (m_canvas)
+ clear();
}
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.h b/chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.h
index 5ee66b49f46..407cdcbf311 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.h
@@ -32,7 +32,7 @@
#define UnacceleratedImageBufferSurface_h
#include "platform/graphics/ImageBufferSurface.h"
-#include "wtf/OwnPtr.h"
+#include "wtf/RefPtr.h"
namespace WebCore {
@@ -46,7 +46,7 @@ public:
virtual bool isValid() const OVERRIDE { return m_canvas; }
private:
- OwnPtr<SkCanvas> m_canvas;
+ RefPtr<SkCanvas> m_canvas;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/angle/ANGLEPlatformBridge.cpp b/chromium/third_party/WebKit/Source/platform/graphics/angle/ANGLEPlatformBridge.cpp
deleted file mode 100644
index c683b2ab88a..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/angle/ANGLEPlatformBridge.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2010 Apple 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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"
-
-#include "platform/graphics/angle/ANGLEPlatformBridge.h"
-
-#include "wtf/OwnPtr.h"
-#include "wtf/PassOwnPtr.h"
-
-namespace WebCore {
-
-typedef size_t ANGLEGetInfoType;
-
-inline static ANGLEGetInfoType getValidationResultValue(const ShHandle compiler, ShShaderInfo shaderInfo)
-{
- ANGLEGetInfoType value = 0;
- ShGetInfo(compiler, shaderInfo, &value);
- return value;
-}
-
-static bool getSymbolInfo(ShHandle compiler, ShShaderInfo symbolType, Vector<ANGLEShaderSymbol>& symbols)
-{
- ShShaderInfo symbolMaxNameLengthType;
-
- switch (symbolType) {
- case SH_ACTIVE_ATTRIBUTES:
- symbolMaxNameLengthType = SH_ACTIVE_ATTRIBUTE_MAX_LENGTH;
- break;
- case SH_ACTIVE_UNIFORMS:
- symbolMaxNameLengthType = SH_ACTIVE_UNIFORM_MAX_LENGTH;
- break;
- default:
- ASSERT_NOT_REACHED();
- return false;
- }
-
- ANGLEGetInfoType numSymbols = getValidationResultValue(compiler, symbolType);
-
- ANGLEGetInfoType maxNameLength = getValidationResultValue(compiler, symbolMaxNameLengthType);
- if (maxNameLength <= 1)
- return false;
-
- ANGLEGetInfoType maxMappedNameLength = getValidationResultValue(compiler, SH_MAPPED_NAME_MAX_LENGTH);
- if (maxMappedNameLength <= 1)
- return false;
-
- // The maximum allowed symbol name length is 256 characters.
- Vector<char, 256> nameBuffer(maxNameLength);
- Vector<char, 256> mappedNameBuffer(maxMappedNameLength);
-
- for (ANGLEGetInfoType i = 0; i < numSymbols; ++i) {
- ANGLEShaderSymbol symbol;
- ANGLEGetInfoType nameLength = 0;
- switch (symbolType) {
- case SH_ACTIVE_ATTRIBUTES:
- symbol.symbolType = SHADER_SYMBOL_TYPE_ATTRIBUTE;
-#if ANGLE_SH_VERSION >= 112
- ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &symbol.precision, &symbol.staticUse, nameBuffer.data(), mappedNameBuffer.data());
-#else
- ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &symbol.precision, nameBuffer.data(), mappedNameBuffer.data());
-#endif
- break;
- case SH_ACTIVE_UNIFORMS:
- symbol.symbolType = SHADER_SYMBOL_TYPE_UNIFORM;
-#if ANGLE_SH_VERSION >= 112
- ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &symbol.precision, &symbol.staticUse, nameBuffer.data(), mappedNameBuffer.data());
-#else
- ShGetVariableInfo(compiler, symbolType, i, &nameLength, &symbol.size, &symbol.dataType, &symbol.precision, nameBuffer.data(), mappedNameBuffer.data());
-#endif
- break;
- default:
- ASSERT_NOT_REACHED();
- return false;
- }
- if (!nameLength)
- return false;
-
- // The ShGetActive* calls above are guaranteed to produce null-terminated strings for
- // nameBuffer and mappedNameBuffer. Also, the character set for symbol names
- // is a subset of Latin-1 as specified by the OpenGL ES Shading Language, Section 3.1 and
- // WebGL, Section "Characters Outside the GLSL Source Character Set".
-
- String name = String(nameBuffer.data());
- String mappedName = String(mappedNameBuffer.data());
-
- // ANGLE returns array names in the format "array[0]".
- // The only way to know if a symbol is an array is to check if it ends with "[0]".
- // We can't check the size because regular symbols and arrays of length 1 both have a size of 1.
- symbol.isArray = name.endsWith("[0]") && mappedName.endsWith("[0]");
- if (symbol.isArray) {
- // Add a symbol for the array name without the "[0]" suffix.
- name.truncate(name.length() - 3);
- mappedName.truncate(mappedName.length() - 3);
- }
-
- symbol.name = name;
- symbol.mappedName = mappedName;
- symbols.append(symbol);
-
- if (symbol.isArray) {
- // Add symbols for each array element.
- symbol.isArray = false;
- for (int i = 0; i < symbol.size; i++) {
- String arrayBrackets = "[" + String::number(i) + "]";
- symbol.name = name + arrayBrackets;
- symbol.mappedName = mappedName + arrayBrackets;
- symbols.append(symbol);
- }
- }
- }
- return true;
-}
-
-ANGLEPlatformBridge::ANGLEPlatformBridge(ShShaderOutput shaderOutput, ShShaderSpec shaderSpec)
- : builtCompilers(false)
- , m_fragmentCompiler(0)
- , m_vertexCompiler(0)
- , m_shaderOutput(shaderOutput)
- , m_shaderSpec(shaderSpec)
-{
- // This is a no-op if it's already initialized.
- ShInitialize();
-}
-
-ANGLEPlatformBridge::~ANGLEPlatformBridge()
-{
- cleanupCompilers();
-}
-
-void ANGLEPlatformBridge::cleanupCompilers()
-{
- if (m_fragmentCompiler)
- ShDestruct(m_fragmentCompiler);
- m_fragmentCompiler = 0;
- if (m_vertexCompiler)
- ShDestruct(m_vertexCompiler);
- m_vertexCompiler = 0;
-
- builtCompilers = false;
-}
-
-void ANGLEPlatformBridge::setResources(ShBuiltInResources resources)
-{
- // Resources are (possibly) changing - cleanup compilers if we had them already
- cleanupCompilers();
-
- m_resources = resources;
-}
-
-bool ANGLEPlatformBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions)
-{
- if (!builtCompilers) {
- m_fragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
- m_vertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
- if (!m_fragmentCompiler || !m_vertexCompiler) {
- cleanupCompilers();
- return false;
- }
-
- builtCompilers = true;
- }
-
- ShHandle compiler;
-
- if (shaderType == SHADER_TYPE_VERTEX)
- compiler = m_vertexCompiler;
- else
- compiler = m_fragmentCompiler;
-
- const char* const shaderSourceStrings[] = { shaderSource };
-
-#if ANGLE_SH_VERSION >= 111
- bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_VARIABLES | extraCompileOptions);
-#else
- bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | extraCompileOptions);
-#endif
- if (!validateSuccess) {
- int logSize = getValidationResultValue(compiler, SH_INFO_LOG_LENGTH);
- if (logSize > 1) {
- OwnPtr<char[]> logBuffer = adoptArrayPtr(new char[logSize]);
- if (logBuffer) {
- ShGetInfoLog(compiler, logBuffer.get());
- shaderValidationLog = logBuffer.get();
- }
- }
- return false;
- }
-
- int translationLength = getValidationResultValue(compiler, SH_OBJECT_CODE_LENGTH);
- if (translationLength > 1) {
- OwnPtr<char[]> translationBuffer = adoptArrayPtr(new char[translationLength]);
- if (!translationBuffer)
- return false;
- ShGetObjectCode(compiler, translationBuffer.get());
- translatedShaderSource = translationBuffer.get();
- }
-
- if (!getSymbolInfo(compiler, SH_ACTIVE_ATTRIBUTES, symbols))
- return false;
- if (!getSymbolInfo(compiler, SH_ACTIVE_UNIFORMS, symbols))
- return false;
-
- return true;
-}
-
-}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/angle/ANGLEPlatformBridge.h b/chromium/third_party/WebKit/Source/platform/graphics/angle/ANGLEPlatformBridge.h
deleted file mode 100644
index 614f241b126..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/angle/ANGLEPlatformBridge.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2010 Apple 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 ANGLEPlatformBridge_h
-#define ANGLEPlatformBridge_h
-
-#include "platform/PlatformExport.h"
-#include "wtf/text/CString.h"
-#include "wtf/text/WTFString.h"
-#include <GLSLANG/ShaderLang.h>
-
-namespace WebCore {
-
-enum ANGLEShaderType {
- SHADER_TYPE_VERTEX = SH_VERTEX_SHADER,
- SHADER_TYPE_FRAGMENT = SH_FRAGMENT_SHADER,
-};
-
-enum ANGLEShaderSymbolType {
- SHADER_SYMBOL_TYPE_ATTRIBUTE,
- SHADER_SYMBOL_TYPE_UNIFORM
-};
-
-struct PLATFORM_EXPORT ANGLEShaderSymbol {
- ANGLEShaderSymbolType symbolType;
- String name;
- String mappedName;
- ShDataType dataType;
- int size;
- bool isArray;
- ShPrecisionType precision;
-#if ANGLE_SH_VERSION >= 112
- int staticUse;
-#endif
-
- bool isSampler() const
- {
- return symbolType == SHADER_SYMBOL_TYPE_UNIFORM
- && (dataType == SH_SAMPLER_2D
- || dataType == SH_SAMPLER_CUBE
- || dataType == SH_SAMPLER_2D_RECT_ARB
- || dataType == SH_SAMPLER_EXTERNAL_OES);
- }
-};
-
-class PLATFORM_EXPORT ANGLEPlatformBridge {
-public:
-
- ANGLEPlatformBridge(ShShaderOutput = SH_GLSL_OUTPUT, ShShaderSpec = SH_WEBGL_SPEC);
- ~ANGLEPlatformBridge();
-
- ShBuiltInResources getResources() { return m_resources; }
- void setResources(ShBuiltInResources);
-
- bool compileShaderSource(const char* shaderSource, ANGLEShaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions = 0);
-
-private:
-
- void cleanupCompilers();
-
- bool builtCompilers;
-
- ShHandle m_fragmentCompiler;
- ShHandle m_vertexCompiler;
-
- ShShaderOutput m_shaderOutput;
- ShShaderSpec m_shaderSpec;
-
- ShBuiltInResources m_resources;
-};
-
-} // namespace WebCore
-
-#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/cg/GraphicsContextCG.h b/chromium/third_party/WebKit/Source/platform/graphics/cg/GraphicsContextCG.h
deleted file mode 100644
index c2c1a5f52b7..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/cg/GraphicsContextCG.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2010 Apple 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 GraphicsContextCG_h
-#define GraphicsContextCG_h
-
-#include "platform/graphics/GraphicsContext.h"
-
-typedef struct CGColorSpace *CGColorSpaceRef;
-
-namespace WebCore {
-
-CGColorSpaceRef PLATFORM_EXPORT deviceRGBColorSpaceRef();
-CGColorSpaceRef PLATFORM_EXPORT sRGBColorSpaceRef();
-CGColorSpaceRef PLATFORM_EXPORT linearRGBColorSpaceRef();
-
-}
-
-#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/GraphicsContext3DNEON.h b/chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/WebGLImageConversionNEON.h
index c043fedd4a9..1729ecca737 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/GraphicsContext3DNEON.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/WebGLImageConversionNEON.h
@@ -23,8 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef GraphicsContext3DNEON_h
-#define GraphicsContext3DNEON_h
+#ifndef WebGLImageConversionNEON_h
+#define WebGLImageConversionNEON_h
#if HAVE(ARM_NEON_INTRINSICS)
@@ -301,4 +301,4 @@ ALWAYS_INLINE void packOneRowOfRGBA8ToUnsignedShort565(const uint8_t*& source, u
#endif // HAVE(ARM_NEON_INTRINSICS)
-#endif // GraphicsContext3DNEON_h
+#endif // WebGLImageConversionNEON_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/filters/FELightingNEON.h b/chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/filters/FELightingNEON.h
deleted file mode 100644
index 69939a582a4..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/cpu/arm/filters/FELightingNEON.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2011 University of Szeged
- * Copyright (C) 2011 Zoltan Herczeg
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 FELightingNEON_h
-#define FELightingNEON_h
-
-#if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC)
-
-#include "platform/graphics/filters/FELighting.h"
-#include "wtf/Alignment.h"
-#include "wtf/CPU.h"
-#include "wtf/ParallelJobs.h"
-
-namespace WebCore {
-
-// Otherwise: Distant Light.
-#define FLAG_POINT_LIGHT 0x01
-#define FLAG_SPOT_LIGHT 0x02
-#define FLAG_CONE_EXPONENT_IS_1 0x04
-
-// Otherwise: Diffuse light.
-#define FLAG_SPECULAR_LIGHT 0x10
-#define FLAG_DIFFUSE_CONST_IS_1 0x20
-#define FLAG_SPECULAR_EXPONENT_IS_1 0x40
-
-// Must be aligned to 16 bytes.
-struct FELightingFloatArgumentsForNeon {
- float surfaceScale;
- float minusSurfaceScaleDividedByFour;
- float diffuseConstant;
- float padding1;
-
- float coneCutOffLimit;
- float coneFullLight;
- float coneCutOffRange;
- float constOne;
-
- float lightX;
- float lightY;
- float lightZ;
- float padding2;
-
- float directionX;
- float directionY;
- float directionZ;
- float padding3;
-
- float colorRed;
- float colorGreen;
- float colorBlue;
- float padding4;
-};
-
-struct FELightingPaintingDataForNeon {
- unsigned char* pixels;
- float yStart;
- int widthDecreasedByTwo;
- int absoluteHeight;
- // Combination of FLAG constants above.
- int flags;
- int specularExponent;
- int coneExponent;
- FELightingFloatArgumentsForNeon* floatArguments;
- short* paintingConstants;
-};
-
-short* feLightingConstantsForNeon();
-
-extern "C" {
-void neonDrawLighting(FELightingPaintingDataForNeon*);
-}
-
-inline void FELighting::platformApplyNeon(LightingData& data, LightSource::PaintingData& paintingData)
-{
- WTF_ALIGNED(FELightingFloatArgumentsForNeon, floatArguments, 16);
-
- FELightingPaintingDataForNeon neonData = {
- data.pixels->data(),
- 1,
- data.widthDecreasedByOne - 1,
- data.heightDecreasedByOne - 1,
- 0,
- 0,
- 0,
- &floatArguments,
- feLightingConstantsForNeon()
- };
-
- // Set light source arguments.
- floatArguments.constOne = 1;
-
- floatArguments.colorRed = m_lightingColor.red();
- floatArguments.colorGreen = m_lightingColor.green();
- floatArguments.colorBlue = m_lightingColor.blue();
- floatArguments.padding4 = 0;
-
- if (m_lightSource->type() == LS_POINT) {
- neonData.flags |= FLAG_POINT_LIGHT;
- PointLightSource* pointLightSource = static_cast<PointLightSource*>(m_lightSource.get());
- floatArguments.lightX = pointLightSource->position().x();
- floatArguments.lightY = pointLightSource->position().y();
- floatArguments.lightZ = pointLightSource->position().z();
- floatArguments.padding2 = 0;
- } else if (m_lightSource->type() == LS_SPOT) {
- neonData.flags |= FLAG_SPOT_LIGHT;
- SpotLightSource* spotLightSource = static_cast<SpotLightSource*>(m_lightSource.get());
- floatArguments.lightX = spotLightSource->position().x();
- floatArguments.lightY = spotLightSource->position().y();
- floatArguments.lightZ = spotLightSource->position().z();
- floatArguments.padding2 = 0;
-
- floatArguments.directionX = paintingData.directionVector.x();
- floatArguments.directionY = paintingData.directionVector.y();
- floatArguments.directionZ = paintingData.directionVector.z();
- floatArguments.padding3 = 0;
-
- floatArguments.coneCutOffLimit = paintingData.coneCutOffLimit;
- floatArguments.coneFullLight = paintingData.coneFullLight;
- floatArguments.coneCutOffRange = paintingData.coneCutOffLimit - paintingData.coneFullLight;
- neonData.coneExponent = getPowerCoefficients(spotLightSource->specularExponent());
- if (spotLightSource->specularExponent() == 1)
- neonData.flags |= FLAG_CONE_EXPONENT_IS_1;
- } else {
- ASSERT(m_lightSource->type() == LS_DISTANT);
- floatArguments.lightX = paintingData.lightVector.x();
- floatArguments.lightY = paintingData.lightVector.y();
- floatArguments.lightZ = paintingData.lightVector.z();
- floatArguments.padding2 = 1;
- }
-
- // Set lighting arguments.
- floatArguments.surfaceScale = data.surfaceScale;
- floatArguments.minusSurfaceScaleDividedByFour = -data.surfaceScale / 4;
- if (m_lightingType == FELighting::DiffuseLighting) {
- floatArguments.diffuseConstant = m_diffuseConstant;
- } else {
- neonData.flags |= FLAG_SPECULAR_LIGHT;
- floatArguments.diffuseConstant = m_specularConstant;
- neonData.specularExponent = getPowerCoefficients(m_specularExponent);
- if (m_specularExponent == 1)
- neonData.flags |= FLAG_SPECULAR_EXPONENT_IS_1;
- }
- if (floatArguments.diffuseConstant == 1)
- neonData.flags |= FLAG_DIFFUSE_CONST_IS_1;
-
- int optimalThreadNumber = ((data.widthDecreasedByOne - 1) * (data.heightDecreasedByOne - 1)) / s_minimalRectDimension;
- if (optimalThreadNumber > 1) {
- // Initialize parallel jobs
- ParallelJobs<FELightingPaintingDataForNeon> parallelJobs(&WebCore::FELighting::platformApplyNeonWorker, optimalThreadNumber);
-
- // Fill the parameter array
- int job = parallelJobs.numberOfJobs();
- if (job > 1) {
- int yStart = 1;
- int yStep = (data.heightDecreasedByOne - 1) / job;
- for (--job; job >= 0; --job) {
- FELightingPaintingDataForNeon& params = parallelJobs.parameter(job);
- params = neonData;
- params.yStart = yStart;
- params.pixels += (yStart - 1) * (data.widthDecreasedByOne + 1) * 4;
- if (job > 0) {
- params.absoluteHeight = yStep;
- yStart += yStep;
- } else {
- params.absoluteHeight = data.heightDecreasedByOne - yStart;
- }
- }
- parallelJobs.execute();
- return;
- }
- }
-
- neonDrawLighting(&neonData);
-}
-
-} // namespace WebCore
-
-#endif // CPU(ARM_NEON) && COMPILER(GCC)
-
-#endif // FELightingNEON_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.cpp
index 6da197cbb89..b44c393ab9b 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.cpp
@@ -35,7 +35,7 @@
namespace WebCore {
-void DistantLightSource::initPaintingData(PaintingData& paintingData)
+void DistantLightSource::initPaintingData(PaintingData& paintingData) const
{
float azimuth = deg2rad(m_azimuth);
float elevation = deg2rad(m_elevation);
@@ -45,7 +45,7 @@ void DistantLightSource::initPaintingData(PaintingData& paintingData)
paintingData.lightVectorLength = 1;
}
-void DistantLightSource::updatePaintingData(PaintingData&, int, int, float)
+void DistantLightSource::updatePaintingData(PaintingData&, int, int, float) const
{
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.h
index b64b94da7fb..65814e0504e 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/DistantLightSource.h
@@ -34,16 +34,21 @@ public:
return adoptRef(new DistantLightSource(azimuth, elevation));
}
+ virtual PassRefPtr<LightSource> create(const FloatPoint3D& scale, const FloatSize& offset) const OVERRIDE
+ {
+ return adoptRef(new DistantLightSource(m_azimuth, m_elevation));
+ }
+
float azimuth() const { return m_azimuth; }
float elevation() const { return m_elevation; }
virtual bool setAzimuth(float) OVERRIDE;
virtual bool setElevation(float) OVERRIDE;
- virtual void initPaintingData(PaintingData&);
- virtual void updatePaintingData(PaintingData&, int x, int y, float z);
+ virtual void initPaintingData(PaintingData&) const OVERRIDE;
+ virtual void updatePaintingData(PaintingData&, int x, int y, float z) const OVERRIDE;
- virtual TextStream& externalRepresentation(TextStream&) const;
+ virtual TextStream& externalRepresentation(TextStream&) const OVERRIDE;
private:
DistantLightSource(float azimuth, float elevation)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.cpp
index 88aff9f783e..fbf94c35ebc 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.cpp
@@ -201,50 +201,13 @@ static SkXfermode::Mode toSkiaMode(BlendModeType mode)
}
}
-bool FEBlend::applySkia()
-{
- // For now, only use the skia implementation for accelerated rendering.
- if (!filter()->isAccelerated())
- return false;
-
- FilterEffect* in = inputEffect(0);
- FilterEffect* in2 = inputEffect(1);
-
- if (!in || !in2)
- return false;
-
- ImageBuffer* resultImage = createImageBufferResult();
- if (!resultImage)
- return false;
-
- RefPtr<Image> foreground = in->asImageBuffer()->copyImage(DontCopyBackingStore);
- RefPtr<Image> background = in2->asImageBuffer()->copyImage(DontCopyBackingStore);
-
- RefPtr<NativeImageSkia> foregroundNativeImage = foreground->nativeImageForCurrentFrame();
- RefPtr<NativeImageSkia> backgroundNativeImage = background->nativeImageForCurrentFrame();
-
- if (!foregroundNativeImage || !backgroundNativeImage)
- return false;
-
- SkBitmap foregroundBitmap = foregroundNativeImage->bitmap();
- SkBitmap backgroundBitmap = backgroundNativeImage->bitmap();
-
- SkAutoTUnref<SkImageFilter> backgroundSource(new SkBitmapSource(backgroundBitmap));
- SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(toSkiaMode(m_mode)));
- SkAutoTUnref<SkImageFilter> blend(new SkXfermodeImageFilter(mode, backgroundSource));
- SkPaint paint;
- paint.setImageFilter(blend);
- resultImage->context()->drawBitmap(foregroundBitmap, 0, 0, &paint);
- return true;
-}
-
PassRefPtr<SkImageFilter> FEBlend::createImageFilter(SkiaImageFilterBuilder* builder)
{
RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingColorSpace()));
RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingColorSpace()));
SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(toSkiaMode(m_mode)));
SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
- return adoptRef(new SkXfermodeImageFilter(mode, background.get(), foreground.get(), &cropRect));
+ return adoptRef(SkXfermodeImageFilter::Create(mode, background.get(), foreground.get(), &cropRect));
}
static TextStream& operator<<(TextStream& ts, const BlendModeType& type)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.h
index 628c3ee408f..08e850e069c 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEBlend.h
@@ -50,13 +50,12 @@ public:
unsigned colorArrayLength);
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
FEBlend(Filter*, BlendModeType);
virtual void applySoftware() OVERRIDE;
- virtual bool applySkia() OVERRIDE;
BlendModeType m_mode;
};
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.cpp
index e56df350beb..b87769dd4eb 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.cpp
@@ -73,109 +73,6 @@ bool FEColorMatrix::setValues(const Vector<float> &values)
return true;
}
-inline void matrix(float& red, float& green, float& blue, float& alpha, const Vector<float>& values)
-{
- float r = values[0] * red + values[1] * green + values[2] * blue + values[3] * alpha + values[4] * 255;
- float g = values[5] * red + values[6] * green + values[7] * blue + values[8] * alpha + values[9] * 255;
- float b = values[10] * red + values[11] * green + values[12] * blue + values[13] * alpha + values[14] * 255;
- float a = values[15] * red + values[16] * green + values[17] * blue + values[18] * alpha + values[19] * 255;
-
- red = r;
- green = g;
- blue = b;
- alpha = a;
-}
-
-inline void saturateAndHueRotate(float& red, float& green, float& blue, const float* components)
-{
- float r = red * components[0] + green * components[1] + blue * components[2];
- float g = red * components[3] + green * components[4] + blue * components[5];
- float b = red * components[6] + green * components[7] + blue * components[8];
-
- red = r;
- green = g;
- blue = b;
-}
-
-inline void luminance(float& red, float& green, float& blue, float& alpha)
-{
- alpha = 0.2125 * red + 0.7154 * green + 0.0721 * blue;
- red = 0;
- green = 0;
- blue = 0;
-}
-
-template<ColorMatrixType filterType>
-void effectType(Uint8ClampedArray* pixelArray, const Vector<float>& values)
-{
- unsigned pixelArrayLength = pixelArray->length();
- float components[9];
-
- if (filterType == FECOLORMATRIX_TYPE_SATURATE)
- FEColorMatrix::calculateSaturateComponents(components, values[0]);
- else if (filterType == FECOLORMATRIX_TYPE_HUEROTATE)
- FEColorMatrix::calculateHueRotateComponents(components, values[0]);
-
- for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelArrayLength; pixelByteOffset += 4) {
- float red = pixelArray->item(pixelByteOffset);
- float green = pixelArray->item(pixelByteOffset + 1);
- float blue = pixelArray->item(pixelByteOffset + 2);
- float alpha = pixelArray->item(pixelByteOffset + 3);
-
- switch (filterType) {
- case FECOLORMATRIX_TYPE_MATRIX:
- matrix(red, green, blue, alpha, values);
- break;
- case FECOLORMATRIX_TYPE_SATURATE:
- case FECOLORMATRIX_TYPE_HUEROTATE:
- saturateAndHueRotate(red, green, blue, components);
- break;
- case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
- luminance(red, green, blue, alpha);
- break;
- }
-
- pixelArray->set(pixelByteOffset, red);
- pixelArray->set(pixelByteOffset + 1, green);
- pixelArray->set(pixelByteOffset + 2, blue);
- pixelArray->set(pixelByteOffset + 3, alpha);
- }
-}
-
-void FEColorMatrix::applySoftware()
-{
- FilterEffect* in = inputEffect(0);
-
- ImageBuffer* resultImage = createImageBufferResult();
- if (!resultImage)
- return;
-
- resultImage->context()->drawImageBuffer(in->asImageBuffer(), drawingRegionOfInputImage(in->absolutePaintRect()));
-
- IntRect imageRect(IntPoint(), absolutePaintRect().size());
- RefPtr<Uint8ClampedArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect);
-
- switch (m_type) {
- case FECOLORMATRIX_TYPE_UNKNOWN:
- break;
- case FECOLORMATRIX_TYPE_MATRIX:
- effectType<FECOLORMATRIX_TYPE_MATRIX>(pixelArray.get(), m_values);
- break;
- case FECOLORMATRIX_TYPE_SATURATE:
- effectType<FECOLORMATRIX_TYPE_SATURATE>(pixelArray.get(), m_values);
- break;
- case FECOLORMATRIX_TYPE_HUEROTATE:
- effectType<FECOLORMATRIX_TYPE_HUEROTATE>(pixelArray.get(), m_values);
- break;
- case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
- effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(pixelArray.get(), m_values);
- setIsAlphaImage(true);
- break;
- }
-
- resultImage->putByteArray(Unmultiplied, pixelArray.get(), imageRect.size(), imageRect, IntPoint());
-}
-
static void saturateMatrix(float s, SkScalar matrix[20])
{
matrix[0] = 0.213f + 0.787f * s;
@@ -249,31 +146,44 @@ static SkColorFilter* createColorFilter(ColorMatrixType type, const float* value
luminanceToAlphaMatrix(matrix);
break;
}
- return new SkColorMatrixFilter(matrix);
+ return SkColorMatrixFilter::Create(matrix);
}
-bool FEColorMatrix::applySkia()
+void FEColorMatrix::applySoftware()
{
ImageBuffer* resultImage = createImageBufferResult();
if (!resultImage)
- return false;
+ return;
FilterEffect* in = inputEffect(0);
- SkRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
+ IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
SkAutoTUnref<SkColorFilter> filter(createColorFilter(m_type, m_values.data()));
RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame();
if (!nativeImage)
- return false;
+ return;
SkPaint paint;
paint.setColorFilter(filter);
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- resultImage->context()->drawBitmap(nativeImage->bitmap(), drawingRegion.fLeft, drawingRegion.fTop, &paint);
- return true;
+ resultImage->context()->drawBitmap(nativeImage->bitmap(), drawingRegion.x(), drawingRegion.y(), &paint);
+
+ if (affectsTransparentPixels()) {
+ IntRect fullRect = IntRect(IntPoint(), absolutePaintRect().size());
+ resultImage->context()->clipOut(drawingRegion);
+ resultImage->context()->fillRect(fullRect, Color(m_values[4], m_values[9], m_values[14], m_values[19]));
+ }
+ return;
+}
+
+bool FEColorMatrix::affectsTransparentPixels()
+{
+ // Because the input pixels are premultiplied, the only way clear pixels can be
+ // painted is if the additive component for the alpha is not 0.
+ return m_type == FECOLORMATRIX_TYPE_MATRIX && m_values[19] > 0;
}
PassRefPtr<SkImageFilter> FEColorMatrix::createImageFilter(SkiaImageFilterBuilder* builder)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.h
index cd7cf1b5d06..4612161960d 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEColorMatrix.h
@@ -49,7 +49,7 @@ public:
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
static inline void calculateSaturateComponents(float* components, float value);
static inline void calculateHueRotateComponents(float* components, float value);
@@ -58,41 +58,13 @@ private:
FEColorMatrix(Filter*, ColorMatrixType, const Vector<float>&);
virtual void applySoftware() OVERRIDE;
- virtual bool applySkia() OVERRIDE;
+
+ virtual bool affectsTransparentPixels() OVERRIDE;
ColorMatrixType m_type;
Vector<float> m_values;
};
-inline void FEColorMatrix::calculateSaturateComponents(float* components, float value)
-{
- components[0] = (0.213 + 0.787 * value);
- components[1] = (0.715 - 0.715 * value);
- components[2] = (0.072 - 0.072 * value);
- components[3] = (0.213 - 0.213 * value);
- components[4] = (0.715 + 0.285 * value);
- components[5] = (0.072 - 0.072 * value);
- components[6] = (0.213 - 0.213 * value);
- components[7] = (0.715 - 0.715 * value);
- components[8] = (0.072 + 0.928 * value);
-}
-
-inline void FEColorMatrix::calculateHueRotateComponents(float* components, float value)
-{
- float cosHue = cos(value * piFloat / 180);
- float sinHue = sin(value * piFloat / 180);
- components[0] = 0.213 + cosHue * 0.787 - sinHue * 0.213;
- components[1] = 0.715 - cosHue * 0.715 - sinHue * 0.715;
- components[2] = 0.072 - cosHue * 0.072 + sinHue * 0.928;
- components[3] = 0.213 - cosHue * 0.213 + sinHue * 0.143;
- components[4] = 0.715 + cosHue * 0.285 + sinHue * 0.140;
- components[5] = 0.072 - cosHue * 0.072 - sinHue * 0.283;
- components[6] = 0.213 - cosHue * 0.213 - sinHue * 0.787;
- components[7] = 0.715 - cosHue * 0.715 + sinHue * 0.715;
- components[8] = 0.072 + cosHue * 0.928 + sinHue * 0.072;
-}
-
-
} // namespace WebCore
#endif // FEColorMatrix_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.cpp
index c5545830712..2ef679ccc9c 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.cpp
@@ -153,48 +153,51 @@ static void gamma(unsigned char* values, const ComponentTransferFunction& transf
void FEComponentTransfer::applySoftware()
{
FilterEffect* in = inputEffect(0);
-
- Uint8ClampedArray* pixelArray = createUnmultipliedImageResult();
- if (!pixelArray)
- return;
-
- unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
- getValues(rValues, gValues, bValues, aValues);
- unsigned char* tables[] = { rValues, gValues, bValues, aValues };
-
- IntRect drawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- in->copyUnmultipliedImage(pixelArray, drawingRect);
-
- unsigned pixelArrayLength = pixelArray->length();
- for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
- for (unsigned channel = 0; channel < 4; ++channel) {
- unsigned char c = pixelArray->item(pixelOffset + channel);
- pixelArray->set(pixelOffset + channel, tables[channel][c]);
- }
- }
-}
-
-bool FEComponentTransfer::applySkia()
-{
- FilterEffect* in = inputEffect(0);
ImageBuffer* resultImage = createImageBufferResult();
if (!resultImage)
- return false;
+ return;
RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame();
if (!nativeImage)
- return false;
+ return;
unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
getValues(rValues, gValues, bValues, aValues);
+ IntRect destRect = drawingRegionOfInputImage(in->absolutePaintRect());
SkPaint paint;
paint.setColorFilter(SkTableColorFilter::CreateARGB(aValues, rValues, gValues, bValues))->unref();
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- resultImage->context()->drawBitmap(nativeImage->bitmap(), 0, 0, &paint);
+ resultImage->context()->drawBitmap(nativeImage->bitmap(), destRect.x(), destRect.y(), &paint);
- return true;
+ if (affectsTransparentPixels()) {
+ IntRect fullRect = IntRect(IntPoint(), absolutePaintRect().size());
+ resultImage->context()->clipOut(destRect);
+ resultImage->context()->fillRect(fullRect, Color(rValues[0], gValues[0], bValues[0], aValues[0]));
+ }
+}
+
+bool FEComponentTransfer::affectsTransparentPixels()
+{
+ double intercept = 0;
+ switch (m_alphaFunc.type) {
+ case FECOMPONENTTRANSFER_TYPE_UNKNOWN:
+ case FECOMPONENTTRANSFER_TYPE_IDENTITY:
+ break;
+ case FECOMPONENTTRANSFER_TYPE_TABLE:
+ case FECOMPONENTTRANSFER_TYPE_DISCRETE:
+ if (m_alphaFunc.tableValues.size() > 0)
+ intercept = m_alphaFunc.tableValues[0];
+ break;
+ case FECOMPONENTTRANSFER_TYPE_LINEAR:
+ intercept = m_alphaFunc.intercept;
+ break;
+ case FECOMPONENTTRANSFER_TYPE_GAMMA:
+ intercept = m_alphaFunc.offset;
+ break;
+ }
+ return 255 * intercept >= 1;
}
PassRefPtr<SkImageFilter> FEComponentTransfer::createImageFilter(SkiaImageFilterBuilder* builder)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.h
index d71e82f02ff..f65cdaca699 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComponentTransfer.h
@@ -79,14 +79,15 @@ public:
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
FEComponentTransfer(Filter*, const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc,
const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc);
virtual void applySoftware() OVERRIDE;
- virtual bool applySkia() OVERRIDE;
+
+ virtual bool affectsTransparentPixels() OVERRIDE;
void getValues(unsigned char rValues[256], unsigned char gValues[256], unsigned char bValues[256], unsigned char aValues[256]);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.cpp
index 2348d80b2bd..a284840343d 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.cpp
@@ -232,25 +232,61 @@ inline void FEComposite::platformArithmeticSoftware(Uint8ClampedArray* source, U
#endif
}
-void FEComposite::determineAbsolutePaintRect()
+FloatRect FEComposite::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
{
+ FloatRect requestedRect = originalRequestedRect;
+ if (clipsToBounds())
+ requestedRect.intersect(maxEffectRect());
+
+ // We may be called multiple times if result is used more than once. Return
+ // quickly if nothing new is required.
+ if (absolutePaintRect().contains(enclosingIntRect(requestedRect)))
+ return requestedRect;
+
+ // No mapPaintRect required for FEComposite.
+ FloatRect input1Rect = inputEffect(1)->determineAbsolutePaintRect(requestedRect);
+ FloatRect affectedRect;
switch (m_type) {
case FECOMPOSITE_OPERATOR_IN:
+ // 'in' has output only in the intersection of both inputs.
+ affectedRect = intersection(input1Rect, inputEffect(0)->determineAbsolutePaintRect(input1Rect));
+ break;
case FECOMPOSITE_OPERATOR_ATOP:
- // For In and Atop the first effect just influences the result of
- // the second effect. So just use the absolute paint rect of the second effect here.
- setAbsolutePaintRect(inputEffect(1)->absolutePaintRect());
- return;
+ // 'atop' has output only in the extents of the second input.
+ // Make sure first input knows where it needs to produce output.
+ inputEffect(0)->determineAbsolutePaintRect(input1Rect);
+ affectedRect = input1Rect;
+ break;
case FECOMPOSITE_OPERATOR_ARITHMETIC:
- // Arithmetic may influnce the compele filter primitive region. So we can't
- // optimize the paint region here.
- setAbsolutePaintRect(enclosingIntRect(maxEffectRect()));
- return;
+ if (k4() > 0) {
+ // Make sure first input knows where it needs to produce output.
+ inputEffect(0)->determineAbsolutePaintRect(requestedRect);
+ // Arithmetic with non-zero k4 may influnce the complete filter primitive
+ // region. So we can't optimize the paint region here.
+ affectedRect = requestedRect;
+ break;
+ }
+ if (k2() <= 0) {
+ // Input 0 does not appear where input 1 is not present.
+ FloatRect input0Rect = inputEffect(0)->determineAbsolutePaintRect(input1Rect);
+ if (k3() > 0) {
+ affectedRect = input1Rect;
+ } else {
+ // Just k1 is positive. Use intersection.
+ affectedRect = intersection(input1Rect, input0Rect);
+ }
+ break;
+ }
+ // else fall through to use union
default:
// Take the union of both input effects.
- FilterEffect::determineAbsolutePaintRect();
- return;
+ affectedRect = unionRect(input1Rect, inputEffect(0)->determineAbsolutePaintRect(requestedRect));
+ break;
}
+
+ affectedRect.intersect(requestedRect);
+ addAbsolutePaintRect(affectedRect);
+ return affectedRect;
}
void FEComposite::applySoftware()
@@ -296,25 +332,27 @@ void FEComposite::applySoftware()
if (destinationRect.isEmpty())
break;
IntPoint destinationPoint(destinationRect.x() - absolutePaintRect().x(), destinationRect.y() - absolutePaintRect().y());
- IntRect sourceRect(IntPoint(destinationRect.x() - in->absolutePaintRect().x(),
+ FloatRect sourceRect(IntPoint(destinationRect.x() - in->absolutePaintRect().x(),
destinationRect.y() - in->absolutePaintRect().y()), destinationRect.size());
- IntRect source2Rect(IntPoint(destinationRect.x() - in2->absolutePaintRect().x(),
+ FloatRect source2Rect(IntPoint(destinationRect.x() - in2->absolutePaintRect().x(),
destinationRect.y() - in2->absolutePaintRect().y()), destinationRect.size());
- filterContext->drawImageBuffer(imageBuffer2, destinationPoint, source2Rect);
- filterContext->drawImageBuffer(imageBuffer, destinationPoint, sourceRect, CompositeSourceIn);
+ filterContext->drawImageBuffer(imageBuffer2,
+ FloatRect(destinationPoint, imageBuffer2->size()), &source2Rect);
+ filterContext->drawImageBuffer(imageBuffer,
+ FloatRect(destinationPoint, imageBuffer->size()), &sourceRect, CompositeSourceIn);
break;
}
case FECOMPOSITE_OPERATOR_OUT:
filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()));
- filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()), IntRect(IntPoint(), imageBuffer2->size()), CompositeDestinationOut);
+ filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()), 0, CompositeDestinationOut);
break;
case FECOMPOSITE_OPERATOR_ATOP:
filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()));
- filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), IntRect(IntPoint(), imageBuffer->size()), CompositeSourceAtop);
+ filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), 0, CompositeSourceAtop);
break;
case FECOMPOSITE_OPERATOR_XOR:
filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()));
- filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), IntRect(IntPoint(), imageBuffer->size()), CompositeXOR);
+ filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), 0, CompositeXOR);
break;
default:
break;
@@ -342,15 +380,25 @@ SkXfermode::Mode toXfermode(WebCore::CompositeOperationType mode)
PassRefPtr<SkImageFilter> FEComposite::createImageFilter(SkiaImageFilterBuilder* builder)
{
- RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingColorSpace()));
- RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingColorSpace()));
- if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) {
- SkAutoTUnref<SkXfermode> mode(SkArithmeticMode::Create(SkFloatToScalar(m_k1), SkFloatToScalar(m_k2), SkFloatToScalar(m_k3), SkFloatToScalar(m_k4)));
- return adoptRef(new SkXfermodeImageFilter(mode, background.get(), foreground.get()));
- }
+ return createImageFilterInternal(builder, true);
+}
+
+PassRefPtr<SkImageFilter> FEComposite::createImageFilterWithoutValidation(SkiaImageFilterBuilder* builder)
+{
+ return createImageFilterInternal(builder, false);
+}
+
+PassRefPtr<SkImageFilter> FEComposite::createImageFilterInternal(SkiaImageFilterBuilder* builder, bool requiresPMColorValidation)
+{
+ RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingColorSpace(), !mayProduceInvalidPreMultipliedPixels()));
+ RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingColorSpace(), !mayProduceInvalidPreMultipliedPixels()));
SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
- SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(toXfermode(m_type)));
- return adoptRef(new SkXfermodeImageFilter(mode, background.get(), foreground.get(), &cropRect));
+ RefPtr<SkXfermode> mode;
+ if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC)
+ mode = adoptRef(SkArithmeticMode::Create(SkFloatToScalar(m_k1), SkFloatToScalar(m_k2), SkFloatToScalar(m_k3), SkFloatToScalar(m_k4), requiresPMColorValidation));
+ else
+ mode = adoptRef(SkXfermode::Create(toXfermode(m_type)));
+ return adoptRef(SkXfermodeImageFilter::Create(mode.get(), background.get(), foreground.get(), &cropRect));
}
static TextStream& operator<<(TextStream& ts, const CompositeOperationType& type)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.h
index afe24b7c07e..54a94e2eeca 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEComposite.h
@@ -60,19 +60,21 @@ public:
virtual void correctFilterResultIfNeeded() OVERRIDE;
- virtual void determineAbsolutePaintRect();
+ virtual FloatRect determineAbsolutePaintRect(const FloatRect& requestedRect) OVERRIDE;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
+ virtual PassRefPtr<SkImageFilter> createImageFilterWithoutValidation(SkiaImageFilterBuilder*) OVERRIDE;
protected:
- virtual bool requiresValidPreMultipliedPixels() OVERRIDE { return m_type != FECOMPOSITE_OPERATOR_ARITHMETIC; }
+ virtual bool mayProduceInvalidPreMultipliedPixels() OVERRIDE { return m_type == FECOMPOSITE_OPERATOR_ARITHMETIC; }
private:
FEComposite(Filter*, const CompositeOperationType&, float, float, float, float);
virtual void applySoftware() OVERRIDE;
+ PassRefPtr<SkImageFilter> createImageFilterInternal(SkiaImageFilterBuilder*, bool requiresPMColorValidation);
inline void platformArithmeticSoftware(Uint8ClampedArray* source, Uint8ClampedArray* destination,
float k1, float k2, float k3, float k4);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.cpp
index 454541e0b80..418f19b4604 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.cpp
@@ -59,6 +59,14 @@ PassRefPtr<FEConvolveMatrix> FEConvolveMatrix::create(Filter* filter, const IntS
preserveAlpha, kernelMatrix));
}
+FloatRect FEConvolveMatrix::mapPaintRect(const FloatRect& rect, bool forward)
+{
+ FloatRect result = rect;
+
+ result.moveBy(forward ? -m_targetOffset : m_targetOffset - m_kernelSize);
+ result.expand(m_kernelSize);
+ return result;
+}
IntSize FEConvolveMatrix::kernelSize() const
{
@@ -527,7 +535,7 @@ PassRefPtr<SkImageFilter> FEConvolveMatrix::createImageFilter(SkiaImageFilterBui
for (int i = 0; i < numElements; ++i)
kernel[i] = SkFloatToScalar(m_kernelMatrix[numElements - 1 - i]);
SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
- return adoptRef(new SkMatrixConvolutionImageFilter(kernelSize, kernel.get(), gain, bias, target, tileMode, convolveAlpha, input.get(), &cropRect));
+ return adoptRef(SkMatrixConvolutionImageFilter::Create(kernelSize, kernel.get(), gain, bias, target, tileMode, convolveAlpha, input.get(), &cropRect));
}
static TextStream& operator<<(TextStream& ts, const EdgeModeType& type)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.h
index 2191c08a6b8..154ff1ddacb 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.h
@@ -71,9 +71,9 @@ public:
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
+ virtual FloatRect mapPaintRect(const FloatRect&, bool forward = true) OVERRIDE FINAL;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.cpp
index b82fed523a0..cfba8d98260 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.cpp
@@ -78,6 +78,7 @@ float FEDiffuseLighting::diffuseConstant() const
bool FEDiffuseLighting::setDiffuseConstant(float diffuseConstant)
{
+ diffuseConstant = std::max(diffuseConstant, 0.0f);
if (m_diffuseConstant == diffuseConstant)
return false;
m_diffuseConstant = diffuseConstant;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.h
index f93bc5ac0ed..8f2933bfffa 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDiffuseLighting.h
@@ -53,7 +53,7 @@ public:
const LightSource* lightSource() const;
void setLightSource(PassRefPtr<LightSource>);
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
FEDiffuseLighting(Filter*, const Color&, float, float, float, float, PassRefPtr<LightSource>);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.cpp
index ad31826126c..3c6544e8296 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.cpp
@@ -49,6 +49,14 @@ PassRefPtr<FEDisplacementMap> FEDisplacementMap::create(Filter* filter, ChannelS
return adoptRef(new FEDisplacementMap(filter, xChannelSelector, yChannelSelector, scale));
}
+FloatRect FEDisplacementMap::mapPaintRect(const FloatRect& rect, bool)
+{
+ FloatRect result = rect;
+ result.inflateX(filter()->applyHorizontalScale(m_scale / 2));
+ result.inflateY(filter()->applyVerticalScale(m_scale / 2));
+ return result;
+}
+
ChannelSelectorType FEDisplacementMap::xChannelSelector() const
{
return m_xChannelSelector;
@@ -168,48 +176,6 @@ static SkDisplacementMapEffect::ChannelSelectorType toSkiaMode(ChannelSelectorTy
}
}
-bool FEDisplacementMap::applySkia()
-{
- // For now, only use the skia implementation for accelerated rendering.
- if (!filter()->isAccelerated())
- return false;
-
- FilterEffect* in = inputEffect(0);
- FilterEffect* in2 = inputEffect(1);
-
- if (!in || !in2)
- return false;
-
- ImageBuffer* resultImage = createImageBufferResult();
- if (!resultImage)
- return false;
-
- RefPtr<Image> color = in->asImageBuffer()->copyImage(DontCopyBackingStore);
- RefPtr<Image> displ = in2->asImageBuffer()->copyImage(DontCopyBackingStore);
-
- RefPtr<NativeImageSkia> colorNativeImage = color->nativeImageForCurrentFrame();
- RefPtr<NativeImageSkia> displNativeImage = displ->nativeImageForCurrentFrame();
-
- if (!colorNativeImage || !displNativeImage)
- return false;
-
- SkBitmap colorBitmap = colorNativeImage->bitmap();
- SkBitmap displBitmap = displNativeImage->bitmap();
-
- SkAutoTUnref<SkImageFilter> colorSource(new SkBitmapSource(colorBitmap));
- SkAutoTUnref<SkImageFilter> displSource(new SkBitmapSource(displBitmap));
- SkDisplacementMapEffect::ChannelSelectorType typeX = toSkiaMode(m_xChannelSelector);
- SkDisplacementMapEffect::ChannelSelectorType typeY = toSkiaMode(m_yChannelSelector);
- // FIXME : Only applyHorizontalScale is used and applyVerticalScale is ignored
- // This can be fixed by adding a 2nd scale parameter to SkDisplacementMapEffect
- SkAutoTUnref<SkImageFilter> displEffect(new SkDisplacementMapEffect(
- typeX, typeY, SkFloatToScalar(filter()->applyHorizontalScale(m_scale)), displSource, colorSource));
- SkPaint paint;
- paint.setImageFilter(displEffect);
- resultImage->context()->drawBitmap(colorBitmap, 0, 0, &paint);
- return true;
-}
-
PassRefPtr<SkImageFilter> FEDisplacementMap::createImageFilter(SkiaImageFilterBuilder* builder)
{
RefPtr<SkImageFilter> color = builder->build(inputEffect(0), operatingColorSpace());
@@ -219,7 +185,7 @@ PassRefPtr<SkImageFilter> FEDisplacementMap::createImageFilter(SkiaImageFilterBu
SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
// FIXME : Only applyHorizontalScale is used and applyVerticalScale is ignored
// This can be fixed by adding a 2nd scale parameter to SkDisplacementMapEffect
- return adoptRef(new SkDisplacementMapEffect(typeX, typeY, SkFloatToScalar(filter()->applyHorizontalScale(m_scale)), displ.get(), color.get(), &cropRect));
+ return adoptRef(SkDisplacementMapEffect::Create(typeX, typeY, SkFloatToScalar(filter()->applyHorizontalScale(m_scale)), displ.get(), color.get(), &cropRect));
}
static TextStream& operator<<(TextStream& ts, const ChannelSelectorType& type)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.h
index 91e151ef887..27601d71f9d 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDisplacementMap.h
@@ -50,18 +50,17 @@ public:
float scale() const;
bool setScale(float);
- void setResultColorSpace(ColorSpace) OVERRIDE;
+ virtual void setResultColorSpace(ColorSpace) OVERRIDE;
virtual void transformResultColorSpace(FilterEffect*, const int) OVERRIDE;
- virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
+ virtual FloatRect mapPaintRect(const FloatRect&, bool forward = true) OVERRIDE FINAL;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
FEDisplacementMap(Filter*, ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float);
virtual void applySoftware() OVERRIDE;
- virtual bool applySkia() OVERRIDE;
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.cpp
index 4e645b4f69d..443a52c998b 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.cpp
@@ -49,21 +49,6 @@ PassRefPtr<FEDropShadow> FEDropShadow::create(Filter* filter, float stdX, float
return adoptRef(new FEDropShadow(filter, stdX, stdY, dx, dy, shadowColor, shadowOpacity));
}
-void FEDropShadow::determineAbsolutePaintRect()
-{
- Filter* filter = this->filter();
- ASSERT_UNUSED(filter, filter);
-
- FloatRect absolutePaintRect = mapRect(inputEffect(0)->absolutePaintRect());
-
- if (clipsToBounds())
- absolutePaintRect.intersect(maxEffectRect());
- else
- absolutePaintRect.unite(maxEffectRect());
-
- setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
-}
-
FloatRect FEDropShadow::mapRect(const FloatRect& rect, bool forward)
{
FloatRect result = rect;
@@ -77,13 +62,11 @@ FloatRect FEDropShadow::mapRect(const FloatRect& rect, bool forward)
offsetRect.move(-filter->applyHorizontalScale(m_dx), -filter->applyVerticalScale(m_dy));
result.unite(offsetRect);
- unsigned kernelSizeX = 0;
- unsigned kernelSizeY = 0;
- FEGaussianBlur::calculateKernelSize(filter, kernelSizeX, kernelSizeY, m_stdX, m_stdY);
+ IntSize kernelSize = FEGaussianBlur::calculateKernelSize(filter, FloatPoint(m_stdX, m_stdY));
// We take the half kernel size and multiply it with three, because we run box blur three times.
- result.inflateX(3 * kernelSizeX * 0.5f);
- result.inflateY(3 * kernelSizeY * 0.5f);
+ result.inflateX(3 * kernelSize.width() * 0.5f);
+ result.inflateY(3 * kernelSize.height() * 0.5f);
return result;
}
@@ -103,8 +86,9 @@ void FEDropShadow::applySoftware()
GraphicsContext* resultContext = resultImage->context();
ASSERT(resultContext);
- SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(blurRadius.width(), blurRadius.height()));
- SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(m_shadowColor.rgb(), SkXfermode::kSrcIn_Mode));
+ Color color = adaptColorToOperatingColorSpace(m_shadowColor.combineWithAlpha(m_shadowOpacity));
+ SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(blurRadius.width(), blurRadius.height()));
+ SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(color.rgb(), SkXfermode::kSrcIn_Mode));
SkPaint paint;
paint.setImageFilter(blurFilter.get());
paint.setColorFilter(colorFilter.get());
@@ -126,9 +110,10 @@ PassRefPtr<SkImageFilter> FEDropShadow::createImageFilter(SkiaImageFilterBuilder
float dx = filter()->applyHorizontalScale(m_dx);
float dy = filter()->applyVerticalScale(m_dy);
float stdX = filter()->applyHorizontalScale(m_stdX);
- float stdY = filter()->applyHorizontalScale(m_stdY);
+ float stdY = filter()->applyVerticalScale(m_stdY);
+ Color color = adaptColorToOperatingColorSpace(m_shadowColor.combineWithAlpha(m_shadowOpacity));
SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
- return adoptRef(new SkDropShadowImageFilter(SkFloatToScalar(dx), SkFloatToScalar(dy), SkFloatToScalar(stdX), SkFloatToScalar(stdY), m_shadowColor.rgb(), input.get(), &cropRect));
+ return adoptRef(SkDropShadowImageFilter::Create(SkFloatToScalar(dx), SkFloatToScalar(dy), SkFloatToScalar(stdX), SkFloatToScalar(stdY), color.rgb(), input.get(), &cropRect));
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.h
index a3d9d956272..38d643ee135 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEDropShadow.h
@@ -49,12 +49,9 @@ public:
float shadowOpacity() const { return m_shadowOpacity; }
void setShadowOpacity(float shadowOpacity) { m_shadowOpacity = shadowOpacity; }
- static float calculateStdDeviation(float);
-
- virtual void determineAbsolutePaintRect();
virtual FloatRect mapRect(const FloatRect&, bool forward = true) OVERRIDE FINAL;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
private:
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.cpp
index 03ed1f439c3..3bd7991f542 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.cpp
@@ -40,7 +40,6 @@ FEFlood::FEFlood(Filter* filter, const Color& floodColor, float floodOpacity)
, m_floodOpacity(floodOpacity)
{
FilterEffect::setOperatingColorSpace(ColorSpaceDeviceRGB);
- FilterEffect::setResultColorSpace(ColorSpaceDeviceRGB);
}
PassRefPtr<FEFlood> FEFlood::create(Filter* filter, const Color& floodColor, float floodOpacity)
@@ -80,13 +79,14 @@ void FEFlood::applySoftware()
if (!resultImage)
return;
- Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity());
+ Color color = floodColor().combineWithAlpha(floodOpacity());
resultImage->context()->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), color);
+ FilterEffect::setResultColorSpace(ColorSpaceDeviceRGB);
}
PassRefPtr<SkImageFilter> FEFlood::createImageFilter(SkiaImageFilterBuilder* builder)
{
- Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity());
+ Color color = floodColor().combineWithAlpha(floodOpacity());
SkImageFilter::CropRect rect = getCropRect(builder->cropOffset());
SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(color.rgb(), SkXfermode::kSrc_Mode));
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.h
index 918811c7ac2..ee91a997d23 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEFlood.h
@@ -41,14 +41,12 @@ public:
// feFlood does not perform color interpolation of any kind, so the result is always in the current
// color space regardless of the value of color-interpolation-filters.
- void setOperatingColorSpace(ColorSpace) OVERRIDE { }
- void setResultColorSpace(ColorSpace) OVERRIDE { }
+ virtual void setOperatingColorSpace(ColorSpace) OVERRIDE { }
+ virtual void setResultColorSpace(ColorSpace) OVERRIDE { }
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
-
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
FEFlood(Filter*, const Color&, float);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.cpp
index 150aac53213..82554826e56 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.cpp
@@ -41,10 +41,10 @@ using namespace std;
static inline float gaussianKernelFactor()
{
- return 3 / 4.f * sqrtf(2 * piFloat);
+ return 3 / 4.f * sqrtf(twoPiFloat);
}
-static const unsigned gMaxKernelSize = 1000;
+static const int gMaxKernelSize = 1000;
namespace WebCore {
@@ -80,238 +80,69 @@ void FEGaussianBlur::setStdDeviationY(float y)
m_stdY = y;
}
-inline void boxBlur(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray,
- unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage)
+IntSize FEGaussianBlur::calculateUnscaledKernelSize(const FloatPoint& std)
{
- for (int y = 0; y < effectHeight; ++y) {
- int line = y * strideLine;
- for (int channel = 3; channel >= 0; --channel) {
- int sum = 0;
- // Fill the kernel
- int maxKernelSize = min(dxRight, effectWidth);
- for (int i = 0; i < maxKernelSize; ++i)
- sum += srcPixelArray->item(line + i * stride + channel);
-
- // Blurring
- for (int x = 0; x < effectWidth; ++x) {
- int pixelByteOffset = line + x * stride + channel;
- dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
- if (x >= dxLeft)
- sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride);
- if (x + dxRight < effectWidth)
- sum += srcPixelArray->item(pixelByteOffset + dxRight * stride);
- }
- if (alphaImage) // Source image is black, it just has different alpha values
- break;
- }
- }
-}
-
-inline void FEGaussianBlur::platformApplyGeneric(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
-{
- int stride = 4 * paintSize.width();
- int dxLeft = 0;
- int dxRight = 0;
- int dyLeft = 0;
- int dyRight = 0;
- Uint8ClampedArray* src = srcPixelArray;
- Uint8ClampedArray* dst = tmpPixelArray;
-
- for (int i = 0; i < 3; ++i) {
- if (kernelSizeX) {
- kernelPosition(i, kernelSizeX, dxLeft, dxRight);
-#if HAVE(ARM_NEON_INTRINSICS)
- if (!isAlphaImage())
- boxBlurNEON(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height());
- else
- boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), true);
-#else
- boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage());
-#endif
- swap(src, dst);
- }
-
- if (kernelSizeY) {
- kernelPosition(i, kernelSizeY, dyLeft, dyRight);
-#if HAVE(ARM_NEON_INTRINSICS)
- if (!isAlphaImage())
- boxBlurNEON(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width());
- else
- boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), true);
-#else
- boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage());
-#endif
- swap(src, dst);
- }
- }
-
- // The final result should be stored in srcPixelArray.
- if (dst == srcPixelArray) {
- ASSERT(src->length() == dst->length());
- memcpy(dst->data(), src->data(), src->length());
- }
-
-}
-
-void FEGaussianBlur::platformApplyWorker(PlatformApplyParameters* parameters)
-{
- IntSize paintSize(parameters->width, parameters->height);
- parameters->filter->platformApplyGeneric(parameters->srcPixelArray.get(), parameters->dstPixelArray.get(),
- parameters->kernelSizeX, parameters->kernelSizeY, paintSize);
-}
-
-inline void FEGaussianBlur::platformApply(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
-{
- int scanline = 4 * paintSize.width();
- int extraHeight = 3 * kernelSizeY * 0.5f;
- int optimalThreadNumber = (paintSize.width() * paintSize.height()) / (s_minimalRectDimension + extraHeight * paintSize.width());
-
- if (optimalThreadNumber > 1) {
- ParallelJobs<PlatformApplyParameters> parallelJobs(&platformApplyWorker, optimalThreadNumber);
-
- int jobs = parallelJobs.numberOfJobs();
- if (jobs > 1) {
- // Split the job into "blockHeight"-sized jobs but there a few jobs that need to be slightly larger since
- // blockHeight * jobs < total size. These extras are handled by the remainder "jobsWithExtra".
- const int blockHeight = paintSize.height() / jobs;
- const int jobsWithExtra = paintSize.height() % jobs;
-
- int currentY = 0;
- for (int job = 0; job < jobs; job++) {
- PlatformApplyParameters& params = parallelJobs.parameter(job);
- params.filter = this;
-
- int startY = !job ? 0 : currentY - extraHeight;
- currentY += job < jobsWithExtra ? blockHeight + 1 : blockHeight;
- int endY = job == jobs - 1 ? currentY : currentY + extraHeight;
-
- int blockSize = (endY - startY) * scanline;
- if (!job) {
- params.srcPixelArray = srcPixelArray;
- params.dstPixelArray = tmpPixelArray;
- } else {
- params.srcPixelArray = Uint8ClampedArray::createUninitialized(blockSize);
- params.dstPixelArray = Uint8ClampedArray::createUninitialized(blockSize);
- memcpy(params.srcPixelArray->data(), srcPixelArray->data() + startY * scanline, blockSize);
- }
-
- params.width = paintSize.width();
- params.height = endY - startY;
- params.kernelSizeX = kernelSizeX;
- params.kernelSizeY = kernelSizeY;
- }
-
- parallelJobs.execute();
-
- // Copy together the parts of the image.
- currentY = 0;
- for (int job = 1; job < jobs; job++) {
- PlatformApplyParameters& params = parallelJobs.parameter(job);
- int sourceOffset;
- int destinationOffset;
- int size;
- int adjustedBlockHeight = job < jobsWithExtra ? blockHeight + 1 : blockHeight;
-
- currentY += adjustedBlockHeight;
- sourceOffset = extraHeight * scanline;
- destinationOffset = currentY * scanline;
- size = adjustedBlockHeight * scanline;
-
- memcpy(srcPixelArray->data() + destinationOffset, params.srcPixelArray->data() + sourceOffset, size);
- }
- return;
- }
- // Fallback to single threaded mode.
- }
-
- // The selection here eventually should happen dynamically on some platforms.
- platformApplyGeneric(srcPixelArray, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize);
-}
-
-void FEGaussianBlur::calculateUnscaledKernelSize(unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY)
-{
- ASSERT(stdX >= 0 && stdY >= 0);
-
- kernelSizeX = 0;
- if (stdX)
- kernelSizeX = max<unsigned>(2, static_cast<unsigned>(floorf(stdX * gaussianKernelFactor() + 0.5f)));
- kernelSizeY = 0;
- if (stdY)
- kernelSizeY = max<unsigned>(2, static_cast<unsigned>(floorf(stdY * gaussianKernelFactor() + 0.5f)));
+ ASSERT(std.x() >= 0 && std.y() >= 0);
+ IntSize kernelSize;
// Limit the kernel size to 1000. A bigger radius won't make a big difference for the result image but
// inflates the absolute paint rect to much. This is compatible with Firefox' behavior.
- if (kernelSizeX > gMaxKernelSize)
- kernelSizeX = gMaxKernelSize;
- if (kernelSizeY > gMaxKernelSize)
- kernelSizeY = gMaxKernelSize;
-}
+ if (std.x()) {
+ int size = max<unsigned>(2, static_cast<unsigned>(floorf(std.x() * gaussianKernelFactor() + 0.5f)));
+ kernelSize.setWidth(min(size, gMaxKernelSize));
+ }
-void FEGaussianBlur::calculateKernelSize(Filter* filter, unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY)
-{
- stdX = filter->applyHorizontalScale(stdX);
- stdY = filter->applyVerticalScale(stdY);
+ if (std.y()) {
+ int size = max<unsigned>(2, static_cast<unsigned>(floorf(std.y() * gaussianKernelFactor() + 0.5f)));
+ kernelSize.setHeight(min(size, gMaxKernelSize));
+ }
- calculateUnscaledKernelSize(kernelSizeX, kernelSizeY, stdX, stdY);
+ return kernelSize;
}
-void FEGaussianBlur::determineAbsolutePaintRect()
+IntSize FEGaussianBlur::calculateKernelSize(Filter* filter, const FloatPoint& std)
{
- FloatRect absolutePaintRect = mapRect(inputEffect(0)->absolutePaintRect());
-
- if (clipsToBounds())
- absolutePaintRect.intersect(maxEffectRect());
- else
- absolutePaintRect.unite(maxEffectRect());
+ FloatPoint stdError(filter->applyHorizontalScale(std.x()), filter->applyVerticalScale(std.y()));
- setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
+ return calculateUnscaledKernelSize(stdError);
}
FloatRect FEGaussianBlur::mapRect(const FloatRect& rect, bool)
{
FloatRect result = rect;
- unsigned kernelSizeX = 0;
- unsigned kernelSizeY = 0;
- calculateKernelSize(filter(), kernelSizeX, kernelSizeY, m_stdX, m_stdY);
+ IntSize kernelSize = calculateKernelSize(filter(), FloatPoint(m_stdX, m_stdY));
// We take the half kernel size and multiply it with three, because we run box blur three times.
- result.inflateX(3 * kernelSizeX * 0.5f);
- result.inflateY(3 * kernelSizeY * 0.5f);
+ result.inflateX(3 * kernelSize.width() * 0.5f);
+ result.inflateY(3 * kernelSize.height() * 0.5f);
return result;
}
-void FEGaussianBlur::applySoftware()
+FloatRect FEGaussianBlur::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
{
- FilterEffect* in = inputEffect(0);
-
- Uint8ClampedArray* srcPixelArray = createPremultipliedImageResult();
- if (!srcPixelArray)
- return;
-
- setIsAlphaImage(in->isAlphaImage());
-
- IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- in->copyPremultipliedImage(srcPixelArray, effectDrawingRect);
-
- if (!m_stdX && !m_stdY)
- return;
-
- unsigned kernelSizeX = 0;
- unsigned kernelSizeY = 0;
- calculateKernelSize(filter(), kernelSizeX, kernelSizeY, m_stdX, m_stdY);
+ FloatRect requestedRect = originalRequestedRect;
+ if (clipsToBounds())
+ requestedRect.intersect(maxEffectRect());
- IntSize paintSize = absolutePaintRect().size();
- RefPtr<Uint8ClampedArray> tmpImageData = Uint8ClampedArray::createUninitialized(paintSize.width() * paintSize.height() * 4);
- Uint8ClampedArray* tmpPixelArray = tmpImageData.get();
+ FilterEffect* input = inputEffect(0);
+ FloatRect inputRect = input->determineAbsolutePaintRect(mapRect(requestedRect, false));
+ FloatRect outputRect = mapRect(inputRect, true);
+ outputRect.intersect(requestedRect);
+ addAbsolutePaintRect(outputRect);
- platformApply(srcPixelArray, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize);
+ // Blur needs space for both input and output pixels in the paint area.
+ // Input is also clipped to subregion.
+ if (clipsToBounds())
+ inputRect.intersect(maxEffectRect());
+ addAbsolutePaintRect(inputRect);
+ return outputRect;
}
-bool FEGaussianBlur::applySkia()
+void FEGaussianBlur::applySoftware()
{
ImageBuffer* resultImage = createImageBufferResult();
if (!resultImage)
- return false;
+ return;
FilterEffect* in = inputEffect(0);
@@ -326,13 +157,13 @@ bool FEGaussianBlur::applySkia()
SkPaint paint;
GraphicsContext* dstContext = resultImage->context();
- paint.setImageFilter(new SkBlurImageFilter(stdX, stdY))->unref();
+ paint.setImageFilter(SkBlurImageFilter::Create(stdX, stdY))->unref();
- dstContext->saveLayer(0, &paint);
+ SkRect bounds = SkRect::MakeWH(absolutePaintRect().width(), absolutePaintRect().height());
+ dstContext->saveLayer(&bounds, &paint);
paint.setColor(0xFFFFFFFF);
dstContext->drawImage(image.get(), drawingRegion.location(), CompositeCopy);
dstContext->restoreLayer();
- return true;
}
PassRefPtr<SkImageFilter> FEGaussianBlur::createImageFilter(SkiaImageFilterBuilder* builder)
@@ -341,7 +172,7 @@ PassRefPtr<SkImageFilter> FEGaussianBlur::createImageFilter(SkiaImageFilterBuild
float stdX = filter()->applyHorizontalScale(m_stdX);
float stdY = filter()->applyVerticalScale(m_stdY);
SkImageFilter::CropRect rect = getCropRect(builder->cropOffset());
- return adoptRef(new SkBlurImageFilter(SkFloatToScalar(stdX), SkFloatToScalar(stdY), input.get(), &rect));
+ return adoptRef(SkBlurImageFilter::Create(SkFloatToScalar(stdX), SkFloatToScalar(stdY), input.get(), &rect));
}
TextStream& FEGaussianBlur::externalRepresentation(TextStream& ts, int indent) const
@@ -354,10 +185,4 @@ TextStream& FEGaussianBlur::externalRepresentation(TextStream& ts, int indent) c
return ts;
}
-float FEGaussianBlur::calculateStdDeviation(float radius)
-{
- // Blur radius represents 2/3 times the kernel size, the dest pixel is half of the radius applied 3 times
- return max((radius * 2 / 3.f - 0.5f) / gaussianKernelFactor(), 0.f);
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.h
index 1974bea46d6..c10d220d941 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEGaussianBlur.h
@@ -38,14 +38,12 @@ public:
float stdDeviationY() const;
void setStdDeviationY(float);
- static float calculateStdDeviation(float);
-
- virtual void determineAbsolutePaintRect();
virtual FloatRect mapRect(const FloatRect&, bool forward = true) OVERRIDE FINAL;
- static void calculateKernelSize(Filter*, unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY);
- static void calculateUnscaledKernelSize(unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY);
+ virtual FloatRect determineAbsolutePaintRect(const FloatRect& requestedRect) OVERRIDE;
+ static IntSize calculateKernelSize(Filter*, const FloatPoint& std);
+ static IntSize calculateUnscaledKernelSize(const FloatPoint& std);
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
static const int s_minimalRectDimension = 100 * 100; // Empirical data limit for parallel jobs
@@ -63,51 +61,16 @@ private:
unsigned kernelSizeY;
};
- static void platformApplyWorker(PlatformApplyParameters*);
-
FEGaussianBlur(Filter*, float, float);
virtual void applySoftware() OVERRIDE;
- virtual bool applySkia() OVERRIDE;
- static inline void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight);
- inline void platformApply(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
-
- inline void platformApplyGeneric(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
float m_stdX;
float m_stdY;
};
-inline void FEGaussianBlur::kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight)
-{
- // check http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement for details
- switch (boxBlur) {
- case 0:
- if (!(std % 2)) {
- dLeft = std / 2 - 1;
- dRight = std - dLeft;
- } else {
- dLeft = std / 2;
- dRight = std - dLeft;
- }
- break;
- case 1:
- if (!(std % 2)) {
- dLeft++;
- dRight--;
- }
- break;
- case 2:
- if (!(std % 2)) {
- dRight++;
- std++;
- }
- break;
- }
-}
-
} // namespace WebCore
#endif // FEGaussianBlur_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.cpp
index 92efec12059..8e6bc1818ac 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.cpp
@@ -29,7 +29,6 @@
#include "platform/graphics/filters/FELighting.h"
#include "SkLightingImageFilter.h"
-#include "platform/graphics/cpu/arm/filters/FELightingNEON.h"
#include "platform/graphics/filters/DistantLightSource.h"
#include "platform/graphics/filters/ParallelJobs.h"
#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
@@ -45,14 +44,22 @@ FELighting::FELighting(Filter* filter, LightingType lightingType, const Color& l
, m_lightSource(lightSource)
, m_lightingColor(lightingColor)
, m_surfaceScale(surfaceScale)
- , m_diffuseConstant(diffuseConstant)
- , m_specularConstant(specularConstant)
- , m_specularExponent(specularExponent)
+ , m_diffuseConstant(std::max(diffuseConstant, 0.0f))
+ , m_specularConstant(std::max(specularConstant, 0.0f))
+ , m_specularExponent(std::min(std::max(specularExponent, 1.0f), 128.0f))
, m_kernelUnitLengthX(kernelUnitLengthX)
, m_kernelUnitLengthY(kernelUnitLengthY)
{
}
+FloatRect FELighting::mapPaintRect(const FloatRect& rect, bool)
+{
+ FloatRect result = rect;
+ // The areas affected need to be a pixel bigger to accommodate the Sobel kernel.
+ result.inflate(1);
+ return result;
+}
+
const static int cPixelSize = 4;
const static int cAlphaChannelOffset = 3;
const static unsigned char cOpaqueAlpha = static_cast<unsigned char>(0xff);
@@ -179,7 +186,7 @@ inline void FELighting::LightingData::bottomRight(int offset, IntPoint& normalVe
inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData,
int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector)
{
- m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->item(offset + cAlphaChannelOffset)) * data.surfaceScale);
+ data.lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->item(offset + cAlphaChannelOffset)) * data.surfaceScale);
float lightStrength;
if (!normal2DVector.x() && !normal2DVector.y()) {
@@ -286,12 +293,21 @@ inline void FELighting::platformApplyGeneric(LightingData& data, LightSource::Pa
inline void FELighting::platformApply(LightingData& data, LightSource::PaintingData& paintingData)
{
- // The selection here eventually should happen dynamically on some platforms.
-#if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC)
- platformApplyNeon(data, paintingData);
-#else
platformApplyGeneric(data, paintingData);
-#endif
+}
+
+void FELighting::getTransform(FloatPoint3D* scale, FloatSize* offset) const
+{
+ FloatRect initialEffectRect = effectBoundaries();
+ FloatRect absoluteEffectRect = filter()->mapLocalRectToAbsoluteRect(initialEffectRect);
+ FloatPoint absoluteLocation(absolutePaintRect().location());
+ FloatSize positionOffset(absoluteLocation - absoluteEffectRect.location());
+ offset->setWidth(positionOffset.width());
+ offset->setHeight(positionOffset.height());
+ scale->setX(initialEffectRect.width() > 0.0f && initialEffectRect.width() > 0.0f ? absoluteEffectRect.width() / initialEffectRect.width() : 1.0f);
+ scale->setY(initialEffectRect.height() > 0.0f && initialEffectRect.height() > 0.0f ? absoluteEffectRect.height() / initialEffectRect.height() : 1.0f);
+ // X and Y scale should be the same, but, if not, do a best effort by averaging the 2 for Z scale
+ scale->setZ(0.5f * (scale->x() + scale->y()));
}
bool FELighting::drawLighting(Uint8ClampedArray* pixels, int width, int height)
@@ -312,8 +328,14 @@ bool FELighting::drawLighting(Uint8ClampedArray* pixels, int width, int height)
data.widthMultipliedByPixelSize = width * cPixelSize;
data.widthDecreasedByOne = width - 1;
data.heightDecreasedByOne = height - 1;
- paintingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue());
- m_lightSource->initPaintingData(paintingData);
+ FloatPoint3D worldScale;
+ FloatSize originOffset;
+ getTransform(&worldScale, &originOffset);
+ RefPtr<LightSource> lightSource = m_lightSource->create(worldScale, originOffset);
+ data.lightSource = lightSource.get();
+ Color lightColor = adaptColorToOperatingColorSpace(m_lightingColor);
+ paintingData.colorVector = FloatPoint3D(lightColor.red(), lightColor.green(), lightColor.blue());
+ data.lightSource->initPaintingData(paintingData);
// Top/Left corner.
IntPoint normalVector;
@@ -413,7 +435,8 @@ void FELighting::applySoftware()
PassRefPtr<SkImageFilter> FELighting::createImageFilter(SkiaImageFilterBuilder* builder)
{
SkImageFilter::CropRect rect = getCropRect(builder ? builder->cropOffset() : FloatSize());
- RefPtr<SkImageFilter> input(builder ? builder->build(inputEffect(0), operatingColorSpace()) : 0);
+ Color lightColor = adaptColorToOperatingColorSpace(m_lightingColor);
+ RefPtr<SkImageFilter> input(builder ? builder->build(inputEffect(0), operatingColorSpace()) : nullptr);
switch (m_lightSource->type()) {
case LS_DISTANT: {
DistantLightSource* distantLightSource = static_cast<DistantLightSource*>(m_lightSource.get());
@@ -423,16 +446,16 @@ PassRefPtr<SkImageFilter> FELighting::createImageFilter(SkiaImageFilterBuilder*
sinf(azimuthRad) * cosf(elevationRad),
sinf(elevationRad));
if (m_specularConstant > 0)
- return adoptRef(SkLightingImageFilter::CreateDistantLitSpecular(direction, m_lightingColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent, input.get(), &rect));
- return adoptRef(SkLightingImageFilter::CreateDistantLitDiffuse(direction, m_lightingColor.rgb(), m_surfaceScale, m_diffuseConstant, input.get(), &rect));
+ return adoptRef(SkLightingImageFilter::CreateDistantLitSpecular(direction, lightColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent, input.get(), &rect));
+ return adoptRef(SkLightingImageFilter::CreateDistantLitDiffuse(direction, lightColor.rgb(), m_surfaceScale, m_diffuseConstant, input.get(), &rect));
}
case LS_POINT: {
PointLightSource* pointLightSource = static_cast<PointLightSource*>(m_lightSource.get());
FloatPoint3D position = pointLightSource->position();
SkPoint3 skPosition(position.x(), position.y(), position.z());
if (m_specularConstant > 0)
- return adoptRef(SkLightingImageFilter::CreatePointLitSpecular(skPosition, m_lightingColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent, input.get(), &rect));
- return adoptRef(SkLightingImageFilter::CreatePointLitDiffuse(skPosition, m_lightingColor.rgb(), m_surfaceScale, m_diffuseConstant, input.get(), &rect));
+ return adoptRef(SkLightingImageFilter::CreatePointLitSpecular(skPosition, lightColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent, input.get(), &rect));
+ return adoptRef(SkLightingImageFilter::CreatePointLitDiffuse(skPosition, lightColor.rgb(), m_surfaceScale, m_diffuseConstant, input.get(), &rect));
}
case LS_SPOT: {
SpotLightSource* spotLightSource = static_cast<SpotLightSource*>(m_lightSource.get());
@@ -443,43 +466,13 @@ PassRefPtr<SkImageFilter> FELighting::createImageFilter(SkiaImageFilterBuilder*
if (!limitingConeAngle || limitingConeAngle > 90 || limitingConeAngle < -90)
limitingConeAngle = 90;
if (m_specularConstant > 0)
- return adoptRef(SkLightingImageFilter::CreateSpotLitSpecular(location, target, specularExponent, limitingConeAngle, m_lightingColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent, input.get(), &rect));
- return adoptRef(SkLightingImageFilter::CreateSpotLitDiffuse(location, target, specularExponent, limitingConeAngle, m_lightingColor.rgb(), m_surfaceScale, m_diffuseConstant, input.get(), &rect));
+ return adoptRef(SkLightingImageFilter::CreateSpotLitSpecular(location, target, specularExponent, limitingConeAngle, lightColor.rgb(), m_surfaceScale, m_specularConstant, m_specularExponent, input.get(), &rect));
+ return adoptRef(SkLightingImageFilter::CreateSpotLitDiffuse(location, target, specularExponent, limitingConeAngle, lightColor.rgb(), m_surfaceScale, m_diffuseConstant, input.get(), &rect));
}
default:
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
}
-bool FELighting::applySkia()
-{
- // For now, only use the skia implementation for accelerated rendering.
- if (!filter()->isAccelerated())
- return false;
-
- ImageBuffer* resultImage = createImageBufferResult();
- if (!resultImage)
- return false;
-
- FilterEffect* in = inputEffect(0);
-
- IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
-
- setIsAlphaImage(in->isAlphaImage());
-
- RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
- RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame();
- if (!nativeImage)
- return false;
-
- GraphicsContext* dstContext = resultImage->context();
-
- SkPaint paint;
- RefPtr<SkImageFilter> filter = createImageFilter(0);
- paint.setImageFilter(filter.get());
- dstContext->drawBitmap(nativeImage->bitmap(), drawingRegion.location().x(), drawingRegion.location().y(), &paint);
- return true;
-}
-
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.h
index 32fdc122005..123fe51619f 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FELighting.h
@@ -40,14 +40,10 @@
namespace WebCore {
-struct FELightingPaintingDataForNeon;
-
class PLATFORM_EXPORT FELighting : public FilterEffect {
public:
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
-
protected:
static const int s_minimalRectDimension = 100 * 100; // Empirical data limit for parallel jobs
@@ -63,6 +59,7 @@ protected:
int widthMultipliedByPixelSize;
int widthDecreasedByOne;
int heightDecreasedByOne;
+ const LightSource* lightSource;
inline void topLeft(int offset, IntPoint& normalVector);
inline void topRow(int offset, IntPoint& normalVector);
@@ -86,8 +83,10 @@ protected:
int yEnd;
};
+ virtual FloatRect mapPaintRect(const FloatRect&, bool forward = true) OVERRIDE FINAL;
+ virtual bool affectsTransparentPixels() OVERRIDE { return true; }
+
static void platformApplyGenericWorker(PlatformApplyGenericParameters*);
- static void platformApplyNeonWorker(FELightingPaintingDataForNeon*);
FELighting(Filter*, LightingType, const Color&, float, float, float, float, float, float, PassRefPtr<LightSource>);
@@ -104,9 +103,6 @@ protected:
inline void platformApplyGenericPaint(LightingData&, LightSource::PaintingData&, int startX, int startY);
inline void platformApplyGeneric(LightingData&, LightSource::PaintingData&);
- static int getPowerCoefficients(float exponent);
- inline void platformApplyNeon(LightingData&, LightSource::PaintingData&);
-
LightingType m_lightingType;
RefPtr<LightSource> m_lightSource;
@@ -120,7 +116,8 @@ protected:
private:
virtual void applySoftware() OVERRIDE;
- virtual bool applySkia() OVERRIDE;
+
+ void getTransform(FloatPoint3D* scale, FloatSize* offset) const;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.cpp
index c31440d44c4..3845ffe0e22 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.cpp
@@ -68,7 +68,7 @@ PassRefPtr<SkImageFilter> FEMerge::createImageFilter(SkiaImageFilterBuilder* bui
inputs[i] = inputRefs[i].get();
}
SkImageFilter::CropRect rect = getCropRect(builder->cropOffset());
- return adoptRef(new SkMergeImageFilter(inputs.get(), size, 0, &rect));
+ return adoptRef(SkMergeImageFilter::Create(inputs.get(), size, 0, &rect));
}
TextStream& FEMerge::externalRepresentation(TextStream& ts, int indent) const
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.h
index 05e374e58e4..22fd7fc560f 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMerge.h
@@ -35,7 +35,7 @@ public:
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
FEMerge(Filter*);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.cpp
index 5201a45dcde..00483e803b0 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.cpp
@@ -26,6 +26,8 @@
#include "platform/graphics/filters/FEMorphology.h"
#include "SkMorphologyImageFilter.h"
+#include "platform/graphics/GraphicsContext.h"
+#include "platform/graphics/Image.h"
#include "platform/graphics/filters/ParallelJobs.h"
#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
#include "platform/text/TextStream.h"
@@ -80,16 +82,6 @@ float FEMorphology::radiusY() const
return m_radiusY;
}
-void FEMorphology::determineAbsolutePaintRect()
-{
- FloatRect paintRect = mapRect(inputEffect(0)->absolutePaintRect());
- if (clipsToBounds())
- paintRect.intersect(maxEffectRect());
- else
- paintRect.unite(maxEffectRect());
- setAbsolutePaintRect(enclosingIntRect(paintRect));
-}
-
FloatRect FEMorphology::mapRect(const FloatRect& rect, bool)
{
FloatRect result = rect;
@@ -106,135 +98,11 @@ bool FEMorphology::setRadiusY(float radiusY)
return true;
}
-void FEMorphology::platformApplyGeneric(PaintingData* paintingData, int yStart, int yEnd)
-{
- Uint8ClampedArray* srcPixelArray = paintingData->srcPixelArray;
- Uint8ClampedArray* dstPixelArray = paintingData->dstPixelArray;
- const int width = paintingData->width;
- const int height = paintingData->height;
- const int effectWidth = width * 4;
- const int radiusX = paintingData->radiusX;
- const int radiusY = paintingData->radiusY;
-
- Vector<unsigned char> extrema;
- for (int y = yStart; y < yEnd; ++y) {
- int extremaStartY = max(0, y - radiusY);
- int extremaEndY = min(height - 1, y + radiusY);
- for (unsigned clrChannel = 0; clrChannel < 4; ++clrChannel) {
- extrema.clear();
- // Compute extremas for each columns
- for (int x = 0; x <= radiusX; ++x) {
- unsigned char columnExtrema = srcPixelArray->item(extremaStartY * effectWidth + 4 * x + clrChannel);
- for (int eY = extremaStartY + 1; eY < extremaEndY; ++eY) {
- unsigned char pixel = srcPixelArray->item(eY * effectWidth + 4 * x + clrChannel);
- if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema)
- || (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema)) {
- columnExtrema = pixel;
- }
- }
-
- extrema.append(columnExtrema);
- }
-
- // Kernel is filled, get extrema of next column
- for (int x = 0; x < width; ++x) {
- const int endX = min(x + radiusX, width - 1);
- unsigned char columnExtrema = srcPixelArray->item(extremaStartY * effectWidth + endX * 4 + clrChannel);
- for (int i = extremaStartY + 1; i <= extremaEndY; ++i) {
- unsigned char pixel = srcPixelArray->item(i * effectWidth + endX * 4 + clrChannel);
- if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema)
- || (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema))
- columnExtrema = pixel;
- }
- if (x - radiusX >= 0)
- extrema.remove(0);
- if (x + radiusX <= width)
- extrema.append(columnExtrema);
-
- unsigned char entireExtrema = extrema[0];
- for (unsigned kernelIndex = 1; kernelIndex < extrema.size(); ++kernelIndex) {
- if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && extrema[kernelIndex] <= entireExtrema)
- || (m_type == FEMORPHOLOGY_OPERATOR_DILATE && extrema[kernelIndex] >= entireExtrema))
- entireExtrema = extrema[kernelIndex];
- }
- dstPixelArray->set(y * effectWidth + 4 * x + clrChannel, entireExtrema);
- }
- }
- }
-}
-
-void FEMorphology::platformApplyWorker(PlatformApplyParameters* param)
-{
- param->filter->platformApplyGeneric(param->paintingData, param->startY, param->endY);
-}
-
-void FEMorphology::platformApply(PaintingData* paintingData)
-{
- int optimalThreadNumber = (paintingData->width * paintingData->height) / s_minimalArea;
- if (optimalThreadNumber > 1) {
- ParallelJobs<PlatformApplyParameters> parallelJobs(&WebCore::FEMorphology::platformApplyWorker, optimalThreadNumber);
- int numOfThreads = parallelJobs.numberOfJobs();
- if (numOfThreads > 1) {
- // Split the job into "jobSize"-sized jobs but there a few jobs that need to be slightly larger since
- // jobSize * jobs < total size. These extras are handled by the remainder "jobsWithExtra".
- const int jobSize = paintingData->height / numOfThreads;
- const int jobsWithExtra = paintingData->height % numOfThreads;
- int currentY = 0;
- for (int job = numOfThreads - 1; job >= 0; --job) {
- PlatformApplyParameters& param = parallelJobs.parameter(job);
- param.filter = this;
- param.startY = currentY;
- currentY += job < jobsWithExtra ? jobSize + 1 : jobSize;
- param.endY = currentY;
- param.paintingData = paintingData;
- }
- parallelJobs.execute();
- return;
- }
- // Fallback to single thread model
- }
-
- platformApplyGeneric(paintingData, 0, paintingData->height);
-}
-
-
void FEMorphology::applySoftware()
{
- FilterEffect* in = inputEffect(0);
-
- Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
- if (!dstPixelArray)
- return;
-
- setIsAlphaImage(in->isAlphaImage());
- if (m_radiusX <= 0 || m_radiusY <= 0) {
- dstPixelArray->zeroFill();
- return;
- }
-
- Filter* filter = this->filter();
- int radiusX = static_cast<int>(floorf(filter->applyHorizontalScale(m_radiusX)));
- int radiusY = static_cast<int>(floorf(filter->applyVerticalScale(m_radiusY)));
-
- IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<Uint8ClampedArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect);
-
- PaintingData paintingData;
- paintingData.srcPixelArray = srcPixelArray.get();
- paintingData.dstPixelArray = dstPixelArray;
- paintingData.width = effectDrawingRect.width();
- paintingData.height = effectDrawingRect.height();
- paintingData.radiusX = min(effectDrawingRect.width() - 1, radiusX);
- paintingData.radiusY = min(effectDrawingRect.height() - 1, radiusY);
-
- platformApply(&paintingData);
-}
-
-bool FEMorphology::applySkia()
-{
ImageBuffer* resultImage = createImageBufferResult();
if (!resultImage)
- return false;
+ return;
FilterEffect* in = inputEffect(0);
@@ -250,14 +118,14 @@ bool FEMorphology::applySkia()
SkPaint paint;
GraphicsContext* dstContext = resultImage->context();
if (m_type == FEMORPHOLOGY_OPERATOR_DILATE)
- paint.setImageFilter(new SkDilateImageFilter(radiusX, radiusY))->unref();
+ paint.setImageFilter(SkDilateImageFilter::Create(radiusX, radiusY))->unref();
else if (m_type == FEMORPHOLOGY_OPERATOR_ERODE)
- paint.setImageFilter(new SkErodeImageFilter(radiusX, radiusY))->unref();
+ paint.setImageFilter(SkErodeImageFilter::Create(radiusX, radiusY))->unref();
- dstContext->saveLayer(0, &paint);
+ SkRect bounds = SkRect::MakeWH(absolutePaintRect().width(), absolutePaintRect().height());
+ dstContext->saveLayer(&bounds, &paint);
dstContext->drawImage(image.get(), drawingRegion.location(), CompositeCopy);
dstContext->restoreLayer();
- return true;
}
PassRefPtr<SkImageFilter> FEMorphology::createImageFilter(SkiaImageFilterBuilder* builder)
@@ -267,8 +135,8 @@ PassRefPtr<SkImageFilter> FEMorphology::createImageFilter(SkiaImageFilterBuilder
SkScalar radiusY = SkFloatToScalar(filter()->applyVerticalScale(m_radiusY));
SkImageFilter::CropRect rect = getCropRect(builder->cropOffset());
if (m_type == FEMORPHOLOGY_OPERATOR_DILATE)
- return adoptRef(new SkDilateImageFilter(radiusX, radiusY, input.get(), &rect));
- return adoptRef(new SkErodeImageFilter(radiusX, radiusY, input.get(), &rect));
+ return adoptRef(SkDilateImageFilter::Create(radiusX, radiusY, input.get(), &rect));
+ return adoptRef(SkErodeImageFilter::Create(radiusX, radiusY, input.get(), &rect));
}
static TextStream& operator<<(TextStream& ts, const MorphologyOperatorType& type)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.h
index 6b596bf6ea5..6ed926a3341 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEMorphology.h
@@ -48,10 +48,9 @@ public:
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- virtual void determineAbsolutePaintRect();
virtual FloatRect mapRect(const FloatRect&, bool forward = true) OVERRIDE FINAL;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
struct PaintingData {
Uint8ClampedArray* srcPixelArray;
@@ -71,15 +70,10 @@ public:
PaintingData* paintingData;
};
- static void platformApplyWorker(PlatformApplyParameters*);
-
- inline void platformApply(PaintingData*);
- inline void platformApplyGeneric(PaintingData*, const int yStart, const int yEnd);
private:
FEMorphology(Filter*, MorphologyOperatorType, float radiusX, float radiusY);
virtual void applySoftware() OVERRIDE;
- virtual bool applySkia() OVERRIDE;
MorphologyOperatorType m_type;
float m_radiusX;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.cpp
index d9a27788890..a978882eae4 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.cpp
@@ -66,25 +66,13 @@ void FEOffset::setDy(float dy)
m_dy = dy;
}
-void FEOffset::determineAbsolutePaintRect()
-{
- FloatRect paintRect = inputEffect(0)->absolutePaintRect();
- Filter* filter = this->filter();
- paintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
- if (clipsToBounds())
- paintRect.intersect(maxEffectRect());
- else
- paintRect.unite(maxEffectRect());
- setAbsolutePaintRect(enclosingIntRect(paintRect));
-}
-
FloatRect FEOffset::mapRect(const FloatRect& rect, bool forward)
{
FloatRect result = rect;
if (forward)
- result.move(filter()->applyHorizontalScale(m_dx), filter()->applyHorizontalScale(m_dy));
+ result.move(filter()->applyHorizontalScale(m_dx), filter()->applyVerticalScale(m_dy));
else
- result.move(-filter()->applyHorizontalScale(m_dx), -filter()->applyHorizontalScale(m_dy));
+ result.move(-filter()->applyHorizontalScale(m_dx), -filter()->applyVerticalScale(m_dy));
return result;
}
@@ -109,7 +97,7 @@ PassRefPtr<SkImageFilter> FEOffset::createImageFilter(SkiaImageFilterBuilder* bu
RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
Filter* filter = this->filter();
SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
- return adoptRef(new SkOffsetImageFilter(SkFloatToScalar(filter->applyHorizontalScale(m_dx)), SkFloatToScalar(filter->applyVerticalScale(m_dy)), input.get(), &cropRect));
+ return adoptRef(SkOffsetImageFilter::Create(SkFloatToScalar(filter->applyHorizontalScale(m_dx)), SkFloatToScalar(filter->applyVerticalScale(m_dy)), input.get(), &cropRect));
}
TextStream& FEOffset::externalRepresentation(TextStream& ts, int indent) const
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.h
index 6ed388d8cb8..774497c6f53 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FEOffset.h
@@ -38,10 +38,9 @@ public:
float dy() const;
void setDy(float);
- virtual void determineAbsolutePaintRect();
virtual FloatRect mapRect(const FloatRect&, bool forward = true) OVERRIDE FINAL;
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.cpp
index 5a87f10d0d8..cc3ed427d44 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.cpp
@@ -80,6 +80,7 @@ float FESpecularLighting::specularConstant() const
bool FESpecularLighting::setSpecularConstant(float specularConstant)
{
+ specularConstant = std::max(specularConstant, 0.0f);
if (m_specularConstant == specularConstant)
return false;
m_specularConstant = specularConstant;
@@ -93,6 +94,7 @@ float FESpecularLighting::specularExponent() const
bool FESpecularLighting::setSpecularExponent(float specularExponent)
{
+ specularExponent = std::min(std::max(specularExponent, 1.0f), 128.0f);
if (m_specularExponent == specularExponent)
return false;
m_specularExponent = specularExponent;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.h
index fd33b0c086b..fd314ab8432 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FESpecularLighting.h
@@ -54,7 +54,7 @@ public:
const LightSource* lightSource() const;
void setLightSource(PassRefPtr<LightSource>);
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
FESpecularLighting(Filter*, const Color&, float, float, float, float, float, PassRefPtr<LightSource>);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.cpp
index 2e865d3141f..bcbe9fb7d80 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.cpp
@@ -29,7 +29,6 @@
#include "platform/graphics/Pattern.h"
#include "platform/graphics/UnacceleratedImageBufferSurface.h"
#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
-#include "platform/graphics/gpu/AcceleratedImageBufferSurface.h"
#include "platform/text/TextStream.h"
#include "platform/transforms/AffineTransform.h"
#include "third_party/skia/include/core/SkDevice.h"
@@ -46,6 +45,11 @@ PassRefPtr<FETile> FETile::create(Filter* filter)
return adoptRef(new FETile(filter));
}
+FloatRect FETile::mapPaintRect(const FloatRect& rect, bool forward)
+{
+ return forward ? maxEffectRect() : inputEffect(0)->maxEffectRect();
+}
+
void FETile::applySoftware()
{
FilterEffect* in = inputEffect(0);
@@ -64,25 +68,21 @@ void FETile::applySoftware()
if (in->filterEffectType() == FilterEffectTypeSourceInput) {
Filter* filter = this->filter();
tileRect = filter->absoluteFilterRegion();
- tileRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
}
OwnPtr<ImageBufferSurface> surface;
IntSize intTileSize = roundedIntSize(tileRect.size());
- if (filter()->isAccelerated()) {
- surface = adoptPtr(new AcceleratedImageBufferSurface(intTileSize));
- }
- if (!surface || !surface->isValid()) {
- surface = adoptPtr(new UnacceleratedImageBufferSurface(intTileSize));
- }
+ surface = adoptPtr(new UnacceleratedImageBufferSurface(intTileSize));
OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(surface.release());
if (!tileImage)
return;
GraphicsContext* tileImageContext = tileImage->context();
- tileImageContext->scale(FloatSize(intTileSize.width() / tileRect.width(), intTileSize.height() / tileRect.height()));
+ tileImageContext->scale(intTileSize.width() / tileRect.width(), intTileSize.height() / tileRect.height());
tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
- tileImageContext->drawImageBuffer(in->asImageBuffer(), in->absolutePaintRect().location());
+
+ if (ImageBuffer* tileImageBuffer = in->asImageBuffer())
+ tileImageContext->drawImageBuffer(tileImageBuffer, IntRect(in->absolutePaintRect().location(), tileImageBuffer->size()));
RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(CopyBackingStore), true, true);
@@ -94,11 +94,27 @@ void FETile::applySoftware()
filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()));
}
+static FloatRect getRect(FilterEffect* effect)
+{
+ FloatRect result = effect->filter()->filterRegion();
+ FloatRect boundaries = effect->effectBoundaries();
+ if (effect->hasX())
+ result.setX(boundaries.x());
+ if (effect->hasY())
+ result.setY(boundaries.y());
+ if (effect->hasWidth())
+ result.setWidth(boundaries.width());
+ if (effect->hasHeight())
+ result.setHeight(boundaries.height());
+ return result;
+}
+
PassRefPtr<SkImageFilter> FETile::createImageFilter(SkiaImageFilterBuilder* builder)
{
RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
- FloatRect srcRect = inputEffect(0) ? inputEffect(0)->effectBoundaries() : FloatRect();
- return adoptRef(new SkTileImageFilter(srcRect, effectBoundaries(), input.get()));
+ FloatRect srcRect = inputEffect(0) ? getRect(inputEffect(0)) : filter()->filterRegion();
+ FloatRect dstRect = getRect(this);
+ return adoptRef(SkTileImageFilter::Create(srcRect, dstRect, input.get()));
}
TextStream& FETile::externalRepresentation(TextStream& ts, int indent) const
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.h
index ece013c816d..5d882338ca7 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FETile.h
@@ -34,11 +34,11 @@ public:
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
+ virtual FloatRect mapPaintRect(const FloatRect&, bool forward = true) OVERRIDE FINAL;
- virtual FilterEffectType filterEffectType() const { return FilterEffectTypeTile; }
+ virtual FilterEffectType filterEffectType() const OVERRIDE { return FilterEffectTypeTile; }
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
FETile(Filter*);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.cpp
index a6a4e826182..cb123da3e2b 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.cpp
@@ -364,8 +364,6 @@ void FETurbulence::applySoftware()
PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size()));
initPaint(paintingData);
- float baseFrequencyX = 1.0f / filter()->applyHorizontalScale(1.0f / m_baseFrequencyX);
- float baseFrequencyY = 1.0f / filter()->applyVerticalScale(1.0f / m_baseFrequencyY);
int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension;
if (optimalThreadNumber > 1) {
@@ -389,8 +387,8 @@ void FETurbulence::applySoftware()
params.startY = startY;
startY += i < jobsWithExtra ? stepY + 1 : stepY;
params.endY = startY;
- params.baseFrequencyX = baseFrequencyX;
- params.baseFrequencyY = baseFrequencyY;
+ params.baseFrequencyX = m_baseFrequencyX;
+ params.baseFrequencyY = m_baseFrequencyY;
}
// Execute parallel jobs
@@ -400,44 +398,32 @@ void FETurbulence::applySoftware()
}
// Fallback to single threaded mode if there is no room for a new thread or the paint area is too small.
- fillRegion(pixelArray, paintingData, 0, absolutePaintRect().height(), baseFrequencyX, baseFrequencyY);
+ fillRegion(pixelArray, paintingData, 0, absolutePaintRect().height(), m_baseFrequencyX, m_baseFrequencyY);
}
-SkShader* FETurbulence::createShader(const IntRect& filterRegion)
+SkShader* FETurbulence::createShader()
{
- const SkISize size = SkISize::Make(filterRegion.width(), filterRegion.height());
- float baseFrequencyX = 1.0f / filter()->applyHorizontalScale(1.0f / m_baseFrequencyX);
- const float baseFrequencyY = 1.0f / filter()->applyVerticalScale(1.0f / m_baseFrequencyY);
+ const SkISize size = SkISize::Make(effectBoundaries().width(), effectBoundaries().height());
+ // Frequency should be scaled by page zoom, but not by primitiveUnits.
+ // So we apply only the transform scale (as Filter::apply*Scale() do)
+ // and not the target bounding box scale (as SVGFilter::apply*Scale()
+ // would do). Note also that we divide by the scale since this is
+ // a frequency, not a period.
+ const AffineTransform& absoluteTransform = filter()->absoluteTransform();
+ float baseFrequencyX = m_baseFrequencyX / absoluteTransform.a();
+ float baseFrequencyY = m_baseFrequencyY / absoluteTransform.d();
return (type() == FETURBULENCE_TYPE_FRACTALNOISE) ?
SkPerlinNoiseShader::CreateFractalNoise(SkFloatToScalar(baseFrequencyX),
SkFloatToScalar(baseFrequencyY), numOctaves(), SkFloatToScalar(seed()),
stitchTiles() ? &size : 0) :
- SkPerlinNoiseShader::CreateTubulence(SkFloatToScalar(baseFrequencyX),
+ SkPerlinNoiseShader::CreateTurbulence(SkFloatToScalar(baseFrequencyX),
SkFloatToScalar(baseFrequencyY), numOctaves(), SkFloatToScalar(seed()),
stitchTiles() ? &size : 0);
}
-bool FETurbulence::applySkia()
-{
- // For now, only use the skia implementation for accelerated rendering.
- if (!filter()->isAccelerated())
- return false;
-
- ImageBuffer* resultImage = createImageBufferResult();
- if (!resultImage)
- return false;
-
- const IntRect filterRegion(IntPoint::zero(), absolutePaintRect().size());
-
- SkPaint paint;
- paint.setShader(createShader(filterRegion))->unref();
- resultImage->context()->drawRect((SkRect)filterRegion, paint);
- return true;
-}
-
PassRefPtr<SkImageFilter> FETurbulence::createImageFilter(SkiaImageFilterBuilder* builder)
{
- SkAutoTUnref<SkShader> shader(createShader(IntRect()));
+ SkAutoTUnref<SkShader> shader(createShader());
SkImageFilter::CropRect rect = getCropRect(builder->cropOffset());
return adoptRef(SkRectShaderImageFilter::Create(shader, &rect));
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.h
index 6b249e454c9..f5c230b26a7 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FETurbulence.h
@@ -60,9 +60,7 @@ public:
static void fillRegionWorker(void*);
- virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
-
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
static const int s_blockSize = 256;
@@ -118,9 +116,8 @@ private:
FETurbulence(Filter*, TurbulenceType, float, float, int, float, bool);
virtual void applySoftware() OVERRIDE;
- virtual bool applySkia() OVERRIDE;
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
- SkShader* createShader(const IntRect& filterRegion);
+ SkShader* createShader();
inline void initPaint(PaintingData&);
float noise2D(int channel, PaintingData&, StitchData&, const FloatPoint&);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/Filter.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/Filter.h
index 705aa5e19e4..d16659a0aff 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/Filter.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/Filter.h
@@ -25,6 +25,7 @@
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/FloatSize.h"
#include "platform/graphics/ImageBuffer.h"
+#include "third_party/skia/include/core/SkImageFilter.h"
#include "wtf/RefCounted.h"
namespace WebCore {
@@ -33,50 +34,85 @@ class FilterEffect;
class PLATFORM_EXPORT Filter : public RefCounted<Filter> {
public:
- Filter(const AffineTransform& absoluteTransform) : m_isAccelerated(false), m_absoluteTransform(absoluteTransform) { }
+ Filter(const AffineTransform& absoluteTransform)
+ : m_absoluteTransform(absoluteTransform)
+ , m_inverseTransform(absoluteTransform.inverse())
+ {
+ // Filters can only accept scaling and translating transformations, as coordinates
+ // in most primitives are given in horizontal and vertical directions.
+ ASSERT(!absoluteTransform.b() && !absoluteTransform.c());
+ }
virtual ~Filter() { }
void setSourceImage(PassOwnPtr<ImageBuffer> sourceImage) { m_sourceImage = sourceImage; }
ImageBuffer* sourceImage() { return m_sourceImage.get(); }
- FloatSize filterResolution() const { return m_filterResolution; }
- void setFilterResolution(const FloatSize& filterResolution) { m_filterResolution = filterResolution; }
-
const AffineTransform& absoluteTransform() const { return m_absoluteTransform; }
- void setAbsoluteTransform(const AffineTransform& absoluteTransform) { m_absoluteTransform = absoluteTransform; }
- FloatPoint mapAbsolutePointToLocalPoint(const FloatPoint& point) const { return m_absoluteTransform.inverse().mapPoint(point); }
- bool isAccelerated() const { return m_isAccelerated; }
- void setIsAccelerated(bool isAccelerated) { m_isAccelerated = isAccelerated; }
+ void setAbsoluteTransform(const AffineTransform& absoluteTransform)
+ {
+ // Filters can only accept scaling and translating transformations, as coordinates
+ // in most primitives are given in horizontal and vertical directions.
+ ASSERT(!absoluteTransform.b() && !absoluteTransform.c());
+ m_absoluteTransform = absoluteTransform;
+ m_inverseTransform = absoluteTransform.inverse();
+ m_absoluteFilterRegion = m_absoluteTransform.mapRect(m_filterRegion);
+ }
+ FloatPoint mapAbsolutePointToLocalPoint(const FloatPoint& point) const { return m_inverseTransform.mapPoint(point); }
+ FloatRect mapLocalRectToAbsoluteRect(const FloatRect& rect) const { return m_absoluteTransform.mapRect(rect); }
+ FloatRect mapAbsoluteRectToLocalRect(const FloatRect& rect) const { return m_inverseTransform.mapRect(rect); }
virtual float applyHorizontalScale(float value) const
{
- float filterRegionScale = absoluteFilterRegion().isEmpty() || filterRegion().isEmpty() ?
- 1.0f : absoluteFilterRegion().width() / filterRegion().width();
- return value * m_filterResolution.width() * filterRegionScale;
+ return value * m_absoluteTransform.a();
}
virtual float applyVerticalScale(float value) const
{
- float filterRegionScale = absoluteFilterRegion().isEmpty() || filterRegion().isEmpty() ?
- 1.0f : absoluteFilterRegion().height() / filterRegion().height();
- return value * m_filterResolution.height() * filterRegionScale;
+ return value * m_absoluteTransform.d();
}
+ virtual FloatPoint3D resolve3dPoint(const FloatPoint3D& point) const { return point; }
- virtual FloatRect sourceImageRect() const = 0;
+ virtual IntRect sourceImageRect() const = 0;
FloatRect absoluteFilterRegion() const { return m_absoluteFilterRegion; }
- void setAbsoluteFilterRegion(const FloatRect& rect) { m_absoluteFilterRegion = rect; }
FloatRect filterRegion() const { return m_filterRegion; }
- void setFilterRegion(const FloatRect& rect) { m_filterRegion = rect; }
+ void setFilterRegion(const FloatRect& rect)
+ {
+ m_filterRegion = rect;
+ m_absoluteFilterRegion = m_absoluteTransform.mapRect(m_filterRegion);
+ }
+
+ // The methods enableCache() and disableCache() are temporary, and we
+ // should address the real issue inside skia, thus simplifying what the
+ // clients have to know, and can remove these.
+ // Also note that this cache should no longer be used by Blink once the
+ // NON impl-side painting path is removed.
+ void enableCache()
+ {
+ if (!m_cache)
+ m_cache = adoptRef(SkImageFilter::Cache::Create(1));
+ SkImageFilter::SetExternalCache(m_cache.get());
+ }
+
+ void disableCache()
+ {
+ SkImageFilter::SetExternalCache(0);
+ }
+
+ void removeFromCache(SkImageFilter* filter)
+ {
+ if (m_cache)
+ m_cache->remove(filter);
+ }
private:
OwnPtr<ImageBuffer> m_sourceImage;
- FloatSize m_filterResolution;
- bool m_isAccelerated;
AffineTransform m_absoluteTransform;
+ AffineTransform m_inverseTransform;
FloatRect m_absoluteFilterRegion;
FloatRect m_filterRegion;
+ RefPtr<SkImageFilter::Cache> m_cache;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.cpp
index 2b1324298ac..518173bebe3 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.cpp
@@ -28,7 +28,6 @@
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/UnacceleratedImageBufferSurface.h"
#include "platform/graphics/filters/Filter.h"
-#include "platform/graphics/gpu/AcceleratedImageBufferSurface.h"
#if HAVE(ARM_NEON_INTRINSICS)
#include <arm_neon.h>
@@ -36,6 +35,8 @@
namespace WebCore {
+static const float kMaxFilterArea = 4096 * 4096;
+
FilterEffect::FilterEffect(Filter* filter)
: m_alphaImage(false)
, m_filter(filter)
@@ -54,27 +55,49 @@ FilterEffect::~FilterEffect()
{
}
-inline bool isFilterSizeValid(IntRect rect)
+float FilterEffect::maxFilterArea()
+{
+ return kMaxFilterArea;
+}
+
+bool FilterEffect::isFilterSizeValid(const FloatRect& rect)
{
- if (rect.width() < 0 || rect.width() > kMaxFilterSize
- || rect.height() < 0 || rect.height() > kMaxFilterSize)
+ if (rect.width() < 0 || rect.height() < 0
+ || (rect.height() * rect.width() > kMaxFilterArea))
return false;
+
return true;
}
-void FilterEffect::determineAbsolutePaintRect()
+FloatRect FilterEffect::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
{
- m_absolutePaintRect = IntRect();
+ FloatRect requestedRect = originalRequestedRect;
+ // Filters in SVG clip to primitive subregion, while CSS doesn't.
+ if (m_clipsToBounds)
+ requestedRect.intersect(maxEffectRect());
+
+ // We may be called multiple times if result is used more than once. Return
+ // quickly if if nothing new is required.
+ if (absolutePaintRect().contains(enclosingIntRect(requestedRect)))
+ return requestedRect;
+
+ FloatRect inputRect = mapPaintRect(requestedRect, false);
+ FloatRect inputUnion;
unsigned size = m_inputEffects.size();
+
for (unsigned i = 0; i < size; ++i)
- m_absolutePaintRect.unite(m_inputEffects.at(i)->absolutePaintRect());
+ inputUnion.unite(m_inputEffects.at(i)->determineAbsolutePaintRect(inputRect));
+ inputUnion = mapPaintRect(inputUnion, true);
- // Filters in SVG clip to primitive subregion, while CSS doesn't.
- if (m_clipsToBounds)
- m_absolutePaintRect.intersect(enclosingIntRect(m_maxEffectRect));
- else
- m_absolutePaintRect.unite(enclosingIntRect(m_maxEffectRect));
+ if (affectsTransparentPixels() || !size) {
+ inputUnion = requestedRect;
+ } else {
+ // Rect may have inflated. Re-intersect with request.
+ inputUnion.intersect(requestedRect);
+ }
+ addAbsolutePaintRect(inputUnion);
+ return inputUnion;
}
FloatRect FilterEffect::mapRectRecursive(const FloatRect& rect)
@@ -94,7 +117,7 @@ FloatRect FilterEffect::getSourceRect(const FloatRect& destRect, const FloatRect
FloatRect sourceRect = mapRect(destRect, false);
FloatRect sourceClipRect = mapRect(destClipRect, false);
- FloatRect boundaries = effectBoundaries();
+ FloatRect boundaries = filter()->mapLocalRectToAbsoluteRect(effectBoundaries());
if (hasX())
sourceClipRect.setX(boundaries.x());
if (hasY())
@@ -136,14 +159,33 @@ FilterEffect* FilterEffect::inputEffect(unsigned number) const
return m_inputEffects.at(number).get();
}
+void FilterEffect::addAbsolutePaintRect(const FloatRect& paintRect)
+{
+ IntRect intPaintRect(enclosingIntRect(paintRect));
+ if (m_absolutePaintRect.contains(intPaintRect))
+ return;
+ intPaintRect.unite(m_absolutePaintRect);
+ // Make sure we are not holding on to a smaller rendering.
+ clearResult();
+ m_absolutePaintRect = intPaintRect;
+}
+
void FilterEffect::apply()
{
+ // Recursively determine paint rects first, so that we don't redraw images
+ // if a smaller section is requested first.
+ determineAbsolutePaintRect(maxEffectRect());
+ applyRecursive();
+}
+
+void FilterEffect::applyRecursive()
+{
if (hasResult())
return;
unsigned size = m_inputEffects.size();
for (unsigned i = 0; i < size; ++i) {
FilterEffect* in = m_inputEffects.at(i).get();
- in->apply();
+ in->applyRecursive();
if (!in->hasResult())
return;
@@ -151,20 +193,16 @@ void FilterEffect::apply()
transformResultColorSpace(in, i);
}
- determineAbsolutePaintRect();
setResultColorSpace(m_operatingColorSpace);
if (!isFilterSizeValid(m_absolutePaintRect))
return;
- if (requiresValidPreMultipliedPixels()) {
+ if (!mayProduceInvalidPreMultipliedPixels()) {
for (unsigned i = 0; i < size; ++i)
inputEffect(i)->correctFilterResultIfNeeded();
}
- if (applySkia())
- return;
-
applySoftware();
}
@@ -225,6 +263,12 @@ void FilterEffect::clearResult()
m_unmultipliedImageResult.clear();
if (m_premultipliedImageResult)
m_premultipliedImageResult.clear();
+
+ m_absolutePaintRect = IntRect();
+ for (int i = 0; i < 4; i++) {
+ filter()->removeFromCache(m_imageFilters[i].get());
+ m_imageFilters[i] = nullptr;
+ }
}
void FilterEffect::clearResultsRecursive()
@@ -246,10 +290,7 @@ ImageBuffer* FilterEffect::asImageBuffer()
if (m_imageBufferResult)
return m_imageBufferResult.get();
OwnPtr<ImageBufferSurface> surface;
- if (m_filter->isAccelerated())
- surface = adoptPtr(new AcceleratedImageBufferSurface(m_absolutePaintRect.size()));
- if (!m_filter->isAccelerated() || !surface->isValid())
- surface = adoptPtr(new UnacceleratedImageBufferSurface(m_absolutePaintRect.size()));
+ surface = adoptPtr(new UnacceleratedImageBufferSurface(m_absolutePaintRect.size()));
m_imageBufferResult = ImageBuffer::create(surface.release());
if (!m_imageBufferResult)
return 0;
@@ -387,13 +428,11 @@ void FilterEffect::copyPremultipliedImage(Uint8ClampedArray* destination, const
ImageBuffer* FilterEffect::createImageBufferResult()
{
// Only one result type is allowed.
- if (m_absolutePaintRect.isEmpty())
- return 0;
+ ASSERT(!hasResult());
+ ASSERT(isFilterSizeValid(m_absolutePaintRect));
+
OwnPtr<ImageBufferSurface> surface;
- if (m_filter->isAccelerated())
- surface = adoptPtr(new AcceleratedImageBufferSurface(m_absolutePaintRect.size()));
- if (!m_filter->isAccelerated() || !surface->isValid())
- surface = adoptPtr(new UnacceleratedImageBufferSurface(m_absolutePaintRect.size()));
+ surface = adoptPtr(new UnacceleratedImageBufferSurface(m_absolutePaintRect.size()));
m_imageBufferResult = ImageBuffer::create(surface.release());
return m_imageBufferResult.get();
}
@@ -422,6 +461,12 @@ Uint8ClampedArray* FilterEffect::createPremultipliedImageResult()
return m_premultipliedImageResult.get();
}
+Color FilterEffect::adaptColorToOperatingColorSpace(const Color& deviceColor)
+{
+ // |deviceColor| is assumed to be DeviceRGB.
+ return ColorSpaceUtilities::convertColor(deviceColor, operatingColorSpace());
+}
+
void FilterEffect::transformResultColorSpace(ColorSpace dstColorSpace)
{
if (!hasResult() || dstColorSpace == m_resultColorSpace)
@@ -448,7 +493,8 @@ TextStream& FilterEffect::externalRepresentation(TextStream& ts, int) const
FloatRect FilterEffect::determineFilterPrimitiveSubregion(DetermineSubregionFlags flags)
{
- ASSERT(filter());
+ Filter* filter = this->filter();
+ ASSERT(filter);
// FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect.
FloatRect subregion;
@@ -456,15 +502,19 @@ FloatRect FilterEffect::determineFilterPrimitiveSubregion(DetermineSubregionFlag
subregion = inputEffect(0)->determineFilterPrimitiveSubregion(flags);
for (unsigned i = 1; i < numberOfInputEffects; ++i)
subregion.unite(inputEffect(i)->determineFilterPrimitiveSubregion(flags));
- } else
- subregion = filter()->filterRegion();
+ } else {
+ subregion = filter->filterRegion();
+ }
// After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>.
if (filterEffectType() == FilterEffectTypeTile)
- subregion = filter()->filterRegion();
+ subregion = filter->filterRegion();
- if (flags & MapRectForward)
- subregion = mapRect(subregion);
+ if (flags & MapRectForward) {
+ // mapRect works on absolute rectangles.
+ subregion = filter->mapAbsoluteRectToLocalRect(mapRect(
+ filter->mapLocalRectToAbsoluteRect(subregion)));
+ }
FloatRect boundaries = effectBoundaries();
if (hasX())
@@ -478,15 +528,11 @@ FloatRect FilterEffect::determineFilterPrimitiveSubregion(DetermineSubregionFlag
setFilterPrimitiveSubregion(subregion);
- FloatRect absoluteSubregion = filter()->absoluteTransform().mapRect(subregion);
- FloatSize filterResolution = filter()->filterResolution();
- absoluteSubregion.scale(filterResolution.width(), filterResolution.height());
+ FloatRect absoluteSubregion = filter->mapLocalRectToAbsoluteRect(subregion);
// Clip every filter effect to the filter region.
if (flags & ClipToFilterRegion) {
- FloatRect absoluteScaledFilterRegion = filter()->absoluteFilterRegion();
- absoluteScaledFilterRegion.scale(filterResolution.width(), filterResolution.height());
- absoluteSubregion.intersect(absoluteScaledFilterRegion);
+ absoluteSubregion.intersect(filter->absoluteFilterRegion());
}
setMaxEffectRect(absoluteSubregion);
@@ -495,34 +541,63 @@ FloatRect FilterEffect::determineFilterPrimitiveSubregion(DetermineSubregionFlag
PassRefPtr<SkImageFilter> FilterEffect::createImageFilter(SkiaImageFilterBuilder* builder)
{
- return 0;
+ return nullptr;
+}
+
+PassRefPtr<SkImageFilter> FilterEffect::createImageFilterWithoutValidation(SkiaImageFilterBuilder* builder)
+{
+ return createImageFilter(builder);
}
SkImageFilter::CropRect FilterEffect::getCropRect(const FloatSize& cropOffset) const
{
- SkRect rect = SkRect::MakeEmpty();
+ FloatRect rect = filter()->filterRegion();
uint32_t flags = 0;
FloatRect boundaries = effectBoundaries();
- FloatSize resolution = filter()->filterResolution();
- boundaries.scale(resolution.width(), resolution.height());
boundaries.move(cropOffset);
if (hasX()) {
- rect.fLeft = boundaries.x();
+ rect.setX(boundaries.x());
flags |= SkImageFilter::CropRect::kHasLeft_CropEdge;
+ flags |= SkImageFilter::CropRect::kHasRight_CropEdge;
}
if (hasY()) {
- rect.fTop = boundaries.y();
+ rect.setY(boundaries.y());
flags |= SkImageFilter::CropRect::kHasTop_CropEdge;
+ flags |= SkImageFilter::CropRect::kHasBottom_CropEdge;
}
if (hasWidth()) {
- rect.fRight = rect.fLeft + boundaries.width();
+ rect.setWidth(boundaries.width());
flags |= SkImageFilter::CropRect::kHasRight_CropEdge;
}
if (hasHeight()) {
- rect.fBottom = rect.fTop + boundaries.height();
+ rect.setHeight(boundaries.height());
flags |= SkImageFilter::CropRect::kHasBottom_CropEdge;
}
+ rect = filter()->mapLocalRectToAbsoluteRect(rect);
return SkImageFilter::CropRect(rect, flags);
}
+static int getImageFilterIndex(ColorSpace colorSpace, bool requiresPMColorValidation)
+{
+ // Map the (colorspace, bool) tuple to an integer index as follows:
+ // 0 == linear colorspace, no PM validation
+ // 1 == device colorspace, no PM validation
+ // 2 == linear colorspace, PM validation
+ // 3 == device colorspace, PM validation
+ return (colorSpace == ColorSpaceLinearRGB ? 0x1 : 0x0) | (requiresPMColorValidation ? 0x2 : 0x0);
+}
+
+SkImageFilter* FilterEffect::getImageFilter(ColorSpace colorSpace, bool requiresPMColorValidation) const
+{
+ int index = getImageFilterIndex(colorSpace, requiresPMColorValidation);
+ return m_imageFilters[index].get();
+}
+
+void FilterEffect::setImageFilter(ColorSpace colorSpace, bool requiresPMColorValidation, PassRefPtr<SkImageFilter> imageFilter)
+{
+ int index = getImageFilterIndex(colorSpace, requiresPMColorValidation);
+ filter()->removeFromCache(m_imageFilters[index].get());
+ m_imageFilters[index] = imageFilter;
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.h
index 3f0d2c4ccf1..7e050fa2427 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.h
@@ -26,6 +26,7 @@
#include "platform/PlatformExport.h"
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/IntRect.h"
+#include "platform/graphics/Color.h"
#include "platform/graphics/ColorSpace.h"
#include "third_party/skia/include/core/SkImageFilter.h"
@@ -36,8 +37,6 @@
#include "wtf/Uint8ClampedArray.h"
#include "wtf/Vector.h"
-static const float kMaxFilterSize = 5000.0f;
-
namespace WebCore {
class Filter;
@@ -68,6 +67,9 @@ class PLATFORM_EXPORT FilterEffect : public RefCounted<FilterEffect> {
public:
virtual ~FilterEffect();
+ static bool isFilterSizeValid(const FloatRect&);
+ static float maxFilterArea();
+
void clearResult();
void clearResultsRecursive();
@@ -88,6 +90,10 @@ public:
|| m_unmultipliedImageResult
|| m_premultipliedImageResult;
}
+ inline bool hasImageFilter() const
+ {
+ return m_imageFilters[0] || m_imageFilters[1] || m_imageFilters[2] || m_imageFilters[3];
+ }
IntRect drawingRegionOfInputImage(const IntRect&) const;
IntRect requestedRegionOfInputImageData(const IntRect&) const;
@@ -97,7 +103,6 @@ public:
void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; }
IntRect absolutePaintRect() const { return m_absolutePaintRect; }
- void setAbsolutePaintRect(const IntRect& absolutePaintRect) { m_absolutePaintRect = absolutePaintRect; }
FloatRect maxEffectRect() const { return m_maxEffectRect; }
void setMaxEffectRect(const FloatRect& maxEffectRect) { m_maxEffectRect = maxEffectRect; }
@@ -110,8 +115,7 @@ public:
virtual void correctFilterResultIfNeeded() { }
virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*);
-
- virtual void determineAbsolutePaintRect();
+ virtual PassRefPtr<SkImageFilter> createImageFilterWithoutValidation(SkiaImageFilterBuilder*);
// Mapping a rect forwards determines which which destination pixels a
// given source rect would affect. Mapping a rect backwards determines
@@ -120,10 +124,19 @@ public:
// each other. For example, for FEGaussianBlur, they are the same
// transformation.
virtual FloatRect mapRect(const FloatRect& rect, bool forward = true) { return rect; }
+ // A version of the above that is used for calculating paint rects. We can't
+ // use mapRect above for that, because that is also used for calculating effect
+ // regions for CSS filters and has undesirable effects for tile and
+ // displacement map.
+ virtual FloatRect mapPaintRect(const FloatRect& rect, bool forward)
+ {
+ return mapRect(rect, forward);
+ }
FloatRect mapRectRecursive(const FloatRect&);
// This is a recursive version of a backwards mapRect(), which also takes
// into account the filter primitive subregion of each effect.
+ // Note: This works in absolute coordinates!
FloatRect getSourceRect(const FloatRect& destRect, const FloatRect& clipRect);
virtual FilterEffectType filterEffectType() const { return FilterEffectTypeUnknown; }
@@ -165,25 +178,35 @@ public:
void transformResultColorSpace(ColorSpace);
FloatRect determineFilterPrimitiveSubregion(DetermineSubregionFlags = DetermineSubregionNone);
+ void determineAllAbsolutePaintRects();
+
+ virtual FloatRect determineAbsolutePaintRect(const FloatRect& requestedAbsoluteRect);
+ virtual bool affectsTransparentPixels() { return false; }
+
+ // Return false if the filter will only operate correctly on valid RGBA values, with
+ // alpha in [0,255] and each color component in [0, alpha].
+ virtual bool mayProduceInvalidPreMultipliedPixels() { return false; }
+
+ SkImageFilter* getImageFilter(ColorSpace, bool requiresPMColorValidation) const;
+ void setImageFilter(ColorSpace, bool requiresPMColorValidation, PassRefPtr<SkImageFilter>);
protected:
FilterEffect(Filter*);
-
ImageBuffer* createImageBufferResult();
Uint8ClampedArray* createUnmultipliedImageResult();
Uint8ClampedArray* createPremultipliedImageResult();
- // Return true if the filter will only operate correctly on valid RGBA values, with
- // alpha in [0,255] and each color component in [0, alpha].
- virtual bool requiresValidPreMultipliedPixels() { return true; }
+ Color adaptColorToOperatingColorSpace(const Color& deviceColor);
// If a pre-multiplied image, check every pixel for validity and correct if necessary.
void forceValidPreMultipliedPixels();
SkImageFilter::CropRect getCropRect(const FloatSize& cropOffset) const;
+ void addAbsolutePaintRect(const FloatRect& absolutePaintRect);
+
private:
+ void applyRecursive();
virtual void applySoftware() = 0;
- virtual bool applySkia() { return false; }
inline void copyImageBytes(Uint8ClampedArray* source, Uint8ClampedArray* destination, const IntRect&);
@@ -221,6 +244,8 @@ private:
ColorSpace m_operatingColorSpace;
ColorSpace m_resultColorSpace;
+
+ RefPtr<SkImageFilter> m_imageFilters[4];
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperation.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperation.h
index ddc69dd3dde..b0559ddb0fa 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperation.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperation.h
@@ -54,8 +54,6 @@ public:
CONTRAST,
BLUR,
DROP_SHADOW,
- CUSTOM,
- VALIDATED_CUSTOM,
NONE
};
@@ -72,8 +70,6 @@ public:
case CONTRAST:
case BLUR:
case DROP_SHADOW:
- case CUSTOM:
- case VALIDATED_CUSTOM:
return true;
case REFERENCE:
return false;
@@ -115,16 +111,16 @@ private:
class PLATFORM_EXPORT ReferenceFilterOperation : public FilterOperation {
public:
- static PassRefPtr<ReferenceFilterOperation> create(const String& url, const String& fragment)
+ static PassRefPtr<ReferenceFilterOperation> create(const String& url, const AtomicString& fragment)
{
return adoptRef(new ReferenceFilterOperation(url, fragment));
}
- virtual bool affectsOpacity() const { return true; }
- virtual bool movesPixels() const { return true; }
+ virtual bool affectsOpacity() const OVERRIDE { return true; }
+ virtual bool movesPixels() const OVERRIDE { return true; }
const String& url() const { return m_url; }
- const String& fragment() const { return m_fragment; }
+ const AtomicString& fragment() const { return m_fragment; }
ReferenceFilter* filter() const { return m_filter.get(); }
void setFilter(PassRefPtr<ReferenceFilter> filter) { m_filter = filter; }
@@ -133,10 +129,10 @@ private:
virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE
{
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
- virtual bool operator==(const FilterOperation& o) const
+ virtual bool operator==(const FilterOperation& o) const OVERRIDE
{
if (!isSameType(o))
return false;
@@ -144,7 +140,7 @@ private:
return m_url == other->m_url;
}
- ReferenceFilterOperation(const String& url, const String& fragment)
+ ReferenceFilterOperation(const String& url, const AtomicString& fragment)
: FilterOperation(REFERENCE)
, m_url(url)
, m_fragment(fragment)
@@ -152,7 +148,7 @@ private:
}
String m_url;
- String m_fragment;
+ AtomicString m_fragment;
RefPtr<ReferenceFilter> m_filter;
};
@@ -172,7 +168,7 @@ public:
private:
virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
- virtual bool operator==(const FilterOperation& o) const
+ virtual bool operator==(const FilterOperation& o) const OVERRIDE
{
if (!isSameType(o))
return false;
@@ -207,12 +203,12 @@ public:
double amount() const { return m_amount; }
- virtual bool affectsOpacity() const { return m_type == OPACITY; }
+ virtual bool affectsOpacity() const OVERRIDE { return m_type == OPACITY; }
private:
virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
- virtual bool operator==(const FilterOperation& o) const
+ virtual bool operator==(const FilterOperation& o) const OVERRIDE
{
if (!isSameType(o))
return false;
@@ -239,20 +235,20 @@ DEFINE_TYPE_CASTS(BasicComponentTransferFilterOperation, FilterOperation, op, is
class PLATFORM_EXPORT BlurFilterOperation : public FilterOperation {
public:
- static PassRefPtr<BlurFilterOperation> create(Length stdDeviation)
+ static PassRefPtr<BlurFilterOperation> create(const Length& stdDeviation)
{
return adoptRef(new BlurFilterOperation(stdDeviation));
}
- Length stdDeviation() const { return m_stdDeviation; }
+ const Length& stdDeviation() const { return m_stdDeviation; }
- virtual bool affectsOpacity() const { return true; }
- virtual bool movesPixels() const { return true; }
+ virtual bool affectsOpacity() const OVERRIDE { return true; }
+ virtual bool movesPixels() const OVERRIDE { return true; }
private:
virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
- virtual bool operator==(const FilterOperation& o) const
+ virtual bool operator==(const FilterOperation& o) const OVERRIDE
{
if (!isSameType(o))
return false;
@@ -260,7 +256,7 @@ private:
return m_stdDeviation == other->m_stdDeviation;
}
- BlurFilterOperation(Length stdDeviation)
+ BlurFilterOperation(const Length& stdDeviation)
: FilterOperation(BLUR)
, m_stdDeviation(stdDeviation)
{
@@ -284,13 +280,13 @@ public:
int stdDeviation() const { return m_stdDeviation; }
Color color() const { return m_color; }
- virtual bool affectsOpacity() const { return true; }
- virtual bool movesPixels() const { return true; }
+ virtual bool affectsOpacity() const OVERRIDE { return true; }
+ virtual bool movesPixels() const OVERRIDE { return true; }
private:
virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
- virtual bool operator==(const FilterOperation& o) const
+ virtual bool operator==(const FilterOperation& o) const OVERRIDE
{
if (!isSameType(o))
return false;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.cpp
index d2692bd3167..08c8709ffab 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.cpp
@@ -34,14 +34,12 @@ namespace WebCore {
static inline IntSize outsetSizeForBlur(float stdDeviation)
{
- unsigned kernelSizeX = 0;
- unsigned kernelSizeY = 0;
- FEGaussianBlur::calculateUnscaledKernelSize(kernelSizeX, kernelSizeY, stdDeviation, stdDeviation);
+ IntSize kernelSize = FEGaussianBlur::calculateUnscaledKernelSize(FloatPoint(stdDeviation, stdDeviation));
IntSize outset;
// We take the half kernel size and multiply it with three, because we run box blur three times.
- outset.setWidth(3 * kernelSizeX * 0.5f);
- outset.setHeight(3 * kernelSizeY * 0.5f);
+ outset.setWidth(3 * kernelSize.width() * 0.5f);
+ outset.setHeight(3 * kernelSize.height() * 0.5f);
return outset;
}
@@ -90,16 +88,6 @@ bool FilterOperations::canInterpolateWith(const FilterOperations& other) const
return true;
}
-bool FilterOperations::hasCustomFilter() const
-{
- for (size_t i = 0; i < m_operations.size(); ++i) {
- FilterOperation::OperationType type = m_operations.at(i)->type();
- if (type == FilterOperation::CUSTOM || type == FilterOperation::VALIDATED_CUSTOM)
- return true;
- }
- return false;
-}
-
bool FilterOperations::hasReferenceFilter() const
{
for (size_t i = 0; i < m_operations.size(); ++i) {
@@ -160,12 +148,6 @@ FilterOutsets FilterOperations::outsets() const
}
break;
}
- case FilterOperation::CUSTOM:
- case FilterOperation::VALIDATED_CUSTOM: {
- // FIXME: Need to include the filter margins here.
- // https://bugs.webkit.org/show_bug.cgi?id=71400
- break;
- }
default:
break;
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.h
index c220b828adb..4413b1d868b 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperations.h
@@ -70,7 +70,6 @@ public:
bool hasFilterThatAffectsOpacity() const;
bool hasFilterThatMovesPixels() const;
- bool hasCustomFilter() const;
bool hasReferenceFilter() const;
private:
Vector<RefPtr<FilterOperation> > m_operations;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/SharedGraphicsContext3D.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperationsTest.cpp
index 47ace4a032a..93bcf28fe1f 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/gpu/SharedGraphicsContext3D.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/FilterOperationsTest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,27 +23,39 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SharedGraphicsContext3D_h
-#define SharedGraphicsContext3D_h
+#include "config.h"
+#include "platform/graphics/filters/FilterOperations.h"
-#include "platform/PlatformExport.h"
-#include "platform/graphics/GraphicsContext3D.h"
-#include "wtf/RefCounted.h"
-#include "wtf/RefPtr.h"
+#include <gtest/gtest.h>
-namespace WebCore {
+using namespace WebCore;
+using namespace blink;
-class PLATFORM_EXPORT SharedGraphicsContext3D {
-public:
- // The caller may ref this pointer, and hang onto it as long as they like.
- // However, the context should be checked periodically to determine if it
- // has been lost. The easiest way to do that is to simply call this
- // function again. Note that the return value may be 0 if the
- // GPU is unavailable.
- static PassRefPtr<GraphicsContext3D> get();
-};
+namespace {
+TEST(FilterOperationsTest, getOutsetsBlur)
+{
+ FilterOperations ops;
+ ops.operations().append(BlurFilterOperation::create(Length(20.0, WebCore::Fixed)));
+ EXPECT_TRUE(ops.hasOutsets());
+ FilterOutsets outsets = ops.outsets();
+ EXPECT_EQ(57, outsets.top());
+ EXPECT_EQ(57, outsets.right());
+ EXPECT_EQ(57, outsets.bottom());
+ EXPECT_EQ(57, outsets.left());
}
-#endif // SharedGraphicsContext3D_h
+TEST(FilterOperationsTest, getOutsetsDropShadow)
+{
+ FilterOperations ops;
+ ops.operations().append(DropShadowFilterOperation::create(IntPoint(3, 8), 20, Color(1, 2, 3)));
+ EXPECT_TRUE(ops.hasOutsets());
+ FilterOutsets outsets = ops.outsets();
+ EXPECT_EQ(49, outsets.top());
+ EXPECT_EQ(60, outsets.right());
+ EXPECT_EQ(65, outsets.bottom());
+ EXPECT_EQ(54, outsets.left());
+}
+
+}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/ImageFilterBuilderTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/ImageFilterBuilderTest.cpp
new file mode 100644
index 00000000000..5c131e9899b
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/ImageFilterBuilderTest.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2013 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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"
+
+#include "SkImageFilter.h"
+#include "platform/graphics/filters/FEBlend.h"
+#include "platform/graphics/filters/FEGaussianBlur.h"
+#include "platform/graphics/filters/FEMerge.h"
+#include "platform/graphics/filters/FilterOperations.h"
+#include "platform/graphics/filters/ReferenceFilter.h"
+#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
+#include "platform/graphics/filters/SourceGraphic.h"
+#include <gtest/gtest.h>
+
+using testing::Test;
+using namespace WebCore;
+
+class ImageFilterBuilderTest : public Test {
+protected:
+ void colorSpaceTest()
+ {
+ // Build filter tree
+ RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create();
+
+ // Add a dummy source graphic input
+ RefPtr<FilterEffect> sourceEffect = referenceFilter->sourceGraphic();
+ sourceEffect->setOperatingColorSpace(ColorSpaceDeviceRGB);
+
+ // Add a blur effect (with input : source)
+ RefPtr<FilterEffect> blurEffect =
+ FEGaussianBlur::create(referenceFilter.get(), 3.0f, 3.0f);
+ blurEffect->setOperatingColorSpace(ColorSpaceLinearRGB);
+ blurEffect->inputEffects().append(sourceEffect);
+
+ // Add a blend effect (with inputs : blur, source)
+ RefPtr<FilterEffect> blendEffect =
+ FEBlend::create(referenceFilter.get(), FEBLEND_MODE_NORMAL);
+ blendEffect->setOperatingColorSpace(ColorSpaceDeviceRGB);
+ FilterEffectVector& blendInputs = blendEffect->inputEffects();
+ blendInputs.reserveCapacity(2);
+ blendInputs.append(sourceEffect);
+ blendInputs.append(blurEffect);
+
+ // Add a merge effect (with inputs : blur, blend)
+ RefPtr<FilterEffect> mergeEffect = FEMerge::create(referenceFilter.get());
+ mergeEffect->setOperatingColorSpace(ColorSpaceLinearRGB);
+ FilterEffectVector& mergeInputs = mergeEffect->inputEffects();
+ mergeInputs.reserveCapacity(2);
+ mergeInputs.append(blurEffect);
+ mergeInputs.append(blendEffect);
+ referenceFilter->setLastEffect(mergeEffect);
+
+ // Get SkImageFilter resulting tree
+ SkiaImageFilterBuilder builder;
+ RefPtr<SkImageFilter> filter = builder.build(referenceFilter->lastEffect(), ColorSpaceDeviceRGB);
+
+ // Let's check that the resulting tree looks like this :
+ // ColorSpace (Linear->Device) : CS (L->D)
+ // |
+ // Merge (L)
+ // | |
+ // | CS (D->L)
+ // | |
+ // | Blend (D)
+ // | / |
+ // | CS (L->D) |
+ // | / |
+ // Blur (L) |
+ // \ |
+ // CS (D->L) |
+ // \ |
+ // Source Graphic (D)
+
+ EXPECT_EQ(filter->countInputs(), 1); // Should be CS (L->D)
+ SkImageFilter* child = filter->getInput(0); // Should be Merge
+ EXPECT_EQ(child->asColorFilter(0), false);
+ EXPECT_EQ(child->countInputs(), 2);
+ child = child->getInput(1); // Should be CS (D->L)
+ EXPECT_EQ(child->asColorFilter(0), true);
+ EXPECT_EQ(child->countInputs(), 1);
+ child = child->getInput(0); // Should be Blend
+ EXPECT_EQ(child->asColorFilter(0), false);
+ EXPECT_EQ(child->countInputs(), 2);
+ child = child->getInput(0); // Should be CS (L->D)
+ EXPECT_EQ(child->asColorFilter(0), true);
+ EXPECT_EQ(child->countInputs(), 1);
+ child = child->getInput(0); // Should be Blur
+ EXPECT_EQ(child->asColorFilter(0), false);
+ EXPECT_EQ(child->countInputs(), 1);
+ child = child->getInput(0); // Should be CS (D->L)
+ EXPECT_EQ(child->asColorFilter(0), true);
+ EXPECT_EQ(child->countInputs(), 1);
+ }
+};
+
+namespace {
+
+TEST_F(ImageFilterBuilderTest, testColorSpace)
+{
+ colorSpaceTest();
+}
+
+} // namespace
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/LightSource.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/LightSource.h
index 255f66935b1..ecd9271c408 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/LightSource.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/LightSource.h
@@ -57,7 +57,6 @@ public:
FloatPoint3D privateColorVector;
float coneCutOffLimit;
float coneFullLight;
- int specularExponent;
};
LightSource(LightType type)
@@ -69,10 +68,12 @@ public:
LightType type() const { return m_type; }
virtual TextStream& externalRepresentation(TextStream&) const = 0;
- virtual void initPaintingData(PaintingData&) = 0;
+ virtual PassRefPtr<LightSource> create(const FloatPoint3D& scale, const FloatSize& offset) const = 0;
+
+ virtual void initPaintingData(PaintingData&) const = 0;
// z is a float number, since it is the alpha value scaled by a user
// specified "surfaceScale" constant, which type is <number> in the SVG standard
- virtual void updatePaintingData(PaintingData&, int x, int y, float z) = 0;
+ virtual void updatePaintingData(PaintingData&, int x, int y, float z) const = 0;
virtual bool setAzimuth(float) { return false; }
virtual bool setElevation(float) { return false; }
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/ParallelJobs.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/ParallelJobs.h
index 17909017bc6..5c3d17f050a 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/ParallelJobs.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/ParallelJobs.h
@@ -64,9 +64,10 @@ public:
ParallelJobs(WorkerFunction func, size_t requestedJobNumber)
: m_func(func)
{
- m_parameters.grow(requestedJobNumber);
+ size_t numberOfJobs = std::max(static_cast<size_t>(2), std::min(requestedJobNumber, blink::Platform::current()->numberOfProcessors()));
+ m_parameters.grow(numberOfJobs);
// The main thread can execute one job, so only create requestJobNumber - 1 threads.
- for (size_t i = 0; i < requestedJobNumber - 1; ++i) {
+ for (size_t i = 0; i < numberOfJobs - 1; ++i) {
OwnPtr<blink::WebThread> thread = adoptPtr(blink::Platform::current()->createThread("Unfortunate parallel worker"));
m_threads.append(thread.release());
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.cpp
index c88c2ea4b19..5acacbc43c4 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.cpp
@@ -35,11 +35,11 @@
namespace WebCore {
-void PointLightSource::initPaintingData(PaintingData&)
+void PointLightSource::initPaintingData(PaintingData&) const
{
}
-void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z) const
{
paintingData.lightVector.setX(m_position.x() - x);
paintingData.lightVector.setY(m_position.y() - y);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.h
index 6638e89ede8..112f0168e7a 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/PointLightSource.h
@@ -34,15 +34,21 @@ public:
return adoptRef(new PointLightSource(position));
}
+ virtual PassRefPtr<LightSource> create(const FloatPoint3D& scale, const FloatSize& offset) const OVERRIDE
+ {
+ FloatPoint3D position(m_position.x() * scale.x() - offset.width(), m_position.y() * scale.y() - offset.height(), m_position.z() * scale.z());
+ return adoptRef(new PointLightSource(position));
+ }
+
const FloatPoint3D& position() const { return m_position; }
virtual bool setX(float) OVERRIDE;
virtual bool setY(float) OVERRIDE;
virtual bool setZ(float) OVERRIDE;
- virtual void initPaintingData(PaintingData&);
- virtual void updatePaintingData(PaintingData&, int x, int y, float z);
+ virtual void initPaintingData(PaintingData&) const OVERRIDE;
+ virtual void updatePaintingData(PaintingData&, int x, int y, float z) const OVERRIDE;
- virtual TextStream& externalRepresentation(TextStream&) const;
+ virtual TextStream& externalRepresentation(TextStream&) const OVERRIDE;
private:
PointLightSource(const FloatPoint3D& position)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.cpp
index 3367d7ce836..9a3788b7e65 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.cpp
@@ -41,8 +41,6 @@ ReferenceFilter::ReferenceFilter()
: Filter(AffineTransform())
, m_sourceGraphic(SourceGraphic::create(this))
{
- // FIXME: This should come from the filter DOM node's filterRes attribute.
- setFilterResolution(FloatSize(1, 1));
}
void ReferenceFilter::setLastEffect(PassRefPtr<FilterEffect> effect)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.h
index bc9fa3159ef..450490d58e2 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/ReferenceFilter.h
@@ -48,7 +48,7 @@ public:
return adoptRef(new ReferenceFilter());
}
- virtual FloatRect sourceImageRect() const { return FloatRect(); };
+ virtual IntRect sourceImageRect() const OVERRIDE { return IntRect(); };
void setLastEffect(PassRefPtr<FilterEffect>);
FilterEffect* lastEffect() const { return m_lastEffect.get(); }
@@ -57,7 +57,7 @@ public:
private:
ReferenceFilter();
- ~ReferenceFilter();
+ virtual ~ReferenceFilter();
RefPtr<SourceGraphic> m_sourceGraphic;
RefPtr<FilterEffect> m_lastEffect;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.cpp
index abbaf2bba59..5c6404c6c12 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.cpp
@@ -30,26 +30,24 @@
#include "SkColorFilterImageFilter.h"
#include "SkColorMatrixFilter.h"
#include "SkDropShadowImageFilter.h"
+#include "SkMatrixImageFilter.h"
#include "SkTableColorFilter.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/filters/FilterEffect.h"
#include "platform/graphics/filters/FilterOperations.h"
#include "platform/graphics/filters/SourceGraphic.h"
+#include "platform/graphics/skia/SkiaUtils.h"
#include "public/platform/WebPoint.h"
-namespace {
+namespace WebCore {
-PassRefPtr<SkImageFilter> createMatrixImageFilter(SkScalar matrix[20], SkImageFilter* input)
+SkiaImageFilterBuilder::SkiaImageFilterBuilder()
+ : m_context(0)
{
- RefPtr<SkColorFilter> colorFilter(adoptRef(new SkColorMatrixFilter(matrix)));
- return adoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), input));
}
-};
-
-namespace WebCore {
-
-SkiaImageFilterBuilder::SkiaImageFilterBuilder()
+SkiaImageFilterBuilder::SkiaImageFilterBuilder(GraphicsContext* context)
+ : m_context(context)
{
}
@@ -57,22 +55,23 @@ SkiaImageFilterBuilder::~SkiaImageFilterBuilder()
{
}
-PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::build(FilterEffect* effect, ColorSpace colorSpace)
+PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::build(FilterEffect* effect, ColorSpace colorSpace, bool destinationRequiresValidPreMultipliedPixels)
{
if (!effect)
- return 0;
-
- FilterColorSpacePair key(effect, colorSpace);
- FilterBuilderHashMap::iterator it = m_map.find(key);
- if (it != m_map.end()) {
- return it->value;
- } else {
- // Note that we may still need the color transform even if the filter is null
- RefPtr<SkImageFilter> origFilter = effect->createImageFilter(this);
- RefPtr<SkImageFilter> filter = transformColorSpace(origFilter.get(), effect->operatingColorSpace(), colorSpace);
- m_map.set(key, filter);
- return filter.release();
- }
+ return nullptr;
+
+ bool requiresPMColorValidation = effect->mayProduceInvalidPreMultipliedPixels() && destinationRequiresValidPreMultipliedPixels;
+
+ if (SkImageFilter* filter = effect->getImageFilter(colorSpace, requiresPMColorValidation))
+ return filter;
+
+ // Note that we may still need the color transform even if the filter is null
+ RefPtr<SkImageFilter> origFilter = requiresPMColorValidation ? effect->createImageFilter(this) : effect->createImageFilterWithoutValidation(this);
+ RefPtr<SkImageFilter> filter = transformColorSpace(origFilter.get(), effect->operatingColorSpace(), colorSpace);
+ effect->setImageFilter(colorSpace, requiresPMColorValidation, filter.get());
+ if (filter.get() != origFilter.get())
+ effect->setImageFilter(effect->operatingColorSpace(), requiresPMColorValidation, origFilter.get());
+ return filter.release();
}
PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::transformColorSpace(
@@ -91,12 +90,7 @@ bool SkiaImageFilterBuilder::buildFilterOperations(const FilterOperations& opera
return false;
ColorSpace currentColorSpace = ColorSpaceDeviceRGB;
-
- RefPtr<SkImageFilter> noopFilter;
- SkScalar matrix[20];
- memset(matrix, 0, 20 * sizeof(SkScalar));
- matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f;
- noopFilter = createMatrixImageFilter(matrix, 0);
+ SkImageFilter* const nullFilter = 0;
for (size_t i = 0; i < operations.size(); ++i) {
const FilterOperation& op = *operations.at(i);
@@ -106,21 +100,22 @@ bool SkiaImageFilterBuilder::buildFilterOperations(const FilterOperations& opera
ReferenceFilter* referenceFilter = toReferenceFilterOperation(op).filter();
if (referenceFilter && referenceFilter->lastEffect()) {
FilterEffect* filterEffect = referenceFilter->lastEffect();
- // Link SourceGraphic to a noop filter that serves as a placholder for
- // the previous filter in the chain. We don't know what color space the
- // interior nodes will request, so we have to populate the map with both
- // options. (Only one of these will actually have a color transform on it.)
- FilterColorSpacePair deviceKey(referenceFilter->sourceGraphic(), ColorSpaceDeviceRGB);
- FilterColorSpacePair linearKey(referenceFilter->sourceGraphic(), ColorSpaceLinearRGB);
- m_map.set(deviceKey, transformColorSpace(noopFilter.get(), currentColorSpace, ColorSpaceDeviceRGB));
- m_map.set(linearKey, transformColorSpace(noopFilter.get(), currentColorSpace, ColorSpaceLinearRGB));
+ // Prepopulate SourceGraphic with two image filters: one with a null image
+ // filter, and the other with a colorspace conversion filter.
+ // We don't know what color space the interior nodes will request, so we have to
+ // initialize SourceGraphic with both options.
+ // Since we know SourceGraphic is always PM-valid, we also use
+ // these for the PM-validated options.
+ RefPtr<SkImageFilter> deviceFilter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceDeviceRGB);
+ RefPtr<SkImageFilter> linearFilter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceLinearRGB);
+ FilterEffect* sourceGraphic = referenceFilter->sourceGraphic();
+ sourceGraphic->setImageFilter(ColorSpaceDeviceRGB, false, deviceFilter.get());
+ sourceGraphic->setImageFilter(ColorSpaceLinearRGB, false, linearFilter.get());
+ sourceGraphic->setImageFilter(ColorSpaceDeviceRGB, true, deviceFilter.get());
+ sourceGraphic->setImageFilter(ColorSpaceLinearRGB, true, linearFilter.get());
currentColorSpace = filterEffect->operatingColorSpace();
filter = SkiaImageFilterBuilder::build(filterEffect, currentColorSpace);
- // We might have no reference to the SourceGraphic's Skia filter now, so make
- // sure we don't keep it in the map anymore.
- m_map.remove(deviceKey);
- m_map.remove(linearKey);
filters->appendReferenceFilter(filter.get());
}
break;
@@ -181,21 +176,21 @@ bool SkiaImageFilterBuilder::buildFilterOperations(const FilterOperations& opera
filters->appendDropShadowFilter(blink::WebPoint(drop.x(), drop.y()), drop.stdDeviation(), drop.color().rgb());
break;
}
- case FilterOperation::VALIDATED_CUSTOM:
- case FilterOperation::CUSTOM:
- return false; // Not supported.
case FilterOperation::NONE:
break;
}
}
if (currentColorSpace != ColorSpaceDeviceRGB) {
// Transform to device color space at the end of processing, if required
- RefPtr<SkImageFilter> filter;
- filter = transformColorSpace(noopFilter.get(), currentColorSpace, ColorSpaceDeviceRGB);
- if (filter != noopFilter)
- filters->appendReferenceFilter(filter.get());
+ RefPtr<SkImageFilter> filter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceDeviceRGB);
+ filters->appendReferenceFilter(filter.get());
}
return true;
}
+PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::buildTransform(const AffineTransform& transform, SkImageFilter* input)
+{
+ return adoptRef(SkMatrixImageFilter::Create(affineTransformToSkMatrix(transform), SkPaint::kHigh_FilterLevel, input));
+}
+
};
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.h
index 33adf2026e6..a44280b181d 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/SkiaImageFilterBuilder.h
@@ -30,46 +30,37 @@
#include "platform/geometry/FloatSize.h"
#include "platform/graphics/ColorSpace.h"
#include "public/platform/WebFilterOperations.h"
-#include "wtf/HashMap.h"
class SkImageFilter;
namespace WebCore {
+class AffineTransform;
class FilterEffect;
class FilterOperations;
+class GraphicsContext;
class PLATFORM_EXPORT SkiaImageFilterBuilder {
public:
SkiaImageFilterBuilder();
+ explicit SkiaImageFilterBuilder(GraphicsContext*);
~SkiaImageFilterBuilder();
- PassRefPtr<SkImageFilter> build(FilterEffect*, ColorSpace);
+ PassRefPtr<SkImageFilter> build(FilterEffect*, ColorSpace, bool requiresPMColorValidation = true);
bool buildFilterOperations(const FilterOperations&, blink::WebFilterOperations*);
+ PassRefPtr<SkImageFilter> buildTransform(const AffineTransform&, SkImageFilter* input);
PassRefPtr<SkImageFilter> transformColorSpace(
SkImageFilter* input, ColorSpace srcColorSpace, ColorSpace dstColorSpace);
void setCropOffset(const FloatSize& cropOffset) { m_cropOffset = cropOffset; };
FloatSize cropOffset() { return m_cropOffset; }
+ GraphicsContext* context() { return m_context; }
private:
- typedef std::pair<FilterEffect*, ColorSpace> FilterColorSpacePair;
- typedef HashMap<FilterColorSpacePair, RefPtr<SkImageFilter> > FilterBuilderHashMap;
- FilterBuilderHashMap m_map;
FloatSize m_cropOffset;
+ GraphicsContext* m_context;
};
} // namespace WebCore
-namespace WTF {
-
-template<> struct DefaultHash<WebCore::FilterEffect*> {
- typedef PtrHash<WebCore::FilterEffect*> Hash;
-};
-template<> struct DefaultHash<WebCore::ColorSpace> {
- typedef IntHash<unsigned> Hash;
-};
-
-} // namespace WTF
-
#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.cpp
index 1a1df1ba8bb..f00370fbef2 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.cpp
@@ -25,6 +25,8 @@
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/filters/Filter.h"
#include "platform/text/TextStream.h"
+#include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
+#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
#include "wtf/StdLibExtras.h"
#include "wtf/text/WTFString.h"
@@ -41,12 +43,12 @@ const AtomicString& SourceAlpha::effectName()
return s_effectName;
}
-void SourceAlpha::determineAbsolutePaintRect()
+FloatRect SourceAlpha::determineAbsolutePaintRect(const FloatRect& requestedRect)
{
- Filter* filter = this->filter();
- FloatRect paintRect = filter->sourceImageRect();
- paintRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
- setAbsolutePaintRect(enclosingIntRect(paintRect));
+ FloatRect srcRect = filter()->sourceImageRect();
+ srcRect.intersect(requestedRect);
+ addAbsolutePaintRect(srcRect);
+ return srcRect;
}
void SourceAlpha::applySoftware()
@@ -61,7 +63,25 @@ void SourceAlpha::applySoftware()
FloatRect imageRect(FloatPoint(), absolutePaintRect().size());
GraphicsContext* filterContext = resultImage->context();
filterContext->fillRect(imageRect, Color::black);
- filterContext->drawImageBuffer(filter->sourceImage(), IntPoint(), CompositeDestinationIn);
+
+ IntRect srcRect = filter->sourceImageRect();
+ if (ImageBuffer* sourceImageBuffer = filter->sourceImage()) {
+ filterContext->drawImageBuffer(sourceImageBuffer,
+ FloatRect(IntPoint(srcRect.location() - absolutePaintRect().location()), sourceImageBuffer->size()),
+ 0, CompositeDestinationIn);
+ }
+}
+
+PassRefPtr<SkImageFilter> SourceAlpha::createImageFilter(SkiaImageFilterBuilder* builder)
+{
+ SkScalar matrix[20] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, SK_Scalar1, 0
+ };
+ RefPtr<SkColorFilter> colorFilter(adoptRef(SkColorMatrixFilter::Create(matrix)));
+ return adoptRef(SkColorFilterImageFilter::Create(colorFilter.get()));
}
TextStream& SourceAlpha::externalRepresentation(TextStream& ts, int indent) const
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.h
index 519a31af32f..ee1de7f5379 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceAlpha.h
@@ -32,11 +32,12 @@ public:
static const AtomicString& effectName();
- virtual void determineAbsolutePaintRect();
+ virtual FloatRect determineAbsolutePaintRect(const FloatRect& requestedRect) OVERRIDE;
- virtual FilterEffectType filterEffectType() const { return FilterEffectTypeSourceInput; }
+ virtual FilterEffectType filterEffectType() const OVERRIDE { return FilterEffectTypeSourceInput; }
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
+ virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) OVERRIDE;
private:
SourceAlpha(Filter* filter)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.cpp
index c1d69768c04..f9c1195e5bc 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.cpp
@@ -40,12 +40,12 @@ const AtomicString& SourceGraphic::effectName()
return s_effectName;
}
-void SourceGraphic::determineAbsolutePaintRect()
+FloatRect SourceGraphic::determineAbsolutePaintRect(const FloatRect& requestedRect)
{
- Filter* filter = this->filter();
- FloatRect paintRect = filter->sourceImageRect();
- paintRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
- setAbsolutePaintRect(enclosingIntRect(paintRect));
+ FloatRect srcRect = filter()->sourceImageRect();
+ srcRect.intersect(requestedRect);
+ addAbsolutePaintRect(srcRect);
+ return srcRect;
}
void SourceGraphic::applySoftware()
@@ -55,7 +55,11 @@ void SourceGraphic::applySoftware()
if (!resultImage || !filter->sourceImage())
return;
- resultImage->context()->drawImageBuffer(filter->sourceImage(), IntPoint());
+ IntRect srcRect = filter->sourceImageRect();
+ if (ImageBuffer* sourceImageBuffer = filter->sourceImage()) {
+ resultImage->context()->drawImageBuffer(sourceImageBuffer,
+ FloatRect(IntPoint(srcRect.location() - absolutePaintRect().location()), sourceImageBuffer->size()));
+ }
}
TextStream& SourceGraphic::externalRepresentation(TextStream& ts, int indent) const
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.h
index eeeae633f77..582ab51e722 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/SourceGraphic.h
@@ -33,11 +33,11 @@ public:
static const AtomicString& effectName();
- virtual void determineAbsolutePaintRect();
+ virtual FloatRect determineAbsolutePaintRect(const FloatRect& requestedRect) OVERRIDE;
- virtual FilterEffectType filterEffectType() const { return FilterEffectTypeSourceInput; }
+ virtual FilterEffectType filterEffectType() const OVERRIDE { return FilterEffectTypeSourceInput; }
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const OVERRIDE;
private:
SourceGraphic(Filter* filter)
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.cpp
index 9aeb26341ae..aec1320062f 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.cpp
@@ -40,7 +40,7 @@ namespace WebCore {
// according to the SVG 1.1 SE light regression tests
static const float antiAliasTreshold = 0.016f;
-void SpotLightSource::initPaintingData(PaintingData& paintingData)
+void SpotLightSource::initPaintingData(PaintingData& paintingData) const
{
paintingData.privateColorVector = paintingData.colorVector;
paintingData.directionVector.setX(m_direction.x() - m_position.x());
@@ -60,17 +60,9 @@ void SpotLightSource::initPaintingData(PaintingData& paintingData)
paintingData.coneCutOffLimit = cosf(deg2rad(180.0f - limitingConeAngle));
paintingData.coneFullLight = paintingData.coneCutOffLimit - antiAliasTreshold;
}
-
- // Optimization for common specularExponent values
- if (!m_specularExponent)
- paintingData.specularExponent = 0;
- else if (m_specularExponent == 1.0f)
- paintingData.specularExponent = 1;
- else // It is neither 0.0f nor 1.0f
- paintingData.specularExponent = 2;
}
-void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z) const
{
paintingData.lightVector.setX(m_position.x() - x);
paintingData.lightVector.setY(m_position.y() - y);
@@ -88,16 +80,10 @@ void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int
// Set the color of the pixel
float lightStrength;
- switch (paintingData.specularExponent) {
- case 0:
- lightStrength = 1.0f; // -cosineOfAngle ^ 0 == 1
- break;
- case 1:
+ if (1.0f == m_specularExponent) {
lightStrength = -cosineOfAngle; // -cosineOfAngle ^ 1 == -cosineOfAngle
- break;
- default:
+ } else {
lightStrength = powf(-cosineOfAngle, m_specularExponent);
- break;
}
if (cosineOfAngle > paintingData.coneFullLight)
@@ -161,6 +147,7 @@ bool SpotLightSource::setPointsAtZ(float pointsAtZ)
bool SpotLightSource::setSpecularExponent(float specularExponent)
{
+ specularExponent = std::min(std::max(specularExponent, 1.0f), 128.0f);
if (m_specularExponent == specularExponent)
return false;
m_specularExponent = specularExponent;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.h
index ce8ce27f1ef..2b8599457f5 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/filters/SpotLightSource.h
@@ -35,6 +35,13 @@ public:
return adoptRef(new SpotLightSource(position, direction, specularExponent, limitingConeAngle));
}
+ virtual PassRefPtr<LightSource> create(const FloatPoint3D& scale, const FloatSize& offset) const OVERRIDE
+ {
+ FloatPoint3D position(m_position.x() * scale.x() - offset.width(), m_position.y() * scale.y() - offset.height(), m_position.z() * scale.z());
+ FloatPoint3D direction(m_direction.x() * scale.x() - offset.width(), m_direction.y() * scale.y() - offset.height(), m_direction.z() * scale.z());
+ return adoptRef(new SpotLightSource(position, direction, m_specularExponent, m_limitingConeAngle));
+ }
+
const FloatPoint3D& position() const { return m_position; }
const FloatPoint3D& direction() const { return m_direction; }
float specularExponent() const { return m_specularExponent; }
@@ -50,10 +57,10 @@ public:
virtual bool setSpecularExponent(float) OVERRIDE;
virtual bool setLimitingConeAngle(float) OVERRIDE;
- virtual void initPaintingData(PaintingData&);
- virtual void updatePaintingData(PaintingData&, int x, int y, float z);
+ virtual void initPaintingData(PaintingData&) const OVERRIDE;
+ virtual void updatePaintingData(PaintingData&, int x, int y, float z) const OVERRIDE;
- virtual TextStream& externalRepresentation(TextStream&) const;
+ virtual TextStream& externalRepresentation(TextStream&) const OVERRIDE;
private:
SpotLightSource(const FloatPoint3D& position, const FloatPoint3D& direction,
@@ -61,7 +68,7 @@ private:
: LightSource(LS_SPOT)
, m_position(position)
, m_direction(direction)
- , m_specularExponent(specularExponent)
+ , m_specularExponent(std::min(std::max(specularExponent, 1.0f), 128.0f))
, m_limitingConeAngle(limitingConeAngle)
{
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterArrayParameter.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterArrayParameter.cpp
deleted file mode 100644
index 138fef6ef36..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterArrayParameter.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterArrayParameter.h"
-
-#include "platform/animation/AnimationUtilities.h"
-
-namespace WebCore {
-
-PassRefPtr<CustomFilterParameter> CustomFilterArrayParameter::blend(const CustomFilterParameter* from, double progress)
-{
- if (!from || !isSameType(*from))
- return this;
-
- const CustomFilterArrayParameter* fromArray = static_cast<const CustomFilterArrayParameter*>(from);
-
- if (size() != fromArray->size())
- return this;
-
- RefPtr<CustomFilterArrayParameter> result = CustomFilterArrayParameter::create(name());
- for (size_t i = 0; i < size(); ++i)
- result->addValue(WebCore::blend(fromArray->valueAt(i), valueAt(i), progress));
-
- return result.release();
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterArrayParameter.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterArrayParameter.h
deleted file mode 100644
index a58d1525c30..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterArrayParameter.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterArrayParameter_h
-#define CustomFilterArrayParameter_h
-
-#include "platform/PlatformExport.h"
-#include "platform/graphics/filters/custom/CustomFilterParameter.h"
-#include "wtf/Vector.h"
-
-namespace WebCore {
-
-class PLATFORM_EXPORT CustomFilterArrayParameter : public CustomFilterParameter {
-public:
- static PassRefPtr<CustomFilterArrayParameter> create(const String& name)
- {
- return adoptRef(new CustomFilterArrayParameter(name));
- }
-
- unsigned size() const { return m_data.size(); }
- double valueAt(unsigned index) const { return m_data.at(index); }
-
- void addValue(double value) { m_data.append(value); }
-
- virtual PassRefPtr<CustomFilterParameter> blend(const CustomFilterParameter* from, double progress);
-
- virtual bool operator==(const CustomFilterParameter& o) const
- {
- if (!isSameType(o))
- return false;
-
- const CustomFilterArrayParameter* other = static_cast<const CustomFilterArrayParameter*>(&o);
- return m_data == other->m_data;
- }
-
-private:
- CustomFilterArrayParameter(const String& name)
- : CustomFilterParameter(Array, name)
- {
- }
-
- Vector<double> m_data;
-};
-
-} // namespace WebCore
-
-
-#endif // CustomFilterArrayParameter_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterCompiledProgram.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterCompiledProgram.cpp
deleted file mode 100644
index 2e5d853dcc9..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterCompiledProgram.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterCompiledProgram.h"
-
-namespace WebCore {
-
-CustomFilterCompiledProgram::CustomFilterCompiledProgram(PassRefPtr<GraphicsContext3D> context, const String& validatedVertexShader, const String& validatedFragmentShader, CustomFilterProgramType programType)
- : m_context(context)
- , m_program(0)
- , m_positionAttribLocation(-1)
- , m_texAttribLocation(-1)
- , m_meshAttribLocation(-1)
- , m_triangleAttribLocation(-1)
- , m_meshBoxLocation(-1)
- , m_projectionMatrixLocation(-1)
- , m_tileSizeLocation(-1)
- , m_meshSizeLocation(-1)
- , m_samplerLocation(-1)
- , m_samplerSizeLocation(-1)
- , m_contentSamplerLocation(-1)
- , m_isInitialized(false)
-{
- m_context->makeContextCurrent();
-
- Platform3DObject vertexShader = compileShader(GL_VERTEX_SHADER, validatedVertexShader);
- if (!vertexShader)
- return;
-
- Platform3DObject fragmentShader = compileShader(GL_FRAGMENT_SHADER, validatedFragmentShader);
- if (!fragmentShader) {
- m_context->deleteShader(vertexShader);
- return;
- }
-
- m_program = linkProgram(vertexShader, fragmentShader);
-
- m_context->deleteShader(vertexShader);
- m_context->deleteShader(fragmentShader);
-
- if (!m_program)
- return;
-
- initializeParameterLocations(programType);
-
- m_isInitialized = true;
-}
-
-Platform3DObject CustomFilterCompiledProgram::compileShader(GC3Denum shaderType, const String& shaderString)
-{
- ASSERT(!shaderString.isNull());
-
- Platform3DObject shader = m_context->createShader(shaderType);
- m_context->shaderSource(shader, shaderString);
- m_context->compileShader(shader);
-
- int compiled = 0;
- m_context->getShaderiv(shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- // FIXME: This is an invalid shader. Throw some errors.
- // https://bugs.webkit.org/show_bug.cgi?id=74416
- m_context->deleteShader(shader);
- return 0;
- }
-
- return shader;
-}
-
-Platform3DObject CustomFilterCompiledProgram::linkProgram(Platform3DObject vertexShader, Platform3DObject fragmentShader)
-{
- Platform3DObject program = m_context->createProgram();
- m_context->attachShader(program, vertexShader);
- m_context->attachShader(program, fragmentShader);
- m_context->linkProgram(program);
-
- int linked = 0;
- m_context->getProgramiv(program, GL_LINK_STATUS, &linked);
- if (!linked) {
- // FIXME: Invalid vertex/fragment shader combination. Throw some errors here.
- // https://bugs.webkit.org/show_bug.cgi?id=74416
- m_context->deleteProgram(program);
- return 0;
- }
-
- return program;
-}
-
-void CustomFilterCompiledProgram::initializeParameterLocations(CustomFilterProgramType programType)
-{
- m_positionAttribLocation = m_context->getAttribLocation(m_program, "a_position");
- m_texAttribLocation = m_context->getAttribLocation(m_program, "a_texCoord");
- m_meshAttribLocation = m_context->getAttribLocation(m_program, "a_meshCoord");
- m_triangleAttribLocation = m_context->getAttribLocation(m_program, "a_triangleCoord");
- m_meshBoxLocation = m_context->getUniformLocation(m_program, "u_meshBox");
- m_tileSizeLocation = m_context->getUniformLocation(m_program, "u_tileSize");
- m_meshSizeLocation = m_context->getUniformLocation(m_program, "u_meshSize");
- m_projectionMatrixLocation = m_context->getUniformLocation(m_program, "u_projectionMatrix");
- m_samplerSizeLocation = m_context->getUniformLocation(m_program, "u_textureSize");
- m_contentSamplerLocation = m_context->getUniformLocation(m_program, "u_contentTexture");
- if (programType == ProgramTypeBlendsElementTexture) {
- // When the author uses the CSS mix function in a custom filter, WebKit adds the internal
- // symbol css_u_texture to the shader code, which references the texture of the element.
- m_samplerLocation = m_context->getUniformLocation(m_program, "css_u_texture");
- }
-}
-
-int CustomFilterCompiledProgram::uniformLocationByName(const String& name)
-{
- ASSERT(m_isInitialized);
- // FIXME: Improve this by caching the uniform locations.
- return m_context->getUniformLocation(m_program, name);
-}
-
-CustomFilterCompiledProgram::~CustomFilterCompiledProgram()
-{
- if (m_program) {
- m_context->makeContextCurrent();
- m_context->deleteProgram(m_program);
- }
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterCompiledProgram.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterCompiledProgram.h
deleted file mode 100644
index 54b6a0a7f6c..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterCompiledProgram.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterCompiledProgram_h
-#define CustomFilterCompiledProgram_h
-
-#include "platform/graphics/GraphicsContext3D.h"
-#include "platform/graphics/filters/custom/CustomFilterProgramInfo.h"
-#include "wtf/RefCounted.h"
-#include "wtf/text/WTFString.h"
-
-namespace WebCore {
-
-class CustomFilterGlobalContext;
-
-class CustomFilterCompiledProgram: public RefCounted<CustomFilterCompiledProgram> {
-public:
- static PassRefPtr<CustomFilterCompiledProgram> create(PassRefPtr<GraphicsContext3D> context, const String& validatedVertexShader, const String& validatedFragmentShader, CustomFilterProgramType programType)
- {
- return adoptRef(new CustomFilterCompiledProgram(context, validatedVertexShader, validatedFragmentShader, programType));
- }
-
- ~CustomFilterCompiledProgram();
-
- int positionAttribLocation() const { return m_positionAttribLocation; }
- int texAttribLocation() const { return m_texAttribLocation; }
- int meshAttribLocation() const { return m_meshAttribLocation; }
- int triangleAttribLocation() const { return m_triangleAttribLocation; }
- int meshBoxLocation() const { return m_meshBoxLocation; }
- int projectionMatrixLocation() const { return m_projectionMatrixLocation; }
- int tileSizeLocation() const { return m_tileSizeLocation; }
- int meshSizeLocation() const { return m_meshSizeLocation; }
- int samplerLocation() const { return m_samplerLocation; }
- int contentSamplerLocation() const { return m_contentSamplerLocation; }
- int samplerSizeLocation() const { return m_samplerSizeLocation; }
-
- int uniformLocationByName(const String&);
-
- bool isInitialized() const { return m_isInitialized; }
-
- Platform3DObject program() const { return m_program; }
-private:
- CustomFilterCompiledProgram(PassRefPtr<GraphicsContext3D>, const String& validatedVertexShader, const String& validatedFragmentShader, CustomFilterProgramType);
-
- Platform3DObject compileShader(GC3Denum shaderType, const String& shaderString);
- Platform3DObject linkProgram(Platform3DObject vertexShader, Platform3DObject fragmentShader);
- void initializeParameterLocations(CustomFilterProgramType);
-
- RefPtr<GraphicsContext3D> m_context;
- Platform3DObject m_program;
-
- int m_positionAttribLocation;
- int m_texAttribLocation;
- int m_meshAttribLocation;
- int m_triangleAttribLocation;
- int m_meshBoxLocation;
- int m_projectionMatrixLocation;
- int m_tileSizeLocation;
- int m_meshSizeLocation;
- int m_samplerLocation;
- int m_samplerSizeLocation;
- int m_contentSamplerLocation;
-
- bool m_isInitialized;
-};
-
-}
-
-#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterConstants.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterConstants.h
deleted file mode 100644
index 5c3b2143e2a..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterConstants.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterConstants_h
-#define CustomFilterConstants_h
-
-namespace WebCore {
-
-enum CustomFilterMeshConstants {
- // Vertex attribute sizes
- PositionAttribSize = 4,
- TexAttribSize = 2,
- MeshAttribSize = 2,
- TriangleAttribSize = 3,
- // Vertex attribute offsets
- PositionAttribOffset = 0,
- TexAttribOffset = PositionAttribOffset + PositionAttribSize * sizeof(float),
- MeshAttribOffset = TexAttribOffset + TexAttribSize * sizeof(float),
- TriangleAttribOffset = MeshAttribOffset + MeshAttribSize * sizeof(float)
-};
-
-enum CustomFilterMeshType {
- MeshTypeAttached,
- MeshTypeDetached
-};
-
-enum CustomFilterProgramType {
- ProgramTypeNoElementTexture,
- ProgramTypeBlendsElementTexture
-};
-
-} // namespace WebCore
-
-#endif // CustomFilterConstants_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterGlobalContext.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterGlobalContext.cpp
deleted file mode 100644
index a3727ae3446..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterGlobalContext.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterGlobalContext.h"
-
-#include "platform/graphics/GraphicsContext3D.h"
-#include "platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
-
-namespace WebCore {
-
-CustomFilterGlobalContext::CustomFilterGlobalContext()
-{
-}
-
-CustomFilterGlobalContext::~CustomFilterGlobalContext()
-{
- for (CustomFilterValidatedProgramsMap::iterator iter = m_programs.begin(); iter != m_programs.end(); ++iter)
- iter->value->detachFromGlobalContext();
-}
-
-ANGLEPlatformBridge* CustomFilterGlobalContext::webglShaderValidator()
-{
- if (!m_webglShaderValidator)
- m_webglShaderValidator = createShaderValidator(SH_WEBGL_SPEC);
- return m_webglShaderValidator.get();
-}
-
-ANGLEPlatformBridge* CustomFilterGlobalContext::mixShaderValidator()
-{
- if (!m_mixShaderValidator)
- m_mixShaderValidator = createShaderValidator(SH_CSS_SHADERS_SPEC);
- return m_mixShaderValidator.get();
-}
-
-PassOwnPtr<ANGLEPlatformBridge> CustomFilterGlobalContext::createShaderValidator(ShShaderSpec shaderSpec)
-{
- OwnPtr<ANGLEPlatformBridge> validator = adoptPtr(new ANGLEPlatformBridge(SH_ESSL_OUTPUT, shaderSpec));
- ShBuiltInResources resources;
- ShInitBuiltInResources(&resources);
- validator->setResources(resources);
- return validator.release();
-}
-
-void CustomFilterGlobalContext::prepareContextIfNeeded()
-{
- if (m_context.get())
- return;
-
- GraphicsContext3D::Attributes attributes;
- attributes.preserveDrawingBuffer = true;
- attributes.premultipliedAlpha = false;
- attributes.shareResources = true;
- attributes.preferDiscreteGPU = true;
- m_context = GraphicsContext3D::create(attributes);
- if (!m_context)
- return;
- m_context->makeContextCurrent();
- m_context->enable(GL_DEPTH_TEST);
-}
-
-PassRefPtr<CustomFilterValidatedProgram> CustomFilterGlobalContext::getValidatedProgram(const CustomFilterProgramInfo& programInfo)
-{
- CustomFilterValidatedProgramsMap::iterator iter = m_programs.find(programInfo);
- if (iter != m_programs.end())
- return iter->value;
-
- RefPtr<CustomFilterValidatedProgram> validatedProgram = CustomFilterValidatedProgram::create(this, programInfo);
- m_programs.set(programInfo, validatedProgram.get());
- return validatedProgram.release();
-}
-
-void CustomFilterGlobalContext::removeValidatedProgram(const CustomFilterValidatedProgram* program)
-{
- CustomFilterValidatedProgramsMap::iterator iter = m_programs.find(program->programInfo());
- ASSERT_WITH_SECURITY_IMPLICATION(iter != m_programs.end());
- m_programs.remove(iter);
-
-#ifndef NDEBUG
- // Check that there's no way we could have the same program under a different key.
- for (iter = m_programs.begin(); iter != m_programs.end(); ++iter)
- ASSERT(iter->value != program);
-#endif
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterGlobalContext.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterGlobalContext.h
deleted file mode 100644
index 01f54d5fa92..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterGlobalContext.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterGlobalContext_h
-#define CustomFilterGlobalContext_h
-
-#include "platform/graphics/angle/ANGLEPlatformBridge.h"
-#include "platform/graphics/filters/custom/CustomFilterProgramInfo.h"
-#include "wtf/HashMap.h"
-#include "wtf/Noncopyable.h"
-#include "wtf/RefPtr.h"
-
-namespace WebCore {
-
-class CustomFilterValidatedProgram;
-class GraphicsContext3D;
-
-typedef HashMap<CustomFilterProgramInfo, CustomFilterValidatedProgram*> CustomFilterValidatedProgramsMap;
-
-class PLATFORM_EXPORT CustomFilterGlobalContext {
- WTF_MAKE_NONCOPYABLE(CustomFilterGlobalContext);
-public:
- CustomFilterGlobalContext();
- ~CustomFilterGlobalContext();
-
- GraphicsContext3D* context() const { return m_context.get(); }
-
- // CSS shaders not referenced from the CSS mix function should be validated just like regular WebGL shaders.
- // This ANGLE validator uses the SH_WEBGL_SPEC flag.
- ANGLEPlatformBridge* webglShaderValidator();
-
- // CSS shaders referenced from the CSS mix function should be validated slightly differently than WebGL shaders.
- // This ANGLE validator uses the SH_CSS_SHADERS_SPEC flag.
- // Under this flag, most notably:
- // - The "gl_FragColor" built-in is not available.
- // - Instead, the "css_MixColor" and "css_ColorMatrix" built-ins are available.
- // - The "css_" prefix is reserved.
- // - In the translated source that ANGLE returns, ANGLE renames the author's "main" function to "css_main".
- // The complete details are documented in ANGLE/ShaderLang.h.
- ANGLEPlatformBridge* mixShaderValidator();
-
- void prepareContextIfNeeded();
-
- PassRefPtr<CustomFilterValidatedProgram> getValidatedProgram(const CustomFilterProgramInfo&);
- void removeValidatedProgram(const CustomFilterValidatedProgram*);
-private:
- static PassOwnPtr<ANGLEPlatformBridge> createShaderValidator(ShShaderSpec);
-
- RefPtr<GraphicsContext3D> m_context;
- OwnPtr<ANGLEPlatformBridge> m_webglShaderValidator;
- OwnPtr<ANGLEPlatformBridge> m_mixShaderValidator;
- CustomFilterValidatedProgramsMap m_programs;
-};
-
-} // namespace WebCore
-
-#endif // CustomFilterGlobalContext_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMesh.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMesh.cpp
deleted file mode 100644
index cb4c59cfc37..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMesh.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterMesh.h"
-
-#include "platform/graphics/GraphicsContext3D.h"
-#include "platform/graphics/filters/custom/CustomFilterMeshGenerator.h"
-
-namespace WebCore {
-
-CustomFilterMesh::CustomFilterMesh(GraphicsContext3D* context, unsigned columns, unsigned rows,
- const FloatRect& meshBox, CustomFilterMeshType meshType)
- : m_context(context)
- , m_verticesBufferObject(0)
- , m_elementsBufferObject(0)
- , m_meshBox(meshBox)
- , m_meshType(meshType)
-{
- CustomFilterMeshGenerator generator(columns, rows, meshBox, meshType);
- m_indicesCount = generator.indicesCount();
- m_bytesPerVertex = generator.floatsPerVertex() * sizeof(float);
-
- m_context->makeContextCurrent();
-
- m_verticesBufferObject = m_context->createBuffer();
- m_context->bindBuffer(GL_ARRAY_BUFFER, m_verticesBufferObject);
- m_context->bufferData(GL_ARRAY_BUFFER, generator.vertices().size() * sizeof(float), generator.vertices().data(), GL_STATIC_DRAW);
-
- m_elementsBufferObject = m_context->createBuffer();
- m_context->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementsBufferObject);
- m_context->bufferData(GL_ELEMENT_ARRAY_BUFFER, generator.indices().size() * sizeof(uint16_t), generator.indices().data(), GL_STATIC_DRAW);
-}
-
-CustomFilterMesh::~CustomFilterMesh()
-{
- m_context->makeContextCurrent();
- m_context->deleteBuffer(m_verticesBufferObject);
- m_context->deleteBuffer(m_elementsBufferObject);
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMesh.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMesh.h
deleted file mode 100644
index b9e8a1b5f11..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMesh.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterMesh_h
-#define CustomFilterMesh_h
-
-#include "platform/geometry/FloatRect.h"
-#include "platform/graphics/GraphicsTypes3D.h"
-#include "platform/graphics/filters/custom/CustomFilterOperation.h"
-#include "wtf/RefCounted.h"
-
-namespace WebCore {
-
-class GraphicsContext3D;
-
-class PLATFORM_EXPORT CustomFilterMesh : public RefCounted<CustomFilterMesh> {
-public:
- static PassRefPtr<CustomFilterMesh> create(GraphicsContext3D* context, unsigned cols, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType meshType)
- {
- return adoptRef(new CustomFilterMesh(context, cols, rows, meshBox, meshType));
- }
- ~CustomFilterMesh();
-
- Platform3DObject verticesBufferObject() const { return m_verticesBufferObject; }
- unsigned bytesPerVertex() const { return m_bytesPerVertex; }
-
- Platform3DObject elementsBufferObject() const { return m_elementsBufferObject; }
- unsigned indicesCount() const { return m_indicesCount; }
-
- const FloatRect& meshBox() const { return m_meshBox; }
- CustomFilterMeshType meshType() const { return m_meshType; }
-
-private:
- CustomFilterMesh(GraphicsContext3D*, unsigned cols, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType);
-
- GraphicsContext3D* m_context;
-
- Platform3DObject m_verticesBufferObject;
- unsigned m_bytesPerVertex;
-
- Platform3DObject m_elementsBufferObject;
- unsigned m_indicesCount;
-
- FloatRect m_meshBox;
- CustomFilterMeshType m_meshType;
-};
-
-} // namespace WebCore
-
-#endif // CustomFilterMesh_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMeshGenerator.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMeshGenerator.cpp
deleted file mode 100644
index 3e373009979..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMeshGenerator.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterMeshGenerator.h"
-
-#ifndef NDEBUG
-#include <stdio.h> // Needed for printf used in dumpBuffers.
-#endif
-
-namespace WebCore {
-
-#ifndef NDEBUG
-// Use "call 'WebCore::s_dumpCustomFilterMeshBuffers' = 1" in GDB to activate printing of the mesh buffers.
-static bool s_dumpCustomFilterMeshBuffers = false;
-#endif
-
-CustomFilterMeshGenerator::CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType meshType)
- : m_meshType(meshType)
- , m_points(columns + 1, rows + 1)
- , m_tiles(columns, rows)
- , m_tileSizeInPixels(meshBox.width() / m_tiles.width(), meshBox.height() / m_tiles.height())
- , m_tileSizeInDeviceSpace(1.0f / m_tiles.width(), 1.0f / m_tiles.height())
- , m_meshBox(meshBox)
-{
- // Build the two buffers needed to draw triangles:
- // * m_vertices has a number of float attributes that will be passed to the vertex shader
- // for each computed vertex. This number is calculated in floatsPerVertex() based on the meshType.
- // * m_indices is a buffer that will have 3 indices per triangle. Each index will point inside
- // the m_vertices buffer.
- m_vertices.reserveCapacity(verticesCount() * floatsPerVertex());
- m_indices.reserveCapacity(indicesCount());
-
- // Based on the meshType there can be two types of meshes.
- // * attached: each triangle uses vertices from the neighbor triangles. This is useful to save some GPU memory
- // when there's no need to explode the tiles.
- // * detached: each triangle has its own vertices. This means each triangle can be moved independently and a vec3
- // attribute is passed, so that each vertex can be uniquely identified.
- if (m_meshType == MeshTypeAttached)
- generateAttachedMesh();
- else
- generateDetachedMesh();
-
-#ifndef NDEBUG
- if (s_dumpCustomFilterMeshBuffers)
- dumpBuffers();
-#endif
-}
-
-void CustomFilterMeshGenerator::addAttachedMeshIndex(int quadX, int quadY, int triangleX, int triangleY, int)
-{
- m_indices.append((quadY + triangleY) * m_points.width() + (quadX + triangleX));
-}
-
-void CustomFilterMeshGenerator::generateAttachedMesh()
-{
- for (int j = 0; j < m_points.height(); ++j) {
- for (int i = 0; i < m_points.width(); ++i)
- addAttachedMeshVertexAttributes(i, j);
- }
-
- for (int j = 0; j < m_tiles.height(); ++j) {
- for (int i = 0; i < m_tiles.width(); ++i)
- addTile<&CustomFilterMeshGenerator::addAttachedMeshIndex>(i, j);
- }
-}
-
-void CustomFilterMeshGenerator::addDetachedMeshVertexAndIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle)
-{
- addDetachedMeshVertexAttributes(quadX, quadY, triangleX, triangleY, triangle);
- m_indices.append(m_indices.size());
-}
-
-void CustomFilterMeshGenerator::generateDetachedMesh()
-{
- for (int j = 0; j < m_tiles.height(); ++j) {
- for (int i = 0; i < m_tiles.width(); ++i)
- addTile<&CustomFilterMeshGenerator::addDetachedMeshVertexAndIndex>(i, j);
- }
-}
-
-void CustomFilterMeshGenerator::addPositionAttribute(int quadX, int quadY)
-{
- // vec4 a_position
- m_vertices.append(m_tileSizeInPixels.width() * quadX - 0.5f + m_meshBox.x());
- m_vertices.append(m_tileSizeInPixels.height() * quadY - 0.5f + m_meshBox.y());
- m_vertices.append(0.0f); // z
- m_vertices.append(1.0f);
-}
-
-void CustomFilterMeshGenerator::addTexCoordAttribute(int quadX, int quadY)
-{
- // vec2 a_texCoord
- m_vertices.append(m_tileSizeInPixels.width() * quadX + m_meshBox.x());
- m_vertices.append(m_tileSizeInPixels.height() * quadY + m_meshBox.y());
-}
-
-void CustomFilterMeshGenerator::addMeshCoordAttribute(int quadX, int quadY)
-{
- // vec2 a_meshCoord
- m_vertices.append(m_tileSizeInDeviceSpace.width() * quadX);
- m_vertices.append(m_tileSizeInDeviceSpace.height() * quadY);
-}
-
-void CustomFilterMeshGenerator::addTriangleCoordAttribute(int quadX, int quadY, int triangle)
-{
- // vec3 a_triangleCoord
- m_vertices.append(quadX);
- m_vertices.append(quadY);
- m_vertices.append(triangle);
-}
-
-void CustomFilterMeshGenerator::addAttachedMeshVertexAttributes(int quadX, int quadY)
-{
- addPositionAttribute(quadX, quadY);
- addTexCoordAttribute(quadX, quadY);
- addMeshCoordAttribute(quadX, quadY);
-}
-
-void CustomFilterMeshGenerator::addDetachedMeshVertexAttributes(int quadX, int quadY, int triangleX, int triangleY, int triangle)
-{
- addAttachedMeshVertexAttributes(quadX + triangleX, quadY + triangleY);
- addTriangleCoordAttribute(quadX, quadY, triangle);
-}
-
-#ifndef NDEBUG
-void CustomFilterMeshGenerator::dumpBuffers() const
-{
- printf("Mesh buffers: Points.width(): %d, Points.height(): %d meshBox: %f, %f, %f, %f, type: %s\n",
- m_points.width(), m_points.height(), m_meshBox.x(), m_meshBox.y(), m_meshBox.width(), m_meshBox.height(),
- (m_meshType == MeshTypeAttached) ? "Attached" : "Detached");
- printf("---Vertex:\n\t");
- for (unsigned i = 0; i < m_vertices.size(); ++i) {
- printf("%f ", m_vertices.at(i));
- if (!((i + 1) % floatsPerVertex()))
- printf("\n\t");
- }
- printf("\n---Indices: ");
- for (unsigned i = 0; i < m_indices.size(); ++i)
- printf("%d ", m_indices.at(i));
- printf("\n");
-}
-#endif
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMeshGenerator.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMeshGenerator.h
deleted file mode 100644
index d4fc6441611..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterMeshGenerator.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterMeshGenerator_h
-#define CustomFilterMeshGenerator_h
-
-#include "platform/PlatformExport.h"
-#include "platform/geometry/FloatRect.h"
-#include "platform/graphics/filters/custom/CustomFilterConstants.h"
-
-namespace WebCore {
-
-class PLATFORM_EXPORT CustomFilterMeshGenerator {
-public:
- // Lines and columns are the values passed in CSS. The result is vertex mesh that has 'rows' numbers of rows
- // and 'columns' number of columns with a total of 'rows + 1' * 'columns + 1' vertices.
- // MeshBox is the filtered area calculated defined using the border-box, padding-box, content-box or filter-box
- // attributes. A value of (0, 0, 1, 1) will cover the entire output surface.
- CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType);
-
- const Vector<float>& vertices() const { return m_vertices; }
- const Vector<uint16_t>& indices() const { return m_indices; }
-
- const IntSize& points() const { return m_points; }
- unsigned pointsCount() const { return m_points.width() * m_points.height(); }
-
- const IntSize& tiles() const { return m_tiles; }
- unsigned tilesCount() const { return m_tiles.width() * m_tiles.height(); }
-
- unsigned indicesCount() const
- {
- const unsigned trianglesPerTile = 2;
- const unsigned indicesPerTriangle = 3;
- return tilesCount() * trianglesPerTile * indicesPerTriangle;
- }
-
- unsigned floatsPerVertex() const
- {
- static const unsigned AttachedMeshVertexSize = PositionAttribSize + TexAttribSize + MeshAttribSize;
- static const unsigned DetachedMeshVertexSize = AttachedMeshVertexSize + TriangleAttribSize;
- return m_meshType == MeshTypeAttached ? AttachedMeshVertexSize : DetachedMeshVertexSize;
- }
-
- unsigned verticesCount() const
- {
- return m_meshType == MeshTypeAttached ? pointsCount() : indicesCount();
- }
-
-private:
- typedef void (CustomFilterMeshGenerator::*AddTriangleVertexFunction)(int quadX, int quadY, int triangleX, int triangleY, int triangle);
-
- template <AddTriangleVertexFunction addTriangleVertex>
- void addTile(int quadX, int quadY)
- {
- ((*this).*(addTriangleVertex))(quadX, quadY, 0, 0, 1);
- ((*this).*(addTriangleVertex))(quadX, quadY, 1, 0, 2);
- ((*this).*(addTriangleVertex))(quadX, quadY, 1, 1, 3);
- ((*this).*(addTriangleVertex))(quadX, quadY, 0, 0, 4);
- ((*this).*(addTriangleVertex))(quadX, quadY, 1, 1, 5);
- ((*this).*(addTriangleVertex))(quadX, quadY, 0, 1, 6);
- }
-
- void addAttachedMeshIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle);
-
- void generateAttachedMesh();
-
- void addDetachedMeshVertexAndIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle);
-
- void generateDetachedMesh();
- void addPositionAttribute(int quadX, int quadY);
- void addTexCoordAttribute(int quadX, int quadY);
- void addMeshCoordAttribute(int quadX, int quadY);
- void addTriangleCoordAttribute(int quadX, int quadY, int triangle);
- void addAttachedMeshVertexAttributes(int quadX, int quadY);
- void addDetachedMeshVertexAttributes(int quadX, int quadY, int triangleX, int triangleY, int triangle);
-
-#ifndef NDEBUG
- void dumpBuffers() const;
-#endif
-
-private:
- Vector<float> m_vertices;
- Vector<uint16_t> m_indices;
-
- CustomFilterMeshType m_meshType;
- IntSize m_points;
- IntSize m_tiles;
- FloatSize m_tileSizeInPixels;
- FloatSize m_tileSizeInDeviceSpace;
- FloatRect m_meshBox;
-};
-
-} // namespace WebCore
-
-#endif // CustomFilterMeshGenerator_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterNumberParameter.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterNumberParameter.cpp
deleted file mode 100644
index 1fbfa58f6a9..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterNumberParameter.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterNumberParameter.h"
-
-#include "platform/animation/AnimationUtilities.h"
-
-namespace WebCore {
-
-PassRefPtr<CustomFilterParameter> CustomFilterNumberParameter::blend(const CustomFilterParameter* from, double progress)
-{
- if (!from || !isSameType(*from))
- return this;
- const CustomFilterNumberParameter* fromNumber = static_cast<const CustomFilterNumberParameter*>(from);
- if (size() != fromNumber->size())
- return this;
- RefPtr<CustomFilterNumberParameter> result = CustomFilterNumberParameter::create(name());
- for (size_t i = 0; i < size(); ++i)
- result->addValue(WebCore::blend(fromNumber->valueAt(i), valueAt(i), progress));
- return result.release();
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterNumberParameter.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterNumberParameter.h
deleted file mode 100644
index ed2e838fcd9..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterNumberParameter.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterNumberParameter_h
-#define CustomFilterNumberParameter_h
-
-#include "platform/PlatformExport.h"
-#include "platform/graphics/filters/custom/CustomFilterParameter.h"
-#include "wtf/Vector.h"
-
-namespace WebCore {
-
-class PLATFORM_EXPORT CustomFilterNumberParameter : public CustomFilterParameter {
-public:
- static PassRefPtr<CustomFilterNumberParameter> create(const String& name)
- {
- return adoptRef(new CustomFilterNumberParameter(name));
- }
-
- unsigned size() const { return m_data.size(); }
- double valueAt(unsigned index) const { return m_data.at(index); }
-
- void addValue(double value) { m_data.append(value); }
-
- virtual PassRefPtr<CustomFilterParameter> blend(const CustomFilterParameter* from, double progress);
-
- virtual bool operator==(const CustomFilterParameter& o) const
- {
- if (!isSameType(o))
- return false;
- const CustomFilterNumberParameter* other = static_cast<const CustomFilterNumberParameter*>(&o);
- return m_data == other->m_data;
- }
-
-private:
- CustomFilterNumberParameter(const String& name)
- : CustomFilterParameter(Number, name)
- {
- }
-
- Vector<double, 4> m_data;
-};
-
-} // namespace WebCore
-
-
-#endif // CustomFilterNumberParameter_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterOperation.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterOperation.cpp
deleted file mode 100644
index cf13a4998a3..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterOperation.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterOperation.h"
-
-#include "platform/graphics/filters/custom/CustomFilterParameter.h"
-
-namespace WebCore {
-
-CustomFilterOperation::CustomFilterOperation(PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
- : FilterOperation(CUSTOM)
- , m_program(program)
- , m_parameters(sortedParameters)
- , m_meshRows(meshRows)
- , m_meshColumns(meshColumns)
- , m_meshType(meshType)
-{
-}
-
-CustomFilterOperation::~CustomFilterOperation()
-{
-}
-
-PassRefPtr<FilterOperation> CustomFilterOperation::blend(const FilterOperation* from, double progress) const
-{
- if (!from) {
- // FIXME: There's no way to decide what is the "passthrough filter" for shaders using the current CSS Syntax.
- // https://bugs.webkit.org/show_bug.cgi?id=84903
- // https://www.w3.org/Bugs/Public/show_bug.cgi?id=16861
- return const_cast<CustomFilterOperation*>(this);
- }
-
- ASSERT_WITH_SECURITY_IMPLICATION(from->isSameType(*this));
- const CustomFilterOperation* fromOp = toCustomFilterOperation(from);
- if (m_program.get() != fromOp->m_program.get()
- || m_meshRows != fromOp->m_meshRows
- || m_meshColumns != fromOp->m_meshColumns
- || m_meshType != fromOp->m_meshType)
- return const_cast<CustomFilterOperation*>(this);
-
- CustomFilterParameterList animatedParameters;
- m_parameters.blend(fromOp->m_parameters, progress, animatedParameters);
- return CustomFilterOperation::create(m_program, animatedParameters, m_meshRows, m_meshColumns, m_meshType);
-}
-
-} // namespace WebCore
-
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterOperation.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterOperation.h
deleted file mode 100644
index 945a534b108..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterOperation.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterOperation_h
-#define CustomFilterOperation_h
-
-#include "platform/geometry/LayoutSize.h"
-#include "platform/graphics/filters/FilterOperation.h"
-#include "platform/graphics/filters/custom/CustomFilterConstants.h"
-#include "platform/graphics/filters/custom/CustomFilterParameterList.h"
-#include "platform/graphics/filters/custom/CustomFilterProgram.h"
-
-namespace WebCore {
-
-// CSS Shaders
-
-class PLATFORM_EXPORT CustomFilterOperation : public FilterOperation {
-public:
- static PassRefPtr<CustomFilterOperation> create(PassRefPtr<CustomFilterProgram> program, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
- {
- return adoptRef(new CustomFilterOperation(program, sortedParameters, meshRows, meshColumns, meshType));
- }
-
- CustomFilterProgram* program() const { return m_program.get(); }
- void setProgram(PassRefPtr<CustomFilterProgram> program) { m_program = program; }
-
- const CustomFilterParameterList& parameters() const { return m_parameters; }
-
- unsigned meshRows() const { return m_meshRows; }
- unsigned meshColumns() const { return m_meshColumns; }
-
- CustomFilterMeshType meshType() const { return m_meshType; }
-
- virtual ~CustomFilterOperation();
-
- virtual bool affectsOpacity() const { return true; }
- virtual bool movesPixels() const { return true; }
-
-
-protected:
- CustomFilterOperation(PassRefPtr<CustomFilterProgram>, const CustomFilterParameterList&, unsigned meshRows, unsigned meshColumns, CustomFilterMeshType);
-
-private:
- virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
- virtual bool operator==(const FilterOperation& o) const
- {
- if (!isSameType(o))
- return false;
-
- const CustomFilterOperation* other = static_cast<const CustomFilterOperation*>(&o);
- return m_program.get() == other->m_program.get()
- && m_meshRows == other->m_meshRows
- && m_meshColumns == other->m_meshColumns
- && m_meshType == other->m_meshType
- && m_parameters == other->m_parameters;
- }
-
- RefPtr<CustomFilterProgram> m_program;
- CustomFilterParameterList m_parameters;
-
- unsigned m_meshRows;
- unsigned m_meshColumns;
- CustomFilterMeshType m_meshType;
-};
-
-DEFINE_FILTER_OPERATION_TYPE_CASTS(CustomFilterOperation, CUSTOM);
-
-} // namespace WebCore
-
-
-#endif // CustomFilterOperation_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameter.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameter.h
deleted file mode 100644
index 13e1277528a..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameter.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterParameter_h
-#define CustomFilterParameter_h
-
-#include "platform/PlatformExport.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/RefCounted.h"
-#include "wtf/text/WTFString.h"
-
-namespace WebCore {
-
-class PLATFORM_EXPORT CustomFilterParameter : public RefCounted<CustomFilterParameter> {
-public:
- // FIXME: Implement other parameters types:
- // booleans: https://bugs.webkit.org/show_bug.cgi?id=76438
- // textures: https://bugs.webkit.org/show_bug.cgi?id=71442
- // 3d-transforms: https://bugs.webkit.org/show_bug.cgi?id=71443
- // mat2, mat3, mat4: https://bugs.webkit.org/show_bug.cgi?id=71444
- enum ParameterType {
- Array,
- Number,
- Transform
- };
-
- virtual ~CustomFilterParameter() { }
-
- ParameterType parameterType() const { return m_type; }
- const String& name() const { return m_name; }
-
- bool isSameType(const CustomFilterParameter& other) const { return parameterType() == other.parameterType(); }
-
- virtual PassRefPtr<CustomFilterParameter> blend(const CustomFilterParameter*, double progress) = 0;
- virtual bool operator==(const CustomFilterParameter&) const = 0;
- bool operator!=(const CustomFilterParameter& o) const { return !(*this == o); }
-protected:
- CustomFilterParameter(ParameterType type, const String& name)
- : m_name(name)
- , m_type(type)
- {
- }
-
-private:
- String m_name;
- ParameterType m_type;
-};
-
-} // namespace WebCore
-
-
-#endif // CustomFilterParameter_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameterList.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameterList.cpp
deleted file mode 100644
index d10aae8498e..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameterList.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterParameterList.h"
-
-#include "wtf/text/StringHash.h"
-
-namespace WebCore {
-
-CustomFilterParameterList::CustomFilterParameterList()
-{
-}
-
-CustomFilterParameterList::CustomFilterParameterList(size_t size)
- : m_parameters(size)
-{
-}
-
-bool CustomFilterParameterList::operator==(const CustomFilterParameterList& other) const
-{
- if (size() != other.size())
- return false;
- for (size_t i = 0; i < size(); ++i) {
- if (at(i).get() != other.at(i).get()
- && *at(i).get() != *other.at(i).get())
- return false;
- }
- return true;
-}
-
-#ifndef NDEBUG
-bool CustomFilterParameterList::checkAlphabeticalOrder() const
-{
- for (unsigned i = 1; i < size(); ++i) {
- // Break for equal or not-sorted parameters.
- if (!codePointCompareLessThan(at(i - 1)->name(), at(i)->name()))
- return false;
- }
- return true;
-}
-#endif
-
-void CustomFilterParameterList::blend(const CustomFilterParameterList& fromList,
- double progress, CustomFilterParameterList& resultList) const
-{
-#ifndef NDEBUG
- // This method expects both lists to be sorted by parameter name and the result list is also sorted.
- ASSERT(checkAlphabeticalOrder());
- ASSERT(fromList.checkAlphabeticalOrder());
-#endif
- size_t fromListIndex = 0, toListIndex = 0;
- while (fromListIndex < fromList.size() && toListIndex < size()) {
- CustomFilterParameter* paramFrom = fromList.at(fromListIndex).get();
- CustomFilterParameter* paramTo = at(toListIndex).get();
- if (paramFrom->name() == paramTo->name()) {
- resultList.append(paramTo->blend(paramFrom, progress));
- ++fromListIndex;
- ++toListIndex;
- continue;
- }
- if (codePointCompareLessThan(paramFrom->name(), paramTo->name())) {
- resultList.append(paramFrom);
- ++fromListIndex;
- continue;
- }
- resultList.append(paramTo);
- ++toListIndex;
- }
- for (; fromListIndex < fromList.size(); ++fromListIndex)
- resultList.append(fromList.at(fromListIndex));
- for (; toListIndex < size(); ++toListIndex)
- resultList.append(at(toListIndex));
-#ifndef NDEBUG
- ASSERT(resultList.checkAlphabeticalOrder());
-#endif
-}
-
-static bool sortParametersByNameComparator(const RefPtr<CustomFilterParameter>& a, const RefPtr<CustomFilterParameter>& b)
-{
- return codePointCompareLessThan(a->name(), b->name());
-}
-
-void CustomFilterParameterList::sortParametersByName()
-{
- std::sort(m_parameters.begin(), m_parameters.end(), sortParametersByNameComparator);
-}
-
-} // namespace WebCore
-
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameterList.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameterList.h
deleted file mode 100644
index 0dd3dcd9a0e..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterParameterList.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER 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 CustomFilterParameterList_h
-#define CustomFilterParameterList_h
-
-#include "platform/PlatformExport.h"
-#include "platform/geometry/LayoutSize.h"
-#include "platform/graphics/filters/custom/CustomFilterParameter.h"
-#include "wtf/Vector.h"
-
-namespace WebCore {
-
-class PLATFORM_EXPORT CustomFilterParameterList {
-public:
- CustomFilterParameterList();
- explicit CustomFilterParameterList(size_t);
-
- void blend(const CustomFilterParameterList& from, double progress, CustomFilterParameterList& resultList) const;
- bool operator==(const CustomFilterParameterList&) const;
-
- PassRefPtr<CustomFilterParameter> at(size_t index) const { return m_parameters.at(index); }
- size_t size() const { return m_parameters.size(); }
- void append(const PassRefPtr<CustomFilterParameter>& parameter) { m_parameters.append(parameter); }
- void sortParametersByName();
-private:
-#ifndef NDEBUG
- bool checkAlphabeticalOrder() const;
-#endif
- typedef Vector<RefPtr<CustomFilterParameter> > CustomFilterParameterVector;
- CustomFilterParameterVector m_parameters;
-};
-
-} // namespace WebCore
-
-
-#endif // CustomFilterParameterList_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgram.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgram.cpp
deleted file mode 100644
index ebaff283493..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgram.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterProgram.h"
-
-#include "platform/graphics/filters/custom/CustomFilterProgramClient.h"
-
-namespace WebCore {
-
-CustomFilterProgram::CustomFilterProgram(CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType)
- : m_programType(programType)
- , m_mixSettings(mixSettings)
- , m_meshType(meshType)
-{
- // Keep the constructor protected to prevent creating this object directly.
-}
-
-CustomFilterProgram::~CustomFilterProgram()
-{
- // All the clients should keep a reference to this object.
- ASSERT(m_clients.isEmpty());
-}
-
-void CustomFilterProgram::addClient(CustomFilterProgramClient* client)
-{
- if (m_clients.isEmpty()) {
- // Notify the StyleCustomFilterProgram that we now have at least a client
- // and the loading can begin.
- // Note: If the shader is already cached the first client will be notified,
- // even if the filter was already built. Add the client only after notifying
- // the cache about them, so that we avoid a useless recreation of the filters chain.
- willHaveClients();
- }
- m_clients.add(client);
-}
-
-void CustomFilterProgram::removeClient(CustomFilterProgramClient* client)
-{
- m_clients.remove(client);
- if (m_clients.isEmpty()) {
- // We have no clients anymore, the cached resources can be purged from memory.
- didRemoveLastClient();
- }
-}
-
-void CustomFilterProgram::notifyClients()
-{
- for (CustomFilterProgramClientList::iterator iter = m_clients.begin(), end = m_clients.end(); iter != end; ++iter)
- iter->key->notifyCustomFilterProgramLoaded(this);
-}
-
-CustomFilterProgramInfo CustomFilterProgram::programInfo() const
-{
- ASSERT(isLoaded());
- return CustomFilterProgramInfo(vertexShaderString(), fragmentShaderString(), m_programType, m_mixSettings, m_meshType);
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgram.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgram.h
deleted file mode 100644
index 1b949786d8e..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgram.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterProgram_h
-#define CustomFilterProgram_h
-
-#include "platform/graphics/filters/custom/CustomFilterProgramInfo.h"
-
-#include "wtf/HashCountedSet.h"
-#include "wtf/RefCounted.h"
-#include "wtf/text/WTFString.h"
-
-namespace WebCore {
-
-class GraphicsContext3D;
-class CustomFilterCompiledProgram;
-class CustomFilterProgramClient;
-
-// This is the base class for the StyleCustomFilterProgram class which knows how to keep
-// references to the cached shaders.
-class PLATFORM_EXPORT CustomFilterProgram: public RefCounted<CustomFilterProgram> {
-public:
- virtual ~CustomFilterProgram();
-
- virtual bool isLoaded() const = 0;
-
- void addClient(CustomFilterProgramClient*);
- void removeClient(CustomFilterProgramClient*);
-
- CustomFilterProgramInfo programInfo() const;
-
- virtual String vertexShaderString() const = 0;
- virtual String fragmentShaderString() const = 0;
- CustomFilterProgramType programType() const { return m_programType; }
- CustomFilterProgramMixSettings mixSettings() const { return m_mixSettings; }
- CustomFilterMeshType meshType() const { return m_meshType; }
-
-protected:
- // StyleCustomFilterProgram can notify the clients that the cached resources are
- // loaded and it is ready to create CustomFilterCompiledProgram objects.
- void notifyClients();
-
- virtual void willHaveClients() = 0;
- virtual void didRemoveLastClient() = 0;
-
- // Keep the constructor protected to prevent creating this object directly.
- CustomFilterProgram(CustomFilterProgramType, const CustomFilterProgramMixSettings&, CustomFilterMeshType);
-
-private:
- // CustomFilterPrograms are unique combinations of shaders and can be
- // compared using just the pointer value instead.
- // These will catch anyone doing a value equal comparison.
- bool operator==(const CustomFilterProgram&) const;
- bool operator!=(const CustomFilterProgram&) const;
-
- typedef HashCountedSet<CustomFilterProgramClient*> CustomFilterProgramClientList;
- CustomFilterProgramClientList m_clients;
- CustomFilterProgramType m_programType;
- CustomFilterProgramMixSettings m_mixSettings;
- CustomFilterMeshType m_meshType;
-};
-
-}
-
-
-#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramClient.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramClient.cpp
deleted file mode 100644
index 85a378f6bac..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramClient.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterProgramClient.h"
-
-namespace WebCore {
-
-CustomFilterProgramClient::~CustomFilterProgramClient()
-{
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramClient.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramClient.h
deleted file mode 100644
index b13098b9ab8..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramClient.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterProgramClient_h
-#define CustomFilterProgramClient_h
-
-#include "platform/PlatformExport.h"
-
-namespace WebCore {
-
-class CustomFilterProgram;
-
-class PLATFORM_EXPORT CustomFilterProgramClient {
-public:
- virtual ~CustomFilterProgramClient();
-
- virtual void notifyCustomFilterProgramLoaded(CustomFilterProgram*) = 0;
-};
-
-}
-
-
-#endif // CustomFilterProgramClient_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramInfo.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramInfo.cpp
deleted file mode 100644
index a767e6edb90..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramInfo.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterProgramInfo.h"
-
-#include "wtf/HashFunctions.h"
-#include "wtf/text/StringHash.h"
-
-namespace WebCore {
-
-static unsigned hashPossiblyNullString(const String& string)
-{
- return string.isNull() ? 0 : DefaultHash<String>::Hash::hash(string);
-}
-
-CustomFilterProgramInfo::CustomFilterProgramInfo()
-{
-}
-
-bool CustomFilterProgramInfo::isEmptyValue() const
-{
- return m_vertexShaderString.isNull()
- && m_fragmentShaderString.isNull();
-}
-
-CustomFilterProgramInfo::CustomFilterProgramInfo(WTF::HashTableDeletedValueType)
- : m_vertexShaderString(WTF::HashTableDeletedValue)
- , m_fragmentShaderString(WTF::HashTableDeletedValue)
-{
-}
-
-bool CustomFilterProgramInfo::isHashTableDeletedValue() const
-{
- return m_vertexShaderString.isHashTableDeletedValue()
- && m_fragmentShaderString.isHashTableDeletedValue();
-}
-
-CustomFilterProgramInfo::CustomFilterProgramInfo(const String& vertexShader, const String& fragmentShader, CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType)
- : m_vertexShaderString(vertexShader)
- , m_fragmentShaderString(fragmentShader)
- , m_programType(programType)
- , m_mixSettings(mixSettings)
- , m_meshType(meshType)
-{
- // At least one of the shaders needs to be non-null.
- ASSERT(!m_vertexShaderString.isNull() || !m_fragmentShaderString.isNull());
-}
-
-unsigned CustomFilterProgramInfo::hash() const
-{
- // At least one of the shaders needs to be non-null.
- ASSERT(!m_vertexShaderString.isNull() || !m_fragmentShaderString.isNull());
-
- bool blendsElementTexture = (m_programType == ProgramTypeBlendsElementTexture);
- uintptr_t hashCodes[6] = {
- hashPossiblyNullString(m_vertexShaderString),
- hashPossiblyNullString(m_fragmentShaderString),
- blendsElementTexture,
- static_cast<uintptr_t>(blendsElementTexture ? m_mixSettings.blendMode : 0),
- static_cast<uintptr_t>(blendsElementTexture ? m_mixSettings.compositeOperator : 0),
- m_meshType
- };
- return StringHasher::hashMemory<sizeof(hashCodes)>(&hashCodes);
-}
-
-bool CustomFilterProgramInfo::operator==(const CustomFilterProgramInfo& o) const
-{
- ASSERT(!isHashTableDeletedValue());
- ASSERT(!o.isHashTableDeletedValue());
-
- return m_programType == o.m_programType
- && (m_programType != ProgramTypeBlendsElementTexture || m_mixSettings == o.m_mixSettings)
- && m_meshType == o.m_meshType
- && m_vertexShaderString == o.m_vertexShaderString
- && m_fragmentShaderString == o.m_fragmentShaderString;
-}
-
-} // namespace WebCore
-
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramInfo.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramInfo.h
deleted file mode 100644
index 079cd402ede..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterProgramInfo.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterProgramInfo_h
-#define CustomFilterProgramInfo_h
-
-#include "platform/PlatformExport.h"
-#include "platform/graphics/GraphicsTypes.h"
-#include "platform/graphics/filters/custom/CustomFilterConstants.h"
-#include "wtf/HashTableDeletedValueType.h"
-#include "wtf/HashTraits.h"
-#include "wtf/text/WTFString.h"
-
-namespace WebCore {
-
-
-struct CustomFilterProgramMixSettings {
- CustomFilterProgramMixSettings()
- : blendMode(blink::WebBlendModeNormal)
- , compositeOperator(CompositeSourceAtop)
- {
- }
-
- bool operator==(const CustomFilterProgramMixSettings& o) const
- {
- return blendMode == o.blendMode && compositeOperator == o.compositeOperator;
- }
-
- blink::WebBlendMode blendMode;
- CompositeOperator compositeOperator;
-};
-
-// CustomFilterProgramInfo is the key used to link CustomFilterProgram with CustomFilterCompiledProgram.
-// It can be used as a key in a HashMap, with the note that at least one of Strings needs to be non-null.
-// Null strings are placeholders for the default shader.
-class PLATFORM_EXPORT CustomFilterProgramInfo {
-public:
- CustomFilterProgramInfo(const String&, const String&, CustomFilterProgramType, const CustomFilterProgramMixSettings&, CustomFilterMeshType);
-
- CustomFilterProgramInfo();
- bool isEmptyValue() const;
-
- CustomFilterProgramInfo(WTF::HashTableDeletedValueType);
- bool isHashTableDeletedValue() const;
-
- unsigned hash() const;
- bool operator==(const CustomFilterProgramInfo&) const;
-
- const String& vertexShaderString() const { return m_vertexShaderString; }
- const String& fragmentShaderString() const { return m_fragmentShaderString; }
- CustomFilterProgramType programType() const { return m_programType; }
- const CustomFilterProgramMixSettings& mixSettings() const { return m_mixSettings; }
- CustomFilterMeshType meshType() const { return m_meshType; }
-private:
- String m_vertexShaderString;
- String m_fragmentShaderString;
- CustomFilterProgramType m_programType;
- CustomFilterProgramMixSettings m_mixSettings;
- CustomFilterMeshType m_meshType;
-};
-
-struct CustomFilterProgramInfoHash {
- static unsigned hash(const CustomFilterProgramInfo& programInfo) { return programInfo.hash(); }
- static bool equal(const CustomFilterProgramInfo& a, const CustomFilterProgramInfo& b) { return a == b; }
- static const bool safeToCompareToEmptyOrDeleted = false;
-};
-
-struct CustomFilterProgramInfoHashTraits : WTF::SimpleClassHashTraits<CustomFilterProgramInfo> {
- static const bool hasIsEmptyValueFunction = true;
- static bool isEmptyValue(const CustomFilterProgramInfo& info) { return info.isEmptyValue(); }
-};
-
-} // namespace WebCore
-
-namespace WTF {
-
-template<> struct HashTraits<WebCore::CustomFilterProgramInfo> : WebCore::CustomFilterProgramInfoHashTraits { };
-template<> struct DefaultHash<WebCore::CustomFilterProgramInfo> {
- typedef WebCore::CustomFilterProgramInfoHash Hash;
-};
-
-}
-
-#endif // CustomFilterProgramInfo_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterRenderer.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterRenderer.cpp
deleted file mode 100644
index c8480321696..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterRenderer.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
- * Copyright (C) 2012 Company 100, 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:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterRenderer.h"
-
-#include "platform/graphics/GraphicsContext3D.h"
-#include "platform/graphics/filters/custom/CustomFilterArrayParameter.h"
-#include "platform/graphics/filters/custom/CustomFilterCompiledProgram.h"
-#include "platform/graphics/filters/custom/CustomFilterMesh.h"
-#include "platform/graphics/filters/custom/CustomFilterNumberParameter.h"
-#include "platform/graphics/filters/custom/CustomFilterParameter.h"
-#include "platform/graphics/filters/custom/CustomFilterTransformParameter.h"
-#include "platform/transforms/TransformationMatrix.h"
-
-namespace WebCore {
-
-static void orthogonalProjectionMatrix(TransformationMatrix& matrix, float left, float right, float bottom, float top)
-{
- ASSERT(matrix.isIdentity());
-
- float deltaX = right - left;
- float deltaY = top - bottom;
- if (!deltaX || !deltaY)
- return;
- matrix.setM11(2.0f / deltaX);
- matrix.setM41(-(right + left) / deltaX);
- matrix.setM22(2.0f / deltaY);
- matrix.setM42(-(top + bottom) / deltaY);
-
- // Use big enough near/far values, so that simple rotations of rather large objects will not
- // get clipped. 10000 should cover most of the screen resolutions.
- const float farValue = 10000;
- const float nearValue = -10000;
- matrix.setM33(-2.0f / (farValue - nearValue));
- matrix.setM43(- (farValue + nearValue) / (farValue - nearValue));
- matrix.setM44(1.0f);
-}
-
-PassRefPtr<CustomFilterRenderer> CustomFilterRenderer::create(PassRefPtr<GraphicsContext3D> context, CustomFilterProgramType programType, const CustomFilterParameterList& parameters,
- unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
-{
- return adoptRef(new CustomFilterRenderer(context, programType, parameters, meshRows, meshColumns, meshType));
-}
-
-CustomFilterRenderer::CustomFilterRenderer(PassRefPtr<GraphicsContext3D> context, CustomFilterProgramType programType, const CustomFilterParameterList& parameters,
- unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
- : m_context(context)
- , m_programType(programType)
- , m_parameters(parameters)
- , m_meshRows(meshRows)
- , m_meshColumns(meshColumns)
- , m_meshType(meshType)
-{
-}
-
-CustomFilterRenderer::~CustomFilterRenderer()
-{
-}
-
-bool CustomFilterRenderer::premultipliedAlpha() const
-{
- return m_programType == ProgramTypeBlendsElementTexture;
-}
-
-bool CustomFilterRenderer::programNeedsInputTexture() const
-{
- ASSERT(m_compiledProgram.get());
- return m_compiledProgram->samplerLocation() != -1;
-}
-
-void CustomFilterRenderer::draw(Platform3DObject inputTexture, const IntSize& size)
-{
- // FIXME: We would need something like CustomFilterRendererState that will contain the size and other parameters in the future. We should pass that to bindProgramBuffers instead of storing it.
- // https://bugs.webkit.org/show_bug.cgi?id=100107
- m_contextSize = size;
-
- bindProgramAndBuffers(inputTexture);
- m_context->drawElements(GL_TRIANGLES, m_mesh->indicesCount(), GL_UNSIGNED_SHORT, 0);
- unbindVertexAttributes();
-}
-
-void CustomFilterRenderer::setCompiledProgram(PassRefPtr<CustomFilterCompiledProgram> compiledProgram)
-{
- m_compiledProgram = compiledProgram;
-}
-
-bool CustomFilterRenderer::prepareForDrawing()
-{
- m_context->makeContextCurrent();
- if (!m_compiledProgram || !m_compiledProgram->isInitialized())
- return false;
- initializeMeshIfNeeded();
- return true;
-}
-
-void CustomFilterRenderer::initializeMeshIfNeeded()
-{
- if (m_mesh.get())
- return;
-
- // FIXME: Sharing the mesh would just save the time needed to upload it to the GPU, so I assume we could
- // benchmark that for performance.
- // https://bugs.webkit.org/show_bug.cgi?id=88429
- m_mesh = CustomFilterMesh::create(m_context.get(), m_meshColumns, m_meshRows, FloatRect(0, 0, 1, 1), m_meshType);
-}
-
-void CustomFilterRenderer::bindVertexAttribute(int attributeLocation, unsigned size, unsigned offset)
-{
- if (attributeLocation != -1) {
- m_context->vertexAttribPointer(attributeLocation, size, GL_FLOAT, false, m_mesh->bytesPerVertex(), offset);
- m_context->enableVertexAttribArray(attributeLocation);
- }
-}
-
-void CustomFilterRenderer::unbindVertexAttribute(int attributeLocation)
-{
- if (attributeLocation != -1)
- m_context->disableVertexAttribArray(attributeLocation);
-}
-
-void CustomFilterRenderer::bindProgramArrayParameters(int uniformLocation, CustomFilterArrayParameter* arrayParameter)
-{
- unsigned parameterSize = arrayParameter->size();
- Vector<GC3Dfloat> floatVector;
-
- for (unsigned i = 0; i < parameterSize; ++i)
- floatVector.append(arrayParameter->valueAt(i));
-
- m_context->uniform1fv(uniformLocation, parameterSize, floatVector.data());
-}
-
-void CustomFilterRenderer::bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter* numberParameter)
-{
- switch (numberParameter->size()) {
- case 1:
- m_context->uniform1f(uniformLocation, numberParameter->valueAt(0));
- break;
- case 2:
- m_context->uniform2f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1));
- break;
- case 3:
- m_context->uniform3f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1), numberParameter->valueAt(2));
- break;
- case 4:
- m_context->uniform4f(uniformLocation, numberParameter->valueAt(0), numberParameter->valueAt(1), numberParameter->valueAt(2), numberParameter->valueAt(3));
- break;
- default:
- ASSERT_NOT_REACHED();
- }
-}
-
-void CustomFilterRenderer::bindProgramTransformParameter(int uniformLocation, CustomFilterTransformParameter* transformParameter)
-{
- TransformationMatrix matrix;
- if (m_contextSize.width() && m_contextSize.height()) {
- // The viewport is a box with the size of 1 unit, so we are scaling up here to make sure that translations happen using real pixel
- // units. At the end we scale back down in order to map it back to the original box. Note that transforms come in reverse order, because it is
- // supposed to multiply to the left of the coordinates of the vertices.
- // Note that the origin (0, 0) of the viewport is in the middle of the context, so there's no need to change the origin of the transform
- // in order to rotate around the middle of mesh.
- matrix.scale3d(1.0 / m_contextSize.width(), 1.0 / m_contextSize.height(), 1);
- transformParameter->applyTransform(matrix, m_contextSize);
- matrix.scale3d(m_contextSize.width(), m_contextSize.height(), 1);
- }
- float glMatrix[16];
- matrix.toColumnMajorFloatArray(glMatrix);
- m_context->uniformMatrix4fv(uniformLocation, 1, false, &glMatrix[0]);
-}
-
-void CustomFilterRenderer::bindProgramParameters()
-{
- // FIXME: Find a way to reset uniforms that are not specified in CSS. This is needed to avoid using values
- // set by other previous rendered filters.
- // https://bugs.webkit.org/show_bug.cgi?id=76440
-
- size_t parametersSize = m_parameters.size();
- for (size_t i = 0; i < parametersSize; ++i) {
- CustomFilterParameter* parameter = m_parameters.at(i).get();
- int uniformLocation = m_compiledProgram->uniformLocationByName(parameter->name());
- if (uniformLocation == -1)
- continue;
- switch (parameter->parameterType()) {
- case CustomFilterParameter::Array:
- bindProgramArrayParameters(uniformLocation, static_cast<CustomFilterArrayParameter*>(parameter));
- break;
- case CustomFilterParameter::Number:
- bindProgramNumberParameters(uniformLocation, static_cast<CustomFilterNumberParameter*>(parameter));
- break;
- case CustomFilterParameter::Transform:
- bindProgramTransformParameter(uniformLocation, static_cast<CustomFilterTransformParameter*>(parameter));
- break;
- }
- }
-}
-
-void CustomFilterRenderer::bindProgramAndBuffers(Platform3DObject inputTexture)
-{
- ASSERT(m_compiledProgram->isInitialized());
-
- m_context->useProgram(m_compiledProgram->program());
-
- if (programNeedsInputTexture()) {
- // We should be binding the DOM element texture sampler only if the author is using the CSS mix function.
- ASSERT(m_programType == ProgramTypeBlendsElementTexture);
- ASSERT(m_compiledProgram->samplerLocation() != -1);
-
- m_context->activeTexture(GL_TEXTURE0);
- m_context->uniform1i(m_compiledProgram->samplerLocation(), 0);
- m_context->bindTexture(GL_TEXTURE_2D, inputTexture);
- m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
-
- if (m_compiledProgram->projectionMatrixLocation() != -1) {
- TransformationMatrix projectionMatrix;
- orthogonalProjectionMatrix(projectionMatrix, -0.5, 0.5, -0.5, 0.5);
- float glProjectionMatrix[16];
- projectionMatrix.toColumnMajorFloatArray(glProjectionMatrix);
- m_context->uniformMatrix4fv(m_compiledProgram->projectionMatrixLocation(), 1, false, &glProjectionMatrix[0]);
- }
-
- ASSERT(m_meshColumns);
- ASSERT(m_meshRows);
-
- if (m_compiledProgram->meshSizeLocation() != -1)
- m_context->uniform2f(m_compiledProgram->meshSizeLocation(), m_meshColumns, m_meshRows);
-
- if (m_compiledProgram->tileSizeLocation() != -1)
- m_context->uniform2f(m_compiledProgram->tileSizeLocation(), 1.0 / m_meshColumns, 1.0 / m_meshRows);
-
- if (m_compiledProgram->meshBoxLocation() != -1) {
- // FIXME: This will change when filter margins will be implemented,
- // see https://bugs.webkit.org/show_bug.cgi?id=71400
- m_context->uniform4f(m_compiledProgram->meshBoxLocation(), -0.5, -0.5, 1.0, 1.0);
- }
-
- if (m_compiledProgram->samplerSizeLocation() != -1)
- m_context->uniform2f(m_compiledProgram->samplerSizeLocation(), m_contextSize.width(), m_contextSize.height());
-
- m_context->bindBuffer(GL_ARRAY_BUFFER, m_mesh->verticesBufferObject());
- m_context->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_mesh->elementsBufferObject());
-
- bindVertexAttribute(m_compiledProgram->positionAttribLocation(), PositionAttribSize, PositionAttribOffset);
- bindVertexAttribute(m_compiledProgram->texAttribLocation(), TexAttribSize, TexAttribOffset);
- bindVertexAttribute(m_compiledProgram->meshAttribLocation(), MeshAttribSize, MeshAttribOffset);
- if (m_meshType == MeshTypeDetached)
- bindVertexAttribute(m_compiledProgram->triangleAttribLocation(), TriangleAttribSize, TriangleAttribOffset);
-
- bindProgramParameters();
-}
-
-void CustomFilterRenderer::unbindVertexAttributes()
-{
- unbindVertexAttribute(m_compiledProgram->positionAttribLocation());
- unbindVertexAttribute(m_compiledProgram->texAttribLocation());
- unbindVertexAttribute(m_compiledProgram->meshAttribLocation());
- if (m_meshType == MeshTypeDetached)
- unbindVertexAttribute(m_compiledProgram->triangleAttribLocation());
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterRenderer.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterRenderer.h
deleted file mode 100644
index 059fc42a448..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterRenderer.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
- * Copyright (C) 2012 Company 100, 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:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterRenderer_h
-#define CustomFilterRenderer_h
-
-#include "platform/geometry/IntSize.h"
-#include "platform/graphics/GraphicsTypes3D.h"
-#include "platform/graphics/filters/custom/CustomFilterConstants.h"
-#include "platform/graphics/filters/custom/CustomFilterParameterList.h"
-#include "wtf/RefCounted.h"
-#include "wtf/RefPtr.h"
-
-namespace WebCore {
-
-class CustomFilterArrayParameter;
-class CustomFilterCompiledProgram;
-class CustomFilterMesh;
-class CustomFilterNumberParameter;
-class CustomFilterTransformParameter;
-class GraphicsContext3D;
-
-class CustomFilterRenderer : public RefCounted<CustomFilterRenderer> {
-public:
- static PassRefPtr<CustomFilterRenderer> create(PassRefPtr<GraphicsContext3D>, CustomFilterProgramType, const CustomFilterParameterList&,
- unsigned meshRows, unsigned meshColumns, CustomFilterMeshType);
- ~CustomFilterRenderer();
-
- bool premultipliedAlpha() const;
- bool programNeedsInputTexture() const;
-
- bool prepareForDrawing();
-
- void draw(Platform3DObject, const IntSize&);
-
- CustomFilterCompiledProgram* compiledProgram() const { return m_compiledProgram.get(); }
- void setCompiledProgram(PassRefPtr<CustomFilterCompiledProgram>);
-
-private:
- CustomFilterRenderer(PassRefPtr<GraphicsContext3D>, CustomFilterProgramType, const CustomFilterParameterList&,
- unsigned meshRows, unsigned meshColumns, CustomFilterMeshType);
-
- void initializeCompiledProgramIfNeeded();
- void initializeMeshIfNeeded();
-
- void bindVertexAttribute(int attributeLocation, unsigned size, unsigned offset);
- void unbindVertexAttribute(int attributeLocation);
- void bindProgramArrayParameters(int uniformLocation, CustomFilterArrayParameter*);
- void bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter*);
- void bindProgramTransformParameter(int uniformLocation, CustomFilterTransformParameter*);
- void bindProgramParameters();
- void bindProgramAndBuffers(Platform3DObject inputTexture);
- void unbindVertexAttributes();
-
- RefPtr<GraphicsContext3D> m_context;
- RefPtr<CustomFilterCompiledProgram> m_compiledProgram;
- CustomFilterProgramType m_programType;
- RefPtr<CustomFilterMesh> m_mesh;
- IntSize m_contextSize;
-
- CustomFilterParameterList m_parameters;
-
- unsigned m_meshRows;
- unsigned m_meshColumns;
- CustomFilterMeshType m_meshType;
-};
-
-} // namespace WebCore
-
-#endif // CustomFilterRenderer_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterTransformParameter.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterTransformParameter.cpp
deleted file mode 100644
index 317130288e1..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterTransformParameter.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterTransformParameter.h"
-
-#include "platform/geometry/FloatSize.h"
-
-namespace WebCore {
-
-PassRefPtr<CustomFilterParameter> CustomFilterTransformParameter::blend(const CustomFilterParameter* fromParameter, double progress)
-{
- if (!fromParameter || !isSameType(*fromParameter))
- return this;
-
- const CustomFilterTransformParameter* fromTransformParameter = static_cast<const CustomFilterTransformParameter*>(fromParameter);
- const TransformOperations& from = fromTransformParameter->operations();
- const TransformOperations& to = operations();
- if (from == to)
- return this;
-
- RefPtr<CustomFilterTransformParameter> result = CustomFilterTransformParameter::create(name());
- if (from.size() && to.size())
- result->setOperations(to.blend(from, progress));
- else
- result->setOperations(progress > 0.5 ? to : from);
- return result;
-}
-
-bool CustomFilterTransformParameter::operator==(const CustomFilterParameter& o) const
-{
- if (!isSameType(o))
- return false;
- const CustomFilterTransformParameter* other = static_cast<const CustomFilterTransformParameter*>(&o);
- return m_operations == other->m_operations;
-}
-
-void CustomFilterTransformParameter::applyTransform(TransformationMatrix& transform, const FloatSize& boxSize) const
-{
- for (unsigned i = 0, size = m_operations.size(); i < size; ++i)
- m_operations.at(i)->apply(transform, boxSize);
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterTransformParameter.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterTransformParameter.h
deleted file mode 100644
index 62dc58e05ea..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterTransformParameter.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterTransformParameter_h
-#define CustomFilterTransformParameter_h
-
-#include "platform/PlatformExport.h"
-#include "platform/graphics/filters/custom/CustomFilterParameter.h"
-#include "platform/transforms/TransformOperations.h"
-
-namespace WebCore {
-
-class FloatSize;
-class TransformationMatrix;
-
-class PLATFORM_EXPORT CustomFilterTransformParameter : public CustomFilterParameter {
-public:
- static PassRefPtr<CustomFilterTransformParameter> create(const String& name)
- {
- return adoptRef(new CustomFilterTransformParameter(name));
- }
-
- virtual PassRefPtr<CustomFilterParameter> blend(const CustomFilterParameter* fromParameter, double progress);
-
- virtual bool operator==(const CustomFilterParameter&) const;
-
- void applyTransform(TransformationMatrix&, const FloatSize& boxSize) const;
-
- const TransformOperations& operations() const { return m_operations; }
- void setOperations(const TransformOperations& value) { m_operations = value; }
-
-private:
- CustomFilterTransformParameter(const String& name)
- : CustomFilterParameter(Transform, name)
- {
- }
- virtual ~CustomFilterTransformParameter()
- {
- }
-
- TransformOperations m_operations;
-};
-
-} // namespace WebCore
-
-#endif // CustomFilterTransformParameter_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterValidatedProgram.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterValidatedProgram.cpp
deleted file mode 100644
index 63e384383be..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterValidatedProgram.cpp
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
-
-#include "platform/NotImplemented.h"
-#include "platform/graphics/angle/ANGLEPlatformBridge.h"
-#include "platform/graphics/filters/custom/CustomFilterConstants.h"
-#include "platform/graphics/filters/custom/CustomFilterGlobalContext.h"
-#include "wtf/HashMap.h"
-#include "wtf/Vector.h"
-#include "wtf/text/StringBuilder.h"
-#include "wtf/text/StringHash.h"
-
-namespace WebCore {
-
-#define SHADER(Src) (#Src)
-
-typedef HashMap<String, ShDataType> SymbolNameToTypeMap;
-
-static SymbolNameToTypeMap* builtInAttributeNameToTypeMap()
-{
- static SymbolNameToTypeMap* nameToTypeMap = 0;
- if (!nameToTypeMap) {
- nameToTypeMap = new SymbolNameToTypeMap;
- nameToTypeMap->set("a_meshCoord", SH_FLOAT_VEC2);
- nameToTypeMap->set("a_position", SH_FLOAT_VEC4);
- nameToTypeMap->set("a_texCoord", SH_FLOAT_VEC2);
- nameToTypeMap->set("a_triangleCoord", SH_FLOAT_VEC3);
- }
- return nameToTypeMap;
-}
-
-static SymbolNameToTypeMap* builtInUniformNameToTypeMap()
-{
- static SymbolNameToTypeMap* nameToTypeMap = 0;
- if (!nameToTypeMap) {
- nameToTypeMap = new SymbolNameToTypeMap;
- nameToTypeMap->set("u_meshBox", SH_FLOAT_VEC4);
- nameToTypeMap->set("u_meshSize", SH_FLOAT_VEC2);
- nameToTypeMap->set("u_projectionMatrix", SH_FLOAT_MAT4);
- nameToTypeMap->set("u_textureSize", SH_FLOAT_VEC2);
- nameToTypeMap->set("u_tileSize", SH_FLOAT_VEC2);
- }
- return nameToTypeMap;
-}
-
-static bool validateSymbols(const Vector<ANGLEShaderSymbol>& symbols, CustomFilterMeshType meshType)
-{
- for (size_t i = 0; i < symbols.size(); ++i) {
- const ANGLEShaderSymbol& symbol = symbols[i];
- switch (symbol.symbolType) {
- case SHADER_SYMBOL_TYPE_ATTRIBUTE: {
- SymbolNameToTypeMap* attributeNameToTypeMap = builtInAttributeNameToTypeMap();
- SymbolNameToTypeMap::iterator builtInAttribute = attributeNameToTypeMap->find(symbol.name);
- if (builtInAttribute == attributeNameToTypeMap->end()) {
- // The author defined a custom attribute.
- // FIXME: Report the validation error.
- // https://bugs.webkit.org/show_bug.cgi?id=74416
- return false;
- }
- if (meshType == MeshTypeAttached && symbol.name == "a_triangleCoord") {
- // a_triangleCoord is only available for detached meshes.
- // FIXME: Report the validation error.
- // https://bugs.webkit.org/show_bug.cgi?id=74416
- return false;
- }
- if (symbol.dataType != builtInAttribute->value) {
- // The author defined one of the built-in attributes with the wrong type.
- // FIXME: Report the validation error.
- // https://bugs.webkit.org/show_bug.cgi?id=74416
- return false;
- }
- break;
- }
- case SHADER_SYMBOL_TYPE_UNIFORM: {
- if (symbol.isSampler()) {
- // FIXME: For now, we restrict shaders with any sampler defined.
- // When we implement texture parameters, we will allow shaders whose samplers are bound to valid textures.
- // We must not allow OpenGL to give unbound samplers a default value of 0 because that references the element texture,
- // which should be inaccessible to the author's shader code.
- // https://bugs.webkit.org/show_bug.cgi?id=96230
- return false;
- }
-
- SymbolNameToTypeMap* uniformNameToTypeMap = builtInUniformNameToTypeMap();
- SymbolNameToTypeMap::iterator builtInUniform = uniformNameToTypeMap->find(symbol.name);
- if (builtInUniform != uniformNameToTypeMap->end() && (symbol.isArray || symbol.dataType != builtInUniform->value)) {
- // The author defined one of the built-in uniforms with the wrong type.
- // FIXME: Report the validation error.
- // https://bugs.webkit.org/show_bug.cgi?id=74416
- return false;
- }
- break;
- }
- default:
- ASSERT_NOT_REACHED();
- break;
- }
- }
-
- return true;
-}
-
-String CustomFilterValidatedProgram::defaultVertexShaderString()
-{
- DEFINE_STATIC_LOCAL(String, vertexShaderString, (SHADER(
- attribute mediump vec4 a_position;
- uniform mediump mat4 u_projectionMatrix;
-
- void main()
- {
- gl_Position = u_projectionMatrix * a_position;
- }
- )));
- return vertexShaderString;
-}
-
-String CustomFilterValidatedProgram::defaultFragmentShaderString()
-{
- DEFINE_STATIC_LOCAL(String, fragmentShaderString, (SHADER(
- void main()
- {
- }
- )));
- return fragmentShaderString;
-}
-
-CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalContext* globalContext, const CustomFilterProgramInfo& programInfo)
- : m_globalContext(globalContext)
- , m_programInfo(programInfo)
- , m_isInitialized(false)
-{
- platformInit();
-
- String originalVertexShader = programInfo.vertexShaderString();
- if (originalVertexShader.isNull())
- originalVertexShader = defaultVertexShaderString();
-
- String originalFragmentShader = programInfo.fragmentShaderString();
- if (originalFragmentShader.isNull())
- originalFragmentShader = defaultFragmentShaderString();
-
- // Shaders referenced from the CSS mix function use a different validator than regular WebGL shaders. See core/platform/graphics/filters/custom/CustomFilterGlobalContext.h for more details.
- bool blendsElementTexture = (programInfo.programType() == ProgramTypeBlendsElementTexture);
- ANGLEPlatformBridge* validator = blendsElementTexture ? m_globalContext->mixShaderValidator() : m_globalContext->webglShaderValidator();
- String vertexShaderLog, fragmentShaderLog;
- Vector<ANGLEShaderSymbol> symbols;
- bool vertexShaderValid = validator->compileShaderSource(originalVertexShader.utf8().data(), SHADER_TYPE_VERTEX, m_validatedVertexShader, vertexShaderLog, symbols);
- bool fragmentShaderValid = validator->compileShaderSource(originalFragmentShader.utf8().data(), SHADER_TYPE_FRAGMENT, m_validatedFragmentShader, fragmentShaderLog, symbols);
- if (!vertexShaderValid || !fragmentShaderValid) {
- // FIXME: Report the validation errors.
- // https://bugs.webkit.org/show_bug.cgi?id=74416
- return;
- }
-
- if (!validateSymbols(symbols, m_programInfo.meshType())) {
- // FIXME: Report validation errors.
- // https://bugs.webkit.org/show_bug.cgi?id=74416
- return;
- }
-
- // We need to add texture access, blending, and compositing code to shaders that are referenced from the CSS mix function.
- if (blendsElementTexture) {
- rewriteMixVertexShader(symbols);
- rewriteMixFragmentShader();
- }
-
- m_isInitialized = true;
-}
-
-PassRefPtr<CustomFilterCompiledProgram> CustomFilterValidatedProgram::compiledProgram()
-{
- ASSERT(m_isInitialized && m_globalContext && !m_validatedVertexShader.isNull() && !m_validatedFragmentShader.isNull());
- if (!m_compiledProgram) {
- m_compiledProgram = CustomFilterCompiledProgram::create(m_globalContext->context(), m_validatedVertexShader, m_validatedFragmentShader, m_programInfo.programType());
- ASSERT(m_compiledProgram->isInitialized());
- ASSERT(m_compiledProgram->samplerLocation() != -1 || !needsInputTexture());
- }
- return m_compiledProgram;
-}
-
-bool CustomFilterValidatedProgram::needsInputTexture() const
-{
- return m_programInfo.programType() == ProgramTypeBlendsElementTexture
- && m_programInfo.mixSettings().compositeOperator != CompositeClear
- && m_programInfo.mixSettings().compositeOperator != CompositeCopy;
-}
-
-void CustomFilterValidatedProgram::rewriteMixVertexShader(const Vector<ANGLEShaderSymbol>& symbols)
-{
- ASSERT(m_programInfo.programType() == ProgramTypeBlendsElementTexture);
-
- // If the author defined a_texCoord, we can use it to shuttle the texture coordinate to the fragment shader.
- // Note that vertex attributes are read-only in GLSL, so the author could not have changed a_texCoord's value.
- // Also, note that we would have already rejected the shader if the author defined a_texCoord with the wrong type.
- bool texCoordAttributeDefined = false;
- for (size_t i = 0; i < symbols.size(); ++i) {
- if (symbols[i].name == "a_texCoord")
- texCoordAttributeDefined = true;
- }
-
- if (!texCoordAttributeDefined)
- m_validatedVertexShader.append("attribute mediump vec2 a_texCoord;");
-
- // During validation, ANGLE renamed the author's "main" function to "css_main".
- // We write our own "main" function and call "css_main" from it.
- // This makes rewriting easy and ensures that our code runs after all author code.
- m_validatedVertexShader.append(SHADER(
- varying mediump vec2 css_v_texCoord;
-
- void main()
- {
- css_main();
- css_v_texCoord = a_texCoord;
- }
- ));
-}
-
-void CustomFilterValidatedProgram::rewriteMixFragmentShader()
-{
- ASSERT(m_programInfo.programType() == ProgramTypeBlendsElementTexture);
-
- StringBuilder builder;
- // ANGLE considered these symbols as built-ins during validation under the SH_CSS_SHADERS_SPEC flag.
- // Now, we have to define these symbols in order to make this shader valid GLSL.
- // We define these symbols before the author's shader code, which makes them accessible to author code.
- builder.append(SHADER(
- mediump vec4 css_MixColor = vec4(0.0);
- mediump mat4 css_ColorMatrix = mat4(1.0);
- ));
- builder.append(m_validatedFragmentShader);
- builder.append(blendFunctionString(m_programInfo.mixSettings().blendMode));
- builder.append(compositeFunctionString(m_programInfo.mixSettings().compositeOperator));
- // We define symbols like "css_u_texture" after the author's shader code, which makes them inaccessible to author code.
- // In particular, "css_u_texture" represents the DOM element texture, so it's important to keep it inaccessible to
- // author code for security reasons.
- builder.append(SHADER(
- uniform sampler2D css_u_texture;
- varying mediump vec2 css_v_texCoord;
-
- void main()
- {
- css_main();
- mediump vec4 originalColor = texture2D(css_u_texture, css_v_texCoord);
- mediump vec4 multipliedColor = clamp(css_ColorMatrix * originalColor, 0.0, 1.0);
- mediump vec4 clampedMixColor = clamp(css_MixColor, 0.0, 1.0);
- mediump vec3 blendedColor = css_BlendColor(multipliedColor.rgb, clampedMixColor.rgb);
- mediump vec3 weightedColor = (1.0 - multipliedColor.a) * clampedMixColor.rgb + multipliedColor.a * blendedColor;
- gl_FragColor = css_Composite(multipliedColor.rgb, multipliedColor.a, weightedColor.rgb, clampedMixColor.a);
- }
- ));
- m_validatedFragmentShader = builder.toString();
-}
-
-String CustomFilterValidatedProgram::blendFunctionString(blink::WebBlendMode blendMode)
-{
- // Implemented using the same symbol names as the Compositing and Blending spec:
- // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnormal
- // Cs: is the source color in css_BlendColor() and the source color component in css_BlendComponent()
- // Cb: is the backdrop color in css_BlendColor() and the backdrop color component in css_BlendComponent()
- const char* blendColorExpression = "vec3(css_BlendComponent(Cb.r, Cs.r), css_BlendComponent(Cb.g, Cs.g), css_BlendComponent(Cb.b, Cs.b))";
- const char* blendComponentExpression = "Co = 0.0;";
- bool needsLuminosityHelperFunctions = false;
- bool needsSaturationHelperFunctions = false;
- String blendFunctionString;
- switch (blendMode) {
- case blink::WebBlendModeNormal:
- blendColorExpression = "Cs";
- break;
- case blink::WebBlendModeMultiply:
- blendColorExpression = "Cs * Cb";
- break;
- case blink::WebBlendModeScreen:
- blendColorExpression = "Cb + Cs - (Cb * Cs)";
- break;
- case blink::WebBlendModeDarken:
- blendColorExpression = "min(Cb, Cs)";
- break;
- case blink::WebBlendModeLighten:
- blendColorExpression = "max(Cb, Cs)";
- break;
- case blink::WebBlendModeDifference:
- blendColorExpression = "abs(Cb - Cs)";
- break;
- case blink::WebBlendModeExclusion:
- blendColorExpression = "Cb + Cs - 2.0 * Cb * Cs";
- break;
- case blink::WebBlendModeOverlay:
- /*
- Co = HardLight(Cs, Cb)
- = if(Cb <= 0.5)
- Multiply(Cs, 2 x Cb)
- else
- Screen(Cs, 2 x Cb - 1)
- = if(Cb <= 0.5)
- Cs x (2 x Cb)
- else
- Cs + (2 x Cb - 1) - (Cs x (2 x Cb - 1))
- */
- blendComponentExpression = SHADER(
- if (Cb <= 0.5)
- Co = Cs * (2.0 * Cb);
- else
- Co = Cs + (2.0 * Cb - 1.0) - (Cs * (2.0 * Cb - 1.0));
- );
- break;
- case blink::WebBlendModeColorDodge:
- /*
- Co = if(Cs < 1)
- min(1, Cb / (1 - Cs))
- else
- 1
- */
- blendComponentExpression = SHADER(
- if (Cs < 1.0)
- Co = min(1.0, Cb / (1.0 - Cs));
- else
- Co = 1.0;
- );
- break;
- case blink::WebBlendModeColorBurn:
- /*
- Co = if(Cs > 0)
- 1 - min(1, (1 - Cb) / Cs)
- else
- 0
- */
- blendComponentExpression = SHADER(
- if (Cs > 0.0)
- Co = 1.0 - min(1.0, (1.0 - Cb) / Cs);
- else
- Co = 0.0;
- );
- break;
- case blink::WebBlendModeHardLight:
- /*
- Co = if(Cs <= 0.5)
- Multiply(Cb, 2 x Cs)
- else
- Screen(Cb, 2 x Cs -1)
- = if(Cs <= 0.5)
- Cb x (2 x Cs)
- else
- Cb + (2 x Cs - 1) - (Cb x (2 x Cs - 1))
- */
- blendComponentExpression = SHADER(
- if (Cs <= 0.5)
- Co = Cb * (2.0 * Cs);
- else
- Co = Cb + (2.0 * Cs - 1.0) - (Cb * (2.0 * Cs - 1.0));
- );
- break;
- case blink::WebBlendModeSoftLight:
- /*
- Co = if(Cs <= 0.5)
- Cb - (1 - 2 x Cs) x Cb x (1 - Cb)
- else
- Cb + (2 x Cs - 1) x (D(Cb) - Cb)
-
- with
-
- D(Cb) = if(Cb <= 0.25)
- (16 * Cb - 12) x Cb + 4) x Cb
- else
- sqrt(Cb)
- */
- blendComponentExpression = SHADER(
- mediump float D;
- if (Cb <= 0.25)
- D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb;
- else
- D = sqrt(Cb);
-
- if (Cs <= 0.5)
- Co = Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb);
- else
- Co = Cb + (2.0 * Cs - 1.0) * (D - Cb);
- );
- break;
- case blink::WebBlendModeColor:
- needsLuminosityHelperFunctions = true;
- blendColorExpression = "css_SetLum(Cs, css_Lum(Cb))";
- break;
- case blink::WebBlendModeLuminosity:
- needsLuminosityHelperFunctions = true;
- blendColorExpression = "css_SetLum(Cb, css_Lum(Cs))";
- break;
- case blink::WebBlendModeHue:
- needsLuminosityHelperFunctions = true;
- needsSaturationHelperFunctions = true;
- blendColorExpression = "css_SetLum(css_SetSat(Cs, css_Sat(Cb)), css_Lum(Cb))";
- break;
- case blink::WebBlendModeSaturation:
- needsLuminosityHelperFunctions = true;
- needsSaturationHelperFunctions = true;
- blendColorExpression = "css_SetLum(css_SetSat(Cb, css_Sat(Cs)), css_Lum(Cb))";
- break;
- default:
- ASSERT_NOT_REACHED();
- }
-
- if (needsLuminosityHelperFunctions) {
- blendFunctionString.append(SHADER(
- mediump float css_Lum(mediump vec3 C)
- {
- return 0.3 * C.r + 0.59 * C.g + 0.11 * C.b;
- }
- mediump vec3 css_ClipColor(mediump vec3 C)
- {
- mediump float L = css_Lum(C);
- mediump float n = min(min(C.r, C.g), C.b);
- mediump float x = max(max(C.r, C.g), C.b);
- if (n < 0.0)
- C = L + (((C - L) * L) / (L - n));
- if (x > 1.0)
- C = L + (((C - L) * (1.0 - L) / (x - L)));
- return C;
- }
- mediump vec3 css_SetLum(mediump vec3 C, mediump float l)
- {
- C += l - css_Lum(C);
- return css_ClipColor(C);
- }
- ));
- }
-
- if (needsSaturationHelperFunctions) {
- blendFunctionString.append(SHADER(
- mediump float css_Sat(mediump vec3 C)
- {
- mediump float cMin = min(min(C.r, C.g), C.b);
- mediump float cMax = max(max(C.r, C.g), C.b);
- return cMax - cMin;
- }
- void css_SetSatHelper(inout mediump float cMin, inout mediump float cMid, inout mediump float cMax, mediump float s)
- {
- if (cMax > cMin) {
- cMid = (((cMid - cMin) * s) / (cMax - cMin));
- cMax = s;
- } else {
- cMid = cMax = 0.0;
- }
- cMin = 0.0;
- }
- mediump vec3 css_SetSat(mediump vec3 C, mediump float s)
- {
- if (C.r <= C.g) {
- if (C.g <= C.b) {
- css_SetSatHelper(C.r, C.g, C.b, s);
- } else {
- if (C.r <= C.b)
- css_SetSatHelper(C.r, C.b, C.g, s);
- else
- css_SetSatHelper(C.b, C.r, C.g, s);
- }
- } else {
- if (C.r <= C.b) {
- css_SetSatHelper(C.g, C.r, C.b, s);
- } else {
- if (C.g <= C.b)
- css_SetSatHelper(C.g, C.b, C.r, s);
- else
- css_SetSatHelper(C.b, C.g, C.r, s);
- }
- }
- return C;
- }
- ));
- }
-
- blendFunctionString.append(String::format(SHADER(
- mediump float css_BlendComponent(mediump float Cb, mediump float Cs)
- {
- mediump float Co;
- %s
- return Co;
- }
- mediump vec3 css_BlendColor(mediump vec3 Cb, mediump vec3 Cs)
- {
- return %s;
- }
- ), blendComponentExpression, blendColorExpression));
-
- return blendFunctionString;
-}
-
-String CustomFilterValidatedProgram::compositeFunctionString(CompositeOperator compositeOperator)
-{
- // Use the same symbol names as the Compositing and Blending spec:
- // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnormal
- // Cs: is the source color
- // Cb: is the backdrop color
- // as: is the source alpha
- // ab: is the backdrop alpha
- // Fa: is defined by the Porter Duff operator in use
- // Fb: is defined by the Porter Duff operator in use
- const char* Fa = 0;
- const char* Fb = 0;
- switch (compositeOperator) {
- case CompositeSourceAtop:
- Fa = "ab";
- Fb = "1.0 - as";
- break;
- case CompositeClear:
- Fa = "0.0";
- Fb = "0.0";
- break;
- case CompositeCopy:
- Fa = "1.0";
- Fb = "0.0";
- break;
- case CompositeSourceOver:
- Fa = "1.0";
- Fb = "1.0 - as";
- break;
- case CompositeSourceIn:
- Fa = "ab";
- Fb = "0.0";
- break;
- case CompositeSourceOut:
- Fa = "1.0 - ab";
- Fb = "0.0";
- break;
- case CompositeDestinationOver:
- Fa = "1.0 - ab";
- Fb = "1.0";
- break;
- case CompositeDestinationIn:
- Fa = "0.0";
- Fb = "as";
- break;
- case CompositeDestinationOut:
- Fa = "0.0";
- Fb = "1.0 - as";
- break;
- case CompositeDestinationAtop:
- Fa = "1.0 - ab";
- Fb = "as";
- break;
- case CompositeXOR:
- Fa = "1.0 - ab";
- Fb = "1.0 - as";
- break;
- case CompositePlusLighter:
- notImplemented();
- return String();
- default:
- // The CSS parser should not have accepted any other composite operators.
- ASSERT_NOT_REACHED();
- return String();
- }
-
- ASSERT(Fa && Fb);
- // Use the general formula for compositing, lifted from the spec:
- // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#generalformula
- return String::format(SHADER(
- mediump vec4 css_Composite(mediump vec3 Cb, mediump float ab, mediump vec3 Cs, mediump float as)
- {
- mediump float Fa = %s;
- mediump float Fb = %s;
- return vec4(as * Fa * Cs + ab * Fb * Cb, as * Fa + ab * Fb);
- }
- ), Fa, Fb);
-}
-
-CustomFilterValidatedProgram::~CustomFilterValidatedProgram()
-{
- platformDestroy();
-
- if (m_globalContext)
- m_globalContext->removeValidatedProgram(this);
-}
-
-CustomFilterProgramInfo CustomFilterValidatedProgram::validatedProgramInfo() const
-{
- ASSERT(m_isInitialized);
- return CustomFilterProgramInfo(m_validatedVertexShader, m_validatedFragmentShader, m_programInfo.programType(), m_programInfo.mixSettings(), m_programInfo.meshType());
-}
-
-void CustomFilterValidatedProgram::platformInit()
-{
-}
-
-void CustomFilterValidatedProgram::platformDestroy()
-{
-}
-
-} // namespace WebCore
-
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterValidatedProgram.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterValidatedProgram.h
deleted file mode 100644
index fed78481ae8..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/CustomFilterValidatedProgram.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 CustomFilterValidatedProgram_h
-#define CustomFilterValidatedProgram_h
-
-#include "platform/graphics/filters/custom/CustomFilterCompiledProgram.h"
-#include "platform/graphics/filters/custom/CustomFilterProgramInfo.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/RefCounted.h"
-#include "wtf/RefPtr.h"
-#include "wtf/text/WTFString.h"
-
-// PlatformCompiledProgram defines a type that is compatible with the framework used to implement accelerated compositing on a particular platform.
-namespace WebCore {
-
-struct ANGLEShaderSymbol;
-class CustomFilterCompiledProgram;
-class CustomFilterGlobalContext;
-
-//
-// A unique combination of vertex shader and fragment shader is only validated and compiled once.
-// All shaders are validated through ANGLE in CustomFilterValidatedProgram before being compiled by the GraphicsContext3D in CustomFilterCompiledProgram.
-// For shaders that use the CSS mix function, CustomFilterValidatedProgram adds shader code to perform DOM texture access, blending, and compositing.
-//
-// The CustomFilterGlobalContext caches the validated programs.
-// CustomFilterValidatedProgram owns a CustomFilterCompiledProgram if validation and compilation succeeds.
-// Thus, compiled programs are cached via their validated program owners.
-//
-// CustomFilterGlobalContext has a weak reference to the CustomFilterValidatedProgram.
-// Thus, the CustomFilterValidatedProgram destructor needs to notify the CustomFilterGlobalContext to remove the program from the cache.
-// FECustomFilter is the reference owner of the CustomFilterValidatedProgram.
-// Thus, a validated and compiled shader is only kept alive as long as there is at least one visible layer that applies the shader.
-//
-class PLATFORM_EXPORT CustomFilterValidatedProgram : public RefCounted<CustomFilterValidatedProgram> {
-public:
- static PassRefPtr<CustomFilterValidatedProgram> create(CustomFilterGlobalContext* globalContext, const CustomFilterProgramInfo& programInfo)
- {
- return adoptRef(new CustomFilterValidatedProgram(globalContext, programInfo));
- }
-
- ~CustomFilterValidatedProgram();
-
- const CustomFilterProgramInfo& programInfo() const { return m_programInfo; }
- CustomFilterProgramInfo validatedProgramInfo() const;
-
- PassRefPtr<CustomFilterCompiledProgram> compiledProgram();
-
- const String& validatedVertexShader() const
- {
- ASSERT(m_isInitialized);
- return m_validatedVertexShader;
- }
-
- const String& validatedFragmentShader() const
- {
- ASSERT(m_isInitialized);
- return m_validatedFragmentShader;
- }
-
- bool isInitialized() const { return m_isInitialized; }
-
- // 'detachFromGlobalContext' is called when the CustomFilterGlobalContext is deleted, and there's no need for the callback anymore.
- // Note that CustomFilterGlobalContext does not keep a strong reference to the CustomFilterValidatedProgram.
- void detachFromGlobalContext() { m_globalContext = 0; }
-private:
- CustomFilterValidatedProgram(CustomFilterGlobalContext*, const CustomFilterProgramInfo&);
-
- void platformInit();
- void platformDestroy();
-
- static String defaultVertexShaderString();
- static String defaultFragmentShaderString();
-
- static String blendFunctionString(blink::WebBlendMode);
- static String compositeFunctionString(CompositeOperator);
-
- void rewriteMixVertexShader(const Vector<ANGLEShaderSymbol>& symbols);
- void rewriteMixFragmentShader();
-
- bool needsInputTexture() const;
-
- CustomFilterGlobalContext* m_globalContext;
- CustomFilterProgramInfo m_programInfo;
-
- String m_validatedVertexShader;
- String m_validatedFragmentShader;
-
- RefPtr<CustomFilterCompiledProgram> m_compiledProgram;
-
- bool m_isInitialized;
-};
-
-}
-
-
-#endif
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/FECustomFilter.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/FECustomFilter.cpp
deleted file mode 100644
index bcce901401a..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/FECustomFilter.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
- * Copyright (C) 2013 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:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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"
-#include "platform/graphics/filters/custom/FECustomFilter.h"
-
-#include "platform/graphics/Extensions3D.h"
-#include "platform/graphics/GraphicsContext3D.h"
-#include "platform/graphics/filters/custom/CustomFilterRenderer.h"
-#include "platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
-#include "platform/text/TextStream.h"
-#include "wtf/Uint8ClampedArray.h"
-
-namespace WebCore {
-
-FECustomFilter::FECustomFilter(Filter* filter, PassRefPtr<GraphicsContext3D> context, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters,
- unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
- : FilterEffect(filter)
- , m_context(context)
- , m_validatedProgram(validatedProgram)
- , m_inputTexture(0)
- , m_frameBuffer(0)
- , m_depthBuffer(0)
- , m_destTexture(0)
- , m_triedMultisampleBuffer(false)
- , m_multisampleFrameBuffer(0)
- , m_multisampleRenderBuffer(0)
- , m_multisampleDepthBuffer(0)
-{
- // We will not pass a CustomFilterCompiledProgram here, as we only want to compile it when we actually need it in the first paint.
- m_customFilterRenderer = CustomFilterRenderer::create(m_context, m_validatedProgram->programInfo().programType(), parameters, meshRows, meshColumns, meshType);
-}
-
-PassRefPtr<FECustomFilter> FECustomFilter::create(Filter* filter, PassRefPtr<GraphicsContext3D> context, PassRefPtr<CustomFilterValidatedProgram> validatedProgram, const CustomFilterParameterList& parameters,
- unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
-{
- return adoptRef(new FECustomFilter(filter, context, validatedProgram, parameters, meshRows, meshColumns, meshType));
-}
-
-FECustomFilter::~FECustomFilter()
-{
- deleteRenderBuffers();
-}
-
-void FECustomFilter::deleteRenderBuffers()
-{
- ASSERT(m_context);
- m_context->makeContextCurrent();
- if (m_inputTexture) {
- m_context->deleteTexture(m_inputTexture);
- m_inputTexture = 0;
- }
- if (m_frameBuffer) {
- // Make sure to unbind any framebuffer from the context first, otherwise
- // some platforms might refuse to bind the same buffer id again.
- m_context->bindFramebuffer(GL_FRAMEBUFFER, 0);
- m_context->deleteFramebuffer(m_frameBuffer);
- m_frameBuffer = 0;
- }
- if (m_depthBuffer) {
- m_context->deleteRenderbuffer(m_depthBuffer);
- m_depthBuffer = 0;
- }
- if (m_destTexture) {
- m_context->deleteTexture(m_destTexture);
- m_destTexture = 0;
- }
- deleteMultisampleRenderBuffers();
-}
-
-void FECustomFilter::deleteMultisampleRenderBuffers()
-{
- if (m_multisampleFrameBuffer) {
- // Make sure to unbind any framebuffer from the context first, otherwise
- // some platforms might refuse to bind the same buffer id again.
- m_context->bindFramebuffer(GL_FRAMEBUFFER, 0);
- m_context->deleteFramebuffer(m_multisampleFrameBuffer);
- m_multisampleFrameBuffer = 0;
- }
- if (m_multisampleRenderBuffer) {
- m_context->deleteRenderbuffer(m_multisampleRenderBuffer);
- m_multisampleRenderBuffer = 0;
- }
- if (m_multisampleDepthBuffer) {
- m_context->deleteRenderbuffer(m_multisampleDepthBuffer);
- m_multisampleDepthBuffer = 0;
- }
-}
-
-void FECustomFilter::applySoftware()
-{
- if (!applyShader())
- clearShaderResult();
-}
-
-void FECustomFilter::clearShaderResult()
-{
- clearResult();
- Uint8ClampedArray* dstPixelArray = createUnmultipliedImageResult();
- if (!dstPixelArray)
- return;
-
- FilterEffect* in = inputEffect(0);
- setIsAlphaImage(in->isAlphaImage());
- IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- in->copyUnmultipliedImage(dstPixelArray, effectDrawingRect);
-}
-
-void FECustomFilter::drawFilterMesh(Platform3DObject inputTexture)
-{
- bool multisample = canUseMultisampleBuffers();
- m_context->bindFramebuffer(GL_FRAMEBUFFER, multisample ? m_multisampleFrameBuffer : m_frameBuffer);
- m_context->viewport(0, 0, m_contextSize.width(), m_contextSize.height());
-
- m_context->clearColor(0, 0, 0, 0);
- m_context->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- m_customFilterRenderer->draw(inputTexture, m_contextSize);
-
- if (multisample)
- resolveMultisampleBuffer();
-}
-
-bool FECustomFilter::prepareForDrawing()
-{
- m_context->makeContextCurrent();
-
- // Lazily inject the compiled program into the CustomFilterRenderer.
- if (!m_customFilterRenderer->compiledProgram())
- m_customFilterRenderer->setCompiledProgram(m_validatedProgram->compiledProgram());
-
- if (!m_customFilterRenderer->prepareForDrawing())
- return false;
-
- // Only allocate a texture if the program needs one and the caller doesn't allocate one by itself.
- if ((m_customFilterRenderer->programNeedsInputTexture() && !ensureInputTexture()) || !ensureFrameBuffer())
- return false;
-
- return true;
-}
-
-bool FECustomFilter::applyShader()
-{
- Uint8ClampedArray* dstPixelArray = m_customFilterRenderer->premultipliedAlpha() ? createPremultipliedImageResult() : createUnmultipliedImageResult();
- if (!dstPixelArray)
- return false;
-
- if (!prepareForDrawing())
- return false;
-
- FilterEffect* in = inputEffect(0);
- IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- IntSize newContextSize(effectDrawingRect.size());
- if (!resizeContextIfNeeded(newContextSize))
- return false;
-
- bool needsInputTexture = m_customFilterRenderer->programNeedsInputTexture();
- if (needsInputTexture) {
- RefPtr<Uint8ClampedArray> srcPixelArray = in->asUnmultipliedImage(effectDrawingRect);
- uploadInputTexture(srcPixelArray.get());
- }
- drawFilterMesh(needsInputTexture ? m_inputTexture : 0);
-
- ASSERT(static_cast<size_t>(newContextSize.width() * newContextSize.height() * 4) == dstPixelArray->length());
- m_context->readPixels(0, 0, newContextSize.width(), newContextSize.height(), GL_RGBA, GL_UNSIGNED_BYTE, dstPixelArray->data());
-
- return true;
-}
-
-bool FECustomFilter::ensureInputTexture()
-{
- if (!m_inputTexture)
- m_inputTexture = m_context->createTexture();
- return m_inputTexture;
-}
-
-void FECustomFilter::uploadInputTexture(Uint8ClampedArray* srcPixelArray)
-{
- m_context->bindTexture(GL_TEXTURE_2D, m_inputTexture);
- m_context->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_contextSize.width(), m_contextSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, srcPixelArray->data());
-}
-
-bool FECustomFilter::ensureFrameBuffer()
-{
- if (!m_frameBuffer)
- m_frameBuffer = m_context->createFramebuffer();
- if (!m_depthBuffer)
- m_depthBuffer = m_context->createRenderbuffer();
- if (!m_destTexture)
- m_destTexture = m_context->createTexture();
- return m_frameBuffer && m_depthBuffer && m_destTexture;
-}
-
-bool FECustomFilter::createMultisampleBuffer()
-{
- ASSERT(!m_triedMultisampleBuffer);
- m_triedMultisampleBuffer = true;
-
- Extensions3D* extensions = m_context->extensions();
- if (!extensions
- || !extensions->supports("GL_ANGLE_framebuffer_multisample")
- || !extensions->supports("GL_ANGLE_framebuffer_blit")
- || !extensions->supports("GL_OES_rgb8_rgba8"))
- return false;
-
- extensions->ensureEnabled("GL_ANGLE_framebuffer_blit");
- extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
- extensions->ensureEnabled("GL_OES_rgb8_rgba8");
-
- if (!m_multisampleFrameBuffer)
- m_multisampleFrameBuffer = m_context->createFramebuffer();
- if (!m_multisampleRenderBuffer)
- m_multisampleRenderBuffer = m_context->createRenderbuffer();
- if (!m_multisampleDepthBuffer)
- m_multisampleDepthBuffer = m_context->createRenderbuffer();
-
- return true;
-}
-
-void FECustomFilter::resolveMultisampleBuffer()
-{
- ASSERT(m_triedMultisampleBuffer && m_multisampleFrameBuffer && m_multisampleRenderBuffer && m_multisampleDepthBuffer);
- m_context->bindFramebuffer(Extensions3D::READ_FRAMEBUFFER, m_multisampleFrameBuffer);
- m_context->bindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, m_frameBuffer);
-
- ASSERT(m_context->extensions());
- m_context->extensions()->blitFramebuffer(0, 0, m_contextSize.width(), m_contextSize.height(), 0, 0, m_contextSize.width(), m_contextSize.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
-
- m_context->bindFramebuffer(Extensions3D::READ_FRAMEBUFFER, 0);
- m_context->bindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, 0);
-
- m_context->bindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);
-}
-
-bool FECustomFilter::canUseMultisampleBuffers() const
-{
- return m_triedMultisampleBuffer && m_multisampleFrameBuffer && m_multisampleRenderBuffer && m_multisampleDepthBuffer;
-}
-
-bool FECustomFilter::resizeMultisampleBuffers(const IntSize& newContextSize)
-{
- if (!m_triedMultisampleBuffer && !createMultisampleBuffer())
- return false;
-
- if (!canUseMultisampleBuffers())
- return false;
-
- static const int kMaxSampleCount = 4;
- int maxSupportedSampleCount = 0;
- m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSupportedSampleCount);
- int sampleCount = std::min(kMaxSampleCount, maxSupportedSampleCount);
- if (!sampleCount) {
- deleteMultisampleRenderBuffers();
- return false;
- }
-
- Extensions3D* extensions = m_context->extensions();
- ASSERT(extensions);
-
- m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFrameBuffer);
-
- m_context->bindRenderbuffer(GL_RENDERBUFFER, m_multisampleRenderBuffer);
- extensions->renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, Extensions3D::RGBA8_OES, newContextSize.width(), newContextSize.height());
- m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_multisampleRenderBuffer);
-
- m_context->bindRenderbuffer(GL_RENDERBUFFER, m_multisampleDepthBuffer);
- extensions->renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_DEPTH_COMPONENT16, newContextSize.width(), newContextSize.height());
- m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_multisampleDepthBuffer);
-
- m_context->bindRenderbuffer(GL_RENDERBUFFER, 0);
-
- if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
- deleteMultisampleRenderBuffers();
- return false;
- }
-
- return true;
-}
-
-bool FECustomFilter::resizeContextIfNeeded(const IntSize& newContextSize)
-{
- if (newContextSize.isEmpty())
- return false;
- if (m_contextSize == newContextSize)
- return true;
-
- int maxTextureSize = 0;
- m_context->getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
- if (newContextSize.height() > maxTextureSize || newContextSize.width() > maxTextureSize)
- return false;
-
- return resizeContext(newContextSize);
-}
-
-bool FECustomFilter::resizeContext(const IntSize& newContextSize)
-{
- bool multisample = resizeMultisampleBuffers(newContextSize);
-
- m_context->bindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);
- m_context->bindTexture(GL_TEXTURE_2D, m_destTexture);
- // We are going to clear the output buffer anyway, so we can safely initialize the destination texture with garbage data.
- // FIXME: GraphicsContext3D::texImage2DDirect is not implemented on Chromium.
- m_context->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, newContextSize.width(), newContextSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_destTexture, 0);
-
- // We don't need the depth buffer for the texture framebuffer, if we already
- // have a multisample buffer.
- if (!multisample) {
- m_context->bindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
- m_context->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, newContextSize.width(), newContextSize.height());
- m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer);
- }
-
- if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- return false;
-
- if (multisample) {
- // Clear the framebuffer first, otherwise the first blit will fail.
- m_context->clearColor(0, 0, 0, 0);
- m_context->clear(GL_COLOR_BUFFER_BIT);
- }
-
- m_context->bindRenderbuffer(GL_RENDERBUFFER, 0);
-
- m_contextSize = newContextSize;
- return true;
-}
-
-TextStream& FECustomFilter::externalRepresentation(TextStream& ts, int indent) const
-{
- writeIndent(ts, indent);
- ts << "[feCustomFilter";
- FilterEffect::externalRepresentation(ts);
- ts << "]\n";
- inputEffect(0)->externalRepresentation(ts, indent + 1);
- return ts;
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/FECustomFilter.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/FECustomFilter.h
deleted file mode 100644
index b2fb50b9d45..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/FECustomFilter.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
- * Copyright (C) 2013 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:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 HOLDER 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 FECustomFilter_h
-#define FECustomFilter_h
-
-#include "platform/graphics/GraphicsTypes3D.h"
-#include "platform/graphics/filters/Filter.h"
-#include "platform/graphics/filters/FilterEffect.h"
-#include "platform/graphics/filters/custom/CustomFilterConstants.h"
-#include "platform/graphics/filters/custom/CustomFilterOperation.h"
-#include "wtf/RefPtr.h"
-
-namespace WebCore {
-
-class CustomFilterRenderer;
-class CustomFilterValidatedProgram;
-class GraphicsContext3D;
-class IntSize;
-
-class PLATFORM_EXPORT FECustomFilter : public FilterEffect {
-public:
- static PassRefPtr<FECustomFilter> create(Filter*, PassRefPtr<GraphicsContext3D>, PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&,
- unsigned meshRows, unsigned meshColumns, CustomFilterMeshType);
-
- virtual TextStream& externalRepresentation(TextStream&, int indention) const;
-
-private:
- FECustomFilter(Filter*, PassRefPtr<GraphicsContext3D>, PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&,
- unsigned meshRows, unsigned meshColumns, CustomFilterMeshType);
- ~FECustomFilter();
-
- virtual void applySoftware() OVERRIDE;
-
- bool applyShader();
- void clearShaderResult();
- bool initializeContext();
-
- bool prepareForDrawing();
-
- void drawFilterMesh(Platform3DObject inputTexture);
- bool ensureInputTexture();
- void uploadInputTexture(Uint8ClampedArray* srcPixelArray);
- bool resizeContextIfNeeded(const IntSize&);
- bool resizeContext(const IntSize&);
-
- bool canUseMultisampleBuffers() const;
- bool createMultisampleBuffer();
- bool resizeMultisampleBuffers(const IntSize&);
- void resolveMultisampleBuffer();
- void deleteMultisampleRenderBuffers();
-
- bool ensureFrameBuffer();
- void deleteRenderBuffers();
-
- RefPtr<GraphicsContext3D> m_context;
- RefPtr<CustomFilterValidatedProgram> m_validatedProgram;
- RefPtr<CustomFilterRenderer> m_customFilterRenderer;
- IntSize m_contextSize;
-
- Platform3DObject m_inputTexture;
- Platform3DObject m_frameBuffer;
- Platform3DObject m_depthBuffer;
- Platform3DObject m_destTexture;
-
- bool m_triedMultisampleBuffer;
- Platform3DObject m_multisampleFrameBuffer;
- Platform3DObject m_multisampleRenderBuffer;
- Platform3DObject m_multisampleDepthBuffer;
-};
-
-} // namespace WebCore
-
-#endif // FECustomFilter_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/ValidatedCustomFilterOperation.cpp b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/ValidatedCustomFilterOperation.cpp
deleted file mode 100644
index c01b3af9e67..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/ValidatedCustomFilterOperation.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER 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"
-#include "platform/graphics/filters/custom/ValidatedCustomFilterOperation.h"
-
-#include "platform/graphics/filters/custom/CustomFilterParameter.h"
-#include "platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
-
-namespace WebCore {
-
-ValidatedCustomFilterOperation::ValidatedCustomFilterOperation(PassRefPtr<CustomFilterValidatedProgram> validatedProgram,
- const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
- : FilterOperation(VALIDATED_CUSTOM)
- , m_validatedProgram(validatedProgram)
- , m_parameters(sortedParameters)
- , m_meshRows(meshRows)
- , m_meshColumns(meshColumns)
- , m_meshType(meshType)
-{
-}
-
-ValidatedCustomFilterOperation::~ValidatedCustomFilterOperation()
-{
-}
-
-PassRefPtr<FilterOperation> ValidatedCustomFilterOperation::blend(const FilterOperation*, double) const
-{
- ASSERT_NOT_REACHED();
- return const_cast<ValidatedCustomFilterOperation*>(this);
-}
-
-} // namespace WebCore
-
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/ValidatedCustomFilterOperation.h b/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/ValidatedCustomFilterOperation.h
deleted file mode 100644
index 9542914869d..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/filters/custom/ValidatedCustomFilterOperation.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER 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 ValidatedCustomFilterOperation_h
-#define ValidatedCustomFilterOperation_h
-
-#include "platform/graphics/filters/FilterOperation.h"
-#include "platform/graphics/filters/custom/CustomFilterConstants.h"
-#include "platform/graphics/filters/custom/CustomFilterParameterList.h"
-
-namespace WebCore {
-
-class CustomFilterValidatedProgram;
-
-class PLATFORM_EXPORT ValidatedCustomFilterOperation : public FilterOperation {
-public:
- static PassRefPtr<ValidatedCustomFilterOperation> create(PassRefPtr<CustomFilterValidatedProgram> validatedProgram,
- const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns, CustomFilterMeshType meshType)
- {
- return adoptRef(new ValidatedCustomFilterOperation(validatedProgram, sortedParameters, meshRows, meshColumns, meshType));
- }
-
- virtual ~ValidatedCustomFilterOperation();
-
- virtual bool affectsOpacity() const { return true; }
- virtual bool movesPixels() const { return true; }
-
-
- CustomFilterValidatedProgram* validatedProgram() const { return m_validatedProgram.get(); }
- const CustomFilterParameterList& parameters() const { return m_parameters; }
-
- unsigned meshRows() const { return m_meshRows; }
- unsigned meshColumns() const { return m_meshColumns; }
-
- CustomFilterMeshType meshType() const { return m_meshType; }
-
-private:
- virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
- virtual bool operator==(const FilterOperation& o) const
- {
- if (!isSameType(o))
- return false;
-
- const ValidatedCustomFilterOperation* other = static_cast<const ValidatedCustomFilterOperation*>(&o);
- return m_validatedProgram.get() == other->m_validatedProgram.get()
- && m_meshRows == other->m_meshRows
- && m_meshColumns == other->m_meshColumns
- && m_meshType == other->m_meshType
- && m_parameters == other->m_parameters;
- }
-
- ValidatedCustomFilterOperation(PassRefPtr<CustomFilterValidatedProgram>, const CustomFilterParameterList&, unsigned meshRows, unsigned meshColumns, CustomFilterMeshType);
-
- RefPtr<CustomFilterValidatedProgram> m_validatedProgram;
-
- CustomFilterParameterList m_parameters;
- unsigned m_meshRows;
- unsigned m_meshColumns;
- CustomFilterMeshType m_meshType;
-};
-
-DEFINE_FILTER_OPERATION_TYPE_CASTS(ValidatedCustomFilterOperation, VALIDATED_CUSTOM);
-
-} // namespace WebCore
-
-
-#endif // ValidatedCustomFilterOperation_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index 54c13e20d7e..0ec4bf91790 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -32,33 +32,41 @@
#include "platform/graphics/gpu/DrawingBuffer.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include <algorithm>
#include "platform/TraceEvent.h"
-#include "platform/graphics/Extensions3D.h"
#include "platform/graphics/GraphicsLayer.h"
+#include "platform/graphics/gpu/Extensions3DUtil.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCompositorSupport.h"
#include "public/platform/WebExternalBitmap.h"
#include "public/platform/WebExternalTextureLayer.h"
#include "public/platform/WebGraphicsContext3D.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
+#ifndef NDEBUG
+#include "wtf/RefCountedLeakCounter.h"
+#endif
using namespace std;
namespace WebCore {
+namespace {
// Global resource ceiling (expressed in terms of pixels) for DrawingBuffer creation and resize.
// When this limit is set, DrawingBuffer::create() and DrawingBuffer::reset() calls that would
// exceed the global cap will instead clear the buffer.
-static const int s_maximumResourceUsePixels = 16 * 1024 * 1024;
-static int s_currentResourceUsePixels = 0;
-static const float s_resourceAdjustedRatio = 0.5;
+const int s_maximumResourceUsePixels = 16 * 1024 * 1024;
+int s_currentResourceUsePixels = 0;
+const float s_resourceAdjustedRatio = 0.5;
-static const bool s_allowContextEvictionOnCreate = true;
-static const int s_maxScaleAttempts = 3;
+const bool s_allowContextEvictionOnCreate = true;
+const int s_maxScaleAttempts = 3;
+
+DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, drawingBufferCounter, ("DrawingBuffer"));
class ScopedTextureUnit0BindingRestorer {
public:
- ScopedTextureUnit0BindingRestorer(GraphicsContext3D* context, GC3Denum activeTextureUnit, Platform3DObject textureUnitZeroId)
+ ScopedTextureUnit0BindingRestorer(blink::WebGraphicsContext3D* context, GLenum activeTextureUnit, Platform3DObject textureUnitZeroId)
: m_context(context)
, m_oldActiveTextureUnit(activeTextureUnit)
, m_oldTextureUnitZeroId(textureUnitZeroId)
@@ -72,48 +80,58 @@ public:
}
private:
- GraphicsContext3D* m_context;
- GC3Denum m_oldActiveTextureUnit;
+ blink::WebGraphicsContext3D* m_context;
+ GLenum m_oldActiveTextureUnit;
Platform3DObject m_oldTextureUnitZeroId;
};
-PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size, PreserveDrawingBuffer preserve, PassRefPtr<ContextEvictionManager> contextEvictionManager)
+} // namespace
+
+PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<blink::WebGraphicsContext3D> context, const IntSize& size, PreserveDrawingBuffer preserve, blink::WebGraphicsContext3D::Attributes requestedAttributes, PassRefPtr<ContextEvictionManager> contextEvictionManager)
{
- Extensions3D* extensions = context->extensions();
- bool multisampleSupported = extensions->supports("GL_ANGLE_framebuffer_blit")
- && extensions->supports("GL_ANGLE_framebuffer_multisample")
- && extensions->supports("GL_OES_rgb8_rgba8");
+ ASSERT(context);
+ OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get());
+ if (!extensionsUtil) {
+ // This might be the first time we notice that the WebGraphicsContext3D is lost.
+ return nullptr;
+ }
+ bool multisampleSupported = extensionsUtil->supportsExtension("GL_CHROMIUM_framebuffer_multisample")
+ && extensionsUtil->supportsExtension("GL_OES_rgb8_rgba8");
if (multisampleSupported) {
- extensions->ensureEnabled("GL_ANGLE_framebuffer_blit");
- extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
- extensions->ensureEnabled("GL_OES_rgb8_rgba8");
+ extensionsUtil->ensureExtensionEnabled("GL_CHROMIUM_framebuffer_multisample");
+ extensionsUtil->ensureExtensionEnabled("GL_OES_rgb8_rgba8");
}
- bool packedDepthStencilSupported = extensions->supports("GL_OES_packed_depth_stencil");
+ bool packedDepthStencilSupported = extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil");
if (packedDepthStencilSupported)
- extensions->ensureEnabled("GL_OES_packed_depth_stencil");
+ extensionsUtil->ensureExtensionEnabled("GL_OES_packed_depth_stencil");
- RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, size, multisampleSupported, packedDepthStencilSupported, preserve, contextEvictionManager));
+ RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, extensionsUtil.release(), multisampleSupported, packedDepthStencilSupported, preserve, requestedAttributes, contextEvictionManager));
+ if (!drawingBuffer->initialize(size)) {
+ drawingBuffer->beginDestruction();
+ return PassRefPtr<DrawingBuffer>();
+ }
return drawingBuffer.release();
}
-DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
- const IntSize& size,
- bool multisampleExtensionSupported,
- bool packedDepthStencilExtensionSupported,
- PreserveDrawingBuffer preserve,
- PassRefPtr<ContextEvictionManager> contextEvictionManager)
+DrawingBuffer::DrawingBuffer(PassOwnPtr<blink::WebGraphicsContext3D> context,
+ PassOwnPtr<Extensions3DUtil> extensionsUtil,
+ bool multisampleExtensionSupported,
+ bool packedDepthStencilExtensionSupported,
+ PreserveDrawingBuffer preserve,
+ blink::WebGraphicsContext3D::Attributes requestedAttributes,
+ PassRefPtr<ContextEvictionManager> contextEvictionManager)
: m_preserveDrawingBuffer(preserve)
, m_scissorEnabled(false)
, m_texture2DBinding(0)
, m_framebufferBinding(0)
, m_activeTextureUnit(GL_TEXTURE0)
, m_context(context)
+ , m_extensionsUtil(extensionsUtil)
, m_size(-1, -1)
+ , m_requestedAttributes(requestedAttributes)
, m_multisampleExtensionSupported(multisampleExtensionSupported)
, m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
, m_fbo(0)
- , m_colorBuffer(0)
- , m_frontColorBuffer(0)
, m_depthStencilBuffer(0)
, m_depthBuffer(0)
, m_stencilBuffer(0)
@@ -121,54 +139,85 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
, m_multisampleColorBuffer(0)
, m_contentsChanged(true)
, m_contentsChangeCommitted(false)
+ , m_layerComposited(false)
+ , m_multisampleMode(None)
, m_internalColorFormat(0)
, m_colorFormat(0)
, m_internalRenderbufferFormat(0)
, m_maxTextureSize(0)
+ , m_sampleCount(0)
+ , m_packAlignment(4)
+ , m_destructionInProgress(false)
, m_contextEvictionManager(contextEvictionManager)
{
// Used by browser tests to detect the use of a DrawingBuffer.
TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation");
- initialize(size);
+#ifndef NDEBUG
+ drawingBufferCounter.increment();
+#endif
}
DrawingBuffer::~DrawingBuffer()
{
- releaseResources();
+ ASSERT(m_destructionInProgress);
+ ASSERT(m_textureMailboxes.isEmpty());
+ m_layer.clear();
+ m_context.clear();
+#ifndef NDEBUG
+ drawingBufferCounter.decrement();
+#endif
}
void DrawingBuffer::markContentsChanged()
{
m_contentsChanged = true;
m_contentsChangeCommitted = false;
+ m_layerComposited = false;
+}
+
+bool DrawingBuffer::layerComposited() const
+{
+ return m_layerComposited;
+}
+
+void DrawingBuffer::markLayerComposited()
+{
+ m_layerComposited = true;
}
blink::WebGraphicsContext3D* DrawingBuffer::context()
{
- if (!m_context)
- return 0;
- return m_context->webContext();
+ return m_context.get();
}
bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox, blink::WebExternalBitmap* bitmap)
{
- if (!m_context || !m_contentsChanged || !m_lastColorBuffer)
+ if (!m_contentsChanged)
return false;
+ if (m_destructionInProgress) {
+ // It can be hit in the following sequence.
+ // 1. WebGL draws something.
+ // 2. The compositor begins the frame.
+ // 3. Javascript makes a context lost using WEBGL_lose_context extension.
+ // 4. Here.
+ return false;
+ }
+
m_context->makeContextCurrent();
- // Resolve the multisampled buffer into the texture referenced by m_lastColorBuffer mailbox.
- if (multisample())
+ // Resolve the multisampled buffer into m_colorBuffer texture.
+ if (m_multisampleMode != None)
commit();
if (bitmap) {
bitmap->setSize(size());
unsigned char* pixels = bitmap->pixels();
- bool needPremultiply = m_attributes.alpha && !m_attributes.premultipliedAlpha;
- GraphicsContext3D::AlphaOp op = needPremultiply ? GraphicsContext3D::AlphaDoPremultiply : GraphicsContext3D::AlphaDoNothing;
+ bool needPremultiply = m_actualAttributes.alpha && !m_actualAttributes.premultipliedAlpha;
+ WebGLImageConversion::AlphaOp op = needPremultiply ? WebGLImageConversion::AlphaDoPremultiply : WebGLImageConversion::AlphaDoNothing;
if (pixels)
- m_context->readBackFramebuffer(pixels, size().width(), size().height(), GraphicsContext3D::ReadbackSkia, op);
+ readBackFramebuffer(pixels, size().width(), size().height(), ReadbackSkia, op);
}
// We must restore the texture binding since creating new textures,
@@ -176,134 +225,221 @@ bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox,
ScopedTextureUnit0BindingRestorer restorer(m_context.get(), m_activeTextureUnit, m_texture2DBinding);
// First try to recycle an old buffer.
- RefPtr<MailboxInfo> nextFrontColorBuffer = recycledMailbox();
+ RefPtr<MailboxInfo> frontColorBufferMailbox = recycledMailbox();
// No buffer available to recycle, create a new one.
- if (!nextFrontColorBuffer) {
- unsigned newColorBuffer = createColorTexture(m_size);
+ if (!frontColorBufferMailbox) {
+ TextureInfo newTexture;
+ newTexture.textureId = createColorTexture();
+ allocateTextureMemory(&newTexture, m_size);
// Bad things happened, abandon ship.
- if (!newColorBuffer)
+ if (!newTexture.textureId)
return false;
- nextFrontColorBuffer = createNewMailbox(newColorBuffer);
+ frontColorBufferMailbox = createNewMailbox(newTexture);
}
if (m_preserveDrawingBuffer == Discard) {
- m_colorBuffer = nextFrontColorBuffer->textureId;
- swap(nextFrontColorBuffer, m_lastColorBuffer);
+ swap(frontColorBufferMailbox->textureInfo, m_colorBuffer);
// It appears safe to overwrite the context's framebuffer binding in the Discard case since there will always be a
// WebGLRenderingContext::clearIfComposited() call made before the next draw call which restores the framebuffer binding.
// If this stops being true at some point, we should track the current framebuffer binding in the DrawingBuffer and restore
// it after attaching the new back buffer here.
m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
- m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
+ if (m_multisampleMode == ImplicitResolve)
+ m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0, m_sampleCount);
+ else
+ m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0);
} else {
- Extensions3D* extensions = m_context->extensions();
- extensions->copyTextureCHROMIUM(GL_TEXTURE_2D, m_colorBuffer, nextFrontColorBuffer->textureId, 0, GL_RGBA, GL_UNSIGNED_BYTE);
+ m_context->copyTextureCHROMIUM(GL_TEXTURE_2D, m_colorBuffer.textureId, frontColorBufferMailbox->textureInfo.textureId, 0, GL_RGBA, GL_UNSIGNED_BYTE);
}
- if (multisample() && !m_framebufferBinding)
+ if (m_multisampleMode != None && !m_framebufferBinding)
bind();
else
restoreFramebufferBinding();
m_contentsChanged = false;
- context()->bindTexture(GL_TEXTURE_2D, nextFrontColorBuffer->textureId);
- context()->produceTextureCHROMIUM(GL_TEXTURE_2D, nextFrontColorBuffer->mailbox.name);
- context()->flush();
- m_context->markLayerComposited();
-
- *outMailbox = nextFrontColorBuffer->mailbox;
- m_frontColorBuffer = nextFrontColorBuffer->textureId;
+ m_context->bindTexture(GL_TEXTURE_2D, frontColorBufferMailbox->textureInfo.textureId);
+ m_context->produceTextureCHROMIUM(GL_TEXTURE_2D, frontColorBufferMailbox->mailbox.name);
+ m_context->flush();
+ frontColorBufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint();
+ frontColorBufferMailbox->mailbox.allowOverlay = frontColorBufferMailbox->textureInfo.imageId != 0;
+ markLayerComposited();
+
+ // set m_parentDrawingBuffer to make sure 'this' stays alive as long as it has live mailboxes
+ ASSERT(!frontColorBufferMailbox->m_parentDrawingBuffer);
+ frontColorBufferMailbox->m_parentDrawingBuffer = this;
+ *outMailbox = frontColorBufferMailbox->mailbox;
+ m_frontColorBuffer = frontColorBufferMailbox->textureInfo;
return true;
}
void DrawingBuffer::mailboxReleased(const blink::WebExternalTextureMailbox& mailbox)
{
+ if (m_destructionInProgress) {
+ mailboxReleasedWhileDestructionInProgress(mailbox);
+ return;
+ }
+
for (size_t i = 0; i < m_textureMailboxes.size(); i++) {
- RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[i];
- if (!memcmp(mailboxInfo->mailbox.name, mailbox.name, sizeof(mailbox.name))) {
- mailboxInfo->mailbox.syncPoint = mailbox.syncPoint;
- m_recycledMailboxes.append(mailboxInfo.release());
- return;
- }
- }
- ASSERT_NOT_REACHED();
+ RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[i];
+ if (nameEquals(mailboxInfo->mailbox, mailbox)) {
+ mailboxInfo->mailbox.syncPoint = mailbox.syncPoint;
+ ASSERT(mailboxInfo->m_parentDrawingBuffer.get() == this);
+ mailboxInfo->m_parentDrawingBuffer.clear();
+ m_recycledMailboxQueue.prepend(mailboxInfo->mailbox);
+ return;
+ }
+ }
+ ASSERT_NOT_REACHED();
+}
+
+void DrawingBuffer::mailboxReleasedWhileDestructionInProgress(const blink::WebExternalTextureMailbox& mailbox)
+{
+ ASSERT(m_textureMailboxes.size());
+ m_context->makeContextCurrent();
+ // Ensure not to call the destructor until deleteMailbox() is completed.
+ RefPtr<DrawingBuffer> self = this;
+ deleteMailbox(mailbox);
}
PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::recycledMailbox()
{
- if (!m_context || m_recycledMailboxes.isEmpty())
+ if (m_recycledMailboxQueue.isEmpty())
return PassRefPtr<MailboxInfo>();
- RefPtr<MailboxInfo> mailboxInfo = m_recycledMailboxes.last().release();
- m_recycledMailboxes.removeLast();
+ blink::WebExternalTextureMailbox mailbox = m_recycledMailboxQueue.takeLast();
+ RefPtr<MailboxInfo> mailboxInfo;
+ for (size_t i = 0; i < m_textureMailboxes.size(); i++) {
+ if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) {
+ mailboxInfo = m_textureMailboxes[i];
+ break;
+ }
+ }
+ ASSERT(mailboxInfo);
if (mailboxInfo->mailbox.syncPoint) {
- context()->waitSyncPoint(mailboxInfo->mailbox.syncPoint);
+ m_context->waitSyncPoint(mailboxInfo->mailbox.syncPoint);
mailboxInfo->mailbox.syncPoint = 0;
}
- context()->bindTexture(GL_TEXTURE_2D, mailboxInfo->textureId);
- context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo->mailbox.name);
-
if (mailboxInfo->size != m_size) {
- m_context->texImage2DResourceSafe(GL_TEXTURE_2D, 0, m_internalColorFormat, m_size.width(), m_size.height(), 0, m_colorFormat, GL_UNSIGNED_BYTE);
+ m_context->bindTexture(GL_TEXTURE_2D, mailboxInfo->textureInfo.textureId);
+ allocateTextureMemory(&mailboxInfo->textureInfo, m_size);
mailboxInfo->size = m_size;
}
return mailboxInfo.release();
}
-PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::createNewMailbox(unsigned textureId)
+PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::createNewMailbox(const TextureInfo& info)
{
RefPtr<MailboxInfo> returnMailbox = adoptRef(new MailboxInfo());
- context()->genMailboxCHROMIUM(returnMailbox->mailbox.name);
- returnMailbox->textureId = textureId;
+ m_context->genMailboxCHROMIUM(returnMailbox->mailbox.name);
+ returnMailbox->textureInfo = info;
returnMailbox->size = m_size;
m_textureMailboxes.append(returnMailbox);
return returnMailbox.release();
}
-void DrawingBuffer::initialize(const IntSize& size)
+void DrawingBuffer::deleteMailbox(const blink::WebExternalTextureMailbox& mailbox)
{
- ASSERT(m_context);
- m_attributes = m_context->getContextAttributes();
+ for (size_t i = 0; i < m_textureMailboxes.size(); i++) {
+ if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) {
+ if (mailbox.syncPoint)
+ m_context->waitSyncPoint(mailbox.syncPoint);
+
+ deleteChromiumImageForTexture(&m_textureMailboxes[i]->textureInfo);
+
+ m_context->deleteTexture(m_textureMailboxes[i]->textureInfo.textureId);
+ m_textureMailboxes.remove(i);
+ return;
+ }
+ }
+ ASSERT_NOT_REACHED();
+}
- if (m_attributes.alpha) {
+bool DrawingBuffer::initialize(const IntSize& size)
+{
+ if (!m_context->makeContextCurrent()) {
+ // Most likely the GPU process exited and the attempt to reconnect to it failed.
+ // Need to try to restore the context again later.
+ return false;
+ }
+
+ if (m_context->isContextLost()) {
+ // Need to try to restore the context again later.
+ return false;
+ }
+
+ if (m_requestedAttributes.alpha) {
m_internalColorFormat = GL_RGBA;
m_colorFormat = GL_RGBA;
- m_internalRenderbufferFormat = Extensions3D::RGBA8_OES;
+ m_internalRenderbufferFormat = GL_RGBA8_OES;
} else {
m_internalColorFormat = GL_RGB;
m_colorFormat = GL_RGB;
- m_internalRenderbufferFormat = Extensions3D::RGB8_OES;
+ m_internalRenderbufferFormat = GL_RGB8_OES;
}
m_context->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
+ int maxSampleCount = 0;
+ m_multisampleMode = None;
+ if (m_requestedAttributes.antialias && m_multisampleExtensionSupported) {
+ m_context->getIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSampleCount);
+ m_multisampleMode = ExplicitResolve;
+ if (m_extensionsUtil->supportsExtension("GL_EXT_multisampled_render_to_texture"))
+ m_multisampleMode = ImplicitResolve;
+ }
+ m_sampleCount = std::min(4, maxSampleCount);
+
m_fbo = m_context->createFramebuffer();
m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
- m_colorBuffer = createColorTexture();
- m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
+ m_colorBuffer.textureId = createColorTexture();
+ if (m_multisampleMode == ImplicitResolve)
+ m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0, m_sampleCount);
+ else
+ m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0);
createSecondaryBuffers();
- reset(size);
- m_lastColorBuffer = createNewMailbox(m_colorBuffer);
-}
-
-unsigned DrawingBuffer::frontColorBuffer() const
-{
- return m_frontColorBuffer;
+ // We first try to initialize everything with the requested attributes.
+ if (!reset(size))
+ return false;
+ // If that succeeds, we then see what we actually got and update our actual attributes to reflect that.
+ m_actualAttributes = m_requestedAttributes;
+ if (m_requestedAttributes.alpha) {
+ blink::WGC3Dint alphaBits = 0;
+ m_context->getIntegerv(GL_ALPHA_BITS, &alphaBits);
+ m_actualAttributes.alpha = alphaBits > 0;
+ }
+ if (m_requestedAttributes.depth) {
+ blink::WGC3Dint depthBits = 0;
+ m_context->getIntegerv(GL_DEPTH_BITS, &depthBits);
+ m_actualAttributes.depth = depthBits > 0;
+ }
+ if (m_requestedAttributes.stencil) {
+ blink::WGC3Dint stencilBits = 0;
+ m_context->getIntegerv(GL_STENCIL_BITS, &stencilBits);
+ m_actualAttributes.stencil = stencilBits > 0;
+ }
+ m_actualAttributes.antialias = multisample();
+ return true;
}
-bool DrawingBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DObject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool premultiplyAlpha, bool flipY)
+bool DrawingBuffer::copyToPlatformTexture(blink::WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY, bool fromFrontBuffer)
{
- if (!m_context || !m_context->makeContextCurrent())
+ if (!m_context->makeContextCurrent())
return false;
+
+ GLint textureId = m_colorBuffer.textureId;
+ if (fromFrontBuffer)
+ textureId = m_frontColorBuffer.textureId;
+
if (m_contentsChanged) {
- if (multisample()) {
+ if (m_multisampleMode != None) {
commit();
if (!m_framebufferBinding)
bind();
@@ -312,30 +448,43 @@ bool DrawingBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3D
}
m_context->flush();
}
- Platform3DObject sourceTexture = colorBuffer();
- if (!context.makeContextCurrent())
+ if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(internalFormat, destType, level))
return false;
- Extensions3D* extensions = context.extensions();
- if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->supports("GL_CHROMIUM_flipy")
- || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, level))
+
+ // Contexts may be in a different share group. We must transfer the texture through a mailbox first
+ RefPtr<MailboxInfo> bufferMailbox = adoptRef(new MailboxInfo());
+ m_context->genMailboxCHROMIUM(bufferMailbox->mailbox.name);
+ m_context->produceTextureDirectCHROMIUM(textureId, GL_TEXTURE_2D, bufferMailbox->mailbox.name);
+ m_context->flush();
+
+ bufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint();
+
+ if (!context->makeContextCurrent())
return false;
+ context->waitSyncPoint(bufferMailbox->mailbox.syncPoint);
+ Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, bufferMailbox->mailbox.name);
+
bool unpackPremultiplyAlphaNeeded = false;
bool unpackUnpremultiplyAlphaNeeded = false;
- if (m_attributes.alpha && m_attributes.premultipliedAlpha && !premultiplyAlpha)
+ if (m_actualAttributes.alpha && m_actualAttributes.premultipliedAlpha && !premultiplyAlpha)
unpackUnpremultiplyAlphaNeeded = true;
- else if (m_attributes.alpha && !m_attributes.premultipliedAlpha && premultiplyAlpha)
+ else if (m_actualAttributes.alpha && !m_actualAttributes.premultipliedAlpha && premultiplyAlpha)
unpackPremultiplyAlphaNeeded = true;
- context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, unpackUnpremultiplyAlphaNeeded);
- context.pixelStorei(Extensions3D::UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, unpackPremultiplyAlphaNeeded);
- context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, flipY);
- extensions->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, texture, level, internalFormat, destType);
- context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, false);
- context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false);
- context.pixelStorei(Extensions3D::UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, false);
- context.flush();
+ context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, unpackUnpremultiplyAlphaNeeded);
+ context->pixelStorei(GC3D_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, unpackPremultiplyAlphaNeeded);
+ context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, flipY);
+ context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, texture, level, internalFormat, destType);
+ context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, false);
+ context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false);
+ context->pixelStorei(GC3D_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, false);
+
+ context->deleteTexture(sourceTexture);
+
+ context->flush();
+ m_context->waitSyncPoint(context->insertSyncPoint());
return true;
}
@@ -347,15 +496,12 @@ Platform3DObject DrawingBuffer::framebuffer() const
blink::WebLayer* DrawingBuffer::platformLayer()
{
- if (!m_context)
- return 0;
-
if (!m_layer) {
m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->createExternalTextureLayer(this));
- m_layer->setOpaque(!m_attributes.alpha);
- m_layer->setBlendBackgroundColor(m_attributes.alpha);
- m_layer->setPremultipliedAlpha(m_attributes.premultipliedAlpha);
+ m_layer->setOpaque(!m_actualAttributes.alpha);
+ m_layer->setBlendBackgroundColor(m_actualAttributes.alpha);
+ m_layer->setPremultipliedAlpha(m_actualAttributes.premultipliedAlpha);
GraphicsLayer::registerContentsLayer(m_layer->layer());
}
@@ -364,17 +510,40 @@ blink::WebLayer* DrawingBuffer::platformLayer()
void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer)
{
- if (!m_context || !m_context->makeContextCurrent() || m_context->extensions()->getGraphicsResetStatusARB() != GL_NO_ERROR)
+ if (!m_context->makeContextCurrent() || m_context->getGraphicsResetStatusARB() != GL_NO_ERROR)
return;
- Extensions3D* extensions = m_context->extensions();
-
if (!imageBuffer)
return;
Platform3DObject tex = imageBuffer->getBackingTexture();
if (tex) {
- extensions->copyTextureCHROMIUM(GL_TEXTURE_2D, m_frontColorBuffer,
+ RefPtr<MailboxInfo> bufferMailbox = adoptRef(new MailboxInfo());
+ m_context->genMailboxCHROMIUM(bufferMailbox->mailbox.name);
+ m_context->bindTexture(GL_TEXTURE_2D, m_frontColorBuffer.textureId);
+ m_context->produceTextureCHROMIUM(GL_TEXTURE_2D, bufferMailbox->mailbox.name);
+ m_context->flush();
+
+ bufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint();
+ OwnPtr<blink::WebGraphicsContext3DProvider> provider =
+ adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+ if (!provider)
+ return;
+ blink::WebGraphicsContext3D* context = provider->context3d();
+ if (!context || !context->makeContextCurrent())
+ return;
+
+ Platform3DObject sourceTexture = context->createTexture();
+ GLint boundTexture = 0;
+ context->getIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture);
+ context->bindTexture(GL_TEXTURE_2D, sourceTexture);
+ context->waitSyncPoint(bufferMailbox->mailbox.syncPoint);
+ context->consumeTextureCHROMIUM(GL_TEXTURE_2D, bufferMailbox->mailbox.name);
+ context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture,
tex, 0, GL_RGBA, GL_UNSIGNED_BYTE);
+ context->bindTexture(GL_TEXTURE_2D, boundTexture);
+ context->deleteTexture(sourceTexture);
+ context->flush();
+ m_context->waitSyncPoint(context->insertSyncPoint());
return;
}
@@ -382,20 +551,21 @@ void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer)
// We have to make a copy of it here and bind that copy instead.
// FIXME: That's not true any more, provided we don't change texture
// parameters.
- unsigned sourceTexture = createColorTexture(m_size);
- extensions->copyTextureCHROMIUM(GL_TEXTURE_2D, m_frontColorBuffer, sourceTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
+ unsigned sourceTexture = createColorTexture();
+ texImage2DResourceSafe(GL_TEXTURE_2D, 0, m_internalColorFormat, m_size.width(), m_size.height(), 0, m_colorFormat, GL_UNSIGNED_BYTE);
+ m_context->copyTextureCHROMIUM(GL_TEXTURE_2D, m_frontColorBuffer.textureId, sourceTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
// Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding).
// FIXME: The WebGLRenderingContext tracks the current framebuffer binding, it would be slightly more efficient to use this value
// rather than querying it off of the context.
- GC3Dint previousFramebuffer = 0;
+ GLint previousFramebuffer = 0;
m_context->getIntegerv(GL_FRAMEBUFFER_BINDING, &previousFramebuffer);
Platform3DObject framebuffer = m_context->createFramebuffer();
m_context->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTexture, 0);
- extensions->paintFramebufferToCanvas(framebuffer, size().width(), size().height(), !m_attributes.premultipliedAlpha, imageBuffer);
+ paintFramebufferToCanvas(framebuffer, size().width(), size().height(), !m_actualAttributes.premultipliedAlpha, imageBuffer);
m_context->deleteFramebuffer(framebuffer);
m_context->deleteTexture(sourceTexture);
@@ -407,45 +577,48 @@ void DrawingBuffer::clearPlatformLayer()
if (m_layer)
m_layer->clearTexture();
- if (m_context)
- m_context->flush();
+ m_context->flush();
}
-void DrawingBuffer::releaseResources()
+void DrawingBuffer::beginDestruction()
{
- if (m_context) {
- m_context->makeContextCurrent();
+ ASSERT(!m_destructionInProgress);
+ m_destructionInProgress = true;
- clearPlatformLayer();
+ m_context->makeContextCurrent();
- for (size_t i = 0; i < m_textureMailboxes.size(); i++)
- m_context->deleteTexture(m_textureMailboxes[i]->textureId);
+ clearPlatformLayer();
- if (m_multisampleColorBuffer)
- m_context->deleteRenderbuffer(m_multisampleColorBuffer);
+ while (!m_recycledMailboxQueue.isEmpty())
+ deleteMailbox(m_recycledMailboxQueue.takeLast());
- if (m_depthStencilBuffer)
- m_context->deleteRenderbuffer(m_depthStencilBuffer);
+ if (m_multisampleFBO)
+ m_context->deleteFramebuffer(m_multisampleFBO);
- if (m_depthBuffer)
- m_context->deleteRenderbuffer(m_depthBuffer);
+ if (m_fbo)
+ m_context->deleteFramebuffer(m_fbo);
- if (m_stencilBuffer)
- m_context->deleteRenderbuffer(m_stencilBuffer);
+ if (m_multisampleColorBuffer)
+ m_context->deleteRenderbuffer(m_multisampleColorBuffer);
- if (m_multisampleFBO)
- m_context->deleteFramebuffer(m_multisampleFBO);
+ if (m_depthStencilBuffer)
+ m_context->deleteRenderbuffer(m_depthStencilBuffer);
- if (m_fbo)
- m_context->deleteFramebuffer(m_fbo);
+ if (m_depthBuffer)
+ m_context->deleteRenderbuffer(m_depthBuffer);
- m_context.clear();
+ if (m_stencilBuffer)
+ m_context->deleteRenderbuffer(m_stencilBuffer);
+
+ if (m_colorBuffer.textureId) {
+ deleteChromiumImageForTexture(&m_colorBuffer);
+ m_context->deleteTexture(m_colorBuffer.textureId);
}
setSize(IntSize());
- m_colorBuffer = 0;
- m_frontColorBuffer = 0;
+ m_colorBuffer = TextureInfo();
+ m_frontColorBuffer = TextureInfo();
m_multisampleColorBuffer = 0;
m_depthStencilBuffer = 0;
m_depthBuffer = 0;
@@ -454,21 +627,12 @@ void DrawingBuffer::releaseResources()
m_fbo = 0;
m_contextEvictionManager.clear();
- m_lastColorBuffer.clear();
- m_recycledMailboxes.clear();
- m_textureMailboxes.clear();
-
- if (m_layer) {
+ if (m_layer)
GraphicsLayer::unregisterContentsLayer(m_layer->layer());
- m_layer.clear();
- }
}
-unsigned DrawingBuffer::createColorTexture(const IntSize& size)
+unsigned DrawingBuffer::createColorTexture()
{
- if (!m_context)
- return 0;
-
unsigned offscreenColorTexture = m_context->createTexture();
if (!offscreenColorTexture)
return 0;
@@ -478,8 +642,6 @@ unsigned DrawingBuffer::createColorTexture(const IntSize& size)
m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- if (!size.isEmpty())
- m_context->texImage2DResourceSafe(GL_TEXTURE_2D, 0, m_internalColorFormat, size.width(), size.height(), 0, m_colorFormat, GL_UNSIGNED_BYTE);
return offscreenColorTexture;
}
@@ -487,7 +649,7 @@ unsigned DrawingBuffer::createColorTexture(const IntSize& size)
void DrawingBuffer::createSecondaryBuffers()
{
// create a multisample FBO
- if (multisample()) {
+ if (m_multisampleMode == ExplicitResolve) {
m_multisampleFBO = m_context->createFramebuffer();
m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
m_multisampleColorBuffer = m_context->createRenderbuffer();
@@ -499,17 +661,19 @@ bool DrawingBuffer::resizeFramebuffer(const IntSize& size)
// resize regular FBO
m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
- m_context->bindTexture(GL_TEXTURE_2D, m_colorBuffer);
- m_context->texImage2DResourceSafe(GL_TEXTURE_2D, 0, m_internalColorFormat, size.width(), size.height(), 0, m_colorFormat, GL_UNSIGNED_BYTE);
- if (m_lastColorBuffer)
- m_lastColorBuffer->size = size;
+ m_context->bindTexture(GL_TEXTURE_2D, m_colorBuffer.textureId);
+
+ allocateTextureMemory(&m_colorBuffer, size);
- m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
+ if (m_multisampleMode == ImplicitResolve)
+ m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0, m_sampleCount);
+ else
+ m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0);
m_context->bindTexture(GL_TEXTURE_2D, 0);
- if (!multisample())
- resizeDepthStencil(size, 0);
+ if (m_multisampleMode != ExplicitResolve)
+ resizeDepthStencil(size);
if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return false;
@@ -518,22 +682,17 @@ bool DrawingBuffer::resizeFramebuffer(const IntSize& size)
bool DrawingBuffer::resizeMultisampleFramebuffer(const IntSize& size)
{
- if (multisample()) {
- int maxSampleCount = 0;
-
- m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount);
- int sampleCount = std::min(4, maxSampleCount);
-
+ if (m_multisampleMode == ExplicitResolve) {
m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
m_context->bindRenderbuffer(GL_RENDERBUFFER, m_multisampleColorBuffer);
- m_context->extensions()->renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, m_internalRenderbufferFormat, size.width(), size.height());
+ m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sampleCount, m_internalRenderbufferFormat, size.width(), size.height());
if (m_context->getError() == GL_OUT_OF_MEMORY)
return false;
m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_multisampleColorBuffer);
- resizeDepthStencil(size, sampleCount);
+ resizeDepthStencil(size);
if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return false;
}
@@ -541,35 +700,44 @@ bool DrawingBuffer::resizeMultisampleFramebuffer(const IntSize& size)
return true;
}
-void DrawingBuffer::resizeDepthStencil(const IntSize& size, int sampleCount)
+void DrawingBuffer::resizeDepthStencil(const IntSize& size)
{
- if (m_attributes.depth && m_attributes.stencil && m_packedDepthStencilExtensionSupported) {
+ if (!m_requestedAttributes.depth && !m_requestedAttributes.stencil)
+ return;
+
+ if (m_packedDepthStencilExtensionSupported) {
if (!m_depthStencilBuffer)
m_depthStencilBuffer = m_context->createRenderbuffer();
m_context->bindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
- if (multisample())
- m_context->extensions()->renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, Extensions3D::DEPTH24_STENCIL8, size.width(), size.height());
+ if (m_multisampleMode == ImplicitResolve)
+ m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(), size.height());
+ else if (m_multisampleMode == ExplicitResolve)
+ m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(), size.height());
else
- m_context->renderbufferStorage(GL_RENDERBUFFER, Extensions3D::DEPTH24_STENCIL8, size.width(), size.height());
+ m_context->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, size.width(), size.height());
m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
} else {
- if (m_attributes.depth) {
+ if (m_requestedAttributes.depth) {
if (!m_depthBuffer)
m_depthBuffer = m_context->createRenderbuffer();
m_context->bindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
- if (multisample())
- m_context->extensions()->renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_DEPTH_COMPONENT16, size.width(), size.height());
+ if (m_multisampleMode == ImplicitResolve)
+ m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount, GL_DEPTH_COMPONENT16, size.width(), size.height());
+ else if (m_multisampleMode == ExplicitResolve)
+ m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sampleCount, GL_DEPTH_COMPONENT16, size.width(), size.height());
else
m_context->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.width(), size.height());
m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer);
}
- if (m_attributes.stencil) {
+ if (m_requestedAttributes.stencil) {
if (!m_stencilBuffer)
m_stencilBuffer = m_context->createRenderbuffer();
m_context->bindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer);
- if (multisample())
- m_context->extensions()->renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_STENCIL_INDEX8, size.width(), size.height());
+ if (m_multisampleMode == ImplicitResolve)
+ m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount, GL_STENCIL_INDEX8, size.width(), size.height());
+ else if (m_multisampleMode == ExplicitResolve)
+ m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sampleCount, GL_STENCIL_INDEX8, size.width(), size.height());
else
m_context->renderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, size.width(), size.height());
m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer);
@@ -580,48 +748,46 @@ void DrawingBuffer::resizeDepthStencil(const IntSize& size, int sampleCount)
-void DrawingBuffer::clearFramebuffers(GC3Dbitfield clearMask)
+void DrawingBuffer::clearFramebuffers(GLbitfield clearMask)
{
- if (!m_context)
- return;
-
- m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo);
-
- m_context->clear(clearMask);
-
- // The multisample fbo was just cleared, but we also need to clear the non-multisampled buffer too.
+ // We will clear the multisample FBO, but we also need to clear the non-multisampled buffer.
if (m_multisampleFBO) {
m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
m_context->clear(GL_COLOR_BUFFER_BIT);
- m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
}
+
+ m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo);
+ m_context->clear(clearMask);
}
-void DrawingBuffer::setSize(const IntSize& size) {
+void DrawingBuffer::setSize(const IntSize& size)
+{
if (m_size == size)
return;
- s_currentResourceUsePixels += pixelDelta(size);
+ s_currentResourceUsePixels += pixelDelta(size, m_size);
m_size = size;
}
-int DrawingBuffer::pixelDelta(const IntSize& size) {
- return (max(0, size.width()) * max(0, size.height())) - (max(0, m_size.width()) * max(0, m_size.height()));
+int DrawingBuffer::pixelDelta(const IntSize& newSize, const IntSize& curSize)
+{
+ return (max(0, newSize.width()) * max(0, newSize.height())) - (max(0, curSize.width()) * max(0, curSize.height()));
}
-IntSize DrawingBuffer::adjustSize(const IntSize& size) {
- IntSize adjustedSize = size;
+IntSize DrawingBuffer::adjustSize(const IntSize& desiredSize, const IntSize& curSize, int maxTextureSize)
+{
+ IntSize adjustedSize = desiredSize;
// Clamp if the desired size is greater than the maximum texture size for the device.
- if (adjustedSize.height() > m_maxTextureSize)
- adjustedSize.setHeight(m_maxTextureSize);
+ if (adjustedSize.height() > maxTextureSize)
+ adjustedSize.setHeight(maxTextureSize);
- if (adjustedSize.width() > m_maxTextureSize)
- adjustedSize.setWidth(m_maxTextureSize);
+ if (adjustedSize.width() > maxTextureSize)
+ adjustedSize.setWidth(maxTextureSize);
// Try progressively smaller sizes until we find a size that fits or reach a scale limit.
int scaleAttempts = 0;
- while ((s_currentResourceUsePixels + pixelDelta(adjustedSize)) > s_maximumResourceUsePixels) {
+ while ((s_currentResourceUsePixels + pixelDelta(adjustedSize, curSize)) > s_maximumResourceUsePixels) {
scaleAttempts++;
if (scaleAttempts > s_maxScaleAttempts)
return IntSize();
@@ -635,8 +801,9 @@ IntSize DrawingBuffer::adjustSize(const IntSize& size) {
return adjustedSize;
}
-IntSize DrawingBuffer::adjustSizeWithContextEviction(const IntSize& size, bool& evictContext) {
- IntSize adjustedSize = adjustSize(size);
+IntSize DrawingBuffer::adjustSizeWithContextEviction(const IntSize& size, bool& evictContext)
+{
+ IntSize adjustedSize = adjustSize(size, m_size, m_maxTextureSize);
if (!adjustedSize.isEmpty()) {
evictContext = false;
return adjustedSize; // Buffer fits without evicting a context.
@@ -647,28 +814,26 @@ IntSize DrawingBuffer::adjustSizeWithContextEviction(const IntSize& size, bool&
int pixelDelta = oldestSize.width() * oldestSize.height();
s_currentResourceUsePixels -= pixelDelta;
- adjustedSize = adjustSize(size);
+ adjustedSize = adjustSize(size, m_size, m_maxTextureSize);
s_currentResourceUsePixels += pixelDelta;
evictContext = !adjustedSize.isEmpty();
return adjustedSize;
}
-void DrawingBuffer::reset(const IntSize& newSize)
+bool DrawingBuffer::reset(const IntSize& newSize)
{
- if (!m_context)
- return;
-
+ ASSERT(!newSize.isEmpty());
IntSize adjustedSize;
bool evictContext = false;
bool isNewContext = m_size.isEmpty();
if (s_allowContextEvictionOnCreate && isNewContext)
adjustedSize = adjustSizeWithContextEviction(newSize, evictContext);
else
- adjustedSize = adjustSize(newSize);
+ adjustedSize = adjustSize(newSize, m_size, m_maxTextureSize);
if (adjustedSize.isEmpty())
- return;
+ return false;
if (evictContext)
m_contextEvictionManager->forciblyLoseOldestContext("WARNING: WebGL contexts have exceeded the maximum allowed backbuffer area. Oldest context will be lost.");
@@ -686,33 +851,31 @@ void DrawingBuffer::reset(const IntSize& newSize)
setSize(adjustedSize);
if (adjustedSize.isEmpty())
- return;
+ return false;
}
m_context->disable(GL_SCISSOR_TEST);
m_context->clearColor(0, 0, 0, 0);
m_context->colorMask(true, true, true, true);
- GC3Dbitfield clearMask = GL_COLOR_BUFFER_BIT;
- if (m_attributes.depth) {
+ GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
+ if (m_actualAttributes.depth) {
m_context->clearDepth(1.0f);
clearMask |= GL_DEPTH_BUFFER_BIT;
m_context->depthMask(true);
}
- if (m_attributes.stencil) {
+ if (m_actualAttributes.stencil) {
m_context->clearStencil(0);
clearMask |= GL_STENCIL_BUFFER_BIT;
m_context->stencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
}
clearFramebuffers(clearMask);
+ return true;
}
void DrawingBuffer::commit(long x, long y, long width, long height)
{
- if (!m_context)
- return;
-
if (width < 0)
width = m_size.width();
if (height < 0)
@@ -721,14 +884,14 @@ void DrawingBuffer::commit(long x, long y, long width, long height)
m_context->makeContextCurrent();
if (m_multisampleFBO && !m_contentsChangeCommitted) {
- m_context->bindFramebuffer(Extensions3D::READ_FRAMEBUFFER, m_multisampleFBO);
- m_context->bindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, m_fbo);
+ m_context->bindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleFBO);
+ m_context->bindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo);
if (m_scissorEnabled)
m_context->disable(GL_SCISSOR_TEST);
// Use NEAREST, because there is no scale performed during the blit.
- m_context->extensions()->blitFramebuffer(x, y, width, height, x, y, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ m_context->blitFramebufferCHROMIUM(x, y, width, height, x, y, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
if (m_scissorEnabled)
m_context->enable(GL_SCISSOR_TEST);
@@ -740,7 +903,7 @@ void DrawingBuffer::commit(long x, long y, long width, long height)
void DrawingBuffer::restoreFramebufferBinding()
{
- if (!m_context || !m_framebufferBinding)
+ if (!m_framebufferBinding)
return;
m_context->bindFramebuffer(GL_FRAMEBUFFER, m_framebufferBinding);
@@ -748,15 +911,162 @@ void DrawingBuffer::restoreFramebufferBinding()
bool DrawingBuffer::multisample() const
{
- return m_attributes.antialias && m_multisampleExtensionSupported;
+ return m_multisampleMode != None;
}
void DrawingBuffer::bind()
{
- if (!m_context)
- return;
-
m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo);
}
+void DrawingBuffer::setPackAlignment(GLint param)
+{
+ m_packAlignment = param;
+}
+
+void DrawingBuffer::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer)
+{
+ paintFramebufferToCanvas(framebuffer(), size().width(), size().height(), !m_actualAttributes.premultipliedAlpha, imageBuffer);
+}
+
+PassRefPtr<Uint8ClampedArray> DrawingBuffer::paintRenderingResultsToImageData(int& width, int& height)
+{
+ if (m_actualAttributes.premultipliedAlpha)
+ return nullptr;
+
+ width = size().width();
+ height = size().height();
+
+ Checked<int, RecordOverflow> dataSize = 4;
+ dataSize *= width;
+ dataSize *= height;
+ if (dataSize.hasOverflowed())
+ return nullptr;
+
+ RefPtr<Uint8ClampedArray> pixels = Uint8ClampedArray::createUninitialized(width * height * 4);
+
+ m_context->bindFramebuffer(GL_FRAMEBUFFER, framebuffer());
+ readBackFramebuffer(pixels->data(), width, height, ReadbackRGBA, WebGLImageConversion::AlphaDoNothing);
+ flipVertically(pixels->data(), width, height);
+
+ return pixels.release();
+}
+
+void DrawingBuffer::paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer* imageBuffer)
+{
+ unsigned char* pixels = 0;
+
+ const SkBitmap& canvasBitmap = imageBuffer->bitmap();
+ const SkBitmap* readbackBitmap = 0;
+ ASSERT(canvasBitmap.colorType() == kPMColor_SkColorType);
+ if (canvasBitmap.width() == width && canvasBitmap.height() == height) {
+ // This is the fastest and most common case. We read back
+ // directly into the canvas's backing store.
+ readbackBitmap = &canvasBitmap;
+ m_resizingBitmap.reset();
+ } else {
+ // We need to allocate a temporary bitmap for reading back the
+ // pixel data. We will then use Skia to rescale this bitmap to
+ // the size of the canvas's backing store.
+ if (m_resizingBitmap.width() != width || m_resizingBitmap.height() != height) {
+ if (!m_resizingBitmap.allocN32Pixels(width, height))
+ return;
+ }
+ readbackBitmap = &m_resizingBitmap;
+ }
+
+ // Read back the frame buffer.
+ SkAutoLockPixels bitmapLock(*readbackBitmap);
+ pixels = static_cast<unsigned char*>(readbackBitmap->getPixels());
+
+ m_context->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ readBackFramebuffer(pixels, width, height, ReadbackSkia, premultiplyAlpha ? WebGLImageConversion::AlphaDoPremultiply : WebGLImageConversion::AlphaDoNothing);
+ flipVertically(pixels, width, height);
+
+ readbackBitmap->notifyPixelsChanged();
+ if (m_resizingBitmap.readyToDraw()) {
+ // We need to draw the resizing bitmap into the canvas's backing store.
+ SkCanvas canvas(canvasBitmap);
+ SkRect dst;
+ dst.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(canvasBitmap.width()), SkIntToScalar(canvasBitmap.height()));
+ canvas.drawBitmapRect(m_resizingBitmap, 0, dst);
+ }
+}
+
+void DrawingBuffer::readBackFramebuffer(unsigned char* pixels, int width, int height, ReadbackOrder readbackOrder, WebGLImageConversion::AlphaOp op)
+{
+ if (m_packAlignment > 4)
+ m_context->pixelStorei(GL_PACK_ALIGNMENT, 1);
+ m_context->readPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ if (m_packAlignment > 4)
+ m_context->pixelStorei(GL_PACK_ALIGNMENT, m_packAlignment);
+
+ size_t bufferSize = 4 * width * height;
+
+ if (readbackOrder == ReadbackSkia) {
+#if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
+ // Swizzle red and blue channels to match SkBitmap's byte ordering.
+ // TODO(kbr): expose GL_BGRA as extension.
+ for (size_t i = 0; i < bufferSize; i += 4) {
+ std::swap(pixels[i], pixels[i + 2]);
+ }
+#endif
+ }
+
+ if (op == WebGLImageConversion::AlphaDoPremultiply) {
+ for (size_t i = 0; i < bufferSize; i += 4) {
+ pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
+ pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
+ pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
+ }
+ } else if (op != WebGLImageConversion::AlphaDoNothing) {
+ ASSERT_NOT_REACHED();
+ }
+}
+
+void DrawingBuffer::flipVertically(uint8_t* framebuffer, int width, int height)
+{
+ m_scanline.resize(width * 4);
+ uint8* scanline = &m_scanline[0];
+ unsigned rowBytes = width * 4;
+ unsigned count = height / 2;
+ for (unsigned i = 0; i < count; i++) {
+ uint8* rowA = framebuffer + i * rowBytes;
+ uint8* rowB = framebuffer + (height - i - 1) * rowBytes;
+ memcpy(scanline, rowB, rowBytes);
+ memcpy(rowB, rowA, rowBytes);
+ memcpy(rowA, scanline, rowBytes);
+ }
+}
+
+void DrawingBuffer::texImage2DResourceSafe(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLint unpackAlignment)
+{
+ ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8);
+ m_context->texImage2D(target, level, internalformat, width, height, border, format, type, 0);
+}
+
+void DrawingBuffer::allocateTextureMemory(TextureInfo* info, const IntSize& size)
+{
+ if (RuntimeEnabledFeatures::webGLImageChromiumEnabled()) {
+ deleteChromiumImageForTexture(info);
+
+ info->imageId = m_context->createImageCHROMIUM(size.width(), size.height(), GL_RGBA8_OES, GC3D_IMAGE_SCANOUT_CHROMIUM);
+ if (info->imageId) {
+ m_context->bindTexImage2DCHROMIUM(GL_TEXTURE_2D, info->imageId);
+ return;
+ }
+ }
+
+ texImage2DResourceSafe(GL_TEXTURE_2D, 0, m_internalColorFormat, size.width(), size.height(), 0, m_colorFormat, GL_UNSIGNED_BYTE);
+}
+
+void DrawingBuffer::deleteChromiumImageForTexture(TextureInfo* info)
+{
+ if (info->imageId) {
+ m_context->releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, info->imageId);
+ m_context->destroyImageCHROMIUM(info->imageId);
+ info->imageId = 0;
+ }
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h b/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
index f1d7afc47de..4c457b7c7b7 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -33,11 +33,15 @@
#include "platform/PlatformExport.h"
#include "platform/geometry/IntSize.h"
-#include "platform/graphics/GraphicsContext3D.h"
#include "platform/graphics/GraphicsTypes3D.h"
-
+#include "platform/graphics/gpu/WebGLImageConversion.h"
#include "public/platform/WebExternalTextureLayerClient.h"
#include "public/platform/WebExternalTextureMailbox.h"
+#include "public/platform/WebGraphicsContext3D.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "wtf/Deque.h"
#include "wtf/Noncopyable.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
@@ -50,8 +54,9 @@ class WebLayer;
}
namespace WebCore {
-class GraphicsContext3D;
+class Extensions3DUtil;
class ImageData;
+class ImageBuffer;
// Abstract interface to allow basic context eviction management
class PLATFORM_EXPORT ContextEvictionManager : public RefCounted<ContextEvictionManager> {
@@ -65,10 +70,27 @@ public:
// Manages a rendering target (framebuffer + attachment) for a canvas. Can publish its rendering
// results to a blink::WebLayer for compositing.
class PLATFORM_EXPORT DrawingBuffer : public RefCounted<DrawingBuffer>, public blink::WebExternalTextureLayerClient {
+ // If we used CHROMIUM_image as the backing storage for our buffers,
+ // we need to know the mapping from texture id to image.
+ struct TextureInfo {
+ Platform3DObject textureId;
+ blink::WGC3Duint imageId;
+
+ TextureInfo()
+ : textureId(0)
+ , imageId(0)
+ {
+ }
+ };
+
struct MailboxInfo : public RefCounted<MailboxInfo> {
blink::WebExternalTextureMailbox mailbox;
- unsigned textureId;
+ TextureInfo textureInfo;
IntSize size;
+ // This keeps the parent drawing buffer alive as long as the compositor is
+ // referring to one of the mailboxes DrawingBuffer produced. The parent drawing buffer is
+ // cleared when the compositor returns the mailbox. See mailboxReleased().
+ RefPtr<DrawingBuffer> m_parentDrawingBuffer;
};
public:
enum PreserveDrawingBuffer {
@@ -76,24 +98,22 @@ public:
Discard
};
- static PassRefPtr<DrawingBuffer> create(GraphicsContext3D*, const IntSize&, PreserveDrawingBuffer, PassRefPtr<ContextEvictionManager>);
+ static PassRefPtr<DrawingBuffer> create(PassOwnPtr<blink::WebGraphicsContext3D>, const IntSize&, PreserveDrawingBuffer, blink::WebGraphicsContext3D::Attributes requestedAttributes, PassRefPtr<ContextEvictionManager>);
- ~DrawingBuffer();
+ virtual ~DrawingBuffer();
- // Clear all resources from this object, as well as context. Called when context is destroyed
- // to prevent invalid accesses to the resources.
- void releaseResources();
+ // Destruction will be completed after all mailboxes are released.
+ void beginDestruction();
// Issues a glClear() on all framebuffers associated with this DrawingBuffer. The caller is responsible for
// making the context current and setting the clear values and masks. Modifies the framebuffer binding.
- void clearFramebuffers(GC3Dbitfield clearMask);
+ void clearFramebuffers(GLbitfield clearMask);
// Given the desired buffer size, provides the largest dimensions that will fit in the pixel budget.
- IntSize adjustSize(const IntSize&);
- void reset(const IntSize&);
+ static IntSize adjustSize(const IntSize& desiredSize, const IntSize& curSize, int maxTextureSize);
+ bool reset(const IntSize&);
void bind();
IntSize size() const { return m_size; }
- bool isZeroSized() const { return m_size.isEmpty(); }
// Copies the multisample color buffer to the normal color buffer and leaves m_fbo bound.
void commit(long x = 0, long y = 0, long width = -1, long height = -1);
@@ -113,40 +133,59 @@ public:
// Track the currently active texture unit. Texture unit 0 is used as host for a scratch
// texture.
- void setActiveTextureUnit(GC3Dint textureUnit) { m_activeTextureUnit = textureUnit; }
+ void setActiveTextureUnit(GLint textureUnit) { m_activeTextureUnit = textureUnit; }
bool multisample() const;
Platform3DObject framebuffer() const;
void markContentsChanged();
+ void markLayerComposited();
+ bool layerComposited() const;
blink::WebLayer* platformLayer();
void paintCompositedResultsToCanvas(ImageBuffer*);
+ blink::WebGraphicsContext3D* context();
+
+ // Returns the actual context attributes for this drawing buffer which may differ from the
+ // requested context attributes due to implementation limits.
+ blink::WebGraphicsContext3D::Attributes getActualAttributes() const { return m_actualAttributes; }
+
// WebExternalTextureLayerClient implementation.
- virtual blink::WebGraphicsContext3D* context() OVERRIDE;
virtual bool prepareMailbox(blink::WebExternalTextureMailbox*, blink::WebExternalBitmap*) OVERRIDE;
virtual void mailboxReleased(const blink::WebExternalTextureMailbox&) OVERRIDE;
- bool copyToPlatformTexture(GraphicsContext3D&, Platform3DObject texture, GC3Denum internalFormat,
- GC3Denum destType, GC3Dint level, bool premultiplyAlpha, bool flipY);
+ // Destroys the TEXTURE_2D binding for the owned context
+ bool copyToPlatformTexture(blink::WebGraphicsContext3D*, Platform3DObject texture, GLenum internalFormat,
+ GLenum destType, GLint level, bool premultiplyAlpha, bool flipY, bool fromFrontBuffer = false);
-private:
- DrawingBuffer(GraphicsContext3D*, const IntSize&, bool multisampleExtensionSupported,
- bool packedDepthStencilExtensionSupported, PreserveDrawingBuffer, PassRefPtr<ContextEvictionManager>);
+ void setPackAlignment(GLint param);
+
+ void paintRenderingResultsToCanvas(ImageBuffer*);
+ PassRefPtr<Uint8ClampedArray> paintRenderingResultsToImageData(int&, int&);
- void initialize(const IntSize&);
+protected: // For unittests
+ DrawingBuffer(
+ PassOwnPtr<blink::WebGraphicsContext3D>,
+ PassOwnPtr<Extensions3DUtil>,
+ bool multisampleExtensionSupported,
+ bool packedDepthStencilExtensionSupported,
+ PreserveDrawingBuffer,
+ blink::WebGraphicsContext3D::Attributes requestedAttributes,
+ PassRefPtr<ContextEvictionManager>);
- Platform3DObject frontColorBuffer() const;
- Platform3DObject colorBuffer() const { return m_colorBuffer; }
+ bool initialize(const IntSize&);
- unsigned createColorTexture(const IntSize& size = IntSize());
+private:
+ void mailboxReleasedWhileDestructionInProgress(const blink::WebExternalTextureMailbox&);
+
+ unsigned createColorTexture();
// Create the depth/stencil and multisample buffers, if needed.
void createSecondaryBuffers();
bool resizeFramebuffer(const IntSize&);
bool resizeMultisampleFramebuffer(const IntSize&);
- void resizeDepthStencil(const IntSize&, int sampleCount);
+ void resizeDepthStencil(const IntSize&);
// Bind to the m_framebufferBinding if it's not 0.
void restoreFramebufferBinding();
@@ -154,31 +193,57 @@ private:
void clearPlatformLayer();
PassRefPtr<MailboxInfo> recycledMailbox();
- PassRefPtr<MailboxInfo> createNewMailbox(unsigned);
+ PassRefPtr<MailboxInfo> createNewMailbox(const TextureInfo&);
+ void deleteMailbox(const blink::WebExternalTextureMailbox&);
// Updates the current size of the buffer, ensuring that s_currentResourceUsePixels is updated.
void setSize(const IntSize& size);
// Calculates the difference in pixels between the current buffer size and the proposed size.
- int pixelDelta(const IntSize& size);
+ static int pixelDelta(const IntSize& newSize, const IntSize& curSize);
// Given the desired buffer size, provides the largest dimensions that will fit in the pixel budget
// Returns true if the buffer will only fit if the oldest WebGL context is forcibly lost
IntSize adjustSizeWithContextEviction(const IntSize&, bool& evictContext);
+ void paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer*);
+
+ // This is the order of bytes to use when doing a readback.
+ enum ReadbackOrder {
+ ReadbackRGBA,
+ ReadbackSkia
+ };
+
+ // Helper function which does a readback from the currently-bound
+ // framebuffer into a buffer of a certain size with 4-byte pixels.
+ void readBackFramebuffer(unsigned char* pixels, int width, int height, ReadbackOrder, WebGLImageConversion::AlphaOp);
+
+ // Helper function to flip a bitmap vertically.
+ void flipVertically(uint8_t* data, int width, int height);
+
+ // Helper to texImage2D with pixel==0 case: pixels are initialized to 0.
+ // By default, alignment is 4, the OpenGL default setting.
+ void texImage2DResourceSafe(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLint alignment = 4);
+ // Allocate buffer storage to be sent to compositor using either texImage2D or CHROMIUM_image based on available support.
+ void allocateTextureMemory(TextureInfo*, const IntSize&);
+ void deleteChromiumImageForTexture(TextureInfo*);
+
PreserveDrawingBuffer m_preserveDrawingBuffer;
bool m_scissorEnabled;
Platform3DObject m_texture2DBinding;
Platform3DObject m_framebufferBinding;
- GC3Denum m_activeTextureUnit;
+ GLenum m_activeTextureUnit;
- RefPtr<GraphicsContext3D> m_context;
+ OwnPtr<blink::WebGraphicsContext3D> m_context;
+ OwnPtr<Extensions3DUtil> m_extensionsUtil;
IntSize m_size;
+ blink::WebGraphicsContext3D::Attributes m_requestedAttributes;
bool m_multisampleExtensionSupported;
bool m_packedDepthStencilExtensionSupported;
Platform3DObject m_fbo;
- Platform3DObject m_colorBuffer;
- Platform3DObject m_frontColorBuffer;
+ // DrawingBuffer's output is double-buffered. m_colorBuffer is the back buffer.
+ TextureInfo m_colorBuffer;
+ TextureInfo m_frontColorBuffer;
// This is used when we have OES_packed_depth_stencil.
Platform3DObject m_depthStencilBuffer;
@@ -196,22 +261,43 @@ private:
// True if commit() has been called since the last time markContentsChanged() had been called.
bool m_contentsChangeCommitted;
+ bool m_layerComposited;
- GraphicsContext3D::Attributes m_attributes;
+ enum MultisampleMode {
+ None,
+ ImplicitResolve,
+ ExplicitResolve,
+ };
+
+ MultisampleMode m_multisampleMode;
+
+ blink::WebGraphicsContext3D::Attributes m_actualAttributes;
unsigned m_internalColorFormat;
unsigned m_colorFormat;
unsigned m_internalRenderbufferFormat;
int m_maxTextureSize;
+ int m_sampleCount;
+ int m_packAlignment;
+ bool m_destructionInProgress;
OwnPtr<blink::WebExternalTextureLayer> m_layer;
// All of the mailboxes that this DrawingBuffer has ever created.
Vector<RefPtr<MailboxInfo> > m_textureMailboxes;
- // Mailboxes that were released by the compositor and can be used again by this DrawingBuffer.
- Vector<RefPtr<MailboxInfo> > m_recycledMailboxes;
- RefPtr<MailboxInfo> m_lastColorBuffer;
+ // Mailboxes that were released by the compositor can be used again by this DrawingBuffer.
+ Deque<blink::WebExternalTextureMailbox> m_recycledMailboxQueue;
RefPtr<ContextEvictionManager> m_contextEvictionManager;
+
+ // If the width and height of the Canvas's backing store don't
+ // match those that we were given in the most recent call to
+ // reshape(), then we need an intermediate bitmap to read back the
+ // frame buffer into. This seems to happen when CSS styles are
+ // used to resize the Canvas.
+ SkBitmap m_resizingBitmap;
+
+ // Used to flip a bitmap vertically.
+ Vector<uint8_t> m_scanline;
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
new file mode 100644
index 00000000000..767fcfdbff1
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -0,0 +1,623 @@
+/*
+ * Copyright (C) 2013 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"
+
+#include "platform/graphics/gpu/DrawingBuffer.h"
+
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/graphics/ImageBuffer.h"
+#include "platform/graphics/UnacceleratedImageBufferSurface.h"
+#include "platform/graphics/gpu/Extensions3DUtil.h"
+#include "platform/graphics/test/MockWebGraphicsContext3D.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebExternalTextureMailbox.h"
+#include "wtf/RefPtr.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+using namespace blink;
+using testing::Test;
+using testing::_;
+
+namespace {
+
+class FakeContextEvictionManager : public ContextEvictionManager {
+public:
+ void forciblyLoseOldestContext(const String& reason) { }
+ IntSize oldestContextSize() { return IntSize(); }
+};
+
+class WebGraphicsContext3DForTests : public MockWebGraphicsContext3D {
+public:
+ WebGraphicsContext3DForTests()
+ : MockWebGraphicsContext3D()
+ , m_boundTexture(0)
+ , m_currentMailboxByte(0)
+ , m_mostRecentlyWaitedSyncPoint(0)
+ , m_currentImageId(1) { }
+
+ virtual void bindTexture(WGC3Denum target, WebGLId texture)
+ {
+ if (target == GL_TEXTURE_2D) {
+ m_boundTexture = texture;
+ }
+ }
+
+ virtual void texImage2D(WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, WGC3Denum format, WGC3Denum type, const void* pixels)
+ {
+ if (target == GL_TEXTURE_2D && !level) {
+ m_textureSizes.set(m_boundTexture, IntSize(width, height));
+ }
+ }
+
+ virtual void genMailboxCHROMIUM(WGC3Dbyte* mailbox)
+ {
+ ++m_currentMailboxByte;
+ WebExternalTextureMailbox temp;
+ memset(mailbox, m_currentMailboxByte, sizeof(temp.name));
+ }
+
+ virtual void produceTextureCHROMIUM(WGC3Denum target, const WGC3Dbyte* mailbox)
+ {
+ ASSERT_EQ(target, static_cast<WGC3Denum>(GL_TEXTURE_2D));
+ m_mostRecentlyProducedSize = m_textureSizes.get(m_boundTexture);
+ }
+
+ IntSize mostRecentlyProducedSize()
+ {
+ return m_mostRecentlyProducedSize;
+ }
+
+ virtual unsigned insertSyncPoint()
+ {
+ static unsigned syncPointGenerator = 0;
+ return ++syncPointGenerator;
+ }
+
+ virtual void waitSyncPoint(unsigned syncPoint)
+ {
+ m_mostRecentlyWaitedSyncPoint = syncPoint;
+ }
+
+ virtual WGC3Duint createImageCHROMIUM(WGC3Dsizei width, WGC3Dsizei height, WGC3Denum internalformat, WGC3Denum usage)
+ {
+ m_imageSizes.set(m_currentImageId, IntSize(width, height));
+ return m_currentImageId++;
+ }
+
+ MOCK_METHOD1(destroyImageMock, void(WGC3Duint imageId));
+ void destroyImageCHROMIUM(WGC3Duint imageId)
+ {
+ m_imageSizes.remove(imageId);
+ // No textures should be bound to this.
+ ASSERT(m_imageToTextureMap.find(imageId) == m_imageToTextureMap.end());
+ m_imageSizes.remove(imageId);
+ destroyImageMock(imageId);
+ }
+
+ MOCK_METHOD1(bindTexImage2DMock, void(WGC3Dint imageId));
+ void bindTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId)
+ {
+ if (target == GL_TEXTURE_2D) {
+ m_textureSizes.set(m_boundTexture, m_imageSizes.find(imageId)->value);
+ m_imageToTextureMap.set(imageId, m_boundTexture);
+ bindTexImage2DMock(imageId);
+ }
+ }
+
+ MOCK_METHOD1(releaseTexImage2DMock, void(WGC3Dint imageId));
+ void releaseTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId)
+ {
+ if (target == GL_TEXTURE_2D) {
+ m_imageSizes.set(m_currentImageId, IntSize());
+ m_imageToTextureMap.remove(imageId);
+ releaseTexImage2DMock(imageId);
+ }
+ }
+
+ unsigned mostRecentlyWaitedSyncPoint()
+ {
+ return m_mostRecentlyWaitedSyncPoint;
+ }
+
+ WGC3Duint nextImageIdToBeCreated()
+ {
+ return m_currentImageId;
+ }
+
+private:
+ WebGLId m_boundTexture;
+ HashMap<WebGLId, IntSize> m_textureSizes;
+ WGC3Dbyte m_currentMailboxByte;
+ IntSize m_mostRecentlyProducedSize;
+ unsigned m_mostRecentlyWaitedSyncPoint;
+ WGC3Duint m_currentImageId;
+ HashMap<WGC3Duint, IntSize> m_imageSizes;
+ HashMap<WGC3Duint, WebGLId> m_imageToTextureMap;
+};
+
+static const int initialWidth = 100;
+static const int initialHeight = 100;
+static const int alternateHeight = 50;
+
+class DrawingBufferForTests : public DrawingBuffer {
+public:
+ static PassRefPtr<DrawingBufferForTests> create(PassOwnPtr<blink::WebGraphicsContext3D> context,
+ const IntSize& size, PreserveDrawingBuffer preserve, PassRefPtr<ContextEvictionManager> contextEvictionManager)
+ {
+ OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get());
+ RefPtr<DrawingBufferForTests> drawingBuffer =
+ adoptRef(new DrawingBufferForTests(context, extensionsUtil.release(), preserve, contextEvictionManager));
+ if (!drawingBuffer->initialize(size)) {
+ drawingBuffer->beginDestruction();
+ return PassRefPtr<DrawingBufferForTests>();
+ }
+ return drawingBuffer.release();
+ }
+
+ DrawingBufferForTests(PassOwnPtr<blink::WebGraphicsContext3D> context,
+ PassOwnPtr<Extensions3DUtil> extensionsUtil,
+ PreserveDrawingBuffer preserve,
+ PassRefPtr<ContextEvictionManager> contextEvictionManager)
+ : DrawingBuffer(context, extensionsUtil, false /* multisampleExtensionSupported */,
+ false /* packedDepthStencilExtensionSupported */, preserve, blink::WebGraphicsContext3D::Attributes(), contextEvictionManager)
+ , m_live(0)
+ { }
+
+ virtual ~DrawingBufferForTests()
+ {
+ if (m_live)
+ *m_live = false;
+ }
+
+ bool* m_live;
+};
+
+class DrawingBufferTest : public Test {
+protected:
+ virtual void SetUp()
+ {
+ RefPtr<FakeContextEvictionManager> contextEvictionManager = adoptRef(new FakeContextEvictionManager());
+ OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests);
+ m_context = context.get();
+ m_drawingBuffer = DrawingBufferForTests::create(context.release(),
+ IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve, contextEvictionManager.release());
+ }
+
+ WebGraphicsContext3DForTests* webContext()
+ {
+ return m_context;
+ }
+
+ WebGraphicsContext3DForTests* m_context;
+ RefPtr<DrawingBufferForTests> m_drawingBuffer;
+};
+
+TEST_F(DrawingBufferTest, testPaintRenderingResultsToCanvas)
+{
+ OwnPtr<ImageBufferSurface> imageBufferSurface = adoptPtr(new UnacceleratedImageBufferSurface(IntSize(initialWidth, initialHeight)));
+ EXPECT_FALSE(!imageBufferSurface);
+ EXPECT_TRUE(imageBufferSurface->isValid());
+ OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageBufferSurface.release());
+ EXPECT_FALSE(!imageBuffer);
+ EXPECT_FALSE(imageBuffer->isAccelerated());
+ EXPECT_FALSE(imageBuffer->bitmap().isNull());
+ m_drawingBuffer->paintRenderingResultsToCanvas(imageBuffer.get());
+ EXPECT_FALSE(imageBuffer->isAccelerated());
+ EXPECT_FALSE(imageBuffer->bitmap().isNull());
+ m_drawingBuffer->beginDestruction();
+}
+
+TEST_F(DrawingBufferTest, verifyResizingProperlyAffectsMailboxes)
+{
+ blink::WebExternalTextureMailbox mailbox;
+
+ IntSize initialSize(initialWidth, initialHeight);
+ IntSize alternateSize(initialWidth, alternateHeight);
+
+ // Produce one mailbox at size 100x100.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize());
+
+ // Resize to 100x50.
+ m_drawingBuffer->reset(IntSize(initialWidth, alternateHeight));
+ m_drawingBuffer->mailboxReleased(mailbox);
+
+ // Produce a mailbox at this size.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ EXPECT_EQ(alternateSize, webContext()->mostRecentlyProducedSize());
+
+ // Reset to initial size.
+ m_drawingBuffer->reset(IntSize(initialWidth, initialHeight));
+ m_drawingBuffer->mailboxReleased(mailbox);
+
+ // Prepare another mailbox and verify that it's the correct size.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize());
+
+ // Prepare one final mailbox and verify that it's the correct size.
+ m_drawingBuffer->mailboxReleased(mailbox);
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize());
+ m_drawingBuffer->beginDestruction();
+}
+
+TEST_F(DrawingBufferTest, verifyDestructionCompleteAfterAllMailboxesReleased)
+{
+ bool live = true;
+ m_drawingBuffer->m_live = &live;
+
+ blink::WebExternalTextureMailbox mailbox1;
+ blink::WebExternalTextureMailbox mailbox2;
+ blink::WebExternalTextureMailbox mailbox3;
+
+ IntSize initialSize(initialWidth, initialHeight);
+
+ // Produce mailboxes.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox1, 0));
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox2, 0));
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox3, 0));
+
+ m_drawingBuffer->markContentsChanged();
+ m_drawingBuffer->mailboxReleased(mailbox1);
+
+ m_drawingBuffer->beginDestruction();
+ EXPECT_EQ(live, true);
+
+ DrawingBufferForTests* weakPointer = m_drawingBuffer.get();
+ m_drawingBuffer.clear();
+ EXPECT_EQ(live, true);
+
+ weakPointer->markContentsChanged();
+ weakPointer->mailboxReleased(mailbox2);
+ EXPECT_EQ(live, true);
+
+ weakPointer->markContentsChanged();
+ weakPointer->mailboxReleased(mailbox3);
+ EXPECT_EQ(live, false);
+}
+
+class TextureMailboxWrapper {
+public:
+ explicit TextureMailboxWrapper(const blink::WebExternalTextureMailbox& mailbox)
+ : m_mailbox(mailbox)
+ { }
+
+ bool operator==(const TextureMailboxWrapper& other) const
+ {
+ return !memcmp(m_mailbox.name, other.m_mailbox.name, sizeof(m_mailbox.name));
+ }
+
+private:
+ blink::WebExternalTextureMailbox m_mailbox;
+};
+
+TEST_F(DrawingBufferTest, verifyRecyclingMailboxesByFIFO)
+{
+ blink::WebExternalTextureMailbox mailbox1;
+ blink::WebExternalTextureMailbox mailbox2;
+ blink::WebExternalTextureMailbox mailbox3;
+
+ // Produce mailboxes.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox1, 0));
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox2, 0));
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox3, 0));
+
+ // Release mailboxes by specific order; 2, 3, 1.
+ m_drawingBuffer->markContentsChanged();
+ m_drawingBuffer->mailboxReleased(mailbox2);
+ m_drawingBuffer->markContentsChanged();
+ m_drawingBuffer->mailboxReleased(mailbox3);
+ m_drawingBuffer->markContentsChanged();
+ m_drawingBuffer->mailboxReleased(mailbox1);
+
+ // The first recycled mailbox must be 2.
+ blink::WebExternalTextureMailbox recycledMailbox;
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&recycledMailbox, 0));
+ EXPECT_EQ(TextureMailboxWrapper(mailbox2), TextureMailboxWrapper(recycledMailbox));
+
+ // The second recycled mailbox must be 3.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&recycledMailbox, 0));
+ EXPECT_EQ(TextureMailboxWrapper(mailbox3), TextureMailboxWrapper(recycledMailbox));
+
+ // The third recycled mailbox must be 1.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&recycledMailbox, 0));
+ EXPECT_EQ(TextureMailboxWrapper(mailbox1), TextureMailboxWrapper(recycledMailbox));
+
+ m_drawingBuffer->mailboxReleased(mailbox1);
+ m_drawingBuffer->mailboxReleased(mailbox2);
+ m_drawingBuffer->mailboxReleased(mailbox3);
+ m_drawingBuffer->beginDestruction();
+}
+
+TEST_F(DrawingBufferTest, verifyInsertAndWaitSyncPointCorrectly)
+{
+ blink::WebExternalTextureMailbox mailbox;
+
+ // Produce mailboxes.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncPoint());
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ // prepareMailbox() does not wait for any sync point.
+ EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncPoint());
+
+ unsigned waitSyncPoint = webContext()->insertSyncPoint();
+ mailbox.syncPoint = waitSyncPoint;
+ m_drawingBuffer->mailboxReleased(mailbox);
+ // m_drawingBuffer will wait for the sync point when recycling.
+ EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncPoint());
+
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ // m_drawingBuffer waits for the sync point when recycling in prepareMailbox().
+ EXPECT_EQ(waitSyncPoint, webContext()->mostRecentlyWaitedSyncPoint());
+
+ m_drawingBuffer->beginDestruction();
+ waitSyncPoint = webContext()->insertSyncPoint();
+ mailbox.syncPoint = waitSyncPoint;
+ m_drawingBuffer->mailboxReleased(mailbox);
+ // m_drawingBuffer waits for the sync point because the destruction is in progress.
+ EXPECT_EQ(waitSyncPoint, webContext()->mostRecentlyWaitedSyncPoint());
+}
+
+class DrawingBufferImageChromiumTest : public DrawingBufferTest {
+protected:
+ virtual void SetUp()
+ {
+ RefPtr<FakeContextEvictionManager> contextEvictionManager = adoptRef(new FakeContextEvictionManager());
+ OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests);
+ m_context = context.get();
+ RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(true);
+ m_imageId0 = webContext()->nextImageIdToBeCreated();
+ EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId0)).Times(1);
+ m_drawingBuffer = DrawingBufferForTests::create(context.release(),
+ IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve, contextEvictionManager.release());
+ testing::Mock::VerifyAndClearExpectations(webContext());
+ }
+
+ virtual void TearDown()
+ {
+ RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(false);
+ }
+ WGC3Duint m_imageId0;
+};
+
+TEST_F(DrawingBufferImageChromiumTest, verifyResizingReallocatesImages)
+{
+ blink::WebExternalTextureMailbox mailbox;
+
+ IntSize initialSize(initialWidth, initialHeight);
+ IntSize alternateSize(initialWidth, alternateHeight);
+
+ WGC3Duint m_imageId1 = webContext()->nextImageIdToBeCreated();
+ EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId1)).Times(1);
+ // Produce one mailbox at size 100x100.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize());
+ EXPECT_TRUE(mailbox.allowOverlay);
+ testing::Mock::VerifyAndClearExpectations(webContext());
+
+ WGC3Duint m_imageId2 = webContext()->nextImageIdToBeCreated();
+ EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId2)).Times(1);
+ EXPECT_CALL(*webContext(), destroyImageMock(m_imageId0)).Times(1);
+ EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId0)).Times(1);
+ // Resize to 100x50.
+ m_drawingBuffer->reset(IntSize(initialWidth, alternateHeight));
+ m_drawingBuffer->mailboxReleased(mailbox);
+ testing::Mock::VerifyAndClearExpectations(webContext());
+
+ WGC3Duint m_imageId3 = webContext()->nextImageIdToBeCreated();
+ EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId3)).Times(1);
+ EXPECT_CALL(*webContext(), destroyImageMock(m_imageId1)).Times(1);
+ EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId1)).Times(1);
+ // Produce a mailbox at this size.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ EXPECT_EQ(alternateSize, webContext()->mostRecentlyProducedSize());
+ EXPECT_TRUE(mailbox.allowOverlay);
+ testing::Mock::VerifyAndClearExpectations(webContext());
+
+ WGC3Duint m_imageId4 = webContext()->nextImageIdToBeCreated();
+ EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId4)).Times(1);
+ EXPECT_CALL(*webContext(), destroyImageMock(m_imageId2)).Times(1);
+ EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId2)).Times(1);
+ // Reset to initial size.
+ m_drawingBuffer->reset(IntSize(initialWidth, initialHeight));
+ m_drawingBuffer->mailboxReleased(mailbox);
+ testing::Mock::VerifyAndClearExpectations(webContext());
+
+ WGC3Duint m_imageId5 = webContext()->nextImageIdToBeCreated();
+ EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId5)).Times(1);
+ EXPECT_CALL(*webContext(), destroyImageMock(m_imageId3)).Times(1);
+ EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId3)).Times(1);
+ // Prepare another mailbox and verify that it's the correct size.
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize());
+ EXPECT_TRUE(mailbox.allowOverlay);
+ testing::Mock::VerifyAndClearExpectations(webContext());
+
+ // Prepare one final mailbox and verify that it's the correct size.
+ m_drawingBuffer->mailboxReleased(mailbox);
+ m_drawingBuffer->markContentsChanged();
+ EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0));
+ EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize());
+ EXPECT_TRUE(mailbox.allowOverlay);
+ m_drawingBuffer->mailboxReleased(mailbox);
+
+ EXPECT_CALL(*webContext(), destroyImageMock(m_imageId5)).Times(1);
+ EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId5)).Times(1);
+ EXPECT_CALL(*webContext(), destroyImageMock(m_imageId4)).Times(1);
+ EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId4)).Times(1);
+ m_drawingBuffer->beginDestruction();
+ testing::Mock::VerifyAndClearExpectations(webContext());
+}
+
+class DepthStencilTrackingContext : public MockWebGraphicsContext3D {
+public:
+ DepthStencilTrackingContext()
+ : m_nextRenderBufferId(1)
+ , m_stencilAttachment(0)
+ , m_depthAttachment(0) { }
+ virtual ~DepthStencilTrackingContext() { }
+
+ int numAllocatedRenderBuffer() const { return m_nextRenderBufferId - 1; }
+ WebGLId stencilAttachment() const { return m_stencilAttachment; }
+ WebGLId depthAttachment() const { return m_depthAttachment; }
+
+ virtual WebString getString(WGC3Denum type) OVERRIDE
+ {
+ if (type == GL_EXTENSIONS) {
+ return WebString::fromUTF8("GL_OES_packed_depth_stencil");
+ }
+ return WebString();
+ }
+
+ virtual WebGLId createRenderbuffer() OVERRIDE
+ {
+ return ++m_nextRenderBufferId;
+ }
+
+ virtual void framebufferRenderbuffer(WGC3Denum target, WGC3Denum attachment, WGC3Denum renderbuffertarget, WebGLId renderbuffer) OVERRIDE
+ {
+ if (attachment == GL_STENCIL_ATTACHMENT) {
+ m_stencilAttachment = renderbuffer;
+ } else {
+ m_depthAttachment = renderbuffer;
+ }
+ }
+
+ virtual void getIntegerv(WGC3Denum ptype, WGC3Dint* value) OVERRIDE
+ {
+ switch (ptype) {
+ case GL_DEPTH_BITS:
+ *value = m_depthAttachment ? 24 : 0;
+ return;
+ case GL_STENCIL_BITS:
+ *value = m_stencilAttachment ? 8 : 0;
+ return;
+ }
+ MockWebGraphicsContext3D::getIntegerv(ptype, value);
+ }
+
+private:
+ WebGLId m_nextRenderBufferId;
+ WebGLId m_stencilAttachment;
+ WebGLId m_depthAttachment;
+};
+
+struct DepthStencilTestCase {
+ DepthStencilTestCase(bool requestStencil, bool requestDepth, int expectedRenderBuffers, bool expectDepthStencil, const char* const testCaseName)
+ : requestStencil(requestStencil)
+ , requestDepth(requestDepth)
+ , expectDepthStencil(expectDepthStencil)
+ , expectedRenderBuffers(expectedRenderBuffers)
+ , testCaseName(testCaseName) { }
+
+ bool requestStencil;
+ bool requestDepth;
+ bool expectDepthStencil;
+ int expectedRenderBuffers;
+ const char* const testCaseName;
+};
+
+// This tests that when the packed depth+stencil extension is supported DrawingBuffer always allocates
+// a single packed renderbuffer if either is requested and properly computes the actual context attributes
+// as defined by WebGL. We always allocate a packed buffer in this case since many desktop OpenGL drivers
+// that support this extension do not consider a framebuffer with only a depth or a stencil buffer attached
+// to be complete.
+TEST(DrawingBufferDepthStencilTest, packedDepthStencilSupported)
+{
+ DepthStencilTestCase cases[] = {
+ DepthStencilTestCase(false, false, false, 0, "neither"),
+ DepthStencilTestCase(true, false, true, 1, "stencil only"),
+ DepthStencilTestCase(false, true, true, 1, "depth only"),
+ DepthStencilTestCase(true, true, true, 1, "both"),
+ };
+
+ for (size_t i = 0; i < arraysize(cases); i++) {
+ SCOPED_TRACE(cases[i].testCaseName);
+ OwnPtr<DepthStencilTrackingContext> context = adoptPtr(new DepthStencilTrackingContext);
+ DepthStencilTrackingContext* trackingContext = context.get();
+ DrawingBuffer::PreserveDrawingBuffer preserve = DrawingBuffer::Preserve;
+ RefPtr<ContextEvictionManager> contextEvictionManager = adoptRef(new FakeContextEvictionManager);
+
+ blink::WebGraphicsContext3D::Attributes requestedAttributes;
+ requestedAttributes.stencil = cases[i].requestStencil;
+ requestedAttributes.depth = cases[i].requestDepth;
+ RefPtr<DrawingBuffer> drawingBuffer = DrawingBuffer::create(context.release(), IntSize(10, 10), preserve, requestedAttributes, contextEvictionManager);
+
+ EXPECT_EQ(cases[i].requestDepth, drawingBuffer->getActualAttributes().depth);
+ EXPECT_EQ(cases[i].requestStencil, drawingBuffer->getActualAttributes().stencil);
+ EXPECT_EQ(cases[i].expectedRenderBuffers, trackingContext->numAllocatedRenderBuffer());
+ if (cases[i].expectDepthStencil) {
+ EXPECT_EQ(trackingContext->stencilAttachment(), trackingContext->depthAttachment());
+ } else if (cases[i].requestStencil || cases[i].requestDepth) {
+ EXPECT_NE(trackingContext->stencilAttachment(), trackingContext->depthAttachment());
+ } else {
+ EXPECT_EQ(0u, trackingContext->stencilAttachment());
+ EXPECT_EQ(0u, trackingContext->depthAttachment());
+ }
+
+ drawingBuffer->reset(IntSize(10, 20));
+ EXPECT_EQ(cases[i].requestDepth, drawingBuffer->getActualAttributes().depth);
+ EXPECT_EQ(cases[i].requestStencil, drawingBuffer->getActualAttributes().stencil);
+ EXPECT_EQ(cases[i].expectedRenderBuffers, trackingContext->numAllocatedRenderBuffer());
+ if (cases[i].expectDepthStencil) {
+ EXPECT_EQ(trackingContext->stencilAttachment(), trackingContext->depthAttachment());
+ } else if (cases[i].requestStencil || cases[i].requestDepth) {
+ EXPECT_NE(trackingContext->stencilAttachment(), trackingContext->depthAttachment());
+ } else {
+ EXPECT_EQ(0u, trackingContext->stencilAttachment());
+ EXPECT_EQ(0u, trackingContext->depthAttachment());
+ }
+
+ drawingBuffer->beginDestruction();
+ }
+}
+
+} // namespace
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp b/chromium/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp
new file mode 100644
index 00000000000..7da33ee5211
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp
@@ -0,0 +1,101 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "platform/graphics/gpu/Extensions3DUtil.h"
+
+#include "public/platform/WebGraphicsContext3D.h"
+#include "wtf/text/CString.h"
+#include "wtf/text/StringHash.h"
+
+namespace WebCore {
+
+namespace {
+
+void splitStringHelper(const String& str, HashSet<String>& set)
+{
+ Vector<String> substrings;
+ str.split(" ", substrings);
+ for (size_t i = 0; i < substrings.size(); ++i)
+ set.add(substrings[i]);
+}
+
+} // anonymous namespace
+
+PassOwnPtr<Extensions3DUtil> Extensions3DUtil::create(blink::WebGraphicsContext3D* context)
+{
+ OwnPtr<Extensions3DUtil> out = adoptPtr(new Extensions3DUtil(context));
+ if (!out->initializeExtensions())
+ return nullptr;
+ return out.release();
+}
+
+Extensions3DUtil::Extensions3DUtil(blink::WebGraphicsContext3D* context)
+ : m_context(context)
+{
+}
+
+Extensions3DUtil::~Extensions3DUtil()
+{
+}
+
+bool Extensions3DUtil::initializeExtensions()
+{
+ if (!m_context->makeContextCurrent()) {
+ // Most likely the GPU process exited and the attempt to reconnect to it failed.
+ // Need to try to restore the context again later.
+ return false;
+ }
+
+ if (m_context->isContextLost()) {
+ // Need to try to restore the context again later.
+ return false;
+ }
+
+ String extensionsString = m_context->getString(GL_EXTENSIONS);
+ splitStringHelper(extensionsString, m_enabledExtensions);
+
+ String requestableExtensionsString = m_context->getRequestableExtensionsCHROMIUM();
+ splitStringHelper(requestableExtensionsString, m_requestableExtensions);
+
+ return true;
+}
+
+
+bool Extensions3DUtil::supportsExtension(const String& name)
+{
+ return m_enabledExtensions.contains(name) || m_requestableExtensions.contains(name);
+}
+
+bool Extensions3DUtil::ensureExtensionEnabled(const String& name)
+{
+ if (m_enabledExtensions.contains(name))
+ return true;
+
+ if (m_requestableExtensions.contains(name)) {
+ m_context->requestExtensionCHROMIUM(name.ascii().data());
+ m_enabledExtensions.clear();
+ m_requestableExtensions.clear();
+ initializeExtensions();
+ }
+ return m_enabledExtensions.contains(name);
+}
+
+bool Extensions3DUtil::isExtensionEnabled(const String& name)
+{
+ return m_enabledExtensions.contains(name);
+}
+
+bool Extensions3DUtil::canUseCopyTextureCHROMIUM(GLenum destFormat, GLenum destType, GLint level)
+{
+ // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE/(Level 0) should be lifted when
+ // WebGraphicsContext3D::copyTextureCHROMIUM(...) are fully functional.
+ if ((destFormat == GL_RGB || destFormat == GL_RGBA)
+ && destType == GL_UNSIGNED_BYTE
+ && !level)
+ return true;
+ return false;
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h b/chromium/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h
new file mode 100644
index 00000000000..3251192950e
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Extensions3DUtil_h
+#define Extensions3DUtil_h
+
+#include "platform/PlatformExport.h"
+#include "platform/graphics/GraphicsTypes3D.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "wtf/HashSet.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+class WebGraphicsContext3D;
+}
+
+namespace WebCore {
+
+class PLATFORM_EXPORT Extensions3DUtil {
+public:
+ // Creates a new Extensions3DUtil. If the passed WebGraphicsContext3D has been spontaneously lost, returns null.
+ static PassOwnPtr<Extensions3DUtil> create(blink::WebGraphicsContext3D*);
+ ~Extensions3DUtil();
+
+ bool supportsExtension(const String& name);
+ bool ensureExtensionEnabled(const String& name);
+ bool isExtensionEnabled(const String& name);
+
+ static bool canUseCopyTextureCHROMIUM(GLenum destFormat, GLenum destType, GLint level);
+
+private:
+ Extensions3DUtil(blink::WebGraphicsContext3D*);
+ bool initializeExtensions();
+
+ blink::WebGraphicsContext3D* m_context;
+ HashSet<String> m_enabledExtensions;
+ HashSet<String> m_requestableExtensions;
+};
+
+} // namespace WebCore
+
+#endif // Extensions3DUtil_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/chromium/third_party/WebKit/Source/platform/graphics/gpu/SharedGraphicsContext3D.cpp
deleted file mode 100644
index 9ce882a824c..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/gpu/SharedGraphicsContext3D.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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"
-
-#include "platform/graphics/gpu/SharedGraphicsContext3D.h"
-
-#include "platform/graphics/Extensions3D.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebGraphicsContext3D.h"
-#include "public/platform/WebGraphicsContext3DProvider.h"
-#include "wtf/MainThread.h"
-
-namespace WebCore {
-
-class SharedGraphicsContext3DImpl {
-public:
- SharedGraphicsContext3DImpl() : m_context(0) { }
-
- PassRefPtr<GraphicsContext3D> getOrCreateContext()
- {
- bool wasCreated = false;
-
- OwnPtr<blink::WebGraphicsContext3DProvider> provider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
-
- blink::WebGraphicsContext3D* webContext = 0;
- GrContext* grContext = 0;
-
- if (provider) {
- webContext = provider->context3d();
- grContext = provider->grContext();
- }
-
- if (webContext && grContext) {
- blink::WebGraphicsContext3D* oldWebContext = m_context ? m_context->webContext() : 0;
- GrContext* oldGrContext = m_context ? m_context->grContext() : 0;
- if (webContext != oldWebContext || grContext != oldGrContext)
- m_context.clear();
-
- if (!m_context) {
- m_context = GraphicsContext3D::createGraphicsContextFromProvider(provider.release());
- wasCreated = true;
- }
- }
-
- if (m_context && wasCreated)
- m_context->extensions()->pushGroupMarkerEXT("SharedGraphicsContext");
- return m_context;
- }
-
-private:
- RefPtr<GraphicsContext3D> m_context;
-};
-
-PassRefPtr<GraphicsContext3D> SharedGraphicsContext3D::get()
-{
- DEFINE_STATIC_LOCAL(SharedGraphicsContext3DImpl, impl, ());
- return impl.getOrCreateContext();
-}
-
-} // namespace WebCore
-
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.cpp b/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.cpp
index a9869c98d2e..3b1cfa187be 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.cpp
@@ -32,20 +32,30 @@
#include "platform/graphics/gpu/WebGLImageBufferSurface.h"
-#include "platform/graphics/gpu/SharedGraphicsContext3D.h"
#include "platform/graphics/skia/GaneshUtils.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
+#include "wtf/PassOwnPtr.h"
namespace WebCore {
WebGLImageBufferSurface::WebGLImageBufferSurface(const IntSize& size, OpacityMode opacityMode)
: ImageBufferSurface(size, opacityMode)
{
- GrContext* gr = SharedGraphicsContext3D::get()->grContext();
+ m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+ if (!m_contextProvider)
+ return;
+ GrContext* gr = m_contextProvider->grContext();
if (!gr)
return;
ensureTextureBackedSkBitmap(gr, m_bitmap, size, kDefault_GrSurfaceOrigin, kRGBA_8888_GrPixelConfig);
}
+WebGLImageBufferSurface::~WebGLImageBufferSurface()
+{
+}
+
Platform3DObject WebGLImageBufferSurface::getBackingTexture() const
{
GrTexture* texture = m_bitmap.getTexture();
@@ -54,4 +64,16 @@ Platform3DObject WebGLImageBufferSurface::getBackingTexture() const
return texture->getTextureHandle();
}
+void WebGLImageBufferSurface::invalidateCachedBitmap()
+{
+ m_cachedBitmap.reset();
+}
+
+void WebGLImageBufferSurface::updateCachedBitmapIfNeeded()
+{
+ if (m_cachedBitmap.isNull() && m_bitmap.pixelRef()) {
+ (m_bitmap.pixelRef())->readPixels(&m_cachedBitmap);
+ }
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.h b/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.h
index 0725ff271e2..a148e907be0 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageBufferSurface.h
@@ -33,6 +33,11 @@
#include "platform/graphics/ImageBufferSurface.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "wtf/OwnPtr.h"
+
+namespace blink {
+class WebGraphicsContext3DProvider;
+}
namespace WebCore {
@@ -41,16 +46,24 @@ class PLATFORM_EXPORT WebGLImageBufferSurface : public ImageBufferSurface {
WTF_MAKE_NONCOPYABLE(WebGLImageBufferSurface); WTF_MAKE_FAST_ALLOCATED;
public:
WebGLImageBufferSurface(const IntSize&, OpacityMode = NonOpaque);
- virtual ~WebGLImageBufferSurface() { }
+ virtual ~WebGLImageBufferSurface();
virtual SkCanvas* canvas() const OVERRIDE { return 0; }
virtual const SkBitmap& bitmap() const OVERRIDE { return m_bitmap; }
virtual bool isValid() const OVERRIDE { return m_bitmap.pixelRef(); }
virtual bool isAccelerated() const OVERRIDE { return true; }
virtual Platform3DObject getBackingTexture() const OVERRIDE;
+ virtual bool cachedBitmapEnabled() const OVERRIDE { return true; }
+ virtual const SkBitmap& cachedBitmap() const OVERRIDE { return m_cachedBitmap; }
+ virtual void invalidateCachedBitmap() OVERRIDE;
+ virtual void updateCachedBitmapIfNeeded() OVERRIDE;
private:
SkBitmap m_bitmap;
+ // This raw-pixel based SkBitmap works as a cache at CPU side to avoid heavy cost
+ // on readback from GPU side to CPU side in some cases.
+ SkBitmap m_cachedBitmap;
+ OwnPtr<blink::WebGraphicsContext3DProvider> m_contextProvider;
};
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3DImagePacking.cpp b/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.cpp
index 60cae8f5ae0..d90b4dddfac 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContext3DImagePacking.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.cpp
@@ -1,90 +1,71 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- * Copyright (C) 2010 Mozilla Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
- */
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "config.h"
-#include "platform/graphics/GraphicsContext3D.h"
+#include "platform/graphics/gpu/WebGLImageConversion.h"
-#include "platform/graphics/cpu/arm/GraphicsContext3DNEON.h"
-#include "platform/image-decoders/ImageDecoder.h"
+#include "platform/CheckedInt.h"
#include "platform/graphics/ImageObserver.h"
+#include "platform/graphics/cpu/arm/WebGLImageConversionNEON.h"
+#include "platform/image-decoders/ImageDecoder.h"
+#include "wtf/OwnPtr.h"
+#include "wtf/PassOwnPtr.h"
namespace WebCore {
namespace {
-GraphicsContext3D::DataFormat getDataFormat(GC3Denum destinationFormat, GC3Denum destinationType)
+WebGLImageConversion::DataFormat getDataFormat(GLenum destinationFormat, GLenum destinationType)
{
- GraphicsContext3D::DataFormat dstFormat = GraphicsContext3D::DataFormatRGBA8;
+ WebGLImageConversion::DataFormat dstFormat = WebGLImageConversion::DataFormatRGBA8;
switch (destinationType) {
case GL_UNSIGNED_BYTE:
switch (destinationFormat) {
case GL_RGB:
- dstFormat = GraphicsContext3D::DataFormatRGB8;
+ dstFormat = WebGLImageConversion::DataFormatRGB8;
break;
case GL_RGBA:
- dstFormat = GraphicsContext3D::DataFormatRGBA8;
+ dstFormat = WebGLImageConversion::DataFormatRGBA8;
break;
case GL_ALPHA:
- dstFormat = GraphicsContext3D::DataFormatA8;
+ dstFormat = WebGLImageConversion::DataFormatA8;
break;
case GL_LUMINANCE:
- dstFormat = GraphicsContext3D::DataFormatR8;
+ dstFormat = WebGLImageConversion::DataFormatR8;
break;
case GL_LUMINANCE_ALPHA:
- dstFormat = GraphicsContext3D::DataFormatRA8;
+ dstFormat = WebGLImageConversion::DataFormatRA8;
break;
default:
ASSERT_NOT_REACHED();
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
- dstFormat = GraphicsContext3D::DataFormatRGBA4444;
+ dstFormat = WebGLImageConversion::DataFormatRGBA4444;
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
- dstFormat = GraphicsContext3D::DataFormatRGBA5551;
+ dstFormat = WebGLImageConversion::DataFormatRGBA5551;
break;
case GL_UNSIGNED_SHORT_5_6_5:
- dstFormat = GraphicsContext3D::DataFormatRGB565;
+ dstFormat = WebGLImageConversion::DataFormatRGB565;
break;
case GL_HALF_FLOAT_OES: // OES_texture_half_float
switch (destinationFormat) {
case GL_RGB:
- dstFormat = GraphicsContext3D::DataFormatRGB16F;
+ dstFormat = WebGLImageConversion::DataFormatRGB16F;
break;
case GL_RGBA:
- dstFormat = GraphicsContext3D::DataFormatRGBA16F;
+ dstFormat = WebGLImageConversion::DataFormatRGBA16F;
break;
case GL_ALPHA:
- dstFormat = GraphicsContext3D::DataFormatA16F;
+ dstFormat = WebGLImageConversion::DataFormatA16F;
break;
case GL_LUMINANCE:
- dstFormat = GraphicsContext3D::DataFormatR16F;
+ dstFormat = WebGLImageConversion::DataFormatR16F;
break;
case GL_LUMINANCE_ALPHA:
- dstFormat = GraphicsContext3D::DataFormatRA16F;
+ dstFormat = WebGLImageConversion::DataFormatRA16F;
break;
default:
ASSERT_NOT_REACHED();
@@ -93,19 +74,19 @@ GraphicsContext3D::DataFormat getDataFormat(GC3Denum destinationFormat, GC3Denum
case GL_FLOAT: // OES_texture_float
switch (destinationFormat) {
case GL_RGB:
- dstFormat = GraphicsContext3D::DataFormatRGB32F;
+ dstFormat = WebGLImageConversion::DataFormatRGB32F;
break;
case GL_RGBA:
- dstFormat = GraphicsContext3D::DataFormatRGBA32F;
+ dstFormat = WebGLImageConversion::DataFormatRGBA32F;
break;
case GL_ALPHA:
- dstFormat = GraphicsContext3D::DataFormatA32F;
+ dstFormat = WebGLImageConversion::DataFormatA32F;
break;
case GL_LUMINANCE:
- dstFormat = GraphicsContext3D::DataFormatR32F;
+ dstFormat = WebGLImageConversion::DataFormatR32F;
break;
case GL_LUMINANCE_ALPHA:
- dstFormat = GraphicsContext3D::DataFormatRA32F;
+ dstFormat = WebGLImageConversion::DataFormatRA32F;
break;
default:
ASSERT_NOT_REACHED();
@@ -254,9 +235,9 @@ void unpack(const SourceType*, DstType*, unsigned)
ASSERT_NOT_REACHED();
}
-template<> void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatRGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
@@ -266,9 +247,9 @@ template<> void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, uint8_t>(cons
}
}
-template<> void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatBGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[2];
destination[1] = source[1];
destination[2] = source[0];
@@ -278,9 +259,9 @@ template<> void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, uint8_t>(cons
}
}
-template<> void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatARGB8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[1];
destination[1] = source[2];
destination[2] = source[3];
@@ -290,9 +271,9 @@ template<> void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, uint8_t>(con
}
}
-template<> void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatABGR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[3];
destination[1] = source[2];
destination[2] = source[1];
@@ -302,11 +283,11 @@ template<> void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, uint8_t>(con
}
}
-template<> void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatBGRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
const uint32_t* source32 = reinterpret_cast_ptr<const uint32_t*>(source);
uint32_t* destination32 = reinterpret_cast_ptr<uint32_t*>(destination);
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
uint32_t bgra = source32[i];
#if CPU(BIG_ENDIAN)
uint32_t brMask = 0xff00ff00;
@@ -320,12 +301,12 @@ template<> void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, uint8_t>(con
}
}
-template<> void unpack<GraphicsContext3D::DataFormatRGBA5551, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatRGBA5551, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
#if HAVE(ARM_NEON_INTRINSICS)
SIMD::unpackOneRowOfRGBA5551ToRGBA8(source, destination, pixelsPerRow);
#endif
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
uint16_t packedValue = source[0];
uint8_t r = packedValue >> 11;
uint8_t g = (packedValue >> 6) & 0x1F;
@@ -339,12 +320,12 @@ template<> void unpack<GraphicsContext3D::DataFormatRGBA5551, uint16_t, uint8_t>
}
}
-template<> void unpack<GraphicsContext3D::DataFormatRGBA4444, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatRGBA4444, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
#if HAVE(ARM_NEON_INTRINSICS)
SIMD::unpackOneRowOfRGBA4444ToRGBA8(source, destination, pixelsPerRow);
#endif
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
uint16_t packedValue = source[0];
uint8_t r = packedValue >> 12;
uint8_t g = (packedValue >> 8) & 0x0F;
@@ -359,12 +340,12 @@ template<> void unpack<GraphicsContext3D::DataFormatRGBA4444, uint16_t, uint8_t>
}
}
-template<> void unpack<GraphicsContext3D::DataFormatRGB565, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatRGB565, uint16_t, uint8_t>(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
#if HAVE(ARM_NEON_INTRINSICS)
SIMD::unpackOneRowOfRGB565ToRGBA8(source, destination, pixelsPerRow);
#endif
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
uint16_t packedValue = source[0];
uint8_t r = packedValue >> 11;
uint8_t g = (packedValue >> 5) & 0x3F;
@@ -378,9 +359,9 @@ template<> void unpack<GraphicsContext3D::DataFormatRGB565, uint16_t, uint8_t>(c
}
}
-template<> void unpack<GraphicsContext3D::DataFormatR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
@@ -390,9 +371,9 @@ template<> void unpack<GraphicsContext3D::DataFormatR8, uint8_t, uint8_t>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatRA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
@@ -402,9 +383,9 @@ template<> void unpack<GraphicsContext3D::DataFormatRA8, uint8_t, uint8_t>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatAR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatAR8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[1];
destination[1] = source[1];
destination[2] = source[1];
@@ -414,9 +395,9 @@ template<> void unpack<GraphicsContext3D::DataFormatAR8, uint8_t, uint8_t>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatA8, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = 0x0;
destination[1] = 0x0;
destination[2] = 0x0;
@@ -426,10 +407,10 @@ template<> void unpack<GraphicsContext3D::DataFormatA8, uint8_t, uint8_t>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatRGBA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatRGBA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
{
const float scaleFactor = 1.0f / 255.0f;
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0] * scaleFactor;
destination[1] = source[1] * scaleFactor;
destination[2] = source[2] * scaleFactor;
@@ -439,10 +420,10 @@ template<> void unpack<GraphicsContext3D::DataFormatRGBA8, uint8_t, float>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatBGRA8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
{
const float scaleFactor = 1.0f / 255.0f;
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[2] * scaleFactor;
destination[1] = source[1] * scaleFactor;
destination[2] = source[0] * scaleFactor;
@@ -452,7 +433,7 @@ template<> void unpack<GraphicsContext3D::DataFormatBGRA8, uint8_t, float>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatABGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
{
const float scaleFactor = 1.0f / 255.0f;
for (unsigned i = 0; i < pixelsPerRow; ++i) {
@@ -465,7 +446,7 @@ template<> void unpack<GraphicsContext3D::DataFormatABGR8, uint8_t, float>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatARGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
{
const float scaleFactor = 1.0f / 255.0f;
for (unsigned i = 0; i < pixelsPerRow; ++i) {
@@ -478,7 +459,7 @@ template<> void unpack<GraphicsContext3D::DataFormatARGB8, uint8_t, float>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatRGB8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
{
const float scaleFactor = 1.0f / 255.0f;
for (unsigned i = 0; i < pixelsPerRow; ++i) {
@@ -491,7 +472,7 @@ template<> void unpack<GraphicsContext3D::DataFormatRGB8, uint8_t, float>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatBGR8, uint8_t, float>(const uint8_t* source, float* destination, unsigned pixelsPerRow)
{
const float scaleFactor = 1.0f / 255.0f;
for (unsigned i = 0; i < pixelsPerRow; ++i) {
@@ -504,9 +485,9 @@ template<> void unpack<GraphicsContext3D::DataFormatBGR8, uint8_t, float>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatRGB32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatRGB32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
@@ -516,9 +497,9 @@ template<> void unpack<GraphicsContext3D::DataFormatRGB32F, float, float>(const
}
}
-template<> void unpack<GraphicsContext3D::DataFormatR32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatR32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
@@ -528,9 +509,9 @@ template<> void unpack<GraphicsContext3D::DataFormatR32F, float, float>(const fl
}
}
-template<> void unpack<GraphicsContext3D::DataFormatRA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatRA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
@@ -540,9 +521,9 @@ template<> void unpack<GraphicsContext3D::DataFormatRA32F, float, float>(const f
}
}
-template<> void unpack<GraphicsContext3D::DataFormatA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void unpack<WebGLImageConversion::DataFormatA32F, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = 0;
destination[1] = 0;
destination[2] = 0;
@@ -562,27 +543,27 @@ void pack(const SourceType*, DstType*, unsigned)
ASSERT_NOT_REACHED();
}
-template<> void pack<GraphicsContext3D::DataFormatA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatA8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[3];
source += 4;
destination += 1;
}
}
-template<> void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatR8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
source += 4;
destination += 1;
}
}
-template<> void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatR8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
destination[0] = sourceR;
@@ -592,9 +573,9 @@ template<> void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDo
}
// FIXME: this routine is lossy and must be removed.
-template<> void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatR8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
destination[0] = sourceR;
@@ -603,9 +584,9 @@ template<> void pack<GraphicsContext3D::DataFormatR8, GraphicsContext3D::AlphaDo
}
}
-template<> void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRA8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[3];
source += 4;
@@ -613,9 +594,9 @@ template<> void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaD
}
}
-template<> void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRA8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
destination[0] = sourceR;
@@ -626,9 +607,9 @@ template<> void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaD
}
// FIXME: this routine is lossy and must be removed.
-template<> void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRA8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
destination[0] = sourceR;
@@ -638,9 +619,9 @@ template<> void pack<GraphicsContext3D::DataFormatRA8, GraphicsContext3D::AlphaD
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
@@ -649,9 +630,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::Alpha
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -665,9 +646,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::Alpha
}
// FIXME: this routine is lossy and must be removed.
-template<> void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -681,14 +662,14 @@ template<> void pack<GraphicsContext3D::DataFormatRGB8, GraphicsContext3D::Alpha
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA8, WebGLImageConversion::AlphaDoNothing, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
memcpy(destination, source, pixelsPerRow * 4);
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA8, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -703,9 +684,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::Alph
}
// FIXME: this routine is lossy and must be removed.
-template<> void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA8, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint8_t>(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -719,12 +700,12 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA8, GraphicsContext3D::Alph
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA4444, WebGLImageConversion::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
{
#if HAVE(ARM_NEON_INTRINSICS)
SIMD::packOneRowOfRGBA8ToUnsignedShort4444(source, destination, pixelsPerRow);
#endif
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
*destination = (((source[0] & 0xF0) << 8)
| ((source[1] & 0xF0) << 4)
| (source[2] & 0xF0)
@@ -734,9 +715,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::A
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA4444, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -751,9 +732,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::A
}
// FIXME: this routine is lossy and must be removed.
-template<> void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA4444, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -767,12 +748,12 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA4444, GraphicsContext3D::A
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA5551, WebGLImageConversion::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
{
#if HAVE(ARM_NEON_INTRINSICS)
SIMD::packOneRowOfRGBA8ToUnsignedShort5551(source, destination, pixelsPerRow);
#endif
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
*destination = (((source[0] & 0xF8) << 8)
| ((source[1] & 0xF8) << 3)
| ((source[2] & 0xF8) >> 2)
@@ -782,9 +763,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::A
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA5551, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -799,9 +780,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::A
}
// FIXME: this routine is lossy and must be removed.
-template<> void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA5551, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -815,12 +796,12 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA5551, GraphicsContext3D::A
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB565, WebGLImageConversion::AlphaDoNothing, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
{
#if HAVE(ARM_NEON_INTRINSICS)
SIMD::packOneRowOfRGBA8ToUnsignedShort565(source, destination, pixelsPerRow);
#endif
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
*destination = (((source[0] & 0xF8) << 8)
| ((source[1] & 0xFC) << 3)
| ((source[2] & 0xF8) >> 3));
@@ -829,9 +810,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::Alp
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB565, WebGLImageConversion::AlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -845,9 +826,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::Alp
}
// FIXME: this routine is lossy and must be removed.
-template<> void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB565, WebGLImageConversion::AlphaDoUnmultiply, uint8_t, uint16_t>(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
@@ -860,9 +841,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGB565, GraphicsContext3D::Alp
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
@@ -871,9 +852,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::Alp
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = source[1] * scaleFactor;
@@ -883,9 +864,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::Alp
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
destination[0] = source[0] * scaleFactor;
destination[1] = source[1] * scaleFactor;
@@ -896,14 +877,14 @@ template<> void pack<GraphicsContext3D::DataFormatRGB32F, GraphicsContext3D::Alp
}
// Used only during RGBA8 or BGRA8 -> floating-point uploads.
-template<> void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
memcpy(destination, source, pixelsPerRow * 4 * sizeof(float));
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = source[1] * scaleFactor;
@@ -914,9 +895,9 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::Al
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
destination[0] = source[0] * scaleFactor;
destination[1] = source[1] * scaleFactor;
@@ -927,27 +908,27 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA32F, GraphicsContext3D::Al
}
}
-template<> void pack<GraphicsContext3D::DataFormatA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatA32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[3];
source += 4;
destination += 1;
}
}
-template<> void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatR32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
source += 4;
destination += 1;
}
}
-template<> void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatR32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
source += 4;
@@ -955,9 +936,9 @@ template<> void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::Alpha
}
}
-template<> void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatR32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
destination[0] = source[0] * scaleFactor;
source += 4;
@@ -965,9 +946,9 @@ template<> void pack<GraphicsContext3D::DataFormatR32F, GraphicsContext3D::Alpha
}
}
-template<> void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRA32F, WebGLImageConversion::AlphaDoNothing, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = source[0];
destination[1] = source[3];
source += 4;
@@ -975,9 +956,9 @@ template<> void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::Alph
}
}
-template<> void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRA32F, WebGLImageConversion::AlphaDoPremultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = source[3];
@@ -986,9 +967,9 @@ template<> void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::Alph
}
}
-template<> void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRA32F, WebGLImageConversion::AlphaDoUnmultiply, float, float>(const float* source, float* destination, unsigned pixelsPerRow)
{
- for (unsigned int i = 0; i < pixelsPerRow; ++i) {
+ for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
destination[0] = source[0] * scaleFactor;
destination[1] = source[3];
@@ -997,7 +978,7 @@ template<> void pack<GraphicsContext3D::DataFormatRA32F, GraphicsContext3D::Alph
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = convertFloatToHalfFloat(source[0]);
@@ -1009,7 +990,7 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::Al
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3];
@@ -1022,7 +1003,7 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::Al
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGBA16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
@@ -1035,7 +1016,7 @@ template<> void pack<GraphicsContext3D::DataFormatRGBA16F, GraphicsContext3D::Al
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = convertFloatToHalfFloat(source[0]);
@@ -1046,7 +1027,7 @@ template<> void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::Alp
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3];
@@ -1058,7 +1039,7 @@ template<> void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::Alp
}
}
-template<> void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRGB16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
@@ -1070,7 +1051,7 @@ template<> void pack<GraphicsContext3D::DataFormatRGB16F, GraphicsContext3D::Alp
}
}
-template<> void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRA16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = convertFloatToHalfFloat(source[0]);
@@ -1080,7 +1061,7 @@ template<> void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::Alph
}
}
-template<> void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRA16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3];
@@ -1091,7 +1072,7 @@ template<> void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::Alph
}
}
-template<> void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatRA16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
@@ -1102,7 +1083,7 @@ template<> void pack<GraphicsContext3D::DataFormatRA16F, GraphicsContext3D::Alph
}
}
-template<> void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatR16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = convertFloatToHalfFloat(source[0]);
@@ -1111,7 +1092,7 @@ template<> void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::Alpha
}
}
-template<> void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatR16F, WebGLImageConversion::AlphaDoPremultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3];
@@ -1121,7 +1102,7 @@ template<> void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::Alpha
}
}
-template<> void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatR16F, WebGLImageConversion::AlphaDoUnmultiply, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f;
@@ -1131,7 +1112,7 @@ template<> void pack<GraphicsContext3D::DataFormatR16F, GraphicsContext3D::Alpha
}
}
-template<> void pack<GraphicsContext3D::DataFormatA16F, GraphicsContext3D::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
+template<> void pack<WebGLImageConversion::DataFormatA16F, WebGLImageConversion::AlphaDoNothing, float, uint16_t>(const float* source, uint16_t* destination, unsigned pixelsPerRow)
{
for (unsigned i = 0; i < pixelsPerRow; ++i) {
destination[0] = convertFloatToHalfFloat(source[3]);
@@ -1142,73 +1123,73 @@ template<> void pack<GraphicsContext3D::DataFormatA16F, GraphicsContext3D::Alpha
bool HasAlpha(int format)
{
- return format == GraphicsContext3D::DataFormatA8
- || format == GraphicsContext3D::DataFormatA16F
- || format == GraphicsContext3D::DataFormatA32F
- || format == GraphicsContext3D::DataFormatRA8
- || format == GraphicsContext3D::DataFormatAR8
- || format == GraphicsContext3D::DataFormatRA16F
- || format == GraphicsContext3D::DataFormatRA32F
- || format == GraphicsContext3D::DataFormatRGBA8
- || format == GraphicsContext3D::DataFormatBGRA8
- || format == GraphicsContext3D::DataFormatARGB8
- || format == GraphicsContext3D::DataFormatABGR8
- || format == GraphicsContext3D::DataFormatRGBA16F
- || format == GraphicsContext3D::DataFormatRGBA32F
- || format == GraphicsContext3D::DataFormatRGBA4444
- || format == GraphicsContext3D::DataFormatRGBA5551;
+ return format == WebGLImageConversion::DataFormatA8
+ || format == WebGLImageConversion::DataFormatA16F
+ || format == WebGLImageConversion::DataFormatA32F
+ || format == WebGLImageConversion::DataFormatRA8
+ || format == WebGLImageConversion::DataFormatAR8
+ || format == WebGLImageConversion::DataFormatRA16F
+ || format == WebGLImageConversion::DataFormatRA32F
+ || format == WebGLImageConversion::DataFormatRGBA8
+ || format == WebGLImageConversion::DataFormatBGRA8
+ || format == WebGLImageConversion::DataFormatARGB8
+ || format == WebGLImageConversion::DataFormatABGR8
+ || format == WebGLImageConversion::DataFormatRGBA16F
+ || format == WebGLImageConversion::DataFormatRGBA32F
+ || format == WebGLImageConversion::DataFormatRGBA4444
+ || format == WebGLImageConversion::DataFormatRGBA5551;
}
bool HasColor(int format)
{
- return format == GraphicsContext3D::DataFormatRGBA8
- || format == GraphicsContext3D::DataFormatRGBA16F
- || format == GraphicsContext3D::DataFormatRGBA32F
- || format == GraphicsContext3D::DataFormatRGB8
- || format == GraphicsContext3D::DataFormatRGB16F
- || format == GraphicsContext3D::DataFormatRGB32F
- || format == GraphicsContext3D::DataFormatBGR8
- || format == GraphicsContext3D::DataFormatBGRA8
- || format == GraphicsContext3D::DataFormatARGB8
- || format == GraphicsContext3D::DataFormatABGR8
- || format == GraphicsContext3D::DataFormatRGBA5551
- || format == GraphicsContext3D::DataFormatRGBA4444
- || format == GraphicsContext3D::DataFormatRGB565
- || format == GraphicsContext3D::DataFormatR8
- || format == GraphicsContext3D::DataFormatR16F
- || format == GraphicsContext3D::DataFormatR32F
- || format == GraphicsContext3D::DataFormatRA8
- || format == GraphicsContext3D::DataFormatRA16F
- || format == GraphicsContext3D::DataFormatRA32F
- || format == GraphicsContext3D::DataFormatAR8;
+ return format == WebGLImageConversion::DataFormatRGBA8
+ || format == WebGLImageConversion::DataFormatRGBA16F
+ || format == WebGLImageConversion::DataFormatRGBA32F
+ || format == WebGLImageConversion::DataFormatRGB8
+ || format == WebGLImageConversion::DataFormatRGB16F
+ || format == WebGLImageConversion::DataFormatRGB32F
+ || format == WebGLImageConversion::DataFormatBGR8
+ || format == WebGLImageConversion::DataFormatBGRA8
+ || format == WebGLImageConversion::DataFormatARGB8
+ || format == WebGLImageConversion::DataFormatABGR8
+ || format == WebGLImageConversion::DataFormatRGBA5551
+ || format == WebGLImageConversion::DataFormatRGBA4444
+ || format == WebGLImageConversion::DataFormatRGB565
+ || format == WebGLImageConversion::DataFormatR8
+ || format == WebGLImageConversion::DataFormatR16F
+ || format == WebGLImageConversion::DataFormatR32F
+ || format == WebGLImageConversion::DataFormatRA8
+ || format == WebGLImageConversion::DataFormatRA16F
+ || format == WebGLImageConversion::DataFormatRA32F
+ || format == WebGLImageConversion::DataFormatAR8;
}
template<int Format>
struct IsFloatFormat {
static const bool Value =
- Format == GraphicsContext3D::DataFormatRGBA32F
- || Format == GraphicsContext3D::DataFormatRGB32F
- || Format == GraphicsContext3D::DataFormatRA32F
- || Format == GraphicsContext3D::DataFormatR32F
- || Format == GraphicsContext3D::DataFormatA32F;
+ Format == WebGLImageConversion::DataFormatRGBA32F
+ || Format == WebGLImageConversion::DataFormatRGB32F
+ || Format == WebGLImageConversion::DataFormatRA32F
+ || Format == WebGLImageConversion::DataFormatR32F
+ || Format == WebGLImageConversion::DataFormatA32F;
};
template<int Format>
struct IsHalfFloatFormat {
static const bool Value =
- Format == GraphicsContext3D::DataFormatRGBA16F
- || Format == GraphicsContext3D::DataFormatRGB16F
- || Format == GraphicsContext3D::DataFormatRA16F
- || Format == GraphicsContext3D::DataFormatR16F
- || Format == GraphicsContext3D::DataFormatA16F;
+ Format == WebGLImageConversion::DataFormatRGBA16F
+ || Format == WebGLImageConversion::DataFormatRGB16F
+ || Format == WebGLImageConversion::DataFormatRA16F
+ || Format == WebGLImageConversion::DataFormatR16F
+ || Format == WebGLImageConversion::DataFormatA16F;
};
template<int Format>
struct Is16bppFormat {
static const bool Value =
- Format == GraphicsContext3D::DataFormatRGBA5551
- || Format == GraphicsContext3D::DataFormatRGBA4444
- || Format == GraphicsContext3D::DataFormatRGB565;
+ Format == WebGLImageConversion::DataFormatRGBA5551
+ || Format == WebGLImageConversion::DataFormatRGBA4444
+ || Format == WebGLImageConversion::DataFormatRGB565;
};
template<int Format, bool IsFloat = IsFloatFormat<Format>::Value, bool IsHalfFloat = IsHalfFloatFormat<Format>::Value, bool Is16bpp = Is16bppFormat<Format>::Value>
@@ -1233,42 +1214,42 @@ struct DataTypeForFormat<Format, false, false, true> {
template<int Format>
struct IntermediateFormat {
- static const int Value = (IsFloatFormat<Format>::Value || IsHalfFloatFormat<Format>::Value) ? GraphicsContext3D::DataFormatRGBA32F : GraphicsContext3D::DataFormatRGBA8;
+ static const int Value = (IsFloatFormat<Format>::Value || IsHalfFloatFormat<Format>::Value) ? WebGLImageConversion::DataFormatRGBA32F : WebGLImageConversion::DataFormatRGBA8;
};
-unsigned TexelBytesForFormat(GraphicsContext3D::DataFormat format)
+unsigned TexelBytesForFormat(WebGLImageConversion::DataFormat format)
{
switch (format) {
- case GraphicsContext3D::DataFormatR8:
- case GraphicsContext3D::DataFormatA8:
+ case WebGLImageConversion::DataFormatR8:
+ case WebGLImageConversion::DataFormatA8:
return 1;
- case GraphicsContext3D::DataFormatRA8:
- case GraphicsContext3D::DataFormatAR8:
- case GraphicsContext3D::DataFormatRGBA5551:
- case GraphicsContext3D::DataFormatRGBA4444:
- case GraphicsContext3D::DataFormatRGB565:
- case GraphicsContext3D::DataFormatA16F:
- case GraphicsContext3D::DataFormatR16F:
+ case WebGLImageConversion::DataFormatRA8:
+ case WebGLImageConversion::DataFormatAR8:
+ case WebGLImageConversion::DataFormatRGBA5551:
+ case WebGLImageConversion::DataFormatRGBA4444:
+ case WebGLImageConversion::DataFormatRGB565:
+ case WebGLImageConversion::DataFormatA16F:
+ case WebGLImageConversion::DataFormatR16F:
return 2;
- case GraphicsContext3D::DataFormatRGB8:
- case GraphicsContext3D::DataFormatBGR8:
+ case WebGLImageConversion::DataFormatRGB8:
+ case WebGLImageConversion::DataFormatBGR8:
return 3;
- case GraphicsContext3D::DataFormatRGBA8:
- case GraphicsContext3D::DataFormatARGB8:
- case GraphicsContext3D::DataFormatABGR8:
- case GraphicsContext3D::DataFormatBGRA8:
- case GraphicsContext3D::DataFormatR32F:
- case GraphicsContext3D::DataFormatA32F:
- case GraphicsContext3D::DataFormatRA16F:
+ case WebGLImageConversion::DataFormatRGBA8:
+ case WebGLImageConversion::DataFormatARGB8:
+ case WebGLImageConversion::DataFormatABGR8:
+ case WebGLImageConversion::DataFormatBGRA8:
+ case WebGLImageConversion::DataFormatR32F:
+ case WebGLImageConversion::DataFormatA32F:
+ case WebGLImageConversion::DataFormatRA16F:
return 4;
- case GraphicsContext3D::DataFormatRGB16F:
+ case WebGLImageConversion::DataFormatRGB16F:
return 6;
- case GraphicsContext3D::DataFormatRA32F:
- case GraphicsContext3D::DataFormatRGBA16F:
+ case WebGLImageConversion::DataFormatRA32F:
+ case WebGLImageConversion::DataFormatRGBA16F:
return 8;
- case GraphicsContext3D::DataFormatRGB32F:
+ case WebGLImageConversion::DataFormatRGB32F:
return 12;
- case GraphicsContext3D::DataFormatRGBA32F:
+ case WebGLImageConversion::DataFormatRGBA32F:
return 16;
default:
return 0;
@@ -1289,17 +1270,17 @@ public:
ASSERT(m_unpackedIntermediateSrcData.get());
}
- void convert(GraphicsContext3D::DataFormat srcFormat, GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp);
+ void convert(WebGLImageConversion::DataFormat srcFormat, WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp);
bool Success() const { return m_success; }
private:
- template<GraphicsContext3D::DataFormat SrcFormat>
- void convert(GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp);
+ template<WebGLImageConversion::DataFormat SrcFormat>
+ void convert(WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp);
- template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat>
- void convert(GraphicsContext3D::AlphaOp);
+ template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat>
+ void convert(WebGLImageConversion::AlphaOp);
- template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat, GraphicsContext3D::AlphaOp alphaOp>
+ template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat, WebGLImageConversion::AlphaOp alphaOp>
void convert();
const unsigned m_width, m_height;
@@ -1310,63 +1291,63 @@ private:
OwnPtr<uint8_t[]> m_unpackedIntermediateSrcData;
};
-void FormatConverter::convert(GraphicsContext3D::DataFormat srcFormat, GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp alphaOp)
+void FormatConverter::convert(WebGLImageConversion::DataFormat srcFormat, WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp alphaOp)
{
#define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \
case SrcFormat: \
return convert<SrcFormat>(dstFormat, alphaOp);
switch (srcFormat) {
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatR8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatA8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatR32F)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatA32F)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRA8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRA32F)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatBGR8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB565)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGB32F)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatARGB8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatABGR8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatAR8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatBGRA8)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA5551)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA4444)
- FORMATCONVERTER_CASE_SRCFORMAT(GraphicsContext3D::DataFormatRGBA32F)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatR8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatA8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatR32F)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatA32F)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRA8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRA32F)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatBGR8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB565)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB32F)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatARGB8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatABGR8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatAR8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatBGRA8)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA5551)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA4444)
+ FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA32F)
default:
ASSERT_NOT_REACHED();
}
#undef FORMATCONVERTER_CASE_SRCFORMAT
}
-template<GraphicsContext3D::DataFormat SrcFormat>
-void FormatConverter::convert(GraphicsContext3D::DataFormat dstFormat, GraphicsContext3D::AlphaOp alphaOp)
+template<WebGLImageConversion::DataFormat SrcFormat>
+void FormatConverter::convert(WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp alphaOp)
{
#define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \
case DstFormat: \
return convert<SrcFormat, DstFormat>(alphaOp);
switch (dstFormat) {
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR8)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR16F)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatR32F)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA8)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA16F)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatA32F)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA8)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA16F)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRA32F)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB8)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB565)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB16F)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGB32F)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA8)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA5551)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA4444)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA16F)
- FORMATCONVERTER_CASE_DSTFORMAT(GraphicsContext3D::DataFormatRGBA32F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR8)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR16F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR32F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA8)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA16F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA32F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA8)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA16F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA32F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB8)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB565)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB16F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB32F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA8)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA5551)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA4444)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA16F)
+ FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA32F)
default:
ASSERT_NOT_REACHED();
}
@@ -1374,29 +1355,29 @@ void FormatConverter::convert(GraphicsContext3D::DataFormat dstFormat, GraphicsC
#undef FORMATCONVERTER_CASE_DSTFORMAT
}
-template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat>
-void FormatConverter::convert(GraphicsContext3D::AlphaOp alphaOp)
+template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat>
+void FormatConverter::convert(WebGLImageConversion::AlphaOp alphaOp)
{
#define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \
case alphaOp: \
return convert<SrcFormat, DstFormat, alphaOp>();
switch (alphaOp) {
- FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoNothing)
- FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoPremultiply)
- FORMATCONVERTER_CASE_ALPHAOP(GraphicsContext3D::AlphaDoUnmultiply)
+ FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoNothing)
+ FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoPremultiply)
+ FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoUnmultiply)
default:
ASSERT_NOT_REACHED();
}
#undef FORMATCONVERTER_CASE_ALPHAOP
}
-template<GraphicsContext3D::DataFormat SrcFormat, GraphicsContext3D::DataFormat DstFormat, GraphicsContext3D::AlphaOp alphaOp>
+template<WebGLImageConversion::DataFormat SrcFormat, WebGLImageConversion::DataFormat DstFormat, WebGLImageConversion::AlphaOp alphaOp>
void FormatConverter::convert()
{
// Many instantiations of this template function will never be entered, so we try
// to return immediately in these cases to avoid the compiler to generate useless code.
- if (SrcFormat == DstFormat && alphaOp == GraphicsContext3D::AlphaDoNothing) {
+ if (SrcFormat == DstFormat && alphaOp == WebGLImageConversion::AlphaDoNothing) {
ASSERT_NOT_REACHED();
return;
}
@@ -1406,17 +1387,17 @@ void FormatConverter::convert()
}
// Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat.
- const bool srcFormatComesFromDOMElementOrImageData = GraphicsContext3D::srcFormatComeFromDOMElementOrImageData(SrcFormat);
+ const bool srcFormatComesFromDOMElementOrImageData = WebGLImageConversion::srcFormatComeFromDOMElementOrImageData(SrcFormat);
if (!srcFormatComesFromDOMElementOrImageData && SrcFormat != DstFormat) {
ASSERT_NOT_REACHED();
return;
}
// Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied.
- if (!srcFormatComesFromDOMElementOrImageData && alphaOp == GraphicsContext3D::AlphaDoUnmultiply) {
+ if (!srcFormatComesFromDOMElementOrImageData && alphaOp == WebGLImageConversion::AlphaDoUnmultiply) {
ASSERT_NOT_REACHED();
return;
}
- if ((!HasAlpha(SrcFormat) || !HasColor(SrcFormat) || !HasColor(DstFormat)) && alphaOp != GraphicsContext3D::AlphaDoNothing) {
+ if ((!HasAlpha(SrcFormat) || !HasColor(SrcFormat) || !HasColor(DstFormat)) && alphaOp != WebGLImageConversion::AlphaDoNothing) {
ASSERT_NOT_REACHED();
return;
}
@@ -1427,8 +1408,8 @@ void FormatConverter::convert()
typedef typename DataTypeForFormat<IntermediateSrcFormat>::Type IntermediateSrcType;
const ptrdiff_t srcStrideInElements = m_srcStride / sizeof(SrcType);
const ptrdiff_t dstStrideInElements = m_dstStride / sizeof(DstType);
- const bool trivialUnpack = (SrcFormat == GraphicsContext3D::DataFormatRGBA8 && !IsFloatFormat<DstFormat>::Value && !IsHalfFloatFormat<DstFormat>::Value) || SrcFormat == GraphicsContext3D::DataFormatRGBA32F;
- const bool trivialPack = (DstFormat == GraphicsContext3D::DataFormatRGBA8 || DstFormat == GraphicsContext3D::DataFormatRGBA32F) && alphaOp == GraphicsContext3D::AlphaDoNothing && m_dstStride > 0;
+ const bool trivialUnpack = (SrcFormat == WebGLImageConversion::DataFormatRGBA8 && !IsFloatFormat<DstFormat>::Value && !IsHalfFloatFormat<DstFormat>::Value) || SrcFormat == WebGLImageConversion::DataFormatRGBA32F;
+ const bool trivialPack = (DstFormat == WebGLImageConversion::DataFormatRGBA8 || DstFormat == WebGLImageConversion::DataFormatRGBA32F) && alphaOp == WebGLImageConversion::AlphaDoNothing && m_dstStride > 0;
ASSERT(!trivialUnpack || !trivialPack);
const SrcType *srcRowStart = static_cast<const SrcType*>(m_srcStart);
@@ -1459,11 +1440,222 @@ void FormatConverter::convert()
} // anonymous namespace
-bool GraphicsContext3D::packImageData(
+bool WebGLImageConversion::computeFormatAndTypeParameters(GLenum format, GLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent)
+{
+ switch (format) {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL_OES:
+ *componentsPerPixel = 1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ *componentsPerPixel = 2;
+ break;
+ case GL_RGB:
+ *componentsPerPixel = 3;
+ break;
+ case GL_RGBA:
+ case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888
+ *componentsPerPixel = 4;
+ break;
+ default:
+ return false;
+ }
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ *bytesPerComponent = sizeof(GLubyte);
+ break;
+ case GL_UNSIGNED_SHORT:
+ *bytesPerComponent = sizeof(GLushort);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ *componentsPerPixel = 1;
+ *bytesPerComponent = sizeof(GLushort);
+ break;
+ case GL_UNSIGNED_INT_24_8_OES:
+ case GL_UNSIGNED_INT:
+ *bytesPerComponent = sizeof(GLuint);
+ break;
+ case GL_FLOAT: // OES_texture_float
+ *bytesPerComponent = sizeof(GLfloat);
+ break;
+ case GL_HALF_FLOAT_OES: // OES_texture_half_float
+ *bytesPerComponent = sizeof(GLushort);
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+GLenum WebGLImageConversion::computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, unsigned* imageSizeInBytes, unsigned* paddingInBytes)
+{
+ ASSERT(imageSizeInBytes);
+ ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8);
+ if (width < 0 || height < 0)
+ return GL_INVALID_VALUE;
+ unsigned bytesPerComponent, componentsPerPixel;
+ if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel))
+ return GL_INVALID_ENUM;
+ if (!width || !height) {
+ *imageSizeInBytes = 0;
+ if (paddingInBytes)
+ *paddingInBytes = 0;
+ return GL_NO_ERROR;
+ }
+ CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel);
+ checkedValue *= width;
+ if (!checkedValue.isValid())
+ return GL_INVALID_VALUE;
+ unsigned validRowSize = checkedValue.value();
+ unsigned padding = 0;
+ unsigned residual = validRowSize % alignment;
+ if (residual) {
+ padding = alignment - residual;
+ checkedValue += padding;
+ }
+ // Last row needs no padding.
+ checkedValue *= (height - 1);
+ checkedValue += validRowSize;
+ if (!checkedValue.isValid())
+ return GL_INVALID_VALUE;
+ *imageSizeInBytes = checkedValue.value();
+ if (paddingInBytes)
+ *paddingInBytes = padding;
+ return GL_NO_ERROR;
+}
+
+WebGLImageConversion::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomSource imageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
+{
+ m_image = image;
+ m_imageHtmlDomSource = imageHtmlDomSource;
+ m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile);
+}
+
+WebGLImageConversion::ImageExtractor::~ImageExtractor()
+{
+ if (m_skiaImage)
+ m_skiaImage->bitmap().unlockPixels();
+}
+
+bool WebGLImageConversion::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
+{
+ if (!m_image)
+ return false;
+ m_skiaImage = m_image->nativeImageForCurrentFrame();
+ m_alphaOp = AlphaDoNothing;
+ bool hasAlpha = m_skiaImage ? !m_skiaImage->bitmap().isOpaque() : true;
+ if ((!m_skiaImage || ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && m_image->data()) {
+ // Attempt to get raw unpremultiplied image data.
+ OwnPtr<ImageDecoder> decoder(ImageDecoder::create(
+ *(m_image->data()), ImageSource::AlphaNotPremultiplied,
+ ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied));
+ if (!decoder)
+ return false;
+ decoder->setData(m_image->data(), true);
+ if (!decoder->frameCount())
+ return false;
+ ImageFrame* frame = decoder->frameBufferAtIndex(0);
+ if (!frame || frame->status() != ImageFrame::FrameComplete)
+ return false;
+ hasAlpha = frame->hasAlpha();
+ m_nativeImage = frame->asNewNativeImage();
+ if (!m_nativeImage.get() || !m_nativeImage->isDataComplete() || !m_nativeImage->bitmap().width() || !m_nativeImage->bitmap().height())
+ return false;
+ if (m_nativeImage->bitmap().colorType() != kPMColor_SkColorType)
+ return false;
+ m_skiaImage = m_nativeImage.get();
+ if (hasAlpha && premultiplyAlpha)
+ m_alphaOp = AlphaDoPremultiply;
+ } else if (!premultiplyAlpha && hasAlpha) {
+ // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value for each pixel is 0xFF
+ // which is true at present and may be changed in the future and needs adjustment accordingly.
+ // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port,
+ // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false.
+ if (m_imageHtmlDomSource != HtmlDomVideo)
+ m_alphaOp = AlphaDoUnmultiply;
+ }
+ if (!m_skiaImage)
+ return false;
+
+ m_imageSourceFormat = SK_B32_SHIFT ? DataFormatRGBA8 : DataFormatBGRA8;
+ m_imageWidth = m_skiaImage->bitmap().width();
+ m_imageHeight = m_skiaImage->bitmap().height();
+ if (!m_imageWidth || !m_imageHeight) {
+ m_skiaImage.clear();
+ return false;
+ }
+ // Fail if the image was downsampled because of memory limits.
+ if (m_imageWidth != (unsigned)m_image->size().width() || m_imageHeight != (unsigned)m_image->size().height()) {
+ m_skiaImage.clear();
+ return false;
+ }
+ m_imageSourceUnpackAlignment = 0;
+ m_skiaImage->bitmap().lockPixels();
+ m_imagePixelData = m_skiaImage->bitmap().getPixels();
+ return true;
+}
+
+unsigned WebGLImageConversion::getClearBitsByFormat(GLenum format)
+{
+ switch (format) {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_RGB565:
+ case GL_RGBA:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ return GL_COLOR_BUFFER_BIT;
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT:
+ return GL_DEPTH_BUFFER_BIT;
+ case GL_STENCIL_INDEX8:
+ return GL_STENCIL_BUFFER_BIT;
+ case GL_DEPTH_STENCIL_OES:
+ return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
+ default:
+ return 0;
+ }
+}
+
+unsigned WebGLImageConversion::getChannelBitsByFormat(GLenum format)
+{
+ switch (format) {
+ case GL_ALPHA:
+ return ChannelAlpha;
+ case GL_LUMINANCE:
+ return ChannelRGB;
+ case GL_LUMINANCE_ALPHA:
+ return ChannelRGBA;
+ case GL_RGB:
+ case GL_RGB565:
+ return ChannelRGB;
+ case GL_RGBA:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ return ChannelRGBA;
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT:
+ return ChannelDepth;
+ case GL_STENCIL_INDEX8:
+ return ChannelStencil;
+ case GL_DEPTH_STENCIL_OES:
+ return ChannelDepth | ChannelStencil;
+ default:
+ return 0;
+ }
+}
+
+bool WebGLImageConversion::packImageData(
Image* image,
const void* pixels,
- GC3Denum format,
- GC3Denum type,
+ GLenum format,
+ GLenum type,
bool flipY,
AlphaOp alphaOp,
DataFormat sourceFormat,
@@ -1488,11 +1680,11 @@ bool GraphicsContext3D::packImageData(
return true;
}
-bool GraphicsContext3D::extractImageData(
+bool WebGLImageConversion::extractImageData(
const uint8_t* imageData,
const IntSize& imageDataSize,
- GC3Denum format,
- GC3Denum type,
+ GLenum format,
+ GLenum type,
bool flipY,
bool premultiplyAlpha,
Vector<uint8_t>& data)
@@ -1514,10 +1706,10 @@ bool GraphicsContext3D::extractImageData(
return true;
}
-bool GraphicsContext3D::extractTextureData(
+bool WebGLImageConversion::extractTextureData(
unsigned width,
unsigned height,
- GC3Denum format, GC3Denum type,
+ GLenum format, GLenum type,
unsigned unpackAlignment,
bool flipY, bool premultiplyAlpha,
const void* pixels,
@@ -1539,7 +1731,7 @@ bool GraphicsContext3D::extractTextureData(
return true;
}
-bool GraphicsContext3D::packPixels(
+bool WebGLImageConversion::packPixels(
const uint8_t* sourceData,
DataFormat sourceDataFormat,
unsigned width,
@@ -1585,4 +1777,3 @@ bool GraphicsContext3D::packPixels(
}
} // namespace WebCore
-
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.h b/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.h
new file mode 100644
index 00000000000..c595c2d80f7
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/gpu/WebGLImageConversion.h
@@ -0,0 +1,168 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WebGLImageConversion_h
+#define WebGLImageConversion_h
+
+#include "platform/PlatformExport.h"
+#include "platform/graphics/Image.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "wtf/RefPtr.h"
+
+namespace WebCore {
+class Image;
+class IntSize;
+
+// Helper functions for texture uploading and pixel readback.
+class PLATFORM_EXPORT WebGLImageConversion {
+public:
+ // Attempt to enumerate all possible native image formats to
+ // reduce the amount of temporary allocations during texture
+ // uploading. This enum must be public because it is accessed
+ // by non-member functions.
+ enum DataFormat {
+ DataFormatRGBA8 = 0,
+ DataFormatRGBA16F,
+ DataFormatRGBA32F,
+ DataFormatRGB8,
+ DataFormatRGB16F,
+ DataFormatRGB32F,
+ DataFormatBGR8,
+ DataFormatBGRA8,
+ DataFormatARGB8,
+ DataFormatABGR8,
+ DataFormatRGBA5551,
+ DataFormatRGBA4444,
+ DataFormatRGB565,
+ DataFormatR8,
+ DataFormatR16F,
+ DataFormatR32F,
+ DataFormatRA8,
+ DataFormatRA16F,
+ DataFormatRA32F,
+ DataFormatAR8,
+ DataFormatA8,
+ DataFormatA16F,
+ DataFormatA32F,
+ DataFormatNumFormats
+ };
+
+ enum ChannelBits {
+ ChannelRed = 1,
+ ChannelGreen = 2,
+ ChannelBlue = 4,
+ ChannelAlpha = 8,
+ ChannelDepth = 16,
+ ChannelStencil = 32,
+ ChannelRGB = ChannelRed | ChannelGreen | ChannelBlue,
+ ChannelRGBA = ChannelRGB | ChannelAlpha,
+ };
+
+ // Possible alpha operations that may need to occur during
+ // pixel packing. FIXME: kAlphaDoUnmultiply is lossy and must
+ // be removed.
+ enum AlphaOp {
+ AlphaDoNothing = 0,
+ AlphaDoPremultiply = 1,
+ AlphaDoUnmultiply = 2
+ };
+
+ enum ImageHtmlDomSource {
+ HtmlDomImage = 0,
+ HtmlDomCanvas = 1,
+ HtmlDomVideo = 2,
+ HtmlDomNone = 3
+ };
+
+ class PLATFORM_EXPORT ImageExtractor {
+ public:
+ ImageExtractor(Image*, ImageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+
+ ~ImageExtractor();
+
+ bool extractSucceeded() { return m_extractSucceeded; }
+ const void* imagePixelData() { return m_imagePixelData; }
+ unsigned imageWidth() { return m_imageWidth; }
+ unsigned imageHeight() { return m_imageHeight; }
+ DataFormat imageSourceFormat() { return m_imageSourceFormat; }
+ AlphaOp imageAlphaOp() { return m_alphaOp; }
+ unsigned imageSourceUnpackAlignment() { return m_imageSourceUnpackAlignment; }
+ ImageHtmlDomSource imageHtmlDomSource() { return m_imageHtmlDomSource; }
+ private:
+ // Extract the image and keeps track of its status, such as width, height, Source Alignment, format and AlphaOp etc.
+ // This needs to lock the resources or relevant data if needed and return true upon success
+ bool extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+
+ RefPtr<NativeImageSkia> m_nativeImage;
+ RefPtr<NativeImageSkia> m_skiaImage;
+ Image* m_image;
+ ImageHtmlDomSource m_imageHtmlDomSource;
+ bool m_extractSucceeded;
+ const void* m_imagePixelData;
+ unsigned m_imageWidth;
+ unsigned m_imageHeight;
+ DataFormat m_imageSourceFormat;
+ AlphaOp m_alphaOp;
+ unsigned m_imageSourceUnpackAlignment;
+ };
+
+ // Computes the components per pixel and bytes per component
+ // for the given format and type combination. Returns false if
+ // either was an invalid enum.
+ static bool computeFormatAndTypeParameters(GLenum format, GLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent);
+
+ // Computes the image size in bytes. If paddingInBytes is not null, padding
+ // is also calculated in return. Returns NO_ERROR if succeed, otherwise
+ // return the suggested GL error indicating the cause of the failure:
+ // INVALID_VALUE if width/height is negative or overflow happens.
+ // INVALID_ENUM if format/type is illegal.
+ static GLenum computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, unsigned* imageSizeInBytes, unsigned* paddingInBytes);
+
+ // Check if the format is one of the formats from the ImageData or DOM elements.
+ // The formats from ImageData is always RGBA8.
+ // The formats from DOM elements vary with Graphics ports. It can only be RGBA8 or BGRA8.
+ static ALWAYS_INLINE bool srcFormatComeFromDOMElementOrImageData(DataFormat SrcFormat)
+ {
+ return SrcFormat == DataFormatBGRA8 || SrcFormat == DataFormatRGBA8;
+ }
+
+ static unsigned getClearBitsByFormat(GLenum);
+ static unsigned getChannelBitsByFormat(GLenum);
+
+ // The Following functions are implemented in GraphicsContext3DImagePacking.cpp
+
+ // Packs the contents of the given Image which is passed in |pixels| into the passed Vector
+ // according to the given format and type, and obeying the flipY and AlphaOp flags.
+ // Returns true upon success.
+ static bool packImageData(Image*, const void* pixels, GLenum format, GLenum type, bool flipY, AlphaOp, DataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector<uint8_t>& data);
+
+ // Extracts the contents of the given ImageData into the passed Vector,
+ // packing the pixel data according to the given format and type,
+ // and obeying the flipY and premultiplyAlpha flags. Returns true
+ // upon success.
+ static bool extractImageData(const uint8_t*, const IntSize&, GLenum format, GLenum type, bool flipY, bool premultiplyAlpha, Vector<uint8_t>& data);
+
+ // Helper function which extracts the user-supplied texture
+ // data, applying the flipY and premultiplyAlpha parameters.
+ // If the data is not tightly packed according to the passed
+ // unpackAlignment, the output data will be tightly packed.
+ // Returns true if successful, false if any error occurred.
+ static bool extractTextureData(unsigned width, unsigned height, GLenum format, GLenum type, unsigned unpackAlignment, bool flipY, bool premultiplyAlpha, const void* pixels, Vector<uint8_t>& data);
+
+ // End GraphicsContext3DImagePacking.cpp functions
+
+private:
+ // Helper for packImageData/extractImageData/extractTextureData which implement packing of pixel
+ // data into the specified OpenGL destination format and type.
+ // A sourceUnpackAlignment of zero indicates that the source
+ // data is tightly packed. Non-zero values may take a slow path.
+ // Destination data will have no gaps between rows.
+ // Implemented in GraphicsContext3DImagePacking.cpp
+ static bool packPixels(const uint8_t* sourceData, DataFormat sourceDataFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, unsigned destinationFormat, unsigned destinationType, AlphaOp, void* destinationData, bool flipY);
+};
+
+} // namespace WebCore
+
+#endif // WebGLImageConversion_h
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/media/MediaPlayer.h b/chromium/third_party/WebKit/Source/platform/graphics/media/MediaPlayer.h
index dba4c80d321..182feb7eb5e 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/media/MediaPlayer.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/media/MediaPlayer.h
@@ -28,30 +28,35 @@
#include "platform/PlatformExport.h"
#include "platform/graphics/GraphicsTypes3D.h"
+#include "public/platform/WebMediaPlayer.h"
#include "wtf/Forward.h"
#include "wtf/Noncopyable.h"
namespace blink {
+class WebGraphicsContext3D;
+class WebContentDecryptionModule;
class WebInbandTextTrack;
class WebLayer;
+class WebMediaSource;
}
namespace WebCore {
class AudioSourceProvider;
class GraphicsContext;
-class GraphicsContext3D;
class IntRect;
-class IntSize;
class KURL;
class MediaPlayer;
-class HTMLMediaSource;
class TimeRanges;
+// GL types as defined in OpenGL ES 2.0 header file gl2.h from khronos.org.
+// That header cannot be included directly due to a conflict with NPAPI headers.
+// See crbug.com/328085.
+typedef unsigned GC3Denum;
+typedef int GC3Dint;
+
class MediaPlayerClient {
public:
- enum CORSMode { Unspecified, Anonymous, UseCredentials };
-
virtual ~MediaPlayerClient() { }
// the network state has changed
@@ -73,6 +78,10 @@ public:
virtual void mediaPlayerRequestSeek(double) = 0;
+ // The URL for video poster image.
+ // FIXME: Remove this when WebMediaPlayerClientImpl::loadInternal does not depend on it.
+ virtual KURL mediaPlayerPosterURL() = 0;
+
// Presentation-related methods
// a new frame of video is available
virtual void mediaPlayerRepaint() = 0;
@@ -80,20 +89,12 @@ public:
// the movie size has changed
virtual void mediaPlayerSizeChanged() = 0;
- enum MediaKeyErrorCode { UnknownError = 1, ClientError, ServiceError, OutputError, HardwareChangeError, DomainError };
- virtual void mediaPlayerKeyAdded(const String& /* keySystem */, const String& /* sessionId */) = 0;
- virtual void mediaPlayerKeyError(const String& /* keySystem */, const String& /* sessionId */, MediaKeyErrorCode, unsigned short /* systemCode */) = 0;
- virtual void mediaPlayerKeyMessage(const String& /* keySystem */, const String& /* sessionId */, const unsigned char* /* message */, unsigned /* messageLength */, const KURL& /* defaultURL */) = 0;
- virtual bool mediaPlayerKeyNeeded(const String& /* keySystem */, const String& /* sessionId */, const unsigned char* /* initData */, unsigned /* initDataLength */) = 0;
- virtual bool mediaPlayerKeyNeeded(Uint8Array*) = 0;
-
- virtual CORSMode mediaPlayerCORSMode() const = 0;
-
virtual void mediaPlayerSetWebLayer(blink::WebLayer*) = 0;
- virtual void mediaPlayerSetOpaque(bool) = 0;
- virtual void mediaPlayerDidAddTrack(blink::WebInbandTextTrack*) = 0;
- virtual void mediaPlayerDidRemoveTrack(blink::WebInbandTextTrack*) = 0;
+ virtual void mediaPlayerDidAddTextTrack(blink::WebInbandTextTrack*) = 0;
+ virtual void mediaPlayerDidRemoveTextTrack(blink::WebInbandTextTrack*) = 0;
+
+ virtual void mediaPlayerMediaSourceOpened(blink::WebMediaSource*) = 0;
};
typedef PassOwnPtr<MediaPlayer> (*CreateMediaEnginePlayer)(MediaPlayerClient*);
@@ -109,20 +110,12 @@ public:
MediaPlayer() { }
virtual ~MediaPlayer() { }
- virtual void load(const String& url) = 0;
- virtual void load(const String& url, PassRefPtr<HTMLMediaSource>) = 0;
-
- virtual void prepareToPlay() = 0;
+ virtual void load(blink::WebMediaPlayer::LoadType, const String& url, blink::WebMediaPlayer::CORSMode) = 0;
virtual void play() = 0;
virtual void pause() = 0;
- virtual bool supportsFullscreen() const = 0;
virtual bool supportsSave() const = 0;
- virtual IntSize naturalSize() const = 0;
-
- virtual bool hasVideo() const = 0;
- virtual bool hasAudio() const = 0;
virtual double duration() const = 0;
@@ -137,52 +130,32 @@ public:
virtual bool paused() const = 0;
- virtual void setVolume(double) = 0;
- virtual void setMuted(bool) = 0;
+ virtual void setPoster(const KURL&) = 0;
enum NetworkState { Empty, Idle, Loading, Loaded, FormatError, NetworkError, DecodeError };
virtual NetworkState networkState() const = 0;
- enum ReadyState { HaveNothing, HaveMetadata, HaveCurrentData, HaveFutureData, HaveEnoughData };
- virtual ReadyState readyState() const = 0;
-
virtual double maxTimeSeekable() const = 0;
virtual PassRefPtr<TimeRanges> buffered() const = 0;
virtual bool didLoadingProgress() const = 0;
virtual void paint(GraphicsContext*, const IntRect&) = 0;
- virtual bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject, GC3Dint, GC3Denum, GC3Denum, bool, bool) = 0;
+ virtual bool copyVideoTextureToPlatformTexture(blink::WebGraphicsContext3D*, Platform3DObject, GC3Dint, GC3Denum, GC3Denum, bool, bool) = 0;
enum Preload { None, MetaData, Auto };
virtual void setPreload(Preload) = 0;
- virtual void showFullscreenOverlay() = 0;
- virtual void hideFullscreenOverlay() = 0;
- virtual bool canShowFullscreenOverlay() const = 0;
-
virtual bool hasSingleSecurityOrigin() const = 0;
- virtual bool didPassCORSAccessCheck() const = 0;
-
// Time value in the movie's time scale. It is only necessary to override this if the media
// engine uses rational numbers to represent media time.
virtual double mediaTimeForTimeValue(double timeValue) const = 0;
- virtual unsigned decodedFrameCount() const = 0;
- virtual unsigned droppedFrameCount() const = 0;
- virtual unsigned corruptedFrameCount() const = 0;
- virtual unsigned audioDecodedByteCount() const = 0;
- virtual unsigned videoDecodedByteCount() const = 0;
-
#if ENABLE(WEB_AUDIO)
virtual AudioSourceProvider* audioSourceProvider() = 0;
#endif
-
- enum MediaKeyException { NoError, InvalidPlayerState, KeySystemNotSupported, InvalidAccess };
- virtual MediaKeyException addKey(const String&, const unsigned char*, unsigned, const unsigned char*, unsigned, const String&) = 0;
- virtual MediaKeyException generateKeyRequest(const String&, const unsigned char*, unsigned) = 0;
- virtual MediaKeyException cancelKeyRequest(const String&, const String&) = 0;
+ virtual blink::WebMediaPlayer* webMediaPlayer() const = 0;
};
}
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/skia/GaneshUtils.cpp b/chromium/third_party/WebKit/Source/platform/graphics/skia/GaneshUtils.cpp
index 149137e441d..19088745806 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/skia/GaneshUtils.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/skia/GaneshUtils.cpp
@@ -61,8 +61,8 @@ bool ensureTextureBackedSkBitmap(GrContext* gr, SkBitmap& bitmap, const IntSize&
SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, texture.get()));
if (!pixelRef)
return false;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- bitmap.setPixelRef(pixelRef, 0)->unref();
+ bitmap.setInfo(info);
+ bitmap.setPixelRef(pixelRef)->unref();
}
return true;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.cpp b/chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.cpp
index 969d23549f9..f0db318605e 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.cpp
@@ -46,6 +46,7 @@
#include "third_party/skia/include/core/SkScalar.h"
#include "third_party/skia/include/core/SkShader.h"
+#include <algorithm>
#include <math.h>
#include <limits>
@@ -56,7 +57,7 @@ static bool nearlyIntegral(float value)
return fabs(value - floorf(value)) < std::numeric_limits<float>::epsilon();
}
-ResamplingMode NativeImageSkia::computeResamplingMode(const SkMatrix& matrix, float srcWidth, float srcHeight, float destWidth, float destHeight) const
+InterpolationQuality NativeImageSkia::computeInterpolationQuality(const SkMatrix& matrix, float srcWidth, float srcHeight, float destWidth, float destHeight) const
{
// The percent change below which we will not resample. This usually means
// an off-by-one error on the web page, and just doing nearest neighbor
@@ -81,7 +82,7 @@ ResamplingMode NativeImageSkia::computeResamplingMode(const SkMatrix& matrix, fl
bool heightNearlyEqual = diffHeight < std::numeric_limits<float>::epsilon();
// We don't need to resample if the source and destination are the same.
if (widthNearlyEqual && heightNearlyEqual)
- return NoResampling;
+ return InterpolationNone;
if (srcWidth <= kSmallImageSizeThreshold
|| srcHeight <= kSmallImageSizeThreshold
@@ -94,11 +95,11 @@ ResamplingMode NativeImageSkia::computeResamplingMode(const SkMatrix& matrix, fl
// when the source image is only one pixel wide in that dimension.
if ((!nearlyIntegral(destWidth) && srcWidth > 1 + std::numeric_limits<float>::epsilon())
|| (!nearlyIntegral(destHeight) && srcHeight > 1 + std::numeric_limits<float>::epsilon()))
- return LinearResampling;
+ return InterpolationLow;
// Otherwise, don't resample small images. These are often used for
// borders and rules (think 1x1 images used to make lines).
- return NoResampling;
+ return InterpolationNone;
}
if (srcHeight * kLargeStretch <= destHeight || srcWidth * kLargeStretch <= destWidth) {
@@ -109,11 +110,11 @@ ResamplingMode NativeImageSkia::computeResamplingMode(const SkMatrix& matrix, fl
// (which might be large) and then is stretching it to fill some part
// of the page.
if (widthNearlyEqual || heightNearlyEqual)
- return NoResampling;
+ return InterpolationNone;
// The image is growing a lot and in more than one direction. Resampling
// is slow and doesn't give us very much when growing a lot.
- return LinearResampling;
+ return InterpolationLow;
}
if ((diffWidth / srcWidth < kFractionalChangeThreshold)
@@ -121,40 +122,40 @@ ResamplingMode NativeImageSkia::computeResamplingMode(const SkMatrix& matrix, fl
// It is disappointingly common on the web for image sizes to be off by
// one or two pixels. We don't bother resampling if the size difference
// is a small fraction of the original size.
- return NoResampling;
+ return InterpolationNone;
}
// When the image is not yet done loading, use linear. We don't cache the
// partially resampled images, and as they come in incrementally, it causes
// us to have to resample the whole thing every time.
if (!isDataComplete())
- return LinearResampling;
+ return InterpolationLow;
// Everything else gets resampled.
// High quality interpolation only enabled for scaling and translation.
if (!(matrix.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)))
- return AwesomeResampling;
+ return InterpolationHigh;
- return LinearResampling;
+ return InterpolationLow;
}
-static ResamplingMode limitResamplingMode(GraphicsContext* context, ResamplingMode resampling)
+static InterpolationQuality limitInterpolationQuality(GraphicsContext* context, InterpolationQuality resampling)
{
- switch (context->imageInterpolationQuality()) {
- case InterpolationNone:
- return NoResampling;
- case InterpolationMedium:
- // For now we treat InterpolationMedium and InterpolationLow the same.
- case InterpolationLow:
- if (resampling == AwesomeResampling)
- return LinearResampling;
- break;
- case InterpolationHigh:
- case InterpolationDefault:
- break;
- }
+ return std::min(resampling, context->imageInterpolationQuality());
+}
+
+static SkPaint::FilterLevel convertToSkiaFilterLevel(bool useBicubicFilter, InterpolationQuality resampling)
+{
+ // FIXME: If we get rid of this special case, this function can go away entirely.
+ if (useBicubicFilter)
+ return SkPaint::kHigh_FilterLevel;
+
+ // InterpolationHigh if useBicubicFilter is false means that we do
+ // a manual high quality resampling before drawing to Skia.
+ if (resampling == InterpolationHigh)
+ return SkPaint::kNone_FilterLevel;
- return resampling;
+ return static_cast<SkPaint::FilterLevel>(resampling);
}
// This function is used to scale an image and extract a scaled fragment.
@@ -223,6 +224,8 @@ SkBitmap NativeImageSkia::extractScaledImageFragment(const SkRect& srcRect, floa
void NativeImageSkia::drawResampledBitmap(GraphicsContext* context, SkPaint& paint, const SkRect& srcRect, const SkRect& destRect) const
{
TRACE_EVENT0("skia", "drawResampledBitmap");
+ if (context->paintingDisabled())
+ return;
// We want to scale |destRect| with transformation in the canvas to obtain
// the final scale. The final scale is a combination of scale transform
// in canvas and explicit scaling (srcRect and destRect).
@@ -233,7 +236,8 @@ void NativeImageSkia::drawResampledBitmap(GraphicsContext* context, SkPaint& pai
// This part of code limits scaling only to visible portion in the
SkRect destRectVisibleSubset;
- ClipRectToCanvas(context, destRect, &destRectVisibleSubset);
+ if (!context->canvas()->getClipBounds(&destRectVisibleSubset))
+ return;
// ClipRectToCanvas often overshoots, resulting in a larger region than our
// original destRect. Intersecting gets us back inside.
@@ -295,6 +299,8 @@ SkBitmap NativeImageSkia::resizedBitmap(const SkISize& scaledImageSize, const Sk
bool shouldCache = isDataComplete()
&& shouldCacheResampling(scaledImageSize, scaledImageSubset);
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ResizeImage", "cached", shouldCache);
+ // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
PlatformInstrumentation::willResizeImage(shouldCache);
SkBitmap resizedImage = skia::ImageOperations::Resize(m_image, skia::ImageOperations::RESIZE_LANCZOS3, scaledImageSize.width(), scaledImageSize.height(), scaledImageSubset);
resizedImage.setImmutable();
@@ -312,9 +318,33 @@ SkBitmap NativeImageSkia::resizedBitmap(const SkISize& scaledImageSize, const Sk
return resizedSubset;
}
-static bool hasNon90rotation(GraphicsContext* context)
+static bool shouldDrawAntiAliased(GraphicsContext* context, const SkRect& destRect)
{
- return !context->getTotalMatrix().rectStaysRect();
+ if (!context->shouldAntialias())
+ return false;
+ const SkMatrix totalMatrix = context->getTotalMatrix();
+ // Don't disable anti-aliasing if we're rotated or skewed.
+ if (!totalMatrix.rectStaysRect())
+ return true;
+ // Disable anti-aliasing for scales or n*90 degree rotations.
+ // Allow to opt out of the optimization though for "hairline" geometry
+ // images - using the shouldAntialiasHairlineImages() GraphicsContext flag.
+ if (!context->shouldAntialiasHairlineImages())
+ return false;
+ // Check if the dimensions of the destination are "small" (less than one
+ // device pixel). To prevent sudden drop-outs. Since we know that
+ // kRectStaysRect_Mask is set, the matrix either has scale and no skew or
+ // vice versa. We can query the kAffine_Mask flag to determine which case
+ // it is.
+ // FIXME: This queries the CTM while drawing, which is generally
+ // discouraged. Always drawing with AA can negatively impact performance
+ // though - that's why it's not always on.
+ SkScalar widthExpansion, heightExpansion;
+ if (totalMatrix.getType() & SkMatrix::kAffine_Mask)
+ widthExpansion = totalMatrix[SkMatrix::kMSkewY], heightExpansion = totalMatrix[SkMatrix::kMSkewX];
+ else
+ widthExpansion = totalMatrix[SkMatrix::kMScaleX], heightExpansion = totalMatrix[SkMatrix::kMScaleY];
+ return destRect.width() * fabs(widthExpansion) < 1 || destRect.height() * fabs(heightExpansion) < 1;
}
void NativeImageSkia::draw(GraphicsContext* context, const SkRect& srcRect, const SkRect& destRect, PassRefPtr<SkXfermode> compOp) const
@@ -325,14 +355,17 @@ void NativeImageSkia::draw(GraphicsContext* context, const SkRect& srcRect, cons
paint.setColorFilter(context->colorFilter());
paint.setAlpha(context->getNormalizedAlpha());
paint.setLooper(context->drawLooper());
- // only antialias if we're rotated or skewed
- paint.setAntiAlias(hasNon90rotation(context));
+ paint.setAntiAlias(shouldDrawAntiAliased(context, destRect));
- ResamplingMode resampling;
+ bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap());
+
+ InterpolationQuality resampling;
if (context->isAccelerated()) {
- resampling = LinearResampling;
+ resampling = InterpolationLow;
} else if (context->printing()) {
- resampling = NoResampling;
+ resampling = InterpolationNone;
+ } else if (isLazyDecoded) {
+ resampling = InterpolationHigh;
} else {
// Take into account scale applied to the canvas when computing sampling mode (e.g. CSS scale or page scale).
SkRect destRectTarget = destRect;
@@ -340,30 +373,27 @@ void NativeImageSkia::draw(GraphicsContext* context, const SkRect& srcRect, cons
if (!(totalMatrix.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)))
totalMatrix.mapRect(&destRectTarget, destRect);
- resampling = computeResamplingMode(totalMatrix,
+ resampling = computeInterpolationQuality(totalMatrix,
SkScalarToFloat(srcRect.width()), SkScalarToFloat(srcRect.height()),
SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height()));
}
- if (resampling == NoResampling) {
+ if (resampling == InterpolationNone) {
// FIXME: This is to not break tests (it results in the filter bitmap flag
- // being set to true). We need to decide if we respect NoResampling
- // being returned from computeResamplingMode.
- resampling = LinearResampling;
+ // being set to true). We need to decide if we respect InterpolationNone
+ // being returned from computeInterpolationQuality.
+ resampling = InterpolationLow;
}
- resampling = limitResamplingMode(context, resampling);
- paint.setFilterBitmap(resampling == LinearResampling);
+ resampling = limitInterpolationQuality(context, resampling);
- bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap());
// FIXME: Bicubic filtering in Skia is only applied to defer-decoded images
// as an experiment. Once this filtering code path becomes stable we should
// turn this on for all cases, including non-defer-decoded images.
- bool useBicubicFilter = resampling == AwesomeResampling && isLazyDecoded;
+ bool useBicubicFilter = resampling == InterpolationHigh && isLazyDecoded;
- if (useBicubicFilter)
- paint.setFilterLevel(SkPaint::kHigh_FilterLevel);
+ paint.setFilterLevel(convertToSkiaFilterLevel(useBicubicFilter, resampling));
- if (resampling == AwesomeResampling && !useBicubicFilter) {
+ if (resampling == InterpolationHigh && !useBicubicFilter) {
// Resample the image and then draw the result to canvas with bilinear
// filtering.
drawResampledBitmap(context, paint, srcRect, destRect);
@@ -381,12 +411,13 @@ void NativeImageSkia::draw(GraphicsContext* context, const SkRect& srcRect, cons
static SkBitmap createBitmapWithSpace(const SkBitmap& bitmap, int spaceWidth, int spaceHeight)
{
- SkBitmap result;
- result.setConfig(bitmap.config(),
- bitmap.width() + spaceWidth,
- bitmap.height() + spaceHeight);
- result.allocPixels();
+ SkImageInfo info = bitmap.info();
+ info.fWidth += spaceWidth;
+ info.fHeight += spaceHeight;
+ info.fAlphaType = kPremul_SkAlphaType;
+ SkBitmap result;
+ result.allocPixels(info);
result.eraseColor(SK_ColorTRANSPARENT);
bitmap.copyPixelsTo(reinterpret_cast<uint8_t*>(result.getPixels()), result.rowBytes() * result.height(), result.rowBytes());
@@ -409,8 +440,9 @@ void NativeImageSkia::drawPattern(
return; // nothing to draw
SkMatrix totalMatrix = context->getTotalMatrix();
- SkScalar ctmScaleX = totalMatrix.getScaleX();
- SkScalar ctmScaleY = totalMatrix.getScaleY();
+ AffineTransform ctm = context->getCTM();
+ SkScalar ctmScaleX = ctm.xScale();
+ SkScalar ctmScaleY = ctm.yScale();
totalMatrix.preScale(scale.width(), scale.height());
// Figure out what size the bitmap will be in the destination. The
@@ -422,82 +454,82 @@ void NativeImageSkia::drawPattern(
float destBitmapWidth = SkScalarToFloat(destRectTarget.width());
float destBitmapHeight = SkScalarToFloat(destRectTarget.height());
+ bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap());
+
// Compute the resampling mode.
- ResamplingMode resampling;
+ InterpolationQuality resampling;
if (context->isAccelerated() || context->printing())
- resampling = LinearResampling;
+ resampling = InterpolationLow;
+ else if (isLazyDecoded)
+ resampling = InterpolationHigh;
else
- resampling = computeResamplingMode(totalMatrix, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight);
- resampling = limitResamplingMode(context, resampling);
+ resampling = computeInterpolationQuality(totalMatrix, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight);
+ resampling = limitInterpolationQuality(context, resampling);
+
+ SkMatrix localMatrix;
+ // We also need to translate it such that the origin of the pattern is the
+ // origin of the destination rect, which is what WebKit expects. Skia uses
+ // the coordinate system origin as the base for the pattern. If WebKit wants
+ // a shifted image, it will shift it from there using the localMatrix.
+ const float adjustedX = phase.x() + normSrcRect.x() * scale.width();
+ const float adjustedY = phase.y() + normSrcRect.y() * scale.height();
+ localMatrix.setTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjustedY));
- SkMatrix shaderTransform;
RefPtr<SkShader> shader;
- bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap());
// Bicubic filter is only applied to defer-decoded images, see
// NativeImageSkia::draw for details.
- bool useBicubicFilter = resampling == AwesomeResampling && isLazyDecoded;
+ bool useBicubicFilter = resampling == InterpolationHigh && isLazyDecoded;
- if (resampling == AwesomeResampling && !useBicubicFilter) {
+ if (resampling == InterpolationHigh && !useBicubicFilter) {
// Do nice resampling.
float scaleX = destBitmapWidth / normSrcRect.width();
float scaleY = destBitmapHeight / normSrcRect.height();
SkRect scaledSrcRect;
+ // Since we are resizing the bitmap, we need to remove the scale
+ // applied to the pixels in the bitmap shader. This means we need
+ // CTM * localMatrix to have identity scale. Since we
+ // can't modify CTM (or the rectangle will be drawn in the wrong
+ // place), we must set localMatrix's scale to the inverse of
+ // CTM scale.
+ localMatrix.preScale(ctmScaleX ? 1 / ctmScaleX : 1, ctmScaleY ? 1 / ctmScaleY : 1);
+
// The image fragment generated here is not exactly what is
// requested. The scale factor used is approximated and image
// fragment is slightly larger to align to integer
// boundaries.
SkBitmap resampled = extractScaledImageFragment(normSrcRect, scaleX, scaleY, &scaledSrcRect);
if (repeatSpacing.isZero()) {
- shader = adoptRef(SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
+ shader = adoptRef(SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix));
} else {
shader = adoptRef(SkShader::CreateBitmapShader(
createBitmapWithSpace(resampled, repeatSpacing.width() * ctmScaleX, repeatSpacing.height() * ctmScaleY),
- SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
+ SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix));
}
-
- // Since we just resized the bitmap, we need to remove the scale
- // applied to the pixels in the bitmap shader. This means we need
- // CTM * shaderTransform to have identity scale. Since we
- // can't modify CTM (or the rectangle will be drawn in the wrong
- // place), we must set shaderTransform's scale to the inverse of
- // CTM scale.
- shaderTransform.setScale(ctmScaleX ? 1 / ctmScaleX : 1, ctmScaleY ? 1 / ctmScaleY : 1);
} else {
+ // Because no resizing occurred, the shader transform should be
+ // set to the pattern's transform, which just includes scale.
+ localMatrix.preScale(scale.width(), scale.height());
+
// No need to resample before drawing.
SkBitmap srcSubset;
bitmap().extractSubset(&srcSubset, enclosingIntRect(normSrcRect));
if (repeatSpacing.isZero()) {
- shader = adoptRef(SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
+ shader = adoptRef(SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix));
} else {
shader = adoptRef(SkShader::CreateBitmapShader(
createBitmapWithSpace(srcSubset, repeatSpacing.width() * ctmScaleX, repeatSpacing.height() * ctmScaleY),
- SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
+ SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix));
}
-
- // Because no resizing occurred, the shader transform should be
- // set to the pattern's transform, which just includes scale.
- shaderTransform.setScale(scale.width(), scale.height());
}
- // We also need to translate it such that the origin of the pattern is the
- // origin of the destination rect, which is what WebKit expects. Skia uses
- // the coordinate system origin as the base for the pattern. If WebKit wants
- // a shifted image, it will shift it from there using the shaderTransform.
- float adjustedX = phase.x() + normSrcRect.x() * scale.width();
- float adjustedY = phase.y() + normSrcRect.y() * scale.height();
- shaderTransform.postTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjustedY));
- shader->setLocalMatrix(shaderTransform);
-
SkPaint paint;
paint.setShader(shader.get());
paint.setXfermode(WebCoreCompositeToSkiaComposite(compositeOp, blendMode).get());
paint.setColorFilter(context->colorFilter());
+ paint.setFilterLevel(convertToSkiaFilterLevel(useBicubicFilter, resampling));
- paint.setFilterBitmap(resampling == LinearResampling);
- if (useBicubicFilter)
- paint.setFilterLevel(SkPaint::kHigh_FilterLevel);
if (isLazyDecoded)
PlatformInstrumentation::didDrawLazyPixelRef(bitmap().getGenerationID());
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.h b/chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.h
index 97b7bcd76bd..aebf1d1a4b8 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/skia/NativeImageSkia.h
@@ -52,20 +52,6 @@ class FloatRect;
class FloatSize;
class GraphicsContext;
-// Used by computeResamplingMode to tell how bitmaps should be resampled.
-enum ResamplingMode {
- // Nearest neighbor resampling. Used when we detect that the page is
- // trying to make a pattern by stretching a small bitmap very large.
- NoResampling,
-
- // Default skia resampling. Used for large growing of images where high
- // quality resampling doesn't get us very much except a slowdown.
- LinearResampling,
-
- // High quality resampling.
- AwesomeResampling,
-};
-
// This object is used as the "native image" in our port. When WebKit uses
// PassNativeImagePtr / NativeImagePtr, it is a smart pointer to this type.
// It has an SkBitmap, and also stores a cached resized image.
@@ -98,18 +84,11 @@ public:
// resized version if there is one.
int decodedSize() const;
- // Sets the immutable flag on the bitmap, indicating that the image data
- // will not be modified any further. This is called by the image decoder
- // when all data is complete, used by us to know whether we can cache
- // resized images, and used by Skia for various optimizations.
- void setDataComplete() { m_image.setImmutable(); }
-
// Returns true if the entire image has been decoded.
bool isDataComplete() const { return m_image.isImmutable(); }
// Get reference to the internal SkBitmap representing this image.
const SkBitmap& bitmap() const { return m_image; }
- SkBitmap& bitmap() { return m_image; }
// We can keep a resized version of the bitmap cached on this object.
// This function will return true if there is a cached version of the given
@@ -173,7 +152,7 @@ private:
// entire thing, it's best to just do it up front.
bool shouldCacheResampling(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const;
- ResamplingMode computeResamplingMode(const SkMatrix&, float srcWidth, float srcHeight, float destWidth, float destHeight) const;
+ InterpolationQuality computeInterpolationQuality(const SkMatrix&, float srcWidth, float srcHeight, float destWidth, float destHeight) const;
SkBitmap extractScaledImageFragment(const SkRect& srcRect, float scaleX, float scaleY, SkRect* scaledSrcRect) const;
void drawResampledBitmap(GraphicsContext*, SkPaint&, const SkRect& srcRect, const SkRect& destRect) const;
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/skia/OpaqueRegionSkia.cpp b/chromium/third_party/WebKit/Source/platform/graphics/skia/OpaqueRegionSkia.cpp
index 060b1754c97..d0976723bd9 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/skia/OpaqueRegionSkia.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/skia/OpaqueRegionSkia.cpp
@@ -47,10 +47,13 @@ OpaqueRegionSkia::OpaqueRegionSkia()
IntRect OpaqueRegionSkia::asRect() const
{
// Returns the largest enclosed rect.
- int left = SkScalarCeil(m_opaqueRect.fLeft);
- int top = SkScalarCeil(m_opaqueRect.fTop);
- int right = SkScalarFloor(m_opaqueRect.fRight);
- int bottom = SkScalarFloor(m_opaqueRect.fBottom);
+ // TODO: actually, this logic looks like its returning the smallest.
+ // to return largest, shouldn't we take floor of left/top
+ // and the ceil of right/bottom?
+ int left = SkScalarCeilToInt(m_opaqueRect.fLeft);
+ int top = SkScalarCeilToInt(m_opaqueRect.fTop);
+ int right = SkScalarFloorToInt(m_opaqueRect.fRight);
+ int bottom = SkScalarFloorToInt(m_opaqueRect.fBottom);
return IntRect(left, top, right-left, bottom-top);
}
@@ -147,7 +150,7 @@ static inline bool paintIsOpaque(const SkPaint& paint, OpaqueRegionSkia::DrawTyp
static inline bool getDeviceClipAsRect(const GraphicsContext* context, SkRect& deviceClipRect)
{
// Get the current clip in device coordinate space.
- if (context->canvas()->getClipType() != SkCanvas::kRect_ClipType)
+ if (!context->canvas()->isClipRect())
return false;
SkIRect deviceClipIRect;
@@ -169,6 +172,7 @@ void OpaqueRegionSkia::pushCanvasLayer(const SkPaint* paint)
void OpaqueRegionSkia::popCanvasLayer(const GraphicsContext* context)
{
+ ASSERT(!context->paintingDisabled());
ASSERT(!m_canvasLayerStack.isEmpty());
if (m_canvasLayerStack.isEmpty())
return;
@@ -195,6 +199,7 @@ void OpaqueRegionSkia::setImageMask(const SkRect& imageOpaqueRect)
void OpaqueRegionSkia::didDrawRect(const GraphicsContext* context, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* sourceBitmap)
{
+ ASSERT(!context->paintingDisabled());
// Any stroking may put alpha in pixels even if the filling part does not.
if (paint.getStyle() != SkPaint::kFill_Style) {
bool fillsBounds = false;
@@ -214,6 +219,7 @@ void OpaqueRegionSkia::didDrawRect(const GraphicsContext* context, const SkRect&
void OpaqueRegionSkia::didDrawPath(const GraphicsContext* context, const SkPath& path, const SkPaint& paint)
{
+ ASSERT(!context->paintingDisabled());
SkRect rect;
if (path.isRect(&rect)) {
didDrawRect(context, rect, paint, 0);
@@ -232,6 +238,7 @@ void OpaqueRegionSkia::didDrawPath(const GraphicsContext* context, const SkPath&
void OpaqueRegionSkia::didDrawPoints(const GraphicsContext* context, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint)
{
+ ASSERT(!context->paintingDisabled());
if (!numPoints)
return;
@@ -260,6 +267,7 @@ void OpaqueRegionSkia::didDrawPoints(const GraphicsContext* context, SkCanvas::P
void OpaqueRegionSkia::didDrawBounded(const GraphicsContext* context, const SkRect& bounds, const SkPaint& paint)
{
+ ASSERT(!context->paintingDisabled());
bool fillsBounds = false;
if (!paint.canComputeFastBounds())
@@ -273,6 +281,7 @@ void OpaqueRegionSkia::didDrawBounded(const GraphicsContext* context, const SkRe
void OpaqueRegionSkia::didDraw(const GraphicsContext* context, const SkRect& rect, const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType drawType)
{
+ ASSERT(!context->paintingDisabled());
SkRect targetRect = rect;
// Apply the transform to device coordinate space.
@@ -299,6 +308,7 @@ void OpaqueRegionSkia::didDraw(const GraphicsContext* context, const SkRect& rec
void OpaqueRegionSkia::didDrawUnbounded(const GraphicsContext* context, const SkPaint& paint, DrawType drawType)
{
+ ASSERT(!context->paintingDisabled());
bool drawsOpaque = paintIsOpaque(paint, drawType, 0);
bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp b/chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp
index 882209b7626..ac2a0b397be 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp
@@ -128,12 +128,6 @@ SkColor SkPMColorToColor(SkPMColor pm)
InvScaleByte(SkGetPackedB32(pm), scale));
}
-void ClipRectToCanvas(const GraphicsContext* context, const SkRect& srcRect, SkRect* destRect)
-{
- if (!context->getClipBounds(destRect) || !destRect->intersect(srcRect))
- destRect->setEmpty();
-}
-
bool SkPathContainsPoint(const SkPath& originalPath, const FloatPoint& point, SkPath::FillType ft)
{
SkRect bounds = originalPath.getBounds();
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h b/chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h
index 0d94406974f..0b4082b7953 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h
+++ b/chromium/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h
@@ -34,6 +34,7 @@
#define SkiaUtils_h
#include "SkMatrix.h"
+#include "SkPaint.h"
#include "SkPath.h"
#include "SkXfermode.h"
#include "platform/PlatformExport.h"
@@ -56,6 +57,13 @@ PassRefPtr<SkXfermode> WebCoreCompositeToSkiaComposite(CompositeOperator, blink:
// move this guy into SkColor.h
SkColor SkPMColorToColor(SkPMColor);
+inline SkPaint::FilterLevel WebCoreInterpolationQualityToSkFilterLevel(InterpolationQuality quality)
+{
+ // FIXME: this reflects existing client mappings, but should probably
+ // be expanded to map higher level interpolations more accurately.
+ return quality != InterpolationNone ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel;
+}
+
// Skia has problems when passed infinite, etc floats, filter them to 0.
inline SkScalar WebCoreFloatToSkScalar(float f)
{
@@ -78,13 +86,6 @@ inline bool WebCoreFloatNearlyEqual(float a, float b)
return SkScalarNearlyEqual(WebCoreFloatToSkScalar(a), WebCoreFloatToSkScalar(b));
}
-// Computes the smallest rectangle that, which when drawn to the given canvas,
-// will cover the same area as the source rectangle. It will clip to the canvas'
-// clip, doing the necessary coordinate transforms.
-//
-// srcRect and destRect can be the same.
-void ClipRectToCanvas(const GraphicsContext*, const SkRect& srcRect, SkRect* destRect);
-
// Determine if a given WebKit point is contained in a path
bool PLATFORM_EXPORT SkPathContainsPoint(const SkPath&, const FloatPoint&, SkPath::FillType);
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/win/TransparencyWin.cpp b/chromium/third_party/WebKit/Source/platform/graphics/win/TransparencyWin.cpp
deleted file mode 100644
index 5c7b56e2d07..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/win/TransparencyWin.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Copyright (C) 2009 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"
-
-#include "platform/graphics/win/TransparencyWin.h"
-
-#include "SkColorPriv.h"
-#include "platform/fonts/SimpleFontData.h"
-#include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/skia/SkiaUtils.h"
-#include "skia/ext/platform_canvas.h"
-
-namespace WebCore {
-
-namespace {
-
-// The maximum size in pixels of the buffer we'll keep around for drawing text
-// into. Buffers larger than this will be destroyed when we're done with them.
-const int maxCachedBufferPixelSize = 65536;
-
-inline const SkBitmap& bitmapForContext(const GraphicsContext& context)
-{
- return context.layerBitmap();
-}
-
-void compositeToCopy(GraphicsContext& sourceLayers, GraphicsContext& destContext, const AffineTransform& matrix)
-{
- // Make a list of all devices. The iterator goes top-down, and we want
- // bottom-up. Note that each layer can also have an offset in canvas
- // coordinates, which is the (x, y) position.
- struct DeviceInfo {
- DeviceInfo(SkBaseDevice* d, int lx, int ly)
- : device(d)
- , x(lx)
- , y(ly) { }
- SkBaseDevice* device;
- int x;
- int y;
- };
- Vector<DeviceInfo> devices;
- SkCanvas* sourceCanvas = sourceLayers.canvas();
- SkCanvas::LayerIter iter(sourceCanvas, false);
- while (!iter.done()) {
- devices.append(DeviceInfo(iter.device(), iter.x(), iter.y()));
- iter.next();
- }
-
- // Create a temporary canvas for the compositing into the destination.
- SkBitmap* destBmp = const_cast<SkBitmap*>(&bitmapForContext(destContext));
- SkCanvas destCanvas(*destBmp);
- destCanvas.setMatrix(affineTransformToSkMatrix(matrix));
-
- for (int i = devices.size() - 1; i >= 0; i--) {
- const SkBitmap& srcBmp = devices[i].device->accessBitmap(false);
-
- SkRect destRect;
- destRect.fLeft = devices[i].x;
- destRect.fTop = devices[i].y;
- destRect.fRight = destRect.fLeft + srcBmp.width();
- destRect.fBottom = destRect.fTop + srcBmp.height();
-
- destCanvas.drawBitmapRect(srcBmp, 0, destRect);
- }
-}
-
-} // namespace
-
-// If either of these pointers is non-null, both must be valid and point to
-// bitmaps of the same size.
-class TransparencyWin::OwnedBuffers {
-public:
- OwnedBuffers(const IntSize& size, bool needReferenceBuffer)
- {
- m_destBitmap = ImageBuffer::create(size);
-
- if (needReferenceBuffer) {
- m_referenceBitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- m_referenceBitmap.allocPixels();
- m_referenceBitmap.eraseARGB(0, 0, 0, 0);
- }
- }
-
- ImageBuffer* destBitmap() { return m_destBitmap.get(); }
-
- // This bitmap will be empty if you don't specify needReferenceBuffer to the
- // constructor.
- SkBitmap* referenceBitmap() { return &m_referenceBitmap; }
-
- // Returns whether the current layer will fix a buffer of the given size.
- bool canHandleSize(const IntSize& size) const
- {
- return m_destBitmap->size().width() >= size.width() && m_destBitmap->size().height() >= size.height();
- }
-
-private:
- // The destination bitmap we're drawing into.
- OwnPtr<ImageBuffer> m_destBitmap;
-
- // This could be an ImageBuffer but this is an optimization. Since this is
- // only ever used as a reference, we don't need to make a full
- // PlatformCanvas using Skia on Windows. Just allocating a regular SkBitmap
- // is much faster since it's just a Malloc rather than a GDI call.
- SkBitmap m_referenceBitmap;
-};
-
-TransparencyWin::OwnedBuffers* TransparencyWin::m_cachedBuffers = 0;
-
-TransparencyWin::TransparencyWin()
- : m_destContext(0)
- , m_orgTransform()
- , m_layerMode(NoLayer)
- , m_transformMode(KeepTransform)
- , m_drawContext(0)
- , m_savedOnDrawContext(false)
- , m_layerBuffer(0)
- , m_referenceBitmap(0)
- , m_validLayer(false)
-{
-}
-
-TransparencyWin::~TransparencyWin()
-{
- // This should be false, since calling composite() is mandatory.
- ASSERT(!m_savedOnDrawContext);
-}
-
-void TransparencyWin::composite()
-{
- // Matches the save() in initializeNewTextContext (or the constructor for
- // SCALE) to put the context back into the same state we found it.
- if (m_savedOnDrawContext) {
- m_drawContext->restore();
- m_savedOnDrawContext = false;
- }
-
- switch (m_layerMode) {
- case NoLayer:
- break;
- case OpaqueCompositeLayer:
- case WhiteLayer:
- compositeOpaqueComposite();
- break;
- case TextComposite:
- compositeTextComposite();
- break;
- }
-}
-
-void TransparencyWin::init(GraphicsContext* dest, LayerMode layerMode, TransformMode transformMode, const IntRect& region)
-{
- m_destContext = dest;
- m_orgTransform = dest->getCTM();
- m_layerMode = layerMode;
- m_transformMode = transformMode;
- m_sourceRect = region;
-
- computeLayerSize();
- setupLayer();
- setupTransform(region);
-}
-
-void TransparencyWin::computeLayerSize()
-{
- if (m_transformMode == Untransform) {
- // The meaning of the "transformed" source rect is a little ambigous
- // here. The rest of the code doesn't care about it in the Untransform
- // case since we're using our own happy coordinate system. So we set it
- // to be the source rect since that matches how the code below actually
- // uses the variable: to determine how to translate things to account
- // for the offset of the layer.
- m_transformedSourceRect = m_sourceRect;
- } else if (m_transformMode == KeepTransform && m_layerMode != TextComposite) {
- // FIXME: support clipping for other modes
- IntRect clippedSourceRect = m_sourceRect;
- SkRect clipBounds;
- if (m_destContext->getClipBounds(&clipBounds)) {
- FloatRect clipRect(clipBounds.left(), clipBounds.top(), clipBounds.width(), clipBounds.height());
- clippedSourceRect.intersect(enclosingIntRect(clipRect));
- }
- m_transformedSourceRect = m_orgTransform.mapRect(clippedSourceRect);
- } else {
- m_transformedSourceRect = m_orgTransform.mapRect(m_sourceRect);
- }
-
- m_layerSize = IntSize(m_transformedSourceRect.width(), m_transformedSourceRect.height());
-}
-
-void TransparencyWin::setupLayer()
-{
- switch (m_layerMode) {
- case NoLayer:
- setupLayerForNoLayer();
- break;
- case OpaqueCompositeLayer:
- setupLayerForOpaqueCompositeLayer();
- break;
- case TextComposite:
- setupLayerForTextComposite();
- break;
- case WhiteLayer:
- setupLayerForWhiteLayer();
- break;
- }
-}
-
-void TransparencyWin::setupLayerForNoLayer()
-{
- m_drawContext = m_destContext; // Draw to the source context.
- m_validLayer = true;
-}
-
-void TransparencyWin::setupLayerForOpaqueCompositeLayer()
-{
- initializeNewContext();
- if (!m_validLayer)
- return;
-
- AffineTransform mapping;
- mapping.translate(-m_transformedSourceRect.x(), -m_transformedSourceRect.y());
- if (m_transformMode == Untransform) {
- // Compute the inverse mapping from the canvas space to the
- // coordinate space of our bitmap.
- mapping *= m_orgTransform.inverse();
- }
- compositeToCopy(*m_destContext, *m_drawContext, mapping);
-
- // Save the reference layer so we can tell what changed.
- SkCanvas referenceCanvas(*m_referenceBitmap);
- referenceCanvas.drawBitmap(bitmapForContext(*m_drawContext), 0, 0);
- // Layer rect represents the part of the original layer.
-}
-
-void TransparencyWin::setupLayerForTextComposite()
-{
- ASSERT(m_transformMode == KeepTransform);
- // Fall through to filling with white.
- setupLayerForWhiteLayer();
-}
-
-void TransparencyWin::setupLayerForWhiteLayer()
-{
- initializeNewContext();
- if (!m_validLayer)
- return;
-
- m_drawContext->fillRect(IntRect(IntPoint(0, 0), m_layerSize), Color::white);
- // Layer rect represents the part of the original layer.
-}
-
-void TransparencyWin::setupTransform(const IntRect& region)
-{
- switch (m_transformMode) {
- case KeepTransform:
- setupTransformForKeepTransform(region);
- break;
- case Untransform:
- setupTransformForUntransform();
- break;
- case ScaleTransform:
- setupTransformForScaleTransform();
- break;
- }
-}
-
-void TransparencyWin::setupTransformForKeepTransform(const IntRect& region)
-{
- if (!m_validLayer)
- return;
-
- if (m_layerMode != NoLayer) {
- // Need to save things since we're modifying the transform.
- m_drawContext->save();
- m_savedOnDrawContext = true;
-
- // Account for the fact that the layer may be offset from the
- // original. This only happens when we create a layer that has the
- // same coordinate space as the parent.
- AffineTransform xform;
- xform.translate(-m_transformedSourceRect.x(), -m_transformedSourceRect.y());
-
- // We're making a layer, so apply the old transform to the new one
- // so it's maintained. We know the new layer has the identity
- // transform now, we we can just multiply it.
- xform *= m_orgTransform;
- m_drawContext->concatCTM(xform);
- }
- m_drawRect = m_sourceRect;
-}
-
-void TransparencyWin::setupTransformForUntransform()
-{
- ASSERT(m_layerMode != NoLayer);
- // We now have a new layer with the identity transform, which is the
- // Untransformed space we'll use for drawing.
- m_drawRect = IntRect(IntPoint(0, 0), m_layerSize);
-}
-
-void TransparencyWin::setupTransformForScaleTransform()
-{
- if (!m_validLayer)
- return;
-
- if (m_layerMode == NoLayer) {
- // Need to save things since we're modifying the layer.
- m_drawContext->save();
- m_savedOnDrawContext = true;
-
- // Undo the transform on the current layer when we're re-using the
- // current one.
- m_drawContext->concatCTM(m_drawContext->getCTM().inverse());
-
- // We're drawing to the original layer with just a different size.
- m_drawRect = m_transformedSourceRect;
- } else {
- // Just go ahead and use the layer's coordinate space to draw into.
- // It will have the scaled size, and an identity transform loaded.
- m_drawRect = IntRect(IntPoint(0, 0), m_layerSize);
- }
-}
-
-void TransparencyWin::setTextCompositeColor(Color color)
-{
- m_textCompositeColor = color;
-}
-
-void TransparencyWin::initializeNewContext()
-{
- int pixelSize = m_layerSize.width() * m_layerSize.height();
- if (pixelSize <= 0)
- return;
-
- if (pixelSize > maxCachedBufferPixelSize) {
- // Create a 1-off buffer for drawing into. We only need the reference
- // buffer if we're making an OpaqueCompositeLayer.
- bool needReferenceBitmap = m_layerMode == OpaqueCompositeLayer;
- m_ownedBuffers = adoptPtr(new OwnedBuffers(m_layerSize, needReferenceBitmap));
- m_layerBuffer = m_ownedBuffers->destBitmap();
- if (!m_layerBuffer)
- return;
-
- m_drawContext = m_layerBuffer->context();
- if (needReferenceBitmap) {
- m_referenceBitmap = m_ownedBuffers->referenceBitmap();
- if (!m_referenceBitmap || !m_referenceBitmap->getPixels())
- return;
- }
- m_validLayer = true;
- return;
- }
-
- if (m_cachedBuffers && m_cachedBuffers->canHandleSize(m_layerSize)) {
- // We can re-use the existing buffer. We don't need to clear it since
- // all layer modes will clear it in their initialization.
- m_layerBuffer = m_cachedBuffers->destBitmap();
- m_drawContext = m_cachedBuffers->destBitmap()->context();
- bitmapForContext(*m_drawContext).eraseARGB(0, 0, 0, 0);
- m_referenceBitmap = m_cachedBuffers->referenceBitmap();
- m_referenceBitmap->eraseARGB(0, 0, 0, 0);
- m_validLayer = true;
- return;
- }
-
- // Create a new cached buffer.
- if (m_cachedBuffers)
- delete m_cachedBuffers;
- m_cachedBuffers = new OwnedBuffers(m_layerSize, true);
-
- m_layerBuffer = m_cachedBuffers->destBitmap();
- m_drawContext = m_cachedBuffers->destBitmap()->context();
- m_referenceBitmap = m_cachedBuffers->referenceBitmap();
- m_validLayer = true;
-}
-
-void TransparencyWin::compositeOpaqueComposite()
-{
- if (!m_validLayer)
- return;
-
- m_destContext->save();
-
- SkBitmap* bitmap = const_cast<SkBitmap*>(
- &bitmapForContext(*m_layerBuffer->context()));
-
- // This function will be called for WhiteLayer as well, which we don't want
- // to change.
- if (m_layerMode == OpaqueCompositeLayer) {
- // Fix up our bitmap, making it contain only the pixels which changed
- // and transparent everywhere else.
- SkAutoLockPixels sourceLock(*m_referenceBitmap);
- SkAutoLockPixels lock(*bitmap);
- for (int y = 0; y < bitmap->height(); y++) {
- uint32_t* source = m_referenceBitmap->getAddr32(0, y);
- uint32_t* dest = bitmap->getAddr32(0, y);
- for (int x = 0; x < bitmap->width(); x++) {
- // Clear out any pixels that were untouched.
- if (dest[x] == source[x])
- dest[x] = 0;
- else
- dest[x] |= (0xFF << SK_A32_SHIFT);
- }
- }
- } else {
- makeLayerOpaque();
- }
-
- SkRect destRect;
- if (m_transformMode != Untransform) {
- // We want to use Untransformed space.
- //
- // Note that we DON'T call m_layerBuffer->image() here. This actually
- // makes a copy of the image, which is unnecessary and slow. Instead, we
- // just draw the image from inside the destination context.
- SkMatrix identity;
- identity.reset();
- m_destContext->setMatrix(identity);
-
- destRect.set(m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.maxX(), m_transformedSourceRect.maxY());
- } else {
- destRect.set(m_sourceRect.x(), m_sourceRect.y(), m_sourceRect.maxX(), m_sourceRect.maxY());
- }
-
- SkPaint paint;
- paint.setFilterBitmap(true);
- paint.setAntiAlias(true);
-
- // Note that we need to specify the source layer subset, since the bitmap
- // may have been cached and it could be larger than what we're using.
- SkRect sourceRect = SkRect::MakeWH(
- SkIntToScalar(m_layerSize.width()),
- SkIntToScalar(m_layerSize.height()));
- m_destContext->drawBitmapRect(*bitmap, &sourceRect, destRect, &paint);
- m_destContext->restore();
-}
-
-void TransparencyWin::compositeTextComposite()
-{
- if (!m_validLayer)
- return;
-
- const SkBitmap& bitmap = m_layerBuffer->context()->layerBitmap(GraphicsContext::ReadWrite);
- SkColor textColor = m_textCompositeColor.rgb();
- for (int y = 0; y < m_layerSize.height(); y++) {
- uint32_t* row = bitmap.getAddr32(0, y);
- for (int x = 0; x < m_layerSize.width(); x++) {
- // The alpha is the average of the R, G, and B channels.
- int alpha = (SkGetPackedR32(row[x]) + SkGetPackedG32(row[x]) + SkGetPackedB32(row[x])) / 3;
-
- // Apply that alpha to the text color and write the result.
- row[x] = SkAlphaMulQ(textColor, SkAlpha255To256(255 - alpha));
- }
- }
-
- // Now the layer has text with the proper color and opacity.
- m_destContext->save();
-
- // We want to use Untransformed space (see above)
- SkMatrix identity;
- identity.reset();
- m_destContext->setMatrix(identity);
- SkRect destRect = { m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.maxX(), m_transformedSourceRect.maxY() };
-
- // Note that we need to specify the source layer subset, since the bitmap
- // may have been cached and it could be larger than what we're using.
- SkRect sourceRect = SkRect::MakeWH(
- SkIntToScalar(m_layerSize.width()),
- SkIntToScalar(m_layerSize.height()));
- m_destContext->drawBitmapRect(bitmap, &sourceRect, destRect, 0);
- m_destContext->restore();
-}
-
-void TransparencyWin::makeLayerOpaque()
-{
- if (!m_validLayer)
- return;
-
- SkBitmap& bitmap = const_cast<SkBitmap&>(m_drawContext->layerBitmap(GraphicsContext::ReadWrite));
- for (int y = 0; y < m_layerSize.height(); y++) {
- uint32_t* row = bitmap.getAddr32(0, y);
- for (int x = 0; x < m_layerSize.width(); x++)
- row[x] |= 0xFF000000;
- }
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/win/TransparencyWin.h b/chromium/third_party/WebKit/Source/platform/graphics/win/TransparencyWin.h
deleted file mode 100644
index 66f4cbd8606..00000000000
--- a/chromium/third_party/WebKit/Source/platform/graphics/win/TransparencyWin.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2009 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 TransparencyWin_h
-#define TransparencyWin_h
-
-#include "platform/graphics/ImageBuffer.h"
-#include "platform/transforms/AffineTransform.h"
-#include "wtf/Noncopyable.h"
-#include "wtf/OwnPtr.h"
-#include <windows.h>
-
-class SkBitmap;
-class SkCanvas;
-
-namespace WebCore {
-
-class GraphicsContext;
-class TransparencyWin_NoLayer_Test;
-class TransparencyWin_WhiteLayer_Test;
-class TransparencyWin_TextComposite_Test;
-class TransparencyWin_OpaqueCompositeLayer_Test;
-
-// Helper class that abstracts away drawing ClearType text and Windows form
-// controls either to the original context directly, or to an offscreen context
-// that is composited later manually. This is to get around Windows' inability
-// to handle the alpha channel, semitransparent text, and transformed form
-// controls.
-class PLATFORM_EXPORT TransparencyWin {
- WTF_MAKE_NONCOPYABLE(TransparencyWin);
-public:
- enum LayerMode {
- // No extra layer is created. Drawing will happen to the source.
- // Valid only with KeepTransform and ScaleTransform. The region being
- // drawn onto must be opaque, since the modified region will be forced
- // to opaque when drawing is complete.
- NoLayer,
-
- // Makes a temporary layer consisting of the composited layers below
- // it. This result must be opaque. When complete, the result will be
- // compared to the original, and the difference will be added to a thee
- // destination layer.
- //
- // This mode only works if the lower layers are opque (normally the
- // case for a web page) and layers are only drawn in the stack order,
- // meaning you can never draw underneath a layer.
- //
- // This doesn't technically produce the correct answer in all cases. If
- // you have an opaque base, a transparency layer, than a semitransparent
- // drawing on top, the result will actually be blended in twice. But
- // this isn't a very important case. This mode is used for form
- // controls which are always opaque except for occationally some
- // antialiasing. It means form control antialiasing will be too light in
- // some cases, but only if you have extra layers.
- OpaqueCompositeLayer,
-
- // Allows semitransparent text to be drawn on any background (even if it
- // is itself semitransparent), but disables ClearType.
- //
- // It makes a trmporary layer filled with white. This is composited with
- // the lower layer with a custom color applied to produce the result.
- // The caller must draw the text in black, and set the desired final
- // text color by calling setTextCompositeColor().
- //
- // Only valid with KeepTransform, which is the only mode where drawing
- // text in this fashion makes sense.
- TextComposite,
-
- // Makes a temporary layer filled with white. When complete, the layer
- // will be forced to be opqaue (since Windows may have messed up the
- // alpha channel) and composited down. Any areas not drawn into will
- // remain white.
- //
- // This is the mode of last resort. If the opacity of the final image
- // is unknown and we can't do the text trick (since we know its color),
- // then we have to live with potential white halos. This is used for
- // form control drawing, for example.
- WhiteLayer,
- };
-
- enum TransformMode {
- // There are no changes to the transform. Use this when drawing
- // horizontal text. The current transform must not have rotation.
- KeepTransform,
-
- // Drawing happens in an Untransformed space, and then that bitmap is
- // transformed according to the current context when it is copied down.
- // Requires that a layer be created (layer mode is not NoLayer).
- Untransform,
-
- // When the current transform only has a scaling factor applied and
- // you're drawing form elements, use this parameter. This will unscale
- // the coordinate space, so the OS will just draw the form controls
- // larger or smaller depending on the destination size.
- ScaleTransform,
- };
-
- // You MUST call init() below.
- // |region| is expressed relative to the current transformation.
- TransparencyWin();
- ~TransparencyWin();
-
- // Initializes the members if you use the 0-argument constructor. Don't call
- // this if you use the multiple-argument constructor.
- void init(GraphicsContext*, LayerMode, TransformMode, const IntRect&);
-
- // Combines the source and destination bitmaps using the given mode.
- // Calling this function before the destructor runs is mandatory in most
- // cases, and harmless otherwise. The mandatory cases are:
- // (m_layerMode != NoLayer) || (m_transformMode == ScaleTransform)
- void composite();
-
- // Returns the context for drawing into, which may be the destination
- // context, or a temporary one.
- GraphicsContext* context() const { return m_drawContext; }
-
- // When the mode is TextComposite, this sets the color that the text will
- // get. See the enum above for more.
- void setTextCompositeColor(Color);
-
- // Returns the input bounds translated into the destination space. This is
- // not necessary for KeepTransform since the rectangle will be unchanged.
- const IntRect& drawRect() { return m_drawRect; }
-
-private:
- friend TransparencyWin_NoLayer_Test;
- friend TransparencyWin_WhiteLayer_Test;
- friend TransparencyWin_TextComposite_Test;
- friend TransparencyWin_OpaqueCompositeLayer_Test;
-
- class OwnedBuffers;
-
- void computeLayerSize();
-
- // Sets up a new layer, if any. setupLayer() will call the appopriate layer-
- // specific helper. Must be called after computeLayerSize();
- void setupLayer();
- void setupLayerForNoLayer();
- void setupLayerForOpaqueCompositeLayer();
- void setupLayerForTextComposite();
- void setupLayerForWhiteLayer();
-
- // Sets up the transformation on the newly created layer. setupTransform()
- // will call the appropriate transform-specific helper. Must be called after
- // setupLayer().
- void setupTransform(const IntRect& region);
- void setupTransformForKeepTransform(const IntRect& region);
- void setupTransformForUntransform();
- void setupTransformForScaleTransform();
-
- void initializeNewContext();
-
- void compositeOpaqueComposite();
- void compositeTextComposite();
-
- // Fixes the alpha channel to make the region inside m_transformedRect
- // opaque.
- void makeLayerOpaque();
-
- // The context our drawing will eventually end up in.
- GraphicsContext* m_destContext;
-
- // The original transform from the destination context.
- AffineTransform m_orgTransform;
-
- LayerMode m_layerMode;
- TransformMode m_transformMode;
-
- // The rectangle we're drawing in the destination's coordinate space
- IntRect m_sourceRect;
-
- // The source rectangle transformed into pixels in the final image. For
- // Untransform this has no meaning, since the destination might not be a
- // rectangle.
- IntRect m_transformedSourceRect;
-
- // The size of the layer we created. If there's no layer, this is the size
- // of the region we're using in the source.
- IntSize m_layerSize;
-
- // The rectangle we're drawing to in the draw context's coordinate space.
- // This will be the same as the source rectangle except for ScaleTransform
- // where we create a new virtual coordinate space for the layer.
- IntRect m_drawRect;
-
- // Points to the graphics context to draw text to, which will either be
- // the original context or the copy, depending on our mode.
- GraphicsContext* m_drawContext;
-
- // This flag is set when we call save() on the draw context during
- // initialization. It allows us to avoid doing an extra save()/restore()
- // when one is unnecessary.
- bool m_savedOnDrawContext;
-
- // Used only when m_mode = TextComposite, this is the color that the text
- // will end up being once we figure out the transparency.
- Color m_textCompositeColor;
-
- // Layer we're drawing to.
- ImageBuffer* m_layerBuffer;
-
- // When the layer type is OpaqueCompositeLayer, this will contain a copy
- // of the original contents of the m_layerBuffer before Windows drew on it.
- // It allows us to re-create what Windows did to the layer. It is an
- // SkBitmap instead of an ImageBuffer because an SkBitmap is lighter-weight
- // (ImageBuffers are also GDI surfaces, which we don't need here).
- SkBitmap* m_referenceBitmap;
-
- // If the given size of bitmap can be cached, they will be stored here. Both
- // the bitmap and the reference are guaranteed to be allocated if this
- // member is non-null.
- static OwnedBuffers* m_cachedBuffers;
-
- // If a buffer was too big to be cached, it will be created temporarily, and
- // this member tracks its scope to make sure it gets deleted. Always use
- // m_layerBuffer, which will either point to this object, or the statically
- // cached one. Don't access directly.
- OwnPtr<OwnedBuffers> m_ownedBuffers;
-
- // Sometimes we're asked to create layers that have negative dimensions.
- // This API is not designed to fail to initialize, so we hide the fact
- // that they are illegal and can't be rendered (failing silently, drawing
- // nothing).
- bool m_validLayer;
-};
-
-} // namespace WebCore
-
-#endif // TransaprencyWin_h