summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics')
-rw-r--r--Source/WebCore/platform/graphics/ANGLEWebKitBridge.h8
-rw-r--r--Source/WebCore/platform/graphics/BitmapImage.cpp1
-rw-r--r--Source/WebCore/platform/graphics/BitmapImage.h20
-rw-r--r--Source/WebCore/platform/graphics/Color.h6
-rw-r--r--Source/WebCore/platform/graphics/ContextShadow.h8
-rw-r--r--Source/WebCore/platform/graphics/DashArray.h4
-rw-r--r--Source/WebCore/platform/graphics/Extensions3D.h5
-rw-r--r--Source/WebCore/platform/graphics/FloatPoint.cpp40
-rw-r--r--Source/WebCore/platform/graphics/FloatPoint.h9
-rw-r--r--Source/WebCore/platform/graphics/FloatRect.cpp21
-rw-r--r--Source/WebCore/platform/graphics/FloatRect.h9
-rw-r--r--Source/WebCore/platform/graphics/FloatSize.h9
-rw-r--r--Source/WebCore/platform/graphics/Font.h3
-rw-r--r--Source/WebCore/platform/graphics/FontCache.cpp17
-rw-r--r--Source/WebCore/platform/graphics/FontMetrics.h5
-rw-r--r--Source/WebCore/platform/graphics/FontPlatformData.h42
-rw-r--r--Source/WebCore/platform/graphics/FontSelector.h11
-rw-r--r--Source/WebCore/platform/graphics/GlyphBuffer.h20
-rw-r--r--Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp3
-rw-r--r--Source/WebCore/platform/graphics/Gradient.cpp4
-rw-r--r--Source/WebCore/platform/graphics/Gradient.h6
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext.cpp32
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext.h45
-rw-r--r--Source/WebCore/platform/graphics/GraphicsContext3D.h37
-rw-r--r--Source/WebCore/platform/graphics/Image.cpp2
-rw-r--r--Source/WebCore/platform/graphics/Image.h5
-rw-r--r--Source/WebCore/platform/graphics/ImageBuffer.cpp4
-rw-r--r--Source/WebCore/platform/graphics/ImageBuffer.h11
-rw-r--r--Source/WebCore/platform/graphics/ImageBufferData.h40
-rw-r--r--Source/WebCore/platform/graphics/ImageSource.h8
-rw-r--r--Source/WebCore/platform/graphics/IntPoint.h4
-rw-r--r--Source/WebCore/platform/graphics/IntRect.cpp21
-rw-r--r--Source/WebCore/platform/graphics/IntRect.h12
-rw-r--r--Source/WebCore/platform/graphics/IntSize.h4
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.cpp13
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.h5
-rw-r--r--Source/WebCore/platform/graphics/Path.cpp5
-rw-r--r--Source/WebCore/platform/graphics/Path.h6
-rw-r--r--Source/WebCore/platform/graphics/Pattern.h4
-rw-r--r--Source/WebCore/platform/graphics/RoundedIntRect.cpp26
-rw-r--r--Source/WebCore/platform/graphics/RoundedIntRect.h13
-rw-r--r--Source/WebCore/platform/graphics/ShadowBlur.cpp265
-rw-r--r--Source/WebCore/platform/graphics/ShadowBlur.h4
-rw-r--r--Source/WebCore/platform/graphics/SimpleFontData.h6
-rw-r--r--Source/WebCore/platform/graphics/WOFFFileFormat.cpp4
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp58
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h26
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h5
-rw-r--r--Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm58
-rw-r--r--Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp14
-rw-r--r--Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h5
-rw-r--r--Source/WebCore/platform/graphics/ca/TransformationMatrixCA.cpp4
-rw-r--r--Source/WebCore/platform/graphics/ca/win/AbstractCACFLayerTreeHost.h52
-rw-r--r--Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h20
-rw-r--r--Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp14
-rw-r--r--Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.h8
-rw-r--r--Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp16
-rw-r--r--Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.cpp17
-rw-r--r--Source/WebCore/platform/graphics/cairo/CairoPath.h50
-rw-r--r--Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp2
-rw-r--r--Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp17
-rw-r--r--Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h2
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp120
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp53
-rw-r--r--Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h24
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp11
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h (renamed from Source/WebCore/platform/graphics/cairo/ImageBufferData.h)7
-rw-r--r--Source/WebCore/platform/graphics/cairo/ImageCairo.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cairo/OpenGLShims.cpp191
-rw-r--r--Source/WebCore/platform/graphics/cairo/OpenGLShims.h315
-rw-r--r--Source/WebCore/platform/graphics/cairo/PathCairo.cpp2
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp47
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h25
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformPathCairo.cpp39
-rw-r--r--Source/WebCore/platform/graphics/cairo/PlatformPathCairo.h43
-rw-r--r--Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp2
-rw-r--r--Source/WebCore/platform/graphics/cg/ColorCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/FloatPointCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/FloatRectCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/FloatSizeCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp14
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp32
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp199
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp387
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h (renamed from Source/WebCore/platform/graphics/cg/ImageBufferData.h)16
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageCG.cpp24
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/IntPointCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/IntRectCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/IntSizeCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/PDFDocumentImage.h4
-rw-r--r--Source/WebCore/platform/graphics/cg/PathCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp4
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp23
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp317
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h38
-rw-r--r--Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp25
-rw-r--r--Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h7
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp60
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp19
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h2
-rw-r--r--Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp154
-rw-r--r--Source/WebCore/platform/graphics/chromium/GLES2Canvas.h5
-rw-r--r--Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h (renamed from Source/WebCore/platform/graphics/chromium/ImageBufferData.h)9
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp62
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h11
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.cpp3
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.h10
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp287
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h47
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp84
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h24
-rw-r--r--Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp18
-rw-r--r--Source/WebCore/platform/graphics/chromium/PlatformCanvas.h14
-rw-r--r--Source/WebCore/platform/graphics/chromium/PlatformImage.cpp6
-rw-r--r--Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp8
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp114
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelper.h14
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp5
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp2
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp30
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h5
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp3
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h3
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCCompletionEvent.h62
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp142
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h13
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp7
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h4
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCMainThread.cpp46
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCMainThread.h53
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCMainThreadTask.h220
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp3
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h3
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCThread.cpp79
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCThread.h75
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCThreadTask.h279
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp3
-rw-r--r--Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h3
-rw-r--r--Source/WebCore/platform/graphics/filters/FEFlood.cpp10
-rw-r--r--Source/WebCore/platform/graphics/filters/FEFlood.h4
-rw-r--r--Source/WebCore/platform/graphics/filters/FELighting.cpp123
-rw-r--r--Source/WebCore/platform/graphics/filters/FELighting.h5
-rw-r--r--Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp5
-rw-r--r--Source/WebCore/platform/graphics/filters/FESpecularLighting.h2
-rw-r--r--Source/WebCore/platform/graphics/filters/arm/FELightingNEON.cpp464
-rw-r--r--Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h96
-rw-r--r--Source/WebCore/platform/graphics/gpu/BicubicShader.cpp9
-rw-r--r--Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp9
-rw-r--r--Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp188
-rw-r--r--Source/WebCore/platform/graphics/gpu/DrawingBuffer.h7
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp102
-rw-r--r--Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.h3
-rw-r--r--Source/WebCore/platform/graphics/gpu/Shader.cpp6
-rw-r--r--Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp8
-rw-r--r--Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp2
-rw-r--r--Source/WebCore/platform/graphics/gpu/TexShader.cpp2
-rw-r--r--Source/WebCore/platform/graphics/gpu/TilingData.cpp3
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h4
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp493
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h51
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowPrivate.h20
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowQt.cpp59
-rw-r--r--Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp2
-rw-r--r--Source/WebCore/platform/graphics/gtk/DrawingBufferGtk.cpp93
-rw-r--r--Source/WebCore/platform/graphics/gtk/FontGtk.cpp103
-rw-r--r--Source/WebCore/platform/graphics/gtk/GraphicsContext3DGtk.cpp158
-rw-r--r--Source/WebCore/platform/graphics/gtk/GraphicsContext3DInternal.cpp254
-rw-r--r--Source/WebCore/platform/graphics/gtk/GraphicsContext3DInternal.h58
-rw-r--r--Source/WebCore/platform/graphics/haiku/ImageBufferDataHaiku.h (renamed from Source/WebCore/platform/graphics/haiku/ImageBufferData.h)6
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextController.h7
-rw-r--r--Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp19
-rw-r--r--Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm2
-rw-r--r--Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm2
-rw-r--r--Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp21
-rw-r--r--Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h1
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp10
-rw-r--r--Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp4
-rw-r--r--Source/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp2
-rw-r--r--Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp2
-rw-r--r--Source/WebCore/platform/graphics/pango/FontPlatformData.h1
-rw-r--r--Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp5
-rw-r--r--Source/WebCore/platform/graphics/qt/Extensions3DQt.h1
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp10
-rw-r--r--Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp2
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h (renamed from Source/WebCore/platform/graphics/qt/ImageBufferData.h)12
-rw-r--r--Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp12
-rw-r--r--Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp28
-rw-r--r--Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp17
-rw-r--r--Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp41
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp14
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageSkia.cpp17
-rw-r--r--Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp25
-rw-r--r--Source/WebCore/platform/graphics/skia/PlatformContextSkia.h29
-rw-r--r--Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp117
-rw-r--r--Source/WebCore/platform/graphics/skia/SkiaFontWin.h4
-rw-r--r--Source/WebCore/platform/graphics/transforms/AffineTransform.h8
-rw-r--r--Source/WebCore/platform/graphics/transforms/TransformationMatrix.h12
-rw-r--r--Source/WebCore/platform/graphics/win/DIBPixelData.cpp87
-rw-r--r--Source/WebCore/platform/graphics/win/DIBPixelData.h72
-rw-r--r--Source/WebCore/platform/graphics/win/FontCacheWin.cpp10
-rw-r--r--Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp4
-rw-r--r--Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp28
-rw-r--r--Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp71
-rw-r--r--Source/WebCore/platform/graphics/win/GraphicsContextWin.cpp17
-rw-r--r--Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp2
-rw-r--r--Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wince/ImageBufferDataWince.h (renamed from Source/WebCore/platform/graphics/wince/ImageBufferData.h)5
-rw-r--r--Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp4
-rw-r--r--Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp2
-rw-r--r--Source/WebCore/platform/graphics/wx/ImageBufferDataWx.h (renamed from Source/WebCore/platform/graphics/wx/ImageBufferData.h)8
218 files changed, 6301 insertions, 1998 deletions
diff --git a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h
index 7bddbf4..a9d2238 100644
--- a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h
+++ b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h
@@ -26,11 +26,15 @@
#ifndef ANGLEWebKitBridge_h
#define ANGLEWebKitBridge_h
-#include "ANGLE/ShaderLang.h"
#include "PlatformString.h"
-
#include <wtf/text/CString.h>
+#if !PLATFORM(GTK)
+#include "ANGLE/ShaderLang.h"
+#else
+#include "ShaderLang.h"
+#endif
+
namespace WebCore {
enum ANGLEShaderType {
diff --git a/Source/WebCore/platform/graphics/BitmapImage.cpp b/Source/WebCore/platform/graphics/BitmapImage.cpp
index 6027f34..7cdb43d 100644
--- a/Source/WebCore/platform/graphics/BitmapImage.cpp
+++ b/Source/WebCore/platform/graphics/BitmapImage.cpp
@@ -103,6 +103,7 @@ void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll)
void BitmapImage::destroyMetadataAndNotify(int framesCleared)
{
m_isSolidColor = false;
+ m_checkedForSolidColor = false;
invalidatePlatformData();
int deltaBytes = framesCleared * -frameBytes(m_size);
diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h
index c8cf0ab..8d9cd94 100644
--- a/Source/WebCore/platform/graphics/BitmapImage.h
+++ b/Source/WebCore/platform/graphics/BitmapImage.h
@@ -53,11 +53,11 @@ namespace WebCore {
struct FrameData;
}
-// This complicated-looking declaration tells the FrameData Vector that it should copy without
-// invoking our constructor or destructor. This allows us to have a vector even for a struct
-// that's not copyable.
namespace WTF {
- template<> struct VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits {};
+ // FIXME: This declaration gives FrameData a default constructor that zeroes
+ // all its data members, even though FrameData's default constructor defined
+ // below does not zero all its data members. One of these must be wrong!
+ template<> struct VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits { };
}
namespace WebCore {
@@ -139,8 +139,9 @@ public:
virtual CFDataRef getTIFFRepresentation();
#endif
-#if PLATFORM(CG)
+#if USE(CG)
virtual CGImageRef getCGImageRef();
+ virtual CGImageRef getFirstCGImageRefOfSize(const IntSize&);
#endif
#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS))
@@ -160,6 +161,14 @@ public:
#endif
virtual NativeImagePtr nativeImageForCurrentFrame() { return frameAtIndex(currentFrame()); }
+ bool frameHasAlphaAtIndex(size_t);
+
+#if !ASSERT_DISABLED
+ bool notSolidColor()
+ {
+ return size().width() != 1 || size().height() != 1 || frameCount() > 1;
+ }
+#endif
protected:
enum RepetitionCountStatus {
@@ -190,7 +199,6 @@ protected:
NativeImagePtr frameAtIndex(size_t);
bool frameIsCompleteAtIndex(size_t);
float frameDurationAtIndex(size_t);
- bool frameHasAlphaAtIndex(size_t);
// Decodes and caches a frame. Never accessed except internally.
void cacheFrame(size_t index);
diff --git a/Source/WebCore/platform/graphics/Color.h b/Source/WebCore/platform/graphics/Color.h
index 05d9554..02ec005 100644
--- a/Source/WebCore/platform/graphics/Color.h
+++ b/Source/WebCore/platform/graphics/Color.h
@@ -30,7 +30,7 @@
#include <wtf/Forward.h>
#include <wtf/unicode/Unicode.h>
-#if PLATFORM(CG)
+#if USE(CG)
#include "ColorSpace.h"
typedef struct CGColor* CGColorRef;
#endif
@@ -143,7 +143,7 @@ public:
operator wxColour() const;
#endif
-#if PLATFORM(CG)
+#if USE(CG)
Color(CGColorRef);
#endif
@@ -191,7 +191,7 @@ inline bool operator!=(const Color& a, const Color& b)
Color colorFromPremultipliedARGB(unsigned);
unsigned premultipliedARGBFromColor(const Color&);
-#if PLATFORM(CG)
+#if USE(CG)
CGColorRef cachedCGColor(const Color&, ColorSpace);
#endif
diff --git a/Source/WebCore/platform/graphics/ContextShadow.h b/Source/WebCore/platform/graphics/ContextShadow.h
index 850d489..87acee0 100644
--- a/Source/WebCore/platform/graphics/ContextShadow.h
+++ b/Source/WebCore/platform/graphics/ContextShadow.h
@@ -34,7 +34,7 @@
#include "IntRect.h"
#include <wtf/RefCounted.h>
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
typedef struct _cairo cairo_t;
typedef struct _cairo_surface cairo_surface_t;
#elif PLATFORM(QT)
@@ -49,7 +49,7 @@ namespace WebCore {
class AffineTransform;
class GraphicsContext;
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
typedef cairo_surface_t* PlatformImage;
typedef cairo_t* PlatformContext;
#elif PLATFORM(QT)
@@ -116,7 +116,7 @@ public:
void setShadowsIgnoreTransforms(bool enable) { m_shadowsIgnoreTransforms = enable; }
bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; }
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius = IntSize(), const IntSize& topRightRadius = IntSize(), const IntSize& bottomLeftRadius = IntSize(), const IntSize& bottomRightRadius = IntSize());
#endif
#if PLATFORM(QT)
@@ -135,7 +135,7 @@ private:
void blurLayerImage(unsigned char*, const IntSize& imageSize, int stride);
IntRect calculateLayerBoundingRect(GraphicsContext*, const FloatRect& layerArea, const IntRect& clipRect);
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
void drawRectShadowWithoutTiling(GraphicsContext*, const IntRect& shadowRect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius, float alpha);
#endif
};
diff --git a/Source/WebCore/platform/graphics/DashArray.h b/Source/WebCore/platform/graphics/DashArray.h
index 46b84a4..0516584 100644
--- a/Source/WebCore/platform/graphics/DashArray.h
+++ b/Source/WebCore/platform/graphics/DashArray.h
@@ -28,9 +28,9 @@
#include <wtf/Vector.h>
-#if PLATFORM(CG)
+#if USE(CG)
typedef Vector<CGFloat> DashArray;
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
typedef Vector<double> DashArray;
#else
typedef Vector<float> DashArray;
diff --git a/Source/WebCore/platform/graphics/Extensions3D.h b/Source/WebCore/platform/graphics/Extensions3D.h
index 5d5a5b7..fee1133 100644
--- a/Source/WebCore/platform/graphics/Extensions3D.h
+++ b/Source/WebCore/platform/graphics/Extensions3D.h
@@ -66,6 +66,11 @@ public:
// extension names for which supports returns true.
virtual void ensureEnabled(const String&) = 0;
+ // 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.
+ virtual bool isEnabled(const String&) = 0;
+
enum ExtensionsEnumType {
// GL_EXT_texture_format_BGRA8888 enums
BGRA_EXT = 0x80E1,
diff --git a/Source/WebCore/platform/graphics/FloatPoint.cpp b/Source/WebCore/platform/graphics/FloatPoint.cpp
index 226ae71..abe9b86 100644
--- a/Source/WebCore/platform/graphics/FloatPoint.cpp
+++ b/Source/WebCore/platform/graphics/FloatPoint.cpp
@@ -31,6 +31,7 @@
#include "TransformationMatrix.h"
#include "FloatConversion.h"
#include "IntPoint.h"
+#include <limits>
#include <math.h>
namespace WebCore {
@@ -73,4 +74,43 @@ FloatPoint FloatPoint::narrowPrecision(double x, double y)
return FloatPoint(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y));
}
+float findSlope(const FloatPoint& p1, const FloatPoint& p2, float& c)
+{
+ if (p2.x() == p1.x())
+ return std::numeric_limits<float>::infinity();
+
+ // y = mx + c
+ float slope = (p2.y() - p1.y()) / (p2.x() - p1.x());
+ c = p1.y() - slope * p1.x();
+ return slope;
+}
+
+bool findIntersection(const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& d1, const FloatPoint& d2, FloatPoint& intersection)
+{
+ float pOffset = 0;
+ float pSlope = findSlope(p1, p2, pOffset);
+
+ float dOffset = 0;
+ float dSlope = findSlope(d1, d2, dOffset);
+
+ if (dSlope == pSlope)
+ return false;
+
+ if (pSlope == std::numeric_limits<float>::infinity()) {
+ intersection.setX(p1.x());
+ intersection.setY(dSlope * intersection.x() + dOffset);
+ return true;
+ }
+ if (dSlope == std::numeric_limits<float>::infinity()) {
+ intersection.setX(d1.x());
+ intersection.setY(pSlope * intersection.x() + pOffset);
+ return true;
+ }
+
+ // Find x at intersection, where ys overlap; x = (c' - c) / (m - m')
+ intersection.setX((dOffset - pOffset) / (pSlope - dSlope));
+ intersection.setY(pSlope * intersection.x() + pOffset);
+ return true;
+}
+
}
diff --git a/Source/WebCore/platform/graphics/FloatPoint.h b/Source/WebCore/platform/graphics/FloatPoint.h
index c4b2943..fd73c69 100644
--- a/Source/WebCore/platform/graphics/FloatPoint.h
+++ b/Source/WebCore/platform/graphics/FloatPoint.h
@@ -31,7 +31,7 @@
#include "IntPoint.h"
#include <wtf/MathExtras.h>
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
typedef struct CGPoint CGPoint;
#endif
@@ -109,7 +109,7 @@ public:
return m_x * m_x + m_y * m_y;
}
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
FloatPoint(const CGPoint&);
operator CGPoint() const;
#endif
@@ -202,6 +202,11 @@ inline IntPoint roundedIntPoint(const FloatPoint& p)
return IntPoint(static_cast<int>(roundf(p.x())), static_cast<int>(roundf(p.y())));
}
+float findSlope(const FloatPoint& p1, const FloatPoint& p2, float& c);
+
+// Find point where lines through the two pairs of points intersect. Returns false if the lines don't intersect.
+bool findIntersection(const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& d1, const FloatPoint& d2, FloatPoint& intersection);
+
}
#endif
diff --git a/Source/WebCore/platform/graphics/FloatRect.cpp b/Source/WebCore/platform/graphics/FloatRect.cpp
index 36f3d3a..165ef76 100644
--- a/Source/WebCore/platform/graphics/FloatRect.cpp
+++ b/Source/WebCore/platform/graphics/FloatRect.cpp
@@ -30,8 +30,8 @@
#include "FloatConversion.h"
#include "IntRect.h"
#include <algorithm>
-#include <limits>
#include <math.h>
+#include <wtf/MathExtras.h>
using std::max;
using std::min;
@@ -97,6 +97,24 @@ void FloatRect::unite(const FloatRect& other)
setLocationAndSizeFromEdges(l, t, r, b);
}
+void FloatRect::uniteIfNonZero(const FloatRect& other)
+{
+ // Handle empty special cases first.
+ if (!other.width() && !other.height())
+ return;
+ if (!width() && !height()) {
+ *this = other;
+ return;
+ }
+
+ float left = min(x(), other.x());
+ float top = min(y(), other.y());
+ float right = max(maxX(), other.maxX());
+ float bottom = max(maxY(), other.maxY());
+
+ setLocationAndSizeFromEdges(left, top, right, bottom);
+}
+
void FloatRect::scale(float sx, float sy)
{
m_location.setX(x() * sx);
@@ -182,6 +200,7 @@ IntRect enclosingIntRect(const FloatRect& rect)
float top = floorf(rect.y());
float width = ceilf(rect.maxX()) - left;
float height = ceilf(rect.maxY()) - top;
+
return IntRect(safeFloatToInt(left), safeFloatToInt(top),
safeFloatToInt(width), safeFloatToInt(height));
}
diff --git a/Source/WebCore/platform/graphics/FloatRect.h b/Source/WebCore/platform/graphics/FloatRect.h
index bd23476..493c068 100644
--- a/Source/WebCore/platform/graphics/FloatRect.h
+++ b/Source/WebCore/platform/graphics/FloatRect.h
@@ -29,7 +29,7 @@
#include "FloatPoint.h"
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
typedef struct CGRect CGRect;
#endif
@@ -59,7 +59,7 @@ class BRect;
struct SkRect;
#endif
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
typedef struct _cairo_rectangle cairo_rectangle_t;
#endif
@@ -112,6 +112,7 @@ public:
void intersect(const FloatRect&);
void unite(const FloatRect&);
+ void uniteIfNonZero(const FloatRect&);
// Note, this doesn't match what IntRect::contains(IntPoint&) does; the int version
// is really checking for containment of 1x1 rect, but that doesn't make sense with floats.
@@ -136,7 +137,7 @@ public:
void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2);
void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3);
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
FloatRect(const CGRect&);
operator CGRect() const;
#endif
@@ -172,7 +173,7 @@ public:
operator VGRect() const;
#endif
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
FloatRect(const cairo_rectangle_t&);
operator cairo_rectangle_t() const;
#endif
diff --git a/Source/WebCore/platform/graphics/FloatSize.h b/Source/WebCore/platform/graphics/FloatSize.h
index 160fc9a..1485c71 100644
--- a/Source/WebCore/platform/graphics/FloatSize.h
+++ b/Source/WebCore/platform/graphics/FloatSize.h
@@ -31,7 +31,7 @@
#include "IntSize.h"
#include <wtf/MathExtras.h>
-#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN))
+#if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
typedef struct CGSize CGSize;
#endif
@@ -89,7 +89,7 @@ public:
return m_width * m_width + m_height * m_height;
}
-#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN))
+#if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
explicit FloatSize(const CGSize&); // don't do this implicitly since it's lossy
operator CGSize() const;
#endif
@@ -148,6 +148,11 @@ inline IntSize roundedIntSize(const FloatSize& p)
return IntSize(static_cast<int>(roundf(p.width())), static_cast<int>(roundf(p.height())));
}
+inline IntSize expandedIntSize(const FloatSize& p)
+{
+ return IntSize(clampToInteger(ceilf(p.width())), clampToInteger(ceilf(p.height())));
+}
+
} // namespace WebCore
#endif // FloatSize_h
diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h
index 554f8a0..beafdc7 100644
--- a/Source/WebCore/platform/graphics/Font.h
+++ b/Source/WebCore/platform/graphics/Font.h
@@ -203,7 +203,8 @@ public:
FontSelector* fontSelector() const;
static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == noBreakSpace; }
- static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || (c >= 0x200c && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == objectReplacementCharacter; }
+ static bool treatAsZeroWidthSpace(UChar c) { return treatAsZeroWidthSpaceInComplexScript(c) || c == 0x200c || c == 0x200d; }
+ static bool treatAsZeroWidthSpaceInComplexScript(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || (c >= 0x200e && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == zeroWidthNoBreakSpace || c == objectReplacementCharacter; }
static bool canReceiveTextEmphasis(UChar32 c);
static inline UChar normalizeSpaces(UChar character)
diff --git a/Source/WebCore/platform/graphics/FontCache.cpp b/Source/WebCore/platform/graphics/FontCache.cpp
index 8c5edfe..d64878b 100644
--- a/Source/WebCore/platform/graphics/FontCache.cpp
+++ b/Source/WebCore/platform/graphics/FontCache.cpp
@@ -121,22 +121,7 @@ struct FontPlatformDataCacheKeyHash {
static const bool safeToCompareToEmptyOrDeleted = true;
};
-struct FontPlatformDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformDataCacheKey> {
- static const bool emptyValueIsZero = true;
- static const FontPlatformDataCacheKey& emptyValue()
- {
- DEFINE_STATIC_LOCAL(FontPlatformDataCacheKey, key, (nullAtom));
- return key;
- }
- static void constructDeletedValue(FontPlatformDataCacheKey& slot)
- {
- new (&slot) FontPlatformDataCacheKey(HashTableDeletedValue);
- }
- static bool isDeletedValue(const FontPlatformDataCacheKey& value)
- {
- return value.isHashTableDeletedValue();
- }
-};
+struct FontPlatformDataCacheKeyTraits : WTF::SimpleClassHashTraits<FontPlatformDataCacheKey> { };
typedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontPlatformDataCache;
diff --git a/Source/WebCore/platform/graphics/FontMetrics.h b/Source/WebCore/platform/graphics/FontMetrics.h
index 89c5545..367f004 100644
--- a/Source/WebCore/platform/graphics/FontMetrics.h
+++ b/Source/WebCore/platform/graphics/FontMetrics.h
@@ -96,6 +96,11 @@ public:
int lineGap() const { return lroundf(m_lineGap); }
int lineSpacing() const { return lroundf(m_lineSpacing); }
+ bool hasIdenticalAscentDescentAndLineGap(const FontMetrics& other) const
+ {
+ return ascent() == other.ascent() && descent() == other.descent() && lineGap() == other.lineGap();
+ }
+
private:
friend class SimpleFontData;
diff --git a/Source/WebCore/platform/graphics/FontPlatformData.h b/Source/WebCore/platform/graphics/FontPlatformData.h
index 5981c16..a32215d 100644
--- a/Source/WebCore/platform/graphics/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/FontPlatformData.h
@@ -51,7 +51,7 @@
#include "RefCountedGDIHandle.h"
#endif
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
#include "HashFunctions.h"
#include <cairo.h>
#endif
@@ -86,7 +86,7 @@ typedef const struct __CTFont* CTFontRef;
typedef struct HFONT__* HFONT;
#endif
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
typedef struct CGFont* CGFontRef;
#if OS(DARWIN)
#ifndef BUILDING_ON_TIGER
@@ -119,9 +119,9 @@ public:
#elif OS(DARWIN)
, m_font(hashTableDeletedFontValue())
#endif
-#if PLATFORM(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN))
+#if USE(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN))
, m_cgFont(0)
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
, m_scaledFont(hashTableDeletedFontValue())
#endif
, m_isColorBitmapFont(false)
@@ -141,9 +141,9 @@ public:
#if OS(DARWIN)
, m_font(0)
#endif
-#if PLATFORM(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN))
+#if USE(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN))
, m_cgFont(0)
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
, m_scaledFont(0)
#endif
, m_isColorBitmapFont(false)
@@ -166,9 +166,9 @@ public:
#if OS(DARWIN)
, m_font(0)
#endif
-#if PLATFORM(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN))
+#if USE(CG) && (defined(BUILDING_ON_TIGER) || PLATFORM(WIN))
, m_cgFont(0)
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
, m_scaledFont(0)
#endif
, m_isColorBitmapFont(false)
@@ -181,6 +181,7 @@ public:
#if OS(DARWIN)
FontPlatformData(NSFont*, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal,
TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth);
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
FontPlatformData(CGFontRef cgFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation,
TextOrientation textOrientation, FontWidthVariant widthVariant)
: m_syntheticBold(syntheticBold)
@@ -195,13 +196,14 @@ public:
{
}
#endif
+#endif
#if PLATFORM(WIN)
FontPlatformData(HFONT, float size, bool syntheticBold, bool syntheticOblique, bool useGDI);
-#if PLATFORM(CG)
+#if USE(CG)
FontPlatformData(HFONT, CGFontRef, float size, bool syntheticBold, bool syntheticOblique, bool useGDI);
#endif
#endif
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
FontPlatformData(cairo_font_face_t*, float size, bool bold, bool italic);
#endif
@@ -215,7 +217,7 @@ public:
void setFont(NSFont*);
#endif
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
#if OS(DARWIN)
#ifndef BUILDING_ON_TIGER
CGFontRef cgFont() const { return m_cgFont.get(); }
@@ -243,19 +245,21 @@ public:
void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
#endif
unsigned hash() const
{
-#if PLATFORM(WIN) && !PLATFORM(CAIRO)
+#if PLATFORM(WIN) && !USE(CAIRO)
return m_font ? m_font->hash() : 0;
#elif OS(DARWIN)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
ASSERT(m_font || !m_cgFont);
+#endif
uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, m_textOrientation << 3 | m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique };
return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
return PtrHash<cairo_scaled_font_t*>::hash(m_scaledFont);
#endif
}
@@ -276,11 +280,11 @@ public:
bool isHashTableDeletedValue() const
{
-#if PLATFORM(WIN) && !PLATFORM(CAIRO)
+#if PLATFORM(WIN) && !USE(CAIRO)
return m_font.isHashTableDeletedValue();
#elif OS(DARWIN)
return m_font == hashTableDeletedFontValue();
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
return m_scaledFont == hashTableDeletedFontValue();
#endif
}
@@ -307,7 +311,7 @@ private:
void platformDataInit(HFONT, float size, HDC, WCHAR* faceName);
#endif
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
static cairo_scaled_font_t* hashTableDeletedFontValue() { return reinterpret_cast<cairo_scaled_font_t*>(-1); }
#endif
@@ -326,7 +330,7 @@ private:
RefPtr<RefCountedGDIHandle<HFONT> > m_font;
#endif
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
#if PLATFORM(WIN)
RetainPtr<CGFontRef> m_cgFont;
#else
@@ -339,7 +343,7 @@ private:
#endif
#endif
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
cairo_scaled_font_t* m_scaledFont;
#endif
diff --git a/Source/WebCore/platform/graphics/FontSelector.h b/Source/WebCore/platform/graphics/FontSelector.h
index 156bf10..e18161b 100644
--- a/Source/WebCore/platform/graphics/FontSelector.h
+++ b/Source/WebCore/platform/graphics/FontSelector.h
@@ -33,6 +33,7 @@ namespace WebCore {
class FontData;
class FontDescription;
+class FontSelectorClient;
class FontSelector : public RefCounted<FontSelector> {
public:
@@ -40,6 +41,16 @@ public:
virtual FontData* getFontData(const FontDescription&, const AtomicString& familyName) = 0;
virtual void fontCacheInvalidated() { }
+
+ virtual void registerForInvalidationCallbacks(FontSelectorClient*) = 0;
+ virtual void unregisterForInvalidationCallbacks(FontSelectorClient*) = 0;
+};
+
+class FontSelectorClient {
+public:
+ virtual ~FontSelectorClient() { }
+
+ virtual void fontsNeedUpdate(FontSelector*) = 0;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/GlyphBuffer.h b/Source/WebCore/platform/graphics/GlyphBuffer.h
index 7aac1e3..f5216a9 100644
--- a/Source/WebCore/platform/graphics/GlyphBuffer.h
+++ b/Source/WebCore/platform/graphics/GlyphBuffer.h
@@ -34,11 +34,11 @@
#include <wtf/UnusedParam.h>
#include <wtf/Vector.h>
-#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN))
+#if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
#include <ApplicationServices/ApplicationServices.h>
#endif
-#if PLATFORM(CAIRO) || (PLATFORM(WX) && defined(__WXGTK__))
+#if USE(CAIRO) || (PLATFORM(WX) && defined(__WXGTK__))
#include <cairo.h>
#endif
@@ -47,7 +47,7 @@ namespace WebCore {
typedef unsigned short Glyph;
class SimpleFontData;
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
// FIXME: Why does Cairo use such a huge struct instead of just an offset into an array?
typedef cairo_glyph_t GlyphBufferGlyph;
#elif OS(WINCE)
@@ -58,7 +58,7 @@ typedef Glyph GlyphBufferGlyph;
// CG uses CGSize instead of FloatSize so that the result of advances()
// can be passed directly to CGContextShowGlyphsWithAdvances in FontMac.mm
-#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN))
+#if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
typedef CGSize GlyphBufferAdvance;
#elif OS(WINCE)
// There is no cross-platform code that uses the height of GlyphBufferAdvance,
@@ -113,7 +113,7 @@ public:
Glyph glyphAt(int index) const
{
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
return m_glyphs[index].index;
#else
return m_glyphs[index];
@@ -122,7 +122,7 @@ public:
float advanceAt(int index) const
{
-#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN))
+#if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
return m_advances[index].width;
#elif OS(WINCE)
return m_advances[index];
@@ -145,7 +145,7 @@ public:
{
m_fontData.append(font);
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
cairo_glyph_t cairoGlyph;
cairoGlyph.index = glyph;
m_glyphs.append(cairoGlyph);
@@ -153,7 +153,7 @@ public:
m_glyphs.append(glyph);
#endif
-#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN))
+#if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
CGSize advance = { width, 0 };
m_advances.append(advance);
#elif OS(WINCE)
@@ -176,7 +176,7 @@ public:
void add(Glyph glyph, const SimpleFontData* font, GlyphBufferAdvance advance)
{
m_fontData.append(font);
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
cairo_glyph_t cairoGlyph;
cairoGlyph.index = glyph;
m_glyphs.append(cairoGlyph);
@@ -192,7 +192,7 @@ public:
{
ASSERT(!isEmpty());
GlyphBufferAdvance& lastAdvance = m_advances.last();
-#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN))
+#if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
lastAdvance.width += width;
#elif OS(WINCE)
lastAdvance += width;
diff --git a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
index e7ed193..951cf56 100644
--- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
+++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
@@ -191,6 +191,9 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu
} else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) {
// Object replacement character must not render at all.
buffer[objectReplacementCharacter - start] = zeroWidthSpace;
+ } else if (start == (zeroWidthNoBreakSpace & ~(GlyphPage::size - 1))) {
+ // ZWNBS/BOM must not render at all.
+ buffer[zeroWidthNoBreakSpace - start] = zeroWidthSpace;
}
} else {
bufferLength = GlyphPage::size * 2;
diff --git a/Source/WebCore/platform/graphics/Gradient.cpp b/Source/WebCore/platform/graphics/Gradient.cpp
index 783e552..4edb4bd 100644
--- a/Source/WebCore/platform/graphics/Gradient.cpp
+++ b/Source/WebCore/platform/graphics/Gradient.cpp
@@ -221,7 +221,11 @@ void Gradient::setGradientSpaceTransform(const AffineTransform& gradientSpaceTra
setPlatformGradientSpaceTransform(gradientSpaceTransformation);
}
+<<<<<<< HEAD
#if !(USE(SKIA) && !PLATFORM(ANDROID)) && !PLATFORM(CAIRO)
+=======
+#if !USE(SKIA) && !USE(CAIRO)
+>>>>>>> WebKit.org at r84325
void Gradient::setPlatformGradientSpaceTransform(const AffineTransform&)
{
}
diff --git a/Source/WebCore/platform/graphics/Gradient.h b/Source/WebCore/platform/graphics/Gradient.h
index acc6125..7595896 100644
--- a/Source/WebCore/platform/graphics/Gradient.h
+++ b/Source/WebCore/platform/graphics/Gradient.h
@@ -35,7 +35,7 @@
#include <wtf/PassRefPtr.h>
#include <wtf/Vector.h>
-#if PLATFORM(CG)
+#if USE(CG)
typedef struct CGContext* CGContextRef;
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
class QGradient;
QT_END_NAMESPACE
typedef QGradient* PlatformGradient;
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
typedef struct _cairo_pattern cairo_pattern_t;
typedef cairo_pattern_t* PlatformGradient;
#elif USE(SKIA)
@@ -146,7 +146,7 @@ namespace WebCore {
void setPlatformGradientSpaceTransform(const AffineTransform& gradientSpaceTransformation);
-#if PLATFORM(CG)
+#if USE(CG)
void paint(CGContextRef);
void paint(GraphicsContext*);
#endif
diff --git a/Source/WebCore/platform/graphics/GraphicsContext.cpp b/Source/WebCore/platform/graphics/GraphicsContext.cpp
index fa3280e..ddaf938 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/Source/WebCore/platform/graphics/GraphicsContext.cpp
@@ -148,7 +148,7 @@ void GraphicsContext::setLegacyShadow(const FloatSize& offset, float blur, const
m_state.shadowBlur = blur;
m_state.shadowColor = color;
m_state.shadowColorSpace = colorSpace;
-#if PLATFORM(CG)
+#if USE(CG)
m_state.shadowsUseLegacyRadius = true;
#endif
setPlatformShadow(offset, blur, color, colorSpace);
@@ -397,7 +397,11 @@ void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const F
if (paintingDisabled())
return;
+ // FIXME: This ownership should be reversed. We should pass BidiRunList
+ // to BidiResolver in createBidiRunsForLine.
BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
+ BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
+
WTF::Unicode::Direction paragraphDirection = run.ltr() ? WTF::Unicode::LeftToRight : WTF::Unicode::RightToLeft;
bidiResolver.setStatus(BidiStatus(paragraphDirection, paragraphDirection, paragraphDirection, BidiContext::create(run.ltr() ? 0 : 1, paragraphDirection, run.directionalOverride())));
@@ -405,11 +409,11 @@ void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const F
bidiResolver.setPosition(TextRunIterator(&run, 0));
bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()));
- if (!bidiResolver.runCount())
+ if (!bidiRuns.runCount())
return;
FloatPoint currPoint = point;
- BidiCharacterRun* bidiRun = bidiResolver.firstRun();
+ BidiCharacterRun* bidiRun = bidiRuns.firstRun();
while (bidiRun) {
TextRun subrun = run;
@@ -425,7 +429,7 @@ void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const F
currPoint.move(font.width(subrun), 0);
}
- bidiResolver.deleteRuns();
+ bidiRuns.deleteRuns();
}
void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, ColorSpace colorSpace, int from, int to)
@@ -563,7 +567,7 @@ void GraphicsContext::addRoundedRectClip(const RoundedIntRect& rect)
return;
Path path;
- path.addRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight());
+ path.addRoundedRect(rect);
clip(path);
}
@@ -573,7 +577,7 @@ void GraphicsContext::clipOutRoundedRect(const RoundedIntRect& rect)
return;
Path path;
- path.addRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight());
+ path.addRoundedRect(rect);
clipOut(path);
}
@@ -584,7 +588,7 @@ void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& re
buffer->clip(this, rect);
}
-#if !PLATFORM(CG)
+#if !USE(CG)
IntRect GraphicsContext::clipBounds() const
{
ASSERT_NOT_REACHED();
@@ -617,7 +621,7 @@ void GraphicsContext::fillRoundedRect(const RoundedIntRect& rect, const Color& c
fillRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight(), color, colorSpace);
}
-#if !PLATFORM(CG)
+#if !USE(CG)
void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedIntRect& roundedHoleRect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
@@ -627,7 +631,7 @@ void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const Rounded
path.addRect(rect);
if (!roundedHoleRect.radii().isZero())
- path.addRoundedRect(roundedHoleRect.rect(), roundedHoleRect.radii().topLeft(), roundedHoleRect.radii().topRight(), roundedHoleRect.radii().bottomLeft(), roundedHoleRect.radii().bottomRight());
+ path.addRoundedRect(roundedHoleRect);
else
path.addRect(roundedHoleRect.rect());
@@ -674,7 +678,11 @@ void GraphicsContext::setPlatformStrokePattern(Pattern*)
}
#endif
+<<<<<<< HEAD
#if !PLATFORM(CG) && !(USE(SKIA) && !PLATFORM(ANDROID))
+=======
+#if !USE(CG) && !USE(SKIA)
+>>>>>>> WebKit.org at r84325
// Implement this if you want to go ahead and push the drawing mode into your native context
// immediately.
void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode)
@@ -682,13 +690,17 @@ void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode)
}
#endif
+<<<<<<< HEAD
#if !PLATFORM(QT) && !PLATFORM(CAIRO) && !(USE(SKIA) && !PLATFORM(ANDROID)) && !PLATFORM(HAIKU) && !PLATFORM(OPENVG)
+=======
+#if !PLATFORM(QT) && !USE(CAIRO) && !USE(SKIA) && !PLATFORM(HAIKU) && !PLATFORM(OPENVG)
+>>>>>>> WebKit.org at r84325
void GraphicsContext::setPlatformStrokeStyle(StrokeStyle)
{
}
#endif
-#if !PLATFORM(CG)
+#if !USE(CG)
void GraphicsContext::setPlatformShouldSmoothFonts(bool)
{
}
diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h
index c555a5f..2b41c2e 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext.h
@@ -37,9 +37,9 @@
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
-#if PLATFORM(CG)
+#if USE(CG)
typedef struct CGContext PlatformGraphicsContext;
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
namespace WebCore {
class ContextShadow;
class PlatformContextCairo;
@@ -99,8 +99,9 @@ typedef void PlatformGraphicsContext;
#endif
#if PLATFORM(WIN)
+#include "DIBPixelData.h"
typedef struct HDC__* HDC;
-#if !PLATFORM(CG)
+#if !USE(CG)
// UInt8 is defined in CoreFoundation/CFBase.h
typedef unsigned char UInt8;
#endif
@@ -161,7 +162,7 @@ namespace WebCore {
GraphicsContextState()
: strokeThickness(0)
, shadowBlur(0)
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
, globalAlpha(1)
#endif
, textDrawingMode(TextModeFill)
@@ -177,7 +178,7 @@ namespace WebCore {
, shouldSmoothFonts(true)
, paintingDisabled(false)
, shadowsIgnoreTransforms(false)
-#if PLATFORM(CG)
+#if USE(CG)
// Core Graphics incorrectly renders shadows with radius > 8px (<rdar://problem/8103442>),
// but we need to preserve this buggy behavior for canvas and -webkit-box-shadow.
, shadowsUseLegacyRadius(false)
@@ -196,7 +197,7 @@ namespace WebCore {
float strokeThickness;
float shadowBlur;
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
float globalAlpha;
#endif
TextDrawingModeFlags textDrawingMode;
@@ -218,7 +219,7 @@ namespace WebCore {
bool shouldSmoothFonts : 1;
bool paintingDisabled : 1;
bool shadowsIgnoreTransforms : 1;
-#if PLATFORM(CG)
+#if USE(CG)
bool shadowsUseLegacyRadius : 1;
#endif
};
@@ -270,7 +271,7 @@ namespace WebCore {
const GraphicsContextState& state() const;
-#if PLATFORM(CG)
+#if USE(CG)
void applyStrokePattern();
void applyFillPattern();
void drawPath(const Path&);
@@ -383,7 +384,11 @@ namespace WebCore {
void drawBidiText(const Font&, const TextRun&, const FloatPoint&);
void drawHighlightForText(const Font&, const TextRun&, const FloatPoint&, int h, const Color& backgroundColor, ColorSpace, int from = 0, int to = -1);
- FloatRect roundToDevicePixels(const FloatRect&);
+ enum RoundingMode {
+ RoundAllSides,
+ RoundOriginAndDimensions
+ };
+ FloatRect roundToDevicePixels(const FloatRect&, RoundingMode = RoundAllSides);
void drawLineForText(const FloatPoint&, float width, bool printing);
enum TextCheckingLineStyle {
@@ -420,7 +425,7 @@ namespace WebCore {
void setMiterLimit(float);
void setAlpha(float);
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
float getAlpha();
#endif
@@ -486,18 +491,17 @@ namespace WebCore {
~WindowsBitmap();
HDC hdc() const { return m_hdc; }
- UInt8* buffer() const { return m_bitmapBuffer; }
- unsigned bufferLength() const { return m_bitmapBufferLength; }
- IntSize size() const { return m_size; }
- unsigned bytesPerRow() const { return m_bytesPerRow; }
+ UInt8* buffer() const { return m_pixelData.buffer(); }
+ unsigned bufferLength() const { return m_pixelData.bufferLength(); }
+ const IntSize& size() const { return m_pixelData.size(); }
+ unsigned bytesPerRow() const { return m_pixelData.bytesPerRow(); }
+ unsigned short bitsPerPixel() const { return m_pixelData.bitsPerPixel(); }
+ const DIBPixelData& windowsDIB() const { return m_pixelData; }
private:
HDC m_hdc;
HBITMAP m_bitmap;
- UInt8* m_bitmapBuffer;
- unsigned m_bitmapBufferLength;
- IntSize m_size;
- unsigned m_bytesPerRow;
+ DIBPixelData m_pixelData;
};
WindowsBitmap* createWindowsBitmap(IntSize);
@@ -521,13 +525,12 @@ namespace WebCore {
void takeOwnershipOfPlatformContext();
#endif
-#if PLATFORM(QT) || PLATFORM(CAIRO)
+#if PLATFORM(QT) || USE(CAIRO)
ContextShadow* contextShadow();
#endif
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
GraphicsContext(cairo_t*);
- void pushImageMask(cairo_surface_t*, const FloatRect&);
#endif
#if PLATFORM(GTK)
diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h
index 351b445..80226cf 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h
@@ -43,8 +43,11 @@
#undef VERSION
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || PLATFORM(GTK)
#include "ANGLEWebKitBridge.h"
+#endif
+
+#if PLATFORM(MAC)
#include <OpenGL/OpenGL.h>
#include <wtf/RetainPtr.h>
#ifdef __OBJC__
@@ -73,7 +76,7 @@ typedef void* PlatformGraphicsContext3D;
const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0;
const Platform3DObject NullPlatform3DObject = 0;
-#if PLATFORM(CG)
+#if USE(CG)
#include <CoreGraphics/CGContext.h>
#endif
@@ -81,12 +84,15 @@ namespace WebCore {
class CanvasRenderingContext;
class DrawingBuffer;
class Extensions3D;
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || PLATFORM(GTK)
class Extensions3DOpenGL;
#endif
class HostWindow;
class Image;
class ImageData;
+#if USE(CAIRO)
+class PlatformContextCairo;
+#endif
struct ActiveInfo {
String name;
@@ -95,7 +101,7 @@ struct ActiveInfo {
};
// FIXME: ideally this would be used on all platforms.
-#if PLATFORM(CHROMIUM) || PLATFORM(QT)
+#if PLATFORM(CHROMIUM) || PLATFORM(QT) || PLATFORM(GTK)
class GraphicsContext3DInternal;
#endif
@@ -465,6 +471,9 @@ public:
#if USE(ACCELERATED_COMPOSITING)
PlatformLayer* platformLayer() const;
#endif
+#elif PLATFORM(GTK)
+ PlatformGraphicsContext3D platformGraphicsContext3D();
+ Platform3DObject platformTexture() const { return m_texture; }
#else
PlatformGraphicsContext3D platformGraphicsContext3D() const { return NullPlatformGraphicsContext3D; }
Platform3DObject platformTexture() const { return NullPlatform3DObject; }
@@ -476,7 +485,7 @@ public:
PassRefPtr<DrawingBuffer> createDrawingBuffer(const IntSize& = IntSize());
-#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
+#if PLATFORM(MAC) || PLATFORM(CHROMIUM) || PLATFORM(GTK)
// With multisampling on, blit from multisampleFBO to regular FBO.
void prepareTexture();
#endif
@@ -753,9 +762,12 @@ public:
void reshape(int width, int height);
-#if PLATFORM(CG)
+#if USE(CG)
void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight,
int canvasWidth, int canvasHeight, CGContextRef context);
+#elif PLATFORM(GTK)
+ void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight,
+ int canvasWidth, int canvasHeight, PlatformContextCairo* context);
#endif
void markContextChanged();
@@ -769,6 +781,8 @@ public:
bool paintsIntoCanvasBuffer() const { return true; }
#elif PLATFORM(CHROMIUM)
bool paintsIntoCanvasBuffer() const;
+#elif PLATFORM(GTK)
+ bool paintsIntoCanvasBuffer() const { return true; }
#else
bool paintsIntoCanvasBuffer() const { return false; }
#endif
@@ -859,7 +873,7 @@ public:
AlphaOp alphaOp,
void* destinationData);
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || PLATFORM(GTK)
// Take into account the user's requested context creation attributes,
// in particular stencil and antialias, and determine which could or
// could not be honored based on the capabilities of the OpenGL
@@ -874,6 +888,11 @@ public:
int m_currentWidth, m_currentHeight;
#if PLATFORM(MAC)
+ CGLContextObj m_contextObj;
+ RetainPtr<WebGLLayer> m_webGLLayer;
+#endif
+
+#if PLATFORM(MAC) || PLATFORM(GTK)
typedef struct {
String source;
String log;
@@ -889,8 +908,6 @@ public:
Attributes m_attrs;
Vector<Vector<float> > m_vertexArray;
- CGLContextObj m_contextObj;
- RetainPtr<WebGLLayer> m_webGLLayer;
GC3Duint m_texture, m_compositorTexture;
GC3Duint m_fbo;
GC3Duint m_depthStencilBuffer;
@@ -912,7 +929,7 @@ public:
#endif
// FIXME: ideally this would be used on all platforms.
-#if PLATFORM(CHROMIUM) || PLATFORM(QT)
+#if PLATFORM(CHROMIUM) || PLATFORM(QT) || PLATFORM(GTK)
friend class GraphicsContext3DInternal;
OwnPtr<GraphicsContext3DInternal> m_internal;
#endif
diff --git a/Source/WebCore/platform/graphics/Image.cpp b/Source/WebCore/platform/graphics/Image.cpp
index 3096680..11da0ab 100644
--- a/Source/WebCore/platform/graphics/Image.cpp
+++ b/Source/WebCore/platform/graphics/Image.cpp
@@ -36,7 +36,7 @@
#include <math.h>
#include <wtf/StdLibExtras.h>
-#if PLATFORM(CG)
+#if USE(CG)
#include <CoreFoundation/CoreFoundation.h>
#endif
diff --git a/Source/WebCore/platform/graphics/Image.h b/Source/WebCore/platform/graphics/Image.h
index 3c5e7fd..834a0d3 100644
--- a/Source/WebCore/platform/graphics/Image.h
+++ b/Source/WebCore/platform/graphics/Image.h
@@ -45,7 +45,7 @@ class NSImage;
#endif
#endif
-#if PLATFORM(CG)
+#if USE(CG)
struct CGContext;
#endif
@@ -136,8 +136,9 @@ public:
virtual CFDataRef getTIFFRepresentation() { return 0; }
#endif
-#if PLATFORM(CG)
+#if USE(CG)
virtual CGImageRef getCGImageRef() { return 0; }
+ virtual CGImageRef getFirstCGImageRefOfSize(const IntSize&) { return 0; }
#endif
#if PLATFORM(WIN)
diff --git a/Source/WebCore/platform/graphics/ImageBuffer.cpp b/Source/WebCore/platform/graphics/ImageBuffer.cpp
index 4a76be4..23b925a 100644
--- a/Source/WebCore/platform/graphics/ImageBuffer.cpp
+++ b/Source/WebCore/platform/graphics/ImageBuffer.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "ImageBuffer.h"
-#if !PLATFORM(CG)
+#if !USE(CG)
#include <math.h>
@@ -69,4 +69,4 @@ void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h
index 860f574..c184bbe 100644
--- a/Source/WebCore/platform/graphics/ImageBuffer.h
+++ b/Source/WebCore/platform/graphics/ImageBuffer.h
@@ -41,10 +41,6 @@
#include <wtf/PassRefPtr.h>
#include <wtf/Vector.h>
-#if (PLATFORM(MAC) && PLATFORM(CA) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD))
-#define WTF_USE_IOSURFACE_CANVAS_BACKING_STORE 1
-#endif
-
namespace WebCore {
class GraphicsContext;
@@ -86,6 +82,7 @@ namespace WebCore {
GraphicsContext* context() const;
+ bool isAccelerated() const { return m_accelerateRendering; }
bool drawsUsingCopy() const; // If the image buffer has to render using a copied image, it will return true.
PassRefPtr<Image> copyImage() const; // Return a new image that is a copy of the buffer.
@@ -96,7 +93,7 @@ namespace WebCore {
void putPremultipliedImageData(ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint);
String toDataURL(const String& mimeType, const double* quality = 0) const;
-#if !PLATFORM(CG)
+#if !USE(CG)
AffineTransform baseTransform() const { return AffineTransform(); }
void transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace);
void platformTransformColorSpace(const Vector<int>&);
@@ -122,7 +119,7 @@ namespace WebCore {
bool m_accelerateRendering;
OwnPtr<GraphicsContext> m_context;
-#if !PLATFORM(CG)
+#if !USE(CG)
Vector<int> m_linearRgbLUT;
Vector<int> m_deviceRgbLUT;
#endif
@@ -132,7 +129,7 @@ namespace WebCore {
ImageBuffer(const IntSize&, ColorSpace colorSpace, RenderingMode renderingMode, bool& success);
};
-#if PLATFORM(CG) || USE(SKIA)
+#if USE(CG) || USE(SKIA)
String ImageDataToDataURL(const ImageData& input, const String& mimeType, const double* quality);
#endif
diff --git a/Source/WebCore/platform/graphics/ImageBufferData.h b/Source/WebCore/platform/graphics/ImageBufferData.h
new file mode 100644
index 0000000..670a10f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ImageBufferData.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#if USE(CG)
+#include "ImageBufferDataCG.h"
+#elif USE(CAIRO)
+#include "ImageBufferDataCairo.h"
+#elif PLATFORM(QT)
+#include "ImageBufferDataQt.h"
+#elif USE(SKIA)
+#include "ImageBufferDataSkia.h"
+#elif PLATFORM(HAIKU)
+#include "ImageBufferDataHaiku.h"
+#elif OS(WINCE)
+#include "ImageBufferDataWince.h"
+#elif PLATFORM(WX)
+#include "ImageBufferDataWx.h"
+#endif
diff --git a/Source/WebCore/platform/graphics/ImageSource.h b/Source/WebCore/platform/graphics/ImageSource.h
index 5ece15b..8dcc9a2 100644
--- a/Source/WebCore/platform/graphics/ImageSource.h
+++ b/Source/WebCore/platform/graphics/ImageSource.h
@@ -34,7 +34,7 @@
#if PLATFORM(WX)
class wxBitmap;
class wxGraphicsBitmap;
-#elif PLATFORM(CG)
+#elif USE(CG)
typedef struct CGImageSource* CGImageSourceRef;
typedef struct CGImage* CGImageRef;
typedef const struct __CFData* CFDataRef;
@@ -43,7 +43,7 @@ typedef const struct __CFData* CFDataRef;
QT_BEGIN_NAMESPACE
class QPixmap;
QT_END_NAMESPACE
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
struct _cairo_surface;
typedef struct _cairo_surface cairo_surface_t;
#elif USE(SKIA)
@@ -68,7 +68,7 @@ class IntPoint;
class IntSize;
class SharedBuffer;
-#if PLATFORM(CG)
+#if USE(CG)
#if USE(WEBKIT_IMAGE_DECODERS)
class ImageDecoder;
typedef ImageDecoder* NativeImageSourcePtr;
@@ -107,7 +107,7 @@ typedef wxGraphicsBitmap* NativeImagePtr;
#else
typedef wxBitmap* NativeImagePtr;
#endif
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
typedef cairo_surface_t* NativeImagePtr;
#elif USE(SKIA)
typedef WebCore::NativeImageSkia* NativeImagePtr;
diff --git a/Source/WebCore/platform/graphics/IntPoint.h b/Source/WebCore/platform/graphics/IntPoint.h
index d27906b..46d49eb 100644
--- a/Source/WebCore/platform/graphics/IntPoint.h
+++ b/Source/WebCore/platform/graphics/IntPoint.h
@@ -32,7 +32,7 @@
#include <QDataStream>
#endif
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
typedef struct CGPoint CGPoint;
#endif
@@ -114,7 +114,7 @@ public:
return IntPoint(m_y, m_x);
}
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
explicit IntPoint(const CGPoint&); // don't do this implicitly since it's lossy
operator CGPoint() const;
#endif
diff --git a/Source/WebCore/platform/graphics/IntRect.cpp b/Source/WebCore/platform/graphics/IntRect.cpp
index 7591c41..9507406 100644
--- a/Source/WebCore/platform/graphics/IntRect.cpp
+++ b/Source/WebCore/platform/graphics/IntRect.cpp
@@ -96,6 +96,27 @@ void IntRect::unite(const IntRect& other)
m_size.setHeight(b - t);
}
+void IntRect::uniteIfNonZero(const IntRect& other)
+{
+ // Handle empty special cases first.
+ if (!other.width() && !other.height())
+ return;
+ if (!width() && !height()) {
+ *this = other;
+ return;
+ }
+
+ int left = min(x(), other.x());
+ int top = min(y(), other.y());
+ int right = max(maxX(), other.maxX());
+ int bottom = max(maxY(), other.maxY());
+
+ m_location.setX(left);
+ m_location.setY(top);
+ m_size.setWidth(right - left);
+ m_size.setHeight(bottom - top);
+}
+
void IntRect::scale(float s)
{
m_location.setX((int)(x() * s));
diff --git a/Source/WebCore/platform/graphics/IntRect.h b/Source/WebCore/platform/graphics/IntRect.h
index c413e7a..d2b348b 100644
--- a/Source/WebCore/platform/graphics/IntRect.h
+++ b/Source/WebCore/platform/graphics/IntRect.h
@@ -29,7 +29,7 @@
#include "IntPoint.h"
#include <wtf/Vector.h>
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
typedef struct CGRect CGRect;
#endif
@@ -133,6 +133,11 @@ public:
setHeight(std::max(0, height() + delta));
}
+ IntPoint minXMinYCorner() const { return m_location; } // typically topLeft
+ IntPoint maxXMinYCorner() const { return IntPoint(m_location.x() + m_size.width(), m_location.y()); } // typically topRight
+ IntPoint minXMaxYCorner() const { return IntPoint(m_location.x(), m_location.y() + m_size.height()); } // typically bottomLeft
+ IntPoint maxXMaxYCorner() const { return IntPoint(m_location.x() + m_size.width(), m_location.y() + m_size.height()); } // typically bottomRight
+
bool intersects(const IntRect&) const;
bool contains(const IntRect&) const;
@@ -144,6 +149,7 @@ public:
void intersect(const IntRect&);
void unite(const IntRect&);
+ void uniteIfNonZero(const IntRect&);
void inflateX(int dx)
{
@@ -182,7 +188,7 @@ public:
operator Eina_Rectangle() const;
#endif
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
operator CGRect() const;
#endif
@@ -228,7 +234,7 @@ inline bool operator!=(const IntRect& a, const IntRect& b)
return a.location() != b.location() || a.size() != b.size();
}
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
IntRect enclosingIntRect(const CGRect&);
#endif
diff --git a/Source/WebCore/platform/graphics/IntSize.h b/Source/WebCore/platform/graphics/IntSize.h
index 9db2224..8cfabf5 100644
--- a/Source/WebCore/platform/graphics/IntSize.h
+++ b/Source/WebCore/platform/graphics/IntSize.h
@@ -26,7 +26,7 @@
#ifndef IntSize_h
#define IntSize_h
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
typedef struct CGSize CGSize;
#endif
@@ -109,7 +109,7 @@ public:
return IntSize(m_height, m_width);
}
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
explicit IntSize(const CGSize&); // don't do this implicitly since it's lossy
operator CGSize() const;
#endif
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp
index 03004b6..a7e4b90 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp
@@ -792,11 +792,12 @@ void MediaPlayer::networkStateChanged()
// If more than one media engine is installed and this one failed before finding metadata,
// let the next engine try.
if (m_private->networkState() >= FormatError
- && m_private->readyState() < HaveMetadata
- && installedMediaEngines().size() > 1
- && bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, m_currentMediaEngine)) {
+ && m_private->readyState() < HaveMetadata
+ && installedMediaEngines().size() > 1) {
+ if ( m_contentMIMEType.isEmpty() || bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, m_currentMediaEngine)) {
m_reloadTimer.startOneShot(0);
return;
+ }
}
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerNetworkStateChanged(this);
@@ -858,6 +859,12 @@ void MediaPlayer::playbackStateChanged()
m_mediaPlayerClient->mediaPlayerPlaybackStateChanged(this);
}
+void MediaPlayer::firstVideoFrameAvailable()
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerFirstVideoFrameAvailable(this);
+}
+
}
#endif
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h
index ff304ea..41cb6d2 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.h
+++ b/Source/WebCore/platform/graphics/MediaPlayer.h
@@ -143,6 +143,10 @@ public:
virtual void mediaPlayerEngineUpdated(MediaPlayer*) { }
+ // The first frame of video is available to render. A media engine need only make this callback if the
+ // first frame is not available immediately when prepareForRendering is called.
+ virtual void mediaPlayerFirstVideoFrameAvailable(MediaPlayer*) { }
+
#if USE(ACCELERATED_COMPOSITING)
// whether the rendering system can accelerate the display of this MediaPlayer.
virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*) { return false; }
@@ -262,6 +266,7 @@ public:
void rateChanged();
void playbackStateChanged();
void durationChanged();
+ void firstVideoFrameAvailable();
void repaint();
diff --git a/Source/WebCore/platform/graphics/Path.cpp b/Source/WebCore/platform/graphics/Path.cpp
index f7aedbe..da09c76 100644
--- a/Source/WebCore/platform/graphics/Path.cpp
+++ b/Source/WebCore/platform/graphics/Path.cpp
@@ -188,4 +188,9 @@ void Path::addRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius,
closeSubpath();
}
+void Path::addRoundedRect(const RoundedIntRect& r)
+{
+ addRoundedRect(r.rect(), r.radii().topLeft(), r.radii().topRight(), r.radii().bottomLeft(), r.radii().bottomRight());
+}
+
}
diff --git a/Source/WebCore/platform/graphics/Path.h b/Source/WebCore/platform/graphics/Path.h
index c2ca576..9c07247 100644
--- a/Source/WebCore/platform/graphics/Path.h
+++ b/Source/WebCore/platform/graphics/Path.h
@@ -28,10 +28,11 @@
#ifndef Path_h
#define Path_h
+#include "RoundedIntRect.h"
#include <wtf/FastAllocBase.h>
#include <wtf/Forward.h>
-#if PLATFORM(CG)
+#if USE(CG)
typedef struct CGPath PlatformPath;
#elif PLATFORM(OPENVG)
namespace WebCore {
@@ -44,7 +45,7 @@ typedef QPainterPath PlatformPath;
#elif PLATFORM(WX) && USE(WXGC)
class wxGraphicsPath;
typedef wxGraphicsPath PlatformPath;
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
namespace WebCore {
class CairoPath;
}
@@ -137,6 +138,7 @@ namespace WebCore {
void addEllipse(const FloatRect&);
void addRoundedRect(const FloatRect&, const FloatSize& roundingRadii);
void addRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
+ void addRoundedRect(const RoundedIntRect&);
void translate(const FloatSize&);
diff --git a/Source/WebCore/platform/graphics/Pattern.h b/Source/WebCore/platform/graphics/Pattern.h
index c88f2fb..1d0b0f8 100644
--- a/Source/WebCore/platform/graphics/Pattern.h
+++ b/Source/WebCore/platform/graphics/Pattern.h
@@ -35,10 +35,10 @@
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
-#if PLATFORM(CG)
+#if USE(CG)
typedef struct CGPattern* CGPatternRef;
typedef CGPatternRef PlatformPatternPtr;
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
#include <cairo.h>
typedef cairo_pattern_t* PlatformPatternPtr;
#elif USE(SKIA)
diff --git a/Source/WebCore/platform/graphics/RoundedIntRect.cpp b/Source/WebCore/platform/graphics/RoundedIntRect.cpp
index 4e80c9a..e919c4f 100644
--- a/Source/WebCore/platform/graphics/RoundedIntRect.cpp
+++ b/Source/WebCore/platform/graphics/RoundedIntRect.cpp
@@ -30,6 +30,8 @@
#include "IntRect.h"
#include <algorithm>
+using namespace std;
+
namespace WebCore {
bool RoundedIntRect::Radii::isZero() const
@@ -60,17 +62,17 @@ void RoundedIntRect::Radii::scale(float factor)
void RoundedIntRect::Radii::expand(int topWidth, int bottomWidth, int leftWidth, int rightWidth)
{
- m_topLeft.setWidth(std::max(0, m_topLeft.width() + leftWidth));
- m_topLeft.setHeight(std::max(0, m_topLeft.height() + topWidth));
+ m_topLeft.setWidth(max(0, m_topLeft.width() + leftWidth));
+ m_topLeft.setHeight(max(0, m_topLeft.height() + topWidth));
- m_topRight.setWidth(std::max(0, m_topRight.width() + rightWidth));
- m_topRight.setHeight(std::max(0, m_topRight.height() + topWidth));
+ m_topRight.setWidth(max(0, m_topRight.width() + rightWidth));
+ m_topRight.setHeight(max(0, m_topRight.height() + topWidth));
- m_bottomLeft.setWidth(std::max(0, m_bottomLeft.width() + leftWidth));
- m_bottomLeft.setHeight(std::max(0, m_bottomLeft.height() + bottomWidth));
+ m_bottomLeft.setWidth(max(0, m_bottomLeft.width() + leftWidth));
+ m_bottomLeft.setHeight(max(0, m_bottomLeft.height() + bottomWidth));
- m_bottomRight.setWidth(std::max(0, m_bottomRight.width() + rightWidth));
- m_bottomRight.setHeight(std::max(0, m_bottomRight.height() + bottomWidth));
+ m_bottomRight.setWidth(max(0, m_bottomRight.width() + rightWidth));
+ m_bottomRight.setHeight(max(0, m_bottomRight.height() + bottomWidth));
}
void RoundedIntRect::Radii::includeLogicalEdges(const RoundedIntRect::Radii& edges, bool isHorizontal, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
@@ -138,4 +140,12 @@ void RoundedIntRect::excludeLogicalEdges(bool isHorizontal, bool excludeLogicalL
m_radii.excludeLogicalEdges(isHorizontal, excludeLogicalLeftEdge, excludeLogicalRightEdge);
}
+bool RoundedIntRect::isRenderable() const
+{
+ return m_radii.topLeft().width() + m_radii.topRight().width() <= m_rect.width()
+ && m_radii.bottomLeft().width() + m_radii.bottomRight().width() <= m_rect.width()
+ && m_radii.topLeft().height() + m_radii.topRight().height() <= m_rect.height()
+ && m_radii.bottomLeft().height() + m_radii.bottomRight().height() <= m_rect.height();
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/RoundedIntRect.h b/Source/WebCore/platform/graphics/RoundedIntRect.h
index c3c972f..74ee892 100644
--- a/Source/WebCore/platform/graphics/RoundedIntRect.h
+++ b/Source/WebCore/platform/graphics/RoundedIntRect.h
@@ -93,11 +93,24 @@ public:
void includeLogicalEdges(const Radii& edges, bool isHorizontal, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
void excludeLogicalEdges(bool isHorizontal, bool excludeLogicalLeftEdge, bool excludeLogicalRightEdge);
+ bool isRenderable() const;
+
private:
IntRect m_rect;
Radii m_radii;
};
+inline bool operator==(const RoundedIntRect::Radii& a, const RoundedIntRect::Radii& b)
+{
+ return a.topLeft() == b.topLeft() && a.topRight() == b.topRight() && a.bottomLeft() == b.bottomLeft() && a.bottomRight() == b.bottomRight();
+}
+
+inline bool operator==(const RoundedIntRect& a, const RoundedIntRect& b)
+{
+ return a.rect() == b.rect() && a.radii() == b.radii();
+}
+
+
} // namespace WebCore
#endif // RoundedIntRect_h
diff --git a/Source/WebCore/platform/graphics/ShadowBlur.cpp b/Source/WebCore/platform/graphics/ShadowBlur.cpp
index 0df51a4..2f25221 100644
--- a/Source/WebCore/platform/graphics/ShadowBlur.cpp
+++ b/Source/WebCore/platform/graphics/ShadowBlur.cpp
@@ -54,6 +54,8 @@ class ScratchBuffer {
public:
ScratchBuffer()
: m_purgeTimer(this, &ScratchBuffer::timerFired)
+ , m_lastRadius(0)
+ , m_lastWasInset(false)
#if !ASSERT_DISABLED
, m_bufferInUse(false)
#endif
@@ -77,6 +79,41 @@ public:
return m_imageBuffer.get();
}
+ void setLastShadowValues(float radius, const Color& color, ColorSpace colorSpace, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii)
+ {
+ m_lastWasInset = false;
+ m_lastRadius = radius;
+ m_lastColor = color;
+ m_lastColorSpace = colorSpace;
+ m_lastShadowRect = shadowRect;
+ m_lastRadii = radii;
+ }
+
+ void setLastInsetShadowValues(float radius, const Color& color, ColorSpace colorSpace, const FloatRect& bounds, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii)
+ {
+ m_lastWasInset = true;
+ m_lastInsetBounds = bounds;
+ m_lastRadius = radius;
+ m_lastColor = color;
+ m_lastColorSpace = colorSpace;
+ m_lastShadowRect = shadowRect;
+ m_lastRadii = radii;
+ }
+
+ bool matchesLastShadow(float radius, const Color& color, ColorSpace colorSpace, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii) const
+ {
+ if (m_lastWasInset)
+ return false;
+ return m_lastRadius == radius && m_lastColor == color && m_lastColorSpace == colorSpace && shadowRect == m_lastShadowRect && radii == m_lastRadii;
+ }
+
+ bool matchesLastInsetShadow(float radius, const Color& color, ColorSpace colorSpace, const FloatRect& bounds, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii) const
+ {
+ if (!m_lastWasInset)
+ return false;
+ return m_lastRadius == radius && m_lastColor == color && m_lastColorSpace == colorSpace && m_lastInsetBounds == bounds && shadowRect == m_lastShadowRect && radii == m_lastRadii;
+ }
+
void scheduleScratchBufferPurge()
{
#if !ASSERT_DISABLED
@@ -100,10 +137,20 @@ private:
void clearScratchBuffer()
{
m_imageBuffer = 0;
+ m_lastRadius = 0;
}
OwnPtr<ImageBuffer> m_imageBuffer;
Timer<ScratchBuffer> m_purgeTimer;
+
+ FloatRect m_lastInsetBounds;
+ FloatRect m_lastShadowRect;
+ RoundedIntRect::Radii m_lastRadii;
+ Color m_lastColor;
+ ColorSpace m_lastColorSpace;
+ float m_lastRadius;
+ bool m_lastWasInset;
+
#if !ASSERT_DISABLED
bool m_bufferInUse;
#endif
@@ -147,14 +194,7 @@ static const int blurSumShift = 15;
void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, int rowStride)
{
- const int channels[4] =
-#if CPU(BIG_ENDIAN)
- { 0, 3, 2, 0 };
-#elif CPU(MIDDLE_ENDIAN)
- { 1, 2, 3, 1 };
-#else
- { 3, 0, 1, 3 };
-#endif
+ const int channels[4] = { 3, 0, 1, 3 };
int diameter;
if (m_shadowsIgnoreTransforms)
@@ -356,40 +396,10 @@ IntRect ShadowBlur::calculateLayerBoundingRect(GraphicsContext* context, const F
return enclosingIntRect(layerRect);
}
-GraphicsContext* ShadowBlur::beginShadowLayer(GraphicsContext* graphicsContext, const IntRect& layerRect)
-{
- adjustBlurRadius(graphicsContext);
-
- // Don't paint if we are totally outside the clip region.
- if (layerRect.isEmpty())
- return 0;
-
- m_layerImage = ScratchBuffer::shared().getScratchBuffer(layerRect.size());
- GraphicsContext* layerContext = m_layerImage->context();
-
- layerContext->save(); // Balanced by restore() in endShadowLayer().
-
- // Always clear the surface first. FIXME: we could avoid the clear on first allocation.
- // Add a pixel to avoid later edge aliasing when rotated.
- layerContext->clearRect(FloatRect(0, 0, m_layerSize.width() + 1, m_layerSize.height() + 1));
- layerContext->translate(m_layerContextTranslation);
-
- return layerContext;
-}
-
-void ShadowBlur::endShadowLayer(GraphicsContext* graphicsContext)
+void ShadowBlur::drawShadowBuffer(GraphicsContext* graphicsContext)
{
if (!m_layerImage)
return;
-
- m_layerImage->context()->restore();
-
- if (m_type == BlurShadow) {
- IntRect blurRect = enclosingIntRect(FloatRect(FloatPoint(), m_layerSize));
- RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect);
- blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4);
- m_layerImage->putUnmultipliedImageData(layerData.get(), blurRect.size(), blurRect, IntPoint());
- }
graphicsContext->save();
@@ -406,11 +416,6 @@ void ShadowBlur::endShadowLayer(GraphicsContext* graphicsContext)
graphicsContext->fillRect(FloatRect(m_layerOrigin, m_sourceRect.size()));
graphicsContext->restore();
-
- m_layerImage = 0;
-
- // Schedule a purge of the scratch buffer. We do not need to destroy the surface.
- ScratchBuffer::shared().scheduleScratchBufferPurge();
}
static void computeSliceSizesFromRadii(int twiceRadius, const RoundedIntRect::Radii& radii, int& leftSlice, int& rightSlice, int& topSlice, int& bottomSlice)
@@ -442,6 +447,8 @@ void ShadowBlur::drawRectShadow(GraphicsContext* graphicsContext, const FloatRec
if (layerRect.isEmpty())
return;
+ adjustBlurRadius(graphicsContext);
+
// drawRectShadowWithTiling does not work with rotations.
// https://bugs.webkit.org/show_bug.cgi?id=45042
if (!graphicsContext->getCTM().isIdentityOrTranslationOrFlipped() || m_type != BlurShadow) {
@@ -466,6 +473,8 @@ void ShadowBlur::drawInsetShadow(GraphicsContext* graphicsContext, const FloatRe
if (layerRect.isEmpty())
return;
+ adjustBlurRadius(graphicsContext);
+
// drawInsetShadowWithTiling does not work with rotations.
// https://bugs.webkit.org/show_bug.cgi?id=45042
if (!graphicsContext->getCTM().isIdentityOrTranslationOrFlipped() || m_type != BlurShadow) {
@@ -486,34 +495,81 @@ void ShadowBlur::drawInsetShadow(GraphicsContext* graphicsContext, const FloatRe
void ShadowBlur::drawRectShadowWithoutTiling(GraphicsContext* graphicsContext, const FloatRect& shadowedRect, const RoundedIntRect::Radii& radii, const IntRect& layerRect)
{
- GraphicsContext* shadowContext = beginShadowLayer(graphicsContext, layerRect);
- if (!shadowContext)
+ m_layerImage = ScratchBuffer::shared().getScratchBuffer(layerRect.size());
+ if (!m_layerImage)
return;
- Path path;
- path.addRoundedRect(shadowedRect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
+ FloatRect bufferRelativeShadowedRect = shadowedRect;
+ bufferRelativeShadowedRect.move(m_layerContextTranslation);
+ if (!ScratchBuffer::shared().matchesLastShadow(m_blurRadius, Color::black, ColorSpaceDeviceRGB, bufferRelativeShadowedRect, radii)) {
+ GraphicsContext* shadowContext = m_layerImage->context();
+ shadowContext->save();
+
+ // Add a pixel to avoid later edge aliasing when rotated.
+ shadowContext->clearRect(FloatRect(0, 0, m_layerSize.width() + 1, m_layerSize.height() + 1));
+ shadowContext->translate(m_layerContextTranslation);
+ shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
+ if (radii.isZero())
+ shadowContext->fillRect(shadowedRect);
+ else {
+ Path path;
+ path.addRoundedRect(shadowedRect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
+ shadowContext->fillPath(path);
+ }
+
+ blurShadowBuffer(expandedIntSize(m_layerSize));
- shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
- shadowContext->fillPath(path);
+ shadowContext->restore();
+
+ ScratchBuffer::shared().setLastShadowValues(m_blurRadius, Color::black, ColorSpaceDeviceRGB, bufferRelativeShadowedRect, radii);
+ }
- endShadowLayer(graphicsContext);
+ drawShadowBuffer(graphicsContext);
+ m_layerImage = 0;
+ ScratchBuffer::shared().scheduleScratchBufferPurge();
}
void ShadowBlur::drawInsetShadowWithoutTiling(GraphicsContext* graphicsContext, const FloatRect& rect, const FloatRect& holeRect, const RoundedIntRect::Radii& holeRadii, const IntRect& layerRect)
{
- GraphicsContext* shadowContext = beginShadowLayer(graphicsContext, layerRect);
- if (!shadowContext)
+ m_layerImage = ScratchBuffer::shared().getScratchBuffer(layerRect.size());
+ if (!m_layerImage)
return;
- Path path;
- path.addRect(rect);
- path.addRoundedRect(holeRect, holeRadii.topLeft(), holeRadii.topRight(), holeRadii.bottomLeft(), holeRadii.bottomRight());
+ FloatRect bufferRelativeRect = rect;
+ bufferRelativeRect.move(m_layerContextTranslation);
+
+ FloatRect bufferRelativeHoleRect = holeRect;
+ bufferRelativeHoleRect.move(m_layerContextTranslation);
- shadowContext->setFillRule(RULE_EVENODD);
- shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
- shadowContext->fillPath(path);
+ if (!ScratchBuffer::shared().matchesLastInsetShadow(m_blurRadius, Color::black, ColorSpaceDeviceRGB, bufferRelativeRect, bufferRelativeHoleRect, holeRadii)) {
+ GraphicsContext* shadowContext = m_layerImage->context();
+ shadowContext->save();
- endShadowLayer(graphicsContext);
+ // Add a pixel to avoid later edge aliasing when rotated.
+ shadowContext->clearRect(FloatRect(0, 0, m_layerSize.width() + 1, m_layerSize.height() + 1));
+ shadowContext->translate(m_layerContextTranslation);
+
+ Path path;
+ path.addRect(rect);
+ if (holeRadii.isZero())
+ path.addRect(holeRect);
+ else
+ path.addRoundedRect(holeRect, holeRadii.topLeft(), holeRadii.topRight(), holeRadii.bottomLeft(), holeRadii.bottomRight());
+
+ shadowContext->setFillRule(RULE_EVENODD);
+ shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
+ shadowContext->fillPath(path);
+
+ blurShadowBuffer(expandedIntSize(m_layerSize));
+
+ shadowContext->restore();
+
+ ScratchBuffer::shared().setLastInsetShadowValues(m_blurRadius, Color::black, ColorSpaceDeviceRGB, bufferRelativeRect, bufferRelativeHoleRect, holeRadii);
+ }
+
+ drawShadowBuffer(graphicsContext);
+ m_layerImage = 0;
+ ScratchBuffer::shared().scheduleScratchBufferPurge();
}
/*
@@ -557,23 +613,35 @@ void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext* graphicsContext, con
const float twiceRadius = roundedRadius * 2;
m_layerImage = ScratchBuffer::shared().getScratchBuffer(templateSize);
+ if (!m_layerImage)
+ return;
// Draw the rectangle with hole.
FloatRect templateBounds(0, 0, templateSize.width(), templateSize.height());
FloatRect templateHole = FloatRect(roundedRadius, roundedRadius, templateSize.width() - twiceRadius, templateSize.height() - twiceRadius);
- Path path;
- path.addRect(templateBounds);
- path.addRoundedRect(templateHole, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
- // Draw shadow into a new ImageBuffer.
- GraphicsContext* shadowContext = m_layerImage->context();
- shadowContext->save();
- shadowContext->clearRect(templateBounds);
- shadowContext->setFillRule(RULE_EVENODD);
- shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
- shadowContext->fillPath(path);
- blurAndColorShadowBuffer(templateSize);
- shadowContext->restore();
+ if (!ScratchBuffer::shared().matchesLastInsetShadow(m_blurRadius, m_color, m_colorSpace, templateBounds, templateHole, radii)) {
+ // Draw shadow into a new ImageBuffer.
+ GraphicsContext* shadowContext = m_layerImage->context();
+ shadowContext->save();
+ shadowContext->clearRect(templateBounds);
+ shadowContext->setFillRule(RULE_EVENODD);
+ shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
+
+ Path path;
+ path.addRect(templateBounds);
+ if (radii.isZero())
+ path.addRect(templateHole);
+ else
+ path.addRoundedRect(templateHole, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
+
+ shadowContext->fillPath(path);
+
+ blurAndColorShadowBuffer(templateSize);
+ shadowContext->restore();
+
+ ScratchBuffer::shared().setLastInsetShadowValues(m_blurRadius, m_color, m_colorSpace, templateBounds, templateHole, radii);
+ }
FloatRect boundingRect = rect;
boundingRect.move(m_offset);
@@ -599,7 +667,6 @@ void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext* graphicsContext, con
graphicsContext->restore();
m_layerImage = 0;
- // Schedule a purge of the scratch buffer.
ScratchBuffer::shared().scheduleScratchBufferPurge();
}
@@ -612,20 +679,31 @@ void ShadowBlur::drawRectShadowWithTiling(GraphicsContext* graphicsContext, cons
const float twiceRadius = roundedRadius * 2;
m_layerImage = ScratchBuffer::shared().getScratchBuffer(templateSize);
+ if (!m_layerImage)
+ return;
- // Draw the rectangle.
FloatRect templateShadow = FloatRect(roundedRadius, roundedRadius, templateSize.width() - twiceRadius, templateSize.height() - twiceRadius);
- Path path;
- path.addRoundedRect(templateShadow, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
- // Draw shadow into the ImageBuffer.
- GraphicsContext* shadowContext = m_layerImage->context();
- shadowContext->save();
- shadowContext->clearRect(FloatRect(0, 0, templateSize.width(), templateSize.height()));
- shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
- shadowContext->fillPath(path);
- blurAndColorShadowBuffer(templateSize);
- shadowContext->restore();
+ if (!ScratchBuffer::shared().matchesLastShadow(m_blurRadius, m_color, m_colorSpace, templateShadow, radii)) {
+ // Draw shadow into the ImageBuffer.
+ GraphicsContext* shadowContext = m_layerImage->context();
+ shadowContext->save();
+ shadowContext->clearRect(FloatRect(0, 0, templateSize.width(), templateSize.height()));
+ shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB);
+
+ if (radii.isZero())
+ shadowContext->fillRect(templateShadow);
+ else {
+ Path path;
+ path.addRoundedRect(templateShadow, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
+ shadowContext->fillPath(path);
+ }
+
+ blurAndColorShadowBuffer(templateSize);
+ shadowContext->restore();
+
+ ScratchBuffer::shared().setLastShadowValues(m_blurRadius, m_color, m_colorSpace, templateShadow, radii);
+ }
FloatRect shadowBounds = shadowedRect;
shadowBounds.move(m_offset.width(), m_offset.height());
@@ -636,7 +714,6 @@ void ShadowBlur::drawRectShadowWithTiling(GraphicsContext* graphicsContext, cons
graphicsContext->restore();
m_layerImage = 0;
- // Schedule a purge of the scratch buffer.
ScratchBuffer::shared().scheduleScratchBufferPurge();
}
@@ -714,14 +791,20 @@ void ShadowBlur::drawLayerPieces(GraphicsContext* graphicsContext, const FloatRe
}
+void ShadowBlur::blurShadowBuffer(const IntSize& templateSize)
+{
+ if (m_type != BlurShadow)
+ return;
+
+ IntRect blurRect(IntPoint(), templateSize);
+ RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect);
+ blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4);
+ m_layerImage->putUnmultipliedImageData(layerData.get(), blurRect.size(), blurRect, IntPoint());
+}
+
void ShadowBlur::blurAndColorShadowBuffer(const IntSize& templateSize)
{
- {
- IntRect blurRect(IntPoint(), templateSize);
- RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect);
- blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4);
- m_layerImage->putUnmultipliedImageData(layerData.get(), blurRect.size(), blurRect, IntPoint());
- }
+ blurShadowBuffer(templateSize);
// Mask the image with the shadow color.
GraphicsContext* shadowContext = m_layerImage->context();
diff --git a/Source/WebCore/platform/graphics/ShadowBlur.h b/Source/WebCore/platform/graphics/ShadowBlur.h
index e52d6dc..4ba8e23 100644
--- a/Source/WebCore/platform/graphics/ShadowBlur.h
+++ b/Source/WebCore/platform/graphics/ShadowBlur.h
@@ -53,8 +53,7 @@ public:
void drawInsetShadow(GraphicsContext*, const FloatRect&, const FloatRect& holeRect, const RoundedIntRect::Radii& holeRadii);
private:
- GraphicsContext* beginShadowLayer(GraphicsContext*, const IntRect& layerRect);
- void endShadowLayer(GraphicsContext*);
+ void drawShadowBuffer(GraphicsContext*);
void adjustBlurRadius(GraphicsContext*);
void blurLayerImage(unsigned char*, const IntSize&, int stride);
@@ -75,6 +74,7 @@ private:
void drawLayerPieces(GraphicsContext*, const FloatRect& shadowBounds, const RoundedIntRect::Radii&, float roundedRadius, const IntSize& templateSize, ShadowDirection);
+ void blurShadowBuffer(const IntSize& templateSize);
void blurAndColorShadowBuffer(const IntSize& templateSize);
enum ShadowType {
diff --git a/Source/WebCore/platform/graphics/SimpleFontData.h b/Source/WebCore/platform/graphics/SimpleFontData.h
index dfb4be3..67e864a 100644
--- a/Source/WebCore/platform/graphics/SimpleFontData.h
+++ b/Source/WebCore/platform/graphics/SimpleFontData.h
@@ -48,7 +48,7 @@ typedef struct OpaqueATSUStyle* ATSUStyle;
#include <usp10.h>
#endif
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
#include <cairo.h>
#endif
@@ -115,7 +115,7 @@ public:
float spaceWidth() const { return m_spaceWidth; }
-#if PLATFORM(CG) || PLATFORM(CAIRO) || PLATFORM(WX)
+#if USE(CG) || USE(CAIRO) || PLATFORM(WX) || USE(SKIA_ON_MAC_CHROME)
float syntheticBoldOffset() const { return m_syntheticBoldOffset; }
#endif
@@ -252,7 +252,7 @@ private:
mutable OwnPtr<DerivedFontData> m_derivedFontData;
-#if PLATFORM(CG) || PLATFORM(CAIRO) || PLATFORM(WX)
+#if USE(CG) || USE(CAIRO) || PLATFORM(WX) || USE(SKIA_ON_MAC_CHROME)
float m_syntheticBoldOffset;
#endif
diff --git a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
index 80a6dcb..d54f3df 100644
--- a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
+++ b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp
@@ -43,7 +43,7 @@
#define ntohs(x) std_ntohs(x)
#endif
-#if PLATFORM(WIN)
+#if OS(WINDOWS)
#if CPU(BIG_ENDIAN)
#define ntohs(x) ((uint16_t)(x))
#define htons(x) ((uint16_t)(x))
@@ -61,7 +61,7 @@
(((uint32_t)(x) & 0x0000ff00) << 8) | (((uint32_t)(x) & 0x000000ff) << 24)))
#define htonl(x) ntohl(x)
#endif
-#endif // PLATFORM(WIN)
+#endif // OS(WINDOWS)
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp
index eb96532..681003f 100644
--- a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp
+++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp
@@ -74,6 +74,8 @@ MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(MediaPlayer* play
, m_cachedHasVideo(false)
, m_cachedHasCaptions(false)
, m_ignoreLoadStateChanges(false)
+ , m_haveReportedFirstVideoFrame(false)
+ , m_playWhenFramesAvailable(false)
{
LOG(Media, "MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(%p)", this);
}
@@ -248,6 +250,25 @@ void MediaPlayerPrivateAVFoundation::prepareToPlay()
checkPlayability();
}
+void MediaPlayerPrivateAVFoundation::play()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::play(%p)", this);
+
+ // If the file has video, don't request playback until the first frame of video is ready to display
+ // or the audio may start playing before we can render video.
+ if (!m_cachedHasVideo || hasAvailableVideoFrame())
+ platformPlay();
+ else
+ m_playWhenFramesAvailable = true;
+}
+
+void MediaPlayerPrivateAVFoundation::pause()
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::pause(%p)", this);
+ m_playWhenFramesAvailable = false;
+ platformPause();
+}
+
void MediaPlayerPrivateAVFoundation::paint(GraphicsContext*, const IntRect&)
{
// This is the base class, only need to remember that a frame has been drawn.
@@ -285,6 +306,8 @@ void MediaPlayerPrivateAVFoundation::setRate(float rate)
{
LOG(Media, "MediaPlayerPrivateAVFoundation::setRate(%p) - seting to %f", this, rate);
m_requestedRate = rate;
+
+ updateRate();
}
bool MediaPlayerPrivateAVFoundation::paused() const
@@ -464,12 +487,22 @@ void MediaPlayerPrivateAVFoundation::updateStates()
if (isReadyForVideoSetup() && currentRenderingMode() != preferredRenderingMode())
setUpVideoRendering();
+ if (!m_haveReportedFirstVideoFrame && m_cachedHasVideo && hasAvailableVideoFrame()) {
+ m_haveReportedFirstVideoFrame = true;
+ m_player->firstVideoFrameAvailable();
+ }
+
if (m_networkState != oldNetworkState)
m_player->networkStateChanged();
if (m_readyState != oldReadyState)
m_player->readyStateChanged();
+ if (m_playWhenFramesAvailable && hasAvailableVideoFrame()) {
+ m_playWhenFramesAvailable = false;
+ platformPlay();
+ }
+
LOG(Media, "MediaPlayerPrivateAVFoundation::updateStates(%p) - exiting with networkState = %i, readyState = %i",
this, static_cast<int>(m_networkState), static_cast<int>(m_readyState));
}
@@ -566,6 +599,14 @@ void MediaPlayerPrivateAVFoundation::timeChanged(double time)
}
}
+void MediaPlayerPrivateAVFoundation::seekCompleted(bool finished)
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::seekCompleted(%p) - finished = %d", this, finished);
+
+ if (finished)
+ m_seekTo = invalidTime;
+}
+
void MediaPlayerPrivateAVFoundation::didEnd()
{
// Hang onto the current time and use it as duration from now on since we are definitely at
@@ -629,12 +670,22 @@ void MediaPlayerPrivateAVFoundation::clearMainThreadPendingFlag()
void MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(Notification::Type type, double time)
{
- LOG(Media, "MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(%p) - notification %d", this, static_cast<int>(type));
+ scheduleMainThreadNotification(Notification(type, time));
+}
+
+void MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(Notification::Type type, bool finished)
+{
+ scheduleMainThreadNotification(Notification(type, finished));
+}
+
+void MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(Notification notification)
+{
+ LOG(Media, "MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(%p) - notification %d", this, static_cast<int>(notification.type()));
m_queueMutex.lock();
// It is important to always process the properties in the order that we are notified,
// so always go through the queue because notifications happen on different threads.
- m_queuedNotifications.append(Notification(type, time));
+ m_queuedNotifications.append(notification);
bool delayDispatch = m_delayCallbacks || !isMainThread();
if (delayDispatch && !m_mainThreadCallPending) {
@@ -714,6 +765,9 @@ void MediaPlayerPrivateAVFoundation::dispatchNotification()
case Notification::PlayerTimeChanged:
timeChanged(notification.time());
break;
+ case Notification::SeekCompleted:
+ seekCompleted(notification.finished());
+ break;
case Notification::AssetMetadataLoaded:
metadataLoaded();
break;
diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h
index a768ab4..becba61 100644
--- a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h
+++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h
@@ -48,6 +48,7 @@ public:
virtual void loadedTimeRangesChanged();
virtual void seekableTimeRangesChanged();
virtual void timeChanged(double);
+ virtual void seekCompleted(bool);
virtual void didEnd();
class Notification {
@@ -66,31 +67,45 @@ public:
AssetMetadataLoaded,
AssetPlayabilityKnown,
PlayerRateChanged,
- PlayerTimeChanged
+ PlayerTimeChanged,
+ SeekCompleted,
};
Notification()
: m_type(None)
, m_time(0)
+ , m_finished(false)
{
}
Notification(Type type, double time)
: m_type(type)
, m_time(time)
+ , m_finished(false)
+ {
+ }
+
+ Notification(Type type, bool finished)
+ : m_type(type)
+ , m_time(0)
+ , m_finished(finished)
{
}
Type type() { return m_type; }
bool isValid() { return m_type != None; }
double time() { return m_time; }
+ bool finished() { return m_finished; }
private:
Type m_type;
double m_time;
+ bool m_finished;
};
+ void scheduleMainThreadNotification(Notification);
void scheduleMainThreadNotification(Notification::Type, double time = 0);
+ void scheduleMainThreadNotification(Notification::Type, bool completed);
void dispatchNotification();
void clearMainThreadPendingFlag();
@@ -105,8 +120,8 @@ protected:
virtual void prepareToPlay();
virtual PlatformMedia platformMedia() const = 0;
- virtual void play() = 0;
- virtual void pause() = 0;
+ virtual void play();
+ virtual void pause();
virtual IntSize naturalSize() const;
virtual bool hasVideo() const { return m_cachedHasVideo; }
@@ -169,7 +184,10 @@ protected:
};
virtual AVAssetStatus assetStatus() const = 0;
+ virtual void platformPlay() = 0;
+ virtual void platformPause() = 0;
virtual void checkPlayability() = 0;
+ virtual void updateRate() = 0;
virtual float rate() const = 0;
virtual void seekToTime(float time) = 0;
virtual unsigned totalBytes() const = 0;
@@ -254,6 +272,8 @@ private:
bool m_cachedHasVideo;
bool m_cachedHasCaptions;
bool m_ignoreLoadStateChanges;
+ bool m_haveReportedFirstVideoFrame;
+ bool m_playWhenFramesAvailable;
};
}
diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h
index cc00c15..7f214b8 100644
--- a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h
+++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.h
@@ -73,8 +73,8 @@ private:
virtual PlatformMedia platformMedia() const;
- virtual void play();
- virtual void pause();
+ virtual void platformPlay();
+ virtual void platformPause();
virtual float currentTime() const;
virtual void setVolume(float);
virtual void setClosedCaptionsVisible(bool);
@@ -93,6 +93,7 @@ private:
virtual MediaPlayerPrivateAVFoundation::AVAssetStatus assetStatus() const;
virtual void checkPlayability();
+ virtual void updateRate();
virtual float rate() const;
virtual void seekToTime(float time);
virtual unsigned totalBytes() const;
diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm
index 55eb433..c4efb9f 100644
--- a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm
+++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundationObjC.mm
@@ -100,6 +100,7 @@ enum MediaPlayerAVFoundationObservationContext {
-(void)playableKnown;
-(void)metadataLoaded;
-(void)timeChanged:(double)time;
+-(void)seekCompleted:(BOOL)finished;
-(void)didEnd:(NSNotification *)notification;
-(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context;
@end
@@ -200,7 +201,7 @@ void MediaPlayerPrivateAVFoundationObjC::destroyContextVideoRenderer()
if (!m_imageGenerator)
return;
- LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyContextVideoRenderer(%p) - destroying", this, m_imageGenerator.get());
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyContextVideoRenderer(%p) - destroying %p", this, m_imageGenerator.get());
m_imageGenerator = 0;
}
@@ -213,7 +214,7 @@ void MediaPlayerPrivateAVFoundationObjC::createVideoLayer()
if (!m_videoLayer) {
m_videoLayer.adoptNS([[AVPlayerLayer alloc] init]);
[m_videoLayer.get() setPlayer:m_avPlayer.get()];
- LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createVideoLayer(%p) - returning", this, m_videoLayer.get());
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createVideoLayer(%p) - returning %p", this, m_videoLayer.get());
}
}
@@ -327,9 +328,9 @@ MediaPlayerPrivateAVFoundation::ItemStatus MediaPlayerPrivateAVFoundationObjC::p
return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusFailed;
if ([m_avPlayerItem.get() isPlaybackLikelyToKeepUp])
return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp;
- if ([m_avPlayerItem.get() isPlaybackBufferFull])
+ if (buffered()->contain(duration()))
return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferFull;
- if ([m_avPlayerItem.get() isPlaybackBufferEmpty])
+ if (buffered()->contain(currentTime()))
return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty;
return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusReadyToPlay;
@@ -350,9 +351,9 @@ PlatformLayer* MediaPlayerPrivateAVFoundationObjC::platformLayer() const
return m_videoLayer.get();
}
-void MediaPlayerPrivateAVFoundationObjC::play()
+void MediaPlayerPrivateAVFoundationObjC::platformPlay()
{
- LOG(Media, "MediaPlayerPrivateAVFoundationObjC::play(%p)", this);
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformPlay(%p)", this);
if (!metaDataAvailable())
return;
@@ -361,9 +362,9 @@ void MediaPlayerPrivateAVFoundationObjC::play()
setDelayCallbacks(false);
}
-void MediaPlayerPrivateAVFoundationObjC::pause()
+void MediaPlayerPrivateAVFoundationObjC::platformPause()
{
- LOG(Media, "MediaPlayerPrivateAVFoundationObjC::pause(%p)", this);
+ LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformPause(%p)", this);
if (!metaDataAvailable())
return;
@@ -408,14 +409,10 @@ void MediaPlayerPrivateAVFoundationObjC::seekToTime(float time)
// setCurrentTime generates several event callbacks, update afterwards.
setDelayCallbacks(true);
- float now = currentTime();
- if (time != now)
- [m_avPlayerItem.get() seekToTime:CMTimeMakeWithSeconds(time, 600) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
- else {
- // Force a call to the "time changed" notifier manually because a seek to the current time is a noop
- // so the seek will never seem to complete.
- [m_objcObserver.get() timeChanged:now];
- }
+ WebCoreAVFMovieObserver *observer = m_objcObserver.get();
+ [m_avPlayerItem.get() seekToTime:CMTimeMakeWithSeconds(time, 600) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
+ [observer seekCompleted:finished];
+ }];
setDelayCallbacks(false);
}
@@ -437,6 +434,13 @@ void MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(bool closedCap
[m_avPlayer.get() setClosedCaptionDisplayEnabled:closedCaptionsVisible];
}
+void MediaPlayerPrivateAVFoundationObjC::updateRate()
+{
+ setDelayCallbacks(true);
+ [m_avPlayer.get() setRate:requestedRate()];
+ setDelayCallbacks(false);
+}
+
float MediaPlayerPrivateAVFoundationObjC::rate() const
{
if (!metaDataAvailable())
@@ -621,12 +625,16 @@ void MediaPlayerPrivateAVFoundationObjC::getSupportedTypes(HashSet<String>& supp
MediaPlayer::SupportsType MediaPlayerPrivateAVFoundationObjC::supportsType(const String& type, const String& codecs)
{
- // Only return "IsSupported" if there is no codecs parameter for now as there is no way to ask if it supports an
- // extended MIME type until rdar://6220037 is fixed.
- if (mimeTypeCache().contains(type))
- return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
+ if (!mimeTypeCache().contains(type))
+ return MediaPlayer::IsNotSupported;
+
+ // The spec says:
+ // "Implementors are encouraged to return "maybe" unless the type can be confidently established as being supported or not."
+ if (codecs.isEmpty())
+ return MediaPlayer::MayBeSupported;
- return MediaPlayer::IsNotSupported;
+ NSString *typeString = [NSString stringWithFormat:@"%@; codecs=\"%@\"", (NSString *)type, (NSString *)codecs];
+ return [AVURLAsset isPlayableExtendedMIMEType:typeString] ? MediaPlayer::IsSupported : MediaPlayer::MayBeSupported;;
}
bool MediaPlayerPrivateAVFoundationObjC::isAvailable()
@@ -758,6 +766,14 @@ NSArray* itemKVOProperties()
m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::PlayerTimeChanged, time);
}
+- (void)seekCompleted:(BOOL)finished
+{
+ if (!m_callback)
+ return;
+
+ m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::SeekCompleted, static_cast<bool>(finished));
+}
+
- (void)didEnd:(NSNotification *)unusedNotification
{
UNUSED_PARAM(unusedNotification);
diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
index 427c7bf..8fb4c9f 100644
--- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
+++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
@@ -255,6 +255,7 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
, m_contentsLayerHasBackgroundColor(false)
, m_uncommittedChanges(NoChange)
, m_contentsScale(1)
+ , m_allowTiledLayer(true)
{
m_layer = PlatformCALayer::create(PlatformCALayer::LayerTypeWebLayer, this);
@@ -492,6 +493,17 @@ void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing)
noteLayerPropertyChanged(AcceleratesDrawingChanged);
}
+void GraphicsLayerCA::setAllowTiledLayer(bool allowTiledLayer)
+{
+ if (allowTiledLayer == m_allowTiledLayer)
+ return;
+
+ m_allowTiledLayer = allowTiledLayer;
+
+ // Handling this as a SizeChanged will cause use to switch in or out of tiled layer as needed
+ noteLayerPropertyChanged(SizeChanged);
+}
+
void GraphicsLayerCA::setBackgroundColor(const Color& color)
{
if (m_backgroundColorSet && m_backgroundColor == color)
@@ -2005,7 +2017,7 @@ FloatSize GraphicsLayerCA::constrainedSize() const
bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const
{
- if (!m_drawsContent)
+ if (!m_drawsContent || !m_allowTiledLayer)
return false;
// FIXME: catch zero-size height or width here (or earlier)?
diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
index 2c39c0a..3f2d3e4 100644
--- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
+++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
@@ -122,6 +122,9 @@ public:
virtual void syncCompositingState();
virtual void syncCompositingStateForThisLayerOnly();
+ bool allowTiledLayer() const { return m_allowTiledLayer; }
+ virtual void setAllowTiledLayer(bool b);
+
protected:
virtual void setOpacityInternal(float);
@@ -399,6 +402,8 @@ private:
float clampedContentsScaleForScale(float) const;
float m_contentsScale;
+
+ bool m_allowTiledLayer;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/ca/TransformationMatrixCA.cpp b/Source/WebCore/platform/graphics/ca/TransformationMatrixCA.cpp
index 0ef5fd0..e5ff5ba 100644
--- a/Source/WebCore/platform/graphics/ca/TransformationMatrixCA.cpp
+++ b/Source/WebCore/platform/graphics/ca/TransformationMatrixCA.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "TransformationMatrix.h"
-#if PLATFORM(CA)
+#if USE(CA)
#include "FloatConversion.h"
#include <QuartzCore/CATransform3D.h>
@@ -66,4 +66,4 @@ TransformationMatrix::operator CATransform3D() const
}
-#endif // PLATFORM(CA)
+#endif // USE(CA)
diff --git a/Source/WebCore/platform/graphics/ca/win/AbstractCACFLayerTreeHost.h b/Source/WebCore/platform/graphics/ca/win/AbstractCACFLayerTreeHost.h
new file mode 100644
index 0000000..13c6746
--- /dev/null
+++ b/Source/WebCore/platform/graphics/ca/win/AbstractCACFLayerTreeHost.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009, 2011 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 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 AbstractCACFLayerTreeHost_h
+#define AbstractCACFLayerTreeHost_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class PlatformCALayer;
+
+class AbstractCACFLayerTreeHost {
+public:
+ virtual PlatformCALayer* rootLayer() const = 0;
+ virtual void addPendingAnimatedLayer(PassRefPtr<PlatformCALayer>) = 0;
+ virtual void layerTreeDidChange() = 0;
+ virtual void flushPendingLayerChangesNow() = 0;
+
+protected:
+ virtual ~AbstractCACFLayerTreeHost() { }
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // AbstractCACFLayerTreeHost_h
diff --git a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h
index 6d91a73..507af0f 100644
--- a/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h
+++ b/Source/WebCore/platform/graphics/ca/win/CACFLayerTreeHost.h
@@ -28,6 +28,7 @@
#if USE(ACCELERATED_COMPOSITING)
+#include "AbstractCACFLayerTreeHost.h"
#include "COMPtr.h"
#include "Timer.h"
@@ -50,9 +51,7 @@ namespace WebCore {
class CACFLayerTreeHostClient;
class PlatformCALayer;
-class CACFLayerTreeHost : public RefCounted<CACFLayerTreeHost> {
- friend PlatformCALayer;
-
+class CACFLayerTreeHost : public RefCounted<CACFLayerTreeHost>, private AbstractCACFLayerTreeHost {
public:
static PassRefPtr<CACFLayerTreeHost> create();
virtual ~CACFLayerTreeHost();
@@ -66,24 +65,31 @@ public:
virtual void paint();
virtual void resize() = 0;
void flushPendingGraphicsLayerChangesSoon();
- void flushPendingLayerChangesNow();
+
+ // AbstractCACFLayerTreeHost
+ virtual void flushPendingLayerChangesNow();
protected:
CACFLayerTreeHost();
CGRect bounds() const;
- PlatformCALayer* rootLayer() const;
HWND window() const { return m_window; }
void notifyAnimationsStarted();
+ // AbstractCACFLayerTreeHost
+ virtual PlatformCALayer* rootLayer() const;
+
virtual bool createRenderer() = 0;
virtual void destroyRenderer();
virtual void contextDidChange();
private:
void initialize();
- void addPendingAnimatedLayer(PassRefPtr<PlatformCALayer>);
- void layerTreeDidChange();
+
+ // AbstractCACFLayerTreeHost
+ virtual void addPendingAnimatedLayer(PassRefPtr<PlatformCALayer>);
+ virtual void layerTreeDidChange();
+
virtual void flushContext() = 0;
virtual CFTimeInterval lastCommitTime() const = 0;
diff --git a/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp
index 3fd857b..ec2a9ff 100644
--- a/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.cpp
@@ -28,8 +28,7 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "CACFLayerTreeHost.h"
-#include "WebCoreInstanceHandle.h"
+#include "AbstractCACFLayerTreeHost.h"
#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
@@ -47,7 +46,7 @@ LayerChangesFlusher::LayerChangesFlusher()
{
}
-void LayerChangesFlusher::flushPendingLayerChangesSoon(CACFLayerTreeHost* host)
+void LayerChangesFlusher::flushPendingLayerChangesSoon(AbstractCACFLayerTreeHost* host)
{
if (!m_hostsWithChangesToFlush.add(host).second || m_hook)
return;
@@ -55,7 +54,7 @@ void LayerChangesFlusher::flushPendingLayerChangesSoon(CACFLayerTreeHost* host)
setHook();
}
-void LayerChangesFlusher::cancelPendingFlush(CACFLayerTreeHost* host)
+void LayerChangesFlusher::cancelPendingFlush(AbstractCACFLayerTreeHost* host)
{
m_hostsWithChangesToFlush.remove(host);
@@ -80,9 +79,8 @@ LRESULT LayerChangesFlusher::hookFired(int code, WPARAM wParam, LPARAM lParam)
ASSERT(m_hook);
// Calling out to the hosts can cause m_hostsWithChangesToFlush to be modified, so we copy it
- // into a Vector first. We have to hold a reference to them because otherwise they could be
- // destroyed while we're calling out to them.
- Vector<RefPtr<CACFLayerTreeHost> > hosts;
+ // into a Vector first.
+ Vector<AbstractCACFLayerTreeHost*> hosts;
copyToVector(m_hostsWithChangesToFlush, hosts);
m_hostsWithChangesToFlush.clear();
@@ -108,7 +106,7 @@ void LayerChangesFlusher::setHook()
DWORD threadID = ::GetCurrentThreadId();
- m_hook = ::SetWindowsHookExW(WH_GETMESSAGE, hookCallback, instanceHandle(), threadID);
+ m_hook = ::SetWindowsHookExW(WH_GETMESSAGE, hookCallback, 0, threadID);
ASSERT_WITH_MESSAGE(m_hook, "::SetWindowsHookExW failed with error %lu", ::GetLastError());
// Post a message to the message queue to prevent ::GetMessage from blocking, which will ensure
diff --git a/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.h b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.h
index 6a98a99..1e7ab31 100644
--- a/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.h
+++ b/Source/WebCore/platform/graphics/ca/win/LayerChangesFlusher.h
@@ -34,15 +34,15 @@
namespace WebCore {
-class CACFLayerTreeHost;
+class AbstractCACFLayerTreeHost;
class LayerChangesFlusher {
WTF_MAKE_NONCOPYABLE(LayerChangesFlusher);
public:
static LayerChangesFlusher& shared();
- void flushPendingLayerChangesSoon(CACFLayerTreeHost*);
- void cancelPendingFlush(CACFLayerTreeHost*);
+ void flushPendingLayerChangesSoon(AbstractCACFLayerTreeHost*);
+ void cancelPendingFlush(AbstractCACFLayerTreeHost*);
private:
LayerChangesFlusher();
@@ -53,7 +53,7 @@ private:
void setHook();
void removeHook();
- HashSet<CACFLayerTreeHost*> m_hostsWithChangesToFlush;
+ HashSet<AbstractCACFLayerTreeHost*> m_hostsWithChangesToFlush;
HHOOK m_hook;
bool m_isCallingHosts;
};
diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp
index b5a26f4..5d20928 100644
--- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp
@@ -29,7 +29,7 @@
#include "PlatformCALayer.h"
-#include "CACFLayerTreeHost.h"
+#include "AbstractCACFLayerTreeHost.h"
#include "Font.h"
#include "GraphicsContext.h"
#include "PlatformCALayerWinInternal.h"
@@ -65,14 +65,14 @@ static CFStringRef toCACFFilterType(PlatformCALayer::FilterType type)
}
}
-static CACFLayerTreeHost* layerTreeHostForLayer(const PlatformCALayer* layer)
+static AbstractCACFLayerTreeHost* layerTreeHostForLayer(const PlatformCALayer* layer)
{
- // We need the CACFLayerTreeHost associated with this layer, which is stored in the UserData of the CACFContext
+ // We need the AbstractCACFLayerTreeHost associated with this layer, which is stored in the UserData of the CACFContext
void* userData = wkCACFLayerGetContextUserData(layer->platformLayer());
if (!userData)
return 0;
- return static_cast<CACFLayerTreeHost*>(userData);
+ return static_cast<AbstractCACFLayerTreeHost*>(userData);
}
static PlatformCALayerWinInternal* intern(const PlatformCALayer* layer)
@@ -156,7 +156,7 @@ PlatformLayer* PlatformCALayer::platformLayer() const
PlatformCALayer* PlatformCALayer::rootLayer() const
{
- CACFLayerTreeHost* host = layerTreeHostForLayer(this);
+ AbstractCACFLayerTreeHost* host = layerTreeHostForLayer(this);
return host ? host->rootLayer() : 0;
}
@@ -167,7 +167,7 @@ void PlatformCALayer::setNeedsDisplay(const FloatRect* dirtyRect)
void PlatformCALayer::setNeedsCommit()
{
- CACFLayerTreeHost* host = layerTreeHostForLayer(this);
+ AbstractCACFLayerTreeHost* host = layerTreeHostForLayer(this);
if (host)
host->layerTreeDidChange();
}
@@ -270,7 +270,7 @@ void PlatformCALayer::addAnimationForKey(const String& key, PlatformCAAnimation*
setNeedsCommit();
// Tell the host about it so we can fire the start animation event
- CACFLayerTreeHost* host = layerTreeHostForLayer(this);
+ AbstractCACFLayerTreeHost* host = layerTreeHostForLayer(this);
if (host)
host->addPendingAnimatedLayer(this);
}
@@ -283,7 +283,7 @@ void PlatformCALayer::removeAnimationForKey(const String& key)
RetainPtr<CFStringRef> s(AdoptCF, key.createCFString());
CACFLayerRemoveAnimation(m_layer.get(), s.get());
- // We don't "remove" a layer from CACFLayerTreeHost when it loses an animation.
+ // We don't "remove" a layer from AbstractCACFLayerTreeHost when it loses an animation.
// There may be other active animations on the layer and if an animation
// callback is fired on a layer without any animations no harm is done.
diff --git a/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.cpp b/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.cpp
index e672c2d..c4c3374 100644
--- a/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.cpp
+++ b/Source/WebCore/platform/graphics/ca/win/WKCACFViewLayerTreeHost.cpp
@@ -31,6 +31,7 @@
#include "PlatformCALayer.h"
#include "SoftLinking.h"
#include <wtf/CurrentTime.h>
+#include <wtf/Threading.h>
typedef struct _CACFLayer* CACFLayerRef;
@@ -42,7 +43,13 @@ SOFT_LINK_DEBUG_LIBRARY(WebKitQuartzCoreAdditions)
SOFT_LINK_LIBRARY(WebKitQuartzCoreAdditions)
#endif
-SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewCreate, WKCACFViewRef, __cdecl, (), ())
+enum WKCACFViewDrawingDestination {
+ kWKCACFViewDrawingDestinationWindow = 0,
+ kWKCACFViewDrawingDestinationImage,
+};
+typedef enum WKCACFViewDrawingDestination WKCACFViewDrawingDestination;
+
+SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewCreate, WKCACFViewRef, __cdecl, (WKCACFViewDrawingDestination destination), (destination))
SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewSetLayer, void, __cdecl, (WKCACFViewRef view, CACFLayerRef layer), (view, layer))
SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewUpdate, void, __cdecl, (WKCACFViewRef view, HWND window, const CGRect* bounds), (view, window, bounds))
SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewCanDraw, bool, __cdecl, (WKCACFViewRef view), (view))
@@ -63,7 +70,7 @@ PassRefPtr<WKCACFViewLayerTreeHost> WKCACFViewLayerTreeHost::create()
}
WKCACFViewLayerTreeHost::WKCACFViewLayerTreeHost()
- : m_view(AdoptCF, WKCACFViewCreate())
+ : m_view(AdoptCF, WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow))
, m_viewNeedsUpdate(true)
{
}
@@ -98,6 +105,12 @@ void WKCACFViewLayerTreeHost::contextDidChangeCallback(WKCACFViewRef view, void*
void WKCACFViewLayerTreeHost::contextDidChange()
{
+ // This should only be called on a background thread when no changes have actually
+ // been committed to the context, eg. when a video frame has been added to an image
+ // queue, so return without triggering animations etc.
+ if (!isMainThread())
+ return;
+
// Tell the WKCACFView to start rendering now that we have some contents to render.
updateViewIfNeeded();
diff --git a/Source/WebCore/platform/graphics/cairo/CairoPath.h b/Source/WebCore/platform/graphics/cairo/CairoPath.h
deleted file mode 100644
index da7affb..0000000
--- a/Source/WebCore/platform/graphics/cairo/CairoPath.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
- Copyright (C) 2010 Igalia S.L.
-
- 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
- aint 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.
-*/
-
-#ifndef CairoPath_h
-#define CairoPath_h
-
-#include <cairo.h>
-
-namespace WebCore {
-
-// This is necessary since cairo_path_fixed_t isn't exposed in Cairo's public API.
-class CairoPath {
-public:
- CairoPath()
- {
- static cairo_surface_t* pathSurface = cairo_image_surface_create(CAIRO_FORMAT_A8, 1, 1);
- m_cr = cairo_create(pathSurface);
- }
-
- ~CairoPath()
- {
- cairo_destroy(m_cr);
- }
-
- cairo_t* context() { return m_cr; }
-
-private:
- cairo_t* m_cr;
-};
-
-} // namespace WebCore
-
-#endif // CairoPath_h
diff --git a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp b/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
index ee159a1..758bce9 100644
--- a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
+++ b/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp
@@ -27,13 +27,13 @@
#include "CairoUtilities.h"
#include "AffineTransform.h"
-#include "CairoPath.h"
#include "Color.h"
#include "FloatPoint.h"
#include "FloatRect.h"
#include "IntRect.h"
#include "OwnPtrCairo.h"
#include "Path.h"
+#include "PlatformPathCairo.h"
#include "RefPtrCairo.h"
#include <wtf/Vector.h>
diff --git a/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp b/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
index 0f90ce4..d968ee9 100644
--- a/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
@@ -42,11 +42,10 @@ using WTF::max;
namespace WebCore {
-static cairo_surface_t* scratchBuffer = 0;
+static RefPtr<cairo_surface_t> gScratchBuffer;
static void purgeScratchBuffer()
{
- cairo_surface_destroy(scratchBuffer);
- scratchBuffer = 0;
+ gScratchBuffer.clear();
}
// ContextShadow needs a scratch image as the buffer for the blur filter.
@@ -68,20 +67,20 @@ static cairo_surface_t* getScratchBuffer(const IntSize& size)
{
int width = size.width();
int height = size.height();
- int scratchWidth = scratchBuffer ? cairo_image_surface_get_width(scratchBuffer) : 0;
- int scratchHeight = scratchBuffer ? cairo_image_surface_get_height(scratchBuffer) : 0;
+ int scratchWidth = gScratchBuffer.get() ? cairo_image_surface_get_width(gScratchBuffer.get()) : 0;
+ int scratchHeight = gScratchBuffer.get() ? cairo_image_surface_get_height(gScratchBuffer.get()) : 0;
// We do not need to recreate the buffer if the current buffer is large enough.
- if (scratchBuffer && scratchWidth >= width && scratchHeight >= height)
- return scratchBuffer;
+ if (gScratchBuffer.get() && scratchWidth >= width && scratchHeight >= height)
+ return gScratchBuffer.get();
purgeScratchBuffer();
// Round to the nearest 32 pixels so we do not grow the buffer for similar sized requests.
width = (1 + (width >> 5)) << 5;
height = (1 + (height >> 5)) << 5;
- scratchBuffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
- return scratchBuffer;
+ gScratchBuffer = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height));
+ return gScratchBuffer.get();
}
PlatformContext ContextShadow::beginShadowLayer(GraphicsContext* context, const FloatRect& layerArea)
diff --git a/Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h b/Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h
index b90bb8c..3a49d5c 100644
--- a/Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h
+++ b/Source/WebCore/platform/graphics/cairo/DrawErrorUnderline.h
@@ -21,7 +21,7 @@
*
*/
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
#ifndef DrawErrorUnderline_h
#define DrawErrorUnderline_h
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
new file mode 100644
index 0000000..c90d8ab
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * 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 "GraphicsContext3D.h"
+#include "PlatformContextCairo.h"
+
+#if ENABLE(WEBGL)
+
+#include "Image.h"
+#include "RefPtrCairo.h"
+#include <cairo.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector)
+{
+ if (!image)
+ return false;
+ // We need this to stay in scope because the native image is just a shallow copy of the data.
+ ImageSource decoder(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied,
+ ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
+ AlphaOp alphaOp = AlphaDoNothing;
+ RefPtr<cairo_surface_t> imageSurface;
+ if (image->data()) {
+ decoder.setData(image->data(), true);
+ if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
+ return false;
+ imageSurface = decoder.createFrameAtIndex(0);
+ } else {
+ imageSurface = image->nativeImageForCurrentFrame();
+ if (!premultiplyAlpha)
+ alphaOp = AlphaDoUnmultiply;
+ }
+
+ if (!imageSurface)
+ return false;
+
+ int width = cairo_image_surface_get_width(imageSurface.get());
+ int height = cairo_image_surface_get_height(imageSurface.get());
+ if (!width || !height)
+ return false;
+
+ if (cairo_image_surface_get_format(imageSurface.get()) != CAIRO_FORMAT_ARGB32)
+ return false;
+
+ unsigned int srcUnpackAlignment = 1;
+ size_t bytesPerRow = cairo_image_surface_get_stride(imageSurface.get());
+ size_t bitsPerPixel = 32;
+ unsigned int padding = bytesPerRow - bitsPerPixel / 8 * width;
+ if (padding) {
+ srcUnpackAlignment = padding + 1;
+ while (bytesPerRow % srcUnpackAlignment)
+ ++srcUnpackAlignment;
+ }
+
+ outputVector.resize(width * height * 4);
+ return packPixels(cairo_image_surface_get_data(imageSurface.get()), SourceFormatBGRA8,
+ width, height, srcUnpackAlignment, format, type, alphaOp, outputVector.data());
+}
+
+void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context)
+{
+ if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context)
+ return;
+
+ cairo_t *cr = context->cr();
+ context->save();
+
+ cairo_rectangle(cr, 0, 0, canvasWidth, canvasHeight);
+ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cr);
+
+ RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data(
+ const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageWidth, imageHeight, imageWidth * 4));
+
+ // OpenGL keeps the pixels stored bottom up, so we need to flip the image here.
+ cairo_translate(cr, 0, imageHeight);
+ cairo_scale(cr, 1, -1);
+
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ cairo_set_source_surface(cr, imageSurface.get(), 0, 0);
+ cairo_rectangle(cr, 0, 0, canvasWidth, -canvasHeight);
+
+ cairo_fill(cr);
+ context->restore();
+}
+
+void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 0fc94df..4cd0844 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -32,10 +32,9 @@
#include "config.h"
#include "GraphicsContext.h"
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
#include "AffineTransform.h"
-#include "CairoPath.h"
#include "CairoUtilities.h"
#include "ContextShadow.h"
#include "FloatConversion.h"
@@ -48,6 +47,7 @@
#include "Path.h"
#include "Pattern.h"
#include "PlatformContextCairo.h"
+#include "PlatformPathCairo.h"
#include "RefPtrCairo.h"
#include "SimpleFontData.h"
#include <cairo.h>
@@ -201,8 +201,9 @@ static void strokeCurrentCairoPath(GraphicsContext* context, cairo_t* cairoCont
}
GraphicsContext::GraphicsContext(cairo_t* cr)
+ : m_updatingControlTints(false)
{
- m_data = new GraphicsContextPlatformPrivate(new PlatformContextCairo(cr));
+ m_data = new GraphicsContextPlatformPrivateToplevel(new PlatformContextCairo(cr));
}
void GraphicsContext::platformInit(PlatformContextCairo* platformContext)
@@ -234,24 +235,13 @@ PlatformContextCairo* GraphicsContext::platformContext() const
void GraphicsContext::savePlatformState()
{
- cairo_save(platformContext()->cr());
+ platformContext()->save();
m_data->save();
m_data->shadowStack.append(m_data->shadow);
- m_data->maskImageStack.append(ImageMaskInformation());
}
void GraphicsContext::restorePlatformState()
{
- cairo_t* cr = platformContext()->cr();
-
- const ImageMaskInformation& maskInformation = m_data->maskImageStack.last();
- if (maskInformation.isValid()) {
- const FloatRect& maskRect = maskInformation.maskRect();
- cairo_pop_group_to_source(cr);
- cairo_mask_surface(cr, maskInformation.maskSurface(), maskRect.x(), maskRect.y());
- }
- m_data->maskImageStack.removeLast();
-
if (m_data->shadowStack.isEmpty())
m_data->shadow = ContextShadow();
else {
@@ -259,7 +249,7 @@ void GraphicsContext::restorePlatformState()
m_data->shadowStack.removeLast();
}
- cairo_restore(cr);
+ platformContext()->restore();
m_data->restore();
}
@@ -765,7 +755,7 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& origin, float wi
cairo_restore(cr);
}
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect, RoundingMode)
{
FloatRect result;
double x = frect.x();
@@ -1190,33 +1180,6 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const
return InterpolationDefault;
}
-void GraphicsContext::pushImageMask(cairo_surface_t* surface, const FloatRect& rect)
-{
- // We must call savePlatformState at least once before we can use image masking,
- // since we actually apply the mask in restorePlatformState.
- ASSERT(!m_data->maskImageStack.isEmpty());
- m_data->maskImageStack.last().update(surface, rect);
-
- // Cairo doesn't support the notion of an image clip, so we push a group here
- // and then paint it to the surface with an image mask (which is an immediate
- // operation) during restorePlatformState.
-
- // We want to allow the clipped elements to composite with the surface as it
- // is now, but they are isolated in another group. To make this work, we're
- // going to blit the current surface contents onto the new group once we push it.
- cairo_t* cr = platformContext()->cr();
- cairo_surface_t* currentTarget = cairo_get_target(cr);
- cairo_surface_flush(currentTarget);
-
- // Pushing a new group ensures that only things painted after this point are clipped.
- cairo_push_group(cr);
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-
- cairo_set_source_surface(cr, currentTarget, 0, 0);
- cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- cairo_fill(cr);
-}
-
} // namespace WebCore
-#endif // PLATFORM(CAIRO)
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
index 2bc290b..8fd056d 100644
--- a/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
@@ -47,25 +47,6 @@ typedef struct _GdkExposeEvent GdkExposeEvent;
namespace WebCore {
-// In Cairo image masking is immediate, so to emulate image clipping we must save masking
-// details as part of the context state and apply it during platform restore.
-class ImageMaskInformation {
-public:
- void update(cairo_surface_t* maskSurface, const FloatRect& maskRect)
- {
- m_maskSurface = maskSurface;
- m_maskRect = maskRect;
- }
-
- bool isValid() const { return m_maskSurface; }
- cairo_surface_t* maskSurface() const { return m_maskSurface.get(); }
- const FloatRect& maskRect() const { return m_maskRect; }
-
-private:
- RefPtr<cairo_surface_t> m_maskSurface;
- FloatRect m_maskRect;
-};
-
class GraphicsContextPlatformPrivate {
public:
GraphicsContextPlatformPrivate(PlatformContextCairo* newPlatformContext)
@@ -81,7 +62,7 @@ public:
{
}
- ~GraphicsContextPlatformPrivate()
+ virtual ~GraphicsContextPlatformPrivate()
{
}
@@ -121,7 +102,6 @@ public:
Vector<float> layers;
ContextShadow shadow;
Vector<ContextShadow> shadowStack;
- Vector<ImageMaskInformation> maskImageStack;
#if PLATFORM(GTK)
GdkEventExpose* expose;
@@ -142,7 +122,7 @@ public:
{
}
- ~GraphicsContextPlatformPrivateToplevel()
+ virtual ~GraphicsContextPlatformPrivateToplevel()
{
delete platformContext;
}
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 1d5d492..8aa6531 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -55,11 +55,10 @@ static inline cairo_surface_t* copySurface(cairo_surface_t* surface)
int height = cairo_image_surface_get_height(surface);
cairo_surface_t* newsurface = cairo_image_surface_create(format, width, height);
- cairo_t* cr = cairo_create(newsurface);
- cairo_set_source_surface(cr, surface, 0, 0);
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
- cairo_paint(cr);
- cairo_destroy(cr);
+ RefPtr<cairo_t> cr = adoptRef(cairo_create(newsurface));
+ cairo_set_source_surface(cr.get(), surface, 0, 0);
+ cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE);
+ cairo_paint(cr.get());
return newsurface;
}
@@ -117,7 +116,7 @@ PassRefPtr<Image> ImageBuffer::copyImage() const
void ImageBuffer::clip(GraphicsContext* context, const FloatRect& maskRect) const
{
- context->pushImageMask(m_data.m_surface, maskRect);
+ context->platformContext()->pushImageMask(m_data.m_surface, maskRect);
}
void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferData.h b/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h
index 42867d1..5ca7262 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h
@@ -23,9 +23,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ImageBufferData_h
-#define ImageBufferData_h
-
#include "PlatformContextCairo.h"
typedef struct _cairo_surface cairo_surface_t;
@@ -42,6 +39,4 @@ public:
PlatformContextCairo m_platformContext;
};
-} // namespace WebCore
-
-#endif // ImageBufferData_h
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
index d3a52ce..ce7d8b2 100644
--- a/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -28,7 +28,7 @@
#include "config.h"
#include "BitmapImage.h"
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
#include "AffineTransform.h"
#include "CairoUtilities.h"
@@ -205,4 +205,4 @@ void BitmapImage::checkForSolidColor()
}
-#endif // PLATFORM(CAIRO)
+#endif // USE(CAIRO)
diff --git a/Source/WebCore/platform/graphics/cairo/OpenGLShims.cpp b/Source/WebCore/platform/graphics/cairo/OpenGLShims.cpp
new file mode 100644
index 0000000..92d79f9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/OpenGLShims.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#if ENABLE(WEBGL)
+
+#define DISABLE_SHIMS
+#include "OpenGLShims.h"
+
+#include <dlfcn.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+#define ASSIGN_FUNCTION_TABLE_ENTRY(FunctionName, success) \
+ openGLFunctionTable()->FunctionName = reinterpret_cast<FunctionName##Type>(lookupOpenGLFunctionAddress(#FunctionName, success))
+
+namespace WebCore {
+
+typedef void* (*glGetProcAddressType) (const char* procName);
+static void* getProcAddress(const char* procName)
+{
+ static bool initialized = false;
+ static glGetProcAddressType getProcAddressFunction = 0;
+
+ if (!initialized) {
+ getProcAddressFunction = reinterpret_cast<glGetProcAddressType>(dlsym(RTLD_DEFAULT, "glXGetProcAddress"));
+ if (!getProcAddressFunction)
+ getProcAddressFunction = reinterpret_cast<glGetProcAddressType>(dlsym(RTLD_DEFAULT, "glXGetProcAddressARB"));
+ }
+
+ if (!getProcAddressFunction)
+ return dlsym(RTLD_DEFAULT, procName);
+ return getProcAddressFunction(procName);
+}
+
+static void* lookupOpenGLFunctionAddress(const char* functionName, bool& success)
+{
+ if (!success)
+ return 0;
+
+ void* target = getProcAddress(functionName);
+ if (target)
+ return target;
+
+ String fullFunctionName(functionName);
+ fullFunctionName.append("ARB");
+ target = getProcAddress(fullFunctionName.utf8().data());
+ if (target)
+ return target;
+
+ fullFunctionName = functionName;
+ fullFunctionName.append("EXT");
+ target = getProcAddress(fullFunctionName.utf8().data());
+
+ // A null address is still a failure case.
+ if (!target)
+ success = false;
+
+ return target;
+}
+
+OpenGLFunctionTable* openGLFunctionTable()
+{
+ static OpenGLFunctionTable table;
+ return &table;
+}
+
+bool initializeOpenGLShims()
+{
+ static bool success = true;
+ static bool initialized = false;
+ if (initialized)
+ return success;
+
+ initialized = true;
+ ASSIGN_FUNCTION_TABLE_ENTRY(glActiveTexture, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glAttachShader, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBindAttribLocation, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBindBuffer, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBindFramebuffer, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBindRenderbuffer, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBlendColor, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBlendEquation, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBlendEquationSeparate, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBlendFuncSeparate, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBlitFramebuffer, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBufferData, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glBufferSubData, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glCheckFramebufferStatus, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glCompileShader, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glCreateProgram, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glCreateShader, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteBuffers, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteFramebuffers, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteProgram, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteRenderbuffers, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteShader, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glDetachShader, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glDisableVertexAttribArray, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glEnableVertexAttribArray, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glFramebufferRenderbuffer, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glFramebufferTexture2D, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGenBuffers, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGenerateMipmap, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGenFramebuffers, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGenRenderbuffers, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetActiveAttrib, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetActiveUniform, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetAttachedShaders, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetAttribLocation, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetBufferParameteriv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetFramebufferAttachmentParameteriv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetProgramInfoLog, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetProgramiv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetRenderbufferParameteriv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetShaderInfoLog, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetShaderiv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetShaderSource, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetUniformfv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetUniformiv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetUniformLocation, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetVertexAttribfv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetVertexAttribiv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glGetVertexAttribPointerv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glIsBuffer, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glIsFramebuffer, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glIsProgram, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glIsRenderbuffer, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glIsShader, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glLinkProgram, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glRenderbufferStorage, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glRenderbufferStorageMultisample, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glSampleCoverage, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glShaderSource, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glStencilFuncSeparate, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glStencilMaskSeparate, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glStencilOpSeparate, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1f, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1i, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1iv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2f, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2i, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2iv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3f, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3i, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3iv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4f, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4i, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4iv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniformMatrix2fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniformMatrix3fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUniformMatrix4fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glUseProgram, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glValidateProgram, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib1f, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib1fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib2f, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib2fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib3f, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib3fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib4f, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib4fv, success);
+ ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttribPointer, success);
+
+ if (!success)
+ LOG_ERROR("Could not initialize OpenGL shims");
+ return success;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/cairo/OpenGLShims.h b/Source/WebCore/platform/graphics/cairo/OpenGLShims.h
new file mode 100644
index 0000000..a431b03
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/OpenGLShims.h
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2010 Tieto Corporation.
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <GL/gl.h>
+
+typedef struct _OpenGLFunctionTable OpenGLFunctionTable;
+
+namespace WebCore {
+bool initializeOpenGLShims();
+OpenGLFunctionTable* openGLFunctionTable();
+}
+
+typedef void (*glActiveTextureType) (GLenum);
+typedef void (*glAttachShaderType) (GLuint, GLuint);
+typedef void (*glBindAttribLocationType) (GLuint, GLuint, const char*);
+typedef void (*glBindBufferType) (GLenum, GLuint);
+typedef void (*glBindFramebufferType) (GLenum, GLuint);
+typedef void (*glBindRenderbufferType) (GLenum, GLuint);
+typedef void (*glBlendColorType) (GLclampf, GLclampf, GLclampf, GLclampf);
+typedef void (*glBlendEquationType) (GLenum);
+typedef void (*glBlendEquationSeparateType)(GLenum, GLenum);
+typedef void (*glBlendFuncSeparateType)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (*glBlitFramebufferType) (GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);
+typedef void (*glBufferDataType) (GLenum, GLsizeiptr, const GLvoid*, GLenum);
+typedef void (*glBufferSubDataType) (GLenum, GLintptr, GLsizeiptr, const GLvoid*);
+typedef GLenum (*glCheckFramebufferStatusType) (GLenum);
+typedef void (*glCompileShaderType) (GLuint);
+typedef GLuint (*glCreateProgramType) ();
+typedef GLuint (*glCreateShaderType) (GLenum);
+typedef void (*glDeleteBuffersType) (GLsizei, const GLuint*);
+typedef void (*glDeleteFramebuffersType) (GLsizei n, const GLuint*);
+typedef void (*glDeleteProgramType) (GLuint);
+typedef void (*glDeleteRenderbuffersType) (GLsizei n, const GLuint*);
+typedef void (*glDeleteShaderType) (GLuint);
+typedef void (*glDetachShaderType) (GLuint, GLuint);
+typedef void (*glDisableVertexAttribArrayType) (GLuint);
+typedef void (*glEnableVertexAttribArrayType) (GLuint);
+typedef void (*glFramebufferRenderbufferType) (GLenum, GLenum, GLenum, GLuint);
+typedef void (*glFramebufferTexture2DType) (GLenum, GLenum, GLenum, GLuint, GLint);
+typedef void (*glGenBuffersType) (GLsizei, GLuint*);
+typedef void (*glGenerateMipmapType) (GLenum target);
+typedef void (*glGenFramebuffersType) (GLsizei, GLuint*);
+typedef void (*glGenRenderbuffersType) (GLsizei, GLuint*);
+typedef void (*glGetActiveAttribType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
+typedef void (*glGetActiveUniformType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*);
+typedef void (*glGetAttachedShadersType) (GLuint, GLsizei, GLsizei*, GLuint*);
+typedef GLint (*glGetAttribLocationType) (GLuint, const char*);
+typedef void (*glGetBufferParameterivType) (GLenum, GLenum, GLint*);
+typedef void (*glGetFramebufferAttachmentParameterivType) (GLenum, GLenum, GLenum, GLint* params);
+typedef void (*glGetProgramInfoLogType) (GLuint, GLsizei, GLsizei*, char*);
+typedef void (*glGetProgramivType) (GLuint, GLenum, GLint*);
+typedef void (*glGetRenderbufferParameterivType) (GLenum, GLenum, GLint*);
+typedef void (*glGetShaderInfoLogType) (GLuint, GLsizei, GLsizei*, char*);
+typedef void (*glGetShaderivType) (GLuint, GLenum, GLint*);
+typedef void (*glGetShaderSourceType) (GLuint, GLsizei, GLsizei*, char*);
+typedef GLint (*glGetUniformLocationType) (GLuint, const char*);
+typedef void (*glGetUniformfvType) (GLuint, GLint, GLfloat*);
+typedef void (*glGetUniformivType) (GLuint, GLint, GLint*);
+typedef void (*glGetVertexAttribfvType) (GLuint, GLenum, GLfloat*);
+typedef void (*glGetVertexAttribivType) (GLuint, GLenum, GLint*);
+typedef void (*glGetVertexAttribPointervType) (GLuint, GLenum, GLvoid**);
+typedef GLboolean (*glIsBufferType) (GLuint);
+typedef GLboolean (*glIsFramebufferType) (GLuint);
+typedef GLboolean (*glIsProgramType) (GLuint);
+typedef GLboolean (*glIsRenderbufferType) (GLuint);
+typedef GLboolean (*glIsShaderType) (GLuint);
+typedef void (*glLinkProgramType) (GLuint);
+typedef void (*glRenderbufferStorageType) (GLenum, GLenum, GLsizei, GLsizei);
+typedef void (*glRenderbufferStorageMultisampleType) (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+typedef void (*glSampleCoverageType) (GLclampf, GLboolean);
+typedef void (*glShaderSourceType) (GLuint, GLsizei, const char**, const GLint*);
+typedef void (*glStencilFuncSeparateType) (GLenum, GLenum, GLint, GLuint);
+typedef void (*glStencilMaskSeparateType) (GLenum, GLuint);
+typedef void (*glStencilOpSeparateType) (GLenum, GLenum, GLenum, GLenum);
+typedef void (*glUniform1fType) (GLint, GLfloat);
+typedef void (*glUniform1fvType) (GLint, GLsizei, const GLfloat*);
+typedef void (*glUniform1iType) (GLint, GLint);
+typedef void (*glUniform1ivType) (GLint, GLsizei, const GLint*);
+typedef void (*glUniform2fType) (GLint, GLfloat, GLfloat);
+typedef void (*glUniform2fvType) (GLint, GLsizei, const GLfloat*);
+typedef void (*glUniform2iType) (GLint, GLint, GLint);
+typedef void (*glUniform2ivType) (GLint, GLsizei, const GLint*);
+typedef void (*glUniform3fType) (GLint, GLfloat, GLfloat, GLfloat);
+typedef void (*glUniform3fvType) (GLint, GLsizei, const GLfloat*);
+typedef void (*glUniform3iType) (GLint, GLint, GLint, GLint);
+typedef void (*glUniform3ivType) (GLint, GLsizei, const GLint*);
+typedef void (*glUniform4fType) (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (*glUniform4fvType) (GLint, GLsizei, const GLfloat*);
+typedef void (*glUniform4iType) (GLint, GLint, GLint, GLint, GLint);
+typedef void (*glUniform4ivType) (GLint, GLsizei, const GLint*);
+typedef void (*glUniformMatrix2fvType) (GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (*glUniformMatrix3fvType) (GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (*glUniformMatrix4fvType) (GLint, GLsizei, GLboolean, const GLfloat*);
+typedef void (*glUseProgramType) (GLuint);
+typedef void (*glValidateProgramType) (GLuint);
+typedef void (*glVertexAttrib1fType) (GLuint, const GLfloat);
+typedef void (*glVertexAttrib1fvType) (GLuint, const GLfloat*);
+typedef void (*glVertexAttrib2fType) (GLuint, const GLfloat, const GLfloat);
+typedef void (*glVertexAttrib2fvType) (GLuint, const GLfloat*);
+typedef void (*glVertexAttrib3fType) (GLuint, const GLfloat, const GLfloat, const GLfloat);
+typedef void (*glVertexAttrib3fvType) (GLuint, const GLfloat*);
+typedef void (*glVertexAttrib4fType) (GLuint, const GLfloat, const GLfloat, const GLfloat, const GLfloat);
+typedef void (*glVertexAttrib4fvType) (GLuint, const GLfloat*);
+typedef void (*glVertexAttribPointerType) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*);
+
+#define FUNCTION_TABLE_ENTRY(FunctionName) FunctionName##Type FunctionName
+
+typedef struct _OpenGLFunctionTable {
+ FUNCTION_TABLE_ENTRY(glActiveTexture);
+ FUNCTION_TABLE_ENTRY(glAttachShader);
+ FUNCTION_TABLE_ENTRY(glBindAttribLocation);
+ FUNCTION_TABLE_ENTRY(glBindBuffer);
+ FUNCTION_TABLE_ENTRY(glBindFramebuffer);
+ FUNCTION_TABLE_ENTRY(glBindRenderbuffer);
+ FUNCTION_TABLE_ENTRY(glBlendColor);
+ FUNCTION_TABLE_ENTRY(glBlendEquation);
+ FUNCTION_TABLE_ENTRY(glBlendEquationSeparate);
+ FUNCTION_TABLE_ENTRY(glBlendFuncSeparate);
+ FUNCTION_TABLE_ENTRY(glBlitFramebuffer);
+ FUNCTION_TABLE_ENTRY(glBufferData);
+ FUNCTION_TABLE_ENTRY(glBufferSubData);
+ FUNCTION_TABLE_ENTRY(glCheckFramebufferStatus);
+ FUNCTION_TABLE_ENTRY(glCompileShader);
+ FUNCTION_TABLE_ENTRY(glCreateProgram);
+ FUNCTION_TABLE_ENTRY(glCreateShader);
+ FUNCTION_TABLE_ENTRY(glDeleteBuffers);
+ FUNCTION_TABLE_ENTRY(glDeleteFramebuffers);
+ FUNCTION_TABLE_ENTRY(glDeleteProgram);
+ FUNCTION_TABLE_ENTRY(glDeleteRenderbuffers);
+ FUNCTION_TABLE_ENTRY(glDeleteShader);
+ FUNCTION_TABLE_ENTRY(glDetachShader);
+ FUNCTION_TABLE_ENTRY(glDisableVertexAttribArray);
+ FUNCTION_TABLE_ENTRY(glEnableVertexAttribArray);
+ FUNCTION_TABLE_ENTRY(glFramebufferRenderbuffer);
+ FUNCTION_TABLE_ENTRY(glFramebufferTexture2D);
+ FUNCTION_TABLE_ENTRY(glGenBuffers);
+ FUNCTION_TABLE_ENTRY(glGenerateMipmap);
+ FUNCTION_TABLE_ENTRY(glGenFramebuffers);
+ FUNCTION_TABLE_ENTRY(glGenRenderbuffers);
+ FUNCTION_TABLE_ENTRY(glGetActiveAttrib);
+ FUNCTION_TABLE_ENTRY(glGetActiveUniform);
+ FUNCTION_TABLE_ENTRY(glGetAttachedShaders);
+ FUNCTION_TABLE_ENTRY(glGetAttribLocation);
+ FUNCTION_TABLE_ENTRY(glGetBufferParameteriv);
+ FUNCTION_TABLE_ENTRY(glGetFramebufferAttachmentParameteriv);
+ FUNCTION_TABLE_ENTRY(glGetProgramInfoLog);
+ FUNCTION_TABLE_ENTRY(glGetProgramiv);
+ FUNCTION_TABLE_ENTRY(glGetRenderbufferParameteriv);
+ FUNCTION_TABLE_ENTRY(glGetShaderInfoLog);
+ FUNCTION_TABLE_ENTRY(glGetShaderiv);
+ FUNCTION_TABLE_ENTRY(glGetShaderSource);
+ FUNCTION_TABLE_ENTRY(glGetUniformfv);
+ FUNCTION_TABLE_ENTRY(glGetUniformiv);
+ FUNCTION_TABLE_ENTRY(glGetUniformLocation);
+ FUNCTION_TABLE_ENTRY(glGetVertexAttribfv);
+ FUNCTION_TABLE_ENTRY(glGetVertexAttribiv);
+ FUNCTION_TABLE_ENTRY(glGetVertexAttribPointerv);
+ FUNCTION_TABLE_ENTRY(glIsBuffer);
+ FUNCTION_TABLE_ENTRY(glIsFramebuffer);
+ FUNCTION_TABLE_ENTRY(glIsProgram);
+ FUNCTION_TABLE_ENTRY(glIsRenderbuffer);
+ FUNCTION_TABLE_ENTRY(glIsShader);
+ FUNCTION_TABLE_ENTRY(glLinkProgram);
+ FUNCTION_TABLE_ENTRY(glRenderbufferStorage);
+ FUNCTION_TABLE_ENTRY(glRenderbufferStorageMultisample);
+ FUNCTION_TABLE_ENTRY(glSampleCoverage);
+ FUNCTION_TABLE_ENTRY(glShaderSource);
+ FUNCTION_TABLE_ENTRY(glStencilFuncSeparate);
+ FUNCTION_TABLE_ENTRY(glStencilMaskSeparate);
+ FUNCTION_TABLE_ENTRY(glStencilOpSeparate);
+ FUNCTION_TABLE_ENTRY(glUniform1f);
+ FUNCTION_TABLE_ENTRY(glUniform1fv);
+ FUNCTION_TABLE_ENTRY(glUniform1i);
+ FUNCTION_TABLE_ENTRY(glUniform1iv);
+ FUNCTION_TABLE_ENTRY(glUniform2f);
+ FUNCTION_TABLE_ENTRY(glUniform2fv);
+ FUNCTION_TABLE_ENTRY(glUniform2i);
+ FUNCTION_TABLE_ENTRY(glUniform2iv);
+ FUNCTION_TABLE_ENTRY(glUniform3f);
+ FUNCTION_TABLE_ENTRY(glUniform3fv);
+ FUNCTION_TABLE_ENTRY(glUniform3i);
+ FUNCTION_TABLE_ENTRY(glUniform3iv);
+ FUNCTION_TABLE_ENTRY(glUniform4f);
+ FUNCTION_TABLE_ENTRY(glUniform4fv);
+ FUNCTION_TABLE_ENTRY(glUniform4i);
+ FUNCTION_TABLE_ENTRY(glUniform4iv);
+ FUNCTION_TABLE_ENTRY(glUniformMatrix2fv);
+ FUNCTION_TABLE_ENTRY(glUniformMatrix3fv);
+ FUNCTION_TABLE_ENTRY(glUniformMatrix4fv);
+ FUNCTION_TABLE_ENTRY(glUseProgram);
+ FUNCTION_TABLE_ENTRY(glValidateProgram);
+ FUNCTION_TABLE_ENTRY(glVertexAttrib1f);
+ FUNCTION_TABLE_ENTRY(glVertexAttrib1fv);
+ FUNCTION_TABLE_ENTRY(glVertexAttrib2f);
+ FUNCTION_TABLE_ENTRY(glVertexAttrib2fv);
+ FUNCTION_TABLE_ENTRY(glVertexAttrib3f);
+ FUNCTION_TABLE_ENTRY(glVertexAttrib3fv);
+ FUNCTION_TABLE_ENTRY(glVertexAttrib4f);
+ FUNCTION_TABLE_ENTRY(glVertexAttrib4fv);
+ FUNCTION_TABLE_ENTRY(glVertexAttribPointer);
+} OpenGLFunctionTable;
+
+// We disable the shims for OpenGLShims.cpp, so that we can set them.
+#ifndef DISABLE_SHIMS
+#define LOOKUP_GL_FUNCTION(Function) WebCore::openGLFunctionTable()->Function
+#define glActiveTexture LOOKUP_GL_FUNCTION(glActiveTexture)
+#define glAttachShader LOOKUP_GL_FUNCTION(glAttachShader)
+#define glBindAttribLocation LOOKUP_GL_FUNCTION(glBindAttribLocation)
+#define glBindBuffer LOOKUP_GL_FUNCTION(glBindBuffer)
+#define glBindFramebufferEXT LOOKUP_GL_FUNCTION(glBindFramebuffer)
+#define glBindRenderbufferEXT LOOKUP_GL_FUNCTION(glBindRenderbuffer)
+#define glBlendColor LOOKUP_GL_FUNCTION(glBlendColor)
+#define glBlendEquation LOOKUP_GL_FUNCTION(glBlendEquation)
+#define glBlendEquationSeparate LOOKUP_GL_FUNCTION(glBlendEquationSeparate)
+#define glBlendFuncSeparate LOOKUP_GL_FUNCTION(glBlendFuncSeparate)
+#define glBlitFramebufferEXT LOOKUP_GL_FUNCTION(glBlitFramebuffer)
+#define glBufferData LOOKUP_GL_FUNCTION(glBufferData)
+#define glBufferSubData LOOKUP_GL_FUNCTION(glBufferSubData)
+#define glCheckFramebufferStatusEXT LOOKUP_GL_FUNCTION(glCheckFramebufferStatus)
+#define glCompileShader LOOKUP_GL_FUNCTION(glCompileShader)
+#define glCreateProgram LOOKUP_GL_FUNCTION(glCreateProgram)
+#define glCreateShader LOOKUP_GL_FUNCTION(glCreateShader)
+#define glDeleteBuffers LOOKUP_GL_FUNCTION(glDeleteBuffers)
+#define glDeleteFramebuffersEXT LOOKUP_GL_FUNCTION(glDeleteFramebuffers)
+#define glDeleteProgram LOOKUP_GL_FUNCTION(glDeleteProgram)
+#define glDeleteRenderbuffersEXT LOOKUP_GL_FUNCTION(glDeleteRenderbuffers)
+#define glDeleteShader LOOKUP_GL_FUNCTION(glDeleteShader)
+#define glDetachShader LOOKUP_GL_FUNCTION(glDetachShader)
+#define glDisableVertexAttribArray LOOKUP_GL_FUNCTION(glDisableVertexAttribArray)
+#define glEnableVertexAttribArray LOOKUP_GL_FUNCTION(glEnableVertexAttribArray)
+#define glFramebufferRenderbufferEXT LOOKUP_GL_FUNCTION(glFramebufferRenderbuffer)
+#define glFramebufferTexture2DEXT LOOKUP_GL_FUNCTION(glFramebufferTexture2D)
+#define glGenBuffers LOOKUP_GL_FUNCTION(glGenBuffers)
+#define glGenerateMipmapEXT LOOKUP_GL_FUNCTION(glGenerateMipmap)
+#define glGenFramebuffersEXT LOOKUP_GL_FUNCTION(glGenFramebuffers)
+#define glGenRenderbuffersEXT LOOKUP_GL_FUNCTION(glGenRenderbuffers)
+#define glGetActiveAttrib LOOKUP_GL_FUNCTION(glGetActiveAttrib)
+#define glGetActiveUniform LOOKUP_GL_FUNCTION(glGetActiveUniform)
+#define glGetAttachedShaders LOOKUP_GL_FUNCTION(glGetAttachedShaders)
+#define glGetAttribLocation LOOKUP_GL_FUNCTION(glGetAttribLocation)
+#define glGetBufferParameteriv LOOKUP_GL_FUNCTION(glGetBufferParameteriv)
+#define glGetBufferParameterivEXT LOOKUP_GL_FUNCTION(glGetBufferParameteriv)
+#define glGetFramebufferAttachmentParameterivEXT LOOKUP_GL_FUNCTION(glGetFramebufferAttachmentParameteriv)
+#define glGetProgramInfoLog LOOKUP_GL_FUNCTION(glGetProgramInfoLog)
+#define glGetProgramiv LOOKUP_GL_FUNCTION(glGetProgramiv)
+#define glGetRenderbufferParameterivEXT LOOKUP_GL_FUNCTION(glGetRenderbufferParameteriv)
+#define glGetShaderInfoLog LOOKUP_GL_FUNCTION(glGetShaderInfoLog)
+#define glGetShaderiv LOOKUP_GL_FUNCTION(glGetShaderiv)
+#define glGetShaderSource LOOKUP_GL_FUNCTION(glGetShaderSource)
+#define glGetUniformfv LOOKUP_GL_FUNCTION(glGetUniformfv)
+#define glGetUniformiv LOOKUP_GL_FUNCTION(glGetUniformiv)
+#define glGetUniformLocation LOOKUP_GL_FUNCTION(glGetUniformLocation)
+#define glGetVertexAttribfv LOOKUP_GL_FUNCTION(glGetVertexAttribfv)
+#define glGetVertexAttribiv LOOKUP_GL_FUNCTION(glGetVertexAttribiv)
+#define glGetVertexAttribPointerv LOOKUP_GL_FUNCTION(glGetVertexAttribPointerv)
+#define glIsBuffer LOOKUP_GL_FUNCTION(glIsBuffer)
+#define glIsFramebufferEXT LOOKUP_GL_FUNCTION(glIsFramebuffer)
+#define glIsProgram LOOKUP_GL_FUNCTION(glIsProgram)
+#define glIsRenderbufferEXT LOOKUP_GL_FUNCTION(glIsRenderbuffer)
+#define glIsShader LOOKUP_GL_FUNCTION(glIsShader)
+#define glLinkProgram LOOKUP_GL_FUNCTION(glLinkProgram)
+#define glRenderbufferStorageEXT LOOKUP_GL_FUNCTION(glRenderbufferStorage)
+#define glRenderbufferStorageMultisampleEXT LOOKUP_GL_FUNCTION(glRenderbufferStorageMultisample)
+#define glSampleCoverage LOOKUP_GL_FUNCTION(glSampleCoverage)
+#define glShaderSource LOOKUP_GL_FUNCTION(glShaderSource)
+#define glStencilFuncSeparate LOOKUP_GL_FUNCTION(glStencilFuncSeparate)
+#define glStencilMaskSeparate LOOKUP_GL_FUNCTION(glStencilMaskSeparate)
+#define glStencilOpSeparate LOOKUP_GL_FUNCTION(glStencilOpSeparate)
+#define glUniform1f LOOKUP_GL_FUNCTION(glUniform1f)
+#define glUniform1fv LOOKUP_GL_FUNCTION(glUniform1fv)
+#define glUniform1i LOOKUP_GL_FUNCTION(glUniform1i)
+#define glUniform1iv LOOKUP_GL_FUNCTION(glUniform1iv)
+#define glUniform2f LOOKUP_GL_FUNCTION(glUniform2f)
+#define glUniform2fv LOOKUP_GL_FUNCTION(glUniform2fv)
+#define glUniform2i LOOKUP_GL_FUNCTION(glUniform2i)
+#define glUniform2iv LOOKUP_GL_FUNCTION(glUniform2iv)
+#define glUniform3f LOOKUP_GL_FUNCTION(glUniform3f)
+#define glUniform3fv LOOKUP_GL_FUNCTION(glUniform3fv)
+#define glUniform3i LOOKUP_GL_FUNCTION(glUniform3i)
+#define glUniform3iv LOOKUP_GL_FUNCTION(glUniform3iv)
+#define glUniform4f LOOKUP_GL_FUNCTION(glUniform4f)
+#define glUniform4fv LOOKUP_GL_FUNCTION(glUniform4fv)
+#define glUniform4i LOOKUP_GL_FUNCTION(glUniform4i)
+#define glUniform4iv LOOKUP_GL_FUNCTION(glUniform4iv)
+#define glUniformMatrix2fv LOOKUP_GL_FUNCTION(glUniformMatrix2fv)
+#define glUniformMatrix3fv LOOKUP_GL_FUNCTION(glUniformMatrix3fv)
+#define glUniformMatrix4fv LOOKUP_GL_FUNCTION(glUniformMatrix4fv)
+#define glUseProgram LOOKUP_GL_FUNCTION(glUseProgram)
+#define glValidateProgram LOOKUP_GL_FUNCTION(glValidateProgram)
+#define glVertexAttrib1f LOOKUP_GL_FUNCTION(glVertexAttrib1f)
+#define glVertexAttrib1fv LOOKUP_GL_FUNCTION(glVertexAttrib1fv)
+#define glVertexAttrib2f LOOKUP_GL_FUNCTION(glVertexAttrib2f)
+#define glVertexAttrib2fv LOOKUP_GL_FUNCTION(glVertexAttrib2fv)
+#define glVertexAttrib3f LOOKUP_GL_FUNCTION(glVertexAttrib3f)
+#define glVertexAttrib3fv LOOKUP_GL_FUNCTION(glVertexAttrib3fv)
+#define glVertexAttrib4f LOOKUP_GL_FUNCTION(glVertexAttrib4f)
+#define glVertexAttrib4fv LOOKUP_GL_FUNCTION(glVertexAttrib4fv)
+#define glVertexAttribPointer LOOKUP_GL_FUNCTION(glVertexAttribPointer)
+#endif
diff --git a/Source/WebCore/platform/graphics/cairo/PathCairo.cpp b/Source/WebCore/platform/graphics/cairo/PathCairo.cpp
index 533df10..d62c33f 100644
--- a/Source/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -27,10 +27,10 @@
#include "Path.h"
#include "AffineTransform.h"
-#include "CairoPath.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "OwnPtrCairo.h"
+#include "PlatformPathCairo.h"
#include "PlatformString.h"
#include "StrokeStyleApplier.h"
#include <cairo.h>
diff --git a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp
index ba75162..061ee06 100644
--- a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp
@@ -35,4 +35,51 @@ PlatformContextCairo::PlatformContextCairo(cairo_t* cr)
{
}
+void PlatformContextCairo::restore()
+{
+ const ImageMaskInformation& maskInformation = m_maskImageStack.last();
+ if (maskInformation.isValid()) {
+ const FloatRect& maskRect = maskInformation.maskRect();
+ cairo_pop_group_to_source(m_cr.get());
+ cairo_mask_surface(m_cr.get(), maskInformation.maskSurface(), maskRect.x(), maskRect.y());
+ }
+ m_maskImageStack.removeLast();
+
+ cairo_restore(m_cr.get());
+}
+
+void PlatformContextCairo::save()
+{
+ m_maskImageStack.append(ImageMaskInformation());
+
+ cairo_save(m_cr.get());
+}
+
+void PlatformContextCairo::pushImageMask(cairo_surface_t* surface, const FloatRect& rect)
+{
+ // We must call savePlatformState at least once before we can use image masking,
+ // since we actually apply the mask in restorePlatformState.
+ ASSERT(!m_maskImageStack.isEmpty());
+ m_maskImageStack.last().update(surface, rect);
+
+ // Cairo doesn't support the notion of an image clip, so we push a group here
+ // and then paint it to the surface with an image mask (which is an immediate
+ // operation) during restorePlatformState.
+
+ // We want to allow the clipped elements to composite with the surface as it
+ // is now, but they are isolated in another group. To make this work, we're
+ // going to blit the current surface contents onto the new group once we push it.
+ cairo_surface_t* currentTarget = cairo_get_target(m_cr.get());
+ cairo_surface_flush(currentTarget);
+
+ // Pushing a new group ensures that only things painted after this point are clipped.
+ cairo_push_group(m_cr.get());
+ cairo_set_operator(m_cr.get(), CAIRO_OPERATOR_SOURCE);
+
+ cairo_set_source_surface(m_cr.get(), currentTarget, 0, 0);
+ cairo_rectangle(m_cr.get(), rect.x(), rect.y(), rect.width(), rect.height());
+ cairo_fill(m_cr.get());
+}
+
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h
index c6cceda..937417a 100644
--- a/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h
+++ b/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h
@@ -31,6 +31,25 @@
namespace WebCore {
+// In Cairo image masking is immediate, so to emulate image clipping we must save masking
+// details as part of the context state and apply them during platform restore.
+class ImageMaskInformation {
+public:
+ void update(cairo_surface_t* maskSurface, const FloatRect& maskRect)
+ {
+ m_maskSurface = maskSurface;
+ m_maskRect = maskRect;
+ }
+
+ bool isValid() const { return m_maskSurface; }
+ cairo_surface_t* maskSurface() const { return m_maskSurface.get(); }
+ const FloatRect& maskRect() const { return m_maskRect; }
+
+private:
+ RefPtr<cairo_surface_t> m_maskSurface;
+ FloatRect m_maskRect;
+};
+
// Much like PlatformContextSkia in the Skia port, this class holds information that
// would normally be private to GraphicsContext, except that we want to allow access
// to it in Font and Image code. This allows us to separate the concerns of Cairo-specific
@@ -40,11 +59,17 @@ class PlatformContextCairo {
WTF_MAKE_NONCOPYABLE(PlatformContextCairo);
public:
PlatformContextCairo(cairo_t*);
+
cairo_t* cr() { return m_cr.get(); }
void setCr(cairo_t* cr) { m_cr = cr; }
+ void save();
+ void restore();
+ void pushImageMask(cairo_surface_t*, const FloatRect&);
+
private:
RefPtr<cairo_t> m_cr;
+ Vector<ImageMaskInformation> m_maskImageStack;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.cpp b/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.cpp
new file mode 100644
index 0000000..3a7d512
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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 "PlatformPathCairo.h"
+
+#include <cairo.h>
+
+namespace WebCore {
+
+static cairo_surface_t* getPathSurface()
+{
+ return cairo_image_surface_create(CAIRO_FORMAT_A8, 1, 1);
+}
+
+static cairo_surface_t* gPathSurface = getPathSurface();
+
+CairoPath::CairoPath()
+ : m_cr(adoptRef(cairo_create(gPathSurface)))
+{
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.h b/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.h
new file mode 100644
index 0000000..938b942
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cairo/PlatformPathCairo.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
+ * Copyright (C) 2010 Igalia S.L.
+ *
+ * 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.
+ */
+
+#ifndef PlatformPathCairo_h
+#define PlatformPathCairo_h
+
+#include "RefPtrCairo.h"
+
+namespace WebCore {
+
+// This is necessary since cairo_path_fixed_t isn't exposed in Cairo's public API.
+class CairoPath {
+public:
+ CairoPath();
+
+ ~CairoPath() {}
+
+ cairo_t* context() { return m_cr.get(); }
+
+private:
+ RefPtr<cairo_t> m_cr;
+};
+
+} // namespace WebCore
+
+#endif // PlatformPathCairo_h
diff --git a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
index 1792002..90bc3b1 100644
--- a/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
+++ b/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
@@ -61,7 +61,7 @@ template<> void refIfNotNull(cairo_font_face_t* ptr)
template<> void derefIfNotNull(cairo_font_face_t* ptr)
{
if (LIKELY(ptr != 0))
- cairo_font_face_reference(ptr);
+ cairo_font_face_destroy(ptr);
}
template<> void refIfNotNull(cairo_scaled_font_t* ptr)
diff --git a/Source/WebCore/platform/graphics/cg/ColorCG.cpp b/Source/WebCore/platform/graphics/cg/ColorCG.cpp
index c9b05da..55a3017 100644
--- a/Source/WebCore/platform/graphics/cg/ColorCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ColorCG.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "Color.h"
-#if PLATFORM(CG)
+#if USE(CG)
#include "GraphicsContextCG.h"
#include <wtf/Assertions.h>
@@ -146,4 +146,4 @@ CGColorRef cachedCGColor(const Color& color, ColorSpace colorSpace)
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/FloatPointCG.cpp b/Source/WebCore/platform/graphics/cg/FloatPointCG.cpp
index f9c3353..5e7aab3 100644
--- a/Source/WebCore/platform/graphics/cg/FloatPointCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/FloatPointCG.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "FloatPoint.h"
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
#include <ApplicationServices/ApplicationServices.h>
@@ -44,4 +44,4 @@ FloatPoint::operator CGPoint() const
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/FloatRectCG.cpp b/Source/WebCore/platform/graphics/cg/FloatRectCG.cpp
index a1ce367..131b7ac 100644
--- a/Source/WebCore/platform/graphics/cg/FloatRectCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/FloatRectCG.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "FloatRect.h"
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
#include <ApplicationServices/ApplicationServices.h>
@@ -44,4 +44,4 @@ FloatRect::operator CGRect() const
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/FloatSizeCG.cpp b/Source/WebCore/platform/graphics/cg/FloatSizeCG.cpp
index 383af21..a035c7a 100644
--- a/Source/WebCore/platform/graphics/cg/FloatSizeCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/FloatSizeCG.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "FloatSize.h"
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
#include <ApplicationServices/ApplicationServices.h>
@@ -44,4 +44,4 @@ FloatSize::operator CGSize() const
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
index 187d296..57abe71 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
@@ -29,8 +29,9 @@
#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
-#include "GraphicsContextCG.h"
+#include "BitmapImage.h"
+#include "GraphicsContextCG.h"
#include "Image.h"
#include <CoreGraphics/CGBitmapContext.h>
@@ -99,7 +100,8 @@ bool GraphicsContext3D::getImageData(Image* image,
return false;
CGImageRef cgImage;
RetainPtr<CGImageRef> decodedImage;
- if (image->data()) {
+ bool hasAlpha = image->isBitmapImage() ? static_cast<BitmapImage*>(image)->frameHasAlphaAtIndex(0) : true;
+ if ((ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && image->data()) {
ImageSource decoder(ImageSource::AlphaNotPremultiplied,
ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
decoder.setData(image->data(), true);
@@ -196,11 +198,6 @@ bool GraphicsContext3D::getImageData(Image* image,
AlphaFormat alphaFormat = AlphaFormatNone;
switch (CGImageGetAlphaInfo(cgImage)) {
case kCGImageAlphaPremultipliedFirst:
- // This is a special case for texImage2D with HTMLCanvasElement input,
- // in which case image->data() should be null, or indexed color models,
- // where we need premultiplied alpha to create the bitmap context
- // successfully.
- ASSERT(!image->data() || model == kCGColorSpaceModelIndexed);
if (!premultiplyAlpha)
neededAlphaOp = AlphaDoUnmultiply;
alphaFormat = AlphaFormatFirst;
@@ -216,9 +213,6 @@ bool GraphicsContext3D::getImageData(Image* image,
alphaFormat = AlphaFormatFirst;
break;
case kCGImageAlphaPremultipliedLast:
- // This is a special case for texImage2D with HTMLCanvasElement input,
- // in which case image->data() should be null.
- ASSERT(!image->data());
if (!premultiplyAlpha)
neededAlphaOp = AlphaDoUnmultiply;
alphaFormat = AlphaFormatLast;
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index 7799137..c7626b9 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -756,9 +756,6 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
if (oldFillColor != color || oldColorSpace != colorSpace)
setCGFillColor(context, color, colorSpace);
- Path path;
- path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
-
bool drawOwnShadow = !isAcceleratedContext() && hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
if (drawOwnShadow) {
float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
@@ -771,7 +768,15 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii(topLeft, topRight, bottomLeft, bottomRight));
}
- fillPath(path);
+ bool equalWidths = (topLeft.width() == topRight.width() && topRight.width() == bottomLeft.width() && bottomLeft.width() == bottomRight.width());
+ bool equalHeights = (topLeft.height() == bottomLeft.height() && bottomLeft.height() == topRight.height() && topRight.height() == bottomRight.height());
+ if (equalWidths && equalHeights && topLeft.width() * 2 == rect.width() && topLeft.height() * 2 == rect.height())
+ CGContextFillEllipseInRect(context, rect);
+ else {
+ Path path;
+ path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
+ fillPath(path);
+ }
if (drawOwnShadow)
CGContextRestoreGState(context);
@@ -791,7 +796,7 @@ void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const Rounded
path.addRect(rect);
if (!roundedHoleRect.radii().isZero())
- path.addRoundedRect(roundedHoleRect.rect(), roundedHoleRect.radii().topLeft(), roundedHoleRect.radii().topRight(), roundedHoleRect.radii().bottomLeft(), roundedHoleRect.radii().bottomRight());
+ path.addRoundedRect(roundedHoleRect);
else
path.addRect(roundedHoleRect.rect());
@@ -1167,8 +1172,11 @@ AffineTransform GraphicsContext::getCTM() const
return AffineTransform(t.a, t.b, t.c, t.d, t.tx, t.ty);
}
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode roundingMode)
{
+#if PLATFORM(CHROMIUM)
+ return rect;
+#else
// It is not enough just to round to pixels in device space. The rotation part of the
// affine transform matrix to device space can mess with this conversion if we have a
// rotating image like the hands of the world clock widget. We just need the scale, so
@@ -1192,8 +1200,13 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
deviceOrigin.x = roundf(deviceOrigin.x);
deviceOrigin.y = roundf(deviceOrigin.y);
- deviceLowerRight.x = roundf(deviceLowerRight.x);
- deviceLowerRight.y = roundf(deviceLowerRight.y);
+ if (roundingMode == RoundAllSides) {
+ deviceLowerRight.x = roundf(deviceLowerRight.x);
+ deviceLowerRight.y = roundf(deviceLowerRight.y);
+ } else {
+ deviceLowerRight.x = deviceOrigin.x + roundf(rect.width() * deviceScaleX);
+ deviceLowerRight.y = deviceOrigin.y + roundf(rect.height() * deviceScaleY);
+ }
// Don't let the height or width round to 0 unless either was originally 0
if (deviceOrigin.y == deviceLowerRight.y && rect.height())
@@ -1204,6 +1217,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
FloatPoint roundedOrigin = FloatPoint(deviceOrigin.x / deviceScaleX, deviceOrigin.y / deviceScaleY);
FloatPoint roundedLowerRight = FloatPoint(deviceLowerRight.x / deviceScaleX, deviceLowerRight.y / deviceScaleY);
return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin);
+#endif
}
void GraphicsContext::drawLineForText(const FloatPoint& point, float width, bool printing)
@@ -1232,7 +1246,7 @@ void GraphicsContext::drawLineForText(const FloatPoint& point, float width, bool
// We try to round all parameters to integer boundaries in device space. If rounding pixels in device space
// makes our thickness more than double, then there must be a shrinking-scale factor and rounding to pixels
// in device space will make the underlines too thick.
- CGRect lineRect = roundToDevicePixels(FloatRect(x, y, lineLength, adjustedThickness));
+ CGRect lineRect = roundToDevicePixels(FloatRect(x, y, lineLength, adjustedThickness), RoundOriginAndDimensions);
if (lineRect.size.height < thickness * 2.0) {
x = lineRect.origin.x;
y = lineRect.origin.y;
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 3c8f959..95ce8c1 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -42,10 +42,6 @@
#include <wtf/Threading.h>
#include <math.h>
-#if USE(IOSURFACE_CANVAS_BACKING_STORE)
-#include <IOSurface/IOSurface.h>
-#endif
-
#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
#include "WebCoreSystemInterface.h"
#endif
@@ -56,6 +52,7 @@ namespace WebCore {
#if USE(IOSURFACE_CANVAS_BACKING_STORE)
static const int maxIOSurfaceDimension = 4096;
+static const int minIOSurfaceArea = 50 * 100;
static RetainPtr<IOSurfaceRef> createIOSurface(const IntSize& size)
{
@@ -100,14 +97,6 @@ static void releaseImageData(void*, const void* data, size_t)
fastFree(const_cast<void*>(data));
}
-ImageBufferData::ImageBufferData(const IntSize&)
- : m_data(0)
-#if USE(IOSURFACE_CANVAS_BACKING_STORE)
- , m_surface(0)
-#endif
-{
-}
-
ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, bool& success)
: m_data(size)
, m_size(size)
@@ -117,7 +106,7 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, Render
if (size.width() < 0 || size.height() < 0)
return;
#if USE(IOSURFACE_CANVAS_BACKING_STORE)
- if (size.width() >= maxIOSurfaceDimension || size.height() >= maxIOSurfaceDimension)
+ if (size.width() >= maxIOSurfaceDimension || size.height() >= maxIOSurfaceDimension || size.width() * size.height() < minIOSurfaceArea)
m_accelerateRendering = false;
#else
ASSERT(renderingMode == Unaccelerated);
@@ -262,208 +251,32 @@ void ImageBuffer::clip(GraphicsContext* contextToClip, const FloatRect& rect) co
CGContextTranslateCTM(platformContextToClip, -rect.x(), -rect.y() - rect.height());
}
-template <Multiply multiplied>
-PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size, bool accelerateRendering)
-{
- RefPtr<ByteArray> result = ByteArray::create(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())
- memset(data, 0, result->length());
-
- int originx = rect.x();
- int destx = 0;
- if (originx < 0) {
- destx = -originx;
- originx = 0;
- }
- int endx = rect.maxX();
- if (endx > size.width())
- endx = size.width();
- int numColumns = endx - originx;
-
- int originy = rect.y();
- int desty = 0;
- if (originy < 0) {
- desty = -originy;
- originy = 0;
- }
- int endy = rect.maxY();
- if (endy > size.height())
- endy = size.height();
- int numRows = endy - originy;
-
- unsigned destBytesPerRow = 4 * rect.width();
- unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
-
- unsigned srcBytesPerRow;
- unsigned char* srcRows;
-
- if (!accelerateRendering) {
- srcBytesPerRow = 4 * size.width();
- srcRows = reinterpret_cast<unsigned char*>(imageData.m_data) + originy * srcBytesPerRow + originx * 4;
-
- for (int y = 0; y < numRows; ++y) {
- for (int x = 0; x < numColumns; x++) {
- int basex = x * 4;
- unsigned char alpha = srcRows[basex + 3];
- if (multiplied == Unmultiplied && alpha) {
- destRows[basex] = (srcRows[basex] * 255) / alpha;
- destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
- destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha;
- destRows[basex + 3] = alpha;
- } else
- reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
- }
- srcRows += srcBytesPerRow;
- destRows += destBytesPerRow;
- }
- } else {
-#if USE(IOSURFACE_CANVAS_BACKING_STORE)
- IOSurfaceRef surface = imageData.m_surface.get();
- IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0);
- srcBytesPerRow = IOSurfaceGetBytesPerRow(surface);
- srcRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + originy * srcBytesPerRow + originx * 4;
-
- for (int y = 0; y < numRows; ++y) {
- for (int x = 0; x < numColumns; x++) {
- int basex = x * 4;
- unsigned char alpha = srcRows[basex + 3];
- if (multiplied == Unmultiplied && alpha) {
- destRows[basex] = (srcRows[basex + 2] * 255) / alpha;
- destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
- destRows[basex + 2] = (srcRows[basex] * 255) / alpha;
- destRows[basex + 3] = alpha;
- } else {
- destRows[basex] = srcRows[basex + 2];
- destRows[basex + 1] = srcRows[basex + 1];
- destRows[basex + 2] = srcRows[basex];
- destRows[basex + 3] = alpha;
- }
- }
- srcRows += srcBytesPerRow;
- destRows += destBytesPerRow;
- }
- IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0);
-#else
- ASSERT_NOT_REACHED();
-#endif
- }
-
- return result.release();
-}
-
PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
if (m_accelerateRendering)
CGContextFlush(context()->platformContext());
- return getImageData<Unmultiplied>(rect, m_data, m_size, m_accelerateRendering);
+ return m_data.getData(rect, m_size, m_accelerateRendering, true);
}
PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
{
if (m_accelerateRendering)
CGContextFlush(context()->platformContext());
- return getImageData<Premultiplied>(rect, m_data, m_size, m_accelerateRendering);
-}
-
-template <Multiply multiplied>
-void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size, bool accelerateRendering)
-{
- ASSERT(sourceRect.width() > 0);
- ASSERT(sourceRect.height() > 0);
-
- int originx = sourceRect.x();
- int destx = destPoint.x() + sourceRect.x();
- ASSERT(destx >= 0);
- ASSERT(destx < size.width());
- ASSERT(originx >= 0);
- ASSERT(originx <= sourceRect.maxX());
-
- int endx = destPoint.x() + sourceRect.maxX();
- ASSERT(endx <= size.width());
-
- int numColumns = endx - destx;
-
- int originy = sourceRect.y();
- int desty = destPoint.y() + sourceRect.y();
- ASSERT(desty >= 0);
- ASSERT(desty < size.height());
- ASSERT(originy >= 0);
- ASSERT(originy <= sourceRect.maxY());
-
- int endy = destPoint.y() + sourceRect.maxY();
- ASSERT(endy <= size.height());
- int numRows = endy - desty;
-
- unsigned srcBytesPerRow = 4 * sourceSize.width();
- unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4;
- unsigned destBytesPerRow;
- unsigned char* destRows;
-
- if (!accelerateRendering) {
- destBytesPerRow = 4 * size.width();
- destRows = reinterpret_cast<unsigned char*>(imageData.m_data) + desty * destBytesPerRow + destx * 4;
- for (int y = 0; y < numRows; ++y) {
- for (int x = 0; x < numColumns; x++) {
- int basex = x * 4;
- unsigned char alpha = srcRows[basex + 3];
- if (multiplied == Unmultiplied && alpha != 255) {
- destRows[basex] = (srcRows[basex] * alpha + 254) / 255;
- destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
- destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255;
- destRows[basex + 3] = alpha;
- } else
- reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
- }
- destRows += destBytesPerRow;
- srcRows += srcBytesPerRow;
- }
- } else {
-#if USE(IOSURFACE_CANVAS_BACKING_STORE)
- IOSurfaceRef surface = imageData.m_surface.get();
- IOSurfaceLock(surface, 0, 0);
- destBytesPerRow = IOSurfaceGetBytesPerRow(surface);
- destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + desty * destBytesPerRow + destx * 4;
-
- for (int y = 0; y < numRows; ++y) {
- for (int x = 0; x < numColumns; x++) {
- int basex = x * 4;
- unsigned char alpha = srcRows[basex + 3];
- if (multiplied == Unmultiplied && alpha != 255) {
- destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255;
- destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
- destRows[basex + 2] = (srcRows[basex] * alpha + 254) / 255;
- destRows[basex + 3] = alpha;
- } else {
- destRows[basex] = srcRows[basex + 2];
- destRows[basex + 1] = srcRows[basex + 1];
- destRows[basex + 2] = srcRows[basex];
- destRows[basex + 3] = alpha;
- }
- }
- destRows += destBytesPerRow;
- srcRows += srcBytesPerRow;
- }
- IOSurfaceUnlock(surface, 0, 0);
-#else
- ASSERT_NOT_REACHED();
-#endif
- }
+ return m_data.getData(rect, m_size, m_accelerateRendering, false);
}
void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
{
if (m_accelerateRendering)
CGContextFlush(context()->platformContext());
- putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size, m_accelerateRendering);
+ m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_accelerateRendering, true);
}
void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
{
if (m_accelerateRendering)
CGContextFlush(context()->platformContext());
- putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size, m_accelerateRendering);
+ m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_accelerateRendering, false);
}
static inline CFStringRef jpegUTI()
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp
new file mode 100644
index 0000000..f067b66
--- /dev/null
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2011 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 "ImageBufferData.h"
+
+#include <wtf/Assertions.h>
+
+#if USE(ACCELERATE)
+#include <Accelerate/Accelerate.h>
+#endif
+
+#if USE(IOSURFACE_CANVAS_BACKING_STORE)
+#include <IOSurface/IOSurface.h>
+#include <dispatch/dispatch.h>
+#endif
+
+#if USE(ACCELERATE)
+struct ScanlineData {
+ vImagePixelCount scanlineWidth;
+ unsigned char* srcData;
+ size_t srcRowBytes;
+ unsigned char* destData;
+ size_t destRowBytes;
+};
+#endif
+
+namespace WebCore {
+
+ImageBufferData::ImageBufferData(const IntSize&)
+: m_data(0)
+#if USE(IOSURFACE_CANVAS_BACKING_STORE)
+, m_surface(0)
+#endif
+{
+}
+
+#if USE(ACCELERATE)
+// The vImage unpremultiply routine had a rounding bug before 10.6.7 <rdar://problem/8631548>
+static bool haveVImageRoundingErrorFix()
+{
+ SInt32 version;
+ static bool result = (Gestalt(gestaltSystemVersion, &version) == noErr && version > 0x1066);
+ return result;
+}
+
+#if USE(IOSURFACE_CANVAS_BACKING_STORE)
+static void convertScanline(void* data, size_t tileNumber, bool premultiply)
+{
+ ScanlineData* scanlineData = static_cast<ScanlineData*>(data);
+
+ vImage_Buffer src;
+ src.data = scanlineData->srcData + tileNumber * scanlineData->srcRowBytes;
+ src.height = 1;
+ src.width = scanlineData->scanlineWidth;
+ src.rowBytes = scanlineData->srcRowBytes;
+
+ vImage_Buffer dest;
+ dest.data = scanlineData->destData + tileNumber * scanlineData->destRowBytes;
+ dest.height = 1;
+ dest.width = scanlineData->scanlineWidth;
+ dest.rowBytes = scanlineData->destRowBytes;
+
+ if (premultiply) {
+ if (kvImageNoError != vImagePremultiplyData_RGBA8888(&src, &dest, kvImageDoNotTile))
+ return;
+ } else {
+ if (kvImageNoError != vImageUnpremultiplyData_RGBA8888(&src, &dest, kvImageDoNotTile))
+ return;
+ }
+
+ // Swap channels 1 and 3, to convert BGRA<->RGBA. IOSurfaces is BGRA, ImageData expects RGBA.
+ const uint8_t map[4] = { 2, 1, 0, 3 };
+ vImagePermuteChannels_ARGB8888(&dest, &dest, map, kvImageDoNotTile);
+}
+
+static void unpremultitplyScanline(void* data, size_t tileNumber)
+{
+ convertScanline(data, tileNumber, false);
+}
+
+static void premultitplyScanline(void* data, size_t tileNumber)
+{
+ convertScanline(data, tileNumber, true);
+}
+#endif // USE(IOSURFACE_CANVAS_BACKING_STORE)
+#endif // USE(ACCELERATE)
+
+PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied) const
+{
+ RefPtr<ByteArray> result = ByteArray::create(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())
+ memset(data, 0, result->length());
+
+ int originx = rect.x();
+ int destx = 0;
+ if (originx < 0) {
+ destx = -originx;
+ originx = 0;
+ }
+ int endx = rect.maxX();
+ if (endx > size.width())
+ endx = size.width();
+ int width = endx - originx;
+
+ int originy = rect.y();
+ int desty = 0;
+ if (originy < 0) {
+ desty = -originy;
+ originy = 0;
+ }
+ int endy = rect.maxY();
+ if (endy > size.height())
+ endy = size.height();
+ int height = endy - originy;
+
+ if (width <= 0 || height <= 0)
+ return result.release();
+
+ unsigned destBytesPerRow = 4 * rect.width();
+ unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
+
+ unsigned srcBytesPerRow;
+ unsigned char* srcRows;
+
+ if (!accelerateRendering) {
+ srcBytesPerRow = 4 * size.width();
+ srcRows = reinterpret_cast<unsigned char*>(m_data) + originy * srcBytesPerRow + originx * 4;
+
+#if USE(ACCELERATE)
+ if (unmultiplied && haveVImageRoundingErrorFix()) {
+ vImage_Buffer src;
+ src.height = height;
+ src.width = width;
+ src.rowBytes = srcBytesPerRow;
+ src.data = srcRows;
+
+ vImage_Buffer dst;
+ dst.height = height;
+ dst.width = width;
+ dst.rowBytes = destBytesPerRow;
+ dst.data = destRows;
+
+ vImageUnpremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags);
+ return result.release();
+ }
+#endif
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; x++) {
+ int basex = x * 4;
+ unsigned char alpha = srcRows[basex + 3];
+ if (unmultiplied && alpha) {
+ destRows[basex] = (srcRows[basex] * 255) / alpha;
+ destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
+ destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha;
+ destRows[basex + 3] = alpha;
+ } else
+ reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
+ }
+ srcRows += srcBytesPerRow;
+ destRows += destBytesPerRow;
+ }
+ } else {
+#if USE(IOSURFACE_CANVAS_BACKING_STORE)
+ IOSurfaceRef surface = m_surface.get();
+ IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0);
+ srcBytesPerRow = IOSurfaceGetBytesPerRow(surface);
+ srcRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + originy * srcBytesPerRow + originx * 4;
+
+#if USE(ACCELERATE)
+ if (unmultiplied) {
+ ScanlineData scanlineData;
+ scanlineData.scanlineWidth = width;
+ scanlineData.srcData = srcRows;
+ scanlineData.srcRowBytes = srcBytesPerRow;
+ scanlineData.destData = destRows;
+ scanlineData.destRowBytes = destBytesPerRow;
+
+ dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, unpremultitplyScanline);
+ } else {
+ vImage_Buffer src;
+ src.height = height;
+ src.width = width;
+ src.rowBytes = srcBytesPerRow;
+ src.data = srcRows;
+
+ vImage_Buffer dest;
+ dest.height = height;
+ dest.width = width;
+ dest.rowBytes = destBytesPerRow;
+ dest.data = destRows;
+
+ // Swap pixel channels from BGRA to RGBA.
+ const uint8_t map[4] = { 2, 1, 0, 3 };
+ vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
+ }
+#else
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; x++) {
+ int basex = x * 4;
+ unsigned char alpha = srcRows[basex + 3];
+ if (unmultiplied && alpha) {
+ destRows[basex] = (srcRows[basex + 2] * 255) / alpha;
+ destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
+ destRows[basex + 2] = (srcRows[basex] * 255) / alpha;
+ destRows[basex + 3] = alpha;
+ } else {
+ destRows[basex] = srcRows[basex + 2];
+ destRows[basex + 1] = srcRows[basex + 1];
+ destRows[basex + 2] = srcRows[basex];
+ destRows[basex + 3] = alpha;
+ }
+ }
+ srcRows += srcBytesPerRow;
+ destRows += destBytesPerRow;
+ }
+#endif // USE(ACCELERATE)
+ IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0);
+#else
+ ASSERT_NOT_REACHED();
+#endif // USE(IOSURFACE_CANVAS_BACKING_STORE)
+ }
+
+ return result.release();
+}
+
+void ImageBufferData::putData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied)
+{
+ ASSERT(sourceRect.width() > 0);
+ ASSERT(sourceRect.height() > 0);
+
+ int originx = sourceRect.x();
+ int destx = destPoint.x() + sourceRect.x();
+ ASSERT(destx >= 0);
+ ASSERT(destx < size.width());
+ ASSERT(originx >= 0);
+ ASSERT(originx <= sourceRect.maxX());
+
+ int endx = destPoint.x() + sourceRect.maxX();
+ ASSERT(endx <= size.width());
+
+ int width = endx - destx;
+
+ int originy = sourceRect.y();
+ int desty = destPoint.y() + sourceRect.y();
+ ASSERT(desty >= 0);
+ ASSERT(desty < size.height());
+ ASSERT(originy >= 0);
+ ASSERT(originy <= sourceRect.maxY());
+
+ int endy = destPoint.y() + sourceRect.maxY();
+ ASSERT(endy <= size.height());
+ int height = endy - desty;
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ unsigned srcBytesPerRow = 4 * sourceSize.width();
+ unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4;
+ unsigned destBytesPerRow;
+ unsigned char* destRows;
+
+ if (!accelerateRendering) {
+ destBytesPerRow = 4 * size.width();
+ destRows = reinterpret_cast<unsigned char*>(m_data) + desty * destBytesPerRow + destx * 4;
+
+#if USE(ACCELERATE)
+ if (haveVImageRoundingErrorFix() && unmultiplied) {
+ vImage_Buffer src;
+ src.height = height;
+ src.width = width;
+ src.rowBytes = srcBytesPerRow;
+ src.data = srcRows;
+
+ vImage_Buffer dst;
+ dst.height = height;
+ dst.width = width;
+ dst.rowBytes = destBytesPerRow;
+ dst.data = destRows;
+
+ vImagePremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags);
+ return;
+ }
+#endif
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; x++) {
+ int basex = x * 4;
+ unsigned char alpha = srcRows[basex + 3];
+ if (unmultiplied && alpha != 255) {
+ destRows[basex] = (srcRows[basex] * alpha + 254) / 255;
+ destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
+ destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255;
+ destRows[basex + 3] = alpha;
+ } else
+ reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
+ }
+ destRows += destBytesPerRow;
+ srcRows += srcBytesPerRow;
+ }
+ } else {
+#if USE(IOSURFACE_CANVAS_BACKING_STORE)
+ IOSurfaceRef surface = m_surface.get();
+ IOSurfaceLock(surface, 0, 0);
+ destBytesPerRow = IOSurfaceGetBytesPerRow(surface);
+ destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + desty * destBytesPerRow + destx * 4;
+
+#if USE(ACCELERATE)
+ if (unmultiplied) {
+ ScanlineData scanlineData;
+ scanlineData.scanlineWidth = width;
+ scanlineData.srcData = srcRows;
+ scanlineData.srcRowBytes = srcBytesPerRow;
+ scanlineData.destData = destRows;
+ scanlineData.destRowBytes = destBytesPerRow;
+
+ dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, premultitplyScanline);
+ } else {
+ vImage_Buffer src;
+ src.height = height;
+ src.width = width;
+ src.rowBytes = srcBytesPerRow;
+ src.data = srcRows;
+
+ vImage_Buffer dest;
+ dest.height = height;
+ dest.width = width;
+ dest.rowBytes = destBytesPerRow;
+ dest.data = destRows;
+
+ // Swap pixel channels from RGBA to BGRA.
+ const uint8_t map[4] = { 2, 1, 0, 3 };
+ vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
+ }
+#else
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; x++) {
+ int basex = x * 4;
+ unsigned char alpha = srcRows[basex + 3];
+ if (unmultiplied && alpha != 255) {
+ destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255;
+ destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
+ destRows[basex + 2] = (srcRows[basex] * alpha + 254) / 255;
+ destRows[basex + 3] = alpha;
+ } else {
+ destRows[basex] = srcRows[basex + 2];
+ destRows[basex + 1] = srcRows[basex + 1];
+ destRows[basex + 2] = srcRows[basex];
+ destRows[basex + 3] = alpha;
+ }
+ }
+ destRows += destBytesPerRow;
+ srcRows += srcBytesPerRow;
+ }
+#endif // USE(ACCELERATE)
+
+ IOSurfaceUnlock(surface, 0, 0);
+#else
+ ASSERT_NOT_REACHED();
+#endif // USE(IOSURFACE_CANVAS_BACKING_STORE)
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferData.h b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h
index 1f706ec..54169e6 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
* Copyright (C) 2008 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,13 +24,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ImageBufferData_h
-#define ImageBufferData_h
-
#include "Image.h"
+#include <wtf/ByteArray.h>
#include <wtf/RefPtr.h>
#include <wtf/RetainPtr.h>
+#if (PLATFORM(MAC) && USE(CA) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD))
+#define WTF_USE_IOSURFACE_CANVAS_BACKING_STORE 1
+#endif
+
typedef struct __IOSurface *IOSurfaceRef;
typedef struct CGColorSpace *CGColorSpaceRef;
typedef struct CGDataProvider *CGDataProviderRef;
@@ -50,8 +53,9 @@ public:
unsigned m_bytesPerRow;
CGColorSpaceRef m_colorSpace;
RetainPtr<IOSurfaceRef> m_surface;
-};
-} // namespace WebCore
+ PassRefPtr<ByteArray> getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied) const;
+ void putData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied);
+};
-#endif // ImageBufferData_h
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/cg/ImageCG.cpp b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
index 08f65bd..635a804 100644
--- a/Source/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "BitmapImage.h"
-#if PLATFORM(CG)
+#if USE(CG)
#include "AffineTransform.h"
#include "FloatConversion.h"
@@ -154,6 +154,19 @@ CGImageRef BitmapImage::getCGImageRef()
return frameAtIndex(0);
}
+CGImageRef BitmapImage::getFirstCGImageRefOfSize(const IntSize& size)
+{
+ size_t count = frameCount();
+ for (size_t i = 0; i < count; ++i) {
+ CGImageRef cgImage = frameAtIndex(i);
+ if (IntSize(CGImageGetWidth(cgImage), CGImageGetHeight(cgImage)) == size)
+ return cgImage;
+ }
+
+ // Fallback to the default CGImageRef if we can't find the right size
+ return getCGImageRef();
+}
+
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
startAnimation();
@@ -186,7 +199,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
// containing only the portion we want to display. We need to do this because high-quality
// interpolation smoothes sharp edges, causing pixels from outside the source rect to bleed
// into the destination rect. See <rdar://problem/6112909>.
- shouldUseSubimage = (interpolationQuality == kCGInterpolationHigh || interpolationQuality == kCGInterpolationDefault) && (srcRect.size() != destRect.size() || !ctxt->getCTM().isIdentityOrTranslationOrFlipped());
+ shouldUseSubimage = (interpolationQuality != kCGInterpolationNone) && (srcRect.size() != destRect.size() || !ctxt->getCTM().isIdentityOrTranslationOrFlipped());
float xScale = srcRect.width() / destRect.width();
float yScale = srcRect.height() / destRect.height();
if (shouldUseSubimage) {
@@ -255,6 +268,11 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
// Avoid a hang under CGContextDrawTiledImage on release builds.
return;
+#if !ASSERT_DISABLED
+ if (this->isBitmapImage())
+ ASSERT(static_cast<BitmapImage*>(this)->notSolidColor());
+#endif
+
CGContextRef context = ctxt->platformContext();
ctxt->save();
CGContextClipToRect(context, destRect);
@@ -346,4 +364,4 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index 068ea5b..1a630d4 100644
--- a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "ImageSource.h"
-#if PLATFORM(CG)
+#if USE(CG)
#include "ImageSourceCG.h"
#include "IntPoint.h"
@@ -356,4 +356,4 @@ bool ImageSource::frameHasAlphaAtIndex(size_t)
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/IntPointCG.cpp b/Source/WebCore/platform/graphics/cg/IntPointCG.cpp
index 95dbe5f..4a1096b 100644
--- a/Source/WebCore/platform/graphics/cg/IntPointCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/IntPointCG.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "IntPoint.h"
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
#include <ApplicationServices/ApplicationServices.h>
@@ -43,4 +43,4 @@ IntPoint::operator CGPoint() const
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/IntRectCG.cpp b/Source/WebCore/platform/graphics/cg/IntRectCG.cpp
index 73fd63f..18edeb0 100644
--- a/Source/WebCore/platform/graphics/cg/IntRectCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/IntRectCG.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "IntRect.h"
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
#include <ApplicationServices/ApplicationServices.h>
@@ -48,4 +48,4 @@ IntRect enclosingIntRect(const CGRect& rect)
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/IntSizeCG.cpp b/Source/WebCore/platform/graphics/cg/IntSizeCG.cpp
index d8e8c83..c844cbc 100644
--- a/Source/WebCore/platform/graphics/cg/IntSizeCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/IntSizeCG.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "IntSize.h"
-#if PLATFORM(CG)
+#if USE(CG) || USE(SKIA_ON_MAC_CHROME)
#include <ApplicationServices/ApplicationServices.h>
@@ -43,4 +43,4 @@ IntSize::operator CGSize() const
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp b/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
index 8bf04f1..a7d465f 100644
--- a/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
+++ b/Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "PDFDocumentImage.h"
-#if PLATFORM(CG)
+#if USE(CG)
#include "GraphicsContext.h"
#include "ImageObserver.h"
@@ -188,4 +188,4 @@ void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect,
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h b/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h
index ecd57be..c69a222 100644
--- a/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h
+++ b/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h
@@ -31,7 +31,7 @@
#include "FloatRect.h"
#include "GraphicsTypes.h"
-#if PLATFORM(CG)
+#if USE(CG)
#include <ApplicationServices/ApplicationServices.h>
@@ -78,6 +78,6 @@ namespace WebCore {
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
#endif // PDFDocumentImage_h
diff --git a/Source/WebCore/platform/graphics/cg/PathCG.cpp b/Source/WebCore/platform/graphics/cg/PathCG.cpp
index b8fc7d4..3b9725a 100644
--- a/Source/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/PathCG.cpp
@@ -27,7 +27,7 @@
#include "config.h"
#include "Path.h"
-#if PLATFORM(CG)
+#if USE(CG)
#include "AffineTransform.h"
#include "FloatRect.h"
@@ -309,4 +309,4 @@ void Path::transform(const AffineTransform& transform)
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp b/Source/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp
index ec40836..b49a2ab 100644
--- a/Source/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp
@@ -27,7 +27,7 @@
#include "AffineTransform.h"
#include "TransformationMatrix.h"
-#if PLATFORM(CG)
+#if USE(CG)
#include <CoreGraphics/CGAffineTransform.h>
#include "FloatConversion.h"
@@ -66,4 +66,4 @@ AffineTransform::operator CGAffineTransform() const
}
-#endif // PLATFORM(CG)
+#endif // USE(CG)
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
index 4cb119a..26ad37a 100644
--- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
@@ -36,6 +36,7 @@
#include "DrawingBuffer.h"
#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
namespace WebCore {
@@ -54,6 +55,8 @@ Canvas2DLayerChromium::~Canvas2DLayerChromium()
{
if (m_textureId)
layerRendererContext()->deleteTexture(m_textureId);
+ if (m_drawingBuffer && layerRenderer())
+ layerRenderer()->removeChildContext(m_drawingBuffer->graphicsContext3D().get());
}
void Canvas2DLayerChromium::updateCompositorResources()
@@ -103,8 +106,28 @@ unsigned Canvas2DLayerChromium::textureId() const
void Canvas2DLayerChromium::setDrawingBuffer(DrawingBuffer* drawingBuffer)
{
if (drawingBuffer != m_drawingBuffer) {
+ if (m_drawingBuffer && layerRenderer())
+ layerRenderer()->removeChildContext(m_drawingBuffer->graphicsContext3D().get());
+
m_drawingBuffer = drawingBuffer;
m_textureChanged = true;
+
+ if (drawingBuffer && layerRenderer())
+ layerRenderer()->addChildContext(m_drawingBuffer->graphicsContext3D().get());
+ }
+}
+
+void Canvas2DLayerChromium::setLayerRenderer(LayerRendererChromium* newLayerRenderer)
+{
+ if (layerRenderer() != newLayerRenderer) {
+ if (m_drawingBuffer->graphicsContext3D()) {
+ if (layerRenderer())
+ layerRenderer()->removeChildContext(m_drawingBuffer->graphicsContext3D().get());
+ if (newLayerRenderer)
+ newLayerRenderer->addChildContext(m_drawingBuffer->graphicsContext3D().get());
+ }
+
+ LayerChromium::setLayerRenderer(newLayerRenderer);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
index 81b118c..4224ab1 100644
--- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
@@ -52,6 +52,8 @@ public:
unsigned textureId() const;
void setDrawingBuffer(DrawingBuffer*);
+ virtual void setLayerRenderer(LayerRendererChromium*);
+
private:
explicit Canvas2DLayerChromium(DrawingBuffer*, GraphicsLayerChromium* owner);
DrawingBuffer* m_drawingBuffer;
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
index 4ea9c92..aff2981 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -41,6 +41,14 @@
#include "RenderLayerBacking.h"
#include "TextStream.h"
+// Maximum size the width or height of this layer can be before enabling tiling
+// when m_tilingOption == AutoTile.
+static int maxUntiledSize = 512;
+// When tiling is enabled, use tiles of this dimension squared.
+static int defaultTileSize = 256;
+
+using namespace std;
+
namespace WebCore {
PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(GraphicsLayerChromium* owner)
@@ -50,240 +58,171 @@ PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(GraphicsLayerChrom
ContentLayerChromium::ContentLayerChromium(GraphicsLayerChromium* owner)
: LayerChromium(owner)
- , m_contentsTexture(0)
- , m_skipsDraw(false)
+ , m_tilingOption(ContentLayerChromium::AutoTile)
{
}
ContentLayerChromium::~ContentLayerChromium()
{
- cleanupResources();
-}
-
-void ContentLayerChromium::cleanupResources()
-{
+ m_tiler.clear();
LayerChromium::cleanupResources();
- m_contentsTexture.clear();
}
-bool ContentLayerChromium::requiresClippedUpdateRect()
-{
- // To avoid allocating excessively large textures, switch into "large layer mode" if
- // one of the layer's dimensions is larger than 2000 pixels or the size of
- // surface it's rendering into. This is a temporary measure until layer tiling is implemented.
- static const int maxLayerSize = 2000;
- return (bounds().width() > max(maxLayerSize, ccLayerImpl()->targetRenderSurface()->contentRect().width())
- || bounds().height() > max(maxLayerSize, ccLayerImpl()->targetRenderSurface()->contentRect().height())
- || !layerRenderer()->checkTextureSize(bounds()));
-}
+class ContentLayerPainter : public TilePaintInterface {
+public:
+ explicit ContentLayerPainter(GraphicsLayerChromium* owner)
+ : m_owner(owner)
+ {
+ }
-void ContentLayerChromium::paintContentsIfDirty()
-{
- RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
- if (!backing || backing->paintingGoesToWindow())
- return;
+ virtual void paint(GraphicsContext& context, const IntRect& contentRect)
+ {
+ context.save();
+ context.clearRect(contentRect);
+ context.clip(contentRect);
+ m_owner->paintGraphicsLayerContents(context, contentRect);
+ context.restore();
+ }
+private:
+ GraphicsLayerChromium* m_owner;
+};
+void ContentLayerChromium::paintContentsIfDirty(const IntRect& targetSurfaceRect)
+{
ASSERT(drawsContent());
-
ASSERT(layerRenderer());
- IntRect dirtyRect;
- IntRect boundsRect(IntPoint(0, 0), bounds());
- IntPoint paintingOffset;
-
- // FIXME: Remove this test when tiled layers are implemented.
- if (requiresClippedUpdateRect()) {
- // Calculate the region of this layer that is currently visible.
- const IntRect clipRect = ccLayerImpl()->targetRenderSurface()->contentRect();
-
- TransformationMatrix layerOriginTransform = ccLayerImpl()->drawTransform();
- layerOriginTransform.translate3d(-0.5 * bounds().width(), -0.5 * bounds().height(), 0);
-
- // We compute the visible portion of the layer by back-mapping the current RenderSurface
- // content area to the layer. To do that, we invert the drawing matrix of the layer
- // and project the content area rectangle to it. If the layer transform is not invertible
- // then we skip rendering the layer.
- if (!layerOriginTransform.isInvertible()) {
- m_skipsDraw = true;
- return;
- }
- TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse();
- FloatQuad mappedClipToLayer = targetToLayerMatrix.projectQuad(FloatRect(clipRect));
- IntRect visibleRectInLayerCoords = mappedClipToLayer.enclosingBoundingBox();
- visibleRectInLayerCoords.intersect(IntRect(0, 0, bounds().width(), bounds().height()));
-
- // If this is still too large to render, then skip the layer completely.
- if (!layerRenderer()->checkTextureSize(visibleRectInLayerCoords.size())) {
- m_skipsDraw = true;
- return;
- }
-
- // If we need to resize the upload buffer we have to repaint everything.
- if (m_canvas.size() != visibleRectInLayerCoords.size()) {
- resizeUploadBuffer(visibleRectInLayerCoords.size());
- m_dirtyRect = boundsRect;
- }
- // If the visible portion of the layer is different from the last upload.
- if (visibleRectInLayerCoords != m_visibleRectInLayerCoords)
- m_dirtyRect = boundsRect;
- m_visibleRectInLayerCoords = visibleRectInLayerCoords;
-
- // Calculate the portion of the dirty rectangle that is visible. m_dirtyRect is in layer space.
- IntRect visibleDirtyRectInLayerSpace = enclosingIntRect(m_dirtyRect);
- visibleDirtyRectInLayerSpace.intersect(visibleRectInLayerCoords);
-
- // What the rectangles mean:
- // dirtyRect: The region of this layer that will be updated.
- // m_uploadUpdateRect: The region of the layer's texture that will be uploaded into.
- dirtyRect = visibleDirtyRectInLayerSpace;
- m_uploadUpdateRect = dirtyRect;
- IntSize visibleRectOffsetInLayerCoords(visibleRectInLayerCoords.x(), visibleRectInLayerCoords.y());
- paintingOffset = IntPoint(visibleRectOffsetInLayerCoords);
- m_uploadUpdateRect.move(-visibleRectOffsetInLayerCoords);
- } else {
- dirtyRect = IntRect(m_dirtyRect);
- // If the texture needs to be reallocated then we must redraw the entire
- // contents of the layer.
- if (m_canvas.size() != bounds()) {
- resizeUploadBuffer(bounds());
- dirtyRect = boundsRect;
- } else {
- // Clip the dirtyRect to the size of the layer to avoid drawing
- // outside the bounds of the backing texture.
- dirtyRect.intersect(boundsRect);
- }
- m_uploadUpdateRect = dirtyRect;
- }
+ createTilerIfNeeded();
- if (dirtyRect.isEmpty())
- return;
+ ContentLayerPainter painter(m_owner);
+ updateLayerSize(layerBounds().size());
- PlatformCanvas::Painter painter(&m_canvas);
- painter.context()->save();
- painter.context()->translate(-paintingOffset.x(), -paintingOffset.y());
- painter.context()->clearRect(dirtyRect);
- painter.context()->clip(dirtyRect);
+ IntRect layerRect = visibleLayerRect(targetSurfaceRect);
+ if (layerRect.isEmpty())
+ return;
+ m_tiler->invalidateRect(enclosingIntRect(m_dirtyRect));
+ m_tiler->update(painter, layerRect);
+ m_dirtyRect = FloatRect();
+}
- m_owner->paintGraphicsLayerContents(*painter.context(), dirtyRect);
- painter.context()->restore();
+void ContentLayerChromium::setLayerRenderer(LayerRendererChromium* layerRenderer)
+{
+ LayerChromium::setLayerRenderer(layerRenderer);
+ createTilerIfNeeded();
+ m_tiler->setLayerRenderer(layerRenderer);
}
-void ContentLayerChromium::resizeUploadBuffer(const IntSize& size)
+TransformationMatrix ContentLayerChromium::tilingTransform()
{
- m_canvas.resize(size);
+ TransformationMatrix transform = ccLayerImpl()->drawTransform();
+ // Tiler draws from the upper left corner. The draw transform
+ // specifies the middle of the layer.
+ IntSize size = bounds();
+ transform.translate(-size.width() / 2.0, -size.height() / 2.0);
+
+ return transform;
}
-void ContentLayerChromium::updateTextureIfNeeded()
+IntRect ContentLayerChromium::visibleLayerRect(const IntRect& targetSurfaceRect)
+{
+ if (targetSurfaceRect.isEmpty())
+ return targetSurfaceRect;
+
+ const IntRect layerBoundRect = layerBounds();
+ const TransformationMatrix transform = tilingTransform();
+
+ // Is this layer fully contained within the target surface?
+ IntRect layerInSurfaceSpace = transform.mapRect(layerBoundRect);
+ if (targetSurfaceRect.contains(layerInSurfaceSpace))
+ return layerBoundRect;
+
+ // If the layer doesn't fill up the entire surface, then find the part of
+ // the surface rect where the layer could be visible. This avoids trying to
+ // project surface rect points that are behind the projection point.
+ IntRect minimalSurfaceRect = targetSurfaceRect;
+ minimalSurfaceRect.intersect(layerInSurfaceSpace);
+
+ // Project the corners of the target surface rect into the layer space.
+ // This bounding rectangle may be larger than it needs to be (being
+ // axis-aligned), but is a reasonable filter on the space to consider.
+ // Non-invertible transforms will create an empty rect here.
+ const TransformationMatrix surfaceToLayer = transform.inverse();
+ IntRect layerRect = surfaceToLayer.projectQuad(FloatQuad(FloatRect(minimalSurfaceRect))).enclosingBoundingBox();
+ layerRect.intersect(layerBoundRect);
+ return layerRect;
+}
+
+IntRect ContentLayerChromium::layerBounds() const
{
- PlatformCanvas::AutoLocker locker(&m_canvas);
- updateTexture(locker.pixels(), m_canvas.size());
+ return IntRect(IntPoint(0, 0), bounds());
}
-void ContentLayerChromium::updateTexture(const uint8_t* pixels, const IntSize& size)
+void ContentLayerChromium::updateLayerSize(const IntSize& layerSize)
{
- if (!pixels)
+ if (!m_tiler)
return;
- GraphicsContext3D* context = layerRendererContext();
- if (!m_contentsTexture)
- m_contentsTexture = LayerTexture::create(context, layerRenderer()->textureManager());
+ const IntSize tileSize(min(defaultTileSize, layerSize.width()), min(defaultTileSize, layerSize.height()));
+ const bool autoTiled = layerSize.width() > maxUntiledSize || layerSize.height() > maxUntiledSize;
- // If we have to allocate a new texture we have to upload the full contents.
- if (!m_contentsTexture->isValid(size, GraphicsContext3D::RGBA))
- m_uploadUpdateRect = IntRect(IntPoint(0, 0), size);
+ bool isTiled;
+ if (m_tilingOption == AlwaysTile)
+ isTiled = true;
+ else if (m_tilingOption == NeverTile)
+ isTiled = false;
+ else
+ isTiled = autoTiled;
- if (!m_contentsTexture->reserve(size, GraphicsContext3D::RGBA)) {
- m_skipsDraw = true;
- return;
- }
-
- IntRect srcRect = IntRect(IntPoint(0, 0), size);
- if (requiresClippedUpdateRect())
- srcRect = m_visibleRectInLayerCoords;
-
- const size_t destStride = m_uploadUpdateRect.width() * 4;
- const size_t srcStride = srcRect.width() * 4;
-
- const uint8_t* uploadPixels = pixels + srcStride * m_uploadUpdateRect.y();
- Vector<uint8_t> uploadBuffer;
- if (srcStride != destStride || m_uploadUpdateRect.x()) {
- uploadBuffer.resize(m_uploadUpdateRect.height() * destStride);
- for (int row = 0; row < m_uploadUpdateRect.height(); ++row) {
- size_t srcOffset = (m_uploadUpdateRect.y() + row) * srcStride + m_uploadUpdateRect.x() * 4;
- ASSERT(srcOffset + destStride <= static_cast<size_t>(size.width() * size.height() * 4));
- size_t destOffset = row * destStride;
- ASSERT(destOffset + destStride <= uploadBuffer.size());
- memcpy(uploadBuffer.data() + destOffset, pixels + srcOffset, destStride);
- }
- uploadPixels = uploadBuffer.data();
- }
-
- m_contentsTexture->bindTexture();
- GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0,
- m_uploadUpdateRect.x(), m_uploadUpdateRect.y(), m_uploadUpdateRect.width(), m_uploadUpdateRect.height(),
- GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE,
- uploadPixels));
+ m_tiler->setTileSize(isTiled ? tileSize : layerSize);
+}
- m_uploadUpdateRect = IntRect();
- m_dirtyRect.setSize(FloatSize());
- // Large layers always stay dirty, because they need to update when the content rect changes.
- m_contentsDirty = requiresClippedUpdateRect();
+void ContentLayerChromium::draw(const IntRect& targetSurfaceRect)
+{
+ const TransformationMatrix transform = tilingTransform();
+ IntRect layerRect = visibleLayerRect(targetSurfaceRect);
+ if (!layerRect.isEmpty())
+ m_tiler->draw(layerRect, transform, ccLayerImpl()->drawOpacity());
+ m_tiler->unreserveTextures();
}
-void ContentLayerChromium::draw()
+void ContentLayerChromium::createTilerIfNeeded()
{
- if (m_skipsDraw)
+ if (m_tiler)
return;
+ m_tiler = LayerTilerChromium::create(layerRenderer(), IntSize(defaultTileSize, defaultTileSize), LayerTilerChromium::HasBorderTexels);
+}
- ASSERT(layerRenderer());
+void ContentLayerChromium::updateCompositorResources()
+{
+ m_tiler->uploadCanvas();
+}
- const ContentLayerChromium::Program* program = layerRenderer()->contentLayerProgram();
- ASSERT(program && program->initialized());
- GraphicsContext3D* context = layerRendererContext();
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
- bindContentsTexture();
- layerRenderer()->useShader(program->program());
- GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
- GLC(context, context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
-
- if (requiresClippedUpdateRect()) {
- // Compute the offset between the layer's center point and the center of the visible portion
- // of the layer.
- FloatPoint visibleRectCenterOffset = FloatRect(m_visibleRectInLayerCoords).center();
- visibleRectCenterOffset.move(-0.5 * bounds().width(), -0.5 * bounds().height());
-
- TransformationMatrix transform = ccLayerImpl()->drawTransform();
- transform.translate(visibleRectCenterOffset.x(), visibleRectCenterOffset.y());
-
- drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
- transform, m_visibleRectInLayerCoords.width(),
- m_visibleRectInLayerCoords.height(), ccLayerImpl()->drawOpacity(),
- program->vertexShader().matrixLocation(),
- program->fragmentShader().alphaLocation());
- } else {
- drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
- ccLayerImpl()->drawTransform(), bounds().width(), bounds().height(),
- ccLayerImpl()->drawOpacity(), program->vertexShader().matrixLocation(),
- program->fragmentShader().alphaLocation());
- }
- unreserveContentsTexture();
+void ContentLayerChromium::setTilingOption(TilingOption option)
+{
+ m_tilingOption = option;
+ updateLayerSize(bounds());
}
-void ContentLayerChromium::updateCompositorResources()
+void ContentLayerChromium::bindContentsTexture()
{
- updateTextureIfNeeded();
+ // This function is only valid for single texture layers, e.g. masks.
+ ASSERT(m_tilingOption == NeverTile);
+ ASSERT(m_tiler);
+
+ LayerTexture* texture = m_tiler->getSingleTexture();
+ ASSERT(texture);
+
+ texture->bindTexture();
}
void ContentLayerChromium::unreserveContentsTexture()
{
- if (!m_skipsDraw && m_contentsTexture)
- m_contentsTexture->unreserve();
+ m_tiler->unreserveTextures();
}
-void ContentLayerChromium::bindContentsTexture()
+void ContentLayerChromium::setIsMask(bool isMask)
{
- if (!m_skipsDraw && m_contentsTexture)
- m_contentsTexture->bindTexture();
+ setTilingOption(isMask ? NeverTile : AutoTile);
}
static void writeIndent(TextStream& ts, int indent)
@@ -296,7 +235,7 @@ void ContentLayerChromium::dumpLayerProperties(TextStream& ts, int indent) const
{
LayerChromium::dumpLayerProperties(ts, indent);
writeIndent(ts, indent);
- ts << "skipsDraw: " << m_skipsDraw << "\n";
+ ts << "skipsDraw: " << m_tiler->skipsDraw() << "\n";
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
index cf296ab..c0cf582 100644
--- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -35,7 +35,7 @@
#if USE(ACCELERATED_COMPOSITING)
#include "LayerChromium.h"
-#include "PlatformCanvas.h"
+#include "LayerTilerChromium.h"
#include "TextureManager.h"
namespace WebCore {
@@ -46,43 +46,43 @@ class LayerTexture;
class ContentLayerChromium : public LayerChromium {
friend class LayerRendererChromium;
public:
+ enum TilingOption { AlwaysTile, NeverTile, AutoTile };
+
static PassRefPtr<ContentLayerChromium> create(GraphicsLayerChromium* owner = 0);
virtual ~ContentLayerChromium();
- virtual void paintContentsIfDirty();
+ virtual void paintContentsIfDirty(const IntRect& targetSurfaceRect);
virtual void updateCompositorResources();
+ virtual void setIsMask(bool);
virtual void unreserveContentsTexture();
virtual void bindContentsTexture();
- virtual void draw();
- virtual bool drawsContent() const { return m_owner && m_owner->drawsContent(); }
-
- typedef ProgramBinding<VertexShaderPosTex, FragmentShaderTexAlpha> Program;
+ virtual void draw(const IntRect& targetSurfaceRect);
+ virtual bool drawsContent() const { return m_owner && m_owner->drawsContent() && (!m_tiler || !m_tiler->skipsDraw()); }
protected:
explicit ContentLayerChromium(GraphicsLayerChromium* owner);
- virtual void cleanupResources();
- bool requiresClippedUpdateRect();
- void resizeUploadBuffer(const IntSize&);
-
virtual const char* layerTypeAsString() const { return "ContentLayer"; }
virtual void dumpLayerProperties(TextStream&, int indent) const;
- OwnPtr<LayerTexture> m_contentsTexture;
- bool m_skipsDraw;
+ virtual void setLayerRenderer(LayerRendererChromium*);
+
+ virtual IntRect layerBounds() const;
- // The portion of the upload buffer that has a pending update, in the coordinates of the texture.
- IntRect m_uploadUpdateRect;
+ virtual TransformationMatrix tilingTransform();
- virtual void updateTextureIfNeeded();
- void updateTexture(const uint8_t* pixels, const IntSize&);
+ // For a given render surface rect that this layer will be transformed and
+ // drawn into, return the layer space rect that is visible in that surface.
+ IntRect visibleLayerRect(const IntRect&);
-private:
- PlatformCanvas m_canvas;
+ void updateLayerSize(const IntSize&);
+ void createTilerIfNeeded();
+ void setTilingOption(TilingOption);
- IntRect m_visibleRectInLayerCoords;
+ OwnPtr<LayerTilerChromium> m_tiler;
+ TilingOption m_tilingOption;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
index e559edb..bad0c6c 100644
--- a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -76,7 +76,7 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
bool multisampleExtensionSupported,
bool packedDepthStencilExtensionSupported)
: m_context(context)
- , m_size(size)
+ , m_size(-1, -1)
, m_multisampleExtensionSupported(multisampleExtensionSupported)
, m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
, m_fbo(0)
@@ -173,6 +173,29 @@ void DrawingBuffer::setGrContext(GrContext* context)
// the SharedGraphicsContext3D object that is giving us the context.
m_grContext = context;
}
+
+void DrawingBuffer::getGrPlatformSurfaceDesc(GrPlatformSurfaceDesc* desc)
+{
+ desc->fSurfaceType = kTextureRenderTarget_GrPlatformSurfaceType;
+
+ desc->fPlatformTexture = m_colorBuffer;
+ if (multisample()) {
+ desc->fRenderTargetFlags = kIsMultisampled_GrPlatformRenderTargetFlagBit | kGrCanResolve_GrPlatformRenderTargetFlagBit;
+ desc->fPlatformRenderTarget = m_multisampleFBO;
+ desc->fPlatformResolveDestination = m_fbo;
+ } else {
+ desc->fRenderTargetFlags = kNone_GrPlatformRenderTargetFlagBit;
+ desc->fPlatformRenderTarget = m_fbo;
+ desc->fPlatformResolveDestination = 0;
+ }
+
+ desc->fWidth = m_size.width();
+ desc->fHeight = m_size.height();
+ desc->fConfig = kRGBA_8888_GrPixelConfig;
+
+ desc->fStencilBits = (m_depthStencilBuffer || m_stencilBuffer) ? 8 : 0;
+}
+
#endif
}
diff --git a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
index 3b0fdbf..c542351 100644
--- a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
@@ -43,6 +43,7 @@ public:
// Extensions3D methods.
virtual bool supports(const String&);
virtual void ensureEnabled(const String&);
+ virtual bool isEnabled(const String&);
virtual int getGraphicsResetStatusARB();
virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter);
virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height);
@@ -66,6 +67,12 @@ public:
// GL_CHROMIUM_copy_texture_to_parent_texture
void copyTextureToParentTextureCHROMIUM(unsigned texture, unsigned parentTexture);
+ // Latch support
+ void getParentToChildLatchCHROMIUM(GC3Duint* latchId);
+ void getChildToParentLatchCHROMIUM(GC3Duint* latchId);
+ void waitLatchCHROMIUM(GC3Duint latchId);
+ void setLatchCHROMIUM(GC3Duint latchId);
+
private:
// Instances of this class are strictly owned by the GraphicsContext3D implementation and do not
// need to be instantiated by any other code.
diff --git a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 3c254dc..ac1e1af 100644
--- a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -43,7 +43,7 @@
#include "TransparencyWin.h"
#include "UniscribeHelperTextRun.h"
-#include "skia/ext/platform_canvas_win.h"
+#include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_win.h" // FIXME: remove this dependency.
#include <windows.h>
@@ -165,7 +165,7 @@ void TransparencyAwareFontPainter::initializeForGDI()
// Set up the DC, using the one from the transparency helper.
if (m_transparency.platformContext()) {
- m_hdc = m_transparency.platformContext()->canvas()->beginPlatformPaint();
+ m_hdc = skia::BeginPlatformPaint(m_transparency.platformContext()->canvas());
SetTextColor(m_hdc, skia::SkColorToCOLORREF(color));
SetBkMode(m_hdc, TRANSPARENT);
}
@@ -179,7 +179,7 @@ TransparencyAwareFontPainter::~TransparencyAwareFontPainter()
if (m_createdTransparencyLayer)
m_graphicsContext->endTransparencyLayer();
m_graphicsContext->restore();
- m_platformContext->canvas()->endPlatformPaint();
+ skia::EndPlatformPaint(m_platformContext->canvas());
}
// Specialization for simple GlyphBuffer painting.
@@ -374,21 +374,14 @@ bool Font::canExpandAroundIdeographsInComplexText()
return false;
}
-void Font::drawGlyphs(GraphicsContext* graphicsContext,
- const SimpleFontData* font,
- const GlyphBuffer& glyphBuffer,
- int from,
- int numGlyphs,
- const FloatPoint& point) const
-{
+static void drawGlyphsWin(GraphicsContext* graphicsContext,
+ const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer,
+ int from,
+ int numGlyphs,
+ const FloatPoint& point) {
graphicsContext->platformContext()->prepareForSoftwareDraw();
- SkColor color = graphicsContext->platformContext()->effectiveFillColor();
- unsigned char alpha = SkColorGetA(color);
- // Skip 100% transparent text; no need to draw anything.
- if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke)
- return;
-
TransparencyAwareGlyphPainter painter(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
// We draw the glyphs in chunks to avoid having to do a heap allocation for
@@ -449,6 +442,39 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext,
}
}
+void Font::drawGlyphs(GraphicsContext* graphicsContext,
+ const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer,
+ int from,
+ int numGlyphs,
+ const FloatPoint& point) const
+{
+ SkColor color = graphicsContext->platformContext()->effectiveFillColor();
+ unsigned char alpha = SkColorGetA(color);
+ // Skip 100% transparent text; no need to draw anything.
+ if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke && !graphicsContext->hasShadow())
+ return;
+ if (!alpha || windowsCanHandleDrawTextShadow(graphicsContext) || !windowsCanHandleTextDrawingWithoutShadow(graphicsContext)) {
+ drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+ return;
+ }
+ // Draw in two passes: skia for the shadow, GDI for foreground text
+ // pass1: shadow (will use skia)
+ graphicsContext->save();
+ graphicsContext->setFillColor(Color::transparent, graphicsContext->fillColorSpace());
+ drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+ graphicsContext->restore();
+ // pass2: foreground text (will use GDI)
+ FloatSize shadowOffset;
+ float shadowBlur;
+ Color shadowColor;
+ ColorSpace shadowColorSpace;
+ graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
+ graphicsContext->setShadow(shadowOffset, shadowBlur, Color::transparent, shadowColorSpace);
+ drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+ graphicsContext->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
+}
+
FloatRect Font::selectionRectForComplexText(const TextRun& run,
const FloatPoint& point,
int h,
@@ -516,7 +542,7 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
// the baseline, so we have to subtract off the ascent.
state.draw(graphicsContext, hdc, lroundf(point.x()), lroundf(point.y() - fontMetrics().ascent()), from, to);
- context->canvas()->endPlatformPaint();
+ skia::EndPlatformPaint(context->canvas());
}
void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
index c3edfac..1fb5957 100644
--- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -122,7 +122,7 @@ int FontPlatformData::emSizeInFontUnits() const
if (m_emSizeInFontUnits)
return m_emSizeInFontUnits;
- SkAdvancedTypefaceMetrics* metrics = m_typeface->getAdvancedTypefaceMetrics(false);
+ SkAdvancedTypefaceMetrics* metrics = m_typeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo);
m_emSizeInFontUnits = metrics->fEmSize;
metrics->unref();
return m_emSizeInFontUnits;
diff --git a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
index bea0572..a4798dd 100644
--- a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
@@ -250,17 +250,31 @@ int getAscent(HFONT hfont)
return gotMetrics ? tm.tmAscent : kUndefinedAscent;
}
+WORD getSpaceGlyph(HFONT hfont)
+{
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, hfont);
+ WCHAR space = L' ';
+ WORD spaceGlyph = 0;
+ GetGlyphIndices(dc, &space, 1, &spaceGlyph, 0);
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ return spaceGlyph;
+}
+
struct FontData {
FontData()
: hfont(0)
, ascent(kUndefinedAscent)
, scriptCache(0)
+ , spaceGlyph(0)
{
}
HFONT hfont;
int ascent;
mutable SCRIPT_CACHE scriptCache;
+ WORD spaceGlyph;
};
// Again, using hash_map does not earn us much here. page_cycler_test intl2
@@ -379,7 +393,8 @@ bool getDerivedFontData(const UChar* family,
LOGFONT* logfont,
int* ascent,
HFONT* hfont,
- SCRIPT_CACHE** scriptCache)
+ SCRIPT_CACHE** scriptCache,
+ WORD* spaceGlyph)
{
ASSERT(logfont);
ASSERT(family);
@@ -408,6 +423,7 @@ bool getDerivedFontData(const UChar* family,
// cache it so that we won't have to call CreateFontIndirect once
// more for HFONT next time.
derived->ascent = getAscent(derived->hfont);
+ derived->spaceGlyph = getSpaceGlyph(derived->hfont);
} else {
derived = &iter->second;
// Last time, GetAscent failed so that only HFONT was
@@ -419,6 +435,7 @@ bool getDerivedFontData(const UChar* family,
*hfont = derived->hfont;
*ascent = derived->ascent;
*scriptCache = &(derived->scriptCache);
+ *spaceGlyph = derived->spaceGlyph;
return *ascent != kUndefinedAscent;
}
diff --git a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h
index b637ede..d9de002 100644
--- a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h
+++ b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h
@@ -78,7 +78,7 @@ const UChar* getFallbackFamily(const UChar* characters, int length,
// intl2 page-cycler test is noticeably slower with one out param than
// the current version although the subsequent 9 passes take about the
// same time.
-bool getDerivedFontData(const UChar* family, int style, LOGFONT*, int* ascent, HFONT*, SCRIPT_CACHE**);
+bool getDerivedFontData(const UChar* family, int style, LOGFONT*, int* ascent, HFONT*, SCRIPT_CACHE**, WORD* spaceGlyph);
enum {
FontStyleNormal = 0,
diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
index cc5a060..87d54b0 100644
--- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
+++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
@@ -38,6 +38,7 @@
#include "GraphicsContext3D.h"
#include "internal_glu.h"
#include "IntRect.h"
+#include "LoopBlinnMathUtils.h"
#include "LoopBlinnPathProcessor.h"
#include "LoopBlinnSolidFillShader.h"
#include "Path.h"
@@ -60,7 +61,7 @@ namespace WebCore {
const int pathTesselation = 30;
typedef void (GLAPIENTRY *TESSCB)();
typedef WTF::Vector<float> FloatVector;
-typedef WTF::Vector<double> DoubleVector;
+typedef WTF::Vector<FloatPoint> FloatPointVector;
struct PathAndTransform {
PathAndTransform(const Path& p, const AffineTransform& t)
@@ -186,7 +187,7 @@ class Cubic {
FloatPoint d = -1.0f * p0 + 3.0f * p1s - 3.0f * p2s + p3s;
return Cubic(p0, b, c, d);
}
- FloatPoint evaluate(float t)
+ inline FloatPoint evaluate(float t)
{
return m_a + t * (m_b + t * (m_c + t * m_d));
}
@@ -198,6 +199,7 @@ GLES2Canvas::GLES2Canvas(SharedGraphicsContext3D* context, DrawingBuffer* drawin
, m_context(context)
, m_drawingBuffer(drawingBuffer)
, m_state(0)
+ , m_pathIndexBuffer(0)
, m_pathVertexBuffer(0)
{
m_flipMatrix.translate(-1.0f, 1.0f);
@@ -209,6 +211,10 @@ GLES2Canvas::GLES2Canvas(SharedGraphicsContext3D* context, DrawingBuffer* drawin
GLES2Canvas::~GLES2Canvas()
{
+ if (m_pathIndexBuffer)
+ m_context->graphicsContext3D()->deleteBuffer(m_pathIndexBuffer);
+ if (m_pathVertexBuffer)
+ m_context->graphicsContext3D()->deleteBuffer(m_pathVertexBuffer);
}
void GLES2Canvas::bindFramebuffer()
@@ -229,6 +235,13 @@ void GLES2Canvas::clearRect(const FloatRect& rect)
}
}
+void GLES2Canvas::applyState()
+{
+ bindFramebuffer();
+ m_context->applyCompositeOperator(m_state->m_compositeOp);
+ applyClipping(m_state->clippingEnabled());
+}
+
void GLES2Canvas::scissorClear(float x, float y, float width, float height)
{
int intX = static_cast<int>(x + 0.5f);
@@ -250,10 +263,7 @@ void GLES2Canvas::fillPath(const Path& path)
endShadowDraw(path.boundingRect());
}
- bindFramebuffer();
- m_context->applyCompositeOperator(m_state->m_compositeOp);
- applyClipping(m_state->clippingEnabled());
-
+ applyState();
fillPathInternal(path, m_state->applyAlpha(m_state->m_fillColor));
}
@@ -265,10 +275,7 @@ void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace
endShadowDraw(rect);
}
- bindFramebuffer();
- m_context->applyCompositeOperator(m_state->m_compositeOp);
- applyClipping(m_state->clippingEnabled());
-
+ applyState();
fillRectInternal(rect, color);
}
@@ -546,38 +553,30 @@ Texture* GLES2Canvas::getTexture(NativeImagePtr ptr)
#if USE(SKIA)
// This is actually cross-platform code, but since its only caller is inside a
// USE(SKIA), it will cause a warning-as-error on Chrome/Mac.
-static void interpolateQuadratic(DoubleVector* vertices, const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2)
+static void interpolateQuadratic(FloatPointVector* vertices, const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2)
{
float tIncrement = 1.0f / pathTesselation, t = tIncrement;
Quadratic c = Quadratic::fromBezier(p0, p1, p2);
- for (int i = 0; i < pathTesselation; ++i, t += tIncrement) {
- FloatPoint p = c.evaluate(t);
- vertices->append(p.x());
- vertices->append(p.y());
- vertices->append(1.0);
- }
+ for (int i = 0; i < pathTesselation; ++i, t += tIncrement)
+ vertices->append(c.evaluate(t));
}
-static void interpolateCubic(DoubleVector* vertices, const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3)
+static void interpolateCubic(FloatPointVector* vertices, const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3)
{
float tIncrement = 1.0f / pathTesselation, t = tIncrement;
Cubic c = Cubic::fromBezier(p0, p1, p2, p3);
- for (int i = 0; i < pathTesselation; ++i, t += tIncrement) {
- FloatPoint p = c.evaluate(t);
- vertices->append(p.x());
- vertices->append(p.y());
- vertices->append(1.0);
- }
+ for (int i = 0; i < pathTesselation; ++i, t += tIncrement)
+ vertices->append(c.evaluate(t));
}
#endif
struct PolygonData {
- PolygonData(FloatVector* vertices, WTF::Vector<short>* indices)
+ PolygonData(FloatPointVector* vertices, WTF::Vector<short>* indices)
: m_vertices(vertices)
, m_indices(indices)
{
}
- FloatVector* m_vertices;
+ FloatPointVector* m_vertices;
WTF::Vector<short>* m_indices;
};
@@ -603,22 +602,24 @@ static void combineData(GLdouble coords[3], void* vertexData[4],
GLfloat weight[4], void **outData, void* data)
{
PolygonData* polygonData = static_cast<PolygonData*>(data);
- int index = polygonData->m_vertices->size() / 3;
- polygonData->m_vertices->append(static_cast<float>(coords[0]));
- polygonData->m_vertices->append(static_cast<float>(coords[1]));
- polygonData->m_vertices->append(1.0f);
+ int index = polygonData->m_vertices->size();
+ polygonData->m_vertices->append(FloatPoint(static_cast<float>(coords[0]), static_cast<float>(coords[1])));
*outData = reinterpret_cast<void*>(index);
}
typedef void (*TESSCB)();
-void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsigned* vertexBuffer, unsigned* indexBuffer)
+void GLES2Canvas::tesselateAndFillPath(const Path& path, const Color& color)
{
- *vertexBuffer = m_context->graphicsContext3D()->createBuffer();
- checkGLError("createVertexBufferFromPath, createBuffer");
- *indexBuffer = m_context->graphicsContext3D()->createBuffer();
- checkGLError("createVertexBufferFromPath, createBuffer");
- DoubleVector inVertices;
+ if (!m_pathVertexBuffer)
+ m_pathVertexBuffer = m_context->graphicsContext3D()->createBuffer();
+ if (!m_pathIndexBuffer)
+ m_pathIndexBuffer = m_context->graphicsContext3D()->createBuffer();
+
+ AffineTransform matrix(m_flipMatrix);
+ matrix *= m_state->m_ctm;
+
+ FloatPointVector inVertices;
WTF::Vector<size_t> contours;
#if USE(SKIA)
const SkPath* skPath = path.platformPath();
@@ -628,14 +629,10 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
switch (verb) {
case SkPath::kMove_Verb:
- inVertices.append(pts[0].fX);
- inVertices.append(pts[0].fY);
- inVertices.append(1.0);
+ inVertices.append(pts[0]);
break;
case SkPath::kLine_Verb:
- inVertices.append(pts[1].fX);
- inVertices.append(pts[1].fY);
- inVertices.append(1.0);
+ inVertices.append(pts[1]);
break;
case SkPath::kQuad_Verb:
interpolateQuadratic(&inVertices, pts[0], pts[1], pts[2]);
@@ -644,7 +641,7 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig
interpolateCubic(&inVertices, pts[0], pts[1], pts[2], pts[3]);
break;
case SkPath::kClose_Verb:
- contours.append(inVertices.size() / 3);
+ contours.append(inVertices.size());
break;
case SkPath::kDone_Verb:
break;
@@ -654,6 +651,21 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig
ASSERT(!"Path extraction not implemented on this platform.");
#endif
+ if (contours.size() == 1 && LoopBlinnMathUtils::isConvex(inVertices.begin(), inVertices.size())) {
+ m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_pathVertexBuffer);
+ m_context->graphicsContext3D()->bufferData(GraphicsContext3D::ARRAY_BUFFER, inVertices.size() * 2 * sizeof(float), inVertices.data(), GraphicsContext3D::STREAM_DRAW);
+ m_context->useFillSolidProgram(matrix, color);
+ m_context->graphicsContext3D()->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, inVertices.size());
+ return;
+ }
+
+ OwnArrayPtr<double> inVerticesDouble = adoptArrayPtr(new double[inVertices.size() * 3]);
+ for (size_t i = 0; i < inVertices.size(); ++i) {
+ inVerticesDouble[i * 3 ] = inVertices[i].x();
+ inVerticesDouble[i * 3 + 1] = inVertices[i].y();
+ inVerticesDouble[i * 3 + 2] = 1.0;
+ }
+
GLUtesselator* tess = internal_gluNewTess();
internal_gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
internal_gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (TESSCB) &beginData);
@@ -662,7 +674,7 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig
internal_gluTessCallback(tess, GLU_TESS_EDGE_FLAG_DATA, (TESSCB) &edgeFlagData);
internal_gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (TESSCB) &combineData);
WTF::Vector<short> indices;
- FloatVector vertices;
+ FloatPointVector vertices;
vertices.reserveInitialCapacity(inVertices.size());
PolygonData data(&vertices, &indices);
internal_gluTessBeginPolygon(tess, &data);
@@ -671,26 +683,27 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig
for (contour = contours.begin(); contour != contours.end(); ++contour) {
internal_gluTessBeginContour(tess);
for (; i < *contour; ++i) {
- vertices.append(inVertices[i * 3]);
- vertices.append(inVertices[i * 3 + 1]);
- vertices.append(1.0f);
- internal_gluTessVertex(tess, &inVertices[i * 3], reinterpret_cast<void*>(i));
+ double* inVertex = &inVerticesDouble[i * 3];
+ vertices.append(FloatPoint(inVertex[0], inVertex[1]));
+ internal_gluTessVertex(tess, inVertex, reinterpret_cast<void*>(i));
}
internal_gluTessEndContour(tess);
}
internal_gluTessEndPolygon(tess);
internal_gluDeleteTess(tess);
- m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, *vertexBuffer);
+ m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_pathVertexBuffer);
checkGLError("createVertexBufferFromPath, bindBuffer ARRAY_BUFFER");
- m_context->graphicsContext3D()->bufferData(GraphicsContext3D::ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GraphicsContext3D::STREAM_DRAW);
+ m_context->graphicsContext3D()->bufferData(GraphicsContext3D::ARRAY_BUFFER, vertices.size() * 2 * sizeof(float), vertices.data(), GraphicsContext3D::STREAM_DRAW);
checkGLError("createVertexBufferFromPath, bufferData ARRAY_BUFFER");
- m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, *indexBuffer);
+ m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_pathIndexBuffer);
checkGLError("createVertexBufferFromPath, bindBuffer ELEMENT_ARRAY_BUFFER");
m_context->graphicsContext3D()->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(short), indices.data(), GraphicsContext3D::STREAM_DRAW);
checkGLError("createVertexBufferFromPath, bufferData ELEMENT_ARRAY_BUFFER");
- *count = indices.size();
+
+ m_context->useFillSolidProgram(matrix, color);
+ m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, indices.size(), GraphicsContext3D::UNSIGNED_SHORT, 0);
}
void GLES2Canvas::fillPathInternal(const Path& path, const Color& color)
@@ -723,29 +736,7 @@ void GLES2Canvas::fillPathInternal(const Path& path, const Color& color)
m_context->useLoopBlinnInteriorProgram(byteSizeOfVertices + byteSizeOfTexCoords, matrix, color);
m_context->drawArrays(GraphicsContext3D::TRIANGLES, 0, m_pathCache.numberOfInteriorVertices());
} else {
- int count;
- unsigned vertexBuffer, indexBuffer;
- createVertexBufferFromPath(path, &count, &vertexBuffer, &indexBuffer);
-
- AffineTransform matrix(m_flipMatrix);
- matrix *= m_state->m_ctm;
-
- m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vertexBuffer);
- checkGLError("bindBuffer");
- m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indexBuffer);
- checkGLError("bindBuffer");
-
- m_context->useFillSolidProgram(matrix, color);
- checkGLError("useFillSolidProgram");
-
- m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, count, GraphicsContext3D::UNSIGNED_SHORT, 0);
- checkGLError("drawArrays");
-
- m_context->graphicsContext3D()->deleteBuffer(vertexBuffer);
- checkGLError("deleteBuffer");
-
- m_context->graphicsContext3D()->deleteBuffer(indexBuffer);
- checkGLError("deleteBuffer");
+ tesselateAndFillPath(path, color);
}
}
@@ -787,9 +778,7 @@ void GLES2Canvas::beginShadowDraw()
m_context->clearColor(Color(RGBA32(0)));
m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
} else {
- bindFramebuffer();
- m_context->applyCompositeOperator(m_state->m_compositeOp);
- applyClipping(m_state->clippingEnabled());
+ applyState();
}
}
@@ -864,19 +853,14 @@ void GLES2Canvas::endShadowDraw(const FloatRect& boundingBox)
std::swap(srcBuffer, dstBuffer);
// Upsample srcBuffer -> main framebuffer using bicubic filtering.
- bindFramebuffer();
- m_context->applyCompositeOperator(m_state->m_compositeOp);
- applyClipping(m_state->clippingEnabled());
+ applyState();
m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, srcBuffer->colorBuffer());
FloatRect dstRect = srcRect;
dstRect.scale(scaleFactor);
drawTexturedQuadMitchell(srcBuffer->size(), flipRect(srcRect), dstRect, AffineTransform(), 1.0);
} else {
// Blur in Y directly to framebuffer.
- bindFramebuffer();
- m_context->applyCompositeOperator(m_state->m_compositeOp);
- applyClipping(m_state->clippingEnabled());
-
+ applyState();
convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementY, kernel.get(), kernelWidth);
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
index f6a8bcf..635eb10 100644
--- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
+++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
@@ -100,14 +100,14 @@ public:
DrawingBuffer* drawingBuffer() const { return m_drawingBuffer; }
private:
+ void applyState();
void scissorClear(float x, float y, float width, float height);
void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
void drawTexturedQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
void drawTexturedQuadMitchell(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
void convolveRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, float imageIncrement[2], const float* kernel, int kernelWidth);
- void applyCompositeOperator(CompositeOperator);
- void createVertexBufferFromPath(const Path&, int* count, unsigned* vertexBuffer, unsigned* indexBuffer);
+ void tesselateAndFillPath(const Path&, const Color&);
void fillPathInternal(const Path&, const Color&);
void fillRectInternal(const FloatRect&, const Color&);
FloatRect flipRect(const FloatRect&);
@@ -131,6 +131,7 @@ private:
// Members for GPU-accelerated path rendering.
LoopBlinnPathCache m_pathCache;
+ unsigned m_pathIndexBuffer;
unsigned m_pathVertexBuffer;
};
diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
index 067c54d..2301ca3 100644
--- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -283,6 +283,8 @@ void GraphicsLayerChromium::setMaskLayer(GraphicsLayer* maskLayer)
GraphicsLayer::setMaskLayer(maskLayer);
LayerChromium* maskLayerChromium = m_maskLayer ? m_maskLayer->platformLayer() : 0;
+ if (maskLayerChromium)
+ maskLayerChromium->setIsMask(true);
m_layer->setMaskLayer(maskLayerChromium);
}
diff --git a/Source/WebCore/platform/graphics/chromium/ImageBufferData.h b/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h
index 504b893..75c91ed 100644
--- a/Source/WebCore/platform/graphics/chromium/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h
@@ -28,9 +28,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ImageBufferData_h
-#define ImageBufferData_h
-
#include "PlatformContextSkia.h"
#include "skia/ext/platform_canvas.h"
@@ -41,10 +38,8 @@ class ImageBufferData {
public:
ImageBufferData(const IntSize&);
- skia::PlatformCanvas m_canvas;
+ OwnPtr<SkCanvas> m_canvas;
PlatformContextSkia m_platformContext;
};
-} // namespace WebCore
-
-#endif // ImageBufferData_h
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
index 60c1332..d72fb1e 100644
--- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
@@ -34,6 +34,7 @@
#include "ImageLayerChromium.h"
+#include "cc/CCLayerImpl.h"
#include "Image.h"
#include "LayerRendererChromium.h"
#include "LayerTexture.h"
@@ -47,42 +48,69 @@ PassRefPtr<ImageLayerChromium> ImageLayerChromium::create(GraphicsLayerChromium*
ImageLayerChromium::ImageLayerChromium(GraphicsLayerChromium* owner)
: ContentLayerChromium(owner)
+ , m_imageForCurrentFrame(0)
, m_contents(0)
{
}
void ImageLayerChromium::setContents(Image* contents)
{
- // Check if the image has changed.
- if (m_contents == contents)
+ // setContents() currently gets called whenever there is any
+ // style change that affects the layer even if that change doesn't
+ // affect the actual contents of the image (e.g. a CSS animation).
+ // With this check in place we avoid unecessary texture uploads.
+ if ((m_contents == contents) && (m_contents->nativeImageForCurrentFrame() == m_imageForCurrentFrame))
return;
+
m_contents = contents;
+ m_imageForCurrentFrame = m_contents->nativeImageForCurrentFrame();
+ m_dirtyRect = IntRect(IntPoint(0, 0), bounds());
setNeedsDisplay();
}
-void ImageLayerChromium::paintContentsIfDirty()
+void ImageLayerChromium::paintContentsIfDirty(const IntRect&)
{
ASSERT(layerRenderer());
- // FIXME: Remove this test when tiled layers are implemented.
- if (requiresClippedUpdateRect()) {
- // Use the base version of updateContents which draws a subset of the
- // image to a bitmap, as the pixel contents can't be uploaded directly.
- ContentLayerChromium::paintContentsIfDirty();
- return;
+ if (!m_dirtyRect.isEmpty()) {
+ m_decodedImage.updateFromImage(m_contents->nativeImageForCurrentFrame());
}
-
- m_decodedImage.updateFromImage(m_contents->nativeImageForCurrentFrame());
}
-void ImageLayerChromium::updateTextureIfNeeded()
+void ImageLayerChromium::updateCompositorResources()
{
- // FIXME: Remove this test when tiled layers are implemented.
- if (requiresClippedUpdateRect()) {
- ContentLayerChromium::updateTextureIfNeeded();
- return;
+ updateLayerSize(m_decodedImage.size());
+
+ IntRect paintRect(IntPoint(0, 0), m_decodedImage.size());
+ if (!m_dirtyRect.isEmpty()) {
+ m_tiler->invalidateRect(paintRect);
+ m_dirtyRect = IntRect();
}
- updateTexture(m_decodedImage.pixels(), m_decodedImage.size());
+ m_tiler->updateFromPixels(paintRect, m_decodedImage.pixels());
+}
+
+IntRect ImageLayerChromium::layerBounds() const
+{
+ return IntRect(IntPoint(0, 0), m_decodedImage.size());
+}
+
+TransformationMatrix ImageLayerChromium::tilingTransform()
+{
+ // Tiler draws from the upper left corner. The draw transform
+ // specifies the middle of the layer.
+ TransformationMatrix transform = ccLayerImpl()->drawTransform();
+ const IntRect sourceRect = layerBounds();
+ const IntSize destSize = bounds();
+
+ transform.translate(-destSize.width() / 2.0, -destSize.height() / 2.0);
+
+ // Tiler also draws at the original content size, so rescale the original
+ // image dimensions to the bounds that it is meant to be drawn at.
+ float scaleX = destSize.width() / static_cast<float>(sourceRect.size().width());
+ float scaleY = destSize.height() / static_cast<float>(sourceRect.size().height());
+ transform.scale3d(scaleX, scaleY, 1.0f);
+
+ return transform;
}
}
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
index 6addabc..8ab76a8 100644
--- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
@@ -37,7 +37,7 @@
#include "ContentLayerChromium.h"
#include "PlatformImage.h"
-#if PLATFORM(CG)
+#if USE(CG)
#include <wtf/RetainPtr.h>
#endif
@@ -50,7 +50,8 @@ class ImageLayerChromium : public ContentLayerChromium {
public:
static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0);
- virtual void paintContentsIfDirty();
+ virtual void paintContentsIfDirty(const IntRect& targetSurfaceRect);
+ virtual void updateCompositorResources();
virtual bool drawsContent() const { return m_contents; }
void setContents(Image* image);
@@ -58,12 +59,14 @@ public:
protected:
virtual const char* layerTypeAsString() const { return "ImageLayer"; }
-private:
- virtual void updateTextureIfNeeded();
+ virtual TransformationMatrix tilingTransform();
+ virtual IntRect layerBounds() const;
+private:
ImageLayerChromium(GraphicsLayerChromium* owner);
PlatformImage m_decodedImage;
+ NativeImagePtr m_imageForCurrentFrame;
RefPtr<Image> m_contents;
};
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
index bc28239..fba1dc5 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -89,6 +89,9 @@ LayerChromium::~LayerChromium()
// way for us to be destroyed while we still have a superlayer.
ASSERT(!superlayer());
+ if (m_ccLayerImpl)
+ m_ccLayerImpl->resetOwner();
+
// Remove the superlayer reference from all sublayers.
removeAllSublayers();
}
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
index 428ce61..5564f91 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -50,11 +50,6 @@
#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>
-
-namespace skia {
-class PlatformCanvas;
-}
-
namespace WebCore {
class CCLayerImpl;
@@ -113,6 +108,7 @@ public:
void setNeedsDisplay(const FloatRect& dirtyRect);
void setNeedsDisplay();
+ virtual void invalidateRect(const FloatRect& dirtyRect) {}
const FloatRect& dirtyRect() const { return m_dirtyRect; }
void resetNeedsDisplay();
@@ -156,11 +152,13 @@ public:
// These methods typically need to be overwritten by derived classes.
virtual bool drawsContent() const { return false; }
+ virtual void paintContentsIfDirty(const IntRect&) { }
virtual void paintContentsIfDirty() { }
virtual void updateCompositorResources() { }
+ virtual void setIsMask(bool) {}
virtual void unreserveContentsTexture() { }
virtual void bindContentsTexture() { }
- virtual void draw() { }
+ virtual void draw(const IntRect&) { }
// These exists just for debugging (via drawDebugBorder()).
void setBorderColor(const Color&);
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index fc15abd..27a67e9 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -34,8 +34,8 @@
#if USE(ACCELERATED_COMPOSITING)
#include "LayerRendererChromium.h"
-#include "cc/CCLayerImpl.h"
#include "Canvas2DLayerChromium.h"
+#include "Extensions3DChromium.h"
#include "FloatQuad.h"
#include "GeometryBinding.h"
#include "GraphicsContext3D.h"
@@ -50,7 +50,7 @@
#if USE(SKIA)
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
-#elif PLATFORM(CG)
+#elif USE(CG)
#include <CoreGraphics/CGBitmapContext.h>
#endif
@@ -88,35 +88,38 @@ static bool isScaleOrTranslation(const TransformationMatrix& m)
}
-bool LayerRendererChromium::compareLayerZ(const CCLayerImpl* a, const CCLayerImpl* b)
+bool LayerRendererChromium::compareLayerZ(const RefPtr<CCLayerImpl>& a, const RefPtr<CCLayerImpl>& b)
{
return a->drawDepth() < b->drawDepth();
}
-PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint)
+PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint)
{
if (!context)
return 0;
- RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context, contentPaint, scrollbarPaint)));
+ RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context, contentPaint)));
if (!layerRenderer->hardwareCompositing())
return 0;
return layerRenderer.release();
}
-LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint)
+LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context,
+ PassOwnPtr<TilePaintInterface> contentPaint)
: m_viewportScrollPosition(IntPoint(-1, -1))
, m_rootLayer(0)
, m_rootLayerContentPaint(contentPaint)
- , m_rootLayerScrollbarPaint(scrollbarPaint)
, m_currentShader(0)
, m_currentRenderSurface(0)
, m_offscreenFramebufferId(0)
, m_compositeOffscreen(false)
, m_context(context)
+ , m_childContextsWereCopied(false)
+ , m_contextSupportsLatch(false)
, m_defaultRenderSurface(0)
{
+ m_contextSupportsLatch = m_context->getExtensions()->supports("GL_CHROMIUM_latch");
m_hardwareCompositing = initializeSharedObjects();
m_rootLayerContentTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels);
ASSERT(m_rootLayerContentTiler);
@@ -150,40 +153,9 @@ void LayerRendererChromium::useShader(unsigned programId)
}
}
-IntRect LayerRendererChromium::verticalScrollbarRect() const
-{
- IntRect verticalScrollbar(IntPoint(m_viewportContentRect.maxX(), m_viewportContentRect.y()), IntSize(m_viewportVisibleRect.width() - m_viewportContentRect.width(), m_viewportVisibleRect.height()));
- return verticalScrollbar;
-}
-
-IntRect LayerRendererChromium::horizontalScrollbarRect() const
-{
- IntRect horizontalScrollbar(IntPoint(m_viewportContentRect.x(), m_viewportContentRect.maxY()), IntSize(m_viewportVisibleRect.width(), m_viewportVisibleRect.height() - m_viewportContentRect.height()));
- return horizontalScrollbar;
-}
-
void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect)
{
m_rootLayerContentTiler->invalidateRect(dirtyRect);
-
- // Scrollbars never need to render beyond the fold, so clip to the viewport.
- IntRect visibleDirtyRect = dirtyRect;
- visibleDirtyRect.intersect(m_viewportVisibleRect);
-
- if (m_horizontalScrollbarTiler) {
- IntRect scrollbar = horizontalScrollbarRect();
- if (visibleDirtyRect.intersects(scrollbar)) {
- m_horizontalScrollbarTiler->setLayerPosition(scrollbar.location());
- m_horizontalScrollbarTiler->invalidateRect(visibleDirtyRect);
- }
- }
- if (m_verticalScrollbarTiler) {
- IntRect scrollbar = verticalScrollbarRect();
- if (visibleDirtyRect.intersects(scrollbar)) {
- m_verticalScrollbarTiler->setLayerPosition(scrollbar.location());
- m_verticalScrollbarTiler->invalidateRect(visibleDirtyRect);
- }
- }
}
void LayerRendererChromium::updateRootLayerContents()
@@ -192,43 +164,14 @@ void LayerRendererChromium::updateRootLayerContents()
m_rootLayerContentTiler->update(*m_rootLayerContentPaint, m_viewportVisibleRect);
}
-void LayerRendererChromium::updateRootLayerScrollbars()
-{
- TRACE_EVENT("LayerRendererChromium::updateRootLayerScrollbars", this, 0);
- if (m_viewportVisibleRect.width() > m_viewportContentRect.width()) {
- IntRect verticalScrollbar = verticalScrollbarRect();
- IntSize tileSize = verticalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize));
- if (!m_verticalScrollbarTiler)
- m_verticalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels);
- else
- m_verticalScrollbarTiler->setTileSize(tileSize);
- m_verticalScrollbarTiler->setLayerPosition(verticalScrollbar.location());
- m_verticalScrollbarTiler->update(*m_rootLayerScrollbarPaint, m_viewportVisibleRect);
- } else
- m_verticalScrollbarTiler.clear();
-
- if (m_viewportVisibleRect.height() > m_viewportContentRect.height()) {
- IntRect horizontalScrollbar = horizontalScrollbarRect();
- IntSize tileSize = horizontalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize));
- if (!m_horizontalScrollbarTiler)
- m_horizontalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels);
- else
- m_horizontalScrollbarTiler->setTileSize(tileSize);
- m_horizontalScrollbarTiler->setLayerPosition(horizontalScrollbar.location());
- m_horizontalScrollbarTiler->update(*m_rootLayerScrollbarPaint, m_viewportVisibleRect);
- } else
- m_horizontalScrollbarTiler.clear();
-}
-
void LayerRendererChromium::drawRootLayer()
{
- m_rootLayerContentTiler->draw(m_viewportVisibleRect);
-
- if (m_verticalScrollbarTiler)
- m_verticalScrollbarTiler->draw(m_viewportVisibleRect);
+ TransformationMatrix scroll;
+ scroll.translate(-m_viewportVisibleRect.x(), -m_viewportVisibleRect.y());
- if (m_horizontalScrollbarTiler)
- m_horizontalScrollbarTiler->draw(m_viewportVisibleRect);
+ m_rootLayerContentTiler->uploadCanvas();
+ m_rootLayerContentTiler->draw(m_viewportVisibleRect, scroll, 1.0f);
+ m_rootLayerContentTiler->unreserveTextures();
}
void LayerRendererChromium::setViewport(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition)
@@ -243,12 +186,7 @@ void LayerRendererChromium::setViewport(const IntRect& visibleRect, const IntRec
// Reset the current render surface to force an update of the viewport and
// projection matrix next time useRenderSurface is called.
m_currentRenderSurface = 0;
-
m_rootLayerContentTiler->invalidateEntireLayer();
- if (m_horizontalScrollbarTiler)
- m_horizontalScrollbarTiler->invalidateEntireLayer();
- if (m_verticalScrollbarTiler)
- m_verticalScrollbarTiler->invalidateEntireLayer();
}
}
@@ -266,18 +204,56 @@ void LayerRendererChromium::updateAndDrawLayers()
if (!m_rootLayer)
return;
- updateRootLayerScrollbars();
+ LayerList renderSurfaceLayerList;
- Vector<CCLayerImpl*> renderSurfaceLayerList;
updateLayers(renderSurfaceLayerList);
+ // Before drawLayers:
+ if (hardwareCompositing() && m_contextSupportsLatch) {
+ // FIXME: The multithreaded compositor case will not work as long as
+ // copyTexImage2D resolves to the parent texture, because the main
+ // thread can execute WebGL calls on the child context at any time,
+ // potentially clobbering the parent texture that is being renderered
+ // by the compositor thread.
+ if (m_childContextsWereCopied) {
+ Extensions3DChromium* parentExt = static_cast<Extensions3DChromium*>(m_context->getExtensions());
+ // For each child context:
+ // glWaitLatch(Offscreen->Compositor);
+ ChildContextMap::iterator i = m_childContexts.begin();
+ for (; i != m_childContexts.end(); ++i) {
+ Extensions3DChromium* childExt = static_cast<Extensions3DChromium*>(i->first->getExtensions());
+ GC3Duint latchId;
+ childExt->getChildToParentLatchCHROMIUM(&latchId);
+ parentExt->waitLatchCHROMIUM(latchId);
+ }
+ }
+ // Reset to false to indicate that we have consumed the dirty child
+ // contexts' parent textures. (This is only useful when the compositor
+ // is multithreaded.)
+ m_childContextsWereCopied = false;
+ }
+
drawLayers(renderSurfaceLayerList);
+ // After drawLayers:
+ if (hardwareCompositing() && m_contextSupportsLatch) {
+ Extensions3DChromium* parentExt = static_cast<Extensions3DChromium*>(m_context->getExtensions());
+ // For each child context:
+ // glSetLatch(Compositor->Offscreen);
+ ChildContextMap::iterator i = m_childContexts.begin();
+ for (; i != m_childContexts.end(); ++i) {
+ Extensions3DChromium* childExt = static_cast<Extensions3DChromium*>(i->first->getExtensions());
+ GC3Duint latchId;
+ childExt->getParentToChildLatchCHROMIUM(&latchId);
+ parentExt->setLatchCHROMIUM(latchId);
+ }
+ }
+
if (isCompositingOffscreen())
copyOffscreenTextureToDisplay();
}
-void LayerRendererChromium::updateLayers(Vector<CCLayerImpl*>& renderSurfaceLayerList)
+void LayerRendererChromium::updateLayers(LayerList& renderSurfaceLayerList)
{
TRACE_EVENT("LayerRendererChromium::updateLayers", this, 0);
m_rootLayer->createCCLayerImplIfNeeded();
@@ -289,8 +265,7 @@ void LayerRendererChromium::updateLayers(Vector<CCLayerImpl*>& renderSurfaceLaye
rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), m_viewportVisibleRect.size());
- // Scissor out the scrollbars to avoid rendering on top of them.
- IntRect rootScissorRect(m_viewportContentRect);
+ IntRect rootScissorRect(m_viewportVisibleRect);
// The scissorRect should not include the scroll offset.
rootScissorRect.move(-m_viewportScrollPosition.x(), -m_viewportScrollPosition.y());
rootDrawLayer->setScissorRect(rootScissorRect);
@@ -309,10 +284,51 @@ void LayerRendererChromium::updateLayers(Vector<CCLayerImpl*>& renderSurfaceLaye
paintContentsRecursive(m_rootLayer.get());
+ // FIXME: Before updateCompositorResourcesRecursive, when the compositor runs in
+ // its own thread, and when the copyTexImage2D bug is fixed, insert
+ // a glWaitLatch(Compositor->Offscreen) on all child contexts here instead
+ // of after updateCompositorResourcesRecursive.
+ // Also uncomment the glSetLatch(Compositor->Offscreen) code in addChildContext.
+// if (hardwareCompositing() && m_contextSupportsLatch) {
+// // For each child context:
+// // glWaitLatch(Compositor->Offscreen);
+// ChildContextMap::iterator i = m_childContexts.begin();
+// for (; i != m_childContexts.end(); ++i) {
+// Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(i->first->getExtensions());
+// GC3Duint childToParentLatchId, parentToChildLatchId;
+// ext->getParentToChildLatchCHROMIUM(&parentToChildLatchId);
+// ext->waitLatchCHROMIUM(parentToChildLatchId);
+// }
+// }
+
updateCompositorResourcesRecursive(m_rootLayer.get());
+
+ // After updateCompositorResourcesRecursive, set/wait latches for all child
+ // contexts. This will prevent the compositor from using any of the child
+ // parent textures while WebGL commands are executing from javascript *and*
+ // while the final parent texture is being blit'd. copyTexImage2D
+ // uses the parent texture as a temporary resolve buffer, so that's why the
+ // waitLatch is below, to block the compositor from using the parent texture
+ // until the next WebGL SwapBuffers (or copyTextureToParentTexture for
+ // Canvas2D).
+ if (hardwareCompositing() && m_contextSupportsLatch) {
+ m_childContextsWereCopied = true;
+ // For each child context:
+ // glSetLatch(Offscreen->Compositor);
+ // glWaitLatch(Compositor->Offscreen);
+ ChildContextMap::iterator i = m_childContexts.begin();
+ for (; i != m_childContexts.end(); ++i) {
+ Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(i->first->getExtensions());
+ GC3Duint childToParentLatchId, parentToChildLatchId;
+ ext->getParentToChildLatchCHROMIUM(&parentToChildLatchId);
+ ext->getChildToParentLatchCHROMIUM(&childToParentLatchId);
+ ext->setLatchCHROMIUM(childToParentLatchId);
+ ext->waitLatchCHROMIUM(parentToChildLatchId);
+ }
+ }
}
-void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList)
+void LayerRendererChromium::drawLayers(const LayerList& renderSurfaceLayerList)
{
TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0);
CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl();
@@ -347,13 +363,14 @@ void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurface
m_context->colorMask(true, true, true, true);
GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
+ GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
// Update the contents of the render surfaces. We traverse the array from
// back to front to guarantee that nested render surfaces get rendered in the
// correct order.
for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
- CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
+ CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get();
ASSERT(renderSurfaceLayer->renderSurface());
// Render surfaces whose drawable area has zero width or height
@@ -369,10 +386,10 @@ void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurface
GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
}
- Vector<CCLayerImpl*>& layerList = renderSurfaceLayer->renderSurface()->m_layerList;
+ LayerList& layerList = renderSurfaceLayer->renderSurface()->m_layerList;
ASSERT(layerList.size());
for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex)
- drawLayer(layerList[layerIndex], renderSurfaceLayer->renderSurface());
+ drawLayer(layerList[layerIndex].get(), renderSurfaceLayer->renderSurface());
}
}
@@ -412,10 +429,6 @@ void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer)
if (m_rootLayer)
m_rootLayer->setLayerRenderer(this);
m_rootLayerContentTiler->invalidateEntireLayer();
- if (m_horizontalScrollbarTiler)
- m_horizontalScrollbarTiler->invalidateEntireLayer();
- if (m_verticalScrollbarTiler)
- m_verticalScrollbarTiler->invalidateEntireLayer();
}
void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
@@ -473,7 +486,7 @@ bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const Transform
// Recursively walks the layer tree starting at the given node and computes all the
// necessary transformations, scissor rectangles, render surfaces, etc.
-void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList)
+void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* layer, const TransformationMatrix& parentMatrix, LayerList& renderSurfaceLayerList, LayerList& layerList)
{
// Make sure we have CCLayerImpls for this subtree.
layer->createCCLayerImplIfNeeded();
@@ -659,7 +672,18 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
// M[s] = M * Tr[-center]
sublayerMatrix.translate3d(-bounds.width() * 0.5, -bounds.height() * 0.5, 0);
- Vector<CCLayerImpl*>& descendants = (drawLayer->renderSurface() ? drawLayer->renderSurface()->m_layerList : layerList);
+ // Compute the depth value of the center of the layer which will be used when
+ // sorting the layers for the preserves-3d property.
+ const TransformationMatrix& layerDrawMatrix = drawLayer->renderSurface() ? drawLayer->renderSurface()->m_drawTransform : drawLayer->drawTransform();
+ if (drawLayer->superlayer()) {
+ if (!drawLayer->superlayer()->preserves3D())
+ drawLayer->setDrawDepth(drawLayer->superlayer()->drawDepth());
+ else
+ drawLayer->setDrawDepth(layerDrawMatrix.m43());
+ } else
+ drawLayer->setDrawDepth(0);
+
+ LayerList& descendants = (drawLayer->renderSurface() ? drawLayer->renderSurface()->m_layerList : layerList);
descendants.append(drawLayer);
unsigned thisLayerIndex = descendants.size() - 1;
@@ -730,17 +754,6 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay
}
}
- // Compute the depth value of the center of the layer which will be used when
- // sorting the layers for the preserves-3d property.
- const TransformationMatrix& layerDrawMatrix = drawLayer->renderSurface() ? drawLayer->renderSurface()->m_drawTransform : drawLayer->drawTransform();
- if (drawLayer->superlayer()) {
- if (!drawLayer->superlayer()->preserves3D())
- drawLayer->setDrawDepth(drawLayer->superlayer()->drawDepth());
- else
- drawLayer->setDrawDepth(layerDrawMatrix.m43());
- } else
- drawLayer->setDrawDepth(0);
-
// If preserves-3d then sort all the descendants by the Z coordinate of their
// center. If the preserves-3d property is also set on the superlayer then
// skip the sorting as the superlayer will sort all the descendants anyway.
@@ -757,14 +770,16 @@ void LayerRendererChromium::paintContentsRecursive(LayerChromium* layer)
if (layer->bounds().isEmpty())
return;
+ const IntRect targetSurfaceRect = layer->ccLayerImpl()->scissorRect();
+
if (layer->drawsContent())
- layer->paintContentsIfDirty();
+ layer->paintContentsIfDirty(targetSurfaceRect);
if (layer->maskLayer() && layer->maskLayer()->drawsContent())
- layer->maskLayer()->paintContentsIfDirty();
+ layer->maskLayer()->paintContentsIfDirty(targetSurfaceRect);
if (layer->replicaLayer() && layer->replicaLayer()->drawsContent())
- layer->replicaLayer()->paintContentsIfDirty();
+ layer->replicaLayer()->paintContentsIfDirty(targetSurfaceRect);
if (layer->replicaLayer() && layer->replicaLayer()->maskLayer() && layer->replicaLayer()->maskLayer()->drawsContent())
- layer->replicaLayer()->maskLayer()->paintContentsIfDirty();
+ layer->replicaLayer()->maskLayer()->paintContentsIfDirty(targetSurfaceRect);
}
void LayerRendererChromium::updateCompositorResourcesRecursive(LayerChromium* layer)
@@ -816,7 +831,7 @@ void LayerRendererChromium::copyOffscreenTextureToDisplay()
m_defaultRenderSurface->m_drawTransform.translate3d(0.5 * m_defaultRenderSurface->m_contentRect.width(),
0.5 * m_defaultRenderSurface->m_contentRect.height(), 0);
m_defaultRenderSurface->m_drawOpacity = 1;
- m_defaultRenderSurface->draw();
+ m_defaultRenderSurface->draw(m_defaultRenderSurface->m_contentRect);
}
}
@@ -857,10 +872,13 @@ bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurfac
void LayerRendererChromium::drawLayer(CCLayerImpl* layer, RenderSurfaceChromium* targetSurface)
{
if (layer->renderSurface() && layer->renderSurface() != targetSurface) {
- layer->renderSurface()->draw();
+ layer->renderSurface()->draw(layer->getDrawRect());
return;
}
+ if (!layer->drawsContent())
+ return;
+
if (layer->bounds().isEmpty()) {
layer->unreserveContentsTexture();
return;
@@ -894,8 +912,7 @@ void LayerRendererChromium::drawLayer(CCLayerImpl* layer, RenderSurfaceChromium*
}
}
- if (layer->drawsContent())
- layer->draw();
+ layer->draw(layer->scissorRect());
// Draw the debug border if there is one.
layer->drawDebugBorder();
@@ -968,7 +985,6 @@ bool LayerRendererChromium::initializeSharedObjects()
m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get()));
m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get()));
- m_contentLayerProgram = adoptPtr(new ContentLayerChromium::Program(m_context.get()));
m_canvasLayerProgram = adoptPtr(new CCCanvasLayerImpl::Program(m_context.get()));
m_videoLayerRGBAProgram = adoptPtr(new CCVideoLayerImpl::RGBAProgram(m_context.get()));
m_videoLayerYUVProgram = adoptPtr(new CCVideoLayerImpl::YUVProgram(m_context.get()));
@@ -978,7 +994,7 @@ bool LayerRendererChromium::initializeSharedObjects()
m_tilerProgram = adoptPtr(new LayerTilerChromium::Program(m_context.get()));
if (!m_sharedGeometry->initialized() || !m_borderProgram->initialized()
- || !m_contentLayerProgram->initialized() || !m_canvasLayerProgram->initialized()
+ || !m_canvasLayerProgram->initialized()
|| !m_videoLayerRGBAProgram->initialized() || !m_videoLayerYUVProgram->initialized()
|| !m_pluginLayerProgram->initialized() || !m_renderSurfaceProgram->initialized()
|| !m_renderSurfaceMaskProgram->initialized() || !m_tilerProgram->initialized()) {
@@ -997,7 +1013,6 @@ void LayerRendererChromium::cleanupSharedObjects()
m_sharedGeometry.clear();
m_borderProgram.clear();
- m_contentLayerProgram.clear();
m_canvasLayerProgram.clear();
m_videoLayerRGBAProgram.clear();
m_videoLayerYUVProgram.clear();
@@ -1010,8 +1025,6 @@ void LayerRendererChromium::cleanupSharedObjects()
// Clear tilers before the texture manager, as they have references to textures.
m_rootLayerContentTiler.clear();
- m_horizontalScrollbarTiler.clear();
- m_verticalScrollbarTiler.clear();
m_textureManager.clear();
}
@@ -1027,6 +1040,48 @@ String LayerRendererChromium::layerTreeAsText() const
return ts.release();
}
+void LayerRendererChromium::addChildContext(GraphicsContext3D* ctx)
+{
+ if (!ctx->getExtensions()->supports("GL_CHROMIUM_latch"))
+ return;
+
+ // This is a ref-counting map, because some contexts are shared by multiple
+ // layers (specifically, Canvas2DLayerChromium).
+
+ // Insert the ctx with a count of 1, or return the existing iterator.
+ std::pair<ChildContextMap::iterator, bool> insert_result = m_childContexts.add(ctx, 1);
+ if (!insert_result.second) {
+ // Already present in map, so increment.
+ ++insert_result.first->second;
+ } else {
+// FIXME(jbates): when compositor is multithreaded and copyTexImage2D bug is fixed,
+// uncomment this block:
+// // This is a new child context - set the parentToChild latch so that it
+// // can continue past its first wait latch.
+// Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(ctx->getExtensions());
+// GC3Duint latchId;
+// ext->getParentToChildLatchCHROMIUM(&latchId);
+// ext->setLatchCHROMIUM(0, latchId);
+ }
+}
+
+void LayerRendererChromium::removeChildContext(GraphicsContext3D* ctx)
+{
+ if (!ctx->getExtensions()->supports("GL_CHROMIUM_latch"))
+ return;
+
+ ChildContextMap::iterator i = m_childContexts.find(ctx);
+ if (i != m_childContexts.end()) {
+ if (--i->second <= 0) {
+ // Count reached zero, so remove from map.
+ m_childContexts.remove(i);
+ }
+ } else {
+ // error
+ ASSERT(0 && "m_childContexts map has mismatched add/remove calls");
+ }
+}
+
void LayerRendererChromium::dumpRenderSurfaces(TextStream& ts, int indent, LayerChromium* layer) const
{
if (layer->ccLayerImpl()->renderSurface())
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
index 667ede2..813eb46 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -52,22 +52,22 @@
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>
-#if PLATFORM(CG)
+#if USE(CG)
#include <CoreGraphics/CGContext.h>
#include <wtf/RetainPtr.h>
#endif
namespace WebCore {
+class CCHeadsUpDisplay;
class CCLayerImpl;
class GeometryBinding;
class GraphicsContext3D;
-class CCHeadsUpDisplay;
// Class that handles drawing of composited render layers using GL.
class LayerRendererChromium : public RefCounted<LayerRendererChromium> {
public:
- static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint);
+ static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint);
~LayerRendererChromium();
@@ -88,7 +88,7 @@ public:
IntSize viewportSize() const { return m_viewportVisibleRect.size(); }
- void setRootLayer(PassRefPtr<LayerChromium> layer);
+ void setRootLayer(PassRefPtr<LayerChromium>);
LayerChromium* rootLayer() { return m_rootLayer.get(); }
void transferRootLayer(LayerRendererChromium* other) { other->m_rootLayer = m_rootLayer.release(); }
@@ -110,7 +110,6 @@ public:
const GeometryBinding* sharedGeometry() const { return m_sharedGeometry.get(); }
const LayerChromium::BorderProgram* borderProgram() const { return m_borderProgram.get(); }
- const ContentLayerChromium::Program* contentLayerProgram() const { return m_contentLayerProgram.get(); }
const RenderSurfaceChromium::Program* renderSurfaceProgram() const { return m_renderSurfaceProgram.get(); }
const RenderSurfaceChromium::MaskProgram* renderSurfaceMaskProgram() const { return m_renderSurfaceMaskProgram.get(); }
const LayerTilerChromium::Program* tilerProgram() const { return m_tilerProgram.get(); }
@@ -131,17 +130,23 @@ public:
String layerTreeAsText() const;
+ void addChildContext(GraphicsContext3D*);
+ void removeChildContext(GraphicsContext3D*);
+
private:
- explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint);
+ typedef Vector<RefPtr<CCLayerImpl> > LayerList;
+ typedef HashMap<GraphicsContext3D*, int> ChildContextMap;
+
+ explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint);
- void updateLayers(Vector<CCLayerImpl*>& renderSurfaceLayerList);
+ void updateLayers(LayerList& renderSurfaceLayerList);
void updateRootLayerContents();
- void updateRootLayerScrollbars();
- void updatePropertiesAndRenderSurfaces(LayerChromium*, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList);
+ void updatePropertiesAndRenderSurfaces(LayerChromium*, const TransformationMatrix& parentMatrix, LayerList& renderSurfaceLayerList, LayerList& layers);
+
void paintContentsRecursive(LayerChromium*);
void updateCompositorResourcesRecursive(LayerChromium*);
- void drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList);
+ void drawLayers(const LayerList& renderSurfaceLayerList);
void drawLayer(CCLayerImpl*, RenderSurfaceChromium*);
void drawRootLayer();
@@ -156,16 +161,13 @@ private:
bool makeContextCurrent();
- static bool compareLayerZ(const CCLayerImpl*, const CCLayerImpl*);
+ static bool compareLayerZ(const RefPtr<CCLayerImpl>&, const RefPtr<CCLayerImpl>&);
void dumpRenderSurfaces(TextStream&, int indent, LayerChromium*) const;
bool initializeSharedObjects();
void cleanupSharedObjects();
- IntRect verticalScrollbarRect() const;
- IntRect horizontalScrollbarRect() const;
-
IntRect m_viewportVisibleRect;
IntRect m_viewportContentRect;
IntPoint m_viewportScrollPosition;
@@ -174,10 +176,7 @@ private:
RefPtr<LayerChromium> m_rootLayer;
OwnPtr<TilePaintInterface> m_rootLayerContentPaint;
- OwnPtr<TilePaintInterface> m_rootLayerScrollbarPaint;
OwnPtr<LayerTilerChromium> m_rootLayerContentTiler;
- OwnPtr<LayerTilerChromium> m_horizontalScrollbarTiler;
- OwnPtr<LayerTilerChromium> m_verticalScrollbarTiler;
bool m_hardwareCompositing;
@@ -188,10 +187,10 @@ private:
bool m_compositeOffscreen;
#if USE(SKIA)
- OwnPtr<skia::PlatformCanvas> m_rootLayerCanvas;
+ OwnPtr<SkCanvas> m_rootLayerCanvas;
OwnPtr<PlatformContextSkia> m_rootLayerSkiaContext;
OwnPtr<GraphicsContext> m_rootLayerGraphicsContext;
-#elif PLATFORM(CG)
+#elif USE(CG)
Vector<uint8_t> m_rootLayerBackingStore;
RetainPtr<CGContextRef> m_rootLayerCGContext;
OwnPtr<GraphicsContext> m_rootLayerGraphicsContext;
@@ -206,7 +205,6 @@ private:
// we cannot store these values in static variables.
OwnPtr<GeometryBinding> m_sharedGeometry;
OwnPtr<LayerChromium::BorderProgram> m_borderProgram;
- OwnPtr<ContentLayerChromium::Program> m_contentLayerProgram;
OwnPtr<RenderSurfaceChromium::Program> m_renderSurfaceProgram;
OwnPtr<RenderSurfaceChromium::MaskProgram> m_renderSurfaceMaskProgram;
OwnPtr<LayerTilerChromium::Program> m_tilerProgram;
@@ -220,6 +218,15 @@ private:
OwnPtr<CCHeadsUpDisplay> m_headsUpDisplay;
RefPtr<GraphicsContext3D> m_context;
+ ChildContextMap m_childContexts;
+
+ // If true, the child contexts were copied to the compositor texture targets
+ // and the compositor will need to wait on the proper latches before using
+ // the target textures. If false, the compositor is reusing the textures
+ // from last frame.
+ bool m_childContextsWereCopied;
+
+ bool m_contextSupportsLatch;
RenderSurfaceChromium* m_defaultRenderSurface;
};
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
index bc37201..54c6ac2 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
@@ -40,6 +40,8 @@
using namespace std;
+static int minTextureSize = 16;
+
namespace WebCore {
PassOwnPtr<LayerTilerChromium> LayerTilerChromium::create(LayerRendererChromium* layerRenderer, const IntSize& tileSize, BorderTexelOption border)
@@ -69,8 +71,10 @@ GraphicsContext3D* LayerTilerChromium::layerRendererContext() const
return layerRenderer()->context();
}
-void LayerTilerChromium::setTileSize(const IntSize& size)
+void LayerTilerChromium::setTileSize(const IntSize& requestedSize)
{
+ IntSize size(max(minTextureSize, requestedSize.width()), max(minTextureSize, requestedSize.height()));
+
if (m_tileSize == size)
return;
@@ -81,6 +85,12 @@ void LayerTilerChromium::setTileSize(const IntSize& size)
m_tilingData.setMaxTextureSize(max(size.width(), size.height()));
}
+LayerTexture* LayerTilerChromium::getSingleTexture()
+{
+ Tile* tile = tileAt(0, 0);
+ return tile ? tile->texture() : 0;
+}
+
void LayerTilerChromium::reset()
{
m_tiles.clear();
@@ -180,7 +190,7 @@ IntRect LayerTilerChromium::tileLayerRect(const Tile* tile) const
void LayerTilerChromium::invalidateRect(const IntRect& contentRect)
{
- if (contentRect.isEmpty())
+ if (contentRect.isEmpty() || m_skipsDraw)
return;
growLayerToContain(contentRect);
@@ -236,6 +246,8 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont
tile = createTile(i, j);
if (!tile->texture()->isValid(m_tileSize, GraphicsContext3D::RGBA))
tile->m_dirtyLayerRect = tileLayerRect(tile);
+ else
+ tile->texture()->reserve(m_tileSize, GraphicsContext3D::RGBA);
dirtyLayerRect.unite(tile->m_dirtyLayerRect);
}
}
@@ -243,27 +255,35 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont
if (dirtyLayerRect.isEmpty())
return;
- const IntRect paintRect = layerRectToContentRect(dirtyLayerRect);
+ m_paintRect = layerRectToContentRect(dirtyLayerRect);
+
+ m_canvas.resize(m_paintRect.size());
- m_canvas.resize(paintRect.size());
- PlatformCanvas::Painter canvasPainter(&m_canvas);
- canvasPainter.context()->translate(-paintRect.x(), -paintRect.y());
+ // Assumption: if a tiler is using border texels, then it is because the
+ // layer is likely to be filtered or transformed. Because of it might be
+ // transformed, draw the text in grayscale instead of subpixel antialiasing.
+ PlatformCanvas::Painter::TextOption textOption = m_tilingData.borderTexels() ? PlatformCanvas::Painter::GrayscaleText : PlatformCanvas::Painter::SubpixelText;
+ PlatformCanvas::Painter canvasPainter(&m_canvas, textOption);
+ canvasPainter.context()->translate(-m_paintRect.x(), -m_paintRect.y());
{
TRACE_EVENT("LayerTilerChromium::update::paint", this, 0);
- painter.paint(*canvasPainter.context(), paintRect);
+ painter.paint(*canvasPainter.context(), m_paintRect);
}
+}
+void LayerTilerChromium::uploadCanvas()
+{
PlatformCanvas::AutoLocker locker(&m_canvas);
{
TRACE_EVENT("LayerTilerChromium::updateFromPixels", this, 0);
- updateFromPixels(paintRect, locker.pixels());
+ updateFromPixels(m_paintRect, locker.pixels());
}
}
void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_t* paintPixels)
{
// Painting could cause compositing to get turned off, which may cause the tiler to become invalidated mid-update.
- if (!m_tiles.size())
+ if (!m_tilingData.totalSizeX() || !m_tilingData.totalSizeY())
return;
GraphicsContext3D* context = layerRendererContext();
@@ -274,21 +294,26 @@ void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_
for (int i = left; i <= right; ++i) {
Tile* tile = tileAt(i, j);
if (!tile)
- CRASH();
- if (!tile->dirty())
+ tile = createTile(i, j);
+ else if (!tile->dirty())
continue;
// Calculate page-space rectangle to copy from.
IntRect sourceRect = tileContentRect(tile);
const IntPoint anchor = sourceRect.location();
sourceRect.intersect(layerRectToContentRect(tile->m_dirtyLayerRect));
+ // Paint rect not guaranteed to line up on tile boundaries, so
+ // make sure that sourceRect doesn't extend outside of it.
+ sourceRect.intersect(paintRect);
if (sourceRect.isEmpty())
continue;
- if (!tile->texture()->reserve(m_tileSize, GraphicsContext3D::RGBA)) {
- m_skipsDraw = true;
- reset();
- return;
+ if (!tile->texture()->isReserved()) {
+ if (!tile->texture()->reserve(m_tileSize, GraphicsContext3D::RGBA)) {
+ m_skipsDraw = true;
+ reset();
+ return;
+ }
}
// Calculate tile-space rectangle to upload into.
@@ -324,8 +349,10 @@ void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_
}
tile->texture()->bindTexture();
- GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST));
- GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST));
+
+ const GC3Dint filter = m_tilingData.borderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST;
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, filter));
+ GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, filter));
GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, destRect.x(), destRect.y(), destRect.width(), destRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixelSource));
@@ -339,7 +366,7 @@ void LayerTilerChromium::setLayerPosition(const IntPoint& layerPosition)
m_layerPosition = layerPosition;
}
-void LayerTilerChromium::draw(const IntRect& contentRect)
+void LayerTilerChromium::draw(const IntRect& contentRect, const TransformationMatrix& globalTransform, float opacity)
{
if (m_skipsDraw || !m_tiles.size())
return;
@@ -354,17 +381,18 @@ void LayerTilerChromium::draw(const IntRect& contentRect)
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
Tile* tile = tileAt(i, j);
- ASSERT(tile);
+ if (!tile)
+ continue;
tile->texture()->bindTexture();
- TransformationMatrix tileMatrix;
+ TransformationMatrix tileMatrix(globalTransform);
// Don't use tileContentRect here, as that contains the full
// rect with border texels which shouldn't be drawn.
IntRect tileRect = m_tilingData.tileBounds(m_tilingData.tileIndex(tile->i(), tile->j()));
tileRect.move(m_layerPosition.x(), m_layerPosition.y());
- tileMatrix.translate3d(tileRect.x() - contentRect.x() + tileRect.width() / 2.0, tileRect.y() - contentRect.y() + tileRect.height() / 2.0, 0);
+ tileMatrix.translate3d(tileRect.x() + tileRect.width() / 2.0, tileRect.y() + tileRect.height() / 2.0, 0);
IntPoint texOffset = m_tilingData.textureOffset(tile->i(), tile->j());
float tileWidth = static_cast<float>(m_tileSize.width());
@@ -374,13 +402,21 @@ void LayerTilerChromium::draw(const IntRect& contentRect)
float texScaleX = tileRect.width() / tileWidth;
float texScaleY = tileRect.height() / tileHeight;
- drawTexturedQuad(context, layerRenderer()->projectionMatrix(), tileMatrix, tileRect.width(), tileRect.height(), 1, texTranslateX, texTranslateY, texScaleX, texScaleY, program);
-
- tile->texture()->unreserve();
+ drawTexturedQuad(context, layerRenderer()->projectionMatrix(), tileMatrix, tileRect.width(), tileRect.height(), opacity, texTranslateX, texTranslateY, texScaleX, texScaleY, program);
}
}
}
+void LayerTilerChromium::unreserveTextures()
+{
+ for (TileMap::iterator iter = m_tiles.begin(); iter != m_tiles.end(); ++iter) {
+ Tile* tile = iter->second.get();
+ if (!tile)
+ continue;
+ tile->texture()->unreserve();
+ }
+}
+
void LayerTilerChromium::growLayerToContain(const IntRect& contentRect)
{
// Grow the tile array to contain this content rect.
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h
index 2f356e4..111dd7e 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h
@@ -56,19 +56,40 @@ public:
~LayerTilerChromium();
+ // Set invalidations to be potentially repainted during update().
void invalidateRect(const IntRect& contentRect);
void invalidateEntireLayer();
+
+ // Paint all invalidations and missing tiles needed to draw the contentRect
+ // into the internal canvas.
void update(TilePaintInterface& painter, const IntRect& contentRect);
+
+ // Reserve and upload tile textures from the internal canvas.
+ void uploadCanvas();
+
+ // Reserve and upload tile textures from an externally painted buffer.
void updateFromPixels(const IntRect& paintRect, const uint8_t* pixels);
- void draw(const IntRect& contentRect);
+
+ // Draw all tiles that intersect with the content rect.
+ void draw(const IntRect& contentRect, const TransformationMatrix&, float opacity);
+
+ // If uploadCanvas/updateFromPixels is called, this must be called after
+ // draw() to unreserve any textures that were reserved prior to uploading.
+ void unreserveTextures();
// Set position of this tiled layer in content space.
void setLayerPosition(const IntPoint& position);
// Change the tile size. This may invalidate all the existing tiles.
void setTileSize(const IntSize& size);
+ void setLayerRenderer(LayerRendererChromium* layerRenderer) { m_layerRenderer = layerRenderer; }
+
+ bool skipsDraw() const { return m_skipsDraw; }
typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderTexAlpha> Program;
+ // If this tiler has exactly one tile, return its texture. Otherwise, null.
+ LayerTexture* getSingleTexture();
+
private:
LayerTilerChromium(LayerRendererChromium*, const IntSize& tileSize, BorderTexelOption);
@@ -140,6 +161,7 @@ private:
// Tightly packed set of unused tiles.
Vector<RefPtr<Tile> > m_unusedTiles;
+ IntRect m_paintRect;
PlatformCanvas m_canvas;
// Cache a tile-sized pixel buffer to draw into.
diff --git a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp
index 29589f4..afaa6f7 100644
--- a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp
+++ b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp
@@ -34,7 +34,7 @@
#include "PlatformContextSkia.h"
#include "SkColorPriv.h"
#include "skia/ext/platform_canvas.h"
-#elif PLATFORM(CG)
+#elif USE(CG)
#include <CoreGraphics/CGBitmapContext.h>
#endif
@@ -52,8 +52,8 @@ void PlatformCanvas::resize(const IntSize& size)
{
m_size = size;
#if USE(SKIA)
- m_skiaCanvas = new skia::PlatformCanvas(size.width(), size.height(), false);
-#elif PLATFORM(CG)
+ m_skiaCanvas = skia::CreateBitmapCanvas(size.width(), size.height(), false);
+#elif USE(CG)
size_t bufferSize = size.width() * size.height() * 4;
m_pixelData = adoptArrayPtr(new uint8_t[bufferSize]);
memset(m_pixelData.get(), 0, bufferSize);
@@ -73,8 +73,9 @@ PlatformCanvas::AutoLocker::AutoLocker(PlatformCanvas* canvas)
m_pixels = static_cast<uint8_t*>(m_bitmap->getPixels());
} else
m_bitmap = 0;
-#elif PLATFORM(CG)
- m_pixels = &canvas->m_pixelData[0];
+#elif USE(CG)
+ if (canvas->m_pixelData)
+ m_pixels = &canvas->m_pixelData[0];
#endif
}
@@ -86,16 +87,15 @@ PlatformCanvas::AutoLocker::~AutoLocker()
#endif
}
-PlatformCanvas::Painter::Painter(PlatformCanvas* canvas)
+PlatformCanvas::Painter::Painter(PlatformCanvas* canvas, PlatformCanvas::Painter::TextOption option)
{
#if USE(SKIA)
m_skiaContext = adoptPtr(new PlatformContextSkia(canvas->m_skiaCanvas.get()));
- // This is needed to get text to show up correctly.
- m_skiaContext->setDrawingToImageBuffer(true);
+ m_skiaContext->setDrawingToImageBuffer(option == GrayscaleText);
m_context = adoptPtr(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_skiaContext.get())));
-#elif PLATFORM(CG)
+#elif USE(CG)
m_colorSpace = CGColorSpaceCreateDeviceRGB();
size_t rowBytes = canvas->size().width() * 4;
diff --git a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h
index 262fdd0..b002d26 100644
--- a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h
+++ b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h
@@ -31,7 +31,7 @@
#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
-#if PLATFORM(CG)
+#if USE(CG)
#include <CoreGraphics/CGColorSpace.h>
#include <CoreGraphics/CGContext.h>
#include <wtf/OwnArrayPtr.h>
@@ -39,8 +39,8 @@
#endif
#if USE(SKIA)
-namespace skia { class PlatformCanvas; }
class SkBitmap;
+class SkCanvas;
#endif
namespace WebCore {
@@ -78,7 +78,9 @@ public:
class Painter {
WTF_MAKE_NONCOPYABLE(Painter);
public:
- explicit Painter(PlatformCanvas*);
+ enum TextOption { GrayscaleText, SubpixelText };
+
+ Painter(PlatformCanvas*, TextOption);
~Painter();
GraphicsContext* context() const { return m_context.get(); }
@@ -86,7 +88,7 @@ public:
OwnPtr<GraphicsContext> m_context;
#if USE(SKIA)
OwnPtr<PlatformContextSkia> m_skiaContext;
-#elif PLATFORM(CG)
+#elif USE(CG)
RetainPtr<CGColorSpaceRef> m_colorSpace;
RetainPtr<CGContextRef> m_contextCG;
#endif
@@ -97,8 +99,8 @@ public:
private:
#if USE(SKIA)
- OwnPtr<skia::PlatformCanvas> m_skiaCanvas;
-#elif PLATFORM(CG)
+ OwnPtr<SkCanvas> m_skiaCanvas;
+#elif USE(CG)
OwnArrayPtr<uint8_t> m_pixelData;
#endif
IntSize m_size;
diff --git a/Source/WebCore/platform/graphics/chromium/PlatformImage.cpp b/Source/WebCore/platform/graphics/chromium/PlatformImage.cpp
index 62cf4f8..c31b29c 100644
--- a/Source/WebCore/platform/graphics/chromium/PlatformImage.cpp
+++ b/Source/WebCore/platform/graphics/chromium/PlatformImage.cpp
@@ -30,7 +30,7 @@
#if USE(SKIA)
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
-#elif PLATFORM(CG)
+#elif USE(CG)
#include <CoreGraphics/CGBitmapContext.h>
#include <CoreGraphics/CGContext.h>
#include <CoreGraphics/CGImage.h>
@@ -54,7 +54,7 @@ void PlatformImage::updateFromImage(NativeImagePtr nativeImage)
IntSize bitmapSize(skiaBitmap->width(), skiaBitmap->height());
ASSERT(skiaBitmap);
-#elif PLATFORM(CG)
+#elif USE(CG)
// NativeImagePtr is a CGImageRef on Mac OS X.
int width = CGImageGetWidth(nativeImage);
int height = CGImageGetHeight(nativeImage);
@@ -73,7 +73,7 @@ void PlatformImage::updateFromImage(NativeImagePtr nativeImage)
// FIXME: do we need to support more image configurations?
ASSERT(skiaBitmap->config()== SkBitmap::kARGB_8888_Config);
skiaBitmap->copyPixelsTo(m_pixelData.get(), bufferSize);
-#elif PLATFORM(CG)
+#elif USE(CG)
// FIXME: we should get rid of this temporary copy where possible.
int tempRowBytes = width * 4;
// Note we do not zero this vector since we are going to
diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
index ca42d0b..c93ef3f 100644
--- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
@@ -143,7 +143,7 @@ void RenderSurfaceChromium::drawSurface(CCLayerImpl* maskLayer, const Transforma
maskLayer->unreserveContentsTexture();
}
-void RenderSurfaceChromium::draw()
+void RenderSurfaceChromium::draw(const IntRect&)
{
if (m_skipsDraw || !m_contentsTexture)
return;
diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
index 6400c63..7c0e984 100644
--- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
@@ -52,7 +52,7 @@ public:
bool prepareContentsTexture();
void cleanupResources();
- void draw();
+ void draw(const IntRect& targetSurfaceRect);
String name() const;
void dumpSurface(TextStream&, int indent) const;
@@ -84,7 +84,7 @@ private:
TransformationMatrix m_replicaDrawTransform;
TransformationMatrix m_originTransform;
IntRect m_scissorRect;
- Vector<CCLayerImpl*> m_layerList;
+ Vector<RefPtr<CCLayerImpl> > m_layerList;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
index 193271d..f2c2394 100644
--- a/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
+++ b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
@@ -49,14 +49,14 @@ namespace {
// into. Buffers larger than this will be destroyed when we're done with them.
const int maxCachedBufferPixelSize = 65536;
-inline skia::PlatformCanvas* canvasForContext(const GraphicsContext& context)
+inline SkCanvas* canvasForContext(const GraphicsContext& context)
{
return context.platformContext()->canvas();
}
inline const SkBitmap& bitmapForContext(const GraphicsContext& context)
{
- return canvasForContext(context)->getTopPlatformDevice().accessBitmap(false);
+ return canvasForContext(context)->getTopDevice()->accessBitmap(false);
}
void compositeToCopy(const GraphicsContext& sourceLayers,
@@ -466,7 +466,7 @@ void TransparencyWin::compositeTextComposite()
if (!m_validLayer)
return;
- const SkBitmap& bitmap = m_layerBuffer->context()->platformContext()->canvas()->getTopPlatformDevice().accessBitmap(true);
+ const SkBitmap& bitmap = m_layerBuffer->context()->platformContext()->canvas()->getTopDevice()->accessBitmap(true);
SkColor textColor = m_textCompositeColor.rgb();
for (int y = 0; y < m_layerSize.height(); y++) {
uint32_t* row = bitmap.getAddr32(0, y);
@@ -502,7 +502,7 @@ void TransparencyWin::makeLayerOpaque()
return;
SkBitmap& bitmap = const_cast<SkBitmap&>(m_drawContext->platformContext()->
- canvas()->getTopPlatformDevice().accessBitmap(true));
+ canvas()->getTopDevice()->accessBitmap(true));
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++)
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
index dda84a9..524beec 100644
--- a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
@@ -31,45 +31,16 @@
#include "config.h"
#include "UniscribeHelper.h"
-#include <windows.h>
-
+#include "Font.h"
#include "FontUtilsChromiumWin.h"
#include "PlatformContextSkia.h"
#include "SkiaFontWin.h"
#include "SkPoint.h"
+#include <windows.h>
#include <wtf/Assertions.h>
namespace WebCore {
-// This function is used to see where word spacing should be applied inside
-// runs. Note that this must match Font::treatAsSpace so we all agree where
-// and how much space this is, so we don't want to do more general Unicode
-// "is this a word break" thing.
-static bool treatAsSpace(UChar c)
-{
- return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0;
-}
-
-// SCRIPT_FONTPROPERTIES contains glyph indices for default, invalid
-// and blank glyphs. Just because ScriptShape succeeds does not mean
-// that a text run is rendered correctly. Some characters may be rendered
-// with default/invalid/blank glyphs. Therefore, we need to check if the glyph
-// array returned by ScriptShape contains any of those glyphs to make
-// sure that the text run is rendered successfully.
-static bool containsMissingGlyphs(WORD *glyphs,
- int length,
- SCRIPT_FONTPROPERTIES* properties)
-{
- for (int i = 0; i < length; ++i) {
- if (glyphs[i] == properties->wgDefault
- || (glyphs[i] == properties->wgInvalid
- && glyphs[i] != properties->wgBlank))
- return true;
- }
-
- return false;
-}
-
// HFONT is the 'incarnation' of 'everything' about font, but it's an opaque
// handle and we can't directly query it to make a new HFONT sharing
// its characteristics (height, style, etc) except for family name.
@@ -102,13 +73,15 @@ UniscribeHelper::UniscribeHelper(const UChar* input,
bool isRtl,
HFONT hfont,
SCRIPT_CACHE* scriptCache,
- SCRIPT_FONTPROPERTIES* fontProperties)
+ SCRIPT_FONTPROPERTIES* fontProperties,
+ WORD spaceGlyph)
: m_input(input)
, m_inputLength(inputLength)
, m_isRtl(isRtl)
, m_hfont(hfont)
, m_scriptCache(scriptCache)
, m_fontProperties(fontProperties)
+ , m_spaceGlyph(spaceGlyph)
, m_directionalOverride(false)
, m_inhibitLigate(false)
, m_letterSpacing(0)
@@ -546,6 +519,7 @@ bool UniscribeHelper::shape(const UChar* input,
SCRIPT_CACHE* scriptCache = m_scriptCache;
SCRIPT_FONTPROPERTIES* fontProperties = m_fontProperties;
int ascent = m_ascent;
+ WORD spaceGlyph = m_spaceGlyph;
HDC tempDC = 0;
HGDIOBJ oldFont = 0;
HRESULT hr;
@@ -601,7 +575,7 @@ bool UniscribeHelper::shape(const UChar* input,
} else if (hr == E_OUTOFMEMORY) {
numGlyphs *= 2;
continue;
- } else if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(&shaping.m_glyphs[0], generatedGlyphs, fontProperties)))
+ } else if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(shaping, run, fontProperties)))
break;
// The current font can't render this run. clear DC and try
@@ -632,7 +606,9 @@ bool UniscribeHelper::shape(const UChar* input,
const UChar *family = getFallbackFamily(input, itemLength,
FontDescription::StandardFamily, 0, 0);
bool fontOk = getDerivedFontData(family, m_style, &m_logfont,
- &ascent, &hfont, &scriptCache);
+ &ascent, &hfont, &scriptCache,
+ &spaceGlyph);
+
if (!fontOk) {
// If this GetDerivedFontData is called from the renderer it
@@ -644,7 +620,8 @@ bool UniscribeHelper::shape(const UChar* input,
// Try again.
fontOk = getDerivedFontData(family, m_style, &m_logfont,
- &ascent, &hfont, &scriptCache);
+ &ascent, &hfont, &scriptCache,
+ &spaceGlyph);
ASSERT(fontOk);
}
@@ -673,6 +650,7 @@ bool UniscribeHelper::shape(const UChar* input,
// because it's not used elsewhere.
shaping.m_hfont = hfont;
shaping.m_scriptCache = scriptCache;
+ shaping.m_spaceGlyph = spaceGlyph;
// The ascent of a font for this run can be different from
// that of the primary font so that we need to keep track of
@@ -806,22 +784,39 @@ void UniscribeHelper::adjustSpaceAdvances()
for (size_t run = 0; run < m_runs.size(); run++) {
Shaping& shaping = m_shapes[run];
+ // FIXME: This loop is not UTF-16-safe. Unicode 6.0 has a couple
+ // of complex script blocks in Plane 1.
for (int i = 0; i < shaping.charLength(); i++) {
- if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
+ UChar c = m_input[m_runs[run].iCharPos + i];
+ bool treatAsSpace = Font::treatAsSpace(c);
+ if (!treatAsSpace && !Font::treatAsZeroWidthSpaceInComplexScript(c))
continue;
int glyphIndex = shaping.m_logs[i];
int currentAdvance = shaping.m_advance[glyphIndex];
- // currentAdvance does not include additional letter-spacing, but
- // space_width does. Here we find out how off we are from the
- // correct width for the space not including letter-spacing, then
- // just subtract that diff.
- int diff = currentAdvance - spaceWidthWithoutLetterSpacing;
- // The shaping can consist of a run of text, so only subtract the
- // difference in the width of the glyph.
- shaping.m_advance[glyphIndex] -= diff;
- shaping.m_abc.abcB -= diff;
+ if (treatAsSpace) {
+ // currentAdvance does not include additional letter-spacing,
+ // but m_spaceWidth does. Here we find out how off we are from
+ // the correct width (spaceWidthWithoutLetterSpacing) and
+ // just subtract that diff.
+ int diff = currentAdvance - spaceWidthWithoutLetterSpacing;
+ // The shaping can consist of a run of text, so only subtract
+ // the difference in the width of the glyph.
+ shaping.m_advance[glyphIndex] -= diff;
+ shaping.m_abc.abcB -= diff;
+ continue;
+ }
+
+ // For characters treated as zero-width space in complex
+ // scripts, set the advance width to zero, adjust
+ // |abcB| of the current run accordingly and set
+ // the glyph to m_spaceGlyph (invisible).
+ shaping.m_advance[glyphIndex] = 0;
+ shaping.m_abc.abcB -= currentAdvance;
+ shaping.m_offsets[glyphIndex].du = 0;
+ shaping.m_offsets[glyphIndex].dv = 0;
+ shaping.m_glyphs[glyphIndex] = shaping.m_spaceGlyph;
}
}
}
@@ -872,7 +867,7 @@ void UniscribeHelper::applySpacing()
// extra wordspacing amount for the glyphs they correspond to.
if (m_wordSpacing != 0) {
for (int i = 0; i < shaping.charLength(); i++) {
- if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
+ if (!Font::treatAsSpace(m_input[m_runs[run].iCharPos + i]))
continue;
// The char in question is a word separator...
@@ -929,4 +924,31 @@ int UniscribeHelper::advanceForItem(int itemIndex) const
return shaping.m_prePadding + justification;
}
+// SCRIPT_FONTPROPERTIES contains glyph indices for default, invalid
+// and blank glyphs. Just because ScriptShape succeeds does not mean
+// that a text run is rendered correctly. Some characters may be rendered
+// with default/invalid/blank glyphs. Therefore, we need to check if the glyph
+// array returned by ScriptShape contains any of those glyphs to make
+// sure that the text run is rendered successfully.
+// However, we should not subject zero-width characters to this test.
+
+bool UniscribeHelper::containsMissingGlyphs(const Shaping& shaping,
+ const SCRIPT_ITEM& run,
+ const SCRIPT_FONTPROPERTIES* properties) const
+{
+ for (int i = 0; i < shaping.charLength(); i++) {
+ UChar c = m_input[run.iCharPos + i];
+ // Skip zero-width space characters because they're not considered to be missing in a font.
+ if (Font::treatAsZeroWidthSpaceInComplexScript(c))
+ continue;
+ int glyphIndex = shaping.m_logs[i];
+ WORD glyph = shaping.m_glyphs[glyphIndex];
+ if (glyph == properties->wgDefault
+ || (glyph == properties->wgInvalid && glyph != properties->wgBlank))
+ return true;
+ }
+ return false;
+}
+
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.h b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.h
index ffd57db..4bcdbd6 100644
--- a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.h
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.h
@@ -76,7 +76,8 @@ public:
bool isRtl,
HFONT,
SCRIPT_CACHE*,
- SCRIPT_FONTPROPERTIES*);
+ SCRIPT_FONTPROPERTIES*,
+ WORD);
virtual ~UniscribeHelper();
@@ -225,7 +226,9 @@ private:
: m_prePadding(0)
, m_hfont(NULL)
, m_scriptCache(NULL)
- , m_ascentOffset(0) {
+ , m_ascentOffset(0)
+ , m_spaceGlyph(0)
+ {
m_abc.abcA = 0;
m_abc.abcB = 0;
m_abc.abcC = 0;
@@ -319,6 +322,8 @@ private:
// when drawing a string, to align multiple runs rendered with
// different fonts.
int m_ascentOffset;
+
+ WORD m_spaceGlyph;
};
// Computes the runs_ array from the text run.
@@ -343,6 +348,10 @@ private:
// Returns the total width of a single item.
int advanceForItem(int) const;
+ bool containsMissingGlyphs(const Shaping&,
+ const SCRIPT_ITEM&,
+ const SCRIPT_FONTPROPERTIES*) const;
+
// Shapes a run (pointed to by |input|) using |hfont| first.
// Tries a series of fonts specified retrieved with NextWinFontData
// and finally a font covering characters in |*input|. A string pointed
@@ -384,6 +393,7 @@ private:
int m_ascent;
LOGFONT m_logfont;
int m_style;
+ WORD m_spaceGlyph;
// Options, see the getters/setters above.
bool m_directionalOverride;
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
index c060b43..8e0bc04 100644
--- a/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
@@ -43,7 +43,8 @@ UniscribeHelperTextRun::UniscribeHelperTextRun(const TextRun& run,
: UniscribeHelper(run.characters(), run.length(), run.rtl(),
font.primaryFont()->platformData().hfont(),
font.primaryFont()->platformData().scriptCache(),
- font.primaryFont()->platformData().scriptFontProperties())
+ font.primaryFont()->platformData().scriptFontProperties(),
+ font.primaryFont()->spaceGlyph())
, m_font(&font)
, m_fontIndex(0)
{
@@ -69,7 +70,7 @@ UniscribeHelperTextRun::UniscribeHelperTextRun(
SCRIPT_CACHE* scriptCache,
SCRIPT_FONTPROPERTIES* fontProperties)
: UniscribeHelper(input, inputLength, isRtl, hfont,
- scriptCache, fontProperties)
+ scriptCache, fontProperties, 0)
, m_font(0)
, m_fontIndex(-1)
{
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index 182e730..e75df24 100644
--- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -96,7 +96,7 @@ void VideoLayerChromium::cleanupResources()
void VideoLayerChromium::updateCompositorResources()
{
- if (!m_contentsDirty)
+ if (!m_contentsDirty || !m_owner)
return;
RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
index 652e752..aef14ed 100644
--- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
@@ -51,6 +51,12 @@ WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner)
{
}
+WebGLLayerChromium::~WebGLLayerChromium()
+{
+ if (m_context && layerRenderer())
+ layerRenderer()->removeChildContext(m_context);
+}
+
void WebGLLayerChromium::updateCompositorResources()
{
if (!m_contentsDirty)
@@ -70,6 +76,9 @@ void WebGLLayerChromium::updateCompositorResources()
}
// Update the contents of the texture used by the compositor.
if (m_contentsDirty && m_textureUpdated) {
+ // prepareTexture copies the contents of the off-screen render target into the texture
+ // used by the compositor.
+ //
m_context->prepareTexture();
m_context->markLayerComposited();
m_contentsDirty = false;
@@ -84,6 +93,13 @@ void WebGLLayerChromium::setTextureUpdated()
void WebGLLayerChromium::setContext(const GraphicsContext3D* context)
{
+ if (m_context != context && layerRenderer()) {
+ if (m_context)
+ layerRenderer()->removeChildContext(m_context);
+ if (context)
+ layerRenderer()->addChildContext(const_cast<GraphicsContext3D*>(context));
+ }
+
m_context = const_cast<GraphicsContext3D*>(context);
unsigned int textureId = m_context->platformTexture();
@@ -95,5 +111,19 @@ void WebGLLayerChromium::setContext(const GraphicsContext3D* context)
m_premultipliedAlpha = m_context->getContextAttributes().premultipliedAlpha;
}
+void WebGLLayerChromium::setLayerRenderer(LayerRendererChromium* newLayerRenderer)
+{
+ if (layerRenderer() != newLayerRenderer) {
+ if (m_context) {
+ if (layerRenderer())
+ layerRenderer()->removeChildContext(m_context);
+ if (newLayerRenderer)
+ newLayerRenderer->addChildContext(m_context);
+ }
+
+ LayerChromium::setLayerRenderer(newLayerRenderer);
+ }
+}
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
index 33db730..342275b 100644
--- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
+++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
@@ -44,12 +44,17 @@ class GraphicsContext3D;
class WebGLLayerChromium : public CanvasLayerChromium {
public:
static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0);
+
+ virtual ~WebGLLayerChromium();
+
virtual bool drawsContent() const { return m_context; }
virtual void updateCompositorResources();
void setTextureUpdated();
void setContext(const GraphicsContext3D* context);
+ virtual void setLayerRenderer(LayerRendererChromium*);
+
protected:
virtual const char* layerTypeAsString() const { return "WebGLLayer"; }
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp
index 649d049..d70e15c 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp
@@ -47,7 +47,7 @@ CCCanvasLayerImpl::~CCCanvasLayerImpl()
{
}
-void CCCanvasLayerImpl::draw()
+void CCCanvasLayerImpl::draw(const IntRect&)
{
ASSERT(layerRenderer());
const CCCanvasLayerImpl::Program* program = layerRenderer()->canvasLayerProgram();
@@ -77,4 +77,3 @@ void CCCanvasLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
}
#endif // USE(ACCELERATED_COMPOSITING)
-
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h
index 8cbf8d1..3aa917c 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h
@@ -42,7 +42,7 @@ public:
typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program;
- virtual void draw();
+ virtual void draw(const IntRect&);
virtual void dumpLayerProperties(TextStream&, int indent) const;
@@ -58,4 +58,3 @@ private:
}
#endif // CCCanvasLayerImpl_h
-
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCompletionEvent.h b/Source/WebCore/platform/graphics/chromium/cc/CCCompletionEvent.h
new file mode 100644
index 0000000..a8ac151
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCCompletionEvent.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef CCCompletionEvent_h
+#define CCCompletionEvent_h
+
+#include <wtf/ThreadingPrimitives.h>
+
+namespace WebCore {
+
+class CCCompletionEvent {
+public:
+ CCCompletionEvent()
+ {
+ m_mutex.lock();
+ }
+
+ ~CCCompletionEvent()
+ {
+ m_mutex.unlock();
+ }
+
+ void wait()
+ {
+ m_condition.wait(m_mutex);
+ }
+
+ void signal()
+ {
+ MutexLocker lock(m_mutex);
+ m_condition.signal();
+ }
+
+private:
+ Mutex m_mutex;
+ ThreadCondition m_condition;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp
index 404944b..d22b098 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp
@@ -44,13 +44,30 @@ namespace WebCore {
using namespace std;
CCHeadsUpDisplay::CCHeadsUpDisplay(LayerRendererChromium* owner)
- : m_currentFrameNumber(0)
+ : m_currentFrameNumber(1)
+ , m_filteredFrameTime(0)
, m_layerRenderer(owner)
, m_showFPSCounter(false)
, m_showPlatformLayerTree(false)
{
m_presentTimeHistoryInSec[0] = currentTime();
m_presentTimeHistoryInSec[1] = m_presentTimeHistoryInSec[0];
+ for (int i = 2; i < kPresentHistorySize; i++)
+ m_presentTimeHistoryInSec[i] = 0;
+
+ FontDescription mediumFontDesc;
+ mediumFontDesc.setGenericFamily(FontDescription::MonospaceFamily);
+ mediumFontDesc.setComputedSize(20);
+
+ m_mediumFont = adoptPtr(new Font(mediumFontDesc, 0, 0));
+ m_mediumFont->update(0);
+
+ FontDescription smallFontDesc;
+ smallFontDesc.setGenericFamily(FontDescription::MonospaceFamily);
+ smallFontDesc.setComputedSize(10);
+
+ m_smallFont = adoptPtr(new Font(smallFontDesc, 0, 0));
+ m_smallFont->update(0);
}
CCHeadsUpDisplay::~CCHeadsUpDisplay()
@@ -79,7 +96,7 @@ void CCHeadsUpDisplay::draw()
PlatformCanvas canvas;
canvas.resize(hudSize);
{
- PlatformCanvas::Painter painter(&canvas);
+ PlatformCanvas::Painter painter(&canvas, PlatformCanvas::Painter::GrayscaleText);
drawHudContents(painter.context(), hudSize);
}
@@ -92,7 +109,7 @@ void CCHeadsUpDisplay::draw()
}
// Draw the HUD onto the default render surface.
- const ContentLayerChromium::Program* program = m_layerRenderer->contentLayerProgram();
+ const LayerTilerChromium::Program* program = m_layerRenderer->tilerProgram();
ASSERT(program && program->initialized());
GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
m_hudTexture->bindTexture();
@@ -111,59 +128,98 @@ void CCHeadsUpDisplay::draw()
void CCHeadsUpDisplay::drawHudContents(GraphicsContext* ctx, const IntSize& hudSize)
{
- FontDescription mediumFontDesc;
- mediumFontDesc.setGenericFamily(FontDescription::MonospaceFamily);
- mediumFontDesc.setComputedSize(12);
- Font mediumFont(mediumFontDesc, 0, 0);
- mediumFont.update(0);
-
- FontDescription smallFontDesc;
- smallFontDesc.setGenericFamily(FontDescription::MonospaceFamily);
- smallFontDesc.setComputedSize(10);
- Font smallFont(smallFontDesc, 0, 0);
- smallFont.update(0);
-
- // We haven't finished rendering yet, so we don't now the "current" present time.
- // So, consider the *last two* present times and use those as our present time.
- double secForLastFrame = m_presentTimeHistoryInSec[(m_currentFrameNumber - 1) % 2] - m_presentTimeHistoryInSec[m_currentFrameNumber % 2];
-
- int y = 14;
-
if (m_showPlatformLayerTree) {
ctx->setFillColor(Color(0, 0, 0, 192), ColorSpaceDeviceRGB);
ctx->fillRect(FloatRect(0, 0, hudSize.width(), hudSize.height()));
}
- // Draw fps.
- String topLine = "";
- if (secForLastFrame > 0 && m_showFPSCounter) {
- double fps = 1.0 / secForLastFrame;
- topLine += String::format("FPS: %3.1f", fps);
- }
- if (topLine.length()) {
- ctx->setFillColor(Color(0, 0, 0, 255), ColorSpaceDeviceRGB);
- TextRun run(topLine);
- ctx->fillRect(FloatRect(2, 2, mediumFont.width(run) + 2.0f, 15));
+ int fpsCounterHeight = m_mediumFont->fontMetrics().floatHeight() + 2;
+ int fpsCounterTop = 2;
+ int platformLayerTreeTop;
+ if (m_showFPSCounter)
+ platformLayerTreeTop = fpsCounterTop + fpsCounterHeight + 2;
+ else
+ platformLayerTreeTop = 0;
+
+ if (m_showFPSCounter)
+ drawFPSCounter(ctx, fpsCounterTop, fpsCounterHeight);
+
+ if (m_showPlatformLayerTree)
+ drawPlatformLayerTree(ctx, platformLayerTreeTop);
+}
+
+void CCHeadsUpDisplay::drawFPSCounter(GraphicsContext* ctx, int top, int height)
+{
+ // Note that since we haven't finished the current frame, the FPS counter
+ // actually reports the last frame's time.
+ double secForLastFrame = m_presentTimeHistoryInSec[(m_currentFrameNumber + kPresentHistorySize - 1) % kPresentHistorySize] -
+ m_presentTimeHistoryInSec[(m_currentFrameNumber + kPresentHistorySize - 2) % kPresentHistorySize];
+
+ // Filter the frame times to avoid spikes.
+ const float alpha = 0.1;
+ if (!m_filteredFrameTime) {
+ if (m_currentFrameNumber == 2)
+ m_filteredFrameTime = secForLastFrame;
+ } else
+ m_filteredFrameTime = ((1.0 - alpha) * m_filteredFrameTime) + (alpha * secForLastFrame);
+
+ // Create & measure FPS text.
+ String text(String::format("FPS: %5.1f", 1.0 / m_filteredFrameTime));
+ TextRun run(text);
+ float textWidth = m_mediumFont->width(run) + 2.0f;
+ float graphWidth = kPresentHistorySize;
+
+ // Draw background.
+ ctx->setFillColor(Color(0, 0, 0, 255), ColorSpaceDeviceRGB);
+ ctx->fillRect(FloatRect(2, top, textWidth + graphWidth, height));
+
+ // Draw FPS text.
+ if (m_filteredFrameTime) {
ctx->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
- ctx->drawText(mediumFont, run, IntPoint(3, y));
- y = 26;
+ ctx->drawText(*m_mediumFont, run, IntPoint(3, top + height - 6));
}
- // Draw layer tree, if enabled.
- if (m_showPlatformLayerTree) {
- ctx->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
- Vector<String> lines;
- m_layerRenderer->layerTreeAsText().split('\n', lines);
- for (size_t i = 0; i < lines.size(); ++i) {
- ctx->drawText(smallFont, TextRun(lines[i]), IntPoint(2, y));
- y += 12;
- }
+ // Draw FPS graph.
+ const double loFPS = 0.0;
+ const double hiFPS = 120.0;
+ ctx->setStrokeStyle(SolidStroke);
+ ctx->setStrokeColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
+ int graphLeft = static_cast<int>(textWidth + 3);
+ IntPoint prev(-1, 0);
+ int x = 0;
+ double h = static_cast<double>(height - 2);
+ for (int i = m_currentFrameNumber % kPresentHistorySize; i != (m_currentFrameNumber - 1) % kPresentHistorySize; i = (i + 1) % kPresentHistorySize) {
+ int j = (i + 1) % kPresentHistorySize;
+ double fps = 1.0 / (m_presentTimeHistoryInSec[j] - m_presentTimeHistoryInSec[i]);
+ double p = 1 - ((fps - loFPS) / (hiFPS - loFPS));
+ if (p < 0)
+ p = 0;
+ if (p > 1)
+ p = 1;
+ IntPoint cur(graphLeft + x, 1 + top + p*h);
+ if (prev.x() != -1)
+ ctx->drawLine(prev, cur);
+ prev = cur;
+ x += 1;
+ }
+}
+
+void CCHeadsUpDisplay::drawPlatformLayerTree(GraphicsContext* ctx, int top)
+{
+ float smallFontHeight = m_smallFont->fontMetrics().floatHeight();
+ int y = top + smallFontHeight - 4;
+ ctx->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
+ Vector<String> lines;
+ m_layerRenderer->layerTreeAsText().split('\n', lines);
+ for (size_t i = 0; i < lines.size(); ++i) {
+ ctx->drawText(*m_smallFont, TextRun(lines[i]), IntPoint(2, y));
+ y += smallFontHeight;
}
}
void CCHeadsUpDisplay::onPresent()
{
- m_presentTimeHistoryInSec[m_currentFrameNumber % 2] = currentTime();
+ m_presentTimeHistoryInSec[m_currentFrameNumber % kPresentHistorySize] = currentTime();
m_currentFrameNumber += 1;
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h
index d56f8ab..09f198a 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h
@@ -27,8 +27,10 @@
#if USE(ACCELERATED_COMPOSITING)
+#include "Font.h"
#include "LayerRendererChromium.h"
+
namespace WebCore {
class GeometryBinding;
@@ -59,17 +61,26 @@ public:
private:
explicit CCHeadsUpDisplay(LayerRendererChromium* owner);
void drawHudContents(GraphicsContext*, const IntSize& hudSize);
+ void drawFPSCounter(GraphicsContext*, int top, int height);
+ void drawPlatformLayerTree(GraphicsContext*, int top);
+
int m_currentFrameNumber;
+ double m_filteredFrameTime;
+
OwnPtr<LayerTexture> m_hudTexture;
LayerRendererChromium* m_layerRenderer;
- double m_presentTimeHistoryInSec[2];
+ static const int kPresentHistorySize = 64;
+ double m_presentTimeHistoryInSec[kPresentHistorySize];
bool m_showFPSCounter;
bool m_showPlatformLayerTree;
+
+ OwnPtr<Font> m_smallFont;
+ OwnPtr<Font> m_mediumFont;
};
}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
index 9411e5a..e2d651d 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
@@ -126,12 +126,12 @@ bool CCLayerImpl::descendantsDrawsContent()
// These belong on CCLayerImpl, but should be overridden by each type and not defer to the LayerChromium subtypes.
bool CCLayerImpl::drawsContent() const
{
- return m_owner->drawsContent();
+ return m_owner && m_owner->drawsContent();
}
-void CCLayerImpl::draw()
+void CCLayerImpl::draw(const IntRect& targetSurfaceRect)
{
- return m_owner->draw();
+ return m_owner->draw(targetSurfaceRect);
}
void CCLayerImpl::updateCompositorResources()
@@ -215,4 +215,3 @@ void CCLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
}
#endif // USE(ACCELERATED_COMPOSITING)
-
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
index 96c4f1b..649f4dd 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
@@ -50,6 +50,7 @@ public:
}
// When this class gets subclasses, remember to add 'virtual' here.
virtual ~CCLayerImpl();
+ void resetOwner() { m_owner = 0; }
#ifndef NDEBUG
int debugID() const { return m_debugID; }
@@ -59,7 +60,7 @@ public:
CCLayerImpl* maskLayer() const;
CCLayerImpl* replicaLayer() const;
- virtual void draw();
+ virtual void draw(const IntRect& contentRect);
virtual void updateCompositorResources();
void unreserveContentsTexture();
void bindContentsTexture();
@@ -205,4 +206,3 @@ private:
}
#endif // CCLayerImpl_h
-
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCMainThread.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCMainThread.cpp
new file mode 100644
index 0000000..cd36817
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCMainThread.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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 "CCMainThread.h"
+
+#include <wtf/MainThread.h>
+
+using namespace WTF;
+
+namespace WebCore {
+
+void CCMainThread::performTask(void* userdata)
+{
+ Task* task = static_cast<Task*>(userdata);
+ task->performTask();
+ delete task;
+}
+
+void CCMainThread::postTask(PassOwnPtr<Task> task)
+{
+ callOnMainThread(performTask, task.leakPtr());
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCMainThread.h b/Source/WebCore/platform/graphics/chromium/cc/CCMainThread.h
new file mode 100644
index 0000000..ca8e8c1
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCMainThread.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+#ifndef CCMainThread_h
+#define CCMainThread_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+// Task wrapper around WTF::callOnMainThreadThread
+class CCMainThread {
+public:
+ class Task {
+ WTF_MAKE_NONCOPYABLE(Task);
+ public:
+ virtual ~Task() { }
+ virtual void performTask() = 0;
+ void* instance() const { return m_instance; }
+ protected:
+ Task(void* instance) : m_instance(instance) { }
+ void* m_instance;
+ };
+
+ static void postTask(PassOwnPtr<Task>); // Executes the task on main thread asynchronously.
+private:
+ static void performTask(void*);
+};
+
+} // namespace WebCore
+
+#endif // CCMainThread_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCMainThreadTask.h b/Source/WebCore/platform/graphics/chromium/cc/CCMainThreadTask.h
new file mode 100644
index 0000000..7de8d71
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCMainThreadTask.h
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+#ifndef CCMainThreadTask_h
+#define CCMainThreadTask_h
+
+#include "CCMainThread.h"
+#include "CrossThreadCopier.h"
+#include "CrossThreadTask.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+template<typename T>
+class MainThreadTask0 : public CCMainThread::Task {
+public:
+ typedef void (T::*Method)();
+ typedef MainThreadTask0<T> MainThreadTaskImpl;
+
+ static PassOwnPtr<MainThreadTaskImpl> create(T* instance, Method method)
+ {
+ return adoptPtr(new MainThreadTaskImpl(instance, method));
+ }
+
+private:
+ MainThreadTask0(T* instance, Method method)
+ : CCMainThread::Task(instance)
+ , m_method(method)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*static_cast<T*>(instance()).*m_method)();
+ }
+
+private:
+ Method m_method;
+};
+
+template<typename T, typename P1, typename MP1>
+class MainThreadTask1 : public CCMainThread::Task {
+public:
+ typedef void (T::*Method)(MP1);
+ typedef MainThreadTask1<T, P1, MP1> MainThreadTaskImpl;
+ typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+
+ static PassOwnPtr<MainThreadTaskImpl> create(T* instance, Method method, Param1 parameter1)
+ {
+ return adoptPtr(new MainThreadTaskImpl(instance, method, parameter1));
+ }
+
+private:
+ MainThreadTask1(T* instance, Method method, Param1 parameter1)
+ : CCMainThread::Task(instance)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*static_cast<T*>(instance()).*m_method)(m_parameter1);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+};
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2>
+class MainThreadTask2 : public CCMainThread::Task {
+public:
+ typedef void (T::*Method)(MP1, MP2);
+ typedef MainThreadTask2<T, P1, MP1, P2, MP2> MainThreadTaskImpl;
+ typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+ typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+
+ static PassOwnPtr<MainThreadTaskImpl> create(T* instance, Method method, Param1 parameter1, Param2 parameter2)
+ {
+ return adoptPtr(new MainThreadTaskImpl(instance, method, parameter1, parameter2));
+ }
+
+private:
+ MainThreadTask2(T* instance, Method method, Param1 parameter1, Param2 parameter2)
+ : CCMainThread::Task(instance)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*static_cast<T*>(instance()).*m_method)(m_parameter1, m_parameter2);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+};
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+class MainThreadTask3 : public CCMainThread::Task {
+public:
+ typedef void (T::*Method)(MP1, MP2, MP3);
+ typedef MainThreadTask3<T, P1, MP1, P2, MP2, P3, MP3> MainThreadTaskImpl;
+ typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+ typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+ typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
+
+ static PassOwnPtr<MainThreadTaskImpl> create(T* instance, Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+ {
+ return adoptPtr(new MainThreadTaskImpl(instance, method, parameter1, parameter2, parameter3));
+ }
+
+private:
+ MainThreadTask3(T* instance, Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+ : CCMainThread::Task(instance)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ , m_parameter3(parameter3)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*static_cast<T*>(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ P3 m_parameter3;
+};
+
+template<typename T>
+PassOwnPtr<CCMainThread::Task> createMainThreadTask(
+ T* const callee,
+ void (T::*method)());
+
+template<typename T>
+PassOwnPtr<CCMainThread::Task> createMainThreadTask(
+ T* const callee,
+ void (T::*method)())
+{
+ return MainThreadTask0<T>::create(
+ callee,
+ method);
+}
+
+template<typename T, typename P1, typename MP1>
+PassOwnPtr<CCMainThread::Task> createMainThreadTask(
+ T* const callee,
+ void (T::*method)(MP1),
+ const P1& parameter1)
+{
+ return MainThreadTask1<T, typename CrossThreadCopier<P1>::Type, MP1>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1));
+}
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2>
+PassOwnPtr<CCMainThread::Task> createMainThreadTask(
+ T* const callee,
+ void (T::*method)(MP1, MP2),
+ const P1& parameter1,
+ const P2& parameter2)
+{
+ return MainThreadTask2<T, typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1),
+ CrossThreadCopier<P2>::copy(parameter2));
+}
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+PassOwnPtr<CCMainThread::Task> createMainThreadTask(
+ T* const callee,
+ void (T::*method)(MP1, MP2, MP3),
+ const P1& parameter1,
+ const P2& parameter2,
+ const P3& parameter3)
+{
+ return MainThreadTask3<T, typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1),
+ CrossThreadCopier<P2>::copy(parameter2),
+ CrossThreadCopier<P3>::copy(parameter3));
+}
+
+} // namespace WebCore
+
+#endif // CCMainThreadTask_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp
index 4aef639..a428829 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp
@@ -46,7 +46,7 @@ CCPluginLayerImpl::~CCPluginLayerImpl()
{
}
-void CCPluginLayerImpl::draw()
+void CCPluginLayerImpl::draw(const IntRect&)
{
ASSERT(layerRenderer());
const CCPluginLayerImpl::Program* program = layerRenderer()->pluginLayerProgram();
@@ -81,4 +81,3 @@ void CCPluginLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
}
#endif // USE(ACCELERATED_COMPOSITING)
-
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
index 65eb5b7..4fd7457 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h
@@ -42,7 +42,7 @@ public:
typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program;
- virtual void draw();
+ virtual void draw(const IntRect&);
virtual void dumpLayerProperties(TextStream&, int indent) const;
@@ -57,4 +57,3 @@ private:
}
#endif // CCPluginLayerImpl_h
-
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThread.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCThread.cpp
new file mode 100644
index 0000000..9566584
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCThread.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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 "CCThread.h"
+
+#include "LayerRendererChromium.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/ThreadingPrimitives.h>
+
+namespace WebCore {
+
+using namespace WTF;
+
+CCThread::CCThread()
+{
+ MutexLocker lock(m_threadCreationMutex);
+ m_threadID = createThread(CCThread::compositorThreadStart, this, "Chromium Compositor");
+}
+
+CCThread::~CCThread()
+{
+ m_queue.kill();
+
+ // Stop thread.
+ void* exitCode;
+ waitForThreadCompletion(m_threadID, &exitCode);
+ m_threadID = 0;
+}
+
+void CCThread::postTask(PassOwnPtr<Task> task)
+{
+ m_queue.append(task);
+}
+
+void* CCThread::compositorThreadStart(void* userdata)
+{
+ CCThread* ccThread = static_cast<CCThread*>(userdata);
+ return ccThread->runLoop();
+}
+
+void* CCThread::runLoop()
+{
+ {
+ // Wait for CCThread::start() to complete to have m_threadID
+ // established before starting the main loop.
+ MutexLocker lock(m_threadCreationMutex);
+ }
+
+ while (OwnPtr<Task> task = m_queue.waitForMessage())
+ task->performTask();
+
+ return 0;
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThread.h b/Source/WebCore/platform/graphics/chromium/cc/CCThread.h
new file mode 100644
index 0000000..177d3f3
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCThread.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#ifndef CCThread_h
+#define CCThread_h
+
+#include <wtf/MessageQueue.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Threading.h>
+
+namespace WebCore {
+
+// The CCThread singleton owns the compositor thread and provides
+// basic infrastructure for messaging between the two threads.
+class CCThread {
+public:
+ static PassOwnPtr<CCThread> create()
+ {
+ return adoptPtr(new CCThread());
+ }
+
+ virtual ~CCThread();
+
+ class Task {
+ WTF_MAKE_NONCOPYABLE(Task);
+ public:
+ virtual ~Task() { }
+ virtual void performTask() = 0;
+ void* instance() const { return m_instance; }
+ protected:
+ Task(void* instance) : m_instance(instance) { }
+ void* m_instance;
+ };
+
+ void postTask(PassOwnPtr<Task>); // Executes the task on context's thread asynchronously.
+
+ WTF::ThreadIdentifier threadID() const { return m_threadID; }
+
+protected:
+ explicit CCThread();
+
+ static void* compositorThreadStart(void*);
+ void* runLoop();
+
+ WTF::ThreadIdentifier m_threadID;
+ MessageQueue<Task> m_queue;
+
+ Mutex m_threadCreationMutex;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadTask.h b/Source/WebCore/platform/graphics/chromium/cc/CCThreadTask.h
new file mode 100644
index 0000000..71245d3
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadTask.h
@@ -0,0 +1,279 @@
+/*
+ * 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.
+ */
+#ifndef CCThreadTask_h
+#define CCThreadTask_h
+
+#include "CCThread.h"
+#include "CrossThreadCopier.h"
+#include "CrossThreadTask.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+template<typename T>
+class CCThreadTask0 : public CCThread::Task {
+public:
+ typedef void (T::*Method)();
+ typedef CCThreadTask0<T> CCThreadTaskImpl;
+
+ static PassOwnPtr<CCThreadTaskImpl> create(T* instance, Method method)
+ {
+ return adoptPtr(new CCThreadTaskImpl(instance, method));
+ }
+
+private:
+ CCThreadTask0(T* instance, Method method)
+ : CCThread::Task(instance)
+ , m_method(method)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*static_cast<T*>(instance()).*m_method)();
+ }
+
+private:
+ Method m_method;
+};
+
+template<typename T, typename P1, typename MP1>
+class CCThreadTask1 : public CCThread::Task {
+public:
+ typedef void (T::*Method)(MP1);
+ typedef CCThreadTask1<T, P1, MP1> CCThreadTaskImpl;
+ typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+
+ static PassOwnPtr<CCThreadTaskImpl> create(T* instance, Method method, Param1 parameter1)
+ {
+ return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1));
+ }
+
+private:
+ CCThreadTask1(T* instance, Method method, Param1 parameter1)
+ : CCThread::Task(instance)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*static_cast<T*>(instance()).*m_method)(m_parameter1);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+};
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2>
+class CCThreadTask2 : public CCThread::Task {
+public:
+ typedef void (T::*Method)(MP1, MP2);
+ typedef CCThreadTask2<T, P1, MP1, P2, MP2> CCThreadTaskImpl;
+ typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+ typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+
+ static PassOwnPtr<CCThreadTaskImpl> create(T* instance, Method method, Param1 parameter1, Param2 parameter2)
+ {
+ return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2));
+ }
+
+private:
+ CCThreadTask2(T* instance, Method method, Param1 parameter1, Param2 parameter2)
+ : CCThread::Task(instance)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*static_cast<T*>(instance()).*m_method)(m_parameter1, m_parameter2);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+};
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+class CCThreadTask3 : public CCThread::Task {
+public:
+ typedef void (T::*Method)(MP1, MP2, MP3);
+ typedef CCThreadTask3<T, P1, MP1, P2, MP2, P3, MP3> CCThreadTaskImpl;
+ typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+ typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+ typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
+
+ static PassOwnPtr<CCThreadTaskImpl> create(T* instance, Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+ {
+ return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2, parameter3));
+ }
+
+private:
+ CCThreadTask3(T* instance, Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3)
+ : CCThread::Task(instance)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ , m_parameter3(parameter3)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*static_cast<T*>(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ P3 m_parameter3;
+};
+
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
+class CCThreadTask4 : public CCThread::Task {
+public:
+ typedef void (T::*Method)(MP1, MP2, MP3, MP4);
+ typedef CCThreadTask4<T, P1, MP1, P2, MP2, P3, MP3, P4, MP4> CCThreadTaskImpl;
+ typedef typename CrossThreadTaskTraits<P1>::ParamType Param1;
+ typedef typename CrossThreadTaskTraits<P2>::ParamType Param2;
+ typedef typename CrossThreadTaskTraits<P3>::ParamType Param3;
+ typedef typename CrossThreadTaskTraits<P4>::ParamType Param4;
+
+ static PassOwnPtr<CCThreadTaskImpl> create(T* instance, Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4)
+ {
+ return adoptPtr(new CCThreadTaskImpl(instance, method, parameter1, parameter2, parameter3, parameter4));
+ }
+
+private:
+ CCThreadTask4(T* instance, Method method, Param1 parameter1, Param2 parameter2, Param3 parameter3, Param4 parameter4)
+ : CCThread::Task(instance)
+ , m_method(method)
+ , m_parameter1(parameter1)
+ , m_parameter2(parameter2)
+ , m_parameter3(parameter3)
+ , m_parameter4(parameter4)
+ {
+ }
+
+ virtual void performTask()
+ {
+ (*static_cast<T*>(instance()).*m_method)(m_parameter1, m_parameter2, m_parameter3, m_parameter4);
+ }
+
+private:
+ Method m_method;
+ P1 m_parameter1;
+ P2 m_parameter2;
+ P3 m_parameter3;
+ P4 m_parameter4;
+};
+
+template<typename T>
+PassOwnPtr<CCThread::Task> createCCThreadTask(
+ T* const callee,
+ void (T::*method)());
+
+template<typename T>
+PassOwnPtr<CCThread::Task> createCCThreadTask(
+ T* const callee,
+ void (T::*method)())
+{
+ return CCThreadTask0<T>::create(
+ callee,
+ method);
+}
+
+template<typename T, typename P1, typename MP1>
+PassOwnPtr<CCThread::Task> createCCThreadTask(
+ T* const callee,
+ void (T::*method)(MP1),
+ const P1& parameter1)
+{
+ return CCThreadTask1<T, typename CrossThreadCopier<P1>::Type, MP1>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1));
+}
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2>
+PassOwnPtr<CCThread::Task> createCCThreadTask(
+ T* const callee,
+ void (T::*method)(MP1, MP2),
+ const P1& parameter1,
+ const P2& parameter2)
+{
+ return CCThreadTask2<T, typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1),
+ CrossThreadCopier<P2>::copy(parameter2));
+}
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3>
+PassOwnPtr<CCThread::Task> createCCThreadTask(
+ T* const callee,
+ void (T::*method)(MP1, MP2, MP3),
+ const P1& parameter1,
+ const P2& parameter2,
+ const P3& parameter3)
+{
+ return CCThreadTask3<T, typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1),
+ CrossThreadCopier<P2>::copy(parameter2),
+ CrossThreadCopier<P3>::copy(parameter3));
+}
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
+PassOwnPtr<CCThread::Task> createCCThreadTask(
+ T* const callee,
+ void (T::*method)(MP1, MP2, MP3, MP4),
+ const P1& parameter1,
+ const P2& parameter2,
+ const P3& parameter3,
+ const P4& parameter4)
+{
+ return CCThreadTask4<T, typename CrossThreadCopier<P1>::Type, MP1, typename CrossThreadCopier<P2>::Type, MP2, typename CrossThreadCopier<P3>::Type, MP3, typename CrossThreadCopier<P4>::Type, MP4>::create(
+ callee,
+ method,
+ CrossThreadCopier<P1>::copy(parameter1),
+ CrossThreadCopier<P2>::copy(parameter2),
+ CrossThreadCopier<P3>::copy(parameter3),
+ CrossThreadCopier<P4>::copy(parameter4));
+
+}
+
+} // namespace WebCore
+
+#endif // CCThreadTask_h
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
index eb3612b..99a148d 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp
@@ -75,7 +75,7 @@ void CCVideoLayerImpl::setTexture(size_t i, VideoLayerChromium::Texture texture)
m_textures[i] = texture;
}
-void CCVideoLayerImpl::draw()
+void CCVideoLayerImpl::draw(const IntRect&)
{
if (m_skipsDraw)
return;
@@ -170,4 +170,3 @@ void CCVideoLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
}
#endif // USE(ACCELERATED_COMPOSITING)
-
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
index 62f8778..0e1d1f6 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h
@@ -47,7 +47,7 @@ public:
typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram;
typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram;
- virtual void draw();
+ virtual void draw(const IntRect&);
virtual void dumpLayerProperties(TextStream&, int indent) const;
@@ -72,4 +72,3 @@ private:
}
#endif // CCVideoLayerImpl_h
-
diff --git a/Source/WebCore/platform/graphics/filters/FEFlood.cpp b/Source/WebCore/platform/graphics/filters/FEFlood.cpp
index 3c48cf9..d832d2b 100644
--- a/Source/WebCore/platform/graphics/filters/FEFlood.cpp
+++ b/Source/WebCore/platform/graphics/filters/FEFlood.cpp
@@ -49,9 +49,12 @@ Color FEFlood::floodColor() const
return m_floodColor;
}
-void FEFlood::setFloodColor(const Color& color)
+bool FEFlood::setFloodColor(const Color& color)
{
+ if (m_floodColor == color)
+ return false;
m_floodColor = color;
+ return true;
}
float FEFlood::floodOpacity() const
@@ -59,9 +62,12 @@ float FEFlood::floodOpacity() const
return m_floodOpacity;
}
-void FEFlood::setFloodOpacity(float floodOpacity)
+bool FEFlood::setFloodOpacity(float floodOpacity)
{
+ if (m_floodOpacity == floodOpacity)
+ return false;
m_floodOpacity = floodOpacity;
+ return true;
}
void FEFlood::apply()
diff --git a/Source/WebCore/platform/graphics/filters/FEFlood.h b/Source/WebCore/platform/graphics/filters/FEFlood.h
index 2e8824f..cac4153 100644
--- a/Source/WebCore/platform/graphics/filters/FEFlood.h
+++ b/Source/WebCore/platform/graphics/filters/FEFlood.h
@@ -34,10 +34,10 @@ public:
static PassRefPtr<FEFlood> create(Filter* filter, const Color&, float);
Color floodColor() const;
- void setFloodColor(const Color &);
+ bool setFloodColor(const Color &);
float floodOpacity() const;
- void setFloodOpacity(float);
+ bool setFloodOpacity(float);
virtual void apply();
virtual void dump();
diff --git a/Source/WebCore/platform/graphics/filters/FELighting.cpp b/Source/WebCore/platform/graphics/filters/FELighting.cpp
index ec1ca88..13a69fd 100644
--- a/Source/WebCore/platform/graphics/filters/FELighting.cpp
+++ b/Source/WebCore/platform/graphics/filters/FELighting.cpp
@@ -30,6 +30,13 @@
#include "FELighting.h"
#include "LightSource.h"
+#include "PointLightSource.h"
+#include "SpotLightSource.h"
+
+#if CPU(ARM_NEON) && COMPILER(GCC)
+#include "FELightingNEON.h"
+#include <wtf/Vector.h>
+#endif
namespace WebCore {
@@ -301,6 +308,9 @@ bool FELighting::drawLighting(ByteArray* pixels, int width, int height)
if (width >= 3 && height >= 3) {
// Interior pixels
+#if CPU(ARM_NEON) && COMPILER(GCC)
+ drawInteriorPixels(data, paintingData);
+#else
for (int y = 1; y < data.heightDecreasedByOne; ++y) {
offset = y * data.widthMultipliedByPixelSize + cPixelSize;
for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) {
@@ -308,6 +318,7 @@ bool FELighting::drawLighting(ByteArray* pixels, int width, int height)
inlineSetPixel(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, normalVector);
}
}
+#endif
}
int lastPixel = data.widthMultipliedByPixelSize * height;
@@ -354,6 +365,118 @@ void FELighting::apply()
drawLighting(srcPixelArray, absolutePaintSize.width(), absolutePaintSize.height());
}
+#if CPU(ARM_NEON) && COMPILER(GCC)
+
+static int getPowerCoefficients(float exponent)
+{
+ // Calling a powf function from the assembly code would require to save
+ // and reload a lot of NEON registers. Since the base is in range [0..1]
+ // and only 8 bit precision is required, we use our own powf function.
+ // This is probably not the best, but it uses only a few registers and
+ // gives us enough precision (modifying the exponent field directly would
+ // also be possible).
+
+ // First, we limit the exponent to maximum of 64, which gives us enough
+ // precision. We split the exponent to an integer and fraction part,
+ // since a^x = (a^y)*(a^z) where x = y+z. The integer exponent of the
+ // power is estimated by square, and the fraction exponent of the power
+ // is estimated by square root assembly instructions.
+ int i, result;
+
+ if (exponent < 0)
+ exponent = 1 / (-exponent);
+
+ if (exponent > 63.99)
+ exponent = 63.99;
+
+ exponent /= 64;
+ result = 0;
+ for (i = 11; i >= 0; --i) {
+ exponent *= 2;
+ if (exponent >= 1) {
+ result |= 1 << i;
+ exponent -= 1;
+ }
+ }
+ return result;
+}
+
+void FELighting::drawInteriorPixels(LightingData& data, LightSource::PaintingData& paintingData)
+{
+ WTF_ALIGNED(FELightingFloatArgumentsForNeon, floatArguments, 16);
+
+ FELightingPaintingDataForNeon neonData = {
+ data.pixels->data(),
+ 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;
+
+ neonDrawLighting(&neonData);
+}
+#endif // CPU(ARM_NEON) && COMPILER(GCC)
+
} // namespace WebCore
#endif // ENABLE(FILTERS)
diff --git a/Source/WebCore/platform/graphics/filters/FELighting.h b/Source/WebCore/platform/graphics/filters/FELighting.h
index fa1c0aa..3dc46e9 100644
--- a/Source/WebCore/platform/graphics/filters/FELighting.h
+++ b/Source/WebCore/platform/graphics/filters/FELighting.h
@@ -33,6 +33,7 @@
#include "FilterEffect.h"
#include "LightSource.h"
#include <wtf/ByteArray.h>
+#include <wtf/Platform.h>
// Common base class for FEDiffuseLighting and FESpecularLighting
@@ -79,6 +80,10 @@ protected:
void setPixel(int offset, LightingData&, LightSource::PaintingData&,
int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector);
+#if CPU(ARM_NEON) && COMPILER(GCC)
+ void drawInteriorPixels(LightingData&, LightSource::PaintingData&);
+#endif
+
LightingType m_lightingType;
RefPtr<LightSource> m_lightSource;
diff --git a/Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp b/Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp
index a20eb8c..2c7b1eb 100644
--- a/Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp
+++ b/Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp
@@ -54,9 +54,12 @@ Color FESpecularLighting::lightingColor() const
return m_lightingColor;
}
-void FESpecularLighting::setLightingColor(const Color& lightingColor)
+bool FESpecularLighting::setLightingColor(const Color& lightingColor)
{
+ if (m_lightingColor == lightingColor)
+ return false;
m_lightingColor = lightingColor;
+ return true;
}
float FESpecularLighting::surfaceScale() const
diff --git a/Source/WebCore/platform/graphics/filters/FESpecularLighting.h b/Source/WebCore/platform/graphics/filters/FESpecularLighting.h
index 9d3ea2d..9fa3add 100644
--- a/Source/WebCore/platform/graphics/filters/FESpecularLighting.h
+++ b/Source/WebCore/platform/graphics/filters/FESpecularLighting.h
@@ -34,7 +34,7 @@ public:
virtual ~FESpecularLighting();
Color lightingColor() const;
- void setLightingColor(const Color&);
+ bool setLightingColor(const Color&);
float surfaceScale() const;
bool setSurfaceScale(float);
diff --git a/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.cpp b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.cpp
new file mode 100644
index 0000000..3807f1f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.cpp
@@ -0,0 +1,464 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "FELightingNEON.h"
+
+#if CPU(ARM_NEON) && COMPILER(GCC)
+
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+// These constants are copied to the following SIMD registers:
+// ALPHAX_Q ALPHAY_Q REMAPX_D REMAPY_D
+
+WTF_ALIGNED(short, s_FELightingConstantsForNeon[], 16) = {
+ // Alpha coefficients.
+ -2, 1, 0, -1, 2, 1, 0, -1,
+ 0, -1, -2, -1, 0, 1, 2, 1,
+ // Remapping indicies.
+ 0x0f0e, 0x0302, 0x0504, 0x0706,
+ 0x0b0a, 0x1312, 0x1514, 0x1716,
+};
+
+short* feLightingConstantsForNeon()
+{
+ return s_FELightingConstantsForNeon;
+}
+
+#define ASSTRING(str) #str
+#define TOSTRING(value) ASSTRING(value)
+
+#define PIXELS_OFFSET TOSTRING(0)
+#define WIDTH_OFFSET TOSTRING(4)
+#define HEIGHT_OFFSET TOSTRING(8)
+#define FLAGS_OFFSET TOSTRING(12)
+#define SPECULAR_EXPONENT_OFFSET TOSTRING(16)
+#define CONE_EXPONENT_OFFSET TOSTRING(20)
+#define FLOAT_ARGUMENTS_OFFSET TOSTRING(24)
+#define DRAWING_CONSTANTS_OFFSET TOSTRING(28)
+#define NL "\n"
+
+// Register allocation
+#define PAINTING_DATA_R "r11"
+#define RESET_WIDTH_R PAINTING_DATA_R
+#define PIXELS_R "r4"
+#define WIDTH_R "r5"
+#define HEIGHT_R "r6"
+#define FLAGS_R "r7"
+#define SPECULAR_EXPONENT_R "r8"
+#define CONE_EXPONENT_R "r10"
+#define SCANLINE_R "r12"
+
+#define TMP1_Q "q0"
+#define TMP1_D0 "d0"
+#define TMP1_S0 "s0"
+#define TMP1_S1 "s1"
+#define TMP1_D1 "d1"
+#define TMP1_S2 "s2"
+#define TMP1_S3 "s3"
+#define TMP2_Q "q1"
+#define TMP2_D0 "d2"
+#define TMP2_S0 "s4"
+#define TMP2_S1 "s5"
+#define TMP2_D1 "d3"
+#define TMP2_S2 "s6"
+#define TMP2_S3 "s7"
+#define TMP3_Q "q2"
+#define TMP3_D0 "d4"
+#define TMP3_S0 "s8"
+#define TMP3_S1 "s9"
+#define TMP3_D1 "d5"
+#define TMP3_S2 "s10"
+#define TMP3_S3 "s11"
+
+#define COSINE_OF_ANGLE "s12"
+#define POWF_INT_S "s13"
+#define POWF_FRAC_S "s14"
+#define SPOT_COLOR_Q "q4"
+
+// Because of VMIN and VMAX CONST_ZERO_S and CONST_ONE_S
+// must be placed on the same side of the double vector
+
+// Current pixel position
+#define POSITION_Q "q5"
+#define POSITION_X_S "s20"
+#define POSITION_Y_S "s21"
+#define POSITION_Z_S "s22"
+#define CONST_ZERO_HI_D "d11"
+#define CONST_ZERO_S "s23"
+
+// -------------------------------
+// Variable arguments
+// Misc arguments
+#define READ1_RANGE "d12-d15"
+#define READ2_RANGE "d16-d19"
+#define READ3_RANGE "d20-d21"
+
+#define SCALE_S "s24"
+#define SCALE_DIV4_S "s25"
+#define DIFFUSE_CONST_S "s26"
+
+// Light source position
+#define CONE_CUT_OFF_S "s28"
+#define CONE_FULL_LIGHT_S "s29"
+#define CONE_CUT_OFF_RANGE_S "s30"
+#define CONST_ONE_HI_D "d15"
+#define CONST_ONE_S "s31"
+
+#define LIGHT_Q "q8"
+#define DIRECTION_Q "q9"
+#define COLOR_Q "q10"
+// -------------------------------
+// Constant coefficients
+#define READ4_RANGE "d22-d25"
+#define READ5_RANGE "d26-d27"
+
+#define ALPHAX_Q "q11"
+#define ALPHAY_Q "q12"
+#define REMAPX_D "d26"
+#define REMAPY_D "d27"
+// -------------------------------
+
+#define ALL_ROWS_D "{d28,d29,d30}"
+#define TOP_ROW_D "d28"
+#define MIDDLE_ROW_D "d29"
+#define BOTTOM_ROW_D "d30"
+
+#define GET_LENGTH(source, temp) \
+ "vmul.f32 " temp##_Q ", " source##_Q ", " source##_Q NL \
+ "vadd.f32 " source##_S3 ", " temp##_S0 ", " temp##_S1 NL \
+ "vadd.f32 " source##_S3 ", " source##_S3 ", " temp##_S2 NL \
+ "vsqrt.f32 " source##_S3 ", " source##_S3 NL
+
+// destination##_S3 can contain the multiply of length.
+#define DOT_PRODUCT(destination, source1, source2) \
+ "vmul.f32 " destination##_Q ", " source1##_Q ", " source2##_Q NL \
+ "vadd.f32 " destination##_S0 ", " destination##_S0 ", " destination##_S1 NL \
+ "vadd.f32 " destination##_S0 ", " destination##_S0 ", " destination##_S2 NL
+
+#define MULTIPLY_BY_DIFFUSE_CONST(normalVectorLength, dotProductLength) \
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_DIFFUSE_CONST_IS_1) NL \
+ "vmuleq.f32 " TMP2_S1 ", " DIFFUSE_CONST_S ", " normalVectorLength NL \
+ "vdiveq.f32 " TMP2_S1 ", " TMP2_S1 ", " dotProductLength NL \
+ "vdivne.f32 " TMP2_S1 ", " normalVectorLength ", " dotProductLength NL
+
+#define POWF_SQR(value, exponent, current, remaining) \
+ "tst " exponent ", #" ASSTRING(current) NL \
+ "vmulne.f32 " value ", " value ", " POWF_INT_S NL \
+ "tst " exponent ", #" ASSTRING(remaining) NL \
+ "vmulne.f32 " POWF_INT_S ", " POWF_INT_S ", " POWF_INT_S NL
+
+#define POWF_SQRT(value, exponent, current, remaining) \
+ "tst " exponent ", #" ASSTRING(remaining) NL \
+ "vsqrtne.f32 " POWF_FRAC_S ", " POWF_FRAC_S NL \
+ "tst " exponent ", #" ASSTRING(current) NL \
+ "vmulne.f32 " value ", " value ", " POWF_FRAC_S NL
+
+// This simplified powf function is sufficiently accurate.
+#define POWF(value, exponent) \
+ "tst " exponent ", #0xfc0" NL \
+ "vmovne.f32 " POWF_INT_S ", " value NL \
+ "tst " exponent ", #0x03f" NL \
+ "vmovne.f32 " POWF_FRAC_S ", " value NL \
+ "vmov.f32 " value ", " CONST_ONE_S NL \
+ \
+ POWF_SQR(value, exponent, 0x040, 0xf80) \
+ POWF_SQR(value, exponent, 0x080, 0xf00) \
+ POWF_SQR(value, exponent, 0x100, 0xe00) \
+ POWF_SQR(value, exponent, 0x200, 0xc00) \
+ POWF_SQR(value, exponent, 0x400, 0x800) \
+ "tst " exponent ", #0x800" NL \
+ "vmulne.f32 " value ", " value ", " POWF_INT_S NL \
+ \
+ POWF_SQRT(value, exponent, 0x20, 0x3f) \
+ POWF_SQRT(value, exponent, 0x10, 0x1f) \
+ POWF_SQRT(value, exponent, 0x08, 0x0f) \
+ POWF_SQRT(value, exponent, 0x04, 0x07) \
+ POWF_SQRT(value, exponent, 0x02, 0x03) \
+ POWF_SQRT(value, exponent, 0x01, 0x01)
+
+// The following algorithm is an ARM-NEON optimized version of
+// the main loop found in FELighting.cpp. Since the whole code
+// is redesigned to be as effective as possible (ARM specific
+// thinking), it is four times faster than its C++ counterpart.
+
+asm ( // NOLINT
+".globl " TOSTRING(neonDrawLighting) NL
+TOSTRING(neonDrawLighting) ":" NL
+ // Because of the clever register allocation, nothing is stored on the stack
+ // except the saved registers.
+ // Stack must be aligned to 8 bytes.
+ "stmdb sp!, {r4-r8, r10, r11, lr}" NL
+ "vstmdb sp!, {d8-d15}" NL
+ "mov " PAINTING_DATA_R ", r0" NL
+
+ // The following two arguments are loaded to SIMD registers.
+ "ldr r0, [" PAINTING_DATA_R ", #" FLOAT_ARGUMENTS_OFFSET "]" NL
+ "ldr r1, [" PAINTING_DATA_R ", #" DRAWING_CONSTANTS_OFFSET "]" NL
+ "ldr " PIXELS_R ", [" PAINTING_DATA_R ", #" PIXELS_OFFSET "]" NL
+ "ldr " WIDTH_R ", [" PAINTING_DATA_R ", #" WIDTH_OFFSET "]" NL
+ "ldr " HEIGHT_R ", [" PAINTING_DATA_R ", #" HEIGHT_OFFSET "]" NL
+ "ldr " FLAGS_R ", [" PAINTING_DATA_R ", #" FLAGS_OFFSET "]" NL
+ "ldr " SPECULAR_EXPONENT_R ", [" PAINTING_DATA_R ", #" SPECULAR_EXPONENT_OFFSET "]" NL
+ "ldr " CONE_EXPONENT_R ", [" PAINTING_DATA_R ", #" CONE_EXPONENT_OFFSET "]" NL
+
+ // Load all data to the SIMD registers with the least number of instructions.
+ "vld1.f32 { " READ1_RANGE " }, [r0]!" NL
+ "vld1.f32 { " READ2_RANGE " }, [r0]!" NL
+ "vld1.f32 { " READ3_RANGE " }, [r0]!" NL
+ "vld1.s16 {" READ4_RANGE "}, [r1]!" NL
+ "vld1.s16 {" READ5_RANGE "}, [r1]!" NL
+
+ // Initializing local variables.
+ "mov " SCANLINE_R ", " WIDTH_R ", lsl #2" NL
+ "add " SCANLINE_R ", " SCANLINE_R ", #8" NL
+ "add " PIXELS_R ", " PIXELS_R ", " SCANLINE_R NL
+ "add " PIXELS_R ", " PIXELS_R ", #3" NL
+ "mov r0, #0" NL
+ "vmov.f32 " CONST_ZERO_S ", r0" NL
+ "vmov.f32 " POSITION_Y_S ", " CONST_ONE_S NL
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPOT_LIGHT) NL
+ "vmov.f32 " SPOT_COLOR_Q ", " COLOR_Q NL
+ "mov " RESET_WIDTH_R ", " WIDTH_R NL
+
+".mainloop:" NL
+ "mov r3, #3" NL
+ "vmov.f32 " POSITION_X_S ", " CONST_ONE_S NL
+
+".scanline:" NL
+ // The ROW registers are storing the alpha channel of the last three pixels.
+ // The alpha channel is stored as signed short (sint16) values. The fourth value
+ // is garbage. The following instructions are shifting out the unnecessary alpha
+ // values and load the next ones.
+ "ldrb r0, [" PIXELS_R ", -" SCANLINE_R "]" NL
+ "ldrb r1, [" PIXELS_R ", +" SCANLINE_R "]" NL
+ "ldrb r2, [" PIXELS_R "], #4" NL
+ "vext.s16 " TOP_ROW_D ", " TOP_ROW_D ", " TOP_ROW_D ", #3" NL
+ "vext.s16 " MIDDLE_ROW_D ", " MIDDLE_ROW_D ", " MIDDLE_ROW_D ", #3" NL
+ "vext.s16 " BOTTOM_ROW_D ", " BOTTOM_ROW_D ", " BOTTOM_ROW_D ", #3" NL
+ "vmov.s16 " TOP_ROW_D "[1], r0" NL
+ "vmov.s16 " MIDDLE_ROW_D "[1], r2" NL
+ "vmov.s16 " BOTTOM_ROW_D "[1], r1" NL
+
+ // The two border pixels (rightmost and leftmost) are skipped when
+ // the next scanline is reached. It also jumps, when the algorithm
+ // is started, and the first free alpha values are loaded to each row.
+ "subs r3, r3, #1" NL
+ "bne .scanline" NL
+
+ // The light vector goes to TMP1_Q. It is constant in case of distant light.
+ // The fourth value contains the length of the light vector.
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_POINT_LIGHT | FLAG_SPOT_LIGHT) NL
+ "beq .distantLight" NL
+
+ "vmov.s16 r3, " MIDDLE_ROW_D "[2]" NL
+ "vmov.f32 " POSITION_Z_S ", r3" NL
+ "vcvt.f32.s32 " POSITION_Z_S ", " POSITION_Z_S NL
+ "vmul.f32 " POSITION_Z_S ", " POSITION_Z_S ", " SCALE_S NL
+
+ "vsub.f32 " TMP1_Q ", " LIGHT_Q ", " POSITION_Q NL
+ GET_LENGTH(TMP1, TMP2)
+
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPOT_LIGHT) NL
+ "bne .cosineOfAngle" NL
+".visiblePixel:" NL
+
+ // | -1 0 1 | | -1 -2 -1 |
+ // X = | -2 0 2 | Y = | 0 0 0 |
+ // | -1 0 1 | | 1 2 1 |
+
+ // Multiply the alpha values by the X and Y matrices.
+
+ // Moving the 8 alpha value to TMP3.
+ "vtbl.8 " TMP3_D0 ", " ALL_ROWS_D ", " REMAPX_D NL
+ "vtbl.8 " TMP3_D1 ", " ALL_ROWS_D ", " REMAPY_D NL
+
+ "vmul.s16 " TMP2_Q ", " TMP3_Q ", " ALPHAX_Q NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D1 NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D0 NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D0 NL
+ "vmov.s16 r0, " TMP2_D0 "[0]" NL
+
+ "vmul.s16 " TMP2_Q ", " TMP3_Q ", " ALPHAY_Q NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D1 NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D0 NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D0 NL
+ "vmov.s16 r1, " TMP2_D0 "[0]" NL
+
+ // r0 and r1 contains the X and Y coordinates of the
+ // normal vector, respectively.
+
+ // Calculating the spot light strength.
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPOT_LIGHT) NL
+ "beq .endLight" NL
+
+ "vneg.f32 " TMP3_S1 ", " COSINE_OF_ANGLE NL
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_CONE_EXPONENT_IS_1) NL
+ "beq .coneExpPowf" NL
+".coneExpPowfFinished:" NL
+
+ // Smoothing the cone edge if necessary.
+ "vcmp.f32 " COSINE_OF_ANGLE ", " CONE_FULL_LIGHT_S NL
+ "fmstat" NL
+ "bhi .cutOff" NL
+".cutOffFinished:" NL
+
+ "vmin.f32 " TMP3_D0 ", " TMP3_D0 ", " CONST_ONE_HI_D NL
+ "vmul.f32 " COLOR_Q ", " SPOT_COLOR_Q ", " TMP3_D0 "[1]" NL
+
+".endLight:" NL
+ // Summarize:
+ // r0 and r1 contains the normalVector.
+ // TMP1_Q contains the light vector and its length.
+ // COLOR_Q contains the color of the light vector.
+
+ // Test whether both r0 and r1 are zero (Normal vector is (0, 0, 1)).
+ "orrs r2, r0, r1" NL
+ "bne .normalVectorIsNonZero" NL
+
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPECULAR_LIGHT) NL
+ "bne .specularLight1" NL
+
+ // Calculate diffuse light strength.
+ MULTIPLY_BY_DIFFUSE_CONST(TMP1_S2, TMP1_S3)
+ "b .lightStrengthCalculated" NL
+
+".specularLight1:" NL
+ // Calculating specular light strength.
+ "vadd.f32 " TMP1_S2 ", " TMP1_S2 ", " TMP1_S3 NL
+ GET_LENGTH(TMP1, TMP2)
+
+ // When the exponent is 1, we don't need to call an expensive powf function.
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPECULAR_EXPONENT_IS_1) NL
+ "vdiveq.f32 " TMP2_S1 ", " TMP1_S2 ", " TMP1_S3 NL
+ "beq .specularExpPowf" NL
+
+ MULTIPLY_BY_DIFFUSE_CONST(TMP1_S2, TMP1_S3)
+ "b .lightStrengthCalculated" NL
+
+".normalVectorIsNonZero:" NL
+ // Normal vector goes to TMP2, and its length is calculated as well.
+ "vmov.s32 " TMP2_S0 ", r0" NL
+ "vcvt.f32.s32 " TMP2_S0 ", " TMP2_S0 NL
+ "vmul.f32 " TMP2_S0 ", " TMP2_S0 ", " SCALE_DIV4_S NL
+ "vmov.s32 " TMP2_S1 ", r1" NL
+ "vcvt.f32.s32 " TMP2_S1 ", " TMP2_S1 NL
+ "vmul.f32 " TMP2_S1 ", " TMP2_S1 ", " SCALE_DIV4_S NL
+ "vmov.f32 " TMP2_S2 ", " CONST_ONE_S NL
+ GET_LENGTH(TMP2, TMP3)
+
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPECULAR_LIGHT) NL
+ "bne .specularLight2" NL
+
+ // Calculating diffuse light strength.
+ DOT_PRODUCT(TMP3, TMP2, TMP1)
+ MULTIPLY_BY_DIFFUSE_CONST(TMP3_S0, TMP3_S3)
+ "b .lightStrengthCalculated" NL
+
+".specularLight2:" NL
+ // Calculating specular light strength.
+ "vadd.f32 " TMP1_S2 ", " TMP1_S2 ", " TMP1_S3 NL
+ GET_LENGTH(TMP1, TMP3)
+ DOT_PRODUCT(TMP3, TMP2, TMP1)
+
+ // When the exponent is 1, we don't need to call an expensive powf function.
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPECULAR_EXPONENT_IS_1) NL
+ "vdiveq.f32 " TMP2_S1 ", " TMP3_S0 ", " TMP3_S3 NL
+ "beq .specularExpPowf" NL
+ MULTIPLY_BY_DIFFUSE_CONST(TMP3_S0, TMP3_S3)
+
+".lightStrengthCalculated:" NL
+ // TMP2_S1 contains the light strength. Clamp it to [0, 1]
+ "vmax.f32 " TMP2_D0 ", " TMP2_D0 ", " CONST_ZERO_HI_D NL
+ "vmin.f32 " TMP2_D0 ", " TMP2_D0 ", " CONST_ONE_HI_D NL
+ "vmul.f32 " TMP3_Q ", " COLOR_Q ", " TMP2_D0 "[1]" NL
+ "vcvt.u32.f32 " TMP3_Q ", " TMP3_Q NL
+ "vmov.u32 r2, r3, " TMP3_S0 ", " TMP3_S1 NL
+ // The color values are stored in-place.
+ "strb r2, [" PIXELS_R ", #-11]" NL
+ "strb r3, [" PIXELS_R ", #-10]" NL
+ "vmov.u32 r2, " TMP3_S2 NL
+ "strb r2, [" PIXELS_R ", #-9]" NL
+
+ // Continue to the next pixel.
+".blackPixel:" NL
+ "vadd.f32 " POSITION_X_S ", " CONST_ONE_S NL
+ "mov r3, #1" NL
+ "subs " WIDTH_R ", " WIDTH_R ", #1" NL
+ "bne .scanline" NL
+
+ // If the end of the scanline is reached, we continue
+ // to the next scanline.
+ "vadd.f32 " POSITION_Y_S ", " CONST_ONE_S NL
+ "mov " WIDTH_R ", " RESET_WIDTH_R NL
+ "subs " HEIGHT_R ", " HEIGHT_R ", #1" NL
+ "bne .mainloop" NL
+
+ // Return.
+ "vldmia sp!, {d8-d15}" NL
+ "ldmia sp!, {r4-r8, r10, r11, pc}" NL
+
+".distantLight:" NL
+ // In case of distant light, the light vector is constant,
+ // we simply copy it.
+ "vmov.f32 " TMP1_Q ", " LIGHT_Q NL
+ "b .visiblePixel" NL
+
+".cosineOfAngle:" NL
+ // If the pixel is outside of the cone angle, it is simply a black pixel.
+ DOT_PRODUCT(TMP3, TMP1, DIRECTION)
+ "vdiv.f32 " COSINE_OF_ANGLE ", " TMP3_S0 ", " TMP1_S3 NL
+ "vcmp.f32 " COSINE_OF_ANGLE ", " CONE_CUT_OFF_S NL
+ "fmstat" NL
+ "bls .visiblePixel" NL
+ "mov r0, #0" NL
+ "strh r0, [" PIXELS_R ", #-11]" NL
+ "strb r0, [" PIXELS_R ", #-9]" NL
+ "b .blackPixel" NL
+
+".cutOff:" NL
+ // Smoothing the light strength on the cone edge.
+ "vsub.f32 " TMP3_S0 ", " CONE_CUT_OFF_S ", " COSINE_OF_ANGLE NL
+ "vdiv.f32 " TMP3_S0 ", " TMP3_S0 ", " CONE_CUT_OFF_RANGE_S NL
+ "vmul.f32 " TMP3_S1 ", " TMP3_S1 ", " TMP3_S0 NL
+ "b .cutOffFinished" NL
+
+".coneExpPowf:" NL
+ POWF(TMP3_S1, CONE_EXPONENT_R)
+ "b .coneExpPowfFinished" NL
+
+".specularExpPowf:" NL
+ POWF(TMP2_S1, SPECULAR_EXPONENT_R)
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_DIFFUSE_CONST_IS_1) NL
+ "vmuleq.f32 " TMP2_S1 ", " TMP2_S1 ", " DIFFUSE_CONST_S NL
+ "b .lightStrengthCalculated" NL
+); // NOLINT
+
+} // namespace WebCore
+
+#endif // CPU(ARM_NEON) && COMPILER(GCC)
diff --git a/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h
new file mode 100644
index 0000000..d83b7fe
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h
@@ -0,0 +1,96 @@
+/*
+ * 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
+
+#include <wtf/Platform.h>
+
+#if CPU(ARM_NEON) && COMPILER(GCC)
+
+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;
+ int widthDecreasedByTwo;
+ int heightDecreasedByTwo;
+ // Combination of FLAG constants above.
+ int flags;
+ int specularExponent;
+ int coneExponent;
+ FELightingFloatArgumentsForNeon* floatArguments;
+ short* paintingConstants;
+};
+
+short* feLightingConstantsForNeon();
+
+extern "C" {
+void neonDrawLighting(FELightingPaintingDataForNeon*);
+}
+
+} // namespace WebCore
+
+#endif // CPU(ARM_NEON) && COMPILER(GCC)
+
+#endif // FELightingNeon_h
diff --git a/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp b/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp
index 40c9843..f6f428d 100644
--- a/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp
+++ b/Source/WebCore/platform/graphics/gpu/BicubicShader.cpp
@@ -55,11 +55,12 @@ PassOwnPtr<BicubicShader> BicubicShader::create(GraphicsContext3D* context)
static const char* vertexShaderSource =
"uniform mat3 matrix;\n"
"uniform mat3 texMatrix;\n"
- "attribute vec3 position;\n"
+ "attribute vec2 position;\n"
"varying vec2 texCoord;\n"
"void main() {\n"
- " texCoord = (texMatrix * position).xy;\n"
- " gl_Position = vec4(matrix * position, 1.0);\n"
+ " vec3 pos = vec3(position, 1.0);\n"
+ " texCoord = (texMatrix * pos).xy;\n"
+ " gl_Position = vec4(matrix * pos, 1.0);\n"
"}\n";
static const char* fragmentShaderSource =
"#ifdef GL_ES\n"
@@ -127,7 +128,7 @@ void BicubicShader::use(const AffineTransform& transform, const AffineTransform&
m_context->uniform1i(m_imageLocation, 0);
m_context->uniform1f(m_alphaLocation, alpha);
- m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0);
+ m_context->vertexAttribPointer(m_positionLocation, 2, GraphicsContext3D::FLOAT, false, 0, 0);
m_context->enableVertexAttribArray(m_positionLocation);
}
diff --git a/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp
index f0b6bd9..b11d966 100644
--- a/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp
+++ b/Source/WebCore/platform/graphics/gpu/ConvolutionShader.cpp
@@ -58,13 +58,14 @@ PassOwnPtr<ConvolutionShader> ConvolutionShader::create(GraphicsContext3D* conte
"uniform mat3 matrix;\n"
"uniform mat3 texMatrix;\n"
"uniform vec2 imageIncrement;\n"
- "attribute vec3 position;\n"
+ "attribute vec2 position;\n"
"varying vec2 imageCoord;\n"
"void main() {\n"
+ " vec3 pos = vec3(position, 1.0);\n"
" // Offset image coords by half of kernel width, in image texels\n"
- " gl_Position = vec4(matrix * position, 1.0);\n"
+ " gl_Position = vec4(matrix * pos, 1.0);\n"
" float scale = (float(KERNEL_WIDTH) - 1.0) / 2.0;\n"
- " imageCoord = (texMatrix * position).xy - vec2(scale, scale) * imageIncrement;\n"
+ " imageCoord = (texMatrix * pos).xy - vec2(scale, scale) * imageIncrement;\n"
"}\n";
char vertexShaderSource[1024];
snprintf(vertexShaderSource, sizeof(vertexShaderSource), vertexShaderRaw, kernelWidth);
@@ -115,7 +116,7 @@ void ConvolutionShader::use(const AffineTransform& transform, const AffineTransf
kernelWidth = m_kernelWidth;
m_context->uniform1fv(m_kernelLocation, const_cast<float*>(kernel), kernelWidth);
- m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0);
+ m_context->vertexAttribPointer(m_positionLocation, 2, GraphicsContext3D::FLOAT, false, 0, 0);
m_context->enableVertexAttribArray(m_positionLocation);
}
diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
index 2a83fcf..8e293f7 100644
--- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
@@ -144,112 +144,128 @@ void DrawingBuffer::resizeDepthStencil(int sampleCount)
m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
}
-void DrawingBuffer::reset(const IntSize& newSize)
+void DrawingBuffer::clearFramebuffer()
{
- m_size = newSize;
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo);
+ const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes();
+ float clearDepth = 0;
+ int clearStencil = 0;
+ unsigned char depthMask = false;
+ unsigned int stencilMask = 0xffffffff;
+ unsigned char isScissorEnabled = false;
+ unsigned long clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
+ if (attributes.depth) {
+ m_context->getFloatv(GraphicsContext3D::DEPTH_CLEAR_VALUE, &clearDepth);
+ m_context->clearDepth(1);
+ m_context->getBooleanv(GraphicsContext3D::DEPTH_WRITEMASK, &depthMask);
+ m_context->depthMask(true);
+ clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
+ }
+ if (attributes.stencil) {
+ m_context->getIntegerv(GraphicsContext3D::STENCIL_CLEAR_VALUE, &clearStencil);
+ m_context->clearStencil(0);
+ m_context->getIntegerv(GraphicsContext3D::STENCIL_WRITEMASK, reinterpret_cast<int*>(&stencilMask));
+ m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xffffffff);
+ clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
+ }
+ isScissorEnabled = m_context->isEnabled(GraphicsContext3D::SCISSOR_TEST);
+ m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+
+ float clearColor[4];
+ m_context->getFloatv(GraphicsContext3D::COLOR_CLEAR_VALUE, clearColor);
+ m_context->clearColor(0, 0, 0, 0);
+ m_context->clear(clearMask);
+ m_context->clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+
+ if (attributes.depth) {
+ m_context->clearDepth(clearDepth);
+ m_context->depthMask(depthMask);
+ }
+ if (attributes.stencil) {
+ m_context->clearStencil(clearStencil);
+ m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, stencilMask);
+ }
+ if (isScissorEnabled)
+ m_context->enable(GraphicsContext3D::SCISSOR_TEST);
+ else
+ m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+}
+bool DrawingBuffer::reset(const IntSize& newSize)
+{
if (!m_context)
- return;
-
+ return false;
+
m_context->makeContextCurrent();
-
- const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes();
- unsigned long internalColorFormat, colorFormat, internalRenderbufferFormat;
- if (attributes.alpha) {
- internalColorFormat = GraphicsContext3D::RGBA;
- colorFormat = GraphicsContext3D::RGBA;
- internalRenderbufferFormat = Extensions3D::RGBA8_OES;
- } else {
- internalColorFormat = GraphicsContext3D::RGB;
- colorFormat = GraphicsContext3D::RGB;
- internalRenderbufferFormat = Extensions3D::RGB8_OES;
- }
+ int maxTextureSize = 0;
+ m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize);
+ if (newSize.height() > maxTextureSize || newSize.width() > maxTextureSize) {
+ clear();
+ return false;
+ }
- // resize multisample FBO
- if (multisample()) {
- int maxSampleCount = 0;
-
- m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount);
- int sampleCount = std::min(8, maxSampleCount);
+ const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes();
- m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
+ if (newSize != m_size) {
+ m_size = newSize;
- m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer);
- m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalRenderbufferFormat, m_size.width(), m_size.height());
- m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer);
- resizeDepthStencil(sampleCount);
- if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
- // Cleanup
- clear();
- return;
+ unsigned long internalColorFormat, colorFormat, internalRenderbufferFormat;
+ if (attributes.alpha) {
+ internalColorFormat = GraphicsContext3D::RGBA;
+ colorFormat = GraphicsContext3D::RGBA;
+ internalRenderbufferFormat = Extensions3D::RGBA8_OES;
+ } else {
+ internalColorFormat = GraphicsContext3D::RGB;
+ colorFormat = GraphicsContext3D::RGB;
+ internalRenderbufferFormat = Extensions3D::RGB8_OES;
}
- }
- // resize regular FBO
- m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
- m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer);
- m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE);
- m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
- m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
- if (!multisample())
- resizeDepthStencil(0);
- if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
- // Cleanup
- clear();
- return;
- }
+ // resize multisample FBO
+ if (multisample()) {
+ int maxSampleCount = 0;
+
+ m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount);
+ int sampleCount = std::min(8, maxSampleCount);
- if (multisample())
- m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
- if (!m_context->getExtensions()->supports("GL_CHROMIUM_resource_safe")) {
- // Initialize renderbuffers (depth/stencil).
- float clearDepth = 0;
- int clearStencil = 0;
- unsigned char depthMask = true;
- unsigned int stencilMask = 0xffffffff;
- unsigned char isScissorEnabled = false;
- unsigned long clearMask = 0;
- if (attributes.depth) {
- m_context->getFloatv(GraphicsContext3D::DEPTH_CLEAR_VALUE, &clearDepth);
- m_context->clearDepth(1);
- m_context->getBooleanv(GraphicsContext3D::DEPTH_WRITEMASK, &depthMask);
- m_context->depthMask(true);
- clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
- }
- if (attributes.stencil) {
- m_context->getIntegerv(GraphicsContext3D::STENCIL_CLEAR_VALUE, &clearStencil);
- m_context->clearStencil(0);
- m_context->getIntegerv(GraphicsContext3D::STENCIL_WRITEMASK, reinterpret_cast<int*>(&stencilMask));
- m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xffffffff);
- clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
+ m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer);
+ m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalRenderbufferFormat, m_size.width(), m_size.height());
+ m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer);
+ resizeDepthStencil(sampleCount);
+ if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
+ // Cleanup
+ clear();
+ return false;
+ }
}
- if (clearMask) {
- isScissorEnabled = m_context->isEnabled(GraphicsContext3D::SCISSOR_TEST);
- m_context->disable(GraphicsContext3D::SCISSOR_TEST);
- m_context->clear(clearMask);
+ // resize regular FBO
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
- if (attributes.depth) {
- m_context->clearDepth(clearDepth);
- m_context->depthMask(depthMask);
- }
- if (attributes.stencil) {
- m_context->clearStencil(clearStencil);
- m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, stencilMask);
- }
- if (isScissorEnabled)
- m_context->enable(GraphicsContext3D::SCISSOR_TEST);
- else
- m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer);
+
+ m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE);
+
+ m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
+
+ if (!multisample())
+ resizeDepthStencil(0);
+ if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
+ // Cleanup
+ clear();
+ return false;
}
}
- m_context->flush();
-
+ clearFramebuffer();
+
didReset();
+
+ return true;
}
void DrawingBuffer::commit(long x, long y, long width, long height)
diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
index 606484e..caf3aa5 100644
--- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
+++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
@@ -44,6 +44,7 @@
#if ENABLE(SKIA_GPU)
class GrContext;
+struct GrPlatformSurfaceDesc;
#endif
namespace WebCore {
@@ -60,7 +61,10 @@ public:
~DrawingBuffer();
- void reset(const IntSize&);
+ void clearFramebuffer();
+
+ // Returns true if the buffer was successfully resized.
+ bool reset(const IntSize&);
void bind();
IntSize size() const { return m_size; }
Platform3DObject colorBuffer() const { return m_colorBuffer; }
@@ -101,6 +105,7 @@ public:
#if ENABLE(SKIA_GPU)
void setGrContext(GrContext* ctx);
+ void getGrPlatformSurfaceDesc(GrPlatformSurfaceDesc*);
#endif
PassRefPtr<GraphicsContext3D> graphicsContext3D() const { return m_context; }
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp b/Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp
index 5b155a5..b228cbf 100644
--- a/Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.cpp
@@ -562,6 +562,108 @@ int numXRayCrossingsForCubic(const XRay& xRay, const FloatPoint cubic[4], bool&
return numCrossings;
}
+/*
+ * Based on C code from the article
+ * "Testing the Convexity of a Polygon"
+ * by Peter Schorn and Frederick Fisher,
+ * (schorn@inf.ethz.ch, fred@kpc.com)
+ * in "Graphics Gems IV", Academic Press, 1994
+ */
+
+static inline int convexCompare(const FloatSize& delta)
+{
+ return (delta.width() > 0) ? -1 : /* x coord diff, second pt > first pt */
+ (delta.width() < 0) ? 1 : /* x coord diff, second pt < first pt */
+ (delta.height() > 0) ? -1 : /* x coord same, second pt > first pt */
+ (delta.height() < 0) ? 1 : /* x coord same, second pt > first pt */
+ 0; /* second pt equals first point */
+}
+
+static inline float convexCross(const FloatSize& p, const FloatSize& q)
+{
+ return p.width() * q.height() - p.height() * q.width();
+}
+
+static inline bool convexCheckTriple(const FloatSize& dcur, const FloatSize& dprev, int* curDir, int* dirChanges, int* angleSign)
+{
+ int thisDir = convexCompare(dcur);
+ if (thisDir == -*curDir)
+ ++*dirChanges;
+ *curDir = thisDir;
+ float cross = convexCross(dprev, dcur);
+ if (cross > 0) {
+ if (*angleSign == -1)
+ return false;
+ *angleSign = 1;
+ } else if (cross < 0) {
+ if (*angleSign == 1)
+ return false;
+ *angleSign = -1;
+ }
+ return true;
+}
+
+bool isConvex(const FloatPoint* vertices, int nVertices)
+{
+ int dirChanges = 0, angleSign = 0;
+ FloatPoint second, third;
+ FloatSize dprev, dcur;
+
+ /* Get different point, return if less than 3 diff points. */
+ if (nVertices < 3)
+ return false;
+ int i = 1;
+ while (true) {
+ second = vertices[i++];
+ dprev = second - vertices[0];
+ if (dprev.width() || dprev.height())
+ break;
+ /* Check if out of points. Check here to avoid slowing down cases
+ * without repeated points.
+ */
+ if (i >= nVertices)
+ return false;
+ }
+ FloatPoint saveSecond = second;
+ int curDir = convexCompare(dprev); /* Find initial direction */
+ while (i < nVertices) {
+ /* Get different point, break if no more points */
+ third = vertices[i++];
+ dcur = third - second;
+ if (!dcur.width() && !dcur.height())
+ continue;
+
+ /* Check current three points */
+ if (!convexCheckTriple(dcur, dprev, &curDir, &dirChanges, &angleSign))
+ return false;
+ second = third; /* Remember ptr to current point. */
+ dprev = dcur; /* Remember current delta. */
+ }
+
+ /* Must check for direction changes from last vertex back to first */
+ third = vertices[0]; /* Prepare for 'ConvexCheckTriple' */
+ dcur = third - second;
+ if (convexCompare(dcur)) {
+ if (!convexCheckTriple(dcur, dprev, &curDir, &dirChanges, &angleSign))
+ return false;
+ second = third; /* Remember ptr to current point. */
+ dprev = dcur; /* Remember current delta. */
+ }
+
+ /* and check for direction changes back to second vertex */
+ dcur = saveSecond - second;
+ if (!convexCheckTriple(dcur, dprev, &curDir, &dirChanges, &angleSign))
+ return false;
+
+ /* Decide on polygon type given accumulated status */
+ if (dirChanges > 2)
+ return false;
+
+ if (angleSign > 0 || angleSign < 0)
+ return true;
+ return false;
+}
+
} // namespace LoopBlinnMathUtils
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.h b/Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.h
index b9d19c5..361d901 100644
--- a/Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.h
+++ b/Source/WebCore/platform/graphics/gpu/LoopBlinnMathUtils.h
@@ -101,6 +101,9 @@ bool xRayCrossesLine(const XRay& xRay,
const FloatPoint lineEndpoints[2],
bool& ambiguous);
+
+bool isConvex(const FloatPoint* vertices, int nVertices);
+
} // namespace LoopBlinnMathUtils
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/gpu/Shader.cpp b/Source/WebCore/platform/graphics/gpu/Shader.cpp
index 1b9bfd5..13c5ebf 100644
--- a/Source/WebCore/platform/graphics/gpu/Shader.cpp
+++ b/Source/WebCore/platform/graphics/gpu/Shader.cpp
@@ -140,7 +140,7 @@ String Shader::generateVertex(Shader::VertexType vertexType, Shader::FillType fi
case TwoDimensional:
builder.append(
"uniform mat3 matrix;\n"
- "attribute vec3 position;\n");
+ "attribute vec2 position;\n");
break;
case LoopBlinnInterior:
builder.append(
@@ -167,7 +167,7 @@ String Shader::generateVertex(Shader::VertexType vertexType, Shader::FillType fi
if (vertexType == TwoDimensional) {
builder.append(
- "gl_Position = vec4(matrix * position, 1.0);\n");
+ "gl_Position = vec4(matrix * vec3(position, 1.0), 1.0);\n");
} else {
builder.append(
"gl_Position = worldViewProjection * vec4(position, 0.0, 1.0);\n");
@@ -179,7 +179,7 @@ String Shader::generateVertex(Shader::VertexType vertexType, Shader::FillType fi
if (fillType == TextureFill) {
builder.append(
- "texCoord = texMatrix * position;\n");
+ "texCoord = texMatrix * vec3(position, 1.0);\n");
}
builder.append(
diff --git a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
index 662d6a8..b7b94c4 100644
--- a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
+++ b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
@@ -346,10 +346,10 @@ void SharedGraphicsContext3D::enableStencil(bool enable)
void SharedGraphicsContext3D::useQuadVertices()
{
if (!m_quadVertices) {
- float vertices[] = { 0.0f, 0.0f, 1.0f,
- 1.0f, 0.0f, 1.0f,
- 0.0f, 1.0f, 1.0f,
- 1.0f, 1.0f, 1.0f };
+ float vertices[] = { 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f };
m_quadVertices = m_context->createBuffer();
m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVertices);
m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW);
diff --git a/Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp b/Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp
index 78381f0..0a6e084 100644
--- a/Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp
+++ b/Source/WebCore/platform/graphics/gpu/SolidFillShader.cpp
@@ -69,7 +69,7 @@ void SolidFillShader::use(const AffineTransform& transform, const Color& color)
affineTo3x3(transform, matrix);
m_context->uniformMatrix3fv(m_matrixLocation, false /*transpose*/, matrix, 1 /*count*/);
- m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0);
+ m_context->vertexAttribPointer(m_positionLocation, 2, GraphicsContext3D::FLOAT, false, 0, 0);
m_context->enableVertexAttribArray(m_positionLocation);
}
diff --git a/Source/WebCore/platform/graphics/gpu/TexShader.cpp b/Source/WebCore/platform/graphics/gpu/TexShader.cpp
index 9eb5c16..ac141a5 100644
--- a/Source/WebCore/platform/graphics/gpu/TexShader.cpp
+++ b/Source/WebCore/platform/graphics/gpu/TexShader.cpp
@@ -72,7 +72,7 @@ void TexShader::use(const AffineTransform& transform, const AffineTransform& tex
m_context->uniform1i(m_samplerLocation, sampler);
m_context->uniform1f(m_alphaLocation, alpha);
- m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0);
+ m_context->vertexAttribPointer(m_positionLocation, 2, GraphicsContext3D::FLOAT, false, 0, 0);
m_context->enableVertexAttribArray(m_positionLocation);
diff --git a/Source/WebCore/platform/graphics/gpu/TilingData.cpp b/Source/WebCore/platform/graphics/gpu/TilingData.cpp
index 1370543..2415ee4 100644
--- a/Source/WebCore/platform/graphics/gpu/TilingData.cpp
+++ b/Source/WebCore/platform/graphics/gpu/TilingData.cpp
@@ -44,6 +44,9 @@ namespace WebCore {
static int computeNumTiles(int maxTextureSize, int totalSize, int borderTexels)
{
+ if (maxTextureSize - 2 * borderTexels <= 0)
+ return totalSize > 0 && maxTextureSize >= totalSize ? 1 : 0;
+
int numTiles = max(1, 1 + (totalSize - 1 - 2 * borderTexels) / (maxTextureSize - 2 * borderTexels));
return totalSize > 0 ? numTiles : 0;
}
diff --git a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h
index 6e53cfc..332908d 100644
--- a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h
+++ b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h
@@ -27,7 +27,7 @@
#include <gst/video/video.h>
#include <wtf/PassRefPtr.h>
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
#include <cairo.h>
#endif
@@ -48,7 +48,7 @@ class ImageGStreamer : public RefCounted<ImageGStreamer> {
private:
RefPtr<BitmapImage> m_image;
-#if PLATFORM(CAIRO)
+#if USE(CAIRO)
ImageGStreamer(GstBuffer*&, IntSize, cairo_format_t&);
#endif
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index 2fb4cef..56c2f30 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -81,194 +81,74 @@ static int greatestCommonDivisor(int a, int b)
return ABS(a);
}
-gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data)
+static gboolean mediaPlayerPrivateMessageCallback(GstBus*, GstMessage* message, MediaPlayerPrivateGStreamer* player)
{
- GOwnPtr<GError> err;
- GOwnPtr<gchar> debug;
- MediaPlayer::NetworkState error;
- MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
- bool issueError = true;
- bool attemptNextLocation = false;
- GstElement* pipeline = mp->pipeline();
-
- if (message->structure) {
- const gchar* messageTypeName = gst_structure_get_name(message->structure);
-
- // Redirect messages are sent from elements, like qtdemux, to
- // notify of the new location(s) of the media.
- if (!g_strcmp0(messageTypeName, "redirect")) {
- mp->mediaLocationChanged(message);
- return true;
- }
- }
-
- switch (GST_MESSAGE_TYPE(message)) {
- case GST_MESSAGE_ERROR:
- if (mp && mp->pipelineReset())
- break;
- gst_message_parse_error(message, &err.outPtr(), &debug.outPtr());
- LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message);
-
- error = MediaPlayer::Empty;
- if (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND
- || err->code == GST_STREAM_ERROR_WRONG_TYPE
- || err->code == GST_STREAM_ERROR_FAILED
- || err->code == GST_CORE_ERROR_MISSING_PLUGIN
- || err->code == GST_RESOURCE_ERROR_NOT_FOUND)
- error = MediaPlayer::FormatError;
- else if (err->domain == GST_STREAM_ERROR) {
- // Let the mediaPlayerClient handle the stream error, in
- // this case the HTMLMediaElement will emit a stalled
- // event.
- if (err->code == GST_STREAM_ERROR_TYPE_NOT_FOUND) {
- LOG_VERBOSE(Media, "Decode error, let the Media element emit a stalled event.");
- break;
- }
- error = MediaPlayer::DecodeError;
- attemptNextLocation = true;
- } else if (err->domain == GST_RESOURCE_ERROR)
- error = MediaPlayer::NetworkError;
-
- if (mp) {
- if (attemptNextLocation)
- issueError = !mp->loadNextLocation();
- if (issueError)
- mp->loadingFailed(error);
- }
- break;
- case GST_MESSAGE_EOS:
- LOG_VERBOSE(Media, "End of Stream");
- mp->didEnd();
- break;
- case GST_MESSAGE_STATE_CHANGED:
- // Ignore state changes if load is delayed (preload=none). The
- // player state will be updated once commitLoad() is called.
- if (mp->loadDelayed()) {
- LOG_VERBOSE(Media, "Media load has been delayed. Ignoring state changes for now");
- break;
- }
-
- // Ignore state changes from internal elements. They are
- // forwarded to playbin2 anyway.
- if (GST_MESSAGE_SRC(message) == reinterpret_cast<GstObject*>(pipeline))
- mp->updateStates();
- break;
- case GST_MESSAGE_BUFFERING:
- mp->processBufferingStats(message);
- break;
- case GST_MESSAGE_DURATION:
- LOG_VERBOSE(Media, "Duration changed");
- mp->durationChanged();
- break;
- default:
- LOG_VERBOSE(Media, "Unhandled GStreamer message type: %s",
- GST_MESSAGE_TYPE_NAME(message));
- break;
- }
- return true;
+ return player->handleMessage(message);
}
-void mediaPlayerPrivateSourceChangedCallback(GObject *object, GParamSpec *pspec, gpointer data)
+static void mediaPlayerPrivateSourceChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
{
- MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
- GOwnPtr<GstElement> element;
-
- g_object_get(mp->m_playBin, "source", &element.outPtr(), NULL);
- gst_object_replace((GstObject**) &mp->m_source, (GstObject*) element.get());
-
- if (WEBKIT_IS_WEB_SRC(element.get())) {
- Frame* frame = mp->m_player->frameView() ? mp->m_player->frameView()->frame() : 0;
-
- if (frame)
- webKitWebSrcSetFrame(WEBKIT_WEB_SRC(element.get()), frame);
- }
+ player->sourceChanged();
}
-void mediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
+static void mediaPlayerPrivateVolumeChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
{
// This is called when playbin receives the notify::volume signal.
- MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
- mp->volumeChanged();
+ player->volumeChanged();
}
-gboolean mediaPlayerPrivateVolumeChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+static gboolean mediaPlayerPrivateVolumeChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
{
// This is the callback of the timeout source created in ::volumeChanged.
player->notifyPlayerOfVolumeChange();
return FALSE;
}
-void mediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
+static void mediaPlayerPrivateMuteChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
{
// This is called when playbin receives the notify::mute signal.
- MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
- mp->muteChanged();
+ player->muteChanged();
}
-gboolean mediaPlayerPrivateMuteChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+static gboolean mediaPlayerPrivateMuteChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
{
// This is the callback of the timeout source created in ::muteChanged.
player->notifyPlayerOfMute();
return FALSE;
}
-void mediaPlayerPrivateVideoTagsChangedCallback(GObject* element, gint streamId, MediaPlayerPrivateGStreamer* player)
+static void mediaPlayerPrivateVideoSinkCapsChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
{
- player->videoTagsChanged(streamId);
+ player->videoChanged();
}
-void mediaPlayerPrivateAudioTagsChangedCallback(GObject* element, gint streamId, MediaPlayerPrivateGStreamer* player)
+static void mediaPlayerPrivateVideoChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
{
- player->audioTagsChanged(streamId);
+ player->videoChanged();
}
-gboolean mediaPlayerPrivateAudioTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+static void mediaPlayerPrivateAudioChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
{
- // This is the callback of the timeout source created in ::audioTagsChanged.
- player->notifyPlayerOfAudioTags();
- return FALSE;
+ player->audioChanged();
}
-gboolean mediaPlayerPrivateVideoTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+static gboolean mediaPlayerPrivateAudioChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
{
- // This is the callback of the timeout source created in ::videoTagsChanged.
- player->notifyPlayerOfVideoTags();
+ // This is the callback of the timeout source created in ::audioChanged.
+ player->notifyPlayerOfAudio();
return FALSE;
}
-static float playbackPosition(GstElement* playbin)
+static gboolean mediaPlayerPrivateVideoChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
{
-
- float ret = 0.0f;
-
- GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
- if (!gst_element_query(playbin, query)) {
- LOG_VERBOSE(Media, "Position query failed...");
- gst_query_unref(query);
- return ret;
- }
-
- gint64 position;
- gst_query_parse_position(query, 0, &position);
-
- // Position is available only if the pipeline is not in GST_STATE_NULL or
- // GST_STATE_READY state.
- if (position != static_cast<gint64>(GST_CLOCK_TIME_NONE))
- ret = static_cast<float>(position) / static_cast<float>(GST_SECOND);
-
- LOG_VERBOSE(Media, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
-
- gst_query_unref(query);
-
- return ret;
+ // This is the callback of the timeout source created in ::videoChanged.
+ player->notifyPlayerOfVideo();
+ return FALSE;
}
-
-void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivateGStreamer* playerPrivate)
+static void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivateGStreamer* playerPrivate)
{
- g_return_if_fail(GST_IS_BUFFER(buffer));
- gst_buffer_replace(&playerPrivate->m_buffer, buffer);
- playerPrivate->repaint();
+ playerPrivate->triggerRepaint(buffer);
}
MediaPlayerPrivateInterface* MediaPlayerPrivateGStreamer::create(MediaPlayer* player)
@@ -347,8 +227,9 @@ MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player)
, m_muteTimerHandler(0)
, m_hasVideo(false)
, m_hasAudio(false)
- , m_audioTagsTimerHandler(0)
- , m_videoTagsTimerHandler(0)
+ , m_audioTimerHandler(0)
+ , m_videoTimerHandler(0)
+ , m_webkitAudioSink(0)
{
if (doGstInit())
createGSTPlayBin();
@@ -392,11 +273,11 @@ MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer()
if (m_volumeTimerHandler)
g_source_remove(m_volumeTimerHandler);
- if (m_videoTagsTimerHandler)
- g_source_remove(m_videoTagsTimerHandler);
+ if (m_videoTimerHandler)
+ g_source_remove(m_videoTimerHandler);
- if (m_audioTagsTimerHandler)
- g_source_remove(m_audioTagsTimerHandler);
+ if (m_audioTimerHandler)
+ g_source_remove(m_audioTimerHandler);
}
void MediaPlayerPrivateGStreamer::load(const String& url)
@@ -425,6 +306,32 @@ void MediaPlayerPrivateGStreamer::commitLoad()
updateStates();
}
+float MediaPlayerPrivateGStreamer::playbackPosition() const
+{
+ float ret = 0.0f;
+
+ GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
+ if (!gst_element_query(m_playBin, query)) {
+ LOG_VERBOSE(Media, "Position query failed...");
+ gst_query_unref(query);
+ return ret;
+ }
+
+ gint64 position;
+ gst_query_parse_position(query, 0, &position);
+
+ // Position is available only if the pipeline is not in GST_STATE_NULL or
+ // GST_STATE_READY state.
+ if (position != static_cast<gint64>(GST_CLOCK_TIME_NONE))
+ ret = static_cast<float>(position) / static_cast<float>(GST_SECOND);
+
+ LOG_VERBOSE(Media, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
+
+ gst_query_unref(query);
+
+ return ret;
+}
+
bool MediaPlayerPrivateGStreamer::changePipelineState(GstState newState)
{
ASSERT(newState == GST_STATE_PLAYING || newState == GST_STATE_PAUSED);
@@ -504,14 +411,14 @@ float MediaPlayerPrivateGStreamer::currentTime() const
if (m_seeking)
return m_seekTime;
- return playbackPosition(m_playBin);
+ return playbackPosition();
}
void MediaPlayerPrivateGStreamer::seek(float time)
{
// Avoid useless seeking.
- if (time == playbackPosition(m_playBin))
+ if (time == playbackPosition())
return;
if (!m_playBin)
@@ -582,6 +489,7 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const
|| !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
&pixelAspectRatioDenominator)) {
gst_object_unref(GST_OBJECT(pad));
+ // The video-sink has likely not yet negotiated its caps.
return IntSize();
}
@@ -618,39 +526,40 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const
return IntSize(static_cast<int>(width), static_cast<int>(height));
}
-void MediaPlayerPrivateGStreamer::videoTagsChanged(gint streamId)
+void MediaPlayerPrivateGStreamer::videoChanged()
{
- if (m_videoTagsTimerHandler)
- g_source_remove(m_videoTagsTimerHandler);
- m_videoTagsTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVideoTagsChangeTimeoutCallback), this);
+ if (m_videoTimerHandler)
+ g_source_remove(m_videoTimerHandler);
+ m_videoTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVideoChangeTimeoutCallback), this);
}
-void MediaPlayerPrivateGStreamer::notifyPlayerOfVideoTags()
+void MediaPlayerPrivateGStreamer::notifyPlayerOfVideo()
{
- m_videoTagsTimerHandler = 0;
+ m_videoTimerHandler = 0;
- gint currentVideo = -1;
+ gint videoTracks = 0;
if (m_playBin)
- g_object_get(m_playBin, "current-video", &currentVideo, NULL);
- m_hasVideo = currentVideo > -1;
+ g_object_get(m_playBin, "n-video", &videoTracks, NULL);
+
+ m_hasVideo = videoTracks > 0;
m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
}
-void MediaPlayerPrivateGStreamer::audioTagsChanged(gint streamId)
+void MediaPlayerPrivateGStreamer::audioChanged()
{
- if (m_audioTagsTimerHandler)
- g_source_remove(m_audioTagsTimerHandler);
- m_audioTagsTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateAudioTagsChangeTimeoutCallback), this);
+ if (m_audioTimerHandler)
+ g_source_remove(m_audioTimerHandler);
+ m_audioTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateAudioChangeTimeoutCallback), this);
}
-void MediaPlayerPrivateGStreamer::notifyPlayerOfAudioTags()
+void MediaPlayerPrivateGStreamer::notifyPlayerOfAudio()
{
- m_audioTagsTimerHandler = 0;
+ m_audioTimerHandler = 0;
- gint currentAudio = -1;
+ gint audioTracks = 0;
if (m_playBin)
- g_object_get(m_playBin, "current-audio", &currentAudio, NULL);
- m_hasAudio = currentAudio > -1;
+ g_object_get(m_playBin, "n-audio", &audioTracks, NULL);
+ m_hasAudio = audioTracks > 0;
m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
}
@@ -704,13 +613,19 @@ void MediaPlayerPrivateGStreamer::setRate(float rate)
m_playbackRate = rate;
m_changingRate = true;
- float currentPosition = static_cast<float>(playbackPosition(m_playBin) * GST_SECOND);
+
+ if (!rate) {
+ gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ return;
+ }
+
+ float currentPosition = static_cast<float>(playbackPosition() * GST_SECOND);
GstSeekFlags flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH);
gint64 start, end;
bool mute = false;
LOG_VERBOSE(Media, "Set Rate to %f", rate);
- if (rate >= 0) {
+ if (rate > 0) {
// Mute the sound if the playback rate is too extreme.
// TODO: in other cases we should perform pitch adjustments.
mute = (bool) (rate < 0.8 || rate > 2);
@@ -788,6 +703,89 @@ PassRefPtr<TimeRanges> MediaPlayerPrivateGStreamer::buffered() const
return timeRanges.release();
}
+gboolean MediaPlayerPrivateGStreamer::handleMessage(GstMessage* message)
+{
+ GOwnPtr<GError> err;
+ GOwnPtr<gchar> debug;
+ MediaPlayer::NetworkState error;
+ bool issueError = true;
+ bool attemptNextLocation = false;
+
+ if (message->structure) {
+ const gchar* messageTypeName = gst_structure_get_name(message->structure);
+
+ // Redirect messages are sent from elements, like qtdemux, to
+ // notify of the new location(s) of the media.
+ if (!g_strcmp0(messageTypeName, "redirect")) {
+ mediaLocationChanged(message);
+ return TRUE;
+ }
+ }
+
+ switch (GST_MESSAGE_TYPE(message)) {
+ case GST_MESSAGE_ERROR:
+ if (m_resetPipeline)
+ break;
+ gst_message_parse_error(message, &err.outPtr(), &debug.outPtr());
+ LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message);
+
+ error = MediaPlayer::Empty;
+ if (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND
+ || err->code == GST_STREAM_ERROR_WRONG_TYPE
+ || err->code == GST_STREAM_ERROR_FAILED
+ || err->code == GST_CORE_ERROR_MISSING_PLUGIN
+ || err->code == GST_RESOURCE_ERROR_NOT_FOUND)
+ error = MediaPlayer::FormatError;
+ else if (err->domain == GST_STREAM_ERROR) {
+ // Let the mediaPlayerClient handle the stream error, in
+ // this case the HTMLMediaElement will emit a stalled
+ // event.
+ if (err->code == GST_STREAM_ERROR_TYPE_NOT_FOUND) {
+ LOG_VERBOSE(Media, "Decode error, let the Media element emit a stalled event.");
+ break;
+ }
+ error = MediaPlayer::DecodeError;
+ attemptNextLocation = true;
+ } else if (err->domain == GST_RESOURCE_ERROR)
+ error = MediaPlayer::NetworkError;
+
+ if (attemptNextLocation)
+ issueError = !loadNextLocation();
+ if (issueError)
+ loadingFailed(error);
+ break;
+ case GST_MESSAGE_EOS:
+ LOG_VERBOSE(Media, "End of Stream");
+ didEnd();
+ break;
+ case GST_MESSAGE_STATE_CHANGED:
+ // Ignore state changes if load is delayed (preload=none). The
+ // player state will be updated once commitLoad() is called.
+ if (m_delayingLoad) {
+ LOG_VERBOSE(Media, "Media load has been delayed. Ignoring state changes for now");
+ break;
+ }
+
+ // Ignore state changes from internal elements. They are
+ // forwarded to playbin2 anyway.
+ if (GST_MESSAGE_SRC(message) == reinterpret_cast<GstObject*>(m_playBin))
+ updateStates();
+ break;
+ case GST_MESSAGE_BUFFERING:
+ processBufferingStats(message);
+ break;
+ case GST_MESSAGE_DURATION:
+ LOG_VERBOSE(Media, "Duration changed");
+ durationChanged();
+ break;
+ default:
+ LOG_VERBOSE(Media, "Unhandled GStreamer message type: %s",
+ GST_MESSAGE_TYPE_NAME(message));
+ break;
+ }
+ return TRUE;
+}
+
void MediaPlayerPrivateGStreamer::processBufferingStats(GstMessage* message)
{
// This is the immediate buffering that needs to happen so we have
@@ -952,6 +950,75 @@ unsigned MediaPlayerPrivateGStreamer::totalBytes() const
return static_cast<unsigned>(length);
}
+unsigned MediaPlayerPrivateGStreamer::decodedFrameCount() const
+{
+ guint64 decodedFrames = 0;
+ if (m_fpsSink)
+ g_object_get(m_fpsSink, "frames-rendered", &decodedFrames, NULL);
+ return static_cast<unsigned>(decodedFrames);
+}
+
+unsigned MediaPlayerPrivateGStreamer::droppedFrameCount() const
+{
+ guint64 framesDropped = 0;
+ if (m_fpsSink)
+ g_object_get(m_fpsSink, "frames-dropped", &framesDropped, NULL);
+ return static_cast<unsigned>(framesDropped);
+}
+
+unsigned MediaPlayerPrivateGStreamer::audioDecodedByteCount() const
+{
+ GstQuery* query = gst_query_new_position(GST_FORMAT_BYTES);
+ gint64 position = 0;
+
+ if (m_webkitAudioSink && gst_element_query(m_webkitAudioSink, query))
+ gst_query_parse_position(query, 0, &position);
+
+ gst_query_unref(query);
+ return static_cast<unsigned>(position);
+}
+
+unsigned MediaPlayerPrivateGStreamer::videoDecodedByteCount() const
+{
+ GstQuery* query = gst_query_new_position(GST_FORMAT_BYTES);
+ gint64 position = 0;
+
+ if (gst_element_query(m_webkitVideoSink, query))
+ gst_query_parse_position(query, 0, &position);
+
+ gst_query_unref(query);
+ return static_cast<unsigned>(position);
+}
+
+void MediaPlayerPrivateGStreamer::updateAudioSink()
+{
+ if (!m_playBin)
+ return;
+
+ GOwnPtr<GstElement> element;
+
+ g_object_get(m_playBin, "audio-sink", &element.outPtr(), NULL);
+ gst_object_replace(reinterpret_cast<GstObject**>(&m_webkitAudioSink),
+ reinterpret_cast<GstObject*>(element.get()));
+}
+
+
+void MediaPlayerPrivateGStreamer::sourceChanged()
+{
+ GOwnPtr<GstElement> element;
+
+ g_object_get(m_playBin, "source", &element.outPtr(), NULL);
+ gst_object_replace(reinterpret_cast<GstObject**>(&m_source),
+ reinterpret_cast<GstObject*>(element.get()));
+
+ if (WEBKIT_IS_WEB_SRC(element.get())) {
+ Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0;
+
+ if (frame)
+ webKitWebSrcSetFrame(WEBKIT_WEB_SRC(element.get()), frame);
+ }
+}
+
void MediaPlayerPrivateGStreamer::cancelLoad()
{
if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded)
@@ -1011,6 +1078,8 @@ void MediaPlayerPrivateGStreamer::updateStates()
// information from GStreamer, while we sync states where
// needed.
if (state == GST_STATE_PAUSED) {
+ if (!m_webkitAudioSink)
+ updateAudioSink();
if (m_buffering && m_bufferingPercentage == 100) {
m_buffering = false;
m_bufferingPercentage = 0;
@@ -1347,8 +1416,11 @@ void MediaPlayerPrivateGStreamer::setVisible(bool visible)
{
}
-void MediaPlayerPrivateGStreamer::repaint()
+
+void MediaPlayerPrivateGStreamer::triggerRepaint(GstBuffer* buffer)
{
+ g_return_if_fail(GST_IS_BUFFER(buffer));
+ gst_buffer_replace(&m_buffer, buffer);
m_player->repaint();
}
@@ -1359,6 +1431,7 @@ void MediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect&
if (!m_player->visible())
return;
+
if (!m_buffer)
return;
@@ -1477,6 +1550,9 @@ static HashSet<String> mimeTypeCache()
|| (g_str_equal(mimetype[0], "application")
&& handledApplicationSubtypes.contains(String(mimetype[1]))))
cache.add(String(name));
+ else if (g_str_equal(name, "application/x-hls"))
+ cache.add(String("application/vnd.apple.mpegurl"));
+
g_strfreev(mimetype);
}
@@ -1584,8 +1660,8 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin()
g_signal_connect(m_playBin, "notify::volume", G_CALLBACK(mediaPlayerPrivateVolumeChangedCallback), this);
g_signal_connect(m_playBin, "notify::source", G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this);
g_signal_connect(m_playBin, "notify::mute", G_CALLBACK(mediaPlayerPrivateMuteChangedCallback), this);
- g_signal_connect(m_playBin, "video-tags-changed", G_CALLBACK(mediaPlayerPrivateVideoTagsChangedCallback), this);
- g_signal_connect(m_playBin, "audio-tags-changed", G_CALLBACK(mediaPlayerPrivateAudioTagsChangedCallback), this);
+ g_signal_connect(m_playBin, "video-changed", G_CALLBACK(mediaPlayerPrivateVideoChangedCallback), this);
+ g_signal_connect(m_playBin, "audio-changed", G_CALLBACK(mediaPlayerPrivateAudioChangedCallback), this);
m_webkitVideoSink = webkit_video_sink_new();
@@ -1613,39 +1689,44 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin()
gst_object_unref(GST_OBJECT(srcPad));
gst_object_unref(GST_OBJECT(sinkPad));
- WTFLogChannel* channel = getChannelFromName("Media");
- if (channel->state == WTFLogChannelOn) {
- m_fpsSink = gst_element_factory_make("fpsdisplaysink", "sink");
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_fpsSink), "video-sink")) {
- g_object_set(m_fpsSink, "video-sink", m_webkitVideoSink, NULL);
- gst_bin_add(GST_BIN(m_videoSinkBin), m_fpsSink);
-#if GST_CHECK_VERSION(0, 10, 30)
- // Faster elements linking, if possible.
- gst_element_link_pads_full(queue, "src", m_fpsSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
-#else
- gst_element_link(queue, m_fpsSink);
-#endif
- } else {
+ GstElement* actualVideoSink = 0;
+ m_fpsSink = gst_element_factory_make("fpsdisplaysink", "sink");
+ if (m_fpsSink) {
+ // The verbose property has been added in -bad 0.10.22. Making
+ // this whole code depend on it because we don't want
+ // fpsdiplaysink to spit data on stdout.
+ GstElementFactory* factory = GST_ELEMENT_FACTORY(GST_ELEMENT_GET_CLASS(m_fpsSink)->elementfactory);
+ if (gst_plugin_feature_check_version(GST_PLUGIN_FEATURE(factory), 0, 10, 22)) {
+ g_object_set(m_fpsSink, "silent", TRUE , NULL);
+
+ // Turn off text overlay unless logging is enabled.
+ WTFLogChannel* channel = getChannelFromName("Media");
+ if (channel->state != WTFLogChannelOn)
+ g_object_set(m_fpsSink, "text-overlay", FALSE , NULL);
+
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_fpsSink), "video-sink")) {
+ g_object_set(m_fpsSink, "video-sink", m_webkitVideoSink, NULL);
+ gst_bin_add(GST_BIN(m_videoSinkBin), m_fpsSink);
+ actualVideoSink = m_fpsSink;
+ } else
+ m_fpsSink = 0;
+ } else
m_fpsSink = 0;
- gst_bin_add(GST_BIN(m_videoSinkBin), m_webkitVideoSink);
-#if GST_CHECK_VERSION(0, 10, 30)
- // Faster elements linking, if possible.
- gst_element_link_pads_full(queue, "src", m_webkitVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
-#else
- gst_element_link(queue, m_webkitVideoSink);
-#endif
- LOG_VERBOSE(Media, "Can't display FPS statistics, you need gst-plugins-bad >= 0.10.18");
- }
- } else {
+ }
+
+ if (!m_fpsSink) {
gst_bin_add(GST_BIN(m_videoSinkBin), m_webkitVideoSink);
+ actualVideoSink = m_webkitVideoSink;
+ }
+
+ ASSERT(actualVideoSink);
#if GST_CHECK_VERSION(0, 10, 30)
// Faster elements linking, if possible.
gst_element_link_pads_full(queue, "src", identity, "sink", GST_PAD_LINK_CHECK_NOTHING);
- gst_element_link_pads_full(identity, "src", m_webkitVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
+ gst_element_link_pads_full(identity, "src", actualVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
#else
- gst_element_link_many(queue, identity, m_webkitVideoSink, NULL);
+ gst_element_link_many(queue, identity, actualVideoSink, NULL);
#endif
- }
// Add a ghostpad to the bin so it can proxy to tee.
GstPad* pad = gst_element_get_static_pad(videoTee, "sink");
@@ -1654,6 +1735,14 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin()
// Set the bin as video sink of playbin.
g_object_set(m_playBin, "video-sink", m_videoSinkBin, NULL);
+
+
+ pad = gst_element_get_static_pad(m_webkitVideoSink, "sink");
+ if (pad) {
+ g_signal_connect(pad, "notify::caps", G_CALLBACK(mediaPlayerPrivateVideoSinkCapsChangedCallback), this);
+ gst_object_unref(GST_OBJECT(pad));
+ }
+
}
}
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
index 8003887..024fad0 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
@@ -35,7 +35,6 @@ typedef struct _WebKitVideoSink WebKitVideoSink;
typedef struct _GstBuffer GstBuffer;
typedef struct _GstMessage GstMessage;
typedef struct _GstElement GstElement;
-typedef struct _GstBus GstBus;
namespace WebCore {
@@ -45,25 +44,11 @@ class IntRect;
class GStreamerGWorld;
class MediaPlayerPrivateGStreamer;
-gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
-void mediaPlayerPrivateVolumeChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
-void mediaPlayerPrivateMuteChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
-void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
-void mediaPlayerPrivateVideoTagsChangedCallback(GObject* element, gint, MediaPlayerPrivateGStreamer*);
-void mediaPlayerPrivateAudioTagsChangedCallback(GObject* element, gint, MediaPlayerPrivateGStreamer*);
-gboolean mediaPlayerPrivateAudioTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player);
-gboolean mediaPlayerPrivateVideoTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player);
-
-gboolean mediaPlayerPrivateVolumeChangeTimeoutCallback(MediaPlayerPrivateGStreamer*);
-gboolean mediaPlayerPrivateMuteChangeTimeoutCallback(MediaPlayerPrivateGStreamer*);
-
class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
- friend gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
- friend void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer* buffer, MediaPlayerPrivateGStreamer* playerPrivate);
- friend void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
public:
static void registerMediaEngine(MediaEngineRegistrar);
+ gboolean handleMessage(GstMessage*);
IntSize naturalSize() const;
bool hasVideo() const { return m_hasVideo; }
@@ -72,7 +57,6 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
void load(const String &url);
void commitLoad();
void cancelLoad();
- bool loadNextLocation();
void prepareToPlay();
void play();
@@ -96,7 +80,6 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
void muteChanged();
void notifyPlayerOfMute();
- bool loadDelayed() const { return m_delayingLoad; }
void setPreload(MediaPlayer::Preload);
void fillTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
@@ -111,7 +94,6 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
void setVisible(bool);
void setSize(const IntSize&);
- void mediaLocationChanged(GstMessage*);
void loadStateChanged();
void sizeChanged();
void timeChanged();
@@ -119,6 +101,7 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
void durationChanged();
void loadingFailed(MediaPlayer::NetworkState);
+ void triggerRepaint(GstBuffer*);
void repaint();
void paint(GraphicsContext*, const IntRect&);
@@ -127,13 +110,17 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
bool supportsFullscreen() const;
PlatformMedia platformMedia() const;
- GstElement* pipeline() const { return m_playBin; }
- bool pipelineReset() const { return m_resetPipeline; }
+ void videoChanged();
+ void audioChanged();
+ void notifyPlayerOfVideo();
+ void notifyPlayerOfAudio();
+
+ void sourceChanged();
- void videoTagsChanged(gint);
- void audioTagsChanged(gint);
- void notifyPlayerOfVideoTags();
- void notifyPlayerOfAudioTags();
+ unsigned decodedFrameCount() const;
+ unsigned droppedFrameCount() const;
+ unsigned audioDecodedByteCount() const;
+ unsigned videoDecodedByteCount() const;
private:
MediaPlayerPrivateGStreamer(MediaPlayer*);
@@ -145,6 +132,10 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
static bool isAvailable();
+ void updateAudioSink();
+
+ float playbackPosition() const;
+
void cacheDuration();
void updateStates();
float maxTimeLoaded() const;
@@ -152,7 +143,10 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
void createGSTPlayBin();
bool changePipelineState(GstState state);
- void processBufferingStats(GstMessage* message);
+ bool loadNextLocation();
+ void mediaLocationChanged(GstMessage*);
+
+ void processBufferingStats(GstMessage*);
private:
MediaPlayer* m_player;
@@ -191,8 +185,9 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
guint m_muteTimerHandler;
bool m_hasVideo;
bool m_hasAudio;
- guint m_audioTagsTimerHandler;
- guint m_videoTagsTimerHandler;
+ guint m_audioTimerHandler;
+ guint m_videoTimerHandler;
+ GstElement* m_webkitAudioSink;
};
}
diff --git a/Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowPrivate.h b/Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowPrivate.h
index 0ae4587..7b441f4 100644
--- a/Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowPrivate.h
+++ b/Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowPrivate.h
@@ -20,21 +20,37 @@
#ifndef PlatformVideoWindowPrivate_h
#define PlatformVideoWindowPrivate_h
+#include <QTimer>
#include <QWidget>
class QKeyEvent;
namespace WebCore {
+class HTMLVideoElement;
+
class FullScreenVideoWindow: public QWidget {
Q_OBJECT
public:
FullScreenVideoWindow();
+ void setVideoElement(HTMLVideoElement*);
signals:
void closed();
protected:
- void keyPressEvent(QKeyEvent* ev);
- bool event(QEvent* ev);
+ void closeEvent(QCloseEvent*);
+ void keyPressEvent(QKeyEvent*);
+ bool event(QEvent*);
+
+public slots:
+ void showFullScreen();
+
+private slots:
+ void hideCursor();
+
+private:
+ void showCursor();
+ QTimer m_cursorTimer;
+ HTMLVideoElement* m_mediaElement;
};
diff --git a/Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowQt.cpp b/Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowQt.cpp
index 872d055..7270785 100644
--- a/Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowQt.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/PlatformVideoWindowQt.cpp
@@ -20,6 +20,7 @@
#include "config.h"
#include "PlatformVideoWindow.h"
+#include "HTMLVideoElement.h"
#include "PlatformVideoWindowPrivate.h"
#include <QApplication>
@@ -28,29 +29,55 @@
#include <QPalette>
using namespace WebCore;
+static const int gHideMouseCursorDelay = 3000;
+
FullScreenVideoWindow::FullScreenVideoWindow()
: QWidget(0, Qt::Window)
+ , m_mediaElement(0)
{
setAttribute(Qt::WA_NativeWindow);
- // Setting these values ensures smooth resizing since it
- // will prevent the system from clearing the background.
+ setWindowModality(Qt::ApplicationModal);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_PaintOnScreen, true);
+
+ m_cursorTimer.setSingleShot(true);
+ connect(&m_cursorTimer, SIGNAL(timeout()), this, SLOT(hideCursor()));
+}
+
+void FullScreenVideoWindow::setVideoElement(HTMLVideoElement* element)
+{
+ m_mediaElement = element;
+}
+
+void FullScreenVideoWindow::closeEvent(QCloseEvent*)
+{
+ m_cursorTimer.stop();
+ setMouseTracking(false);
+ releaseMouse();
+ QApplication::restoreOverrideCursor();
}
void FullScreenVideoWindow::keyPressEvent(QKeyEvent* ev)
{
- if (ev->key() == Qt::Key_Escape) {
- close();
+ if (m_mediaElement && ev->key() == Qt::Key_Space) {
+ if (!m_mediaElement->paused())
+ m_mediaElement->pause(true);
+ else
+ m_mediaElement->play(true);
+ } else if (ev->key() == Qt::Key_Escape)
emit closed();
- }
+ QWidget::keyPressEvent(ev);
}
bool FullScreenVideoWindow::event(QEvent* ev)
{
switch (ev->type()) {
+ case QEvent::MouseMove:
+ showCursor();
+ ev->accept();
+ return true;
case QEvent::MouseButtonDblClick:
- close();
+ emit closed();
ev->accept();
return true;
default:
@@ -58,6 +85,26 @@ bool FullScreenVideoWindow::event(QEvent* ev)
}
}
+void FullScreenVideoWindow::showFullScreen()
+{
+ QWidget::showFullScreen();
+ setMouseTracking(true);
+ raise();
+ setFocus();
+ hideCursor();
+}
+
+void FullScreenVideoWindow::hideCursor()
+{
+ QApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
+}
+
+void FullScreenVideoWindow::showCursor()
+{
+ QApplication::restoreOverrideCursor();
+ m_cursorTimer.start(gHideMouseCursorDelay);
+}
+
PlatformVideoWindow::PlatformVideoWindow()
{
diff --git a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
index 66ea9ba..e48998f 100644
--- a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
@@ -791,7 +791,7 @@ void StreamingClient::didReceiveResponse(ResourceHandle*, const ResourceResponse
gst_element_found_tags_for_pad(GST_ELEMENT(m_src), m_src->priv->srcpad, tags);
}
-void StreamingClient::didReceiveData(ResourceHandle* handle, const char* data, int length, int lengthReceived)
+void StreamingClient::didReceiveData(ResourceHandle* handle, const char* data, int length, int encodedDataLength)
{
WebKitWebSrcPrivate* priv = m_src->priv;
diff --git a/Source/WebCore/platform/graphics/gtk/DrawingBufferGtk.cpp b/Source/WebCore/platform/graphics/gtk/DrawingBufferGtk.cpp
new file mode 100644
index 0000000..17fc334
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gtk/DrawingBufferGtk.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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 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"
+
+#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL)
+
+#include "DrawingBuffer.h"
+
+#include "Extensions3D.h"
+
+namespace WebCore {
+
+DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
+ const IntSize& size,
+ bool multisampleExtensionSupported,
+ bool packedDepthStencilExtensionSupported)
+ : m_context(context)
+ , m_size(-1, -1)
+ , m_multisampleExtensionSupported(multisampleExtensionSupported)
+ , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
+ , m_fbo(context->createFramebuffer())
+ , m_colorBuffer(0)
+ , m_depthStencilBuffer(0)
+ , m_multisampleFBO(0)
+ , m_multisampleColorBuffer(0)
+{
+ ASSERT(m_fbo);
+ if (!m_fbo) {
+ clear();
+ return;
+ }
+
+ // create a texture to render into
+ m_colorBuffer = context->createTexture();
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer);
+ context->texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
+ context->texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
+
+ // Create the FBO
+ m_fbo = context->createFramebuffer();
+ ASSERT(m_fbo);
+ if (!m_fbo) {
+ clear();
+ return;
+ }
+
+ createSecondaryBuffers();
+ reset(size);
+}
+
+DrawingBuffer::~DrawingBuffer()
+{
+ clear();
+}
+
+void DrawingBuffer::didReset()
+{
+}
+
+Platform3DObject DrawingBuffer::platformColorBuffer() const
+{
+ return m_colorBuffer;
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/gtk/FontGtk.cpp b/Source/WebCore/platform/graphics/gtk/FontGtk.cpp
index d14b052..977aa62 100644
--- a/Source/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/Source/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -35,9 +35,10 @@
#include "CairoUtilities.h"
#include "ContextShadow.h"
-#include "PlatformContextCairo.h"
+#include "GOwnPtr.h"
#include "GraphicsContext.h"
#include "NotImplemented.h"
+#include "PlatformContextCairo.h"
#include "SimpleFontData.h"
#include "TextRun.h"
#include <cairo.h>
@@ -84,75 +85,71 @@ IntRect getPangoRegionExtents(PangoRegionType region)
#define IS_HIGH_SURROGATE(u) ((UChar)(u) >= (UChar)0xd800 && (UChar)(u) <= (UChar)0xdbff)
#define IS_LOW_SURROGATE(u) ((UChar)(u) >= (UChar)0xdc00 && (UChar)(u) <= (UChar)0xdfff)
-static void utf16_to_utf8(const UChar* aText, gint aLength, char* &text, gint &length)
+static gchar* utf16ToUtf8(const UChar* aText, gint aLength, gint &length)
{
- gboolean need_copy = FALSE;
- int i;
+ gboolean needCopy = FALSE;
- for (i = 0; i < aLength; i++) {
- if (!aText[i] || IS_LOW_SURROGATE(aText[i])) {
- need_copy = TRUE;
- break;
- }
- else if (IS_HIGH_SURROGATE(aText[i])) {
- if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1]))
- i++;
- else {
- need_copy = TRUE;
- break;
- }
+ for (int i = 0; i < aLength; i++) {
+ if (!aText[i] || IS_LOW_SURROGATE(aText[i])) {
+ needCopy = TRUE;
+ break;
+ }
+
+ if (IS_HIGH_SURROGATE(aText[i])) {
+ if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1]))
+ i++;
+ else {
+ needCopy = TRUE;
+ break;
+ }
+ }
}
- }
-
- if (need_copy) {
- /* Pango doesn't correctly handle nuls. We convert them to 0xff. */
- /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */
-
- UChar* p = (UChar*)g_memdup(aText, aLength * sizeof(aText[0]));
-
- /* don't need to reset i */
- for (i = 0; i < aLength; i++) {
- if (!p[i] || IS_LOW_SURROGATE(p[i]))
- p[i] = 0xFFFD;
- else if (IS_HIGH_SURROGATE(p[i])) {
- if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1]))
- i++;
- else
- p[i] = 0xFFFD;
- }
+ GOwnPtr<UChar> copiedString;
+ if (needCopy) {
+ /* Pango doesn't correctly handle nuls. We convert them to 0xff. */
+ /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */
+
+ copiedString.set(static_cast<UChar*>(g_memdup(aText, aLength * sizeof(aText[0]))));
+ UChar* p = copiedString.get();
+
+ /* don't need to reset i */
+ for (int i = 0; i < aLength; i++) {
+ if (!p[i] || IS_LOW_SURROGATE(p[i]))
+ p[i] = 0xFFFD;
+ else if (IS_HIGH_SURROGATE(p[i])) {
+ if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1]))
+ i++;
+ else
+ p[i] = 0xFFFD;
+ }
+ }
+
+ aText = p;
}
- aText = p;
- }
-
- glong items_written;
- text = g_utf16_to_utf8(reinterpret_cast<const gunichar2*>(aText), aLength, NULL, &items_written, NULL);
- length = items_written;
-
- if (need_copy)
- g_free((gpointer)aText);
+ gchar* utf8Text;
+ glong itemsWritten;
+ utf8Text = g_utf16_to_utf8(static_cast<const gunichar2*>(aText), aLength, 0, &itemsWritten, 0);
+ length = itemsWritten;
+ return utf8Text;
}
static gchar* convertUniCharToUTF8(const UChar* characters, gint length, int from, int to)
{
- gchar* utf8 = 0;
- gint new_length = 0;
- utf16_to_utf8(characters, length, utf8, new_length);
- if (!utf8)
- return NULL;
+ gint newLength = 0;
+ GOwnPtr<gchar> utf8Text(utf16ToUtf8(characters, length, newLength));
+ if (!utf8Text)
+ return 0;
+ gchar* pos = utf8Text.get();
if (from > 0) {
// discard the first 'from' characters
// FIXME: we should do this before the conversion probably
- gchar* str_left = g_utf8_offset_to_pointer(utf8, from);
- gchar* tmp = g_strdup(str_left);
- g_free(utf8);
- utf8 = tmp;
+ pos = g_utf8_offset_to_pointer(utf8Text.get(), from);
}
- gchar* pos = utf8;
gint len = strlen(pos);
GString* ret = g_string_new_len(NULL, len);
diff --git a/Source/WebCore/platform/graphics/gtk/GraphicsContext3DGtk.cpp b/Source/WebCore/platform/graphics/gtk/GraphicsContext3DGtk.cpp
new file mode 100644
index 0000000..8e03ad7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gtk/GraphicsContext3DGtk.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * 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 "GraphicsContext3D.h"
+
+#if ENABLE(WEBGL)
+
+#include "Extensions3DOpenGL.h"
+#include "GraphicsContext3DInternal.h"
+#include "OpenGLShims.h"
+#include "ShaderLang.h"
+#include <wtf/NotFound.h>
+
+namespace WebCore {
+
+PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle)
+{
+ // This implementation doesn't currently support rendering directly to the HostWindow.
+ if (renderStyle == RenderDirectlyToHostWindow)
+ return 0;
+
+ GraphicsContext3DInternal* internal = GraphicsContext3DInternal::create();
+ if (!internal)
+ return 0;
+
+ RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attributes, hostWindow, false));
+ context->m_internal.set(internal);
+ return context.release();
+}
+
+GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, HostWindow*, bool)
+ : m_currentWidth(0)
+ , m_currentHeight(0)
+ , m_attrs(attributes)
+ , m_texture(0)
+ , m_fbo(0)
+ , m_depthStencilBuffer(0)
+ , m_boundFBO(0)
+ , m_multisampleFBO(0)
+ , m_multisampleDepthStencilBuffer(0)
+ , m_multisampleColorBuffer(0)
+{
+ GraphicsContext3DInternal::addActiveGraphicsContext(this);
+
+ validateAttributes();
+
+ // Create a texture to render into.
+ ::glGenTextures(1, &m_texture);
+ ::glBindTexture(GL_TEXTURE_2D, m_texture);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+
+ // Create an FBO.
+ ::glGenFramebuffersEXT(1, &m_fbo);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+
+ m_boundFBO = m_fbo;
+ if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth))
+ ::glGenRenderbuffersEXT(1, &m_depthStencilBuffer);
+
+ // Create a multisample FBO.
+ if (m_attrs.antialias) {
+ ::glGenFramebuffersEXT(1, &m_multisampleFBO);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
+ m_boundFBO = m_multisampleFBO;
+ ::glGenRenderbuffersEXT(1, &m_multisampleColorBuffer);
+ if (m_attrs.stencil || m_attrs.depth)
+ ::glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer);
+ }
+
+ // ANGLE initialization.
+ ShBuiltInResources ANGLEResources;
+ ShInitBuiltInResources(&ANGLEResources);
+
+ getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs);
+ getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors);
+ getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors);
+ getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits);
+ getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits);
+ getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits);
+ getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors);
+
+ // Always set to 1 for OpenGL ES.
+ ANGLEResources.MaxDrawBuffers = 1;
+ m_compiler.setResources(ANGLEResources);
+
+ ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+ ::glEnable(GL_POINT_SPRITE);
+ ::glClearColor(0, 0, 0, 0);
+}
+
+GraphicsContext3D::~GraphicsContext3D()
+{
+ GraphicsContext3DInternal::removeActiveGraphicsContext(this);
+ if (!m_internal->m_context)
+ return;
+
+ makeContextCurrent();
+ ::glDeleteTextures(1, &m_texture);
+ if (m_attrs.antialias) {
+ ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer);
+ if (m_attrs.stencil || m_attrs.depth)
+ ::glDeleteRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer);
+ ::glDeleteFramebuffersEXT(1, &m_multisampleFBO);
+ } else {
+ if (m_attrs.stencil || m_attrs.depth)
+ ::glDeleteRenderbuffersEXT(1, &m_depthStencilBuffer);
+ }
+ ::glDeleteFramebuffersEXT(1, &m_fbo);
+}
+
+void GraphicsContext3D::makeContextCurrent()
+{
+ if (!m_internal)
+ return;
+ m_internal->makeContextCurrent();
+}
+
+PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D()
+{
+ return m_internal->m_context;
+}
+
+bool GraphicsContext3D::isGLES2Compliant() const
+{
+ return false;
+}
+
+}
+
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/gtk/GraphicsContext3DInternal.cpp b/Source/WebCore/platform/graphics/gtk/GraphicsContext3DInternal.cpp
new file mode 100644
index 0000000..de24554
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gtk/GraphicsContext3DInternal.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "GraphicsContext3DInternal.h"
+
+#if ENABLE(WEBGL)
+
+#include "GraphicsContext3D.h"
+#include "OpenGLShims.h"
+#include <GL/glx.h>
+#include <dlfcn.h>
+
+// We do not want to call glXMakeContextCurrent using different Display pointers,
+// because it might lead to crashes in some drivers (fglrx). We use a shared display
+// pointer here.
+static Display* gSharedDisplay = 0;
+static Display* sharedDisplay()
+{
+ if (!gSharedDisplay)
+ gSharedDisplay = XOpenDisplay(0);
+ return gSharedDisplay;
+}
+
+namespace WebCore {
+
+// Because of driver bugs, exiting the program when there are active pbuffers
+// can crash the X server (this has been observed with the official Nvidia drivers).
+// We need to ensure that we clean everything up on exit. There are several reasons
+// that GraphicsContext3Ds will still be alive at exit, including user error (memory
+// leaks) and the page cache. In any case, we don't want the X server to crash.
+static bool cleaningUpAtExit = false;
+static Vector<GraphicsContext3D*>& activeGraphicsContexts()
+{
+ DEFINE_STATIC_LOCAL(Vector<GraphicsContext3D*>, contexts, ());
+ return contexts;
+}
+
+void GraphicsContext3DInternal::addActiveGraphicsContext(GraphicsContext3D* context)
+{
+ static bool addedAtExitHandler = false;
+ if (!addedAtExitHandler) {
+ atexit(&GraphicsContext3DInternal::cleanupActiveContextsAtExit);
+ addedAtExitHandler = true;
+ }
+ activeGraphicsContexts().append(context);
+}
+
+void GraphicsContext3DInternal::removeActiveGraphicsContext(GraphicsContext3D* context)
+{
+ if (cleaningUpAtExit)
+ return;
+
+ Vector<GraphicsContext3D*>& contexts = activeGraphicsContexts();
+ size_t location = contexts.find(context);
+ if (location != WTF::notFound)
+ contexts.remove(location);
+}
+
+void GraphicsContext3DInternal::cleanupActiveContextsAtExit()
+{
+ cleaningUpAtExit = true;
+
+ Vector<GraphicsContext3D*>& contexts = activeGraphicsContexts();
+ for (size_t i = 0; i < contexts.size(); i++)
+ contexts[i]->~GraphicsContext3D();
+
+ if (!gSharedDisplay)
+ return;
+ XCloseDisplay(gSharedDisplay);
+ gSharedDisplay = 0;
+}
+
+GraphicsContext3DInternal* GraphicsContext3DInternal::create()
+{
+ if (!sharedDisplay())
+ return 0;
+
+ static bool initialized = false;
+ static bool success = true;
+ if (!initialized) {
+ success = initializeOpenGLShims();
+ initialized = true;
+ }
+ if (!success)
+ return 0;
+
+ GraphicsContext3DInternal* internal = createPbufferContext();
+ if (!internal)
+ internal = createPixmapContext();
+ if (!internal)
+ return 0;
+
+ // The GraphicsContext3D constructor requires that this context is the current OpenGL context.
+ internal->makeContextCurrent();
+ return internal;
+}
+
+GraphicsContext3DInternal* GraphicsContext3DInternal::createPbufferContext()
+{
+ int fbConfigAttributes[] = {
+ GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_ALPHA_SIZE, 1,
+ GLX_DEPTH_SIZE, 1,
+ GLX_STENCIL_SIZE, 1,
+ GLX_SAMPLE_BUFFERS, 1,
+ GLX_DOUBLEBUFFER, GL_FALSE,
+ GLX_SAMPLES, 4,
+ 0
+ };
+ int returnedElements;
+ GLXFBConfig* configs = glXChooseFBConfig(sharedDisplay(), 0, fbConfigAttributes, &returnedElements);
+ if (!configs) {
+ fbConfigAttributes[20] = 0; // Attempt without anti-aliasing.
+ configs = glXChooseFBConfig(sharedDisplay(), 0, fbConfigAttributes, &returnedElements);
+ }
+ if (!returnedElements) {
+ XFree(configs);
+ return 0;
+ }
+
+ // We will be rendering to a texture, so our pbuffer does not need to be large.
+ static const int pbufferAttributes[] = { GLX_PBUFFER_WIDTH, 1, GLX_PBUFFER_HEIGHT, 1, 0 };
+ GLXPbuffer pbuffer = glXCreatePbuffer(sharedDisplay(), configs[0], pbufferAttributes);
+ if (!pbuffer) {
+ XFree(configs);
+ return 0;
+ }
+
+ GLXContext context = glXCreateNewContext(sharedDisplay(), configs[0], GLX_RGBA_TYPE, 0, GL_TRUE);
+ XFree(configs);
+ if (!context)
+ return 0;
+ return new GraphicsContext3DInternal(context, pbuffer);
+}
+
+GraphicsContext3DInternal* GraphicsContext3DInternal::createPixmapContext()
+{
+ static int visualAttributes[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_ALPHA_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ 0
+ };
+
+ XVisualInfo* visualInfo = glXChooseVisual(sharedDisplay(), DefaultScreen(sharedDisplay()), visualAttributes);
+ if (!visualInfo)
+ return 0;
+
+ GLXContext context = glXCreateContext(sharedDisplay(), visualInfo, 0, GL_TRUE);
+ if (!context) {
+ XFree(visualInfo);
+ return 0;
+ }
+
+ Pixmap pixmap = XCreatePixmap(sharedDisplay(), DefaultRootWindow(sharedDisplay()), 1, 1, visualInfo->depth);
+ if (!pixmap) {
+ XFree(visualInfo);
+ return 0;
+ }
+
+ GLXPixmap glxPixmap = glXCreateGLXPixmap(sharedDisplay(), visualInfo, pixmap);
+ if (!glxPixmap) {
+ XFreePixmap(sharedDisplay(), pixmap);
+ XFree(visualInfo);
+ return 0;
+ }
+
+ return new GraphicsContext3DInternal(context, pixmap, glxPixmap);
+}
+
+GraphicsContext3DInternal::GraphicsContext3DInternal(GLXContext context, GLXPbuffer pbuffer)
+ : m_context(context)
+ , m_pbuffer(pbuffer)
+ , m_pixmap(0)
+ , m_glxPixmap(0)
+{
+}
+
+GraphicsContext3DInternal::GraphicsContext3DInternal(GLXContext context, Pixmap pixmap, GLXPixmap glxPixmap)
+ : m_context(context)
+ , m_pbuffer(0)
+ , m_pixmap(pixmap)
+ , m_glxPixmap(glxPixmap)
+{
+}
+
+GraphicsContext3DInternal::~GraphicsContext3DInternal()
+{
+ if (m_context) {
+ // This may be necessary to prevent crashes with NVidia's closed source drivers. Originally
+ // from Mozilla's 3D canvas implementation at: http://bitbucket.org/ilmari/canvas3d/
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ ::glXMakeContextCurrent(sharedDisplay(), 0, 0, 0);
+ ::glXDestroyContext(sharedDisplay(), m_context);
+ m_context = 0;
+ }
+
+ if (m_pbuffer) {
+ ::glXDestroyPbuffer(sharedDisplay(), m_pbuffer);
+ m_pbuffer = 0;
+ }
+ if (m_glxPixmap) {
+ glXDestroyGLXPixmap(sharedDisplay(), m_glxPixmap);
+ m_glxPixmap = 0;
+ }
+ if (m_pixmap) {
+ XFreePixmap(sharedDisplay(), m_pixmap);
+ m_pixmap = 0;
+ }
+}
+
+void GraphicsContext3DInternal::makeContextCurrent()
+{
+ if (::glXGetCurrentContext() == m_context)
+ return;
+ if (!m_context)
+ return;
+ if (m_pbuffer) {
+ ::glXMakeCurrent(sharedDisplay(), m_pbuffer, m_context);
+ return;
+ }
+
+ ASSERT(m_glxPixmap);
+ ::glXMakeCurrent(sharedDisplay(), m_glxPixmap, m_context);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE_WEBGL
diff --git a/Source/WebCore/platform/graphics/gtk/GraphicsContext3DInternal.h b/Source/WebCore/platform/graphics/gtk/GraphicsContext3DInternal.h
new file mode 100644
index 0000000..f4a60d9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/gtk/GraphicsContext3DInternal.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef GraphicsContext3DInternal_h
+#define GraphicsContext3DInternal_h
+
+typedef struct __GLXcontextRec *GLXContext;
+typedef unsigned long GLXPbuffer;
+typedef unsigned long GLXPixmap;
+typedef unsigned char GLubyte;
+typedef unsigned long Pixmap;
+
+namespace WebCore {
+
+class GraphicsContext3D;
+
+class GraphicsContext3DInternal {
+ public:
+ static GraphicsContext3DInternal* create();
+ ~GraphicsContext3DInternal();
+ void makeContextCurrent();
+
+ private:
+ friend class GraphicsContext3D;
+ static GraphicsContext3DInternal* createPbufferContext();
+ static GraphicsContext3DInternal* createPixmapContext();
+ GraphicsContext3DInternal(GLXContext, GLXPbuffer);
+ GraphicsContext3DInternal(GLXContext, Pixmap, GLXPixmap);
+
+ static void addActiveGraphicsContext(GraphicsContext3D*);
+ static void removeActiveGraphicsContext(GraphicsContext3D*);
+ static void cleanupActiveContextsAtExit();
+
+ GLXContext m_context;
+ GLXPbuffer m_pbuffer;
+ Pixmap m_pixmap;
+ GLXPixmap m_glxPixmap;
+};
+
+}
+
+#endif // GraphicsContext3DIternal_h
diff --git a/Source/WebCore/platform/graphics/haiku/ImageBufferData.h b/Source/WebCore/platform/graphics/haiku/ImageBufferDataHaiku.h
index 7c676cd..10285fc 100644
--- a/Source/WebCore/platform/graphics/haiku/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/haiku/ImageBufferDataHaiku.h
@@ -25,9 +25,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ImageBufferData_h
-#define ImageBufferData_h
-
#include <Bitmap.h>
#include <View.h>
@@ -45,6 +42,3 @@ public:
};
} // namespace WebCore
-
-#endif // ImageBufferData_h
-
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.h b/Source/WebCore/platform/graphics/mac/ComplexTextController.h
index 44a7994..281e49f 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextController.h
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.h
@@ -116,9 +116,6 @@ private:
static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef, URefCon, void*, ATSULayoutOperationCallbackStatus*);
#endif
-#if USE(CORE_TEXT)
- RetainPtr<CTRunRef> m_coreTextRun;
-#endif
unsigned m_glyphCount;
const SimpleFontData* m_fontData;
const UChar* m_characters;
@@ -159,6 +156,10 @@ private:
Vector<UChar, 256> m_smallCapsBuffer;
+#if USE(CORE_TEXT)
+ // Retain lines rather than their runs for better performance.
+ Vector<RetainPtr<CTLineRef> > m_coreTextLines;
+#endif
Vector<RefPtr<ComplexTextRun>, 16> m_complexTextRuns;
Vector<CGSize, 256> m_adjustedAdvances;
Vector<CGGlyph, 256> m_adjustedGlyphs;
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
index d2fbaf5..1473b1e 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
@@ -43,33 +43,32 @@ extern const CFStringRef kCTTypesetterOptionForcedEmbeddingLevel;
namespace WebCore {
ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange)
- : m_coreTextRun(ctRun)
- , m_fontData(fontData)
+ : m_fontData(fontData)
, m_characters(characters)
, m_stringLocation(stringLocation)
, m_stringLength(stringLength)
, m_indexEnd(runRange.location + runRange.length)
, m_isMonotonic(true)
{
- m_glyphCount = CTRunGetGlyphCount(m_coreTextRun.get());
- m_coreTextIndices = CTRunGetStringIndicesPtr(m_coreTextRun.get());
+ m_glyphCount = CTRunGetGlyphCount(ctRun);
+ m_coreTextIndices = CTRunGetStringIndicesPtr(ctRun);
if (!m_coreTextIndices) {
m_coreTextIndicesVector.grow(m_glyphCount);
- CTRunGetStringIndices(m_coreTextRun.get(), CFRangeMake(0, 0), m_coreTextIndicesVector.data());
+ CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), m_coreTextIndicesVector.data());
m_coreTextIndices = m_coreTextIndicesVector.data();
}
- m_glyphs = CTRunGetGlyphsPtr(m_coreTextRun.get());
+ m_glyphs = CTRunGetGlyphsPtr(ctRun);
if (!m_glyphs) {
m_glyphsVector.grow(m_glyphCount);
- CTRunGetGlyphs(m_coreTextRun.get(), CFRangeMake(0, 0), m_glyphsVector.data());
+ CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), m_glyphsVector.data());
m_glyphs = m_glyphsVector.data();
}
- m_advances = CTRunGetAdvancesPtr(m_coreTextRun.get());
+ m_advances = CTRunGetAdvancesPtr(ctRun);
if (!m_advances) {
m_advancesVector.grow(m_glyphCount);
- CTRunGetAdvances(m_coreTextRun.get(), CFRangeMake(0, 0), m_advancesVector.data());
+ CTRunGetAdvances(ctRun, CFRangeMake(0, 0), m_advancesVector.data());
m_advances = m_advancesVector.data();
}
}
@@ -159,6 +158,8 @@ void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UC
line.adoptCF(wkCreateCTLineWithUniCharProvider(&provideStringAndAttributes, 0, &info));
}
+ m_coreTextLines.append(line.get());
+
CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
CFIndex runCount = CFArrayGetCount(runArray);
diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
index 997c976..2a469a7 100644
--- a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
+++ b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
@@ -90,8 +90,8 @@ PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attri
GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, bool)
: m_currentWidth(0)
, m_currentHeight(0)
- , m_attrs(attrs)
, m_contextObj(0)
+ , m_attrs(attrs)
, m_texture(0)
, m_compositorTexture(0)
, m_fbo(0)
diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index cd34000..f34d53b 100644
--- a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -241,6 +241,7 @@ void SimpleFontData::platformInit()
NSString *familyName = [m_platformData.font() familyName];
if ([familyName isEqualToString:@"Times"] || [familyName isEqualToString:@"Helvetica"] || [familyName isEqualToString:@"Courier"])
ascent += floorf(((ascent + descent) * 0.15f) + 0.5f);
+#if defined(BUILDING_ON_LEOPARD)
else if ([familyName isEqualToString:@"Geeza Pro"]) {
// Geeza Pro has glyphs that draw slightly above the ascent or far below the descent. Adjust
// those vertical metrics to better match reality, so that diacritics at the bottom of one line
@@ -248,6 +249,7 @@ void SimpleFontData::platformInit()
ascent *= 1.08f;
descent *= 2.f;
}
+#endif
// Compute and store line spacing, before the line metrics hacks are applied.
m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp
index e09534e..4c7164e 100644
--- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp
@@ -35,6 +35,8 @@
#if PLATFORM(MAC)
#include "ANGLE/ShaderLang.h"
#include <OpenGL/gl.h>
+#elif PLATFORM(GTK)
+#include "OpenGLShims.h"
#endif
namespace WebCore {
@@ -116,6 +118,17 @@ void Extensions3DOpenGL::ensureEnabled(const String& name)
#endif
}
+bool Extensions3DOpenGL::isEnabled(const String& name)
+{
+#if PLATFORM(MAC)
+ if (name == "GL_OES_standard_derivatives") {
+ ANGLEWebKitBridge& compiler = m_context->m_compiler;
+ return compiler.getResources().OES_standard_derivatives;
+ }
+#endif
+ return supports(name);
+}
+
int Extensions3DOpenGL::getGraphicsResetStatusARB()
{
return GraphicsContext3D::NO_ERROR;
@@ -134,7 +147,7 @@ void Extensions3DOpenGL::renderbufferStorageMultisample(unsigned long target, un
Platform3DObject Extensions3DOpenGL::createVertexArrayOES()
{
m_context->makeContextCurrent();
-#if defined GL_APPLE_vertex_array_object && GL_APPLE_vertex_array_object
+#if !PLATFORM(GTK) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object
GLuint array = 0;
glGenVertexArraysAPPLE(1, &array);
return array;
@@ -149,7 +162,7 @@ void Extensions3DOpenGL::deleteVertexArrayOES(Platform3DObject array)
return;
m_context->makeContextCurrent();
-#if defined GL_APPLE_vertex_array_object && GL_APPLE_vertex_array_object
+#if !PLATFORM(GTK) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object
glDeleteVertexArraysAPPLE(1, &array);
#endif
}
@@ -160,7 +173,7 @@ GC3Dboolean Extensions3DOpenGL::isVertexArrayOES(Platform3DObject array)
return GL_FALSE;
m_context->makeContextCurrent();
-#if defined GL_APPLE_vertex_array_object && GL_APPLE_vertex_array_object
+#if !PLATFORM(GTK) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object
return glIsVertexArrayAPPLE(array);
#else
return GL_FALSE;
@@ -173,7 +186,7 @@ void Extensions3DOpenGL::bindVertexArrayOES(Platform3DObject array)
return;
m_context->makeContextCurrent();
-#if defined GL_APPLE_vertex_array_object && GL_APPLE_vertex_array_object
+#if !PLATFORM(GTK) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object
glBindVertexArrayAPPLE(array);
#endif
}
diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h
index 9188507..e545fbc 100644
--- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h
+++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h
@@ -41,6 +41,7 @@ public:
// Extensions3D methods.
virtual bool supports(const String&);
virtual void ensureEnabled(const String&);
+ virtual bool isEnabled(const String&);
virtual int getGraphicsResetStatusARB();
virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter);
virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height);
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
index f831550..af46293 100644
--- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
@@ -42,14 +42,16 @@
#include "Int32Array.h"
#include "NotImplemented.h"
#include "Uint8Array.h"
+#include <cstring>
+#include <wtf/UnusedParam.h>
+#include <wtf/text/CString.h>
#if PLATFORM(MAC)
#include <OpenGL/gl.h>
+#elif PLATFORM(GTK)
+#include "OpenGLShims.h"
#endif
-#include <wtf/UnusedParam.h>
-#include <wtf/text/CString.h>
-
namespace WebCore {
void GraphicsContext3D::validateAttributes()
@@ -163,7 +165,7 @@ PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData()
void GraphicsContext3D::reshape(int width, int height)
{
- if (!m_contextObj)
+ if (!platformGraphicsContext3D())
return;
if (width == m_currentWidth && height == m_currentHeight)
diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
index 9765937..1493966 100644
--- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
+++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
@@ -388,7 +388,7 @@ void TextureMapperGL::drawTexture(const BitmapTexture& texture, const IntRect& t
GL_CMD(glBindTexture(GL_TEXTURE_2D, textureGL.m_id))
GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0))
const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
- GL_CMD(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, unitRect))
+ GL_CMD(glVertexAttribPointer(gInVertexAttributeIndex, 2, GL_FLOAT, GL_FALSE, 0, unitRect))
TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix(
targetRect.width(), 0, 0, 0,
@@ -641,7 +641,7 @@ void TextureMapperGL::paintToTarget(const BitmapTexture& aSurface, const IntSize
GL_CMD(glUniformMatrix4fv(programInfo.vars[TextureMapperGLData::ShaderInfo::InSourceMatrixVariable], 1, GL_FALSE, m4src))
GL_CMD(glBindBuffer(GL_ARRAY_BUFFER, 0))
const GLfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
- GL_CMD(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, unitRect))
+ GL_CMD(glVertexAttribPointer(gInVertexAttributeIndex, 2, GL_FLOAT, GL_FALSE, 0, unitRect))
GL_CMD(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA))
GL_CMD(glEnable(GL_BLEND))
setClip(visibleRect);
diff --git a/Source/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp b/Source/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
index 7f4547d..6afe3d9 100644
--- a/Source/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
+++ b/Source/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
@@ -70,7 +70,7 @@ struct TableDirectoryEntry {
BigEndianULong length;
};
-#if !PLATFORM(CG) || !defined(COREGRAPHICS_INCLUDES_CORESERVICES_HEADER)
+#if !USE(CG) || !defined(COREGRAPHICS_INCLUDES_CORESERVICES_HEADER)
// Fixed type is not defined on non-CG and Windows platforms. |version| in sfntHeader
// and headTable and |fontRevision| in headTable are of Fixed, but they're
// not actually refered to anywhere. Therefore, we just have to match
diff --git a/Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
index 75dbadb..1595692 100644
--- a/Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
+++ b/Source/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
@@ -257,7 +257,7 @@ void GraphicsContext::drawLineForTextChecking(const IntPoint& origin, int width,
UNUSED_PARAM(style);
}
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode)
{
if (paintingDisabled())
return FloatRect();
diff --git a/Source/WebCore/platform/graphics/pango/FontPlatformData.h b/Source/WebCore/platform/graphics/pango/FontPlatformData.h
index 180d23b..bd9251b 100644
--- a/Source/WebCore/platform/graphics/pango/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/pango/FontPlatformData.h
@@ -68,6 +68,7 @@ public:
bool syntheticOblique() const { return m_syntheticOblique; }
FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+ void setOrientation(FontOrientation) { } // FIXME: Implement.
cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
diff --git a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp b/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp
index 3adc93f..45d5e9c 100644
--- a/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/Extensions3DQt.cpp
@@ -52,6 +52,11 @@ void Extensions3DQt::ensureEnabled(const String& name)
ASSERT(supports(name));
}
+bool Extensions3DQt::isEnabled(const String& name)
+{
+ return supports(name);
+}
+
int Extensions3DQt::getGraphicsResetStatusARB()
{
return GraphicsContext3D::NO_ERROR;
diff --git a/Source/WebCore/platform/graphics/qt/Extensions3DQt.h b/Source/WebCore/platform/graphics/qt/Extensions3DQt.h
index c67fbed..1bc47b8 100644
--- a/Source/WebCore/platform/graphics/qt/Extensions3DQt.h
+++ b/Source/WebCore/platform/graphics/qt/Extensions3DQt.h
@@ -37,6 +37,7 @@ public:
// Extensions3D methods.
virtual bool supports(const String&);
virtual void ensureEnabled(const String&);
+ virtual bool isEnabled(const String&);
virtual int getGraphicsResetStatusARB();
virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter);
virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height);
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index 4daa4dc..e92f927 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -447,6 +447,12 @@ GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attribut
GraphicsContext3DInternal::~GraphicsContext3DInternal()
{
+ m_glWidget->makeCurrent();
+ if (m_glWidget->isValid()) {
+ ::glDeleteTextures(1, &m_texture);
+ deleteRenderbuffers(1, &m_depthBuffer);
+ deleteFramebuffers(1, &m_canvasFbo);
+ }
delete m_glWidget;
m_glWidget = 0;
}
@@ -588,7 +594,7 @@ void* GraphicsContext3DInternal::getProcAddress(const String& proc)
for (int i = 0; i < 3; i++) {
String nameWithExt = proc + ext[i];
- void* addr = m_glWidget->context()->getProcAddress(nameWithExt.utf8().data());
+ void* addr = m_glWidget->context()->getProcAddress(QString(nameWithExt));
if (addr)
return addr;
}
@@ -656,7 +662,7 @@ PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData()
void GraphicsContext3D::reshape(int width, int height)
{
- if (width == m_currentWidth && height == m_currentHeight || (!m_internal))
+ if ((width == m_currentWidth && height == m_currentHeight) || (!m_internal))
return;
m_currentWidth = width;
diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index e3e0fa6..a3a08eb 100644
--- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -900,7 +900,7 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint&, float, TextChec
notImplemented();
}
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect, RoundingMode)
{
// It is not enough just to round to pixels in device space. The rotation part of the
// affine transform matrix to device space can mess with this conversion if we have a
diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferData.h b/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h
index 602197e..8b49829 100644
--- a/Source/WebCore/platform/graphics/qt/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h
@@ -23,16 +23,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ImageBufferData_h
-#define ImageBufferData_h
-
#include "Image.h"
-#include <wtf/RefPtr.h>
+#include "OwnPtr.h"
#include <QPainter>
#include <QPixmap>
-
-#include "OwnPtr.h"
+#include <wtf/RefPtr.h>
namespace WebCore {
@@ -49,6 +45,4 @@ public:
RefPtr<Image> m_image;
};
-} // namespace WebCore
-
-#endif // ImageBufferData_h
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
index bc43acf..e7efdf9 100644
--- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
@@ -84,7 +84,17 @@ MediaPlayer::SupportsType MediaPlayerPrivateQt::supportsType(const String& mime,
if (!mime.startsWith("audio/") && !mime.startsWith("video/"))
return MediaPlayer::IsNotSupported;
- if (QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMultimediaKit::ProbablySupported)
+ // Parse and trim codecs.
+ QString codecStr = codec;
+ QStringList codecList = codecStr.split(QLatin1Char(','), QString::SkipEmptyParts);
+ QStringList codecListTrimmed;
+ foreach (const QString& codecStrNotTrimmed, codecList) {
+ QString codecStrTrimmed = codecStrNotTrimmed.trimmed();
+ if (!codecStrTrimmed.isEmpty())
+ codecListTrimmed.append(codecStrTrimmed);
+ }
+
+ if (QMediaPlayer::hasSupport(mime, codecListTrimmed) >= QtMultimediaKit::ProbablySupported)
return MediaPlayer::IsSupported;
return MediaPlayer::MayBeSupported;
diff --git a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
index 5d0b302..9bf1030 100644
--- a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
+++ b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2008, 2009, 2010, 2011 Nokia Corporation and/or its subsidiary(-ies)
Copyright (C) 2008 Holger Hans Peter Freyther
This library is free software; you can redistribute it and/or
@@ -48,11 +48,29 @@ void SimpleFontData::platformInit()
}
QFontMetricsF fm(m_platformData.font());
- m_fontMetrics.setAscent(fm.ascent());
- m_fontMetrics.setDescent(fm.descent());
+
+ // Qt subtracts 1 from the descent to account for the baseline,
+ // we add it back here to get correct metrics for WebKit.
+ float descent = fm.descent() + 1;
+ float ascent = fm.ascent();
+
+ float lineSpacing = fm.lineSpacing();
+
+ // The line spacing should always be >= (ascent + descent), but this
+ // may be false in some cases due to misbehaving platform libraries.
+ // Workaround from SimpleFontPango.cpp and SimpleFontFreeType.cpp
+ if (lineSpacing < ascent + descent)
+ lineSpacing = ascent + descent;
+
+ // QFontMetricsF::leading() may return negative values on platforms
+ // such as FreeType. Calculate the line gap manually instead.
+ float lineGap = lineSpacing - ascent - descent;
+
+ m_fontMetrics.setAscent(ascent);
+ m_fontMetrics.setDescent(descent);
+ m_fontMetrics.setLineSpacing(lineSpacing);
m_fontMetrics.setXHeight(fm.xHeight());
- m_fontMetrics.setLineGap(fm.leading());
- m_fontMetrics.setLineSpacing(fm.lineSpacing());
+ m_fontMetrics.setLineGap(lineGap);
m_spaceWidth = fm.width(QLatin1Char(' '));
}
diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
index 5950c35..0fb44e7 100644
--- a/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
@@ -30,6 +30,7 @@
#include "GraphicsContext3D.h"
+#include "BitmapImage.h"
#include "Image.h"
#include "ImageSource.h"
#include "NativeImageSkia.h"
@@ -50,15 +51,17 @@ bool GraphicsContext3D::getImageData(Image* image,
if (!image)
return false;
OwnPtr<NativeImageSkia> pixels;
- NativeImageSkia* skiaImage = 0;
+ NativeImageSkia* skiaImage = image->nativeImageForCurrentFrame();
AlphaOp neededAlphaOp = AlphaDoNothing;
- if (image->data()) {
+ bool hasAlpha = skiaImage ? !skiaImage->isOpaque() : true;
+ if ((!skiaImage || ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && image->data()) {
ImageSource decoder(ImageSource::AlphaNotPremultiplied,
ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
+ // Attempt to get raw unpremultiplied image data
decoder.setData(image->data(), true);
if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
return false;
- bool hasAlpha = decoder.frameHasAlphaAtIndex(0);
+ hasAlpha = decoder.frameHasAlphaAtIndex(0);
pixels = adoptPtr(decoder.createFrameAtIndex(0));
if (!pixels.get() || !pixels->isDataComplete() || !pixels->width() || !pixels->height())
return false;
@@ -68,12 +71,8 @@ bool GraphicsContext3D::getImageData(Image* image,
skiaImage = pixels.get();
if (hasAlpha && premultiplyAlpha)
neededAlphaOp = AlphaDoPremultiply;
- } else {
- // This is a special case for texImage2D with HTMLCanvasElement input.
- skiaImage = image->nativeImageForCurrentFrame();
- if (!premultiplyAlpha)
- neededAlphaOp = AlphaDoUnmultiply;
- }
+ } else if (!premultiplyAlpha && hasAlpha)
+ neededAlphaOp = AlphaDoUnmultiply;
if (!skiaImage)
return false;
SkBitmap& skiaImageRef = *skiaImage;
diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index df680eb..f285c9b 100644
--- a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -44,8 +44,10 @@
#include "PlatformContextSkia.h"
#include "SkBitmap.h"
-#include "SkBlurDrawLooper.h"
+#include "SkBlurMaskFilter.h"
+#include "SkColorFilter.h"
#include "SkCornerPathEffect.h"
+#include "SkLayerDrawLooper.h"
#include "SkShader.h"
#include "SkiaUtils.h"
#include "skia/ext/platform_canvas.h"
@@ -853,6 +855,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect,
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
+ paint.setColor(color.rgb());
platformContext()->canvas()->drawPath(path, paint);
}
@@ -867,7 +870,7 @@ AffineTransform GraphicsContext::getCTM() const
SkScalarToDouble(m.getTranslateY()));
}
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode)
{
return rect;
}
@@ -1043,16 +1046,15 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size,
double height = size.height();
double blur = blurFloat;
- uint32_t blurFlags = SkBlurDrawLooper::kHighQuality_BlurFlag |
- SkBlurDrawLooper::kOverrideColor_BlurFlag;
+ uint32_t mfFlags = SkBlurMaskFilter::kHighQuality_BlurFlag;
if (m_state.shadowsIgnoreTransforms) {
// Currently only the GraphicsContext associated with the
// CanvasRenderingContext for HTMLCanvasElement have shadows ignore
// Transforms. So with this flag set, we know this state is associated
// with a CanvasRenderingContext.
- blurFlags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
-
+ mfFlags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
+
// CG uses natural orientation for Y axis, but the HTML5 canvas spec
// does not.
// So we now flip the height since it was flipped in
@@ -1068,9 +1070,32 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size,
// TODO(tc): Should we have a max value for the blur? CG clamps at 1000.0
// for perf reasons.
- SkDrawLooper* dl = new SkBlurDrawLooper(blur / 2, width, height, c, blurFlags);
+
+ SkLayerDrawLooper* dl = new SkLayerDrawLooper;
+ SkAutoUnref aur(dl);
+
+ // top layer, we just draw unchanged
+ dl->addLayer();
+
+ // lower layer contains our offset, blur, and colorfilter
+ SkLayerDrawLooper::LayerInfo info;
+
+ info.fPaintBits |= SkLayerDrawLooper::kMaskFilter_Bit; // our blur
+ info.fPaintBits |= SkLayerDrawLooper::kColorFilter_Bit;
+ info.fColorMode = SkXfermode::kDst_Mode;
+ info.fOffset.set(width, height);
+ info.fPostTranslate = m_state.shadowsIgnoreTransforms;
+
+ SkMaskFilter* mf = SkBlurMaskFilter::Create(blur / 2, SkBlurMaskFilter::kNormal_BlurStyle, mfFlags);
+
+ SkColorFilter* cf = SkColorFilter::CreateModeFilter(c, SkXfermode::kSrcIn_Mode);
+
+ SkPaint* paint = dl->addLayer(info);
+ SkSafeUnref(paint->setMaskFilter(mf));
+ SkSafeUnref(paint->setColorFilter(cf));
+
+ // dl is now built, just install it
platformContext()->setDrawLooper(dl);
- dl->unref();
}
void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor, ColorSpace colorSpace)
diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index b89c68d..2352672 100644
--- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -66,19 +66,21 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& s
: m_data(size)
, m_size(size)
{
- if (!m_data.m_canvas.initialize(size.width(), size.height(), false)) {
+ SkCanvas* canvas = skia::CreateBitmapCanvas(size.width(), size.height(), false);
+ if (!canvas) {
success = false;
return;
}
- m_data.m_platformContext.setCanvas(&m_data.m_canvas);
+ m_data.m_canvas = canvas;
+ m_data.m_platformContext.setCanvas(m_data.m_canvas.get());
m_context.set(new GraphicsContext(&m_data.m_platformContext));
m_context->platformContext()->setDrawingToImageBuffer(true);
// Make the background transparent. It would be nice if this wasn't
// required, but the canvas is currently filled with the magic transparency
// color. Can we have another way to manage this?
- m_data.m_canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
+ m_data.m_canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
success = true;
}
@@ -117,6 +119,7 @@ void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, con
{
if (m_data.m_platformContext.useGPU() && context->platformContext()->useGPU()) {
if (context->platformContext()->canAccelerate()) {
+ m_data.m_platformContext.prepareForHardwareDraw();
DrawingBuffer* sourceDrawingBuffer = m_data.m_platformContext.gpuCanvas()->drawingBuffer();
unsigned sourceTexture = static_cast<unsigned>(sourceDrawingBuffer->platformColorBuffer());
FloatRect destRectNormalized(normalizeRect(destRect));
@@ -344,6 +347,8 @@ void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& so
template <typename T>
static String ImageToDataURL(T& source, const String& mimeType, const double* quality)
{
+ ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+
Vector<unsigned char> encodedImage;
if (mimeType == "image/jpeg") {
int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality;
@@ -365,9 +370,6 @@ static String ImageToDataURL(T& source, const String& mimeType, const double* qu
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
{
- ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
-
- Vector<unsigned char> encodedImage;
SkDevice* device = context()->platformContext()->canvas()->getDevice();
SkBitmap bitmap = device->accessBitmap(false);
diff --git a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
index 72bec29..6987e00 100644
--- a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -66,6 +66,7 @@ enum ResamplingMode {
RESAMPLE_AWESOME,
};
+#if !ENABLE(SKIA_GPU)
static ResamplingMode computeResamplingMode(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight)
{
if (platformContext->hasImageResamplingHint()) {
@@ -150,6 +151,7 @@ static ResamplingMode computeResamplingMode(PlatformContextSkia* platformContext
return RESAMPLE_LINEAR;
}
+#endif
// Draws the given bitmap to the given canvas. The subset of the source bitmap
// identified by src_rect is drawn to the given destination rect. The bitmap
@@ -262,12 +264,17 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag
paint.setAlpha(platformContext->getNormalizedAlpha());
paint.setLooper(platformContext->getDrawLooper());
- skia::PlatformCanvas* canvas = platformContext->canvas();
+ SkCanvas* canvas = platformContext->canvas();
- ResamplingMode resampling = platformContext->isPrinting() ? RESAMPLE_NONE :
+ ResamplingMode resampling;
+#if ENABLE(SKIA_GPU)
+ resampling = RESAMPLE_LINEAR;
+#else
+ resampling = platformContext->printing() ? RESAMPLE_NONE :
computeResamplingMode(platformContext, bitmap, srcRect.width(), srcRect.height(),
SkScalarToFloat(destRect.width()),
SkScalarToFloat(destRect.height()));
+#endif
if (resampling == RESAMPLE_AWESOME) {
drawResampledBitmap(*canvas, paint, bitmap, srcRect, destRect);
} else {
@@ -363,13 +370,17 @@ void Image::drawPattern(GraphicsContext* context,
// Compute the resampling mode.
ResamplingMode resampling;
- if (context->platformContext()->isPrinting())
+#if ENABLE(SKIA_GPU)
+ resampling = RESAMPLE_LINEAR;
+#else
+ if (context->platformContext()->printing())
resampling = RESAMPLE_LINEAR;
else {
resampling = computeResamplingMode(context->platformContext(), *bitmap,
srcRect.width(), srcRect.height(),
destBitmapWidth, destBitmapHeight);
}
+#endif
// Load the transform WebKit requested.
SkMatrix matrix(patternTransform);
diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index 8e1937f..4cc5457 100644
--- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -213,8 +213,9 @@ SkColor PlatformContextSkia::State::applyAlpha(SkColor c) const
// PlatformContextSkia ---------------------------------------------------------
// Danger: canvas can be NULL.
-PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas)
+PlatformContextSkia::PlatformContextSkia(SkCanvas* canvas)
: m_canvas(canvas)
+ , m_printing(false)
, m_drawingToImageBuffer(false)
, m_useGPU(false)
#if ENABLE(ACCELERATED_2D_CANVAS)
@@ -232,15 +233,18 @@ PlatformContextSkia::~PlatformContextSkia()
if (m_gpuCanvas) {
#if ENABLE(SKIA_GPU)
// make sure everything related to this platform context has been flushed
- if (!m_useGPU)
- m_gpuCanvas->context()->grContext()->flush(0);
+ if (!m_useGPU) {
+ SharedGraphicsContext3D* context = m_gpuCanvas->context();
+ context->makeContextCurrent();
+ context->grContext()->flush(0);
+ }
#endif
m_gpuCanvas->drawingBuffer()->setWillPublishCallback(0);
}
#endif
}
-void PlatformContextSkia::setCanvas(skia::PlatformCanvas* canvas)
+void PlatformContextSkia::setCanvas(SkCanvas* canvas)
{
m_canvas = canvas;
}
@@ -609,12 +613,12 @@ const SkBitmap* PlatformContextSkia::bitmap() const
return &m_canvas->getDevice()->accessBitmap(false);
}
-bool PlatformContextSkia::isPrinting()
+bool PlatformContextSkia::isNativeFontRenderingAllowed()
{
#if ENABLE(SKIA_GPU)
- return true;
+ return false;
#else
- return m_canvas->getTopPlatformDevice().IsVectorial();
+ return skia::SupportsPlatformPaint(m_canvas);
#endif
}
@@ -738,7 +742,12 @@ void PlatformContextSkia::setSharedGraphicsContext3D(SharedGraphicsContext3D* co
gr->resetContext();
drawingBuffer->setGrContext(gr);
- SkDeviceFactory* factory = new SkGpuDeviceFactory(gr, SkGpuDevice::Current3DApiRenderTarget());
+ GrPlatformSurfaceDesc drawBufDesc;
+ drawingBuffer->getGrPlatformSurfaceDesc(&drawBufDesc);
+ GrTexture* drawBufTex = static_cast<GrTexture*>(gr->createPlatformSurface(drawBufDesc));
+ SkDeviceFactory* factory = new SkGpuDeviceFactory(gr, drawBufTex);
+ drawBufTex->unref();
+
SkDevice* device = factory->newDevice(m_canvas, SkBitmap::kARGB_8888_Config, drawingBuffer->size().width(), drawingBuffer->size().height(), false, false);
m_canvas->setDevice(device)->unref();
m_canvas->setDeviceFactory(factory);
diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
index d7dd6a9..fc82221 100644
--- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -72,12 +72,12 @@ class PlatformContextSkia {
public:
// For printing, there shouldn't be any canvas. canvas can be NULL. If you
// supply a NULL canvas, you can also call setCanvas later.
- PlatformContextSkia(skia::PlatformCanvas*);
+ PlatformContextSkia(SkCanvas*);
~PlatformContextSkia();
// Sets the canvas associated with this context. Use when supplying NULL
// to the constructor.
- void setCanvas(skia::PlatformCanvas*);
+ void setCanvas(SkCanvas*);
// If false we're rendering to a GraphicsContext for a web page, if false
// we're not (as is the case when rendering to a canvas object).
@@ -146,7 +146,8 @@ public:
// by the current alpha.
SkColor effectiveStrokeColor() const;
- skia::PlatformCanvas* canvas() { return m_canvas; }
+ // Returns the canvas used for painting, NOT guaranteed to be non-null.
+ SkCanvas* canvas() { return m_canvas; }
InterpolationQuality interpolationQuality() const;
void setInterpolationQuality(InterpolationQuality interpolationQuality);
@@ -159,17 +160,16 @@ public:
const SkBitmap* bitmap() const;
- // Returns the canvas used for painting, NOT guaranteed to be non-NULL.
- //
- // Warning: This function is deprecated so the users are reminded that they
- // should use this layer of indirection instead of using the canvas
- // directly. This is to help with the eventual serialization.
- skia::PlatformCanvas* canvas() const;
-
// Returns if the context is a printing context instead of a display
// context. Bitmap shouldn't be resampled when printing to keep the best
// possible quality.
- bool isPrinting();
+ bool printing() const { return m_printing; }
+ void setPrinting(bool p) { m_printing = p; }
+
+ // Returns if the context allows rendering of fonts using native platform
+ // APIs. If false is returned font rendering is performed using the skia
+ // text drawing APIs.
+ bool isNativeFontRenderingAllowed();
void getImageResamplingHint(IntSize* srcSize, FloatSize* dstSize) const;
void setImageResamplingHint(const IntSize& srcSize, const FloatSize& dstSize);
@@ -186,10 +186,10 @@ public:
GLES2Canvas* gpuCanvas() const { return 0; }
#endif
// Call these before making a call that manipulates the underlying
- // skia::PlatformCanvas or WebCore::GLES2Canvas
+ // SkCanvas or WebCore::GLES2Canvas
void prepareForSoftwareDraw() const;
void prepareForHardwareDraw() const;
- // Call to force the skia::PlatformCanvas to contain all rendering results.
+ // Call to force the SkCanvas to contain all rendering results.
void syncSoftwareCanvas() const;
void markDirtyRect(const IntRect& rect);
@@ -206,7 +206,7 @@ private:
struct State;
// NULL indicates painting is disabled. Never delete this object.
- skia::PlatformCanvas* m_canvas;
+ SkCanvas* m_canvas;
// States stack. Enables local drawing state change with save()/restore()
// calls.
@@ -219,6 +219,7 @@ private:
// Values are used in ImageSkia.cpp
IntSize m_imageResamplingHintSrcSize;
FloatSize m_imageResamplingHintDstSize;
+ bool m_printing;
bool m_drawingToImageBuffer;
bool m_useGPU;
#if ENABLE(ACCELERATED_2D_CANVAS)
diff --git a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
index b0cb0c7..8ab823e 100644
--- a/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
+++ b/Source/WebCore/platform/graphics/skia/SkiaFontWin.cpp
@@ -39,16 +39,11 @@
#include "SkPaint.h"
#include "SkShader.h"
#include "SkTemplates.h"
-#include "SkTypeface.h"
+#include "SkTypeface_win.h"
#include <wtf/ListHashSet.h>
#include <wtf/Vector.h>
-#if ENABLE(SKIA_TEXT)
-// FIXME: a future role of skia will have this in a proper header
-extern SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT&);
-#endif
-
namespace WebCore {
struct CachedOutlineKey {
@@ -235,11 +230,23 @@ bool windowsCanHandleDrawTextShadow(GraphicsContext *context)
ColorSpace shadowColorSpace;
bool hasShadow = context->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
- return (hasShadow && (shadowBlur == 0) && (shadowColor.alpha() == 255) && (context->fillColor().alpha() == 255));
+ return !hasShadow || (!shadowBlur && (shadowColor.alpha() == 255) && (context->fillColor().alpha() == 255));
}
bool windowsCanHandleTextDrawing(GraphicsContext* context)
{
+ if (!windowsCanHandleTextDrawingWithoutShadow(context))
+ return false;
+
+ // Check for shadow effects.
+ if (!windowsCanHandleDrawTextShadow(context))
+ return false;
+
+ return true;
+}
+
+bool windowsCanHandleTextDrawingWithoutShadow(GraphicsContext* context)
+{
// Check for non-translation transforms. Sometimes zooms will look better in
// Skia, and sometimes better in Windows. The main problem is that zooming
// in using Skia will show you the hinted outlines for the smaller size,
@@ -261,8 +268,7 @@ bool windowsCanHandleTextDrawing(GraphicsContext* context)
if (context->fillPattern() || context->strokePattern())
return false;
- // Check for shadow effects.
- if (context->platformContext()->getDrawLooper() && (!windowsCanHandleDrawTextShadow(context)))
+ if (!context->platformContext()->isNativeFontRenderingAllowed())
return false;
return true;
@@ -272,7 +278,7 @@ bool windowsCanHandleTextDrawing(GraphicsContext* context)
// pattern may be NULL, in which case a solid colour is used.
static bool skiaDrawText(HFONT hfont,
HDC dc,
- SkCanvas* canvas,
+ PlatformContextSkia* platformContext,
const SkPoint& point,
SkPaint* paint,
const WORD* glyphs,
@@ -280,47 +286,47 @@ static bool skiaDrawText(HFONT hfont,
const GOFFSET* offsets,
int numGlyphs)
{
-#if ENABLE(SKIA_TEXT)
- SkASSERT(sizeof(WORD) == sizeof(uint16_t));
-
- // Reserve space for 64 glyphs on the stack. If numGlyphs is larger, the array
- // will dynamically allocate it space for numGlyph glyphs.
- static const size_t kLocalGlyphMax = 64;
- SkAutoSTArray<kLocalGlyphMax, SkPoint> posStorage(numGlyphs);
- SkPoint* pos = posStorage.get();
- SkScalar x = point.fX;
- SkScalar y = point.fY;
- for (int i = 0; i < numGlyphs; i++) {
- pos[i].set(x + (offsets ? offsets[i].du : 0),
- y + (offsets ? offsets[i].dv : 0));
- x += SkIntToScalar(advances[i]);
- }
- canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, *paint);
-#else
- float x = point.fX, y = point.fY;
-
- for (int i = 0; i < numGlyphs; i++) {
- const SkPath* path = SkiaWinOutlineCache::lookupOrCreatePathForGlyph(dc, hfont, glyphs[i]);
- if (!path)
- return false;
-
- float offsetX = 0.0f, offsetY = 0.0f;
- if (offsets && (offsets[i].du != 0 || offsets[i].dv != 0)) {
- offsetX = offsets[i].du;
- offsetY = offsets[i].dv;
+ SkCanvas* canvas = platformContext->canvas();
+ if (!platformContext->isNativeFontRenderingAllowed()) {
+ SkASSERT(sizeof(WORD) == sizeof(uint16_t));
+
+ // Reserve space for 64 glyphs on the stack. If numGlyphs is larger, the array
+ // will dynamically allocate it space for numGlyph glyphs.
+ static const size_t kLocalGlyphMax = 64;
+ SkAutoSTArray<kLocalGlyphMax, SkPoint> posStorage(numGlyphs);
+ SkPoint* pos = posStorage.get();
+ SkScalar x = point.fX;
+ SkScalar y = point.fY;
+ for (int i = 0; i < numGlyphs; i++) {
+ pos[i].set(x + (offsets ? offsets[i].du : 0),
+ y + (offsets ? offsets[i].dv : 0));
+ x += SkIntToScalar(advances[i]);
}
+ canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, *paint);
+ } else {
+ float x = point.fX, y = point.fY;
+
+ for (int i = 0; i < numGlyphs; i++) {
+ const SkPath* path = SkiaWinOutlineCache::lookupOrCreatePathForGlyph(dc, hfont, glyphs[i]);
+ if (!path)
+ return false;
+
+ float offsetX = 0.0f, offsetY = 0.0f;
+ if (offsets && (offsets[i].du || offsets[i].dv)) {
+ offsetX = offsets[i].du;
+ offsetY = offsets[i].dv;
+ }
- SkPath newPath;
- newPath.addPath(*path, x + offsetX, y + offsetY);
- canvas->drawPath(newPath, *paint);
+ SkPath newPath;
+ newPath.addPath(*path, x + offsetX, y + offsetY);
+ canvas->drawPath(newPath, *paint);
- x += advances[i];
+ x += advances[i];
+ }
}
-#endif
return true;
}
-#if ENABLE(SKIA_TEXT)
static void setupPaintForFont(HFONT hfont, SkPaint* paint)
{
// FIXME:
@@ -339,7 +345,6 @@ static void setupPaintForFont(HFONT hfont, SkPaint* paint)
paint->setTypeface(face);
SkSafeUnref(face);
}
-#endif
bool paintSkiaText(GraphicsContext* context,
HFONT hfont,
@@ -359,14 +364,14 @@ bool paintSkiaText(GraphicsContext* context,
SkPaint paint;
platformContext->setupPaintForFilling(&paint);
paint.setFlags(SkPaint::kAntiAlias_Flag);
-#if ENABLE(SKIA_TEXT)
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- setupPaintForFont(hfont, &paint);
-#endif
+ if (!platformContext->isNativeFontRenderingAllowed()) {
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ setupPaintForFont(hfont, &paint);
+ }
bool didFill = false;
- if ((textMode & TextModeFill) && SkColorGetA(paint.getColor())) {
- if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint,
+ if ((textMode & TextModeFill) && (SkColorGetA(paint.getColor()) || paint.getLooper())) {
+ if (!skiaDrawText(hfont, dc, platformContext, *origin, &paint,
&glyphs[0], &advances[0], &offsets[0], numGlyphs))
return false;
didFill = true;
@@ -380,10 +385,10 @@ bool paintSkiaText(GraphicsContext* context,
paint.reset();
platformContext->setupPaintForStroking(&paint, 0, 0);
paint.setFlags(SkPaint::kAntiAlias_Flag);
-#if ENABLE(SKIA_TEXT)
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- setupPaintForFont(hfont, &paint);
-#endif
+ if (!platformContext->isNativeFontRenderingAllowed()) {
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ setupPaintForFont(hfont, &paint);
+ }
if (didFill) {
// If there is a shadow and we filled above, there will already be
@@ -398,7 +403,7 @@ bool paintSkiaText(GraphicsContext* context,
paint.setLooper(0);
}
- if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint,
+ if (!skiaDrawText(hfont, dc, platformContext, *origin, &paint,
&glyphs[0], &advances[0], &offsets[0], numGlyphs))
return false;
}
diff --git a/Source/WebCore/platform/graphics/skia/SkiaFontWin.h b/Source/WebCore/platform/graphics/skia/SkiaFontWin.h
index 40bee62..33b4aaf 100644
--- a/Source/WebCore/platform/graphics/skia/SkiaFontWin.h
+++ b/Source/WebCore/platform/graphics/skia/SkiaFontWin.h
@@ -76,6 +76,10 @@ bool windowsCanHandleDrawTextShadow(GraphicsContext*);
// Returns true if advanced font rendering is recommended.
bool windowsCanHandleTextDrawing(GraphicsContext*);
+// Returns true if advanced font rendering is recommended if shadows are
+// disregarded.
+bool windowsCanHandleTextDrawingWithoutShadow(GraphicsContext*);
+
// Note that the offsets parameter is optional. If not NULL it represents a
// per glyph offset (such as returned by ScriptPlace Windows API function).
//
diff --git a/Source/WebCore/platform/graphics/transforms/AffineTransform.h b/Source/WebCore/platform/graphics/transforms/AffineTransform.h
index 14431aa..176c41e 100644
--- a/Source/WebCore/platform/graphics/transforms/AffineTransform.h
+++ b/Source/WebCore/platform/graphics/transforms/AffineTransform.h
@@ -32,9 +32,9 @@
#include <string.h> // for memcpy
#include <wtf/FastAllocBase.h>
-#if PLATFORM(CG)
+#if USE(CG)
#include <CoreGraphics/CGAffineTransform.h>
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
#include <cairo.h>
#elif PLATFORM(OPENVG)
#include "VGUtils.h"
@@ -157,9 +157,9 @@ public:
return result;
}
-#if PLATFORM(CG)
+#if USE(CG)
operator CGAffineTransform() const;
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
operator cairo_matrix_t() const;
#elif PLATFORM(OPENVG)
operator VGMatrix() const;
diff --git a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
index adda46b..ff668bb 100644
--- a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
+++ b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
@@ -31,12 +31,12 @@
#include <string.h> //for memcpy
#include <wtf/FastAllocBase.h>
-#if PLATFORM(CA)
+#if USE(CA)
typedef struct CATransform3D CATransform3D;
#endif
-#if PLATFORM(CG)
+#if USE(CG)
typedef struct CGAffineTransform CGAffineTransform;
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
#include <cairo.h>
#elif PLATFORM(OPENVG)
#include "VGUtils.h"
@@ -308,14 +308,14 @@ public:
return result;
}
-#if PLATFORM(CA)
+#if USE(CA)
TransformationMatrix(const CATransform3D&);
operator CATransform3D() const;
#endif
-#if PLATFORM(CG)
+#if USE(CG)
TransformationMatrix(const CGAffineTransform&);
operator CGAffineTransform() const;
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
operator cairo_matrix_t() const;
#elif PLATFORM(OPENVG)
operator VGMatrix() const;
diff --git a/Source/WebCore/platform/graphics/win/DIBPixelData.cpp b/Source/WebCore/platform/graphics/win/DIBPixelData.cpp
new file mode 100644
index 0000000..e45ba06
--- /dev/null
+++ b/Source/WebCore/platform/graphics/win/DIBPixelData.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 Brent Fulgham <bfulgham@webkit.org>
+ *
+ * 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. ``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
+ * 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 "DIBPixelData.h"
+
+namespace WebCore {
+
+static const WORD bitmapType = 0x4d42; // BMP format
+static const WORD bitmapPixelsPerMeter = 2834; // 72 dpi
+
+DIBPixelData::DIBPixelData(HBITMAP bitmap)
+{
+ initialize(bitmap);
+}
+
+void DIBPixelData::initialize(HBITMAP bitmap)
+{
+ BITMAP bmpInfo;
+ GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
+
+ m_bitmapBuffer = reinterpret_cast<UInt8*>(bmpInfo.bmBits);
+ m_bitmapBufferLength = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+ m_size = IntSize(bmpInfo.bmWidth, bmpInfo.bmHeight);
+ m_bytesPerRow = bmpInfo.bmWidthBytes;
+ m_bitsPerPixel = bmpInfo.bmBitsPixel;
+}
+
+#ifndef NDEBUG
+void DIBPixelData::writeToFile(LPCWSTR filePath)
+{
+ HANDLE hFile = ::CreateFile(filePath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (INVALID_HANDLE_VALUE == hFile)
+ return;
+
+ BITMAPFILEHEADER header;
+ header.bfType = bitmapType;
+ header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
+ header.bfReserved1 = 0;
+ header.bfReserved2 = 0;
+ header.bfSize = sizeof(BITMAPFILEHEADER);
+
+ BITMAPINFOHEADER info;
+ info.biSize = sizeof(BITMAPINFOHEADER);
+ info.biWidth = m_size.width();
+ info.biHeight = m_size.height();
+ info.biPlanes = 1;
+ info.biBitCount = m_bitsPerPixel;
+ info.biCompression = BI_RGB;
+ info.biSizeImage = bufferLength();
+ info.biXPelsPerMeter = bitmapPixelsPerMeter;
+ info.biYPelsPerMeter = bitmapPixelsPerMeter;
+ info.biClrUsed = 0;
+ info.biClrImportant = 0;
+
+ DWORD bytesWritten = 0;
+ ::WriteFile(hFile, &header, sizeof(header), &bytesWritten, 0);
+ ::WriteFile(hFile, &info, sizeof(info), &bytesWritten, 0);
+ ::WriteFile(hFile, buffer(), bufferLength(), &bytesWritten, 0);
+
+ ::CloseHandle(hFile);
+}
+#endif
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/win/DIBPixelData.h b/Source/WebCore/platform/graphics/win/DIBPixelData.h
new file mode 100644
index 0000000..40afa2b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/win/DIBPixelData.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 Brent Fulgham <bfulgham@webkit.org>
+ *
+ * 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. ``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
+ * 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 DIBPixelData_h
+#define DIBPixelData_h
+
+#include "IntSize.h"
+#include <windows.h>
+
+#if !USE(CG)
+// UInt8 is defined in CoreFoundation/CFBase.h
+typedef unsigned char UInt8;
+#endif
+
+namespace WebCore {
+
+class DIBPixelData {
+ public:
+ DIBPixelData()
+ : m_bitmapBuffer(0)
+ , m_bitmapBufferLength(0)
+ , m_bytesPerRow(0)
+ , m_bitsPerPixel(0)
+ {
+ }
+ DIBPixelData(HBITMAP);
+
+ void initialize(HBITMAP);
+
+#ifndef NDEBUG
+ void writeToFile(LPCWSTR);
+#endif
+
+ UInt8* buffer() const { return m_bitmapBuffer; }
+ unsigned bufferLength() const { return m_bitmapBufferLength; }
+ const IntSize& size() const { return m_size; }
+ unsigned bytesPerRow() const { return m_bytesPerRow; }
+ unsigned short bitsPerPixel() const { return m_bitsPerPixel; }
+
+ private:
+ UInt8* m_bitmapBuffer;
+ unsigned m_bitmapBufferLength;
+ IntSize m_size;
+ unsigned m_bytesPerRow;
+ unsigned short m_bitsPerPixel;
+};
+
+} // namespace WebCore
+
+#endif // DIBPixelData_h
diff --git a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
index 5382ef7..46f6f11 100644
--- a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp
@@ -36,7 +36,7 @@
#include <windows.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringHash.h>
-#if PLATFORM(CG)
+#if USE(CG)
#include <ApplicationServices/ApplicationServices.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
#endif
@@ -48,7 +48,7 @@ namespace WebCore
void FontCache::platformInit()
{
-#if PLATFORM(CG)
+#if USE(CG)
wkSetUpFontCache(1536 * 1024 * 4); // This size matches Mac.
#endif
}
@@ -471,7 +471,7 @@ static HFONT createGDIFont(const AtomicString& family, LONG desiredWeight, bool
matchData.m_chosen.lfUnderline = false;
matchData.m_chosen.lfStrikeOut = false;
matchData.m_chosen.lfCharSet = DEFAULT_CHARSET;
-#if PLATFORM(CG) || PLATFORM(CAIRO)
+#if USE(CG) || USE(CAIRO)
matchData.m_chosen.lfOutPrecision = OUT_TT_ONLY_PRECIS;
#else
matchData.m_chosen.lfOutPrecision = OUT_TT_PRECIS;
@@ -581,9 +581,9 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
FontPlatformData* result = new FontPlatformData(hfont, fontDescription.computedPixelSize(), synthesizeBold, synthesizeItalic, useGDI);
-#if PLATFORM(CG)
+#if USE(CG)
bool fontCreationFailed = !result->cgFont();
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
bool fontCreationFailed = !result->scaledFont();
#endif
diff --git a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
index 301198d..d0b37bd 100644
--- a/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
+++ b/Source/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
@@ -41,9 +41,9 @@ FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool obliq
, m_orientation(Horizontal)
, m_textOrientation(TextOrientationVerticalRight)
, m_widthVariant(RegularWidth)
-#if PLATFORM(CG)
+#if USE(CG)
, m_cgFont(0)
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
, m_scaledFont(0)
#endif
, m_isColorBitmapFont(false)
diff --git a/Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index d0bd4e9..cb0c9a7 100644
--- a/Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/Source/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -40,25 +40,24 @@ namespace WebCore {
static CGContextRef CGContextWithHDC(HDC hdc, bool hasAlpha)
{
HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
- BITMAP info;
- GetObject(bitmap, sizeof(info), &info);
+ DIBPixelData pixelData(bitmap);
// FIXME: We can get here because we asked for a bitmap that is too big
// when we have a tiled layer and we're compositing. In that case
// bmBitsPixel will be 0. This seems to be benign, so for now we will
// exit gracefully and look at it later:
// https://bugs.webkit.org/show_bug.cgi?id=52041
- // ASSERT(info.bmBitsPixel == 32);
- if (info.bmBitsPixel != 32)
+ // ASSERT(bitmapBits.bitsPerPixel() == 32);
+ if (pixelData.bitsPerPixel() != 32)
return 0;
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | (hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst);
- CGContextRef context = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8,
- info.bmWidthBytes, deviceRGBColorSpaceRef(), bitmapInfo);
+ CGContextRef context = CGBitmapContextCreate(pixelData.buffer(), pixelData.size().width(), pixelData.size().height(), 8,
+ pixelData.bytesPerRow(), deviceRGBColorSpaceRef(), bitmapInfo);
// Flip coords
- CGContextTranslateCTM(context, 0, info.bmHeight);
+ CGContextTranslateCTM(context, 0, pixelData.size().height());
CGContextScaleCTM(context, 1, -1);
// Put the HDC In advanced mode so it will honor affine transforms.
@@ -99,16 +98,14 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo
if (dstRect.isEmpty())
return;
- HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+ OwnPtr<HBITMAP> bitmap = adoptPtr(static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP)));
+
+ DIBPixelData pixelData(bitmap.get());
- // Need to make a CGImage out of the bitmap's pixel buffer and then draw
- // it into our context.
- BITMAP info;
- GetObject(bitmap, sizeof(info), &info);
- ASSERT(info.bmBitsPixel == 32);
+ ASSERT(pixelData.bitsPerPixel() == 32);
- CGContextRef bitmapContext = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8,
- info.bmWidthBytes, deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Little |
+ CGContextRef bitmapContext = CGBitmapContextCreate(pixelData.buffer(), pixelData.size().width(), pixelData.size().height(), 8,
+ pixelData.bytesPerRow(), deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Little |
(supportAlphaBlend ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst));
CGImageRef image = CGBitmapContextCreateImage(bitmapContext);
@@ -118,7 +115,6 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo
CGImageRelease(image);
CGContextRelease(bitmapContext);
::DeleteDC(hdc);
- ::DeleteObject(bitmap);
}
void GraphicsContext::drawWindowsBitmap(WindowsBitmap* image, const IntPoint& point)
diff --git a/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
index 7ce7ee9..9f7aece 100644
--- a/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
+++ b/Source/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
@@ -78,7 +78,7 @@ void GraphicsContext::platformInit(HDC dc, bool hasAlpha)
else
setPaintingDisabled(true);
- m_data = new GraphicsContextPlatformPrivateTopLevel(new PlatformContextCairo(cr));
+ m_data = new GraphicsContextPlatformPrivateToplevel(new PlatformContextCairo(cr));
m_data->m_hdc = dc;
if (platformContext()->cr()) {
// Make sure the context starts in sync with our state.
@@ -93,6 +93,33 @@ static void setRGBABitmapAlpha(unsigned char* bytes, size_t length, unsigned cha
bytes[i + 3] = level;
}
+static void drawBitmapToContext(GraphicsContextPlatformPrivate* context, cairo_t* cr, const DIBPixelData& pixelData, const IntSize& translate)
+{
+ // Need to make a cairo_surface_t out of the bitmap's pixel buffer and then draw
+ // it into our context.
+ cairo_surface_t* surface = cairo_image_surface_create_for_data(pixelData.buffer(),
+ CAIRO_FORMAT_ARGB32,
+ pixelData.size().width(),
+ pixelData.size().height(),
+ pixelData.bytesPerRow());
+
+ // Flip the target surface so that when we set the srcImage as
+ // the surface it will draw right-side-up.
+ cairo_save(cr);
+ cairo_translate(cr, static_cast<double>(translate.width()), static_cast<double>(translate.height()));
+ cairo_scale(cr, 1, -1);
+ cairo_set_source_surface(cr, surface, 0, 0);
+
+ if (context->layers.size())
+ cairo_paint_with_alpha(cr, context->layers.last());
+ else
+ cairo_paint(cr);
+
+ // Delete all our junk.
+ cairo_surface_destroy(surface);
+ cairo_restore(cr);
+}
+
void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
bool createdBitmap = mayCreateBitmap && (!m_data->m_hdc || inTransparencyLayer());
@@ -104,46 +131,26 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo
if (dstRect.isEmpty())
return;
- HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+ OwnPtr<HBITMAP> bitmap = adoptPtr(static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP)));
- BITMAP info;
- GetObject(bitmap, sizeof(info), &info);
- ASSERT(info.bmBitsPixel == 32);
+ DIBPixelData pixelData(bitmap.get());
+ ASSERT(pixelData.bitsPerPixel() == 32);
// If this context does not support alpha blending, then it may have
// been drawn with GDI functions which always set the alpha channel
// to zero. We need to manually set the bitmap to be fully opaque.
- unsigned char* bytes = reinterpret_cast<unsigned char*>(info.bmBits);
+ unsigned char* bytes = reinterpret_cast<unsigned char*>(pixelData.buffer());
if (!supportAlphaBlend)
- setRGBABitmapAlpha(bytes, info.bmHeight * info.bmWidthBytes, 255);
+ setRGBABitmapAlpha(bytes, pixelData.size().height() * pixelData.bytesPerRow(), 255);
- // Need to make a cairo_surface_t out of the bitmap's pixel buffer and then draw
- // it into our context.
- cairo_surface_t* image = cairo_image_surface_create_for_data(bytes,
- CAIRO_FORMAT_ARGB32,
- info.bmWidth,
- info.bmHeight,
- info.bmWidthBytes);
-
- // Scale the target surface to the new image size, and flip it
- // so that when we set the srcImage as the surface it will draw
- // right-side-up.
- cairo_t* cr = platformContext()->cr();
- cairo_save(cr);
- cairo_translate(cr, dstRect.x(), dstRect.height() + dstRect.y());
- cairo_scale(cr, 1, -1);
- cairo_set_source_surface(cr, image, 0, 0);
+ drawBitmapToContext(m_data, platformContext()->cr(), pixelData, IntSize(dstRect.x(), dstRect.height() + dstRect.y()));
- if (m_data->layers.size())
- cairo_paint_with_alpha(cr, m_data->layers.last());
- else
- cairo_paint(cr);
-
- // Delete all our junk.
- cairo_surface_destroy(image);
::DeleteDC(hdc);
- ::DeleteObject(bitmap);
- cairo_restore(cr);
+}
+
+void GraphicsContext::drawWindowsBitmap(WindowsBitmap* bitmap, const IntPoint& point)
+{
+ drawBitmapToContext(m_data, platformContext()->cr(), bitmap->windowsDIB(), IntSize(point.x(), bitmap->size().height() + point.y()));
}
void GraphicsContextPlatformPrivate::syncContext(cairo_t* cr)
diff --git a/Source/WebCore/platform/graphics/win/GraphicsContextWin.cpp b/Source/WebCore/platform/graphics/win/GraphicsContextWin.cpp
index f2850e4..28ce55a 100644
--- a/Source/WebCore/platform/graphics/win/GraphicsContextWin.cpp
+++ b/Source/WebCore/platform/graphics/win/GraphicsContextWin.cpp
@@ -26,9 +26,9 @@
#include "config.h"
#include "GraphicsContext.h"
-#if PLATFORM(CG)
+#if USE(CG)
#include "GraphicsContextPlatformPrivateCG.h"
-#elif PLATFORM(CAIRO)
+#elif USE(CAIRO)
#include "GraphicsContextPlatformPrivateCairo.h"
#endif
@@ -65,21 +65,20 @@ bool GraphicsContext::shouldIncludeChildWindows() const
GraphicsContext::WindowsBitmap::WindowsBitmap(HDC hdc, IntSize size)
: m_hdc(0)
- , m_size(size)
{
- BitmapInfo bitmapInfo = BitmapInfo::create(m_size);
+ BitmapInfo bitmapInfo = BitmapInfo::create(size);
- m_bitmap = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, reinterpret_cast<void**>(&m_bitmapBuffer), 0, 0);
+ void* storage = 0;
+ m_bitmap = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &storage, 0, 0);
if (!m_bitmap)
return;
m_hdc = CreateCompatibleDC(hdc);
SelectObject(m_hdc, m_bitmap);
- BITMAP bmpInfo;
- GetObject(m_bitmap, sizeof(bmpInfo), &bmpInfo);
- m_bytesPerRow = bmpInfo.bmWidthBytes;
- m_bitmapBufferLength = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+ m_pixelData.initialize(m_bitmap);
+
+ ASSERT(storage == m_pixelData.buffer());
SetGraphicsMode(m_hdc, GM_ADVANCED);
}
diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
index dd3cd32..588146a 100644
--- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
+++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
@@ -30,7 +30,7 @@
#include "WebCoreInstanceHandle.h"
#include <windows.h>
-#if PLATFORM(CG)
+#if USE(CG)
#include <CoreGraphics/CGColor.h>
#endif
diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
index 323ff73..db730ca 100644
--- a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
+++ b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
@@ -39,7 +39,7 @@
#include <winsock2.h>
#include <wtf/MathExtras.h>
-#if PLATFORM(CG)
+#if USE(CG)
#include <ApplicationServices/ApplicationServices.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
#endif
diff --git a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
index 19683df..e501621 100644
--- a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
+++ b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
@@ -1300,7 +1300,7 @@ void GraphicsContext::drawRoundCorner(bool needsNewClip, RECT clipRect, RECT rec
}
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect, RoundingMode)
{
notImplemented();
return frect;
diff --git a/Source/WebCore/platform/graphics/wince/ImageBufferData.h b/Source/WebCore/platform/graphics/wince/ImageBufferDataWince.h
index cbd49dc..dd46d38 100644
--- a/Source/WebCore/platform/graphics/wince/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/wince/ImageBufferDataWince.h
@@ -17,9 +17,6 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef ImageBufferData_h
-#define ImageBufferData_h
-
#include "SharedBitmap.h"
namespace WebCore {
@@ -33,5 +30,3 @@ public:
};
} // namespace WebCore
-
-#endif // ImageBufferData_h
diff --git a/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
index 830cd05..3d98aeb 100644
--- a/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
@@ -99,12 +99,14 @@ FontPlatformData::FontPlatformData(const FontDescription& desc, const AtomicStri
)
));
#endif
-#if OS(DARWIN) && !defined(wxOSX_USE_CORE_TEXT)
+#if OS(DARWIN)
+#if !wxOSX_USE_CORE_TEXT
#if wxCHECK_VERSION(2,9,0)
m_atsuFontID = m_font->font()->OSXGetATSUFontID();
#else
m_atsuFontID = m_font->font()->MacGetATSUFontID();
#endif
+#endif
m_nsFont = 0;
cacheNSFont();
#endif
diff --git a/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 47f3211..071df47 100644
--- a/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/Source/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -416,7 +416,7 @@ void GraphicsContext::scale(const FloatSize& scale)
}
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect, RoundingMode)
{
FloatRect result;
diff --git a/Source/WebCore/platform/graphics/wx/ImageBufferData.h b/Source/WebCore/platform/graphics/wx/ImageBufferDataWx.h
index d4a6114..9961fee 100644
--- a/Source/WebCore/platform/graphics/wx/ImageBufferData.h
+++ b/Source/WebCore/platform/graphics/wx/ImageBufferDataWx.h
@@ -23,10 +23,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ImageBufferData_h
-#define ImageBufferData_h
-
-
#include "OwnPtr.h"
namespace WebCore {
@@ -38,6 +34,4 @@ public:
ImageBufferData(const IntSize&);
};
-} // namespace WebCore
-
-#endif // ImageBufferData_h
+} // namespace WebCore